4.7 KiB
Contabo release operations
This site publishes static content through the merged Contabo release manager.
It does not run nixos-rebuild, reload nginx, change DNS, or write directly to
/srv/www/azinstitute4autism.com/www/dist.
Required local tools and private inputs
- Node.js 22+, Git, tar, SSH and rsync.
- A normal SSH identity accepted by the existing root receiver:
AIA_DEPLOY_SSH_IDENTITY=/absolute/path/to/identity. AIA_DEPLOY_HOST=administrator@host(or the approved equivalent).- For a real public release, an owner-controlled, regular encrypted payload:
AIA_PORTAL_PRODUCTION_CIPHERTEXT_FILE=/absolute/private/employee-portal/approved-production-ciphertext.json.
The payload remains outside Git and the source snapshot. It is browser ciphertext only; neither access code nor decrypted portal HTML enters an Astro environment variable, public resource directory, build log, or deployment manifest.
Commands
From www/:
npm run deploy -- --dry-run
Dry-run performs the local production build, tests, artifact verification, manifest creation and source-snapshot preparation. With no private production payload it uses a generated synthetic two-stream fixture and explicitly reports that the result is not production-ready. It never opens SSH or rsync.
AIA_DEPLOY_HOST='root@approved-host' \
AIA_DEPLOY_SSH_IDENTITY="$HOME/.ssh/AIAMarketing" \
AIA_PORTAL_PRODUCTION_CIPHERTEXT_FILE="$PWD/private/employee-portal/approved-production-ciphertext.json" \
npm run deploy -- --confirm
The confirmed command builds with PUBLIC_ALLOW_INDEXING=true, Form A live and
counters off, then uploads only fresh commit-specific staging/source-<sha> and
staging/dist-<sha> directories. It runs, in order:
aia-website-release verify
aia-website-release sync-source
aia-website-release promote
The VPS verifies the manifest, promotes an immutable release by atomic symlink, and retains the prior release. A successful rsync transfer alone is not success.
Rollback requires the reviewed manifest retained at the server’s fixed path:
AIA_DEPLOY_HOST='root@approved-host' \
AIA_DEPLOY_SSH_IDENTITY="$HOME/.ssh/AIAMarketing" \
npm run deploy:rollback -- FULL_APPROVED_SHA --confirm
Employee resources: separate one-time operation
Approved non-PHI employee files are never part of an ordinary release. After the VPS SOPS-backed Basic Auth material is independently ready:
npm run deploy:portal-resources -- --dry-run
AIA_DEPLOY_HOST='root@approved-host' \
AIA_DEPLOY_SSH_IDENTITY="$HOME/.ssh/AIAMarketing" \
npm run deploy:portal-resources -- --confirm
For the first install, the client extracts portal-resource-install.sh from the
current reviewed Git commit, uploads it into the root-controlled commit staging
directory, verifies its SHA-256 remotely, and invokes it through NixOS's base
/bin/sh and coreutils path. A prior public site release and a globally installed
Node.js runtime are not prerequisites. It reads only the private collection manifest,
accepts approved STAFF-INTERNAL and MANAGEMENT-INTERNAL mappings to
/staff-resources/ and /management-resources/, verifies every local hash, rejects links/traversal and
uploads a root-controlled temporary tree. It never uses --delete for resource
directories and refuses to replace a different existing file. The VPS installs
regular files as root:nginx mode 0640 and reports metadata only.
Local mapping approval authorizes preparation and installation only. After the authorized VPS rehearsal, verify installed hashes, ownership/mode, staff versus management Basic Auth, and both protected URLs before deploying portal links.
Before public DNS cutover, test the site with approved host-header/SNI methods, including the portal’s noindex response, valid ciphertext unlock, both protected resource namespaces, denial cases, redirects, Form A, IPv4 and IPv6. Portal shared-code rotation is coordinated: update VPS SOPS inputs and privately re-encrypt the browser payload together. This interim portal is non-PHI and is not an employee identity system.
The portal uses one code entry per page session. A successful decrypt retains
the code only in page memory and sends the matching fixed username (staff or
management) in an explicit same-origin Basic Authorization header when a
protected link is clicked. It downloads the authenticated response as a Blob
and never navigates directly to the protected URL after an error. Verify that
ordinary clicks download without a native credential dialog, inline errors
appear for denied or unavailable files, direct unauthenticated requests remain
401, and neither role can request the other namespace. Reloading, leaving the
page, or an Astro page swap discards the in-memory credential.