diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index 3d4621a..a7d8ecc 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -174,7 +174,7 @@ jobs: - name: Pull latest Docker images run: | cd "${{ secrets.DOCKER_DIR }}" - sudo docker compose pull + sudo docker compose pull --quiet - name: Apply Docker Compose changes run: | diff --git a/docker/caddy/Caddyfile b/docker/caddy/Caddyfile index 132b1ff..409a5a8 100644 --- a/docker/caddy/Caddyfile +++ b/docker/caddy/Caddyfile @@ -2,101 +2,117 @@ # https://caddyserver.com/docs/caddyfile { - # Global options + # Global options - # Monitoring - admin :2019 - metrics { - per_host - } + # Monitoring + admin :2019 + metrics { + per_host + } +} + +(logging) { + log { + output file /data/logs/{args[0]}.log { + roll_size 10mb + roll_keep 5 + roll_local_time + } + format console + level INFO + } } # Global Imports (all) { - handle_errors { - respond "{err.status_code} {err.status_text}" + # Error handling for Caddy-generated errors + handle_errors { + root * /opt/caddy-error-pages + rewrite * /error.html + templates + file_server } - # handle_errors { - # rewrite * /404.html - # file_server { - # status 404 - # } - # } } # Default options for internal facing sites (home) { - import all - tls internal + import all + tls internal } grafana.home { - import home - reverse_proxy http://{$IP_GRAFANA}:3000 + import home + import logging grafana.home + reverse_proxy http://{$IP_GRAFANA}:3000 } uptime.home { - import home - reverse_proxy http://{$IP_UPTIME_KUMA}:3001 + import home + import logging uptime.home + reverse_proxy http://{$IP_UPTIME_KUMA}:3001 } # Default options for external facing sites (external) { - import all + import all - tls { + tls { dns cloudflare {env.CLOUDFLARE_API_TOKEN} } - header { - Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" - X-Xss-Protection "1; mode=block" - X-Content-Type-Options "nosniff" - X-Frame-Options "DENY" - Content-Security-Policy "upgrade-insecure-requests" - Referrer-Policy "strict-origin-when-cross-origin" - Cache-Control "public, max-age=15, must-revalidate" - Permissions-Policy "accelerometer=(), ambient-light-sensor=(), autoplay=(self), camera=(), encrypted-media=(), fullscreen=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(*), speaker-selection=(), usb=(), xr-spatial-tracking=()" - [defer] - } - file_server + header { + Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" + X-Xss-Protection "1; mode=block" + X-Content-Type-Options "nosniff" + X-Frame-Options "DENY" + Content-Security-Policy "upgrade-insecure-requests" + Referrer-Policy "strict-origin-when-cross-origin" + Cache-Control "public, max-age=15, must-revalidate" + Permissions-Policy "accelerometer=(), ambient-light-sensor=(), autoplay=(self), camera=(), encrypted-media=(), fullscreen=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(*), speaker-selection=(), usb=(), xr-spatial-tracking=()" + [defer] + } + file_server } (geeksbsmrt) { - import external + import external } geeksbsmrt.com { - import geeksbsmrt - + import geeksbsmrt + import logging geeksbsmrt.com root * /srv/geeksbsmrt.com } analytics.geeksbsmrt.com { import geeksbsmrt - + import logging analytics.geeksbsmrt.com reverse_proxy http://{$IP_UMAMI_APP}:3000 } *.geeksbsmrt.com { - import geeksbsmrt + import geeksbsmrt + import logging wildcard.geeksbsmrt.com } (smrtgeekdevs) { - import external + import external } smrtgeekdevs.com { - #root * /var/www/smrtgeekdevs + import smrtgeekdevs # Inherit `external` config here + import logging smrtgeekdevs.com + #root * /var/www/smrtgeekdevs } pihole.smrtgeekdevs.com { - import smrtgeekdevs - - redir / /admin{uri} - reverse_proxy pihole + import smrtgeekdevs + import logging pihole.smrtgeekdevs.com + redir / /admin{uri} 308 + reverse_proxy http://pihole } *.smrtgeekdevs.com { - import smrtgeekdevs + import smrtgeekdevs + import logging wildcard.smrtgeekdevs.com } diff --git a/docker/caddy/error-pages/error.html b/docker/caddy/error-pages/error.html new file mode 100644 index 0000000..a6193b9 --- /dev/null +++ b/docker/caddy/error-pages/error.html @@ -0,0 +1,62 @@ + + + + + + Error {{placeholder "http.error.status_code"}} - {{placeholder "http.error.status_text"}} + + + + +
+

Error {{placeholder "http.error.status_code"}} - {{placeholder "http.error.status_text"}}

+

+ {{if ge (atoi (placeholder "http.error.status_code")) 500}} + We’re experiencing some internal trouble. Please try again later. + {{else if ge (atoi (placeholder "http.error.status_code")) 400}} + The page you're looking for doesn't exist or your request was invalid. + {{else}} + An unexpected issue occurred. + {{end}} +

+ {{ with placeholder "http.error.message" }} +

Details: {{.}}

+ {{ end }} +

Return to Homepage

+
+ + + diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 0009b19..a61b22f 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -64,11 +64,17 @@ services: hostname: caddy image: ghcr.io/caddybuilds/caddy-cloudflare:latest restart: unless-stopped + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "5" networks: macvlan: ipv4_address: ${IP_CADDY} volumes: - ./caddy/Caddyfile:/etc/caddy/Caddyfile + - ./caddy/error-pages:/opt/caddy-error-pages:ro - /srv:/srv - caddy_data:/data - caddy_config:/config