vantezzen/pay
Self-host

Environment variables

Required configuration for a self-hosted vantezzen/pay instance.

Web app variables

VariableExampleNotes
DATABASE_URLpostgres://...Postgres connection string.
PAY_PROVIDER_SERVICE_URLhttp://provider-service:3001Internal URL the web app uses for provider operations.
PAY_PROVIDER_SERVICE_SECRETbase64...Shared secret between the web app and provider service.
BETTER_AUTH_SECRETbase64...Random auth secret.
BETTER_AUTH_URLhttps://pay.example.comPublic dashboard/auth URL.
NEXT_PUBLIC_APP_URLhttps://pay.example.comPublic URL used for webhooks, checkout returns, and registry links.
PAY_ALLOW_SIGNUPStrue or falseAllow new dashboard accounts.
RESEND_API_KEYre_...Resend API key for auth emails and wallet recovery.
RESEND_FROMvantezzen/pay <[email protected]>Verified sender used for transactional emails.
GITHUB_CLIENT_IDIv1...Optional GitHub OAuth app client id for dashboard sign-in.
GITHUB_CLIENT_SECRET...Optional GitHub OAuth app client secret.
PAY_BILLING_MODEself_hostedKeep this as self_hosted for unbilled self-hosted deployments.

The hosted billing variables (PAY_HOSTED_PAY_SECRET_KEY, NEXT_PUBLIC_HOSTED_PAY_URL, NEXT_PUBLIC_HOSTED_PAY_KEY, PAY_ALL_ACCESS_EMAILS, and PAY_ALL_ACCESS_USER_IDS) are only for the official hosted pay.vantezzen.io deployment. Do not set them for normal self-hosting.

Provider service variables

Put these in services/provider/.env or the provider service deployment:

VariableExampleNotes
DATABASE_URLpostgres://...Postgres connection string. Can use a narrower DB role.
PAY_PROVIDER_SERVICE_SECRETbase64...Same shared secret as the web app.
PAY_PROVIDER_SERVICE_PORT3001Local port.
PAY_SECRETS_PROVIDERenv or vaultDefaults to env.
PAY_ENCRYPTION_KEYbase64...Required for PAY_SECRETS_PROVIDER=env; must decode to exactly 32 bytes.
VAULT_ADDRhttps://vault.example.comRequired for PAY_SECRETS_PROVIDER=vault.
VAULT_TOKENhvs...Vault token for Transit encrypt/decrypt.
VAULT_TRANSIT_MOUNTtransitVault Transit mount path.
VAULT_TRANSIT_KEYpay-provider-secretsVault Transit key name.

Generate secrets

Generate secrets locally:

openssl rand -base64 32
openssl rand -base64 32
openssl rand -base64 32

Use one value for BETTER_AUTH_SECRET, one for PAY_PROVIDER_SERVICE_SECRET, and one for PAY_ENCRYPTION_KEY if you use the default env secrets provider.

Local example

.env
DATABASE_URL="postgres://pay:pay@localhost:5432/pay"
PAY_PROVIDER_SERVICE_URL="http://localhost:3001"
PAY_PROVIDER_SERVICE_SECRET="..."
BETTER_AUTH_SECRET="..."
BETTER_AUTH_URL="http://localhost:3000"
NEXT_PUBLIC_APP_URL="http://localhost:3000"
PAY_ALLOW_SIGNUPS="true"
RESEND_API_KEY="re_..."
RESEND_FROM="vantezzen/pay <[email protected]>"
PAY_BILLING_MODE="self_hosted"
services/provider/.env
DATABASE_URL="postgres://pay:pay@localhost:5432/pay"
PAY_PROVIDER_SERVICE_SECRET="..."
PAY_PROVIDER_SERVICE_PORT="3001"
PAY_SECRETS_PROVIDER="env"
PAY_ENCRYPTION_KEY="..."

Production tips

  • Keep BETTER_AUTH_URL and NEXT_PUBLIC_APP_URL on the same public origin unless you have a specific reason not to.
  • Rotate provider API keys from the provider dashboard, then update vantezzen/pay.
  • Put PAY_ENCRYPTION_KEY, PAY_SECRETS_PROVIDER, and VAULT_* on the provider service, not the public web app.
  • Do not rotate PAY_ENCRYPTION_KEY casually; it encrypts stored provider secrets.
  • Set PAY_ALLOW_SIGNUPS=false after your first admin user exists.
  • Set up Resend before enabling real users. Email verification, password reset, email changes, account deletion confirmation, and wallet recovery all depend on transactional email.
  • For GitHub login, set the OAuth app callback URL to https://pay.example.com/api/auth/callback/github.