Caddy first implementation

This commit is contained in:
Eduardo Silva
2026-03-10 18:18:04 -03:00
parent 6a78391ce1
commit 29aeb51cf0
3 changed files with 255 additions and 1 deletions

View File

@@ -0,0 +1,8 @@
FROM caddy:2-alpine
COPY entrypoint.sh /usr/local/bin/caddy-entrypoint.sh
RUN chmod +x /usr/local/bin/caddy-entrypoint.sh
ENTRYPOINT ["/usr/local/bin/caddy-entrypoint.sh"]
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]

View File

@@ -0,0 +1,224 @@
#!/bin/sh
set -eu
MANUAL_CERT_DIR="${MANUAL_CERT_DIR:-/certificates}"
CADDYFILE_PATH="${CADDYFILE_PATH:-/etc/caddy/Caddyfile}"
trim_value() {
printf '%s' "$1" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
}
is_valid_hostname() {
host_value="$1"
if [ -z "$host_value" ]; then
return 1
fi
if is_ip_host "$host_value"; then
return 1
fi
if printf '%s' "$host_value" | grep -Eq '^[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)*$'; then
return 0
fi
return 1
}
is_ip_host() {
host_value="$1"
case "$host_value" in
\[*\]|*:*:*)
return 0
;;
*)
;;
esac
if printf '%s' "$host_value" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
return 0
fi
return 1
}
is_internal_tls_host() {
host_value="$1"
case "$host_value" in
localhost|*.localhost)
return 0
;;
esac
if is_ip_host "$host_value"; then
return 0
fi
return 1
}
normalize_host() {
raw_value="$(trim_value "$1")"
raw_value="${raw_value#http://}"
raw_value="${raw_value#https://}"
raw_value="${raw_value%%/*}"
case "$raw_value" in
\[*\]:*)
printf '%s' "${raw_value%:*}"
;;
*:*)
case "$raw_value" in
*:*:*)
printf '%s' "$raw_value"
;;
*)
printf '%s' "${raw_value%%:*}"
;;
esac
;;
*)
printf '%s' "$raw_value"
;;
esac
}
append_host() {
candidate_host="$(normalize_host "$1")"
if [ -z "$candidate_host" ]; then
return
fi
case "
$HOSTS
" in
*"
$candidate_host
"*)
return
;;
esac
if [ -z "$HOSTS" ]; then
HOSTS="$candidate_host"
return
fi
HOSTS="$HOSTS
$candidate_host"
}
append_dns_host() {
candidate_host="$(normalize_host "$1")"
if [ -z "$candidate_host" ]; then
return
fi
if is_internal_tls_host "$candidate_host"; then
return
fi
append_host "$candidate_host"
}
build_common_block() {
cat <<'EOF'
import wireguard_common
EOF
}
build_tls_block() {
domain_name="$1"
cert_file="${MANUAL_CERT_DIR}/${domain_name}/fullchain.pem"
key_file="${MANUAL_CERT_DIR}/${domain_name}/key.pem"
if [ -f "$cert_file" ] && [ -f "$key_file" ]; then
cat <<EOF
tls ${cert_file} ${key_file}
EOF
return
fi
if is_internal_tls_host "$domain_name"; then
cat <<'EOF'
tls internal
EOF
return
fi
cat <<'EOF'
tls {
issuer acme
issuer internal
}
EOF
}
HOSTS=""
PRIMARY_HOST="$(normalize_host "${SERVER_ADDRESS:-}")"
if ! is_valid_hostname "$PRIMARY_HOST"; then
echo "SERVER_ADDRESS must be a hostname, not an IP address. Received: ${SERVER_ADDRESS:-}"
exit 1
fi
append_host "$PRIMARY_HOST"
ORIGINAL_IFS="$IFS"
IFS=','
for configured_host in ${EXTRA_ALLOWED_HOSTS:-}; do
append_dns_host "$configured_host"
done
IFS="$ORIGINAL_IFS"
if [ -z "$HOSTS" ]; then
echo "No valid hostnames were provided for Caddy."
exit 1
fi
mkdir -p "$(dirname "$CADDYFILE_PATH")"
cat > "$CADDYFILE_PATH" <<'EOF'
(wireguard_common) {
encode gzip
@static path /static/*
handle @static {
root * /static
uri strip_prefix /static
file_server
header Cache-Control "public, max-age=3600"
}
handle {
reverse_proxy wireguard-webadmin:8000 {
header_up Host {host}
}
}
}
EOF
printf '%s\n' "$HOSTS" | while IFS= read -r current_host; do
if [ -z "$current_host" ]; then
continue
fi
{
printf '\n%s {\n' "$current_host"
build_common_block
build_tls_block "$current_host"
printf '}\n'
} >> "$CADDYFILE_PATH"
done
if command -v caddy >/dev/null 2>&1; then
caddy fmt --overwrite "$CADDYFILE_PATH" >/dev/null 2>&1
fi
exec "$@"

View File

@@ -25,7 +25,7 @@ services:
- rrd_data:/rrd_data/
ports:
# Do not directly expose the Django port to the internet, use some kind of reverse proxy with SSL.
- "8000:8000"
# - "8000:8000"
# Warning: Docker will have a hard time handling large amount of ports. Expose only the ports that you need.
# Ports for multiple WireGuard instances. (Probably, you just need one)
- "51820-51839:51820-51839/udp"
@@ -79,9 +79,31 @@ services:
volumes:
- dnsmasq_conf:/etc/dnsmasq/
wireguard-webadmin-caddy:
container_name: wireguard-webadmin-caddy
restart: unless-stopped
build:
context: ./containers/caddy
dockerfile: Dockerfile-caddy
environment:
- SERVER_ADDRESS=${SERVER_ADDRESS}
- EXTRA_ALLOWED_HOSTS=${EXTRA_ALLOWED_HOSTS}
- TZ=${TIMEZONE}
volumes:
- static_volume:/static
- https_cert:/certificates
- letsencrypt_data:/data
ports:
- "80:80"
- "443:443"
depends_on:
- wireguard-webadmin
volumes:
static_volume:
https_cert:
wireguard:
dnsmasq_conf:
app_secrets:
rrd_data:
letsencrypt_data: