Skip to content
Back to skills

Traefik

CSecurity

Use when setting up Traefik as a local reverse proxy — real domains on 127.0.0.1, trusted HTTPS via mkcert, automatic service discovery, and multi-project routing.

  • 10 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added June 5, 2026
ai-agentsrustgophpbashnodedockerawsapifrontenddevops

Works with

  • api

Security analysis

C67/100
  • mediumUses curl or wget to download content
  • criticalAccesses sensitive system or user directories

Pro shows the line behind each finding and how to fix it

Scanned June 5, 2026

npx -y skills add event4u-app/agent-config --skill traefik --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Traefik?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Traefik
[![Security: C — Skills Directory](https://www.skillsdirectory.com/api/skills/event4u-app-traefik/badge)](https://www.skillsdirectory.com/skills/event4u-app-traefik)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
model_tier: medium
name: traefik
description: "Use when setting up Traefik as a local reverse proxy — real domains on 127.0.0.1, trusted HTTPS via mkcert, automatic service discovery, and multi-project routing."
domain: devops
workspaces:
  - engineering
packs:
  - engineering-base
---

# Traefik Skill

## When to use

Use this skill when:
- Setting up local development with real domain names and trusted HTTPS
- Configuring SSL certificates (self-signed, mkcert, ACME via Namecheap/AWS)
- Routing multiple Docker projects through a single reverse proxy
- Embedding external services (Grafana, etc.) that require HTTPS/same-origin

## Procedure: Set up Traefik

### 0. Understand current setup

Before changing any routing configuration:

1. **Check existing proxy setup** — is Traefik already running? Check `docker ps | grep traefik`.
2. **Review docker-compose** — read `docker-compose.yml` for existing labels and network config.
3. **Check DNS/hosts** — review `/etc/hosts` or dnsmasq for existing domain mappings.

### Architecture

Traefik acts as a **local reverse proxy** that:
1. Resolves real domains (e.g., `local.example.dev`, `app.test`) to `127.0.0.1`
2. Terminates HTTPS with trusted certificates
3. Auto-discovers Docker services via labels (no manual config per service)
4. Routes requests to the correct container based on hostname

```
Browser → https://app.example.com
    → DNS resolves to 127.0.0.1 (via /etc/hosts or dnsmasq)
    → Traefik (port 443) picks up the request
    → Routes to app container (based on Docker labels)
```

## DNS Resolution (domains → 127.0.0.1)

**Option A: `/etc/hosts` (simple, per-domain)**

```
127.0.0.1  local.example.dev
127.0.0.1  grafana.local.example.dev
```

**Option B: dnsmasq (wildcard, all subdomains — preferred)**

```bash
brew install dnsmasq
echo 'address=/.local.example.dev/127.0.0.1' >> /opt/homebrew/etc/dnsmasq.conf
sudo brew services restart dnsmasq
sudo mkdir -p /etc/resolver
echo 'nameserver 127.0.0.1' | sudo tee /etc/resolver/local.example.dev
```

## Certificate Strategies

Choose based on project needs:

| Strategy | Tool | Trust | Use when |
|---|---|---|---|
| **Self-signed** | openssl | Manual trust via keychain | Quick local dev, no external deps |
| **mkcert** | mkcert | Auto-trusted local CA | Local dev, easiest setup |
| **ACME (Namecheap)** | lego + DNS-01 | Real CA (Let's Encrypt) | Real domain, Namecheap DNS |
| **ACME (AWS Route53)** | lego + DNS-01 | Real CA (Let's Encrypt) | Real domain, AWS DNS |

### Self-signed (openssl)

```bash
mkdir -p traefik/certificates
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout traefik/certificates/_.${CERT_DOMAIN}.key \
  -out traefik/certificates/_.${CERT_DOMAIN}.crt \
  -subj "/CN=*.${CERT_DOMAIN}" \
  -addext "subjectAltName=DNS:*.${CERT_DOMAIN},DNS:${CERT_DOMAIN}"

# Trust on macOS
sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain traefik/certificates/tls.crt
```

### mkcert (simplest for local dev)

```bash
brew install mkcert && mkcert -install
mkcert "local.example.dev" "*.local.example.dev"
```

### ACME via Lego container (real certs)

```yaml
# docker-compose.yml
lego:
  image: goacme/lego:latest
  profiles: [manual]   # Only run on demand
  volumes:
    - ./traefik/certificates:/etc/lego
```

```bash
# Namecheap DNS-01
docker compose run --rm \
  -e NAMECHEAP_API_USER -e NAMECHEAP_API_KEY \
  lego --dns namecheap \
  --domains "*.${CERT_DOMAIN}" --email "admin@${CERT_DOMAIN}" \
  --path /etc/lego run

# AWS Route53 DNS-01
docker compose run --rm \
  -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_REGION \
  lego --dns route53 \
  --domains "*.${CERT_DOMAIN}" --email "admin@${CERT_DOMAIN}" \
  --path /etc/lego run
```

### Taskfile integration for cert management

```yaml
# certificates/generate.yml (included in main Taskfile)
tasks:
  selfsigned:
    desc: Generate self-signed certificate for ${CERT_DOMAIN}
    cmds: [...]

  namecheap:
    desc: Generate ACME certificate via Namecheap DNS-01
    cmds: [...]

  aws:
    desc: Generate ACME certificate via AWS Route53 DNS-01
    cmds: [...]
```

```yaml
# Main Taskfile
trust:
  desc: Add cert to macOS keychain
  cmds:
    - sudo security add-trusted-cert -d -r trustRoot \
        -k /Library/Keychains/System.keychain traefik/certificates/tls.crt

untrust:
  desc: Remove cert from macOS keychain
  cmds:
    - sudo security delete-certificate -c "*.${CERT_DOMAIN}" \
        /Library/Keychains/System.keychain

cert:setup:
  desc: Generate and trust self-signed certificate
  deps: [generate:selfsigned, trust]
```

## Traefik Container

```yaml
traefik:
  image: traefik:v3.2   # or v2.11 for older setups
  command:
    - --providers.docker=true
    - --providers.docker.exposedbydefault=false
    - --providers.file.directory=/etc/traefik/dynamic
    - --providers.file.watch=true
    - --entrypoints.web.address=:80
    - --entrypoints.websecure.address=:443
  ports:
    - "${TRAEFIK_HTTP_PORT:-80}:80"
    - "${TRAEFIK_HTTPS_PORT:-443}:443"
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
    - ./traefik/dynamic:/etc/traefik/dynamic:ro
    - ./traefik/certificates:/certs:ro
```

### TLS dynamic config

```yaml
# traefik/dynamic/tls.yml
tls:
  certificates:
    - certFile: /certs/tls.crt
      keyFile: /certs/tls.key
```

## Service Labels

### Basic pattern (HTTP → HTTPS redirect + TLS)

```yaml
my-service:
  labels:
    - "traefik.enable=true"
    # HTTP router (redirect to HTTPS)
    - "traefik.http.routers.myapp.rule=Host(`${CERT_HOST}`)"
    - "traefik.http.routers.myapp.entrypoints=web"
    - "traefik.http.routers.myapp.middlewares=myapp-https-redirect"
    - "traefik.http.middlewares.myapp-https-redirect.redirectscheme.scheme=https"
    - "traefik.http.middlewares.myapp-https-redirect.redirectscheme.port=${TRAEFIK_HTTPS_PORT}"
    # HTTPS router
    - "traefik.http.routers.myapp-secure.rule=Host(`${CERT_HOST}`)"
    - "traefik.http.routers.myapp-secure.entrypoints=websecure"
    - "traefik.http.routers.myapp-secure.tls=true"
    - "traefik.http.services.myapp.loadbalancer.server.port=80"
```

### Subdomain routing

```yaml
grafana:
  labels:
    - "traefik.enable=true"
    - "traefik.http.routers.grafana-secure.rule=Host(`grafana.${CERT_HOST}`)"
    - "traefik.http.routers.grafana-secure.entrypoints=websecure"
    - "traefik.http.routers.grafana-secure.tls=true"
    - "traefik.http.services.grafana.loadbalancer.server.port=3000"
```

### Path-based routing

```yaml
horizon:
  labels:
    - "traefik.http.routers.horizon-secure.rule=Host(`${CERT_HOST}`) && PathPrefix(`/horizon`)"
```

## Integration Patterns

### With NGINX

Traefik sits **in front of** NGINX — does NOT replace it:

```
Traefik (443) → NGINX (80 internal) → PHP-FPM
```

NGINX keeps: PHP-FPM routing, Xdebug header detection, static files.
Traefik adds: real domains, HTTPS, multi-service routing.

### Standalone

Traefik routes directly to the app container:

```
Traefik (443) → App container (80 internal)
```

### Multi-project (shared Traefik)

One Traefik instance routes to multiple projects via shared network:

```yaml
networks:
  traefik-public:
    external: true   # docker network create traefik-public
```

```
traefik
├── local.example.dev      → api-service
├── grafana.local.example.dev → grafana
├── other.local.example.dev → other-service
└── app.test               → frontend
```

## Middleware Examples

```yaml
# Rate limiting
- "traefik.http.middlewares.rate-limit.ratelimit.average=100"

# Basic auth
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$..."

# CORS
- "traefik.http.middlewares.cors.headers.accesscontrolalloworiginlist=*"
```

## Related

- **Skill:** `docker` — Docker setup, compose services, container architecture
- **Skill:** `devcontainer` — DevContainer and Codespaces setup
- **Skill:** `grafana` — Grafana dashboards (benefits from HTTPS for embedding)
- **Skill:** `dashboard-design` — Grafana embedding requires same-origin/HTTPS
- **Rule:** `docker-commands.md` — all commands run inside Docker containers

### Validate

- Verify Traefik dashboard is accessible and shows all expected services.
- Confirm HTTPS works with trusted certificates (no browser warnings).
- Check that each service has correct Docker labels for routing.
- Test DNS resolution: `curl -I https://your-domain.localhost` should return 200.

## Output format

1. Traefik configuration with routing rules and TLS setup
2. Docker labels or dynamic config for service discovery

## Gotcha

- Traefik requires Docker labels on each service — a missing label means the service isn't routed.
- mkcert certificates must be trusted by the OS — `mkcert -install` is a one-time setup step.
- The model forgets to add the Traefik network to docker-compose services — no network = no routing.

## Do NOT

- Do NOT expose internal services without authentication.
- Do NOT use self-signed certificates when mkcert is available.

## Auto-trigger keywords

- Traefik
- reverse proxy
- local domains
- HTTPS
- mkcert

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.