Karma Yoga and SSL Certificates
Even though getting enlightened while doing the dishes sounds enticing, many people are nowadays equipped with a dishwasher. Luckily enough, technical innovation does not permeate all aspects of one’s life at the same pace, leaving leeway for inner work1. If you’re into IT and can relate, this blog post is for you. You don’t need to know anything about CI/CD, Kubernetes, or certbots.
Karma Yoga is the transformation of being that is based on one’s daily work in the world2. Let’s see how much karma we can create and get the witness, awareness, (and patience) in action3. We’ll use SSL certificates as an alibi and see how big of an endeavour we can make configuring Træfik with custom certificates4 5. We’ll expose 1 web app to a WAN via https with a database as backend.
I’ve been deploying containerized applications for many years now. Steps remain the same, growing on me like a mantra:
“भण्डारं क्लोन कुर्वन्तु, docker-compose.yaml इत्यस्य अनुकूलनं कुर्वन्तु, चित्रं निर्मायन्तु तथा च पात्रं चालयन्तु, भण्डारणं/दत्तांशकोशं विन्यस्यन्तु, पात्रं प्रति DNS अभिलेखबिन्दुं कुर्वन्तु, अन्त्यबिन्दुं सुरक्षितरूपेण WAN प्रति उजागरयन्तु, सम्भवतः VPN इत्यस्य पृष्ठतः. ॐ शान्ति: शान्ति: शान्ति:॥.”
This process takes me between 15 minutes and 0.5 days depending on the quality of the documentation and my level of caffeination. We are however not looking for speed or efficiency here, I’m just bragging.
Let’s start the exercise. Let’s first request the resources we will need to run our 2 containers. Durations are for indicative purposes only.
# | Task | Duration |
---|---|---|
1 | Get compute (e.g., a Debian VM) with an IP on a WAN | 1 day |
2 | Install Docker, build and run 2 containers | 10 minutes |
3 | Get the domain name | 4 months |
4 | Get the email configuration | 6 weeks |
5 | Get SSL certificate | 1 week |
6 | Get SSL certificate again, this time without a typo | 20 days |
6 | Piece everything together | 10 minutes |
Total: ~190 days |
The net result is very yogic. After involving only 6 people and in less than 200 days one gets: 1 mostly idling VM (for 2 containers), no service redundancy, no backup strategy, no CI/CD, but another prospective round of emails in 1 year when certs will silently expire (you may want to put a reminder in your calendar now before you forget).
All the pieces are now here. Let’s add a third container in the mix. Træfik is our reverse proxy of choice. Below, docker-compose.yaml
is given to serve the web app (myapp in the example) using a PostgreSQL database (db in the example). You’ll need to mount the certificate and key file you got via email into the Træfik container and reference them in traefik_dynamic.yaml
, itself referenced in traefik.yaml
. All code snippets are provided below.
docker-compose.yaml
version: "3"
services:
# ------------- #
# REVERSE PROXY #
# ------------- #
traefik:
image: traefik:2.8.5
container_name: traefik
restart: always
ports:
- 80:80 # http
- 443:443 # https
- 8080:8080 # dashboard
volumes:
# System mounts
- /var/run/docker.sock:/var/run/docker.sock
- /etc/localtime:/etc/localtime:ro
# Traefik config mounts
- ./traefik.yaml:/etc/traefik/traefik.yaml:ro
- ./traefik_dynamic.yaml:/etc/traefik/traefik_dynamic.yaml:ro
- ./ssl/certs:/etc/ssl/certs
# Traefik log mounts
- /data/traefik/log:/var/log
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.entrypoints=websecure"
# ------- #
# THE APP #
# ------- #
myapp:
restart: always
hostname: myapp
container_name: myapp-app
depends_on:
- db
image: myapp:1
volumes:
- /data/app/files:/usr/src/files:rw
labels:
# Enable Træfik
- "traefik.enable=true"
- "traefik.http.routers.myapp.service=myapp"
- "traefik.http.routers.myapp.entrypoints=websecure"
- "traefik.http.services.myapp.loadbalancer.server.port=3000"
- "traefik.http.routers.myapp.rule=Host(`myapp.com`, `www.myapp.com`)"
# HTTP redirect
- "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.https_redirect.redirectscheme.permanent=true"
- "traefik.http.routers.http_catchall.rule=HostRegexp(`{any:.+}`)"
- "traefik.http.routers.http_catchall.entrypoints=web"
- "traefik.http.routers.http_catchall.middlewares=https_redirect"
env_file: .env-local
networks:
- web
- myapp
# ------ #
# THE DB #
# ------ #
db:
restart: always
container_name: myapp-db
image: postgresql:15
volumes:
- /data/db/pgdata:/var/lib/postgresql/data:rw
env_file: .env-local-postgres
networks:
- myapp
networks:
myapp:
web:
external: true
traefik.yaml
# REFERENCE: https://github.com/traefik/traefik/blob/master/traefik.sample.yml
global:
checkNewVersion: true
sendAnonymousUsage: false
entryPoints:
web:
address: :80
websecure:
address: :443
http:
tls: {}
log:
level: INFO
filePath: /var/log/traefik.json
format: json
accessLog:
filePath: /var/log/traefik-accesslog.json
format: json
api:
insecure: true # False when prod
dashboard: true # False when prod
ping:
entryPoint: traefik
providers:
docker:
endpoint: unix:///var/run/docker.sock
watch: true
network: web
exposedByDefault: false
file:
filename: "/etc/traefik/traefik_dynamic.yaml"
watch: true
traefik_dynamic.yaml
tls:
certificates:
- certFile: /etc/ssl/certs/certificate.pem
keyFile: /etc/ssl/certs/private.key
After issuing ~$ docker compose up
, you should be able to read Træfik’s logs. It should look like traefik.json
provided below.
traefik.json
{"level":"info","msg":"Traefik version 2.8.5 built on 2022-09-13T15:19:09Z","time":"2022-09-22T17:57:17+02:00"}
{"level":"info","msg":"\nStats collection is disabled.\nHelp us improve Traefik by turning this feature on :)\nMore details on: https://doc.traefik.io/traefik/contributing/data-collection/\n","time":"2022-09-22T17:57:17+02:00"}
{"level":"warning","msg":"Traefik Pilot is deprecated and will be removed soon. Please check our Blog for migration instructions later this year.","time":"2022-09-22T17:57:17+02:00"}
{"level":"info","msg":"Starting provider aggregator aggregator.ProviderAggregator","time":"2022-09-22T17:57:17+02:00"}
{"level":"info","msg":"Starting provider *file.Provider","time":"2022-09-22T17:57:17+02:00"}
{"level":"info","msg":"Starting provider *traefik.Provider","time":"2022-09-22T17:57:17+02:00"}
{"level":"info","msg":"Starting provider *acme.ChallengeTLSALPN","time":"2022-09-22T17:57:17+02:00"}
{"level":"info","msg":"Starting provider *docker.Provider","time":"2022-09-22T17:57:17+02:00"}
Here are some things you may want to check if stuff goes wrong:
- Are you using the right certificate and key file?
- Use the
file
CLI tool to check the types of your files on the file system. You should seeserver.pem: PEM certificate
,private.key: ASCII text
- You can
cat
the content of the files:
server.pem
is contained between-----BEGIN CERTIFICATE-----
and-----END CERTIFICATE-----
private.key
is contained between-----BEGIN PRIVATE KEY-----
and-----END PRIVATE KEY-----
- Use the
- Have a look into Træfik’s logs:
/var/log/traefik.json
, not just thestdout
provided by Docker. - Map port 8080 in
docker-compose.yaml
and allow api insecure and dashboard intraefik.yaml
to peak into the services status.
Namaste 🔮
Categories: #web #spirituality