diff --git a/docs/production-todo.md b/docs/production-todo.md index 4be500c..e14f7d8 100644 --- a/docs/production-todo.md +++ b/docs/production-todo.md @@ -1,52 +1,70 @@ # Production Todo -Checklist of things to do before going live. Items are roughly in dependency order. +Fresh server — no Grav installed yet. Work through these sections in order. --- -## Grav 2.0 upgrade on production +## 1. Pre-install: fix server-install.sh for Grav 2.0 -- [ ] Update `make remote-upgrade-grav` to use the direct download method (GPM still reports 1.7.x as latest — see CLAUDE.md §2 for the correct curl + copy steps) -- [ ] Install Admin2 (`admin2` plugin) on production from the grav-admin bundle -- [ ] Disable old `admin` plugin on production (`enabled: false` in `user/plugins/admin/admin.yaml`) +`server-install.sh` has a gap: it copies the `grav-admin` bundle (which includes `user/plugins/admin2/`) but then immediately does `rm -rf user && git clone ...`, which wipes admin2. It never gets reinstalled because GPM doesn't carry Admin2. -## Infrastructure +- [ ] Update `server-install.sh` to stash admin2 before wiping user/, then restore it after: -- [ ] Set `accounts.type: flex` and `pages.type: flex` in production `system.yaml` (required for Admin2) -- [ ] Ensure production user account has `api.super: true` and `api.access: true` -- [ ] Verify `session.save_path` is set to a writable path in production PHP config -- [ ] Confirm JWT secret auto-generates on production (`jwt_secret: ''` in api.yaml is correct — Grav generates one on first run) +```bash +# After "cp -rf grav-admin/. ." and before "rm -rf user": +cp -rf grav-admin/user/plugins/admin2 /tmp/admin2-plugin -## Config +# After "git clone $USER_REPO user" and "mkdir -p user/plugins ...": +cp -rf /tmp/admin2-plugin user/plugins/admin2 +rm -rf /tmp/admin2-plugin +``` + +- [ ] Remove `admin` from `plugins.txt` if it's there — Admin2 replaces it and both conflict on `/admin` + +## 2. Pre-install: configure .env + +- [ ] Set `GRAV_VERSION=2.0.0-rc.9` in `.env` +- [ ] Set `GRAV_CHANNEL_SUFFIX=?testing` in `.env` (makes the download URL resolve to the RC) +- [ ] Set `REMOTE_HOST`, `REMOTE_USER`, `REMOTE_PORT`, `REMOTE_HOME` for the production server +- [ ] Set `USER_REPO` and `MAIN_REPO` (Gitea URLs) +- [ ] Set `GITEA_HOST`, `GITEA_USER`, `GITEA_TOKEN` for the install-time clone + +## 3. Run the install + +```bash +make remote-env-setup # writes Gitea token to server temporarily +make remote-install # downloads Grav, clones repos, installs plugins +make remote-env-remove # removes token from server +``` + +After install, the script prints the server's SSH public key. Add it as a deploy key to both Gitea repos so `make remote-fetch` works going forward. + +## 4. Post-install: config + +These are already committed to the `user/` repo so they'll be present after the clone — just verify: + +- [ ] `user/config/system.yaml` has `accounts.type: flex` and `pages.type: flex` +- [ ] `user/config/system.yaml` `custom_base_url` is set to the production domain (currently set to the local dev IP — update before deploy) +- [ ] `user/accounts/mischa.yaml` has `api.super: true` and `api.access: true` +- [ ] Disable old admin plugin: set `enabled: false` in `user/plugins/admin/admin.yaml` on production (or ensure it's not in `plugins.txt`) + +## 5. Post-install: switch to production mode - [ ] Set `twig.cache: true` in `user/config/system.yaml` -- [ ] Run pre-launch smoke test: submit one post via `/post`, confirm entry appears in `/trips/japan-korea-2026/dailies` immediately (verifies cache-on-save plugin works with Twig cache enabled) -- [ ] Set `custom_base_url` in `system.yaml` to the production domain (currently set to `http://100.96.115.96:8081`) -- [ ] Confirm `post-form.md` `pageconfig.parent` matches `active_trip` in `site.yaml` +- [ ] Smoke test: submit one post via `/post`, confirm entry appears in `/trips/japan-korea-2026/dailies` immediately (verifies cache-on-save plugin works with Twig cache on) -## Plugins +## 6. Security -- [ ] Audit `plugins.txt` — it is manually maintained; verify it includes all plugins currently installed (admin2, api, flex-objects, form, add-page-by-form, cache-on-save, etc.) -- [ ] Run `make remote-install-plugins` after Grav 2.0 upgrade +- [ ] Change admin password to a strong production password +- [ ] Confirm `/post` requires login — unauthenticated visitors must not be able to post -## Map tiles +## 7. Map tiles -- [ ] Register a Carto account and review terms for production traffic — free tier requires registration for higher-volume usage -- [ ] Decide whether to stay on CartoDB or switch to a paid provider (Stadia, Mapbox) with an API key +- [ ] Register at [carto.com](https://carto.com) and review terms for production traffic (CartoDB dark tiles are free but registration is expected for production use) -## Content +## 8. Content -- [ ] Upload actual GPX route file(s) to the Japan & Korea 2026 trip page media (currently no GPX files — map renders no route) -- [ ] Set `date_start` on the trip page (`user/pages/01.trips/japan-korea-2026/trip.md`) -- [ ] Add `cover_image` to the trip page - -## Security - -- [ ] Change admin password from the dev password to a strong production password -- [ ] Confirm `/post` form requires login (`access: site.login: true` enforced — unauthenticated users cannot post) -- [ ] Review `custom_base_url` — ensure it uses HTTPS on production - -## Testing - -- [ ] Run full test suite (`make test-config && make test-post && make test-ui`) after Grav 2.0 production upgrade -- [ ] Manual smoke test all pages: `/trips/japan-korea-2026/dailies`, `/trips/japan-korea-2026/map`, `/trips/japan-korea-2026/stats`, `/post`, `/admin` +- [ ] Set `date_start` on the Japan & Korea 2026 trip page (`user/pages/01.trips/japan-korea-2026/trip.md`) +- [ ] Upload actual GPX route file(s) to the trip page media — currently no GPX files, so the map shows no route +- [ ] Add `cover_image` to the trip page (used on the trips listing) +- [ ] Run `make content-push` to push any local content changes to Gitea before going live