Awwwth Identity — production operations
Requires Docker Compose. The image uses Bun 1.4.0 and PostgreSQL 18. Production requires HTTPS, persistent database/key volumes, and a configured email provider.
Deploy
cp oci.env.example oci.env
# Configure domains, database credentials, email, and the trusted proxy IP.
docker compose --env-file oci.env -f compose.yml -f compose.oci.yml up -d --build
The OCI override is required for production; the base Compose file alone uses
local development defaults. The app waits for database migrations and key setup.
Keep port 4100 bound to loopback and terminate HTTPS at the reverse proxy.
deploy/nginx/awwwth.conf is an HTTP proxy template; configure TLS separately and
adapt its hostnames to DOCKER_AUTH_ORIGIN and DOCKER_AUTH_API_ORIGIN.
The API virtual host must forward the issuer hostname in its upstream Host header.
Keep oci.env, .env, and private keys out of version control. Use the same
password in DOCKER_POSTGRES_PASSWORD and DOCKER_DATABASE_URL. Configure
DOCKER_TRUSTED_PROXY_IP to the exact container-visible address of the proxy.
Operate
docker compose --env-file oci.env -f compose.yml -f compose.oci.yml ps
docker compose --env-file oci.env -f compose.yml -f compose.oci.yml logs --tail 100 app
docker compose --env-file oci.env -f compose.yml -f compose.oci.yml exec app bun run admin account@example.com
Create the account before granting administrator access. /healthz checks process
liveness; /health also checks PostgreSQL. The app drains active requests and
background delivery before closing its database pool on shutdown.
Back up PostgreSQL and the persistent key volume before upgrades. Keep the previous
image for rollback. Never use docker compose down --volumes on a deployment whose
data or keys must be retained. Applied migration files are immutable and must remain
available for checksum verification.
Build and direct execution
bun install --frozen-lockfile
bun run build
The build validates TypeScript and generates dist/tailwind.css. Browser JavaScript
is bundled at process startup. Docker retains only runtime dependencies in the final
image; TypeScript and Tailwind are build-time dependencies.
For direct execution outside Docker, bun run setup generates keys under
.local/keys. Configure the environment from .env.example, set ENCRYPTION_KEY
from the generated private encryption.key, run bun run migrate, then bun start.
Setup does not create a database or configure the environment.
Optional OTLP trace export is configured through the environment. The
observability/casting.yaml file supports a separate SigNoz deployment.
Related documentation
Back to README · Configuration reference
The public documentation frontend is available at /docs after deployment. It
renders the Markdown files in docs/ plus the repository README. The runtime
image must contain those files and public/docs.js; the Dockerfile copies them.
The site also serves /sitemap.xml and /robots.txt for documentation discovery.
Deployment resources
The OCI override configures PostgreSQL with shared_buffers=2GB,
effective_cache_size=7GB, work_mem=8MB, maintenance_work_mem=256MB,
and max_connections=100. Review these settings against host capacity before
using the override on a smaller machine. The application pool allows 20 connections.
Persistent Compose volumes hold PostgreSQL data (postgres_data), private keys
(secret_data), and development email (mail_data). Volume names are normally
prefixed with the Compose project name, awwwth.
Upgrade and recovery
Shared-sign-in policy
The provider now automatically authorizes registered apps when the browser has an
active, verified session in the app's account directory. Deploy this provider
version before expecting automatic sign-in from the CLI-generated gateways.
Registration is therefore a trust decision: default authorization no longer asks
for consent separately for every app. Explicit prompt=consent still shows that
screen, and directory isolation remains enforced. Revoking a connection ends its
current grants, but a later visit can authorize the trusted app again.
The CLI gateway deployment is separate from the identity server. Each app needs its own client credentials, private backend, gateway process, and production HTTPS origin. See the setup guide.
Upgrading an existing installation after the Awwwth rename
The default Compose project name is now awwwth, the image is awwwth-auth:local,
and new development databases use the awwwth role and awwwth_auth database.
For an existing deployment, retain its original Compose project name with -p
on every Compose command so its database and key volumes continue to be used.
Keep the actual existing database credentials in the database URL; changing
Compose defaults does not rename a database or role in an initialized volume.
For base-Compose installations, override the PostgreSQL environment and health
check, plus the app and migration database URLs, to match the existing database.
Back up the database and keys before switching configurations.
Update consumers to /awwwth.js, SDK exports such as AwwwthAuthError, and
X-Awwwth-Request, X-Awwwth-Account, and X-Awwwth-Tenant headers. The setup
directory variable is now AWWWTH_SECRET_DIRECTORY, and the Nginx template is
deploy/nginx/awwwth.conf. Old SDK routes and header names are not aliases.
Cookie names changed, so existing browser sessions require sign-in again. Saved theme preferences use a new storage key. Encryption authenticated-data bytes remain unchanged for existing TOTP secrets and queued messages. Email delivery idempotency keys use the new prefix; drain pending deliveries before upgrading to avoid duplicate delivery across the change.
Routine upgrade procedure
- Back up PostgreSQL and the key volume, and verify that backups can be restored.
- Retain the current image and deployment configuration.
- Read pending migrations for compatibility constraints. Drain old application processes before migrations that change semantics, including migration 003.
- Build and deploy with the same production Compose files and environment file.
- Check migration/setup exit status, application logs,
/healthz, and/health. - Verify login and a registered application's authorization flow.
There is no down-migration command. Reverting an image is only safe when it supports the resulting schema; otherwise recovery requires a compatible release or a planned restore of the database and matching keys. Never regenerate keys as a recovery step for an existing database.
Troubleshooting
| Symptom | Check |
|---|---|
Invalid host | Public origin and reverse-proxy upstream Host; API hostname must forward the issuer Host |
invalid_origin | Exact Origin and X-Awwwth-Request: 1 on account mutations |
account_changed | Refresh account state and use its ID in X-Awwwth-Account |
reauthentication_required | Confirm password/MFA or passkey, then retry the action |
| Signing file missing | Set SIGNING_KEY_PATH to setup's actual output path |
| Encryption key rejected | Use the generated base64url key without extra whitespace |
| Startup database failure | Database URL, credentials, connectivity, and completed migrations |
| Migration checksum failure | Restore the original applied migration; put new changes in a new file |
| Email does not arrive | Mail mode, sender, provider credentials, worker logs, and outbox retries |
| Company login appears missing | Correct tenant query/header and directory-specific account |
OAuth invalid_grant | Code expiry/use, exact redirect URI, PKCE verifier, session status, or refresh reuse |
| Passkey fails after hostname change | Credentials are bound to the configured relying-party hostname |
| Stylesheet unavailable | Run bun run build before starting directly |
/healthz only confirms the process can respond. /health checks PostgreSQL, but
neither endpoint confirms email or logout callback delivery. Monitor delivery logs:
jobs are removed after 24 failed attempts. There is no dead-letter queue or built-in
operator replay command.