From bf1634f44f4ec3fa5c3ba2da776ef45dd81aa0c4 Mon Sep 17 00:00:00 2001 From: Job79 Date: Wed, 1 May 2024 20:57:26 +0200 Subject: [PATCH] init --- .gitignore | 2 ++ README.md | 18 ++++++++++ caddy-logs.volume | 0 caddy.network | 2 ++ caddy.volume | 2 ++ config/Caddyfile | 26 +++++++++++++++ configure.sh | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 134 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 caddy-logs.volume create mode 100644 caddy.network create mode 100644 caddy.volume create mode 100644 config/Caddyfile create mode 100755 configure.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed744e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +caddy.container +config/*.caddy diff --git a/README.md b/README.md new file mode 100644 index 0000000..c0d1c98 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Caddy +Webserver and reverse proxy for installed services. +Detects installed services and proxies them based on given configuration. + +## Configuration +Other services can use caddy as proxy. +To do so, they need to provide caddy configuration files and give caddy access to their network. +The `./configure.sh` script will find the configuration files/networks and add them to the caddy configuration. + +To configure a service to be proxied by caddy: +1. Add `*.caddy` file(s) to your service with caddy configuration +2. Add the `caddy=true` label to your network(s) that should be accessible by caddy +3. Call `./configure.sh` on the server to refresh the caddy configuration + +## Installation +1. Clone repository to service directory +2. Configure the service by calling `./configure.sh` +3. Start the service by calling `systemctl --user start caddy-* caddy` diff --git a/caddy-logs.volume b/caddy-logs.volume new file mode 100644 index 0000000..e69de29 diff --git a/caddy.network b/caddy.network new file mode 100644 index 0000000..70cde7b --- /dev/null +++ b/caddy.network @@ -0,0 +1,2 @@ +[Network] +IPv6=true diff --git a/caddy.volume b/caddy.volume new file mode 100644 index 0000000..9057088 --- /dev/null +++ b/caddy.volume @@ -0,0 +1,2 @@ +[Volume] +Label="backup=true" diff --git a/config/Caddyfile b/config/Caddyfile new file mode 100644 index 0000000..a5ddb3f --- /dev/null +++ b/config/Caddyfile @@ -0,0 +1,26 @@ +{ + log { + exclude http.log.access + } + + log access { + format json + output file /data/logs/access.log { + roll_size 1gb + roll_keep 5 + roll_keep_for 720h + } + } +} + +(default-headers) { + header { + ?Cache-Control max-age=3600 + Strict-Transport-Security max-age=63072000; preload + X-Content-Type-Options nosniff + X-Frame-Options SAMEORIGIN + -Server + } +} + +import *.caddy diff --git a/configure.sh b/configure.sh new file mode 100755 index 0000000..6085572 --- /dev/null +++ b/configure.sh @@ -0,0 +1,84 @@ +#!/bin/sh +# ====================================== +# configure.sh v1.0; job79 +# Generate caddy configuration based on +# the installed services. +# ====================================== + +set -eu +log() { printf '\e[%sm%s\e[0m %s\n' "${3:-36}" "${2:-○}" "$1"; } +ask() { printf '\e[33m?\e[0m %s ' "$1"; read a; [ "${a,,}" = 'y' ]; } + +# gen_quadlet_file generates the caddy container quadlet file +gen_quadlet_file() { + log 'start generating quadlet file' + cat > "$CADDY_QUADLET_FILE" <<- EOF + # ============================================================================ + # This file is generated by caddy/configure.sh, do not edit this file manually + # ============================================================================ + [Container] + Image=docker.io/caddy:2.7 + AutoUpdate=registry + + # storage + Volume=caddy.volume:/data/caddy + Volume=caddy-logs.volume:/data/logs + Volume=%h/services/caddy/config:/etc/caddy:Z,ro + + # networking + Network=caddy.network + PublishPort=0.0.0.0:80:80 + PublishPort=0.0.0.0:443:443 + PublishPort=0.0.0.0:443:443/udp + EOF + + log 'search for networks with caddy=true label' + podman network ls -f label=caddy=true --format "{{.Name}}" | while read -r network; do + log "found $network" '↖' 35 + echo "Network=$network" >> "$CADDY_QUADLET_FILE" + done + + cat >> "$CADDY_QUADLET_FILE" <<- EOF + # security + ReadOnly=true + NoNewPrivileges=true + DropCapability=ALL + AddCapability=NET_BIND_SERVICE + + [Service] + Restart=always + RestartSec=5 + + [Install] + WantedBy=multi-user.target default.target + EOF + log 'finished generating quadlet file' '✓' 32 +} + +# gen_config_dir generates the caddy config directory +gen_config_dir() { + log 'generate caddy config directory with *.caddy files from services' + find "$CADDY_CONFIG_DIR" -name '*.caddy' -exec rm {} \; + find "$SERVICES_DIR" -name '*.caddy' -not -path "$CADDY_CONFIG_DIR/*" | while read -r in; do + log "found $in" '↖' 35 + cp "$in" "$CADDY_CONFIG_DIR" + done + log 'finished generating caddy config directory' '✓' 32 +} + +## MAIN ## +SERVICES_DIR="$(dirname "$(dirname "$(realpath "$0")")")" +CADDY_QUADLET_FILE="$SERVICES_DIR/caddy/caddy.container" +CADDY_CONFIG_DIR="$SERVICES_DIR/caddy/config" + +gen_quadlet_file +gen_config_dir + +ask "apply config changes by reloading config (y/N)?" && \ + podman exec -w /etc/caddy systemd-caddy caddy reload && \ + log 'successfully applied config changes' '✓' 32 + +ask "restart caddy? required to join new networks (y/N)?" && \ + systemctl --user daemon-reload && \ + systemctl --user restart caddy && \ + log 'successfully restarted caddy' '✓' 32