Setup a VPS with Traefik and Docker
IMPORTANT
Please check out the 2022 version of the article on how to set up a VPS here.
This article is a short read and may be of some value if you are just starting to explore the topic.
So, you have a fresh and clean VPS server instance, wipe it and install a clean slate Ubuntu (LTS preferred) or a modern Debian.
Now ssh into it and start shelling:
$ sudo apt update
$ service apache2 stop
- just in case you didn’t clean slate ;-)
Install Docker
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sh get-docker.sh
$ rm get-docker.sh
Install a Firewall, Python Pip for Docker Compose, Fail2Ban for ssh security
$ sudo apt install ufw python-pip fail2ban
$ 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 status
check your settings before enabling
$ ufw enable
Read more about UncomplicatedFirewall here
Fail2Ban
Protect, watch, track, lock suspicious logins using Fail2Ban
Read a bit and setup, as much as you need.
SSH Keys
Add your local ssh key as an authorized key, usually here (use an editor of your choice, if like vim):
$ vim .ssh/authorized_keys
Taken from the Traefik Documentation (2019-03-31)
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
$ touch /opt/traefik/acme.json && chmod 600 /opt/traefik/acme.json
$ touch /opt/traefik/traefik.toml
# /opt/traefik/docker-compose.yml
version: '2'
services:
traefik:
image: traefik:1.5.4
restart: always
ports:
- 80:80
- 443:443
networks:
- web
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/traefik/traefik.toml:/traefik.toml
- /opt/traefik/acme.json:/acme.json
container_name: traefik
networks:
web:
external: true
debug = false
logLevel = "ERROR"
defaultEntryPoints = ["https","http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[retry]
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "my-awesome-app.org"
watch = true
exposedByDefault = false
[acme]
email = "your-email-here@my-awesome-app.org"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"
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.docker.network=web"
- "traefik.enable=true"
- "traefik.basic.frontend.rule=Host:app.my-awesome-app.org"
- "traefik.basic.port=9000"
- "traefik.basic.protocol=http"
- "traefik.admin.frontend.rule=Host:admin-app.my-awesome-app.org"
- "traefik.admin.protocol=https"
- "traefik.admin.port=9443"
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 ➡️