Setup a VPS with Traefik v2.5 and Docker
This tutorial is targeted for fresh Ubuntu (maybe Debian, too, but I won’t promise 😛)
So, you booked a fresh and clean VPS server instance, now ssh into it and start shelling around:
$ sudo apt update -y && sudo apt upgrade -y --no-install-recommends
$ sudo apt install -y fail2ban ufw
$ service apache2 stop
- just in case Apache blocks port 80! Having ports 80 and 443 preoccupied will give you a hard time, as a beginner.
Lock your VPS for root and password login
PLEASE exchange your-username
in the following lines with your proper chosen username
- generate your custom (main/admin/owner) user account
$ adduser your-username
-
give this user sudo permissions
$ usermod -aG sudo your-username
-
switch roles to your-username
$ su - your-username
-
prepare to ssh only login restrictions
$ mkdir ~/.ssh && chmod 700 ~/.ssh
$ touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys
-
copy the content of your .pub ssh key into the authorized_keys
$ nano ~/.ssh/authorized_keys
-
restrict ssh settings for session
$ sudo nano /etc/ssh/sshd_config
and change the permission to “NO” for the following# /etc/ssh/sshd_config PasswordAuthentication no PermitRootLogin no
I absolutely recommend reading a little deeper and restrict what you DO NOT need!
-
recheck your authorized_keys are set properly and sshd_config is fine, then:
$ sudo systemctl restart ssh.service
-
in a second terminal you should now be able to login as:
$ ssh -A your-username@your-vps-server.ip.com
-
another fresh terminal window and verfiy you cannot login as root anymore
$ ssh root@your-vps-server.ip.com
Install Docker
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sh get-docker.sh
$ rm get-docker.sh
*Read carefully what docker prints in the end AND read the documentation
Setup a basic Firewall for security
There is a neat blog post with further apps, that help you keep the guards up on Digital Ocean!
$ ufw default deny incoming
$ ufw default allow outgoing
$ ufw allow 22/tcp
this usually is ssh (make sure you allow your chosen ssh key)
$ ufw allow 80/tcp
for http requests
$ ufw allow 443/tcp
for https requests
$ ufw show added
check your settings before enabling
$ ufw enable
Read more about UncomplicatedFirewall here
Keep in mind, you might need other ports now or in the future 🪲
What’s Fail2Ban?
Protect, watch, track, lock suspicious logins using Fail2Ban
Read a bit and setup, as much as you need.
Taken from the Traefik Documentation (2019-03-31)
From this point on, you should make yourself a little familiar about user rights and folder permissions. This is more an inspiration on how you can achieve this yourself.
I advise you read it yourself ;-) Traefik - Let’s Encrypt & Docker
$ docker network create web
$ mkdir -p /opt/traefik
$ touch /opt/traefik/docker-compose.yml
# /opt/traefik/docker-compose.yml
version: "3.9"
networks:
web:
external: true
services:
traefik:
image: "traefik:2.5.3"
container_name: "traefik"
restart: always
networks:
- web
- default
command:
- "--providers.docker.swarmMode=false"
# - "--providers.docker.constraints=Label(`traefik.constraint-label`, `traefik-public`)"
- "--log.level=DEBUG"
- "--api.insecure=false"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=web"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web"
# - "--certificatesresolvers.myhttpchallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.myhttpchallenge.acme.email=INSERT-YOUR-EMAIL-HERE@test.test"
- "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
# - "8080:8080"
volumes:
- "traefik-public-certificates:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
volumes:
# Create a volume to store the certificates, there is a constraint to make sure
# Traefik is always deployed to the same Docker node with the same volume containing
# the HTTPS certificates
traefik-public-certificates:
Example Docker Compose
version: "2.1"
services:
app:
image: my-docker-registry.com/my-awesome-app/app:latest
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
restart: always
networks:
- web
- default
expose:
- "9000"
labels:
- "traefik.enable=true"
- "traefik.docker.network=web"
- "traefik.http.routers.my_nice_app.entrypoints=web"
- "traefik.http.routers.my_nice_app.rule=Host(`app.test.test`)"
- "traefik.http.routers.my_nice_app.middlewares=https_redirect"
- "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https"
- "traefik.http.routers.my_nice_app_https.entrypoints=websecure"
- "traefik.http.routers.my_nice_app_https.tls.certresolver=myhttpchallenge"
- "traefik.http.routers.my_nice_app_https.rule=Host(`app.test.test`)"
- "traefik.http.services.my_nice_app.loadbalancer.server.port=9000"
db:
image: my-docker-registry.com/back-end/5.7
restart: always
redis:
image: my-docker-registry.com/back-end/redis:4-alpine
restart: always
events:
image: my-docker-registry.com/my-awesome-app/events:latest
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
restart: always
networks:
- web
- default
expose:
- "3000"
labels:
- "traefik.backend=my-awesome-app-events"
- "traefik.docker.network=web"
- "traefik.frontend.rule=Host:events.my-awesome-app.org"
- "traefik.enable=true"
- "traefik.port=3000"
networks:
web:
external: true
Most Important Tip in the Docs
Always specify the correct port where the container expects HTTP traffic using traefik.port label. If a container exposes multiple ports, Traefik may forward traffic to the wrong port. Even if a container only exposes one port, you should always write configuration defensively and explicitly.
⬅️ Read previous Read next ➡️