Some scratch notes on setting up a Hetzner VPS to run docker-based Flask projects, static websites, and more using Caddy as a reverse proxy.
Purchase Cheapest Cloud VPS from Hetzner
Their Falkenstein, Germany location gave me the best ping times, so I chose that one. At €2.49/month for a KVM-based VPS with 2GB RAM, 1 vCPU, and 20GB SSD, this was cheaper than my previous preferred European provide, Time4VPS.
I chose a Debian 10 Buster image. It was deployed within seconds (no account verification needed… and didn’t even have to pay yet). They didn’t provide a root password, but luckily they have a section in their web panel that allows adding an SSH key. Put in my public key and logged in as root via SSH.
Initial Setup…
Let’s setup a sudo user, aliases, and initial installs
adduser <my_user_name>
usermod -aG sudo <my_user_name>
sudo apt update
sudo apt install apt-transport-https ca-certificates curl \
software-properties-common mc htop tmux gcc g++ libc6-dev
Update .bashrc
to enable my favorite alias with this line: alias ll='ls -alF'
Also, since the Hetzner SSH key web interface puts the authorized key into the root space, I had to copy it to my user space and change owner:
sudo cp /root/.ssh/authorized_keys /home/<my_user_name>/.ssh/authorized_keys
cd ~/.ssh
sudo chown <my_user_name> authorized_keys
sudo chgrp <my_user_name> authorized_keys
Some SSH Setup
Create a private/public key pair:
ssh-keygen -t rsa
Update /etc/ssh/sshd_config
with the following:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
Install Docker:
Get Docker repositories into apt sources, then install:
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/debian buster stable"
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
Install Gitlab Runner:
Get Gitlab repositories into apt sources, then install. Replace the url with https://packages.gitlab.com/install/repositories/runner/gitlab-runner:
curl -L \
<url>/script.deb.sh \
| sudo bash
sudo apt update
sudo apt install gitlab-runner
Delete or rename .bash_logout under the gitlab-runner userspace:
cd /home/gitlab-runner
mv .bash_logout .bash_logout_rename
Add gitlab-runner to the docker group so it can run build and deploy jobs:
sudo usermod -aG docker gitlab-runner
If you are ready to register this VPS with a Gitlab project, then do this:
sudo gitlab-runner register # I chose shell as exectutor
Install Go
Get binary and install:
wget https://golang.org/dl/go1.15.1.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.14.3.linux-amd64.tar.gz
Add Go path to path in .profile
:
PATH="/usr/local/go/bin:$PATH"
Install Hugo
The best static site generator is Hugo. The best way to install the latest version is from source:
mkdir $HOME/src
cd $HOME/src
git clone https://github.com/gohugoio/hugo.git
cd hugo
go install --tags extended
It will put the hugo binary in ~/go/bin
, although I like to move it to /usr/local/go/bin
. It will also leave a bunch of files in a download cache in ~/go/pkg
. Clean it up with:
go clean -modcache
Install Caddy
Get binary and install:
echo "deb [trusted=yes] https://apt.fury.io/caddy/ /" \
| sudo tee -a /etc/apt/sources.list.d/caddy-fury.list
sudo apt update
sudo apt install caddy
I like creating a ~/caddy
directory and putting Caddyfile
inside. An example of using it for a reverse proxy:
# Add gzip compression to requests
(webconf) {
encode gzip
}
subdomain.example.org {
reverse_proxy 127.0.0.1:8000
tls [email protected] # For automatic Let's Encrypt SSL certificates
import webconf
}
It’s nice having a hard-linked file in my user space while still having it in Caddy’s system startup space:
cd /etc/caddy
sudo mv Caddyfile Caddyfile_bak
sudo ln ~/caddy/Caddyfile /etc/caddy/Caddyfile
Caddy will automatically start when the system is started and will load the Caddyfile that is hard-linked to my user space Caddyfile.
How is this VPS Used?
Basically, gitlab-runner is registered to a project (i.e. Flask application) that is designed to run out of a Docker. And build and deploy scripts are called in the .gitlab-ci.yml
file of the respective repository. This server will take care of the rest.