--- name: Zulip on VM 103 description: Zulip chat server config, tus upload fix, Caddy/Authelia setup at crew.chrissader.com type: reference --- Zulip runs on VM 103 (192.168.86.122) port 8085, accessible at crew.chrissader.com. **Compose**: `/opt/docker/stacks/zulip/` (project name `zulip-docker` in `.env` to preserve volumes) **Caddy**: Uses `route` block with `@exempt path /api/* /json/* /user_uploads/*` matcher and `reverse_proxy @exempt` before `forward_auth`. The `route` directive is critical — without it, Caddy reorders directives and runs `forward_auth` first regardless of source order. The `handle` block approach also doesn't work. Authelia also has bypass rules for the same paths as belt-and-suspenders. **Tus upload fix**: Zulip's puppet overwrites `/etc/nginx/zulip-include/app` on container start. The tus location block needs `proxy_redirect http://crew.chrissader.com https://crew.chrissader.com;` added (inlined proxy config, no `include proxy`). Without this, tusd generates `http://` Location headers and browsers block the PATCH as mixed content. **How to apply:** After any `docker compose up` that recreates the zulip container, run `/opt/docker/stacks/zulip/post-start.sh` to re-apply the nginx fix. **LOADBALANCER_IPS**: Includes `172.26.0.0/16` (Docker bridge) so nginx trusts `X-Forwarded-Proto` from Caddy.