Marketing and documentation production cutover
The public marketing and documentation container runs on Echo without customer
builds, tenant stacks, privileged mounts, or public container ports. Nginx is
the only public listener and proxies both hostnames to 127.0.0.1:3051 while
preserving the original Host header.
Preconditions
reaperci.dev,www.reaperci.dev, anddocs.reaperci.devare controlled by the operator but still point at the previous provider until the edge is ready./home/cam/projects/active/reaperci-marketingis a clean checkout of the canonical Gitea mirror.- The staged site contains no public signup form or Cloud upstream. The retired
/api/v1/waitlistroute returns410. - Managed prices and limits are labelled planned and unavailable for purchase.
- Draft terms, acceptable-use policy, privacy notice, and DPA are not packaged
into the public image. Add a contact CTA only after the privacy notice is
approved and
hello@reaperci.devpasses an outside-in delivery test. - Echo port
3051is bound only to loopback and the marketing container is healthy. - The operator has interactive sudo for nginx and Certbot. Do not weaken sudo policy or copy private keys to automate this step.
Deploy or upgrade the container
cd /home/cam/projects/active/reaperci-marketing
git fetch origin main
git merge --ff-only origin/main
sha="$(git rev-parse HEAD)"
created="$(git show -s --format=%cI "$sha")"
cp deploy/marketing/echo.env.example marketing/.env.echo
# Replace each placeholder with the full SHA and RFC3339 creation time.
chmod 600 marketing/.env.echo
docker compose --env-file marketing/.env.echo \
-p reaperci-marketing -f marketing/compose.yaml up -d --build
curl -fsS -H 'Host: reaperci.dev' http://127.0.0.1:3051/healthz
curl -fsS -H 'Host: docs.reaperci.dev' http://127.0.0.1:3051/installation
docker image inspect "reaperci-marketing:sha-$sha" \
--format '{{ index .Config.Labels "org.opencontainers.image.revision" }}'
The Compose project is restart-safe and does not require an nginx reload for ordinary image upgrades. Record the previous immutable image before replacing the container; it is the primary rollback target.
Stage nginx and TLS
- Copy
deploy/marketing/reaperci.dev.http.confto/etc/nginx/sites-available/reaperci.dev. - Link it into
/etc/nginx/sites-enabled, runnginx -t, and reload nginx. - Lower TTL to 300 seconds and record the previous apex address
2.57.91.91. Change the apex and docs records to Echo (85.209.95.8); retainwwwas an apex redirect. - Wait for authoritative and public resolvers to agree, then request one SAN
certificate for
reaperci.dev,www.reaperci.dev, anddocs.reaperci.devusing the existing webroot/var/www/certbot. - Replace the bootstrap file with
deploy/marketing/reaperci.dev.https.conf, runnginx -t, and reload. - Run
scripts/smoke-marketing-edge.shfrom a machine outside Echo.
The initial HSTS policy is max-age=300 without includeSubDomains. Increase
it only after seven stable days and after every intended subdomain supports
HTTPS.
Do not publish app.reaperci.dev or wildcard tenant DNS as part of this edge
cutover. Those names belong to the dedicated managed infrastructure.
Truth gates
Before DNS cutover, prove the public image has no form, no automated fetch, no
Cloud network attachment, and no fixed managed price or limit. Confirm
POST /api/v1/waitlist returns 410. Keep the contact CTA absent until the
approved privacy notice and outside-in mailbox evidence are attached to the
release record.
Rollback
If image, health, or content checks fail, restore the previous immutable
marketing image and configuration on Echo. Revert DNS to 2.57.91.91 only
when the Echo edge itself is unavailable. If nginx caused the incident, restore
the previously backed-up site file, run nginx -t, and reload. Do not delete
the certificate, checkout, or image during rollback; preserve them as evidence.