5.5 KiB
Deployment
Server layout confirmed
The production server currently runs multiple separate Docker Compose projects:
- Main public site WordPress stack:
- project:
goodwalkconz - path:
/docker/wordpress/goodwalk.co.nz
- project:
- Onboarding WordPress stack:
- project:
onboardinggoodwalkconz - path:
/docker/wordpress/onboarding.goodwalk.co.nz
- project:
- Shared nginx:
- project:
nginx - path:
/docker/nginx
- project:
- Shared mysql:
- project:
mysql - path:
/docker/mysql
- project:
The deployment scripts in this repo are set up to deploy the new Svelte site as a separate stack at:
- remote path:
/docker/goodwalk-svelte - compose file:
docker-compose.prod.yml - docker project:
goodwalk-svelte
This leaves the onboarding site, shared nginx, shared mysql, and other unrelated containers untouched.
Files involved
- deploy.ps1
- Windows entrypoint for packaging the repo, uploading it, and running the remote deployment helper over SSH.
- scripts/deploy-remote.sh
- Server-side helper that updates only the
goodwalk-sveltecompose project.
- Server-side helper that updates only the
- docker-compose.prod.yml
- Production compose file for the new Svelte app, mail API, and Postgres.
scripts/export-homepage-content.mjs- Local helper that exports the current
src/lib/content/homepage.tsinto a deployable JSON payload before each deployment.
- Local helper that exports the current
scripts/sync-homepage-content.mjs- Runtime helper that upserts the exported homepage content into PostgreSQL after deploys that affect the app/database.
- ssh-config
- Repo-local SSH config used by the deployment script.
- nginx/goodwalk.co.nz.svelte.conf.example
- Example shared-nginx config for routing the main public site to the new Svelte app and mail API.
First-time server preparation
-
Fill in ssh-config with the real host details.
-
Create the deployment directory on the server:
mkdir -p /docker/goodwalk-svelte
- The first deployment will auto-create the production env file on the server at:
/docker/goodwalk-svelte/.env
It is created from deploy.env.template. Current template contents:
APP_VERSION=4.0.1
TZ=Pacific/Auckland
POSTGRES_DB=goodwalk
POSTGRES_USER=goodwalk
POSTGRES_PASSWORD=gw_Pg_7Jm9!Qx4#Ld2@Vr8
POSTGRES_PASSWORD_URLENCODED=gw_Pg_7Jm9%21Qx4%23Ld2%40Vr8
RESEND_API_KEY=replace-me
OWNER_EMAIL=replace-me
FROM_EMAIL=GoodWalk <bookings@goodwalk.co.nz>
REPLY_TO=aless@goodwalk.co.nz
FORM_MIN_SECONDS=4
FORM_MAX_SECONDS=7200
RATE_LIMIT_WINDOW_SECONDS=900
RATE_LIMIT_MAX_PER_IP=5
RATE_LIMIT_MAX_PER_EMAIL=3
RATE_LIMIT_MIN_INTERVAL_SECONDS=20
After the first deploy, edit /docker/goodwalk-svelte/.env on the server and replace:
RESEND_API_KEY=replace-meOWNER_EMAIL=replace-me
- Confirm the shared Docker network already exists:
docker network ls | grep webnet
Your server already uses webnet, so this should already be present.
First deploy
From Windows PowerShell in the repo root:
powershell -ExecutionPolicy Bypass -File .\deploy.ps1
Or skip the confirmation prompt:
powershell -ExecutionPolicy Bypass -File .\deploy.ps1 -Force
To rebuild and restart only one service, for example the mail API:
powershell -ExecutionPolicy Bypass -File .\deploy.ps1 -Force -Service mail-api
Homepage content sync
Local development can feel fresher than production because production reads the
homepage/shared content from PostgreSQL whenever DATABASE_URL is set.
The deployment flow now handles that automatically:
deploy.ps1exports the currentsrc/lib/content/homepage.tsintodeploy-data/homepage-content.json.- The deploy archive uploads that JSON payload with the app source.
- After the Goodwalk stack is updated, the remote helper runs a content sync inside the app container.
- That sync upserts the
homepagerow insite_content.
This means future deploys will carry your latest file-based homepage/navigation/ shared content changes into production PostgreSQL automatically.
Cutover nginx
After the new Svelte stack is up and healthy, update the shared nginx config on the server for the main site.
Current live file:
/docker/nginx/conf.d/goodwalk.co.nz.conf
Use the repo example as the new target config:
nginx/goodwalk.co.nz.svelte.conf.example
Important:
- The normal
deploy.ps1flow does not deploy or reload the shared nginx stack. - Copy the updated nginx config to
/docker/nginx/conf.d/goodwalk.co.nz.confand reload nginx once. - The repo example now uses Docker's internal resolver so future app/mail container rebuilds will not leave nginx pinned to stale upstream IPs.
Then reload nginx:
docker compose -p nginx -f /docker/nginx/docker-compose.yml exec nginx nginx -t
docker compose -p nginx -f /docker/nginx/docker-compose.yml exec nginx nginx -s reload
Important notes
- Do not deploy the top-level
docker-compose.ymlto this server for production. It includes its own nginx service and does not match the shared nginx setup on the host. - The deployment scripts do not stop or remove the onboarding WordPress stack.
- The deployment scripts do not touch the shared mysql compose project.
- The deployment scripts preserve the remote
.envfile. - The site check in
deploy.ps1targetshttps://www.goodwalk.co.nz/api/health. Before nginx cutover, use-SkipSiteCheckor expect that check to fail.