Initial Setup

Security Updates

Once you're logged in for first time using the root credentials, you'll want to run security updates immediately. Doing so helps protect against unauthorized access to your Linode as a result of any outstanding security holes in packages.

sudo apt-get update
sudo apt-get upgrade --show-upgraded

Set the Hostname

Now we'll set the hostname for the system. You can choose any name you like, but something unique and descriptive might be prudent. The hostname is what your machine calls itself, and you can choose any name you want. In this example, we will call it "myhost".

echo "myhost" > /etc/hostname
hostname -F /etc/hostname

Edit hosts file to include our fqdn of server

echo "123.45.67.890 myhost.domain.com myhost" >> /etc/hosts

Create Admin User

We need to add an initial administator user, in this example the user will be called demo.

adduser demo

As you know, we never log in as the root user (this initial setup is the only time you would need to log in as root). As such, the main administration user (demo) needs to have sudo (Super User) privileges so they can, with a password, complete administrative tasks.

To configure this, give the 'visudo' command:

visudo

At the end of the file add:

demo   ALL=(ALL) ALL

Secure SSH Configuration

nano /etc/ssh/sshd_config

Use can use this ssh configuration as an example.

The main things to change (or check) are:

Port 30000
Protocol 2
PermitRootLogin no
X11Forwarding no
UseDNS no
AllowUsers demo

I think the setting are fairly self explanatory but the main thing is to move it from the default port of 22 to one of your choosing, turn off root logins and define which users can log in.

Basic Firewall Setup

This section guides you through the initial setup of a firewall. It limits the initial ports that are open but additional services may require this to be updated for them to work.

Firstly, we install ufw firewall manager which will install iptables as one of it's dependencies.

sudo aptitude install ufw

The next thing is to set up our iptables so we have a more secure installation. To start with, we're going to have three ports open: ssh, http and https.
We're going to create two files, /etc/iptables.test.rules and /etc/iptables.up.rules. The first is a temporary (test) set of rules and the second the 'permanent' set of rules (this is the one iptables will use when starting up after a reboot for example).

Note that we are logged in as the root user. This is the only time we will log in as the root user. As such, if you are completing this step at a later date using the admin user, you will need to put a 'sudo' in front of the commands.

So, as the user with root privileges, save any existing rules to /etc/iptables.up.rules:

iptables-save > /etc/iptables.up.rules

Now let's see what's running at the moment:

iptables -L

You will see something similar to this:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

As you can see, we are accepting anything from anyone on any port and allowing anything to happen.

One theory is that if there are no services running then it doesn't matter. I disagree. If connections to unused (and popular) ports are blocked or dropped, then the vast majority of script kiddies will move on to another machine where ports are accepting connections. It takes two minutes to set up a firewall - is it really worth not doing?

Let's assume you've decided that you want a firewall. Create the file /etc/iptables.test.rules and add some rules to it.

nano /etc/iptables.test.rules

Look at this example below,

*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 30000 -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

The rules are very simple and it is not designed to give you the ultimate firewall. It is a simple beginning.

Hopefully you will begin to see the pattern of the configuration file. It isn't complicated and is very flexible. You can change and add ports as you see fit.
Good. Defined your rules?

Then lets apply those rules to our server:

iptables-restore < /etc/iptables.test.rules

Let's see if there is any difference:

iptables -L

Notice the change? (If there is no change in the output, you did something wrong. Try again from the start).

Have a look at the rules and see exactly what is being accepted, rejected and dropped. Once you are happy with the rules, it's time to save our rules permanently:

iptables-save > /etc/iptables.up.rules

Now we need to ensure that the iptables rules are applied when we reboot the server. At the moment, the changes will be lost and it will go back to allowing everything from everywhere.

Open the file /etc/network/interfaces

nano /etc/network/interfaces

Add a single line (shown below) just after 'iface lo inet loopback':

...
auto lo
iface lo inet loopback
pre-up iptables-restore < /etc/iptables.up.rules

# The primary network interface
...

As you can see, this line will restore the iptables rules from the /etc/iptables.up.rules file. Simple but effective.

Test the Admin User Account

Now that we have our basic firewall humming along and we've set the SSH configuration, we need to test it. Reload SSH so it uses the new ports and configurations:

/etc/init.d/ssh reload

Don't logout yet…

As you have an already established connection you will not be locked out of your ssh session (look at the iptables config file: it accepts already established connections).

On your LOCAL computer, open a new terminal and log in using the administration user (in this case, demo) to the port number you configured in the sshd_config file:

ssh -p 30000 demo@123.45.67.890

The reason we use a new terminal is that if you can't login you will still have the working connection to try and fix any errors. Linode also has the excellent ajax console so if it all goes horribly wrong, you can log into your slice from the Linode management area.

If all goes well you should login to a plain terminal:

demo@yourvpsname:~$

Success! We now know that the firewall and ssh_config works and we can log in. Right, use the logout command to exit that shell. You should be able to restart the server and log in as the non-root admin user.

shutdown now

Once the server reboots you need to log in and perform the remainder of these steps using the newly created admin user account.

OS Check and Free Memory

First thing is to confirm what OS we're using. We know we should be using Ubuntu Lucid but let's see:

cat /etc/lsb-release

You should get an output similar to this:

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=8.04
DISTRIB_CODENAME=hardy
DISTRIB_DESCRIPTION="Ubuntu 8.04"

Good. Memory usage should be very low at this point but let's check using 'free -m' (the -m suffix displays the result in MB's which I find easier to read):

free -m

It's nice to know what is going on so let's look at that output:

.                  total       used       free     shared    buffers     cached
Mem:             254       43         211          0          3            74
-/+ buffers/cache:       26         228
Swap:            511        0           511

The line to take notice of is the second one as the first line includes cached memory - in this demo slice I have 254MB of useable memory with 26MB actually used, 228MB free and no swap used. Nice.

Configure the Shell

Let's make the terminal a bit more attractive and a bit more informative by adding a few lines to our . bashrc file.

nano ~/.bashrc

Add the next few lines at the end of the existing text. The following line will make the terminal show the server name in colour and display the working directory (the directory we are in) in a different colour:

export PS1='\[\033[0;35m\]\h\[\033[0;33m\] \w\[\033[00m\]: '

If you look at the existing content of the .bashrc file, you may notice some 'PS1' content already - you can change the existing content if you prefer. This method simply changes the default output.

Now we can add aliases to the file. Aliases are short cuts to commands or sequences of commands. I've included a few below but you can have as many or as few as you want.

# Add aliases for frequently used commands
alias free="free -m"
alias update="sudo aptitude update"
alias install="sudo aptitude install"
alias upgrade="sudo aptitude safe-upgrade"
alias remove="sudo aptitude remove"

The examples above are pretty simple. Instead of typing free -m every time I want to look at the memory usage, I just type free. Typing sudo aptitude install can get tedious, so I just type install.

NOTE: The remaining Wiki pages give instructions without using these aliases. I did this so the documentation will make sense if separated. However, in general I always use these short cuts.

I still need to provide my password for the sudo command to work, but it is more productive/quicker/easier to have short cuts.

To activate the changes issue this command:

source ~/.bashrc

You should now see the slice name in purple and the working directory in brown.

To change the colours to your choosing, adjust the 0;35m and the 0;33m values in the 'export PS1' line of your .bashrc. For example:

export PS1='\[\033[0;32m\]\h\[\033[0;36m\] \w\[\033[00m\]: '

would give you a green and blue output.

Package Repositories

The Ubuntu Lucid Slice comes with a basic set of repositories but let's have a check to see what sources we are using:

sudo nano /etc/apt/sources.list

You should see the default list as follows:

## main & restricted repositories
deb http://us.archive.ubuntu.com/ubuntu/ lucid main restricted
deb-src http://us.archive.ubuntu.com/ubuntu/ lucid main restricted

deb http://security.ubuntu.com/ubuntu lucid-updates main restricted
deb-src http://security.ubuntu.com/ubuntu lucid-updates main restricted

deb http://security.ubuntu.com/ubuntu lucid-security main restricted
deb-src http://security.ubuntu.com/ubuntu lucid-security main restricted

## universe repositories - uncomment to enable
deb http://us.archive.ubuntu.com/ubuntu/ lucid universe
deb-src http://us.archive.ubuntu.com/ubuntu/ lucid universe

deb http://us.archive.ubuntu.com/ubuntu/ lucid-updates universe
deb-src http://us.archive.ubuntu.com/ubuntu/ lucid-updates universe

deb http://security.ubuntu.com/ubuntu lucid-security universe
deb-src http://security.ubuntu.com/ubuntu lucid-security universe

You can, of course, add more repositories whenever you want to but I would just give a word of caution: Some of the available repositories are not officially supported and may not receive any security updates should a flaw be discovered.

Keep in mind it is a server we are building and security and stability are paramount.

Update

Now we can update the sources so we have the latest list of software packages:

sudo aptitude update

NOTE: If you have used the .bashrc shown above you just need to enter update as the alias will use the entire command. I've put the whole thing here so you know what is happening.

Locales

Remember the Lucid Lynx install is a bare bones system so we need set the system locale:

sudo locale-gen en_GB.UTF-8
...
sudo /usr/sbin/update-locale LANG=en_GB.UTF-8

Time Zone

Let's begin by setting the timezone of your server. It may be set to your timezone or the timezone of the bulk of your users. If you're unsure which timezone would be best, consider using universal coordinated time (or UTC, ie. Greenwich Mean Time). Run the following command to set it:

dpkg-reconfigure tzdata

System Upgrade

Now we have updated the sources.list repositories and set the locale, let's see if there are any upgrade options:

sudo aptitude safe-upgrade

Followed by a:

sudo aptitude full-upgrade

Once any updates have been installed, we can move on to installing some essential packages.

Build Essentials

Ubuntu Lucid has some handy meta-packages that include a set of pre-defined programmes needed for a single purpose.

So instead of installing a dozen different package names, you can install just one meta-package. One such package is called 'build-essential'. Issue the command:

sudo aptitude install build-essential

Notice the programmes that are to be installed include gcc, make, patch and so on. All these are needed for many other programmes to install properly. A neat system indeed.

Enter 'Y' and install them.

Extra Bits

Here are some extra things I like to install, they are of course completely optional.

Locate tool

I like this tool for finding files on my system. You can build an index of the file system using the updatedb command. Then use locate to find items in the tree.

install locate
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License