ReaperCI Documentation

ReaperCI documentation

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, and docs.reaperci.dev are controlled by the operator but still point at the previous provider until the edge is ready.
  • /home/cam/projects/active/reaperci-marketing is a clean checkout of the canonical Gitea mirror.
  • The staged site contains no public signup form or Cloud upstream. The retired /api/v1/waitlist route returns 410.
  • 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.dev passes an outside-in delivery test.
  • Echo port 3051 is 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

  1. Copy deploy/marketing/reaperci.dev.http.conf to /etc/nginx/sites-available/reaperci.dev.
  2. Link it into /etc/nginx/sites-enabled, run nginx -t, and reload nginx.
  3. 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); retain www as an apex redirect.
  4. Wait for authoritative and public resolvers to agree, then request one SAN certificate for reaperci.dev, www.reaperci.dev, and docs.reaperci.dev using the existing webroot /var/www/certbot.
  5. Replace the bootstrap file with deploy/marketing/reaperci.dev.https.conf, run nginx -t, and reload.
  6. Run scripts/smoke-marketing-edge.sh from 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.