Traefik
Purpose
Traefik is the central HTTPS reverse proxy for the Bytek homelab.
Traefik receives HTTPS requests, selects the correct application according to the requested hostname, and forwards the request to the appropriate private backend.
Traefik provides:
Service Information
192.168.2.182
HTTPS entry point
TCP 443
Public dashboard hostname
proxy.bytek.ca
Deployment directory
/opt/traefik
Container DNS
192.168.2.65
Certificate authority
Let’s Encrypt
ACME challenge type
DNS-01
DNS automation
WHC cPanel API
Normal dashboard authentication
Authentik ForwardAuth
Secondary dashboard authentication
Basic Auth while retained
Backup coverage
Proxmox scheduled backup
Proxmox VM ID
Confirm current VM ID
Dashboard:
Architecture Role
Traefik is the common application-routing layer for both external and internal clients.
External Request Path
38.29.213.101.
The VPS receives HTTPS traffic.
The VPS forwards the traffic through WireGuard.
The home WireGuard gateway sends the request to Traefik at 192.168.2.182.
Traefik examines the requested hostname.
Traefik forwards the request to the matching private backend.
Internal Request Path
192.168.2.182.
The client connects directly to Traefik.
Traefik forwards the request to the matching private backend.
The same application hostname is used internally and externally.
Application Routing Reference
portal.bytek.ca
192.168.2.162:9000
Authentik native authentication
cloud.bytek.ca
192.168.2.100:11000
Nextcloud native OIDC
projects.bytek.ca
192.168.2.121:3456
Vikunja native OIDC
docs.bytek.ca
BookStack private IP on TCP 6875
BookStack native OIDC
status.bytek.ca
Uptime Kuma or Authentik embedded outpost
Authentik Proxy Provider
proxy.bytek.ca
Traefik internal dashboard service
Authentik ForwardAuth
The BookStack private address must be confirmed and added to this page.
Configuration Locations
/opt/traefik/compose.yml
Static Traefik configuration
/opt/traefik/traefik.yml
Environment variables
/opt/traefik/.env
Dynamic configuration
/opt/traefik/dynamic/
Certificate state
/opt/traefik/data/acme.json
Traefik log
/opt/traefik/logs/traefik.log
Access log
Confirm current path
Additional persistent data
/opt/traefik/data/
The exact certificate and log paths should be confirmed against the current Compose file before relying on them during recovery.
Dynamic Configuration
Each application normally has its own dynamic configuration file.
Known files include:
authentik.yml
Authentik router and service
authentik-forwardauth.yml
Shared Authentik middleware and outpost service
bookstack.yml
BookStack router and service
dashboard.yml
Traefik dashboard router
nextcloud.yml
Nextcloud router and service
uptime-kuma.yml
Uptime Kuma router and service
vikunja.yml
Vikunja router and service
Separating services into individual files makes configuration changes easier to review and reverse.
Before editing a working file:
Static Configuration
The static Traefik configuration defines platform-level settings such as:
Static configuration changes normally require a Traefik container restart or recreation.
Dynamic routing changes are usually detected automatically by the file provider when file watching is enabled.
Docker DNS
The Traefik container explicitly uses Pi-hole at 192.168.2.65.
This configuration was added after Docker’s embedded resolver failed to resolve the Let’s Encrypt ACME API following a power interruption.
The observed error reported that the Docker resolver at 127.0.0.11 was misbehaving.
Explicit Pi-hole DNS allows Traefik to resolve:
Verify the configured Docker DNS using:
sudo docker inspect --format='DNS={{json .HostConfig.Dns}}' traefik
Expected result:
192.168.2.65 appears in the DNS list.
The container’s internal resolver file may still show Docker’s embedded resolver at 127.0.0.11.
That is normal when Docker forwards requests to the explicitly configured upstream DNS server.
Container Management
Move to the deployment directory before running Compose commands:
cd /opt/traefik
Check the stack:
sudo docker compose ps
View recent logs:
sudo docker compose logs --tail 100 traefik
Follow logs live:
sudo docker compose logs -f traefik
Validate the Compose file:
sudo docker compose config --quiet
Apply normal Compose changes:
sudo docker compose up -d
Recreate Traefik after changing container-level settings such as DNS:
sudo docker compose up -d --force-recreate traefik
Restart Traefik after a static configuration change:
sudo docker compose restart traefik
A normal restart does not apply changes to Docker-level settings such as container DNS, network mode, volume mounts, or environment variables. Those changes require container recreation.
Naming and Routing Standard
Every Traefik application should have:
websecure entry point.
TLS enabled.
The correct certificate resolver.
A private backend destination.
Host-header forwarding where required.
Authentication middleware only when appropriate.
A route should not contain Authentik ForwardAuth if the application already uses native OIDC and requires direct API or client access.
Applications That Must Not Use ForwardAuth
Do not attach Authentik ForwardAuth to:
Nextcloud
Nextcloud mobile clients, desktop clients, WebDAV, CalDAV, CardDAV, and application authentication must reach Nextcloud directly.
Nextcloud uses native OIDC.
Vikunja
Vikunja uses native Authentik OIDC.
BookStack
BookStack uses native Authentik OIDC.
Authentik
Authentik must never depend on its own ForwardAuth middleware.
Proxmox VE
Proxmox uses native OIDC and remains outside Traefik.
Plex
Plex clients use Plex authentication and Plex-specific APIs.
Applications That Use Authentik Proxy Integration
Traefik Dashboard
The Traefik dashboard uses single-application ForwardAuth.
The dashboard request is validated by the Authentik embedded outpost before access is granted.
Uptime Kuma
Uptime Kuma uses an Authentik Proxy Provider because Uptime Kuma does not provide the same native OIDC integration as the other applications.
Selected status-page and monitoring endpoints may bypass authentication when public access is intentionally required.
Traefik Dashboard Authentication
The dashboard is available at:
Access is restricted by:
bytek-admin.
Authentik policy Allow bytek.ca users.
Policy engine mode ALL.
During the initial ForwardAuth validation, Traefik Basic Auth remains enabled as a second authentication layer.
The expected initial flow is:
proxy.bytek.ca.
Traefik invokes Authentik ForwardAuth.
Authentik validates the user and MFA.
Authentik checks the application bindings.
Traefik receives the authenticated request.
Traefik presents the existing Basic Auth challenge.
The administrator enters the Traefik Basic Auth credentials.
The dashboard opens.
Basic Auth may be removed only after ForwardAuth and recovery procedures are fully tested.
Authentik ForwardAuth Middleware
The ForwardAuth middleware sends authentication requests to the Authentik embedded outpost.
The outpost backend is hosted by Authentik at 192.168.2.162 on TCP port 9000.
The middleware should trust the forwarded request headers and return Authentik identity headers to the protected application.
Typical identity headers include:
Do not log full authentication headers in a location accessible to untrusted users.
Authentik Outpost Callback Route
The path under /outpost.goauthentik.io/ must remain reachable without the ForwardAuth middleware.
If the callback path is protected by the same middleware, an authentication loop can occur.
The callback router should:
proxy.bytek.ca.
Match the /outpost.goauthentik.io/ path prefix.
Use the Authentik outpost service.
Have a higher routing priority than the dashboard router.
Use HTTPS.
Avoid the dashboard ForwardAuth middleware.
Test the outpost with:
curl -k -I https://proxy.bytek.ca/outpost.goauthentik.io/ping
Expected result:
A normal browser link is not useful for this endpoint because an HTTP 204 response intentionally contains no page content.
Certificate Management
Traefik obtains HTTPS certificates from Let’s Encrypt.
The current design uses:
letsencrypt.
Each public router should reference the correct certificate resolver.
A router without the certificate resolver may use the Traefik default certificate instead of requesting the intended hostname certificate.
ACME DNS-01 Flow
Certificate issuance follows this sequence:
acme.json.
Traefik serves the certificate for the matching hostname.
Traefik must have working DNS before this process can succeed.
Certificate Storage
Certificate state is stored in:
/opt/traefik/data/acme.json
The file must:
Deleting acme.json can remove all stored certificates and account state.
That may trigger unnecessary reissuance and certificate-rate-limit risk.
Certificate Validation
Inspect a certificate served by Traefik using:
openssl s_client -connect 127.0.0.1:443 -servername projects.bytek.ca </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName
Verify:
Repeat with the relevant hostname when validating another service.
Certificate Troubleshooting
Certificate Missing From the Dashboard
Check:
ACME DNS Failure
A previously observed error reported:
127.0.0.11.
Docker DNS server misbehaving.
The correction was to configure the Traefik container to use Pi-hole explicitly and recreate the container.
Wrong Certificate Served
Possible causes include:
Application Onboarding
When adding a new public application:
38.29.213.101.
Add the Pi-hole local DNS record pointing to 192.168.2.182.
Create a dynamic Traefik configuration file.
Add the hostname router.
Add the private backend service.
Enable TLS with the correct resolver.
Validate YAML formatting.
Confirm Traefik loaded the router.
Confirm certificate issuance.
Test from the Traefik VM.
Test from the home LAN.
Test from an external network.
Add Uptime Kuma monitors.
Update BookStack documentation.
Backend Validation
Before troubleshooting an application through Traefik, test the direct backend from the Traefik VM.
Examples:
Nextcloud
nc -zv -w 5 192.168.2.100 11000
Vikunja
curl -i http://192.168.2.121:3456/health
Authentik
curl -I http://192.168.2.162:9000/-/health/ready/
BookStack
Use the confirmed BookStack IP on TCP port 6875.
A direct backend failure must be resolved before changing the Traefik router.
Local Router Validation
Traefik can be tested locally without relying on public DNS.
Example for Vikunja:
curl -k --resolve projects.bytek.ca:443:127.0.0.1 https://projects.bytek.ca/health
This forces the requested hostname to the local Traefik listener.
A successful response confirms:
Logging
Review the main Traefik log using:
sudo tail -n 100 /opt/traefik/logs/traefik.log
Filter common issues using:
sudo grep -iE 'error|acme|certificate|middleware|service|router|dns' /opt/traefik/logs/traefik.log | tail -n 100
Look for:
If access logging is enabled, use it to distinguish:
Do not copy session cookies, bearer tokens, or authorization headers into BookStack.
YAML Validation
YAML indentation must use spaces, not tabs.
Check dynamic configuration files using:
sudo grep -RnP '\t' /opt/traefik/dynamic/
Expected result:
Review a specific file using:
sudo cat /opt/traefik/dynamic/<filename>.yml
Common YAML problems include:
IP Address Changes
If an application IP changes:
/opt/traefik for the old address.
Update Proxmox firewall rules.
Update Authentik internal hosts if applicable.
Update Uptime Kuma monitors.
Test the direct backend.
Test the local Traefik route.
Test the public route.
Update BookStack documentation.
A stale backend address causes gateway errors even when the application itself is healthy.
Firewall Requirements
The Traefik VM must accept:
Application VM firewalls must permit Traefik to reach their backend ports.
Known requirements include:
192.168.2.182
TCP 11000
Vikunja
192.168.2.182
TCP 3456
Authentik
192.168.2.182
TCP 9000
BookStack
192.168.2.182
TCP 6875
Uptime Kuma direct route, if retained
192.168.2.182
TCP 3001
Do not allow public clients to connect directly to these backend ports.
Monitoring
Recommended Uptime Kuma monitors include:
192.168.2.182
Traefik HTTPS
TCP 443
Authentik route
portal.bytek.ca readiness endpoint
Nextcloud route
Nextcloud status endpoint
Vikunja route
Vikunja health endpoint
BookStack route
BookStack login endpoint
Certificate expiry
Each important public hostname
Public VPS to Traefik path
External application monitor
Monitoring should distinguish between:
Power-Failure Recovery
After a power interruption:
192.168.2.182.
Confirm Docker is active.
Confirm the Traefik container is running.
Confirm the container uses Pi-hole DNS.
Review Traefik logs for DNS errors.
Confirm routers loaded.
Confirm certificates are present.
Test Authentik locally.
Test an application locally.
Test a public application externally.
Restart or recreate Traefik only if required.
If Traefik started before Pi-hole and DNS remains broken, recreate the Traefik container after Pi-hole is healthy.
Backup
The Traefik VM is included in the Proxmox scheduled backup job.
Protect the following paths:
/opt/traefik/compose.yml
/opt/traefik/traefik.yml
/opt/traefik/.env
/opt/traefik/dynamic/
/opt/traefik/data/acme.json
Relevant logs.
Any authentication files.
Any custom certificate files.
Any dashboard Basic Auth configuration.
Secrets must remain in a password manager or encrypted backup.
BookStack should document the secret location, not the secret itself.
Recovery Procedure
If Traefik configuration is broken:
If the VM must be restored:
/opt/traefik.
Verify acme.json.
Verify environment and dynamic configuration.
Shut down the failed production VM.
Assign the expected network identity.
Start the restored VM.
Confirm 192.168.2.182.
Confirm Docker and Traefik.
Test all routers.
Reconnect public traffic only after validation.
Security Checklist
bytek-admin.
The dashboard callback path bypasses ForwardAuth.
Authentik is not protected by its own ForwardAuth.
Nextcloud uses native OIDC.
Vikunja uses native OIDC.
BookStack uses native OIDC.
Certificate API credentials are protected.
acme.json has restrictive permissions.
Container DNS points to Pi-hole.
The Docker socket is mounted read-only where supported.
The Docker API is not publicly exposed.
SSH uses keys.
Dynamic configuration is backed up.
Basic Auth recovery credentials are stored securely.
Proxmox backup includes the Traefik VM.
Validation Checklist
192.168.2.182.
Docker is active.
Traefik container is running.
TCP 443 is listening.
Pi-hole DNS works inside the container.
Dynamic YAML contains no tabs.
Authentik router works.
Nextcloud router works.
Vikunja router works.
BookStack router works.
Uptime Kuma router works.
Dashboard authentication works.
Outpost ping returns HTTP 204.
Certificates match every public hostname.
Certificate renewal works.
Public ingress works through the VPS and WireGuard.
Internal split-DNS access works directly.
acme.json is included in backup.
A known-good dynamic configuration backup exists.
Document Control
192.168.2.182
Public dashboard: proxy.bytek.ca
Primary entry point: TCP 443
Deployment directory: /opt/traefik
Certificate authority: Let’s Encrypt
ACME challenge: DNS-01 through WHC cPanel API
Container DNS: 192.168.2.65
Dashboard authentication: Authentik ForwardAuth
Secondary authentication: Basic Auth while retained
Proxmox VM ID: Confirm current VM ID
Last verified: YYYY-MM-DD
Last certificate-renewal test: YYYY-MM-DD
Last ForwardAuth test: YYYY-MM-DD
Last restore test: YYYY-MM-DD
Known limitation: Public applications depend on one Traefik VM and one certificate store