powerhour

Self-hosting guide

Powerhour runs on your own infrastructure. You own the database, the credentials, and the data. Follow these steps to get up and running.

Prerequisites

  • Docker Engine with Compose v2 (runs Postgres and, in production, the app itself)
  • Node.js 22 or later (source/dev workflow only — not required for the release image)
  • Plaid developer account
  • A strong session secret (32+ chars)
1

Clone and configure

Clone the repository, copy .env.example to .env, and fill in your Plaid credentials, database URL, and session secret.

git clone https://github.com/aidandevv/powerhour
cd powerhour
npm install
npm run setup
2

Start Postgres with Docker

Docker Engine with Compose v2 is the one hard infrastructure requirement. It runs Postgres for you — no local database install needed.

docker compose -f docker/docker-compose.yml up db -d
3

Push the schema and start the app

Apply the Drizzle schema, then run the dev server. Demo mode is available if you don't have Plaid credentials yet.

npm run db:push
npm run dev
4

Go to production with a release image

For a real deployment, skip the source checkout entirely: pull a versioned, checksum-verified image from GHCR and run the bundled production Compose file with its migrate service.

export POWERHOUR_VERSION=v1.0.0
curl -fsSLO "https://github.com/aidandevv/powerhour/releases/download/${POWERHOUR_VERSION}/docker-compose.yml"
curl -fsSLo .env.example "https://github.com/aidandevv/powerhour/releases/download/${POWERHOUR_VERSION}/env.example"
curl -fsSLO "https://github.com/aidandevv/powerhour/releases/download/${POWERHOUR_VERSION}/checksums.sha256"
sha256sum -c checksums.sha256

docker compose --profile tools run --rm migrate
docker compose up -d

Environment variables

Copy .env.example to .env and fill in the following:

VariableDescription
DATABASE_URLPostgreSQL connection string
PLAID_CLIENT_IDFrom the Plaid dashboard
PLAID_SECRETEnvironment-specific Plaid secret
PLAID_ENVsandbox, development, or production
SESSION_SECRET32+ character random string for iron-session
DEMO_MODESet to true to seed demo data on startup (optional)

Production deployment

The recommended production path uses a versioned, checksum-verified image from GHCR and never requires a source checkout or Node.js on the server.

export POWERHOUR_VERSION=v1.0.0
curl -fsSLO "https://github.com/aidandevv/powerhour/releases/download/${POWERHOUR_VERSION}/docker-compose.yml"
curl -fsSLo .env.example "https://github.com/aidandevv/powerhour/releases/download/${POWERHOUR_VERSION}/env.example"
curl -fsSLO "https://github.com/aidandevv/powerhour/releases/download/${POWERHOUR_VERSION}/checksums.sha256"
sha256sum -c checksums.sha256

docker compose --profile tools run --rm migrate
docker compose up -d

The app binds to 127.0.0.1:3000 by default — put Caddy, nginx, Traefik, or Cloudflare Tunnel in front for internet access. If you build from source instead, the bundled docker/docker-compose.yml ships an opt-in nginx + Let's Encrypt profile (--profile tls).

Daily backups are a one-line cron job: docker compose exec -T db pg_dump piped through gpg encryption. Restore with the same command in reverse.