Skip to main content

Deploy the live neobank on one server

The server Compose path publishes only Caddy on ports 80 and 443. PostgreSQL, both Redis instances, Vault, FastAPI, the worker, scheduler, and web service remain private.

Configure the environment

Run the Auth0 reconciliation from a trusted administration machine first. The resulting .env.auth0 contains both runtime application credentials and Management API credentials. Export only the runtime settings to a temporary file:
Transfer .env.runtime with Secure Copy Protocol (SCP). Set server to the SSH account and host. Set server_dir to the repository directory on that server:
Do not transfer AUTH0_MANAGEMENT_CLIENT_ID, AUTH0_MANAGEMENT_CLIENT_SECRET, or AUTH0_OPERATOR_ROLE_ID. On a new server, create the target environment and restrict both files before writing secrets:
Set CADDY_ACME_EMAIL in .env.server, then prepare the deployment:
The script copies the runtime Auth0 and branding values, sets NEOBANK_HOST from the public origin, generates distinct database, metrics, and Vault secrets on a new deployment, and creates or validates the Vault TLS files. It retains already prepared server secrets on subsequent runs. Delete the server copy after the script succeeds:
After the server starts successfully, delete the administration-machine copy with the same command.
Do not replace an existing .env.server with the example file. Back it up in the protected secret store, confirm it contains # NEOBANK_PREPARED_PROJECT=perflo-neobank-server, and run the same preparation command. The script retains the provisioned database, metrics, and Vault secrets. If the marker is absent, stop and reconcile the existing environment and volumes before adopting it; do not generate new state-service credentials over live volumes.
Keep NEOBANK_PERFLO_ADAPTER=live and all five reviewed Perflo origins unchanged. See Configure a dedicated Auth0 tenant for the tenant-side procedure. The edge network is pinned to 172.30.255.0/24, Caddy to 172.30.255.2, and the API to 172.30.255.3. Uvicorn trusts forwarded client addresses only from the Caddy IP. If that subnet conflicts with the host, change the subnet, both static addresses, and NEOBANK_TRUSTED_PROXY_IPS together in a reviewed deployment override; never widen the trusted proxy setting to all private networks. Compose isolates sessions, tasks, PostgreSQL, and Vault on separate internal networks. The API joins edge, sessions, database, and Vault; the worker joins tasks, database, Vault, and a dedicated outbound-only provider bridge; the scheduler joins only tasks. The worker and scheduler cannot reach customer session Redis, and Caddy and web cannot reach data planes.

Understand Vault TLS

The preparation script creates ca.pem, server.pem, and server-key.pem in the directory named by NEOBANK_VAULT_TLS_DIR. The certificate covers DNS:vault and IP:127.0.0.1. Compose mounts the CA into the API and worker; the scheduler has no Vault network or credential. Stop the server before replacing an invalid or expiring certificate. The bootstrap sidecar initializes and unseals Vault, enables Transit, creates the derived neobank-perflo-credentials key, and creates the restricted application token. Protect the TLS key, Vault data, and bootstrap state as one recovery unit.

Start the server

Validate and start:
The one-shot migrate service applies pending migrations before the API starts — an empty database is initialized and an existing one is upgraded in place. Nothing ever deletes an existing database.

Verify the boundary

Check health, readiness, public branding, and the customer login redirect:
Replace neobank.example with the configured host. The public configuration must contain the configured application name and mark and no Auth0 settings. The login response must be an HTTP redirect whose Location uses the configured Auth0 custom domain. Complete one customer login and one operator login; operator login must require MFA. Confirm an unauthenticated customer route returns 401. Caddy removes caller-supplied debug identity headers and preserves bearer authorization for OAuth-authenticated agents and server integrations. Production documentation routes require operator authentication. Run the controlled live canary before production traffic. Stop containers without deleting volumes by running make server-down. Revoke every Perflo device before deleting PostgreSQL or Vault state.