10 KiB
Reverse Proxy Setup Guide
This guide helps you configure reverse proxies (Nginx, Traefik, Zoraxy, Authelia, Caddy, etc.) to work with Mailcow Alias Manager.
🔧 ENABLE_PROXY Configuration
The application supports two access modes controlled by the ENABLE_PROXY environment variable in docker-compose.yml:
Mode 1: Direct Access (ENABLE_PROXY=false) - DEFAULT
Use this when accessing the application directly via IP:port without a reverse proxy.
docker-compose.yml:
environment:
- ENABLE_PROXY=false # Default setting
Access: http://192.168.1.100:5172 (replace with your server IP)
Features:
- ✅ Works over HTTP (no HTTPS required)
- ✅ Standard cookie behavior (SameSite=Lax)
- ✅ No proxy configuration needed
- ✅ Simple login flow
- ✅ Perfect for internal/LAN access
When to use:
- Accessing from internal network only
- No reverse proxy in place
- Testing or development
- Simple single-server setup
Mode 2: Proxy Access (ENABLE_PROXY=true)
Use this when running behind a reverse proxy (Authelia, Zoraxy, Nginx, Traefik, Caddy).
docker-compose.yml:
environment:
- ENABLE_PROXY=true
Access: https://alias.yourdomain.com (through your reverse proxy)
Features:
- ✅ ProxyFix middleware handles X-Forwarded-* headers
- ✅ HTTPS redirect support
- ✅ Secure cookies (HTTPS only)
- ✅ Works with authentication proxies (Authelia)
- ✅ Multi-proxy chain support
When to use:
- Accessing from internet via domain name
- Behind Nginx, Traefik, Caddy, HAProxy
- Behind authentication proxy (Authelia, Authentik)
- SSL/TLS termination at proxy
- Production deployments with HTTPS
Special Feature - Authelia Auto-Login:
When ENABLE_PROXY=true and you're using Authelia, the app automatically logs you in using Authelia's authentication headers. No app password needed! Simply authenticate through Authelia, and you'll be logged into the Mailcow Alias Manager automatically.
Switching Between Modes
To switch from one mode to another:
-
Edit
docker-compose.yml# Change this line: - ENABLE_PROXY=false # or true -
Restart the container
docker compose down docker compose up -d -
Verify mode in logs
docker compose logs mailcow-alias-manager | grep "ACCESS MODE"You should see either:
ACCESS MODE: Direct IP:Port (ENABLE_PROXY=false)ACCESS MODE: Reverse Proxy (ENABLE_PROXY=true)
-
Clear browser cookies (IMPORTANT!)
- Press F12 → Application → Cookies
- Delete all cookies for your domain
- Close and reopen browser
-
Login again
Quick Reference Table
| Access Method | ENABLE_PROXY | Access URL | Cookie Mode |
|---|---|---|---|
| Direct IP:port | false (default) |
http://192.168.1.100:5172 |
HTTP, SameSite=Lax |
| Nginx/Traefik | true |
https://alias.example.com |
HTTPS, SameSite=None |
| Authelia + Zoraxy | true |
https://alias.example.com |
HTTPS, SameSite=None |
| Caddy | true |
https://alias.example.com |
HTTPS, SameSite=None |
Local dev (python3 app.py) |
N/A (not set) | http://localhost:5172 |
HTTP, SameSite=Lax |
✅ Built-in Proxy Support (When ENABLE_PROXY=true)
The application includes ProxyFix middleware that automatically handles:
- ✅ HTTPS detection via
X-Forwarded-Proto - ✅ Host header forwarding via
X-Forwarded-Host - ✅ Client IP forwarding via
X-Forwarded-For - ✅ Path prefix support via
X-Forwarded-Prefix
Works with 2 proxies in chain (e.g., Zoraxy → Authelia → App)
Common Proxy Configurations
Zoraxy (Your Current Setup)
Zoraxy automatically sets the required headers. Just configure:
- Upstream Target:
http://localhost:5172(or your Docker IP) - Enable WebSocket: Yes (optional, recommended)
- Enable Proxy Headers: Yes (should be default)
Example Zoraxy Config:
{
"name": "mailcow-alias-manager",
"upstream": "http://localhost:5172",
"domain": "aliases.yourdomain.com"
}
Authelia (Authentication Proxy)
If using Authelia in front of the app:
- Authelia forwards the user after login - this should work automatically
- Make sure Authelia passes these headers:
X-Forwarded-ProtoX-Forwarded-HostX-Forwarded-For
Common Issue: Authelia redirects → App login page
Solution: The app has its own authentication. You have two options:
- Option A: Disable app login (requires code modification)
- Option B: Use Authelia for network access, app login for API access
Nginx
server {
listen 443 ssl http2;
server_name aliases.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:5172;
# Required headers for ProxyFix
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
# Optional: WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Traefik
docker-compose.yml:
services:
mailcow-alias-manager:
image: gitlab.pm/rune/malias-web:latest
container_name: mailcow-alias-manager
volumes:
- ./data:/app/data
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.malias.rule=Host(`aliases.yourdomain.com`)"
- "traefik.http.routers.malias.entrypoints=websecure"
- "traefik.http.routers.malias.tls=true"
- "traefik.http.routers.malias.tls.certresolver=letsencrypt"
- "traefik.http.services.malias.loadbalancer.server.port=5172"
networks:
- traefik
networks:
traefik:
external: true
Traefik automatically sets X-Forwarded-* headers by default.
Caddy
aliases.yourdomain.com {
reverse_proxy localhost:5172
}
Caddy automatically handles all proxy headers - no configuration needed!
🔧 Troubleshooting
Issue: "NetworkError when attempting to fetch resource"
Causes:
- Mixed HTTP/HTTPS content
- CORS blocking requests
- Session cookie not being set
- Proxy not forwarding headers
Solutions:
1. Check Proxy Headers
Your proxy MUST forward these headers:
X-Forwarded-Proto: https
X-Forwarded-Host: aliases.yourdomain.com
X-Forwarded-For: <client-ip>
2. Check Browser Console
Open browser DevTools (F12) → Console tab → Look for errors:
- CORS errors: Proxy misconfiguration
- Mixed content: HTTP resources on HTTPS page
- 401 Unauthorized: Session/cookie issue
3. Test Direct Access
# Test without proxy
curl http://localhost:5172/
# Should return HTML (login page)
If this works but proxy doesn't, it's a proxy configuration issue.
4. Check Session Cookies
In browser DevTools → Application tab → Cookies:
- Domain: Should match your proxy domain
- Path:
/ - HttpOnly: Should be
true - Secure: Depends on your setup
Issue: Login works but redirects to HTTP instead of HTTPS
Solution: Already fixed in latest version via PREFERRED_URL_SCHEME='https' in app config.
If still happening:
- Verify proxy sends
X-Forwarded-Proto: https - Check
docker compose logs -f mailcow-alias-manager - Rebuild image:
docker compose up -d --build
Issue: "Invalid password" but password is correct
This is NOT a proxy issue - this is an authentication issue:
# Reset password
docker exec -it mailcow-alias-manager python3 reset_password.py "newpass"
Issue: 502 Bad Gateway
Causes:
- App not running
- Wrong upstream port
- Container network issue
Check:
# Is container running?
docker ps | grep mailcow-alias-manager
# Check logs
docker compose logs -f mailcow-alias-manager
# Test internal connectivity
docker exec mailcow-alias-manager curl http://localhost:5172
🔒 Security Best Practices
1. HTTPS Only
Always use HTTPS in production. HTTP is only for local testing.
2. Restrict Access
Use firewall or proxy rules to restrict access:
# Nginx: Restrict to internal network only
allow 192.168.1.0/24;
deny all;
3. Use Authelia/Authentik
Add SSO layer for additional security:
- Users authenticate via Authelia
- Then app login provides API access
- Two-factor authentication recommended
4. Keep Session Cookies Secure
The app sets:
HttpOnly=True- Prevents JavaScript accessSameSite=Lax- CSRF protection
For HTTPS-only deployments, you can enforce secure cookies:
# In app.py, change:
SESSION_COOKIE_SECURE=True # Only send cookie over HTTPS
📊 Testing Your Setup
1. Basic Connectivity
curl -v https://aliases.yourdomain.com/
# Should return 200 OK with HTML
2. Login Test
curl -v -X POST https://aliases.yourdomain.com/login \
-H "Content-Type: application/json" \
-d '{"password":"yourpassword"}' \
-c cookies.txt
# Check response - should be JSON with status: success
3. Session Test
curl -v https://aliases.yourdomain.com/ \
-b cookies.txt
# Should return main page HTML (not login redirect)
🆘 Still Having Issues?
Enable Debug Logging
docker-compose.yml:
environment:
- FLASK_DEBUG=True # Enable debug mode
Restart:
docker compose down
docker compose up -d
docker compose logs -f
Check Application Logs
# View logs
docker compose logs -f mailcow-alias-manager
# Check for errors
docker compose logs mailcow-alias-manager | grep -i error
Test Without Proxy
Temporarily bypass proxy to isolate the issue:
# Direct access test
curl http://localhost:5172/
If this works, the issue is with proxy configuration, not the app.
✅ Summary
The app is already configured for reverse proxies!
Key points:
- ✅ ProxyFix middleware is enabled
- ✅ Handles X-Forwarded-* headers automatically
- ✅ HTTPS redirect support built-in
- ✅ Session cookies work behind proxies
- ✅ No code changes needed
Just make sure your proxy forwards the standard headers and you're good to go! 🚀