View as markdown

Self-hosting Hub

The shortest path is one command:

npx @getpaseo/hub

Open http://localhost:3000. A fresh Hub creates its embedded database and authentication secret, then guides you through creating the operator account and the GitHub, Slack, or Discord apps you want.

Follow the quickstart to connect Slack over Socket Mode and run the first workflow without a public server.

Local data

Without DATABASE_URL, Hub stores an embedded PGlite database and its generated authentication secret under $XDG_DATA_HOME/paseo-hub. If XDG_DATA_HOME is not set to an absolute path, Hub uses ~/.local/share/paseo-hub. Both survive restarts.

Set a different location explicitly with:

PASEO_HUB_DATA_DIR=/path/to/paseo-hub-data npx @getpaseo/hub

Embedded mode supports one Hub process per data directory. It is intended for a personal or single-process Hub. Back up the whole data directory before upgrading or moving it.

Public addresses

Hub defaults to http://localhost:3000. That is enough for its dashboard, daemons, Slack Socket Mode, and providers that connect out from Hub.

GitHub event triggers use webhooks and need a public HTTPS address. Repository access can still work without the webhook. Slack's optional Webhooks transport also needs public HTTPS; Socket Mode does not.

When Hub is available at a stable public origin, set it before starting:

PASEO_HUB_APP_URL=https://hub.example.com npx @getpaseo/hub

Changing the public origin requires updating callback and webhook settings in the provider apps. The Apps page generates the URLs for the origin Hub is currently using.

PostgreSQL

Set DATABASE_URL to use PostgreSQL instead of the embedded database:

DATABASE_URL=postgres://paseo:password@localhost:5432/paseo_hub \
  npx @getpaseo/hub

Use PostgreSQL for a durable server deployment, more than one Hub process, or an existing database backup and operations setup. Migrations run automatically at startup. Hub does not start listening when a migration fails.

The database also stores Hub's generated authentication secret. Set PASEO_HUB_AUTH_SECRET only when the deployment must supply that secret from a platform secret store. While the override is set, Hub uses it without replacing the stored secret. Changing the effective secret signs everyone out of the dashboard; execution credentials already issued remain valid until their execution ends.

App configuration

The operator configures GitHub, Slack, and Discord under Apps. Hub verifies the credentials before saving them in its database and starts the same provider runtime used by environment-configured deployments.

Environment variables remain available for deployments that manage secrets outside Hub. A complete environment configuration takes precedence over a saved application and appears as Managed by environment in the dashboard.

# GitHub
GITHUB_APP_SLUG=
GITHUB_APP_ID=
GITHUB_APP_CLIENT_ID=
GITHUB_APP_CLIENT_SECRET=
GITHUB_APP_PRIVATE_KEY=          # or GITHUB_APP_PRIVATE_KEY_PATH
GITHUB_WEBHOOK_SECRET=

# Slack Socket Mode
SLACK_TRANSPORT=socket
SLACK_APP_ID=
SLACK_APP_TOKEN=

# Slack Webhooks instead of Socket Mode
SLACK_TRANSPORT=webhook
SLACK_APP_ID=
SLACK_CLIENT_ID=
SLACK_CLIENT_SECRET=
SLACK_SIGNING_SECRET=

# Discord
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
DISCORD_BOT_TOKEN=

See GitHub, Slack, and Discord for provider behavior and connection steps.

Bootstrap from environment

Browser setup is the default for a fresh database. An unattended deployment can create the first operator from environment variables instead:

PASEO_BOOTSTRAP_ORGANIZATION=My organization
PASEO_BOOTSTRAP_OWNER_EMAIL=me@example.com
PASEO_BOOTSTRAP_OWNER_PASSWORD=replace-with-a-temporary-password

The password must be at least 12 characters. Sign in once, replace it in the dashboard, then remove PASEO_BOOTSTRAP_OWNER_PASSWORD. Hub keeps the account and organization.

Docker Compose

The repository contains Hub and PostgreSQL as one Compose stack:

git clone https://github.com/getpaseo/hub.git
cd hub
cp .env.example .env
docker compose up -d

Open http://localhost:3000 and complete browser setup. For a public deployment, set PASEO_HUB_APP_URL and any reverse-proxy settings in .env before starting the stack.

The stack publishes Hub on port 3000 and stores PostgreSQL data in a named volume. The Hub image is ghcr.io/getpaseo/hub:latest.

HTTPS with Caddy

Compose serves plain HTTP on port 3000. Run Caddy on the same host to terminate TLS:

hub.example.com {
  reverse_proxy 127.0.0.1:3000
}

Point hub.example.com at the host and open ports 80 and 443. Caddy obtains and renews the certificate.

Then set in .env:

PASEO_HUB_APP_URL=https://hub.example.com
PASEO_HUB_TRUSTED_CLIENT_IP_HEADER=x-forwarded-for

To keep port 3000 off the public interface, change the hub port in compose.yml to "127.0.0.1:3000:3000".

Fly

Clone the repository and create an app and database under names you control:

git clone https://github.com/getpaseo/hub.git
cd hub
fly apps create your-hub
fly postgres create --name your-hub-db
fly postgres attach your-hub-db -a your-hub

Deploy the Dockerfile and give Hub its public origin:

fly deploy -a your-hub \
  -e PASEO_HUB_APP_URL=https://your-hub.fly.dev

Open that address and complete browser setup, or set the bootstrap environment before deploying.

Keep one machine running. Hub holds Slack Socket Mode and Discord gateway connections and dispatches events to daemons, so a stopped machine misses events.

Upgrades

Pull the new image or source and deploy it. Migrations are forward-only. Back up the embedded data directory or PostgreSQL database first; it contains accounts, app credentials, configuration revisions, connections, and execution history.