My server setup: Ranvir Singh and Linux containers

Over the next few weeks, we're going to be exploring how a few of our team members set up brand-new servers of their own. These aren't meant to be tutorials, but rather fun investigations into the near-infinite ways we can accomplish the same task.

If you'd like to be featured in a future edition, feel free to let me know: [email protected].

We all have our particular setups, applications we install, and services we run to keep our servers well-organized and secure. Today, I wanted to talk about a few things I do when starting with a new server.

Updates and security

The first thing I presume we all do is run apt update && apt upgrade -y, or a similar command for the package manager on your distro. After this, I try my luck with apt autoremove which, gets rid of some the unwanted files and packages that I won’t need.

Notice how I didn’t mention sudo in the above commands… that’s because when I first log in to my VPS, I’m logged in as the omnipotent root user. What’s worse is that I’m logged in as root user over SSH! Not good. So, my next step involves changing a few things about my server:

  1. Create a new user with root privileges.
  2. Make sure that the new user can log in over SSH using a public-private key pair.
  3. Make sure that root user can’t login over SSH.
  4. Block unnecessary ports.

The order of this checklist is essential!

1. Create a new user

All this involves is:

$ adduser USER
$ usermod -aG sudo USER

The first command creates the user named USER, prompts me for a new UNIX password plus a few details that you can skip through. The second command adds (appends) this user to the elite sudo group. I usually test this user by running login USER followed by the password I selected. I test the sudo capability by running a simple command like sudo apt update.

Sometimes I want to use sudo without entering the password every time. To do this, I open the sudoers file using the visudo command (similar to the vim editor), and append the following line at the end:


Here I replace the word USER with my actual username, of course. This is useful when I want to run automated tasks (as this user) and minimize the amount of manual (aka human) intervention. I seldom set up this passwordless sudo capability, but it comes in handy from time to time.

2. Adding SSH keys

Next, I add my public SSH key to by editing the file ~/.ssh/authorized_keys as the new user and append the contents of a public key from my local machine. You can learn more about SSH at our guide.

3. Making sure that root can’t log in

I perform this step only after I’ve confirmed I can SSH into my VPS as the new USER. I also make sure this user can perform sudo actions otherwise, I might end up locking myself out of my brand-new VPS.

I edit the sshd_config file located at /etc/ssh/sshd_configto change thePermitRootLogin yes` line to:

PermitRootLogin no

This adds a bit of extra security, since the attacker now has to guess my username as well—no generic phrase like root would work. Also, if sudo privileges are protected by yet another user password, an attacker would have another hurdle before gaining total control over my VPS.

Another thing I to change inside this sshd_config file is the permission for using clear text passwords. Using SSH keys to login should be the norm since passwords are sent as clear text over the SSH channel and can compromise server security.

I uncomment the line #PasswordAuthentication ... and set its value to no as shown below:

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
#PermitEmptyPasswords no

4. Enabling a firewall

This is perhaps the most diverse topic, since firewalls differ from OS to OS. However, I mostly use Ubuntu, where ufw is easy to use and configure. I open a few important ports for SSH, HTTP, and HTTPS, and the rest stay shut:

$ sudo ufw allow ssh
$ sudo ufw allow http https
$ sudo ufw enable

I always make sure not to run ufw enable without opening the SSH port! That’s just another opportunity for me to lock myself out of my VPS.

I’m well aware that all these security measures could be improved upon—I could even automate most of them!

Installing the essentials

The essentials that I use every day for my environment are:

  • Docker
  • Git
  • LXC

The Docker installation is easy if you follow the official documentation or our getting started guide. It involves adding official the Docker repository to our list of trusted repositories and installing Docker from there. However, I like to create a new Docker network to use instead of the default network Docker provides.

This uses the same bridge driver as the default Docker network does, but is vastly easier to work with as documented here. The following command creates a new network my-network:

$ docker network create --driver bridge my-network

Containers on this network can talk to one another freely without the user having to expose any ports. I like to run untrusted containers in a different Docker network away from any sensitive data.

Using this bridge network significantly eases the process of deployment, and my Dockerfiles stay relatively free from EXPOSE commands. After this, I log in to my Docker Store. I use this sometimes to get a snapshot of a running container docker commit and save it in this registry for further use as a backup or for postmortem debugging if a container keeps crashing. Admittedly, this is a dirty way of doing this, and there are better alternatives. But if it ain’t broken…

While I’m at it, I also make a point of setting up my GitHub username. This is nothing special, but it does come handy at times.

A true container hypervisor

While Docker is great, I sometimes need a container that feels like an actual isolated operating system. For this, I use LX Containers.

LXC containers come with their own subnet, DNS and you can log in to any one of them and never realize that you are in a container, unless you know where to look. The storage comes from a nice OpenZFS backbone. This means automates backups using zfs send, super-fast and efficient compression and most importantly no chance of undetected data corruption.

You can get a glimpse of a simple LXC setup over here, and I hope you can get creative with it and get the most of out of your VPS.

What did I miss?

Hopefully, my setup inspired you to organize your VPS better. However, there’s always room for improvement. In case, you find that something in my setup can be improved upon, I would love to hear your constructive criticism. Feel free to email me at [email protected]!