TL;DR

Server Setup

  • chose a provider, create (and verify) your account
  • rent a virtual server fitting your needs
  • connect to your server as root
  • add a new user to your server that is in the sudoers group
  • verify that you can connect as the user and use sudo
  • disable password and root login
  • setup ssh to connect as your user automatically

Webserver Setup

  • install & setup nginx
  • let your user own nginx root directory
  • check for logrotate
  • setup letsencrypt
  • let your domain point to your new server

Chosing a provider

There are different providers on the market. Famous, big names might be Amazon Web Services (AWS) or GCP (Google Cloud Platform). You can also self-host a blog using GitHub Pages. Depending on what you want to pay and what features you want to have, your choice can differ from mine. The main criteria I considered where:

  • company & company principal office bc. of legal reasons
  • pricing

My choice

I chose Hetzner because I had experience with it already from my jobs and friends who had been customers there already. After registering an account, you can add your payment information and book a server. The provisioning of the virtual server with Ubuntu took less than three minutes. At Hetzner, you can add an SSH-key before the server is provisioned. Thus, you can directly ssh onto your server once the provisioning is done using ssh root@yourServerIP.

Server setup - Ubuntu

When connecting the first time, you will connect as root. Root logins are a target of attacks and the root user is the user that can do - and break - everything. It is a security best-practice to not connect as root. Moreover, it is also recommended to disable password login. Thus, you want to create your own “admin” user, that is part of the sudoers group so you can do things only root can do (using sudo) while disabling password login and root login to protect against attacks (and password leaks).

User Setup

  1. As root, run adduser yourusername to add your user
  2. As root, run usermod -aG sudo yourusername to add your user to the sudoers group
  3. As root, set a root password with passwd (you need that when switching to the user on the server)
  4. As root, set a password for your user: passwd username (you need that when using sudo with your user)
  5. Copy your public ssh-key to the server for your user so your user can connect via ssh: ssh-copy-id yourusername@yourServerIP (it adds your public key to the .ssh/authorized_keys of the user)

Security Setup

Warning

Keep the terminal with the root user connection open so you still have a root connection if something goes wrong during the setup.

  1. As root, edit /etc/ssh/sshd_config:
    • Set PasswordAuthentication no to disable password login
    • Set PermitRootLogin no to disable root login
    • Resart the ssh-service for changes to take effect: systemctl restart ssh
  2. Start a new terminal and try to connect as root. It should fail. Try to connect as your user ssh yourusername@yourServerIP. It should work.
  3. Switch to the root user using su root. Enter the root password. It should work. Use exit to switch back.

Local Setup

For convenience, you can modify your local ssh-config so that you automatically connect as your user to your server. Instead of ssh yourusername@yourServerIP you then only need to enter ssh yourServerIp. Once you have DNS enabled and your domain pointing to your server IP, this setting can be used to connect like ssh your-domain.com. Edit your .ssh/config (create the file if it does not exist):

Host your-domain.com
   User yourusername

Webserver setup

Nginx

Your virtual server is blank. You will need a Webserver to answer incoming requests. Install nginx running sudo apt install nginx. Nginx comes with some default config. Checkout /etc/nginx on your server to make yourself familiar with it. For details, checkout the official nginx guide. In /etc/nginx/nginx.conf. it is those two lines that matter (in there per default after the installation):

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

In sites-enabled, you will see a default symlink to a config in sites-available. I followed this default and renamed the config inside sites-available to “blog.conf” (because it is for my blog). All configuration for routing requests to my blog goes in there.

Without changes, the default config inside sites-available should show a block like this:

	location / {
		root /var/www/html;
		index index.html;
		try_files $uri $uri/ =404;
	}

So the document root that is used by nginx to look for files to serve is /var/www/html. Because my blog consists only of static files, I will put the content in that very directory. In order to keep my security setup, I want that directory to be owned by the user I use to connect to my server. I will use that very user to sync files to the server.

Change ownership of /var/www/html

sudo chown $USER:yourusername /var/www/html

See “your” first site

If you enter your IP in a browser, you should see the “Welcome to Nginx” landingpage. Congratulations, you just accessed a resource on your server!

Logrotate

Nginx writes logs. You can see them in /var/log/nginx. Those logs will slowly consume storage on your server, if you do not do something about it. There is a ready to use solution called logrotate. DigitalOcean has a neat article on setting up logrotate on Ubuntu. With my machine on Hetzner, logrotate was preconfigured and all I had to do was check the log retention times.

SSL & DNS

Warning

Before carrying out this step, you might want to migrate content of your blog to /var/www/html before you switch to serving content for your-domain.com from the new server we just set up.

The first site we saw earlier was accessible via http only. State of the art is using https. In order to be able to serve your content via https, you need a valid SSL certificate. There is a free service you can set up on your server to take care of that: letsencrypt.

DigitalOcean got us covered again, I followed this guide to set up letsencrypt with nginx on Ubuntu.

Info

The important note here is: you need to have your domain registered already.

I had one because this blog existed before I migrated to an own virtual server. I had my domain registered via IONOS. So I had to log in to my IONOS Admin backend and change the A and AAAA records for my domain to point to my new server’s IP. As soon as you do that, your blog is down. In order for certbot to work, you need to have your domain pointing to your IP before you run certbot. Otherwise, certbot cannot verify the domain ownership and will fail.

If it succeeds, you should be able to reach your site via https and your blog is online again, now served from your new server.