Docker Certbot , reverse proxy setup advice

Hi All,

I could really use some advice,

(bit of back story) currently I have a server that runs Armbian and I'm trying to transition to a new OS , SkiffOS for any interested parties, I have several docker container services ( home assistant , caldav,etc) behind a nginx container acting as a reverse proxy , I have certbot installed using the package manager , I use a cronjob to check and renew certs for all exposed services .

@daily certbot renew --pre-hook "docker-compose -f /root/docker-compose.yml down" --post-hook "docker-compose -f /root/docker-compose.yml up -d"

however the new OS has one issue, its based on build root and so doesn't have Certbot available as a buildable package, So I would like to use the Certbot docker image.

I was thinking that the cron job could be the same but inplace of the certbot renew command I could use

@daily docker run -it --rm --name certbot -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" -p 80:80 certbot/certbot certonly --pre-hook "docker-compose -f /root/docker-compose.yml down"  --post-hook "docker-compose -f /root/docker-compose.yml up -d"

would this work ?

however I am open to alternative methods if this is not optimal and there is a better way of doing it .

thank you in advance for you advice.

1 Like

Well, without the contents of the docker compose files (not that I have any experience with those :stuck_out_tongue:), I can only say in general "yes, running certbot from the docker container and mapping all the relevant volumes should work". Although I'm pretty sure you should also map some TCP ports? Not sure.. As I said, no docker experience..

Reading those pre and post hooks, I'm assuming you're running certbot with the standalone plugin? Well, if it works.. Usually, I'm not a fan of the standalone plugin (a little bit of downtime..), but I'm not going to advice against it, because.. Well.. Docker.. :grimacing:

3 Likes

Hi thanks for the reply , I forgot to put a port 80 in the docker run command , Ive edited the original post now just in case some one else wishes to use it. If it helps I can post my nginx.conf and my docker compose for people to peruse .

docker-compose.yml

version: '3.7'
services:

  nginx:
    depends_on:
      - radicale
      - homeassistant 
    image: nginx:latest
    container_name: nginx_reverse_proxy
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /root/nginx.conf:/etc/nginx/nginx.conf
      - /root/nginx/error.log:/etc/nginx/error.log
      - /root/nginx/access.log:/etc/nginx/access.log
      - /etc/letsencrypt/:/etc/letsencrypt/
      - /root/nginx/dhparams.pem:/etc/nginx/dhparams.pem
      - snikket_data:/snikket:ro  
    restart: unless-stopped
    network_mode: host
 
  radicale:
    image: tomsquest/docker-radicale
    container_name: radicale
    ports:
      - 127.0.0.1:5232:5232
    init: true
    read_only: true
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - SETUID
      - SETGID
      - CHOWN
      - KILL
    healthcheck:
      test: curl -f http://127.0.0.1:5232 || exit 1
      interval: 30s
      retries: 3
    restart: unless-stopped
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /root/radicale/data:/data
      - /root/radicale/config:/config:ro
      - /root/radicale/users:/etc/radicale/users
      - /root/radicale/log:/var/log/radicale/log

  homeassistant:
    container_name: home-assistant
    image: homeassistant/home-assistant:stable
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /root/homeassistant:/config
    environment:
      - TZ=Europe/London
    restart: unless-stopped
    network_mode: host

  esphome:
    image: esphome/esphome
    volumes:
      - /root/esphome/config:/config:rw
      - /etc/localtime:/etc/localtime:ro
    network_mode: host
    restart: unless-stopped

  snikket_proxy:
    container_name: snikket-proxy
    image: snikket/snikket-web-proxy:dev
    env_file: snikket.conf
    network_mode: host
    volumes:
      - snikket_data:/snikket
      - acme_challenges:/var/www/html/.well-known/acme-challenge
    restart: "unless-stopped"
  snikket_certs:
    container_name: snikket-certs
    image: snikket/snikket-cert-manager:dev
    env_file: snikket.conf
    volumes:
      - snikket_data:/snikket
      - acme_challenges:/var/www/.well-known/acme-challenge
    restart: "unless-stopped"
  snikket_portal:
    container_name: snikket-portal
    image: snikket/snikket-web-portal:dev
    network_mode: host
    env_file: snikket.conf
    restart: "unless-stopped"

  snikket_server:
    container_name: snikket
    image: snikket/snikket-server:dev
    network_mode: host
    volumes:
      - snikket_data:/snikket
    env_file: snikket.conf
    restart: "unless-stopped"

volumes:
  acme_challenges:
  snikket_data:

I should point out that Snikket (my xmpp server ) gets its own certs so I don't require certbot to get them for these containers only the caldav and home assistant containers.

here is my nginx.conf

user www-data;
worker_rlimit_core 500M;
worker_processes 1;

events {

  worker_connections 1024;

}

http {
  map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
  }
  error_log /etc/nginx/error.log warn;
  access_log /etc/nginx/access.log;
  ssl_dhparam /etc/nginx/dhparams.pem;
  ssl_prefer_server_ciphers on;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_protocols TLSv1.2 TLSv1.3;
  add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
  ssl_stapling on;
  ssl_stapling_verify on;
  ssl_certificate /etc/letsencrypt/live/myradicaleserver.duckdns.org/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/myradicaleserver.duckdns.org/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/myradicaleserver.duckdns.org/chain.pem;
  ssl_session_cache shared:SSL:10m;
  proxy_buffering off;

  server {
    listen 80;
    server_name myradicaleserver.duckdns.org;
    return 301 https://$server_name$request_uri;    
  }
  
  server {
    listen 443 ssl http2;
    server_name myradicaleserver.duckdns.org;

    location /radicale/ {
    proxy_pass           http://localhost:5232/;
    proxy_set_header     X-Script-Name /radicale;
    proxy_set_header     X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass_header    Authorization;
    }
  }

  server {
    listen 80;
    server_name myhomeassistantserver.duckdns.org;
    return 301 https://$server_name$request_uri;
  }

  server {
    listen 443 ssl http2;
    server_name myhomeassistantserver.duckdns.org;

    location / {
        proxy_pass http://localhost:8123;
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     }

     location /api/websocket {
        proxy_pass http://localhost:8123/api/websocket;
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

     }
  }

  server {
   # Accept HTTP connections
    listen 80;
    listen [::]:80;

    server_name mysnikketserver.duckdns.org;
    server_name groups.mysnikketserver.duckdns.org;
    server_name share.mysnikketserver.duckdns.org;
    client_max_body_size 20M;
 
    location / {
        proxy_pass http://localhost:5080/;
        proxy_set_header      Host              $host;
        proxy_set_header      X-Forwarded-For   $proxy_add_x_forwarded_for;
     }
  }

  server {
    # Accept HTTPS connections
    listen [::]:443 ssl ipv6only=on;
    listen 443 ssl;
    ssl_certificate /snikket/letsencrypt/live/mysnikketserver.duckdns.org/fullchain.pem;
    ssl_certificate_key /snikket/letsencrypt/live/mysnikketserver.duckdns.org/privkey.pem;
    client_max_body_size 20M;       
 
    server_name mysnikketserver.duckdns.org;
    server_name groups.mysnikketserver.duckdns.org;
    server_name share.mysnikketserver.duckdns.org;

    location / {
        proxy_pass https://localhost:5443/;
        proxy_set_header      Host              $host;
        proxy_set_header      X-Forwarded-For   $proxy_add_x_forwarded_for;
        # REMOVE THIS IF YOU CHANGE `localhost` TO ANYTHING ELSE ABOVE
        proxy_ssl_verify      off;
        proxy_set_header      X-Forwarded-Proto https;
        proxy_ssl_server_name on;
     }
  }  
}

thanks again for the advice

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.