5 min read

Containerised Hosting Part [1/3]: Server Preparation

A tutorial on setting up your own web hosting service with automation and security using Ubuntu, Docker, Traefik, Let's Encrypt and more!
Containerised Hosting Part [1/3]: Server Preparation


This series of posts aim at setting up a server as a container host which can be managed via admin panels through a browser.

This Architecture will provide instructions and sample configurations to setup the following.

  • Docker for Ubuntu
  • Webmin Management Panel
  • Docker Compose
  • Traffic Edge Router with Let’s Encrypt
  • Portainer (Container Management Panel)
  • Wordpress Blog and it’s dependencies
  • Ghost Blog and It’s Dependencies

This series will be releasing with 1 post every week and more sample configurations may be added in the future.

Let’s get started!

Step 0 - Find a Server

On your favourite Public/Private Cloud provider,Personal Server or even a Virtual Machine, start by installing Ubuntu Server 20.04. Once done with installing the OS, there are certain things to be done to improve the security and usability of the server.

Step 1 - Login as Root

To login to your server, you will need your server IP address and root user credentials. If you have an SSH key for authentication, you will need to have the private key for the root user.

ssh root@<your_server_ip>

Accept the warning about host authenticity if it appears. If you are using password authentication, provide your root password to log in.

Note: If this is your first time logging into the server with a password, you may also be prompted to change the root password.

Step 2 - Create a User

Once you are logged in as root, you need to create a new user account

adduser <username>

Substitute <username> with your desired username.

You will be asked a few questions, starting with the account password.

Enter a strong password and, optionally, fill in any of the additional information if you would like. This is not required and you can just hit ENTER in any field you wish to skip.

Step 3 - Grant Administrative Rights to the New User

We now have an account with normal privileges, However we sometimes need to perform administrative tasks.

We can avoid logging out and logging into the root account by simply granting our current user root privileges.

This will allow our normal user to run commands with admin rights by using the word sudo before each command.

As root run the following command to add your new account to the sudo group. (Substitute <username> with your normal account username):

usermod -aG sudo <username>

Now, when logged in as your regular user, you can type sudo before commands to perform actions with superuser privileges.

Step 4 - Setup a Firewall (Uncomplicated Firewall a.k.a. UFW)

Ubuntu Servers come with UFW installed and this can be used to ensure connections are allowed to only certain preconfigured services.

Applications can register their profiles with UFW on install. These profiles allow UFW to manage these applications directly by name. OpenSSH which is the service that provides SSH capabilities to the server has a profile registered with UFW, we will be using that as an example.

You can see the list by running:

ufw app list

You should see an output similar to

Available applications:

We now need to allow SSH connections through the firewall so that we can login to the server the next time. We do this by typing:

ufw allow OpenSSH

We can now enable the firewall by running:

ufw enable

Type y and press ENTER to proceed.

You can see the status of the firewall by running the following command:

ufw status

You should see the following output:

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

The Firewall is now blocking all connections except SSH so if you have any more services, make sure you configure those too. You can refer the UFW Essentials guide by DigitalOcean for more UFW operations.

Step 5 - Enable External Access for new User

The process for configuring SSH access for your new user depends on whether your server’s root account uses a password or SSH keys for authentication.

If the Account uses Password Authentication

If you logged in to your root account using a password, then password authentication is enabled for SSH. You can SSH to your new user account by opening up a new terminal session and using SSH with your new username:

ssh <username>@<your_server_ip>

After entering your regular user’s password, you’ll be logged into your account. If you need to run a command with administrative rights, you need to append sudo to the start of your command like so:

sudo <command_to_be_run>

You will be prompted for your password for the first time in each session when you run a command with sudo

I do recommend setting up SSH Keys for authentication instead of password authentication. You can Follow DigitalOcean’s excellent guide on how to do that, here.

If the Account uses SSH Key Authentication

If you logged in to your root account using SSH keys, then password authentication is disabled for SSH. You will need to add a copy of your local public key to the new user’s ~/.ssh/authorized_keys file to log in successfully.

Since your public key is already in the root account’s ~/.ssh/authorized_keys file on the server, we can copy that file and directory structure to our new user account in our existing session.

rsync --archive --chown=<username>:<username> ~/.ssh /home/<username>
Note: The rsync command treats sources and destinations that end with a trailing slash differently than those without a trailing slash. When using rsync below, be sure that the source directory (~/.ssh) does not include a trailing slash (check to make sure you are not using ~/.ssh/).

Step 6 - Install Docker Engine for Ubuntu

Uninstall Existing Versions:

sudo apt-get remove docker docker-engine docker.io containerd runc
It’s OK if apt-get reports that none of these packages are installed.

Setup the Repository:

Update the apt package index and install packages to allow apt to use a repository over HTTPS

sudo apt-get update

sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \

Add Docker’s official GPG key:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

Configure the repository for the stable version of docker:

sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \

Install Docker Engine:

Update the apt package index, and install the latest version of Docker Engine and containerd:

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

Add your user to the docker group:

The docker group grants privileges equivalent to the root user. For details on how this impacts security in your system, see Docker Daemon Attack Surface.
sudo usermod -aG docker $USER

Log out and log back in so that your group membership is re-evaluated.

Verify that you can run docker without sudo

docker run hello-world

Configure Docker to start on boot

sudo systemctl enable docker

Come back next week for Part 2 of this series where we will continue setting up our management services and edge routers.