Running behind a proxy
monoki serves plain HTTP and does not terminate TLS. That is deliberate: almost every self-hosted deployment already has something in front — Caddy, Traefik, nginx, or a tunnel — and having two things fight over certificates is a reliable way to end up with neither.
Bind it to loopback and let the proxy own the public address:
monoki run --addr 127.0.0.1:8080
What the proxy must send
| Header | Why |
|---|---|
X-Forwarded-Proto: https |
Tells monoki the connection is secure, so the session cookie is issued with Secure. Without it the cookie is set without that flag. |
X-Forwarded-For |
Used for login rate limiting and audit records. Without it, every request appears to come from the proxy, so one attacker's failures lock out everybody. |
Both of these are trusted as given. monoki is meant to be reached only through your proxy; if the port is also exposed directly, a client can forge either header. Bind to loopback.
Caddy
apps.example.com {
reverse_proxy 127.0.0.1:8080
}
Caddy sets both headers and handles certificates on its own. Nothing else needed.
Traefik (labels)
labels:
- traefik.enable=true
- traefik.http.routers.monoki.rule=Host(`apps.example.com`)
- traefik.http.routers.monoki.entrypoints=websecure
- traefik.http.routers.monoki.tls.certresolver=le
- traefik.http.services.monoki.loadbalancer.server.port=8080
nginx
server {
listen 443 ssl http2;
server_name apps.example.com;
# ... ssl_certificate directives ...
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Icons can be a couple of hundred kilobytes.
client_max_body_size 2m;
}
}
A note on sub-paths
monoki expects to own the root of whatever host it is on. Serving it under
https://example.com/monoki/ will not work — the SPA's routes and its API
paths are both absolute. Give it a subdomain.
Exposing it to the internet
You can, and the session auth is built for it — but read Security first. In particular: monoki has no second factor and no account lockout beyond per-address login rate limiting, so a publicly-reachable instance is only as strong as its passwords.
Putting it behind a VPN, a Tailscale/WireGuard network, or your proxy's own authentication is a meaningfully stronger position for very little effort.