backlog-md/backlog/tasks/task-011 - Host-level-Traef...

2.3 KiB

id title status assignee created_date labels dependencies priority
task-011 Host-level Traefik hardening and cron setup To Do
2026-03-15 08:00
dev-ops
enhancement
task-010
high

Description

Security hardening tasks that require host-level access on Netcup RS 8000. Cannot be done from the claude-dev container. Scripts are pre-built at /opt/apps/dev-ops/.

Acceptance Criteria

  • #1 Run Traefik hardening script: bash /opt/apps/dev-ops/traefik-hardening.sh
  • #2 Edit Traefik docker-compose: add cap_drop: [ALL], cap_add: [NET_BIND_SERVICE], security_opt: [no-new-privileges:true], read_only: true
  • #3 Restrict Traefik ports to localhost: 127.0.0.1:80:80 and 127.0.0.1:443:443
  • #4 Add resource limits to Traefik: memory: 512M, cpus: 2.0
  • #5 Add CSP frame-ancestors 'self' to security-headers.yml
  • #6 Remove insecureSkipVerify from pentagi transport config
  • #7 Add weekly Docker prune cron: 23 4 * * 0 /opt/apps/dev-ops/docker-weekly-prune.sh >> /var/log/docker-prune.log 2>&1
  • #8 Restart Traefik and verify: cd /root/traefik && docker compose up -d

Notes

Quick start

# 1. Run the pre-built script (creates TLS + rate limit configs)
bash /opt/apps/dev-ops/traefik-hardening.sh

# 2. Edit Traefik compose (location: /root/traefik/docker-compose.yml)
#    Add to traefik service:
#      cap_drop: [ALL]
#      cap_add: [NET_BIND_SERVICE]
#      security_opt: [no-new-privileges:true]
#      read_only: true
#      tmpfs: [/tmp]
#      deploy:
#        resources:
#          limits:
#            memory: 512M
#            cpus: '2.0'
#    Change ports to:
#      - '127.0.0.1:80:80'
#      - '127.0.0.1:443:443'

# 3. Add weekly prune cron
crontab -e
# Add: 23 4 * * 0 /opt/apps/dev-ops/docker-weekly-prune.sh >> /var/log/docker-prune.log 2>&1

# 4. Restart
cd /root/traefik && docker compose up -d

# 5. Verify
curl -I https://jeffemmett.com

Risk

  • Restricting ports to 127.0.0.1 means ONLY Cloudflare tunnel traffic reaches Traefik. If cloudflared goes down, all external access is lost until it recovers. This is the intended behavior (no direct IP access).
  • read_only on Traefik may need a tmpfs for /data if ACME cert storage is inside the container.