Skip to main content
Anchor can be configured using environment variables in your docker-compose.yml file. Most settings are optional with sensible defaults.

Configuration Overview

Anchor uses a minimal configuration approach:
  • Most environment variables are optional
  • Defaults work out of the box for development and testing
  • Only production deployments need additional configuration
  • Some settings can be managed via the admin panel UI

Environment Variables

Application Settings

APP_URL
string
default:"http://localhost:3000"
Base URL where Anchor is served. Required for OIDC authentication and proper redirects.Examples:
  • http://localhost:3000 (development)
  • https://notes.example.com (production)
Set this to your public URL when using a reverse proxy.
JWT_SECRET
string
default:"auto-generated"
Secret key for signing authentication tokens. If not provided, a random secret is generated and persisted in /data/.jwt_secret.Recommended: Let Anchor auto-generate this on first run.
# Generate a secure secret manually (optional)
openssl rand -hex 32
Changing JWT_SECRET will invalidate all existing user sessions.
USER_SIGNUP
string
default:"(not set)"
Controls user registration. If not set, admins can control this via the admin panel.Options:
  • enabled - Anyone can register
  • disabled - Registration is closed
  • review - Registrations require admin approval
environment:
  - USER_SIGNUP=review
When not set, admins can dynamically change this setting through the admin panel UI.

Database Settings

PG_HOST
string
default:"(empty)"
PostgreSQL server hostname. Leave empty to use embedded PostgreSQL.
# Embedded (default)
environment:
  - PG_HOST=

# External database
environment:
  - PG_HOST=postgres.example.com
PG_PORT
number
default:"5432"
PostgreSQL server port.
environment:
  - PG_PORT=5432
PG_USER
string
default:"anchor"
PostgreSQL username.
environment:
  - PG_USER=anchor
PG_PASSWORD
string
default:"password"
PostgreSQL password.
Change this from the default for production deployments!
environment:
  - PG_PASSWORD=strong-password-here
PG_DATABASE
string
default:"anchor"
PostgreSQL database name.
environment:
  - PG_DATABASE=anchor

OIDC Authentication

Anchor supports OpenID Connect (OIDC) for single sign-on. Learn more in the OIDC Authentication guide.
OIDC_ENABLED
boolean
default:"false"
Enable OIDC authentication.
environment:
  - OIDC_ENABLED=true
OIDC_PROVIDER_NAME
string
default:"OIDC Provider"
Display name shown on the login button.
environment:
  - OIDC_PROVIDER_NAME=Pocket ID
OIDC_ISSUER_URL
string
required
Base URL of your OIDC provider.
environment:
  - OIDC_ISSUER_URL=https://auth.example.com
OIDC_CLIENT_ID
string
required
OIDC client ID from your provider.
environment:
  - OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET
string
default:"(empty)"
OIDC client secret. Omit for public clients using PKCE.
# Confidential client (web only)
environment:
  - OIDC_CLIENT_SECRET=your-client-secret

# Public client (mobile app support)
environment:
  - OIDC_CLIENT_SECRET=
For mobile app support, configure your OIDC provider as a public client and omit this variable.
DISABLE_INTERNAL_AUTH
boolean
default:"false"
Hide the local username/password login form. Users can only sign in via OIDC.
environment:
  - DISABLE_INTERNAL_AUTH=true
Ensure OIDC is working before enabling this option, or you may lock yourself out.

Configuration Examples

Minimal Setup (Development)

docker-compose.yml
services:
  anchor:
    image: ghcr.io/zhfahim/anchor:latest
    ports:
      - "3000:3000"
    volumes:
      - anchor_data:/data

volumes:
  anchor_data:

Production with External Database

docker-compose.yml
services:
  anchor:
    image: ghcr.io/zhfahim/anchor:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - APP_URL=https://notes.example.com
      - JWT_SECRET=${JWT_SECRET}
      - PG_HOST=postgres
      - PG_PORT=5432
      - PG_USER=anchor
      - PG_PASSWORD=${PG_PASSWORD}
      - PG_DATABASE=anchor
      - USER_SIGNUP=review
    volumes:
      - anchor_data:/data

  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_USER=anchor
      - POSTGRES_PASSWORD=${PG_PASSWORD}
      - POSTGRES_DB=anchor
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  anchor_data:
  postgres_data:
Use a .env file to store sensitive values like JWT_SECRET and PG_PASSWORD.

Production with OIDC Authentication

docker-compose.yml
services:
  anchor:
    image: ghcr.io/zhfahim/anchor:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - APP_URL=https://notes.example.com
      - JWT_SECRET=${JWT_SECRET}
      - PG_HOST=postgres
      - PG_PASSWORD=${PG_PASSWORD}
      # OIDC Configuration
      - OIDC_ENABLED=true
      - OIDC_PROVIDER_NAME=Pocket ID
      - OIDC_ISSUER_URL=https://auth.example.com
      - OIDC_CLIENT_ID=${OIDC_CLIENT_ID}
      - OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}
      - DISABLE_INTERNAL_AUTH=false
      # User Management
      - USER_SIGNUP=review
    volumes:
      - anchor_data:/data

  postgres:
    image: postgres:16-alpine
    environment:
      - POSTGRES_USER=anchor
      - POSTGRES_PASSWORD=${PG_PASSWORD}
      - POSTGRES_DB=anchor
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  anchor_data:
  postgres_data:

OIDC-Only Mode (No Local Auth)

docker-compose.yml
services:
  anchor:
    image: ghcr.io/zhfahim/anchor:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - APP_URL=https://notes.example.com
      - OIDC_ENABLED=true
      - OIDC_PROVIDER_NAME=Corporate SSO
      - OIDC_ISSUER_URL=https://sso.company.com
      - OIDC_CLIENT_ID=${OIDC_CLIENT_ID}
      - OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}
      - DISABLE_INTERNAL_AUTH=true  # Hide local login
      - USER_SIGNUP=enabled  # Auto-create users on first OIDC login
    volumes:
      - anchor_data:/data

volumes:
  anchor_data:

Using .env Files

Store sensitive configuration in a .env file:
.env
JWT_SECRET=your-generated-secret-here
PG_PASSWORD=strong-database-password
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
Reference in docker-compose.yml:
docker-compose.yml
services:
  anchor:
    image: ghcr.io/zhfahim/anchor:latest
    env_file:
      - .env
    environment:
      - APP_URL=https://notes.example.com
      - PG_HOST=postgres
Add .env to your .gitignore to avoid committing secrets.

Admin Panel Configuration

Some settings can be managed through the admin panel UI:
  1. Navigate to the admin panel (admin users only)
  2. Go to Settings
  3. Configure:
    • User signup mode (if USER_SIGNUP env var is not set)
    • OIDC settings (if OIDC env vars are not all set)
    • System settings
Environment variables take precedence over admin panel settings. If you set USER_SIGNUP or OIDC variables, the admin panel cannot override them.

Viewing Current Configuration

Check which environment variables are active:
# View container environment
docker exec anchor env | grep -E "APP_URL|PG_|OIDC_|JWT_|USER_SIGNUP"

# Check logs for startup configuration
docker compose logs anchor | grep "\[anchor\]"

Next Steps

Database Options

Learn about embedded vs external PostgreSQL

OIDC Authentication

Set up single sign-on with OIDC

Build docs developers (and LLMs) love