AlphornAlphorn Docs

Self-Hosting

Deploy Alphorn on your own infrastructure.

Alphorn is fully open source (AGPL-3.0-or-later) and designed to be self-hosted. You need a PostgreSQL database — that's the only external dependency.

The fastest way to get Alphorn running. The repository includes a ready-to-use docker-compose.yml — refer to it for the latest configuration.

Here's a minimal example:

docker-compose.yml
services:
  alphorn:
    image: ghcr.io/alphorn-dev/alphorn:latest
    ports:
      - "3000:3000"
    environment:
      # PostgreSQL connection string
      DATABASE_URL: postgres://alphorn:secret@db:5432/alphorn
      # Generate with: openssl rand -base64 32
      BETTER_AUTH_SECRET: your-secret-key
      # Public URL where Alphorn will be accessible
      BETTER_AUTH_URL: http://localhost:3000
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:18
    environment:
      POSTGRES_USER: alphorn
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: alphorn
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U alphorn"]

volumes:
  pgdata:
docker compose up -d

Alphorn is available at http://localhost:3000.

Podman

Podman is a drop-in replacement for Docker that runs rootless by default. The same compose file works with podman-compose or Podman's built-in podman compose:

podman compose up -d

Or run the containers individually:

# Create a pod so containers can communicate
podman pod create --name alphorn -p 3000:3000

# Start PostgreSQL
podman run -d --pod alphorn --name alphorn-db \
  -e POSTGRES_USER=alphorn \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=alphorn \
  -v pgdata:/var/lib/postgresql/data \
  postgres:18

# Start Alphorn
podman run -d --pod alphorn --name alphorn-app \
  -e DATABASE_URL=postgres://alphorn:secret@localhost:5432/alphorn \
  -e BETTER_AUTH_SECRET=your-secret-key \
  -e BETTER_AUTH_URL=http://localhost:3000 \
  ghcr.io/alphorn-dev/alphorn:latest

Alphorn is available at http://localhost:3000.

Running from Source

Clone the repository and run directly:

git clone https://github.com/alphorn-dev/alphorn.git
cd alphorn/app
pnpm install
pnpm build
pnpm start

Make sure you have a PostgreSQL instance running and set the required environment variables listed below.

Environment Variables

For the full list of environment variables, see the .env.example in the repository.

Required

VariableDescription
DATABASE_URLPostgreSQL connection string
BETTER_AUTH_SECRETSecret key for session signing — generate with openssl rand -base64 32
BETTER_AUTH_URLPublic URL of your Alphorn instance

SSO / OAuth (optional)

Alphorn supports social login and enterprise SSO. Set the relevant environment variables to enable a provider — if the variables are absent, the provider is simply not shown on the login page.

GitHub

VariableDescription
GITHUB_CLIENT_IDOAuth App Client ID
GITHUB_CLIENT_SECRETOAuth App Client Secret

Create an OAuth App at GitHub → Settings → Developer settings → OAuth Apps. Set the callback URL to {BETTER_AUTH_URL}/api/auth/callback/github.

Google

VariableDescription
GOOGLE_CLIENT_IDOAuth Client ID
GOOGLE_CLIENT_SECRETOAuth Client Secret

Create credentials at Google Cloud Console → APIs & Services → Credentials → OAuth client ID (Web application). Add {BETTER_AUTH_URL}/api/auth/callback/google as an authorized redirect URI.

Microsoft

VariableDescription
MICROSOFT_CLIENT_IDApplication (client) ID
MICROSOFT_CLIENT_SECRETClient secret value
MICROSOFT_TENANT_IDTenant ID — use common for any Microsoft account, organizations for work/school only, consumers for personal only, or a specific tenant GUID (default: common)

Register an app in Azure Portal → App registrations. Under Redirect URIs, add a Web URI: {BETTER_AUTH_URL}/api/auth/oauth2/callback/microsoft-entra-id.

Generic OIDC (Keycloak, Okta, Azure AD, etc.)

Connect any OIDC-compliant identity provider.

VariableRequiredDescription
OIDC_CLIENT_IDYesOIDC Client ID (enables the provider)
OIDC_CLIENT_SECRETYesOIDC Client Secret
OIDC_DISCOVERY_URLRecommendedOIDC discovery endpoint (auto-configures URLs below)
OIDC_AUTHORIZATION_URLNoManual authorization endpoint (if not using discovery)
OIDC_TOKEN_URLNoManual token endpoint (if not using discovery)
OIDC_USERINFO_URLNoManual userinfo endpoint (if not using discovery)
OIDC_PROVIDER_IDNoCustom provider identifier (default: custom-oidc)
OIDC_PROVIDER_NAMENoDisplay name on the login page (default: SSO)
OIDC_SCOPESNoSpace-separated scopes (default: openid profile email)
OIDC_PKCENoEnable PKCE (default: false)

Architecture

Alphorn runs as a single process with two roles:

  • Web — Serves the dashboard and API
  • Worker — Processes notification delivery queue

Both run in the same container/process by default. For high-throughput deployments, you can scale them independently behind a load balancer.

Database

Alphorn uses PostgreSQL exclusively — no Redis, no MongoDB, no additional infrastructure. Database migrations run automatically on startup. All configuration and message history lives in the database — back it up regularly.

Supported versions

  • PostgreSQL 14+

Updating

Pull the latest image and restart:

# Docker
docker compose pull
docker compose up -d

# Podman
podman compose pull
podman compose up -d

Database migrations apply automatically.

On this page