Wednesday, April 17, 2013

How do I set up a Next Generation Rackspace Cloud Server running Debian 7 (Wheezy)?

First, launch a new Debian 7 (Wheezy) server by following the instructions found at:
http://www.rackspace.com/knowledge_center/article/rackspace-cloud-essentials-2-creating-a-cloud-server

After doing so, you should have a new root user, the root user's password, and an IP address.

Next, launch Terminal and run the following command (using your server's IP address rather than 165.210.5.238):
ssh root@165.210.5.238
You'll be prompted with the following message:
The authenticity of host '165.210.5.238 (165.210.5.238)' can't be established.
RSA key fingerprint is 9a:7d:4r:25:1b:30:a9:39:ft:b2:a1:99:t9:52:z6:99.
Are you sure you want to continue connecting (yes/no)?
Enter the following word:
yes
You'll then be prompted with the following message:
Warning: Permanently added '165.210.5.238' (RSA) to the list of known hosts.
Perfect. After that you'll be asked for the root user's password via the following prompt:
root@165.210.5.238's password:
Enter it.

Next we're going to update the root user's password to something insane. We'll do so by entering the following command:
passwd
You'll be prompted to input your new, totally insane, root user password via the following prompt:
Enter new UNIX password:
You'll enter it. Then you'll be prompted again. You'll enter it again.

At this point you should start to feel awesome.

But not too awesome because we're running commands as root right now which isn't awesome. So, let's fix that. Time to create a new user.

Enter the following command (this tutorial uses 'admin' throughout but you can name your user whatever you want... like tim, jane, bob, or even tbone_smith):
adduser admin
You'll see the following output:
Adding user `admin' ...
Adding new group `admin' (1000) ...
Adding new user `admin' (1000) with group `admin' ...
Creating home directory `/home/admin' ...
Copying files from `/etc/skel' ...
You'll then be prompted to enter the new user's password via the following prompt (twice):
Enter new UNIX password:
You'll enter the new password (twice). You'll then be prompted for some additional information:
passwd: password updated successfully
Changing the user information for admin
Enter the new value, or press ENTER for the default
 Full Name []: 
 Room Number []: 
 Work Phone []: 
 Home Phone []: 
 Other []: 
If you're working out of a hotel room make sure to enter your room number. After answering all the questions above (whichever ones you want) you'll be prompted with the following:
Is the information correct? [Y/n]
Enter:
yes
Now that's pretty cool, but not that cool. Our new user can't do much unless we grant them sudo privileges. So enter the following command:
visudo
You'll notice a section near the middle of the file that matches:
# User privilege specification
root    ALL=(ALL) ALL
Add an additional line after root for your new user like so:
# User privilege specification
root    ALL=(ALL) ALL
admin   ALL=(ALL) ALL
Save the file.

Now we need to update our ssh config file. We're going to update our ssh port number to be non-standard, enable password authentication, and white label (allow) the user we just created. Let's kick off this bad-ass-ness by running the following command:
nano /etc/ssh/sshd_config
Find the lines (near the top) that match:
# What ports, IPs and protocols we listen for
Port 22
Update the digit 22 to be something highly random like 30062. Next, find the lines that match:
# Change to no to disable tunnelled clear text passwords
#PasswordAuthentication yes
Uncomment the 2nd line above to make it so we can ssh in to this machine using a password (you can set this directive to "no" later, after you get ssh keys set up). Save the file.

Now that's pretty bomb, but not that bomb. In order to go bomb-status we need to setup our software firewall using iptables. To get started run the following command:
nano /etc/iptables.test.rules
Then, copy and paste the following rules into your /etc/iptables.test.rules file:
*filter


#  Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT


#  Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT


#  Allows all outbound traffic
#  You can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT


# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT


#  Allows SSH connections
#
# THE -dport NUMBER IS THE SAME ONE YOU SET UP IN THE SSHD_CONFIG FILE
#
-A INPUT -p tcp -m state --state NEW --dport 30062 -j ACCEPT


# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT


# log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7


# Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT
We're basically accepting localhost traffic, outbound traffic, http, https, ssh (on our custom port), pings, and rejecting everything else.

Note: The above template is an exact copy of a SliceHost reference doc located at http://articles.slicehost.com/assets/2007/9/4/iptables.txt (with the exception of line 27 which you can see I've updated to match our highly random custom ssh port of 30062).

To apply this bomb-status-ness run the following command:
iptables-restore < /etc/iptables.test.rules
To review our work we can run the following command:
iptables -L
Which should output:
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             loopback/8          reject-with icmp-port-unreachable 
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:www 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:https 
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:30077 
ACCEPT     icmp --  anywhere             anywhere            icmp echo-request 
LOG        all  --  anywhere             anywhere            limit: avg 5/min burst 5 LOG level debug prefix `iptables denied: ' 
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
Pretty cool, right? Wrong! Well not totally wrong, we just need to save these rules as our default configuration and then wire them up so when we restart the server we don't lose them!

There are a few ways to go about this. You can either edit your interfaces file directly or create a special script that gets run when your network interfaces are started. I've been told the scripting approach is superior. I'll cover both approaches ("editing your interfaces file directly" first, "scripting" second).

With either approach, we begin by saving our rules to a file via the following command:
iptables-save > /etc/iptables.up.rules
Okay, if you'd like to edit your interfaces file directly, start by opening your network interface config file via the following command:
nano /etc/network/interfaces
The first 5 lines will be as follows:
# Used by ifup(8) and ifdown(8). See the interfaces(5) manpage or
# /usr/share/doc/ifupdown/examples for more information.
# The loopback network interface
auto lo
iface lo inet loopback
Add a sixth line right after 'iface lo inet loopback' that says:
pre-up iptables-restore < /etc/iptables.up.rules
Then, save the file. Now we won't lose our software firewall rules on reboot. Now that's pretty cool!

Okay, that concludes the "edit your interfaces file directly" approach. If you want to take the "scripting" approach (which, again, I've been told is a superior method), follow these steps:
nano /etc/network/if-pre-up.d/iptables
Add the following lines to the new file:
#!/bin/sh
/sbin/iptables-restore < /etc/iptables.up.rules
Save your changes, then make the new script executable:
chmod +x /etc/network/if-pre-up.d/iptables
Okay cool, now we won't lose our software firewall rules on reboot! Yay!

Alright, we're almost done with our root account and we're about to switch over to operating via our new admin user. Before we do that though, since we made changes to our ssh config file, we need to apply them. You can do so via the following command:
/etc/init.d/ssh reload
Now exit:
exit
Then, ssh back into the machine via our new admin user account using our custom ssh port:
ssh -p 30062 admin@165.210.5.238
And if you successfully connected to the machine... we can officially say, "Boom goes the dynamite".

We're done right? Wrong! It's time get down with some personal preference style settings in our bash config file (you can skip this step if you'd like). Start by running the following command:
nano ~/.bashrc
Then, find the following line:
#force_color_prompt=yes
Remove the # character, save the file, then reload your config file via the following command:
source ~/.bashrc
Boom. Your terminal prompt just got jacked! Well I don't even know exactly what that means but you'll notice your prompt is now printed in a fatty daddy green color which helps distinguish it from command output.

At this point you're probably whining like a little baby wondering if we're done yet. No!

Time to update our server so we're not running code that's like 40 thousands years old. To do this, run the following command:
sudo aptitude update
Next, we'll want to set up our region information. First, let's start with installing locales. Run the following command:
sudo aptitude install locales
After doing that, let's reconfigure it:
sudo dpkg-reconfigure locales
A blue screen should pop up. Select en_US.UTF-8 until you're back in your regular command prompt (should take two selections of en_US.UTF-8 to complete).

Next we're going to set up our timezone info:
sudo dpkg-reconfigure tzdata
A blue screen should pop up. I selected America then Chicago (since my server is in Chicago). After completing this step you'll see the following information printed to your screen:
Current default time zone: 'America/Chicago'
Local time is now:      Wed Apr 17 08:56:45 CDT 2013.
Universal Time is now:  Wed Apr 17 13:56:45 UTC 2013.
Now that we've updated our software listings from the repositories (in a previous step), it's time to run the actual upgrade (we'll do this via two commands starting with a safe upgrade first):
sudo aptitude safe-upgrade
You'll get prompted about disk usage (incoming file size) along the way. Say yes to these prompts. Once that's done we'll run the full upgrade:
sudo aptitude full-upgrade
Now we're pretty much done except for one thing. Let's install the build essential package to help resolve future dependencies... that is, unless you'd rather spend your time in dependency hell rather than getting barreled in some sick surf.
sudo aptitude install build-essential
Now das wassup! Our server is on lock down & ready to go! You now have proof that you're awesome!

Way to go!

Now that you've got your server set up and on lock down you may be interested in setting up the rest of the LAMP stack (Apache, MySQL, & PHP). If so, checkout a post I recently published that walks you through the process step by step: http://oneqonea.blogspot.com/2013/04/how-do-i-install-latest-versions-of.html

Final note: The vast majority of this tutorial was derived from a YouTube video by ckeck. So props there! Thx dude!

9 comments:

  1. finally someone who can actually create a walk-through that works. If I had to create one more server, my crap was going out the window. Everyone does it differently but yours worked like a charm. Thanks a lot!!!

    ReplyDelete
  2. I ve faced an issue during the process and I found a solution; some of you might have trouble with the iptables-restore < /etc/iptables.test.rules . I had an error mentionning this iptables-restore v1.3.5: no command specified Error occurred at line: 2. If you ve that you will need to Flush the iptables rules, then manually add each iptable rule. If you don't get any errors, then use iptables-save to save to the working rules to a file you can use with iptables-restore.
    Line by line worked for me.
    In order to flush the table check this : http://www.cyberciti.biz/tips/linux-iptables-how-to-flush-all-rules.html

    ReplyDelete
  3. I had the same issue as Guillaume. I found that all the blank lines in /etc/iptables.test.rules actually had space characters in them. Removing the spaces from the blank lines did the trick! Thanks John for these tutorials - they've been very helpful!

    ReplyDelete
  4. Brilliant, thanks for posting Alice that helped me out!

    ReplyDelete
  5. Thanks for the tutorial. You can also set up your cloud server at Go4hosting. They have a team of experts who provide 24*7 technical support with which you can resolve any kind of issue related to the cloud servers.

    ReplyDelete
  6. Hi John,

    Is this applicable also to Debian Jessie?

    ReplyDelete
  7. It works with Debian Jessie too. Except that I have to change the aptitude command with apt.
    The rest works like a charm. Thank you so much!

    ReplyDelete

  8. I had one positive hosting experience withserverwala.org . I’d grade them just slightly ahead of rackbank for support, though both had good phone support.

    ReplyDelete

About Me

My photo
I code. I figured I should start a blog that keeps track of the many questions and answers that are asked and answered along the way. The name of my blog is "One Q, One A". The name describes the format. When searching for an answer to a problem, I typically have to visit more than one site to get enough information to solve the issue at hand. I always end up on stackoverflow.com, quora.com, random blogs, etc before the answer is obtained. In my blog, each post will consist of one question and one answer. All the noise encountered along the way will be omitted.