feat(reverse-proxy): Add Caddy for reverse proxy

Signed-off-by: Tuan-Dat Tran <tuan-dat.tran@tudattr.dev>
This commit is contained in:
Tuan-Dat Tran
2025-01-12 21:19:37 +01:00
parent 88141f8869
commit 1a1b8cb69c
18 changed files with 299 additions and 47 deletions

13
docker-lb.yml Normal file
View File

@@ -0,0 +1,13 @@
---
- name: Set up reverse proxy for docker
hosts: docker_lb
gather_facts: yes
vars_files:
- secrets.yml
roles:
- role: common
tags:
- common
- role: reverse_proxy
tags:
- reverse_proxy

View File

@@ -2,3 +2,78 @@ docker:
url: "https://download.docker.com/linux"
apt_release_channel: "stable"
dirs: "/opt/docker"
caddy:
admin_email: me+acme@tudattr.dev
domain: "seyshiro.de"
services:
- name: syncthing
vm:
- docker-host00
port: 8384
- name: status
vm:
- docker-host00
port: 3001
- name: plex
vm:
- docker-host00
port: 32400
- name: jellyfin
vm:
- docker-host02
port: 8096
- name: hass
vm:
- docker-host02
port: 8123
- name: ddns
vm:
- docker-host00
port: 8123
- name: sonarr
vm:
- docker-host00
port: 8989
- name: radarr
vm:
- docker-host00
port: 7878
- name: lidarr
vm:
- docker-host00
port: 8686
- name: prowlarr
vm:
- docker-host00
port: 9696
- name: qbit
vm:
- docker-host00
port: 9696
- name: tl
vm:
- docker-host00
port: 9696
- name: paperless
vm:
- docker-host00
port: 8000
- name: pdf
vm:
- docker-host00
port: 8080
- name: git
vm:
- docker-host02
port: 3000
- name: changedetection
vm:
- docker-host00
port: 5000
- name: calibre
vm:
- docker-host00
port: 5000

View File

@@ -8,19 +8,3 @@ ansible_become_pass: "{{ vault.docker.host00.sudo }}"
host:
hostname: "docker-host00"
ip: "{{ ansible_host }}"
enable_nginx: true
enable_syncthing: true
enable_kuma: true
enable_plex: true
enable_arr: true
enable_prometheus: false
enable_grafana: false
enable_ddns_updater: true
enable_homeassistant: false
enable_stirling: true
enable_jellyfin: false
enable_paperless: true
enable_gitea: false
enable_changedetection: true
enable_calibre: false

View File

@@ -8,3 +8,19 @@ ansible_become_pass: "{{ vault.docker.host01.sudo }}"
host:
hostname: "docker-host01"
ip: "{{ ansible_host }}"
enable_nginx: true
enable_syncthing: true
enable_kuma: true
enable_plex: true
enable_arr: true
enable_prometheus: false
enable_grafana: false
enable_ddns_updater: true
enable_homeassistant: false
enable_stirling: true
enable_jellyfin: false
enable_paperless: true
enable_gitea: false
enable_changedetection: true
enable_calibre: false

View File

@@ -8,19 +8,3 @@ ansible_become_pass: "{{ vault.docker.host02.sudo }}"
host:
hostname: "docker-host02"
ip: "{{ ansible_host }}"
enable_nginx: true
enable_syncthing: false
enable_kuma: false
enable_plex: false
enable_arr: false
enable_prometheus: false
enable_grafana: false
enable_ddns_updater: false
enable_homeassistant: true
enable_stirling: false
enable_jellyfin: true
enable_paperless: false
enable_gitea: true
enable_changedetection: false
enable_calibre: false

10
host_vars/docker-lb.yml Normal file
View File

@@ -0,0 +1,10 @@
---
ansible_user: "{{ user }}"
ansible_host: 192.168.20.37
ansible_port: 22
ansible_ssh_private_key_file: "{{ pk_path }}"
ansible_become_pass: "{{ vault.docker.lb.sudo }}"
host:
hostname: "docker-lb"
ip: "{{ ansible_host }}"

View File

@@ -66,12 +66,18 @@ ansible_ssh_common_args='-o ProxyCommand="ssh -p 22 -W %h:%p -q aya01"'
[docker]
docker-host00
docker-host01
docker-host02
docker-lb
[docker_host]
docker-host00
docker-host01
docker-host02
[docker_lb]
docker-lb
[proxmox]
aya01
lulu

View File

@@ -50,3 +50,7 @@ if ! shopt -oq posix; then
. /etc/bash_completion
fi
fi
if [ -f /etc/profile ]; then
. /etc/profile
fi

View File

@@ -1,5 +1,6 @@
services:
{% if enable_nginx %}
{% for service in services %}
{% if service.name == 'nginx' and inventory_hostname in service.vm %}
nginx:
container_name: "nginx"
image: "jc21/nginx-proxy-manager:latest"
@@ -16,7 +17,7 @@ services:
- "/var/run/docker.sock:/var/run/docker.sock"
{% endif %}
{% if enable_syncthing %}
{% if service.name == 'syncthing' and inventory_hostname in service.vm %}
syncthing:
image: syncthing/syncthing
container_name: syncthing
@@ -38,7 +39,7 @@ services:
hostname: syncthing
{% endif %}
{% if enable_kuma %}
{% if service.name == 'status' and inventory_hostname in service.vm %}
kuma:
container_name: kuma
image: louislam/uptime-kuma:1
@@ -57,7 +58,7 @@ services:
- "/opt/local/kuma/:/app/data"
{% endif %}
{% if enable_plex %}
{% if service.name == 'plex' and inventory_hostname in service.vm %}
plex:
image: lscr.io/linuxserver/plex:latest
container_name: plex
@@ -89,7 +90,7 @@ services:
- "/media/songs:/music:ro"
{% endif %}
{% if enable_arr %}
{% if service.name == 'sonarr' and inventory_hostname in service.vm %}
sonarr:
image: lscr.io/linuxserver/sonarr:latest
container_name: sonarr
@@ -106,7 +107,9 @@ services:
- /opt/local/sonarr/config:/config
- /media/series:/tv #optional
- /media/docker/data/arr_downloads/sonarr:/downloads #optional
{% endif %}
{% if service.name == 'radarr' and inventory_hostname in service.vm %}
radarr:
image: lscr.io/linuxserver/radarr:latest
container_name: radarr
@@ -123,7 +126,9 @@ services:
- /opt/local/radarr/config:/config
- /media/movies:/movies #optional
- /media/docker/data/arr_downloads/radarr:/downloads #optional
{% endif %}
{% if service.name == 'lidarr' and inventory_hostname in service.vm %}
lidarr:
image: lscr.io/linuxserver/lidarr:latest
container_name: lidarr
@@ -140,7 +145,9 @@ services:
- /opt/local/lidarr/config:/config
- /media/songs:/music #optional
- /media/docker/data/arr_downloads/lidarr:/downloads #optional
{% endif %}
{% if service.name == 'prowlarr' and inventory_hostname in service.vm %}
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
@@ -155,7 +162,9 @@ services:
- TZ=Europe/Berlin
volumes:
- /opt/local/prowlarr/config:/config
{% endif %}
{% if service.name == 'tl' and inventory_hostname in service.vm %}
gluetun:
image: qmcgaw/gluetun
container_name: gluetun
@@ -181,7 +190,9 @@ services:
- SERVER_COUNTRIES=Hungary
- OPENVPN_USER=MfCOtzTIEsmu1wY-q2lAZ3X1+pmp
- OPENVPN_PASSWORD=knCl1Zl5PHz4HMWVCGR77dYa
{% endif %}
{% if service.name == 'tl' and inventory_hostname in service.vm %}
torrentleech:
image: qbittorrentofficial/qbittorrent-nox
container_name: torrentleech
@@ -198,7 +209,9 @@ services:
volumes:
- /opt/docker/config/torrentleech/config:/config
- /media/docker/data/arr_downloads:/downloads
{% endif %}
{% if service.name == 'qbit' and inventory_hostname in service.vm %}
qbit:
image: qbittorrentofficial/qbittorrent-nox
container_name: qbit
@@ -217,7 +230,7 @@ services:
- /media/docker/data/arr_downloads:/downloads
{% endif %}
{% if enable_prometheus %}
{% if service.name == 'prometheus' and inventory_hostname in service.vm %}
prometheus:
image: prom/prometheus
container_name: prometheus
@@ -235,7 +248,7 @@ services:
- prometheus_data:/prometheus/
{% endif %}
{% if enable_grafana %}
{% if service.name == 'grafana' and inventory_hostname in service.vm %}
grafana:
image: grafana/grafana-oss
container_name: grafana
@@ -254,7 +267,7 @@ services:
- /opt/docker/config/grafana/config/:/etc/grafana/
{% endif %}
{% if enable_ddns_updater %}
{% if service.name == 'ddns' and inventory_hostname in service.vm %}
ddns-updater:
container_name: ddns-updater
image: "ghcr.io/qdm12/ddns-updater"
@@ -267,7 +280,7 @@ services:
- "/opt/docker/config/ddns-updater/data/:/updater/data/"
{% endif %}
{% if enable_homeassistant %}
{% if service.name == 'hass' and inventory_hostname in service.vm %}
homeassistant:
container_name: homeassistant
image: "ghcr.io/home-assistant/home-assistant:stable"
@@ -287,7 +300,7 @@ services:
- 5683:5683/udp
{% endif %}
{% if enable_stirling %}
{% if service.name == 'pdf' and inventory_hostname in service.vm %}
stirling:
container_name: stirling
image: frooodle/s-pdf:latest
@@ -298,7 +311,7 @@ services:
net: {}
{% endif %}
{% if enable_jellyfin %}
{% if service.name == 'jellyfin' and inventory_hostname in service.vm %}
jellyfin:
container_name: jellyfin
image: jellyfin/jellyfin
@@ -319,7 +332,7 @@ services:
- "8096:8096"
{% endif %}
{% if enable_paperless %}
{% if service.name == 'paperless' and inventory_hostname in service.vm %}
paperless-broker:
container_name: paperless-broker
image: docker.io/library/redis:7
@@ -378,7 +391,7 @@ services:
- "PAPERLESS_OCR_LANGUAGE=deu"
{% endif %}
{% if enable_gitea %}
{% if service.name == 'git' and inventory_hostname in service.vm %}
git:
container_name: git
image: gitea/gitea:1.20.5-rootless
@@ -400,7 +413,7 @@ services:
- USER_GID=1000
{% endif %}
{% if enable_changedetection %}
{% if service.name == 'changedetection' and inventory_hostname in service.vm %}
changedetection:
container_name: changedetection
image: dgtlmoon/changedetection.io
@@ -413,7 +426,7 @@ services:
- "/opt/docker/config/changedetection/data/:/datastore"
{% endif %}
{% if enable_calibre %}
{% if service.name == 'calibre' and inventory_hostname in service.vm %}
calibre:
container_name: calibre
image: lscr.io/linuxserver/calibre-web:latest
@@ -431,6 +444,7 @@ services:
- "/opt/local/calibre/:/config"
- "/media/docker/data/calibre/:/books"
{% endif %}
{% endfor %}
networks:
net:

View File

@@ -0,0 +1,6 @@
---
caddy_version: latest
caddy_config_path: /etc/caddy/Caddyfile
caddy_binary: ./caddy
go_version: 1.23.4

View File

@@ -0,0 +1,4 @@
---
- name: Restart Caddy
ansible.builtin.command: "{{ caddy_binary }} reload --config {{ caddy_config_path }}"
become: true

View File

@@ -0,0 +1,15 @@
---
- name: Ensure Caddy configuration directory exists
ansible.builtin.file:
path: /etc/caddy
state: directory
mode: "0755"
become: true
- name: Deploy Caddy configuration file
ansible.builtin.template:
src: Caddyfile.j2
dest: "{{ caddy_config_path }}"
mode: "0644"
become: true
notify: Restart Caddy

View File

@@ -0,0 +1,32 @@
---
- name: Download xCaddy GPG key
ansible.builtin.get_url:
url: "https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key"
dest: /etc/apt/keyrings/caddy-xcaddy.asc
mode: "0644"
become: true
- name: Add xCaddy repository to apt sources
ansible.builtin.apt_repository:
repo: "deb [signed-by=/etc/apt/keyrings/caddy-xcaddy.asc] https://dl.cloudsmith.io/public/caddy/xcaddy/deb/debian any-version main"
state: present
update_cache: true
become: true
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
become: true
- name: Install xCaddy
ansible.builtin.apt:
name: xcaddy
state: present
become: true
- name: Install Caddy
ansible.builtin.command: xcaddy build --with github.com/caddy-dns/netcup
environment:
PATH: "{{ ansible_env.PATH }}:/usr/local/go/bin"
register: xcaddy_build
failed_when: xcaddy_build.rc != 0

View File

@@ -0,0 +1,9 @@
---
- name: Install Prerequisites
ansible.builtin.include_tasks: prereq.yml
- name: Install Caddy
ansible.builtin.include_tasks: install.yml
- name: Configure Caddy
ansible.builtin.include_tasks: configure.yml
- name: Start Caddy
ansible.builtin.include_tasks: start.yml

View File

@@ -0,0 +1,44 @@
---
- name: Install prerequisites for Caddy
ansible.builtin.apt:
name:
- debian-keyring
- debian-archive-keyring
- apt-transport-https
- curl
state: present
update_cache: true
become: true
- name: Remove existing Go installation
ansible.builtin.file:
path: /usr/local/go
state: absent
become: true
- name: Download Go tarball
ansible.builtin.get_url:
url: "https://go.dev/dl/go{{ go_version }}.linux-amd64.tar.gz"
dest: "/tmp/go{{ go_version }}.linux-amd64.tar.gz"
mode: "0755"
- name: Extract Go tarball to /usr/local
ansible.builtin.unarchive:
src: /tmp/go1.23.4.linux-amd64.tar.gz
dest: /usr/local
remote_src: true
become: true
register: go_install
- name: Ensure Go binary path is added to /etc/profile
ansible.builtin.lineinfile:
path: /etc/profile
line: "PATH=$PATH:/usr/local/go/bin"
state: present
regexp: "^PATH=.*:/usr/local/go/bin$"
become: true
- name: Source /etc/profile to update PATH for the current session
ansible.builtin.shell: "source /etc/profile"
args:
executable: /bin/bash

View File

@@ -0,0 +1,4 @@
---
- name: Ensure Caddy service is running
ansible.builtin.command: "{{ caddy_binary }} start --config {{ caddy_config_path }}"
become: true

View File

@@ -0,0 +1,26 @@
{
email {{ caddy.admin_email | default('admin@example.com') }}
acme_ca {{ caddy.acme_ca | default('https://acme-v02.api.letsencrypt.org/directory') }}
}
{% for service in services %}
{{ service.name }}.{{ domain }} {
{% for vm in service.vm %}
reverse_proxy {{ hostvars[vm].ansible_host }}:{{ service.port }}
{% endfor %}
log {
output file /var/log/caddy/{{ service.name }}.log
format json
}
tls {
dns netcup {
customer_number {{ vault.netcup.customer_number }}
api_key {{ vault.netcup.api_key}}
api_password {{ vault.netcup.api_password }}
}
propagation_timeout 900s
propagation_delay 600s
resolvers 1.1.1.1
}
}
{% endfor %}

View File

@@ -31,3 +31,9 @@ vault:
sudo: ........
host02:
sudo: ........
lb:
sudo: ........
netcup:
customer_number: ........
api_key: ........
api_password: ........