Create staging-environment-setup.md via n8n

This commit is contained in:
herbygitea 2026-04-15 11:00:36 +00:00
parent 94c08c20a5
commit 953aaa1cef

View File

@ -0,0 +1,119 @@
---
project: staging-environment-setup
type: reference
status: active
path: Tech/Reference
tags:
- pbs
- infrastructure
- staging
- traefik
- cloudflare
- docker
created: 2026-04-15
updated: 2026-04-15
---
# Staging Environment — Architecture Reference
Reference doc for how the PBS staging environment is structured. Captured
retroactively from the original Feb 24 build session, before the n8n email
pipeline existed.
> **Note on path:** Filed under a proposed new `Tech/Reference` folder for
evergreen architecture docs (vs. `Tech/Sessions` for point-in-time notes or
`Tech/Projects` for active work). Flag if you'd rather move it.
## Domain & DNS Strategy
Staging lives at `staging.plantbasedsoutherner.com`, with all supporting
tools nested as further subdomains under it.
```
staging.plantbasedsoutherner.com ← WordPress
n8n.staging.plantbasedsoutherner.com ← n8n
portainer.staging.plantbasedsoutherner.com ← Portainer
status.staging.plantbasedsoutherner.com ← Uptime Kuma
db.staging.plantbasedsoutherner.com ← phpMyAdmin
gitea.staging.plantbasedsoutherner.com ← Gitea
```
**Cloudflare DNS uses a wildcard A record** so new subdomains require zero
DNS work:
```
Type: A
Name: *.staging
Value:
Proxy: DNS only (grey cloud)
```
The wildcard must remain **DNS only** (grey cloud) for Let's Encrypt HTTP
challenges to succeed. With Cloudflare proxy on, ACME hits Cloudflare's IP
instead of the origin and TLS handshake fails.
## SSL / Traefik
Traefik handles all routing and SSL via Let's Encrypt **HTTP challenge**
(not TLS challenge — TLS challenge is incompatible with Cloudflare in
front).
Each container declares its hostname via Traefik labels; Traefik handles
cert issuance and renewal automatically per hostname.
## Migration Pattern (Prod → Staging Clone)
The original staging build used a full prod clone. Key gotchas:
- **Database URL replacement:** Use WP-CLI `search-replace` (not raw SQL)
to handle serialized Elementor data correctly. Run from inside the
wordpress container.
- **Avoid "staging.staging" loops:** Replace `plantbasedsoutherner.com` → `
staging.plantbasedsoutherner.com` in one direction only; double-check
existing staging references before running.
- **Redis password:** Must be present in the container env for both prod
and staging — easy to forget when moving env vars between `.env` files.
- **DB user recreation:** Fresh MySQL inits won't carry over user grants
from the prod dump.
## Resource Sizing
Staging started on a 1GB Linode Nanode and was upgraded to 2GB after
hitting memory ceilings during full-stack runs (WordPress + MySQL + Redis +
n8n + Traefik + monitoring). 2GB is the practical minimum for the full
stack.
## Healthchecks
All Docker containers have healthchecks defined. A few patterns learned:
- **Traefik** requires an IPv6 loopback target in some configurations.
- **Containers without `curl`** (slim images, Gitea, Python slim) need
alternative healthcheck commands — wget, a Python one-liner, or the
application's own CLI.
- **Gitea healthcheck on `/api/v1/version`** returns 404 before the setup
wizard completes, blocking initial Traefik routing. Remove the healthcheck
for first-time setup, then add it back.
## Inventory & Ansible (added later)
The Ansible inventory eventually evolved to keep staging and production
strictly separated — see the GitHub deploy key project for the final
structure with `bootstrap_staging`, `bootstrap_production`, `staging`, and
`production` groups (no meta-groups that could hit both environments).
## Open Items
- [ ] Confirm `Tech/Reference` is the right folder for this kind of doc, or
move to `Tech/Sessions` / `Tech/Projects`
- [ ] Cross-link this from the GitHub deploy key project plan once both are
in the vault
## Related
- GitHub private repo + Ansible inventory restructure (April 2026)
- PBS Security Hardening (Crowdsec + Authelia, staged on staging first)
- WP-Cron / Supercronic deploy (March 2026)
...sent from Jenny & Travis