Guide: Deploying Custom Error Pages in Traefik Using File Provider
My current setup uses the file provider for dynamic configuration (/etc/traefik/dynamic_config.yml) and an HTTP provider for some Traefik-specific config.
The solution involves:
- Adding a dedicated
error-pagesservice (using thetarampampam/error-pagesimage). - Defining the router, middleware, and service entirely in your dynamic file configuration (YAML format).
- Applying the errors middleware to your existing routers (e.g., the main app routers).
- For 404 Not Found on unknown hosts/paths (Traefik default errors), add a low-priority catch-all router that routes to the error-pages service (it will serve a nice 404 page while preserving the 404 status).
Step 1: Add the Error Pages Service to Your Compose File
Add this to your services section in the compose file (template variables like {{.Something}} are preserved):
error-pages:
image: ghcr.io/tarampampam/error-pages:3 # Pin a specific version; avoid :latest
container_name: error-pages
restart: unless-stopped
environment:
TEMPLATE_NAME: l7 # Choose your preferred template (e.g., l7, ghost, hacker-terminal, etc.)
# Optional: SHOW_DETAILS: 'true' # Shows more info on pages
healthcheck: # Optional but recommended
test: ["CMD", "curl", "-f", "http://localhost:8080/404.html"]
interval: "30s"
timeout: "10s"
retries: 3
depends_on:
traefik:
condition: service_started # Ensure Traefik can reach it
No labels needed on this service (or any other). Traefik will discover it via the HTTP provider or direct internal URL.
Step 2: Update Your Dynamic Configuration File
Your current dynamic file (./config/traefik/dynamic_config.yml mounted as /etc/traefik/dynamic_config.yml) already defines routers, services, and middlewares.
Add the following sections to it (YAML format):
http:
middlewares:
redirect-to-https:
redirectScheme:
scheme: https
# New: Errors middleware (applies to backend errors like 5xx, 502, etc.)
error-pages-middleware:
errors:
status:
- "400-599" # Catch all client and server errors; adjust as needed (e.g., "500-599")
service: error-pages-service
query: "/{status}.html" # The image serves pages like /404.html, /500.html, etc.
routers:
# Your existing routers (unchanged except adding the middleware chain)
main-app-router-redirect:
rule: "Host(`{{.DashboardDomain}}`)"
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
priority: 100 # Ensure high priority
next-router:
rule: "Host(`{{.DashboardDomain}}`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
middlewares:
- error-pages-middleware # Add this for custom pages on backend errors
tls:
certResolver: letsencrypt
priority: 100
api-router:
rule: "Host(`{{.DashboardDomain}}`) && PathPrefix(`/api/v1`)"
service: api-service
entryPoints:
- websecure
middlewares:
- error-pages-middleware # Add this
tls:
certResolver: letsencrypt
priority: 100
ws-router:
rule: "Host(`{{.DashboardDomain}}`)"
service: api-service
entryPoints:
- websecure
middlewares:
- error-pages-middleware # Add this if desired
tls:
certResolver: letsencrypt
priority: 100
# New: Catch-all router for unknown hosts/paths (Traefik 404/503 errors)
catch-all-errors:
rule: HostRegexp(`{host:.+}`) # Matches any host
service: error-pages-service
entryPoints:
- web
- websecure
middlewares:
- error-pages-middleware # Optional: enhances if any sub-error occurs
tls:
certResolver: letsencrypt # Enable TLS for websecure
priority: 1 # Very low priority – only matches if no other router does
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002"
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000"
# New: Service pointing to the error-pages container
error-pages-service:
loadBalancer:
servers:
- url: "http://error-pages:8080" # Internal Docker network URL (container name + port)
Step 3: Restart and Test
- Run
docker compose up -d(or your deployment command). - Traefik will reload the file config automatically (file provider watches changes).
- Test:
- Visit a non-existent path on your domain → Should show custom 404 from the template.
- Visit an unknown subdomain → Custom 404 (catch-all router).
- Trigger a backend error (e.g., stop pangolin temporarily) → Custom 502/503/etc. page.
- Direct access:
http://your-ip:80/404.html(via catch-all) to preview.
Why This Works Without Labels
- All routing/middleware is defined in the file provider YAML.
- The
error-pagescontainer is reachable internally via its container name (error-pages). - The catch-all router has low priority, so your main routers take precedence.
- For Traefik-native errors (no matching router), it falls to the catch-all → custom page with preserved status.
Tips
- Choose a different
TEMPLATE_NAMEfrom the image docs (e.g.,ghost,noise). - If you only want errors for backend issues (not 404), remove the catch-all router and limit
statusto500-599. - Monitor Traefik dashboard for config reloads.
If you are using middleware manage then this is the guide
It helps you add error pagers to individual resources
Guide: Adding Custom Error Pages to Pangolin Resources - Guides & Tutorials - HHF Technology Forums