# Calendar setup The calendar stack runs on `pinix`: - Radicale provides CalDAV on the pinix Tailnet address, port `5002`. - Nginx serves a small read-only FullCalendar frontend on the pinix Tailnet address, port `5001`. - LLDAP authenticates users who edit calendars through CalDAV. - Each authenticated LLDAP user owns a private calendar namespace below their username and can create calendars there. - All authenticated LLDAP users can edit `calendar/public`, but cannot delete or overwrite the shared collection itself. Anonymous access remains read-only. ## Access **Changed 29.07.2026:** `cal.0ff.space` and Radicale used to share the same hostname, resolving differently depending on network (frontend externally, Radicale directly inside the Tailnet) because two separate Traefik routers matched it. That ambiguity was the likely cause of changes not showing up consistently (Vikunja `#125`). Now: - `cal.0ff.space` is always the read-only frontend, on both networks. - Radicale moved to its own internal-only hostname: ```text https://calendar.0ff.space ``` Only resolvable inside the Tailnet (AdGuardHome rewrite in `hosts/blunix/localServices/adguard.nix`); there is no public route to Radicale directly. Point CalDAV clients at `calendar.0ff.space` while on the Tailnet. On the public Traefik entrypoint, `cal.0ff.space` serves the read-only calendar frontend. Its only data endpoint is: ```text https://cal.0ff.space/calendar.ics ``` Nginx maps that exact path to Radicale's anonymously readable `/calendar/public/` collection. Other public paths are never proxied to Radicale, and the proxy removes credentials and cookies. **Changed 30.07.2026:** the frontend's source moved out of this flake into its own Forgejo repo, `lukas/calendar-web`. `nginx`'s root for `cal.${domain}` now points at `/var/www/calendar-web/dist` on pinix, kept current by the `gitpull-calendar-web` webhook hook (`hosts/pinix/localServices/webhook.nix`): push to the repo's `dev` branch, the hook `git pull`s, runs `npm ci && npm run build` (esbuild bundles FullCalendar + ical.js), done -- no `nixos-rebuild` needed for frontend-only changes. This flake still owns the nginx vhost, firewall ports, and the CSP/proxy config around it. ## Network boundaries Radicale and the frontend listen only on the pinix Tailnet address. The NixOS firewall permits ports `5001` and `5002` only on `tailscale0`. Public traffic passes through Traefik on `blunix`. ## Verification After deployment: 1. Check that Radicale and Nginx are active. 2. Confirm that ports `5001` and `5002` listen only on the pinix Tailnet IP. 3. Verify that `/calendar.ics` is anonymously readable through the frontend. 4. Verify an authenticated LLDAP CalDAV login. 5. Create and delete a temporary event in `calendar/public` with two different authenticated accounts. 6. Create a personal calendar and verify that another account cannot read it.