Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion config/dynamic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tls:

http:
middlewares:
security-headers:
strict-headers:
headers:
customResponseHeaders:
X-Frame-Options: "DENY"
Expand All @@ -17,3 +17,12 @@ http:
X-XSS-Protection: "0"
Strict-Transport-Security: "max-age=31536000; includeSubDomains"
Content-Security-Policy: "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; object-src 'none'; base-uri 'self'"
relaxed-headers:
headers:
customResponseHeaders:
X-Frame-Options: "DENY"
X-Content-Type-Options: "nosniff"
Referrer-Policy: "strict-origin-when-cross-origin"
X-XSS-Protection: "0"
Strict-Transport-Security: "max-age=31536000; includeSubDomains"
Content-Security-Policy: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; object-src 'none'; base-uri 'self'"
8 changes: 4 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ services:
- "traefik.http.routers.dashboard.rule=Host(`traefik.docker.localhost`)"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.tls=true"
- "traefik.http.routers.dashboard.middlewares=security-headers@file"
- "traefik.http.routers.dashboard.middlewares=relaxed-headers@file"

redis:
image: redis:8.6.1-alpine
Expand Down Expand Up @@ -131,7 +131,7 @@ services:
- "traefik.enable=true"
- "traefik.http.routers.pma.rule=Host(`pma.docker.localhost`)"
- "traefik.http.routers.pma.tls=true"
- "traefik.http.routers.pma.middlewares=security-headers@file"
- "traefik.http.routers.pma.middlewares=strict-headers@file"

pgadmin:
image: dpage/pgadmin4:9.12.0
Expand Down Expand Up @@ -160,7 +160,7 @@ services:
- "traefik.enable=true"
- "traefik.http.routers.pgadmin.rule=Host(`pgadmin.docker.localhost`)"
- "traefik.http.routers.pgadmin.tls=true"
- "traefik.http.routers.pgadmin.middlewares=security-headers@file"
- "traefik.http.routers.pgadmin.middlewares=strict-headers@file"

mailpit:
image: axllent/mailpit:v1.29.1
Expand All @@ -183,7 +183,7 @@ services:
- "traefik.enable=true"
- "traefik.http.routers.mailpit.rule=Host(`mailpit.docker.localhost`)"
- "traefik.http.routers.mailpit.tls=true"
- "traefik.http.routers.mailpit.middlewares=security-headers@file"
- "traefik.http.routers.mailpit.middlewares=strict-headers@file"
- "traefik.http.services.mailpit.loadbalancer.server.port=8025"

volumes:
Expand Down
20 changes: 12 additions & 8 deletions docs/INTEGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5230,9 +5230,12 @@ pre-configured security headers middleware to protect against common web vulnera

#### Security Headers Middleware

The proxy includes a **security headers middleware** (`security-headers`) that automatically applies essential security
headers to HTTP responses. These headers protect against common attacks like clickjacking, MIME-type sniffing, and
protocol downgrade attacks.
The proxy includes two **security headers middlewares**:

- **`strict-headers`** — full CSP without `unsafe-inline`; use this for your own services
- **`relaxed-headers`** — relaxed CSP with `unsafe-inline` allowed; used internally by the Traefik dashboard which requires inline scripts and styles

Both apply the same security headers (HSTS, X-Frame-Options, etc.) and differ only in the `Content-Security-Policy` directive.

**Included Headers:**

Expand All @@ -5259,8 +5262,8 @@ services:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`app.docker.localhost`)"
- "traefik.http.routers.app.tls=true"
# Apply security headers middleware
- "traefik.http.routers.app.middlewares=security-headers@file"
# Apply strict security headers middleware
- "traefik.http.routers.app.middlewares=strict-headers@file"

networks:
traefik-proxy:
Expand All @@ -5270,9 +5273,10 @@ networks:
**Key Points:**

- The `@file` suffix tells Traefik to use middleware defined in the dynamic configuration file (`config/dynamic.yml`)
- Security headers are applied automatically to the Traefik dashboard
- The Traefik dashboard uses `relaxed-headers@file` (allows `unsafe-inline` required by its Vue.js frontend)
- Use `strict-headers@file` for your own services — it enforces a strict CSP without `unsafe-inline`
- You can chain multiple middlewares by separating them with commas:
`middlewares=security-headers@file,other-middleware`
`middlewares=strict-headers@file,other-middleware`
- The CSP includes `object-src 'none'` (prevents plugin embedding like Flash) and `base-uri 'self'` (prevents base URL hijacking attacks)

**Verification:**
Expand Down Expand Up @@ -5333,7 +5337,7 @@ networks:

3. **Combine security headers with other middleware:**
```yaml
- "traefik.http.routers.app.middlewares=security-headers@file,compress,ratelimit"
- "traefik.http.routers.app.middlewares=strict-headers@file,compress,ratelimit"
```

**For More Information:**
Expand Down