TLS / HTTPS
Put a reverse proxy in front of Drevnix to terminate TLS. Examples for nginx, Caddy, and Traefik.
Using an AI assistant? Give it this file.
/llms.md is a single Markdown file covering installation, configuration, quickstart, clients, upstreams, permissions, TLS, and production deployment. Copy it and paste it into your AI chat, or tell the AI to fetch https://drevnix.tech/llms.md.
TLS / HTTPS
Drevnix does not terminate TLS itself. Run a reverse proxy in front of it to handle certificates and HTTPS.
Only the proxy port (:8000) typically needs to be public-facing. The portal (:8001) and REST API (:8002) should be accessible via VPN or internal network only.
nginx
server {
listen 443 ssl;
server_name drevnix.company.com;
ssl_certificate /etc/ssl/certs/drevnix.crt;
ssl_certificate_key /etc/ssl/private/drevnix.key;
# Docker layer downloads can be very large — disable buffering
proxy_buffering off;
proxy_request_buffering off;
client_max_body_size 0;
location / {
proxy_pass http://127.0.0.1:8000;
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;
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name drevnix.company.com;
return 301 https://$host$request_uri;
}
The proxy_buffering off and client_max_body_size 0 settings are important. Docker image layers can be gigabytes in size and will time out or fail if buffered.
Caddy
drevnix.company.com {
reverse_proxy localhost:8000 {
header_up X-Forwarded-For {remote_host}
flush_interval -1
}
}
Caddy automatically obtains and renews TLS certificates from Let’s Encrypt. The flush_interval -1 setting disables response buffering, which is required for large layer downloads.
Traefik (Docker labels)
labels:
- "traefik.enable=true"
- "traefik.http.routers.drevnix.rule=Host(`drevnix.company.com`)"
- "traefik.http.routers.drevnix.entrypoints=websecure"
- "traefik.http.routers.drevnix.tls.certresolver=letsencrypt"
- "traefik.http.services.drevnix.loadbalancer.server.port=8000"
- "traefik.http.services.drevnix.loadbalancer.responseForwarding.flushInterval=1ms"
X-Forwarded-For and real client IPs
When Drevnix runs behind a reverse proxy, the TCP remote address it sees is the proxy’s IP, not the original client. This affects audit log client_ip entries and rate limiting buckets (five failed logins from “the proxy IP” is not useful).
TRUSTED_PROXIES controls how Drevnix resolves the real client IP. Getting this wrong means audit logs show proxy IPs instead of real clients, and rate limiting misfires. Set it correctly before going to production.
Which value should I use?
-
Is Drevnix directly reachable from the internet — no firewall, load balancer, or proxy in front of it? → Yes: leave
TRUSTED_PROXIESunset. Done. → No: continue. -
Do you need to restrict which specific proxy IPs are trusted? → No (most deployments): set
TRUSTED_PROXIES=*— correct for nginx, Traefik, Caddy, AWS ALB, GCP LB, Hetzner LB, Cloudflare, or any chain of proxies, as long as Drevnix is not directly internet-reachable. → Yes: setTRUSTED_PROXIESto a comma-separated list of your proxy CIDRs.
| Value | When to use |
|---|---|
| unset | App exposed directly to the internet, no proxy |
* | App behind any proxy/LB, not directly internet-reachable |
10.0.0.0/8,... | You need precise per-CIDR proxy trust |
Unset (default) — X-Forwarded-For is ignored. remote-addr is always used as the client IP. Safe for direct deployments — no configuration needed, spoofed headers have no effect.
Wildcard (*) — X-Forwarded-For is always trusted. The leftmost token is used as the client IP, falling back to remote-addr if the header is absent.
TRUSTED_PROXIES=*
Only use
*when Drevnix is not directly reachable from the internet. If it is, any client can forge their IP viaX-Forwarded-For. Enforce this at the network level: firewall or security group should only allow inbound traffic from your proxy.
CIDR list — X-Forwarded-For is trusted only when remote-addr falls within one of the specified ranges. Otherwise remote-addr is used directly. Accepts a comma-separated list of IPv4 or IPv6 CIDR ranges. A single host is /32 (IPv4) or /128 (IPv6).
TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12
Whitespace around entries is ignored. A malformed CIDR causes a startup error rather than silently failing mid-request.
Behavior matrix:
| Scenario | TRUSTED_PROXIES | TCP remote addr | X-Forwarded-For | IP used |
|---|---|---|---|---|
| Direct deployment | unset | 1.2.3.4 | 9.9.9.9 (spoofed) | 1.2.3.4 |
| Direct deployment | unset | 1.2.3.4 | absent | 1.2.3.4 |
| Behind proxy (wildcard) | * | 10.0.0.1 (proxy) | 1.2.3.4 (client) | 1.2.3.4 |
| Behind proxy (wildcard), no XFF | * | 10.0.0.1 | absent | 10.0.0.1 |
| Behind proxy (CIDR) | 10.0.0.0/8 | 10.0.0.1 (proxy) | 1.2.3.4 (client) | 1.2.3.4 |
| Behind proxy, multi-hop | 10.0.0.0/8 | 10.0.0.1 | 1.2.3.4, 10.0.0.2 | 1.2.3.4 |
| Behind proxy, no XFF header | 10.0.0.0/8 | 10.0.0.1 | absent | 10.0.0.1 |
| Untrusted remote | 10.0.0.0/8 | 5.5.5.5 | 9.9.9.9 (spoofed) | 5.5.5.5 |
TRUSTED_PROXIES applies to portal login, proxy auth, and REST API auth — all three use the same IP resolution, so one setting covers the entire application.
Exposing portal and API over HTTPS
If you need remote access to the portal or REST API, put them behind the same reverse proxy on a separate subdomain or path, and restrict access with IP allowlisting or mTLS at the proxy level.