From 32d81d978580034754dfb1753242b9e0ef3f02e2 Mon Sep 17 00:00:00 2001 From: Jozsef Gtta Date: Thu, 2 Jul 2026 04:02:47 +0000 Subject: [PATCH] Add AdventureLog setup summary --- AdventureLog-Setup-Summary.md | 104 ++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/AdventureLog-Setup-Summary.md b/AdventureLog-Setup-Summary.md index e69de29..9215d81 100644 --- a/AdventureLog-Setup-Summary.md +++ b/AdventureLog-Setup-Summary.md @@ -0,0 +1,104 @@ +# AdventureLog Setup Summary + +## What It Is +AdventureLog is a self-hosted travel logging app with a SvelteKit frontend and Django/PostGIS backend. +Live at: **https://go.jgitta.com** + +--- + +## Infrastructure + +| Component | Detail | +|-----------|--------| +| Host | siklos (192.168.88.27) | +| Portainer Stack | #47 — `adventurelog` (endpoint 3) | +| Frontend container | `adventurelog-frontend` — port 8015 (SvelteKit SSR) | +| Backend container | `adventurelog-backend` — port 8016 (Django/nginx → gunicorn :8000) | +| Database container | `adventurelog-db` (PostGIS 16-3.5) | +| Data volumes | `/srv/docker/adventurelog/postgres_data/` and `/srv/docker/adventurelog/media/` | +| Reverse proxy | Caddy VM (192.168.88.110) — `go.jgitta.com` block in `/etc/caddy/sites/infrastructure.caddy` | + +--- + +## Caddy Routing (Critical — Non-Obvious) + +AdventureLog has a SvelteKit API proxy that deletes the `csrftoken` cookie from the browser on every request, making direct browser→Django API calls impossible. The routing is split: + +```caddy +go.jgitta.com { + # GET/HEAD/OPTIONS /api/* → Django directly (port 8016) + # Browser sends session cookie; no CSRF needed for reads. + # Accept: application/json header forces JSON instead of DRF HTML. + @api_read { method GET HEAD OPTIONS; path /api/* } + handle @api_read { + reverse_proxy http://192.168.88.27:8016 { + header_up Accept "application/json" + } + } + + # All other requests (pages + POST/PUT/DELETE /api/*) → SvelteKit (port 8015) + # SvelteKit proxy fetches fresh CSRF token server-to-server and handles auth. + @frontend { not path /media* /admin* /static* /accounts* } + handle @frontend { reverse_proxy http://192.168.88.27:8015 } + + # Django: media, admin, static, auth endpoints + handle { reverse_proxy http://192.168.88.27:8016 } +} +``` + +**Why this matters:** POST/PUT/DELETE must go through SvelteKit (port 8015 → gunicorn :8000). These requests will NOT appear in the Django nginx access log (`/var/log/nginx/access.log` inside the backend container). Only GET requests via Caddy appear there. + +--- + +## Portainer Environment Variables + +All 17 env vars are stored in Portainer's environment section (not hardcoded in compose). Key ones: + +| Variable | Value | +|----------|-------| +| ORIGIN | https://go.jgitta.com | +| PUBLIC_URL | https://go.jgitta.com | +| CSRF_TRUSTED_ORIGINS | https://go.jgitta.com | +| FRONTEND_URL | https://go.jgitta.com | +| PUBLIC_SERVER_URL | http://server:8000 | +| FRONTEND_PORT | 8015 | +| BACKEND_PORT | 8016 | +| POSTGRES_DB | adventurelog | +| POSTGRES_USER | adventure | +| DEBUG | False | +| DISABLE_REGISTRATION | False | + +Secrets (password, secret key, admin credentials) are in Portainer only — not in this file. + +--- + +## Bugs Fixed During Setup + +### 1. CSRF errors on login +Django's `CSRF_TRUSTED_ORIGINS` must match the public URL exactly. Fixed by setting it in env. + +### 2. GET /api/* returning DRF HTML instead of JSON +Caddy was doing a broken URI rewrite (`{1}` not expanding). Fixed by removing the rewrite and adding `header_up Accept "application/json"`. + +### 3. Geocode search returning 401 +GET requests were going through SvelteKit's proxy, which strips the session cookie on redirect. Fixed by routing GET /api/* directly to Django (see Caddy config above). + +### 4. Category creation returning 500 +AdventureLog has an unhandled `IntegrityError` when a duplicate category slug is created — it returns 500 instead of 400. Workaround: delete duplicate categories via Django shell if this occurs. + +### 5. "Use My Location" button blocked +Caddy's `web_secure` snippet sets `Permissions-Policy: geolocation=()`. Changed the `go.jgitta.com` block to use inline headers with `geolocation=(self)` instead. + +--- + +## Admin Access +- **URL**: https://go.jgitta.com/admin +- **Username**: admin +- **Django shell**: `docker exec -it adventurelog-backend python manage.py shell` + +--- + +## Known Limitations / Not Configured +- No Google Maps API key — geocoding uses OpenStreetMap/Nominatim (works fine) +- No Strava integration +- B2/Kopia backup not configured for this stack