My server setup checklist

This is the checklist I follow when I create a new Linux Debian Server. The goal is a safe shared hosting environment where every user can ssh to the server but no user can see the content of another users home folder.

Setup language

You need to setup language if you get error messages like this one

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
        LANGUAGE = "en_US.UTF-8",
        LC_ALL = (unset),
        LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").

Run the following two commands to solve the issue:

locale-gen en_US en_US.UTF-8
dpkg-reconfigure locales

File Permissions

Files should be restricted to the owner only. This must be the case for newly created files. Thus we set an umask that works both locally and over SSH. We also ensure the home folder for the current user, as well as future ones, has those strict permissions.

  1. In the file /etc/login.defs
    do: umask 077
  2. In the file /etc/profile
    do: umask 077
  3. In the file /etc/pam.d/common-session
    do: session optional umask=077
    (you might just need to append umask=077 at the end of an existing line)
  4. In the file /etc/adduser.conf
    do: DIR_MODE=0700
  5. run: chmod -r 700 /home/CURRENTUSER

Login security and Root login security and sudoers

You should not be able to log in as root using password. Instead we use key authentication for root.

Paste your public key into /root/.ssh/authorized_keys. Try to log in using your key to make sure this works.

passwd -d root

Modify /etc/sudoers to give your own account full sudo rights. My file looks like this somewhere in the middle:

# User privilege specification
root ALL=(ALL) ALL

That is a kinda crude way to do it. On ubuntu the standard way to do is to add the user to the admin group:

sudo adduser USERNAME admin

IP configuration

  1. Make the changes to /etc/network/interfaces
  2. /etc/init.d/networking restart

Configure mounts and limit disk IO

Please start with reading my guide on how to add storage devices.

If you have loads of RAM available and want to limit disc IO you can tell the kernel to avoid swapping processes out of physical memory for as long as possible:

sudo sysctl vm.swappiness=0

Add/Remove new users

To add a new user use the command: adduser [username]
Note that usage of this command (adduser) is recommended compared to using the more lowlevel command useradd.

To remove a user use the command: userdel -fr [username] The -fr part makes sure home folder and other files are delete. Without it you will have to delete the files using another command.

To list the current users: cat /etc/passwd | cut -d":" -f1

Install web server packages

We install:

sudo apt-get install apache2
sudo apt-get install libapache2-mod-ruid2
sudo apt-get install libapache2-mod-macro
sudo a2enmod macro proxy_http ssl rewrite
sudo apt-get install php5 php5-gd php5-curl php5-mcrypt php5-json
sudo apt-get install mysql-server mysql-client libapache2-mod-auth-mysql php5-mysql
sudo apt-get install postfix

Configure PHP

Change the following values in /etc/php5/apache2/php.ini
To increase some limits

Configure MySQL

We want mysql to use utf8 per default instead of latin1. Find your MySQL configuration file (on most Linux/BSD systems it's /etc/mysql/my.cnf) and make sure it's got the following statements under the relevant headers. None of these settings should be set per default so just paste them directly under the corresponding header:


Also make sure you only accept connections from localhost. This is good for security and is the default in Ubuntu 11.10:


If you scan your computer from the outside using nmap you will notice that port 3306 is actually closed from the outside world. With this setting there is no reason to add firewall rules for it.

Restart MySQL and make sure it’s working:

service mysql restart

TODO: query cache size etc.

Configure Apache2

Do you get this message?

apache2: Could not reliably determine the server's fully qualified domain name, using for ServerName
 ... waiting apache2: Could not reliably determine the server's fully qualified domain name, using for ServerName

We just need to tell apache what the name of the server is. The name of my server is berit. So I ServerName berit to /etc/apache2/httpd.conf:

echo -e "\nServerName berit" | sudo tee --append /etc/apache2/httpd.conf

Upload and update the config files according to this link.

sudo a2dissite 0*
sudo rm /etc/apache2/sites-available/default
sudo rm /etc/apache2/sites-available/default-ssl
sudo a2ensite macrobased
sudo a2enconf macro
sudo service apache2 reload

Configure PHPMyAdmin

Open the file /etc/phpmyadmin/

You may want to hide some system databases from the web interface. To do that you would add a row like this to the middle of the file:

$cfg['Servers'][$i]['hide_db'] = 'information_schema';
$cfg['Servers'][$i]['hide_db'] = '^information_schema|mysql|performance_schema|phpmyadmin|test$';

Add these rows to the end of the file to force SSL and increase the max rows per page:

$cfg['ForceSSL'] = true;
$cfg['MaxRows'] = 1000;

If you want to be able to autologin as root (dangerous but handy on local installations):

$cfg['Servers'][$i]['AllowNoPassword'] = 'true'; 
$cfg['Servers'][$i]['auth_type'] = 'config';
$cfg['Servers'][$i]['user'] = 'root';
$cfg['Servers'][$i]['password'] = '';

Setting up Backups

I have written a separate guide on how to setup backups for your linux server.