BasicAuth Protection for Observability Services¶
This document describes the HTTP Basic Authentication setup for protecting Prometheus, Loki, and Grafana Alloy services.
Overview¶
BasicAuth middleware is configured in Traefik to protect observability services that don't have native authentication: - Prometheus (http://prometheus.localhost) - Loki (http://loki.localhost) - Grafana Alloy (http://alloy.localhost)
Credentials¶
Default credentials (DEVELOPMENT ONLY): - Username: admin - Password: admin
⚠️ IMPORTANT: These are development credentials. CHANGE THEM IN PRODUCTION!
How It Works¶
- User accesses a protected service (e.g., http://prometheus.localhost)
- Traefik
observability-authmiddleware intercepts the request - Browser shows HTTP Basic Authentication popup
- User enters credentials
- Traefik validates credentials against
.htpasswdfile - If valid, request is forwarded to the service
Configuration Files¶
1. Password File¶
Location: docker/traefik/dynamic/.htpasswd
Contains MD5-hashed passwords in Apache htpasswd format:
2. Traefik Middleware¶
Location: docker/traefik/dynamic/middleware.yml
Defines the observability-auth BasicAuth middleware:
3. Service Configuration¶
Location: docker/docker-compose.yml
Services apply the middleware via Traefik labels:
- "traefik.http.routers.prometheus.middlewares=observability-auth@file,secure-headers@file"
- "traefik.http.routers.loki.middlewares=observability-auth@file,secure-headers@file"
- "traefik.http.routers.alloy.middlewares=observability-auth@file,secure-headers@file"
Protected Services¶
| Service | URL | BasicAuth | Notes |
|---|---|---|---|
| Prometheus | http://prometheus.localhost | ✅ Required | Metrics & monitoring |
| Loki | http://loki.localhost | ✅ Required | Log aggregation (API only, no UI) |
| Grafana Alloy | http://alloy.localhost | ✅ Required | Observability collector |
| Grafana | http://grafana.localhost | ❌ Not protected | Has its own authentication |
| FastAPI | http://api.localhost | ❌ Not protected | Has Keycloak authentication |
Testing¶
Command Line Tests¶
Test without credentials (should return 401 Unauthorized):
Test with credentials (should return 200/302 OK):
curl -I -u admin:admin http://prometheus.localhost/
curl -I -u admin:admin http://loki.localhost/
curl -I -u admin:admin http://alloy.localhost/
Browser Test¶
- Navigate to http://prometheus.localhost
- Browser shows authentication popup
- Enter username:
admin, password:admin - Prometheus UI loads successfully
Changing Passwords¶
Method 1: Generate New Password Hash (Recommended)¶
# Generate new password hash
docker run --rm httpd:2.4-alpine htpasswd -nbm admin newpassword > docker/traefik/dynamic/.htpasswd
# Restart Traefik to reload configuration
docker-compose -f docker/docker-compose.yml restart traefik
Method 2: Add Multiple Users¶
# Add first user
docker run --rm httpd:2.4-alpine htpasswd -nbm admin adminpass > docker/traefik/dynamic/.htpasswd
# Add more users (append with >>)
docker run --rm httpd:2.4-alpine htpasswd -nbm developer devpass >> docker/traefik/dynamic/.htpasswd
docker run --rm httpd:2.4-alpine htpasswd -nbm readonly readonlypass >> docker/traefik/dynamic/.htpasswd
# Restart Traefik
docker-compose -f docker/docker-compose.yml restart traefik
Method 3: Use BCrypt (More Secure)¶
# Generate BCrypt hash (more secure than MD5)
docker run --rm httpd:2.4-alpine htpasswd -nbB admin strongpassword > docker/traefik/dynamic/.htpasswd
# Restart Traefik
docker-compose -f docker/docker-compose.yml restart traefik
Production Recommendations¶
Security Best Practices¶
-
Change Default Credentials Immediately
-
Use Strong Passwords
- Minimum 16 characters
- Mix of uppercase, lowercase, numbers, symbols
-
Use a password manager
-
Use BCrypt Instead of MD5
- BCrypt is more secure than MD5
-
Use
-Bflag instead of-mwhen generating passwords -
Restrict Access by IP (Optional) Add IP whitelist middleware for additional security:
-
Enable HTTPS
- BasicAuth sends credentials in Base64 encoding (not encrypted)
- Always use HTTPS in production
-
Configure TLS in Traefik for proper encryption
-
Rotate Passwords Regularly
- Change passwords every 90 days
-
Remove old/unused accounts
-
Consider Upgrading to OAuth2
- For better security, consider OAuth2 Proxy with Keycloak (see issue #124)
- BasicAuth is a simple solution but not ideal for production SSO
Environment Variables for Secrets¶
Instead of hardcoding passwords, consider using Docker secrets or environment variables:
# docker-compose.yml
services:
traefik:
secrets:
- htpasswd
secrets:
htpasswd:
file: ./secrets/.htpasswd
Troubleshooting¶
Issue: Still Getting 401 with Correct Credentials¶
Solution 1: Verify password hash format
# Check .htpasswd file
cat docker/traefik/dynamic/.htpasswd
# Regenerate if corrupted
docker run --rm httpd:2.4-alpine htpasswd -nbm admin admin > docker/traefik/dynamic/.htpasswd
docker-compose -f docker/docker-compose.yml restart traefik
Solution 2: Check file is mounted correctly
# Verify file exists in container
docker exec hw-traefik ls -la /etc/traefik/dynamic/.htpasswd
docker exec hw-traefik cat /etc/traefik/dynamic/.htpasswd
Issue: 404 Not Found¶
Solution: Ensure .htpasswd is in the correct location
# File must be in docker/traefik/dynamic/.htpasswd
# NOT in docker/traefik/.htpasswd
mv docker/traefik/.htpasswd docker/traefik/dynamic/.htpasswd
docker-compose -f docker/docker-compose.yml restart traefik
Issue: No Authentication Popup in Browser¶
Solution: Clear browser cache and cookies
# Or test with curl
curl -v http://prometheus.localhost/
# Should show: Www-Authenticate: Basic realm="traefik"
Issue: Grafana Also Requires BasicAuth¶
Solution: Verify Grafana router does NOT have observability-auth middleware
# Check docker-compose.yml
grep "grafana.middlewares" docker/docker-compose.yml
# Should NOT contain "observability-auth@file"
Monitoring¶
Check Who's Accessing Services¶
Traefik logs show BasicAuth attempts:
Failed Login Attempts¶
Monitor for suspicious activity:
# Watch for repeated 401s (possible brute force)
docker logs -f hw-traefik 2>&1 | grep "401 Unauthorized"
References¶
- Traefik BasicAuth Middleware Documentation
- Apache htpasswd Documentation
- Issue #123: Add BasicAuth protection for observability services
- Issue #124: Future OAuth2 Proxy investigation
Migration Path¶
This BasicAuth setup is a simple, immediate solution. For production environments requiring SSO and better security:
- Short-term (current): BasicAuth with strong passwords
- Medium-term: Add IP whitelisting + HTTPS
- Long-term: Migrate to OAuth2 Proxy with Keycloak (issue #124)
BasicAuth provides adequate protection while keeping the solution simple and maintainable.