feat: create cameleer-traefik image with cert generation and config baked in
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
7
docker/cameleer-traefik/Dockerfile
Normal file
7
docker/cameleer-traefik/Dockerfile
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM traefik:v3
|
||||
RUN apk add --no-cache openssl
|
||||
COPY traefik.yml /etc/traefik/traefik.yml
|
||||
COPY traefik-dynamic.yml /etc/traefik/dynamic.yml
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
60
docker/cameleer-traefik/entrypoint.sh
Normal file
60
docker/cameleer-traefik/entrypoint.sh
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
CERTS_DIR="/certs"
|
||||
|
||||
# Skip if certs already exist (idempotent)
|
||||
if [ ! -f "$CERTS_DIR/cert.pem" ]; then
|
||||
mkdir -p "$CERTS_DIR"
|
||||
|
||||
if [ -n "$CERT_FILE" ] && [ -n "$KEY_FILE" ]; then
|
||||
# User-supplied certificate
|
||||
echo "[certs] Installing user-supplied certificate..."
|
||||
cp "$CERT_FILE" "$CERTS_DIR/cert.pem"
|
||||
cp "$KEY_FILE" "$CERTS_DIR/key.pem"
|
||||
if [ -n "$CA_FILE" ]; then
|
||||
cp "$CA_FILE" "$CERTS_DIR/ca.pem"
|
||||
fi
|
||||
# Validate key matches cert
|
||||
CERT_MOD=$(openssl x509 -noout -modulus -in "$CERTS_DIR/cert.pem" 2>/dev/null | md5sum)
|
||||
KEY_MOD=$(openssl rsa -noout -modulus -in "$CERTS_DIR/key.pem" 2>/dev/null | md5sum)
|
||||
if [ "$CERT_MOD" != "$KEY_MOD" ]; then
|
||||
echo "[certs] ERROR: Certificate and key do not match!"
|
||||
rm -f "$CERTS_DIR/cert.pem" "$CERTS_DIR/key.pem" "$CERTS_DIR/ca.pem"
|
||||
exit 1
|
||||
fi
|
||||
SELF_SIGNED=false
|
||||
echo "[certs] Installed user-supplied certificate."
|
||||
else
|
||||
# Generate self-signed certificate
|
||||
HOST="${PUBLIC_HOST:-localhost}"
|
||||
echo "[certs] Generating self-signed certificate for $HOST..."
|
||||
openssl req -x509 -newkey rsa:4096 \
|
||||
-keyout "$CERTS_DIR/key.pem" -out "$CERTS_DIR/cert.pem" \
|
||||
-days 365 -nodes \
|
||||
-subj "/CN=$HOST" \
|
||||
-addext "subjectAltName=DNS:$HOST,DNS:*.$HOST"
|
||||
SELF_SIGNED=true
|
||||
echo "[certs] Generated self-signed certificate for $HOST."
|
||||
fi
|
||||
|
||||
# Write metadata for SaaS app to seed DB
|
||||
SUBJECT=$(openssl x509 -noout -subject -in "$CERTS_DIR/cert.pem" 2>/dev/null | sed 's/subject=//')
|
||||
FINGERPRINT=$(openssl x509 -noout -fingerprint -sha256 -in "$CERTS_DIR/cert.pem" 2>/dev/null | sed 's/.*=//')
|
||||
NOT_BEFORE=$(openssl x509 -noout -startdate -in "$CERTS_DIR/cert.pem" 2>/dev/null | sed 's/notBefore=//')
|
||||
NOT_AFTER=$(openssl x509 -noout -enddate -in "$CERTS_DIR/cert.pem" 2>/dev/null | sed 's/notAfter=//')
|
||||
HAS_CA=false
|
||||
[ -f "$CERTS_DIR/ca.pem" ] && HAS_CA=true
|
||||
cat > "$CERTS_DIR/meta.json" <<METAEOF
|
||||
{"subject":"$SUBJECT","fingerprint":"$FINGERPRINT","selfSigned":$SELF_SIGNED,"hasCa":$HAS_CA,"notBefore":"$NOT_BEFORE","notAfter":"$NOT_AFTER"}
|
||||
METAEOF
|
||||
|
||||
mkdir -p "$CERTS_DIR/staged" "$CERTS_DIR/prev"
|
||||
chmod 775 "$CERTS_DIR" "$CERTS_DIR/staged" "$CERTS_DIR/prev"
|
||||
chmod 660 "$CERTS_DIR"/*.pem 2>/dev/null || true
|
||||
else
|
||||
echo "[certs] Certificates already exist, skipping generation."
|
||||
fi
|
||||
|
||||
# Start Traefik
|
||||
exec traefik "$@"
|
||||
24
docker/cameleer-traefik/traefik-dynamic.yml
Normal file
24
docker/cameleer-traefik/traefik-dynamic.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
http:
|
||||
routers:
|
||||
root-redirect:
|
||||
rule: "Path(`/`)"
|
||||
priority: 100
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls: {}
|
||||
middlewares:
|
||||
- root-to-platform
|
||||
service: saas@docker
|
||||
middlewares:
|
||||
root-to-platform:
|
||||
redirectRegex:
|
||||
regex: "^(https?://[^/]+)/?$"
|
||||
replacement: "${1}/platform/"
|
||||
permanent: false
|
||||
|
||||
tls:
|
||||
stores:
|
||||
default:
|
||||
defaultCertificate:
|
||||
certFile: /etc/traefik/certs/cert.pem
|
||||
keyFile: /etc/traefik/certs/key.pem
|
||||
23
docker/cameleer-traefik/traefik.yml
Normal file
23
docker/cameleer-traefik/traefik.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
api:
|
||||
dashboard: false
|
||||
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":80"
|
||||
http:
|
||||
redirections:
|
||||
entryPoint:
|
||||
to: websecure
|
||||
scheme: https
|
||||
websecure:
|
||||
address: ":443"
|
||||
admin-console:
|
||||
address: ":3002"
|
||||
|
||||
providers:
|
||||
docker:
|
||||
endpoint: "unix:///var/run/docker.sock"
|
||||
exposedByDefault: false
|
||||
network: cameleer
|
||||
file:
|
||||
filename: /etc/traefik/dynamic.yml
|
||||
Reference in New Issue
Block a user