Self-Host Allowealth
Self-host Allowealth when you want full control over data, updates, and deployment.
Who self-hosting is for
Section titled “Who self-hosting is for”- Teams comfortable managing their own runtime, secrets, and backups
- Organizations that need private networking, custom domains, or data residency controls
- Developers who want to evaluate or extend Allowealth before rolling it out
Prerequisites
Section titled “Prerequisites”- Docker Engine 24+
- Docker Compose v2
- A machine that can build Docker images
- Google OAuth credentials for your domain
- Cloudflare Turnstile site and secret keys
Quick start
Section titled “Quick start”# 1. Clone the repository at the release you wantgit clone https://github.com/ivankristianto/allowealth.gitcd allowealthgit checkout vX.Y.Z # Replace with your target version
# 2. First run: create .env and generate secrets (exits after setup)bun run docker:start
# 3. Edit .env with your OAuth/Turnstile values# Then start the containers:bun run docker:startThe app runs at http://localhost:3000 by default.
First-run setup
Section titled “First-run setup”When the app starts with an empty database, the installer guides you through creating the first workspace and admin account.
- Open your
PUBLIC_URL(e.g.,http://localhost:3000) - The app redirects to
/installer— fill in:- Workspace name
- Admin full name, email, and password
- Installer secret (if you set
INSTALLER_SECRETin.env)
- Submit the form to complete setup
- Sign in with the admin credentials you created
The installer only appears when no users exist. After setup, /installer redirects to the login page.
Environment variables
Section titled “Environment variables”The following variables are required for production:
| Variable | Required | Description |
|---|---|---|
PUBLIC_URL | Yes | Origin users access (e.g., https://finances.example.com) |
BETTER_AUTH_SECRET | Yes | Long random string for auth signing |
EMAIL_ENCRYPTION_KEY | Yes | Base64 32-byte key for encrypted secrets |
COOKIE_SIGNING_SECRET | Yes | Separate secret for cookie signing |
GOOGLE_CLIENT_ID | Yes | Google OAuth client ID |
GOOGLE_CLIENT_SECRET | Yes | Google OAuth client secret |
PUBLIC_TURNSTILE_SITE_KEY | Yes | Cloudflare Turnstile site key |
TURNSTILE_SECRET_KEY | Yes | Cloudflare Turnstile secret key |
Optional variables:
| Variable | Default | Description |
|---|---|---|
DATABASE_URL | /data/allowealth.db | SQLite path inside container |
SIGNUP_MODE | invite_only | invite_only or public registration |
EMAIL_MODE | console | console logs emails, real sends via provider |
CACHE_DRIVER | redis | redis, memory, or upstash |
REDIS_PASSWORD | changeme | Redis password (internal Docker network) |
PUBLIC_SITE_URL | https://allowealth.io | Marketing site URL |
See docker/.env.example for email provider and cache configuration options.
Volume persistence
Section titled “Volume persistence”SQLite lives at /data/allowealth.db inside the container, backed by a named Docker volume (allowealth-data). The volume persists across container restarts and image updates.
Backup
Section titled “Backup”docker compose -f docker/docker-compose.yml stop appdocker run --rm \ -v allowealth-data:/data \ -v "$(pwd)":/backup \ busybox sh -c 'tar czf /backup/allowealth-backup-$(date +%Y%m%d).tar.gz -C / data'docker compose -f docker/docker-compose.yml start appStop the app before backing up. SQLite uses WAL mode, so live backups can miss recent changes.
Restore
Section titled “Restore”docker compose -f docker/docker-compose.yml stop appdocker run --rm \ -v allowealth-data:/data \ -v "$(pwd)":/backup \ busybox tar xzf /backup/allowealth-backup-YYYYMMDD.tar.gz -C /docker compose -f docker/docker-compose.yml start appReverse proxy
Section titled “Reverse proxy”Allowealth listens on port 3000 inside the container. Put it behind a reverse proxy for HTTPS.
Nginx example
Section titled “Nginx example”server { listen 443 ssl; server_name finances.example.com;
# SSL configuration here
location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }}Caddy and Traefik work equally well. Set PUBLIC_URL to the final HTTPS origin your proxy serves.
Updates
Section titled “Updates”git fetch --tagsgit checkout vX.Y.Z # switch to target versiondocker compose -f docker/docker-compose.yml up -d --buildMigrations run automatically when the container starts.
Database management
Section titled “Database management”Run migrations manually
Section titled “Run migrations manually”docker exec allowealth-app bun run src/db/migrate.tsSeed with demo data
Section titled “Seed with demo data”# Default: 6 months of transactionsdocker exec allowealth-app bun run src/db/seed/index.ts
# Custom optionsdocker exec allowealth-app bun run src/db/seed/index.ts --months=12docker exec allowealth-app bun run src/db/seed/index.ts --stressReset database
Section titled “Reset database”docker exec allowealth-app bun run src/db/setup.tsTroubleshooting
Section titled “Troubleshooting”Container exits immediately
Section titled “Container exits immediately”A migration failed or a required environment variable is missing. Check the logs:
docker compose -f docker/docker-compose.yml logs appTo run migrations manually:
docker exec allowealth-app bun run src/db/migrate.tsIf the container has exited, restart it first:
docker compose -f docker/docker-compose.yml up -dApp unreachable on port 3000
Section titled “App unreachable on port 3000”Verify the container is running:
docker compose -f docker/docker-compose.yml psdocker compose -f docker/docker-compose.yml logs appIf the container is healthy but unreachable, check your firewall rules and reverse proxy configuration.
Next steps
Section titled “Next steps”- Review Getting Started for first-run workflows and demo account credentials
- Follow Setup and Deployment for Cloudflare and Node deployment details
- Use Deployment Guide for rollout and rollback checks
- Keep Commands Reference nearby for CLI syntax
- Review Database Management before planning backups