Deletes 13 docs/intent/ files whose tasks are already shipped (verified against git log, not just their own "Status" headers) plus docs/log.md and docs/notiz-hardware-architektur.md, whose content is superseded or fully absorbed elsewhere. Two still-open intent docs (forgejo-umzug-blunix, ipv6-mango-connector-poc) get folded into docs/roadmap.md as visible open items instead of sitting unlinked in docs/intent/. Cross-checked every candidate against the rest of the repo first: agents/design/herdr-self-close-entwurf.md and docs/intent/sdlc-playbook-prozessergaenzungen.md are read at runtime by agents/tests/roles.sh (would have broken the test suite), and docs/hdm-klon-plan.md, docs/herdr-eskalation-review-entwurf.md, docs/graphify-dashboard-plan.md and docs/intent/kanban-board-admin-trigger.md are actively cited by live service code or explicitly declared to remain elsewhere — all six were kept out of the original consolidation list for that reason. Cleaned up dangling docs/log.md references left behind in README.md, operator-prompt.md, memory/INDEX.md, memory/project-context.md, docs/repos.md, dex.nix, radicale.nix and finance-agent/README.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYZodsX5a4ksWdrwKXSExX |
||
|---|---|---|
| .. | ||
| default.nix | ||
| H+9wX | ||
| radicale.nix | ||
| README.md | ||
| web.nix | ||
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.spaceis always the read-only frontend, on both networks. -
Radicale moved to its own internal-only hostname:
https://calendar.0ff.spaceOnly resolvable inside the Tailnet (AdGuardHome rewrite in
hosts/blunix/localServices/adguard.nix); there is no public route to Radicale directly. Point CalDAV clients atcalendar.0ff.spacewhile on the Tailnet.
On the public Traefik entrypoint, two hostnames serve the same read-only calendar frontend:
https://cal.0ff.space/calendar.ics
https://cal.lukasrosier.com/lukas.ics
cal.0ff.space only shows the shared calendar/public collection;
cal.lukasrosier.com only shows Lukas's existing personal calendar
collection. Nginx maps only the corresponding exact feed path to Radicale.
The other feed path returns an empty valid calendar because the shared
frontend bundle requests both paths. Other public paths are never proxied to
Radicale. Both feed proxies remove credentials and cookies, all feed
locations permit only GET and HEAD, and Radicale's rights keep anonymous
access read-only.
The HTML served on cal.lukasrosier.com gets a host-specific title and
subscription link through Nginx's sub_filter; both hosts still use the same
build from lukas/calendar-web.
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 pulls, 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.
Boot-time gotcha, fixed 31.07.2026: because Radicale binds directly to
the tailnet address, it can fail once at boot with "Cannot assign requested
address" if it starts before tailscaled-autoconnect.service has actually
assigned that address -- found after a real pinix reboot, where it stayed
down instead of recovering on its own. radicale.nix now depends on
tailscaled-autoconnect.service and disables systemd's restart-limit
(StartLimitIntervalSec = 0), the same fix already in place for
gotosocial.nix/webdav.nix.
Verification
After deployment:
- Check that Radicale and Nginx are active.
- Confirm that ports
5001and5002listen only on the pinix Tailnet IP. - Verify that
https://cal.0ff.space/calendar.icsis anonymously readable and rejects methods other thanGETandHEAD. - Verify that
https://cal.lukasrosier.com/lukas.icsis anonymously readable and rejects methods other thanGETandHEAD. - Confirm that each frontend displays only its corresponding feed and that neither hostname exposes a direct Radicale path.
- Verify an authenticated LLDAP CalDAV login.
- Create and delete a temporary event in
calendar/publicwith two different authenticated accounts. - Create a personal calendar and verify that another account cannot read it.