Skip to content

Environment Variables

club is configured primarily through environment variables. Every setting can be controlled via an environment variable, and environment variables always take precedence over values in the YAML config file.

Priority order: Environment variable > YAML config file > Default value

Server

VariableRequiredDefaultDescription
SERVER_URLYesPublic URL of the club server
HOSTNo0.0.0.0IP address to bind the HTTP server to
LISTEN_PORTNo8080Port the server listens on inside the container
LOG_LEVELNoinfoLog verbosity

SERVER_URL

The public URL where clients will reach the server. Used to construct archive_url in API responses, upload redirect URLs, and the implicitly-trusted Origin for browser requests.

Terminal window
SERVER_URL=https://packages.example.com

HOST

The IP address to bind the HTTP listener to.

Terminal window
HOST=0.0.0.0 # Listen on all interfaces (default)
HOST=127.0.0.1 # Localhost only (when behind a reverse proxy on the same machine)

LISTEN_PORT

The port the server listens on inside the container (or host, for a from-source install).

Terminal window
LISTEN_PORT=8080 # Default
LISTEN_PORT=3000 # Custom port

LOG_LEVEL

Controls log verbosity. Valid values: debug, info, warning, error.

Terminal window
LOG_LEVEL=info # Default: normal operation
LOG_LEVEL=debug # Verbose logging for development/debugging
LOG_LEVEL=warning # Quiet mode, only warnings and errors

Authentication and sessions

VariableRequiredDefaultDescription
JWT_SECRETYesHMAC secret used by the auth subsystem (>= 32 chars). Name is historical — sessions themselves are opaque tokens, not JWTs.
SESSION_TTL_HOURSNo1Session token sliding time-to-live in hours
TOKEN_EXPIRY_DAYSNo365Default API token expiry in days
BCRYPT_COSTNo12bcrypt hashing cost factor (10-14 recommended)
SIGNUP_ENABLEDNofalseEnable /signup and public POST /api/auth/signup
TRUST_PROXYNofalseTrust X-Forwarded-Proto / X-Forwarded-For headers
ALLOWED_ORIGINSNoCSV of extra browser origins permitted on public state-changing endpoints

JWT_SECRET

HMAC secret used by the auth subsystem. Must be at least 32 characters. (The name is historical — session tokens themselves are opaque values stored in the database, not JSON Web Tokens.)

Terminal window
# Generate a secure secret
JWT_SECRET=$(openssl rand -hex 32)

SESSION_TTL_HOURS

How long web UI session tokens remain valid, in hours.

Terminal window
SESSION_TTL_HOURS=1 # Default: 1 hour
SESSION_TTL_HOURS=8 # Longer sessions for internal use

TOKEN_EXPIRY_DAYS

Default expiry for newly created API tokens, in days. Users can override this per-token.

Terminal window
TOKEN_EXPIRY_DAYS=365 # Default: 1 year
TOKEN_EXPIRY_DAYS=90 # Shorter expiry for tighter security

BCRYPT_COST

The bcrypt cost factor for password hashing. Higher values are more secure but slower.

Terminal window
BCRYPT_COST=12 # Default: good balance of security and speed
BCRYPT_COST=14 # Higher security, ~4x slower than 12
BCRYPT_COST=10 # Faster, acceptable for development

SIGNUP_ENABLED

When true, exposes the /signup page and POST /api/auth/signup endpoint so anyone can self-register. New signups are created with the member role so they can publish immediately. Default: false (closed / invite-only).

Terminal window
SIGNUP_ENABLED=true

TRUST_PROXY

When true, the server honours X-Forwarded-Proto (to decide whether to set the Secure attribute on session cookies) and X-Forwarded-For (to record the real client IP in audit logs). Enable only when club is behind a reverse proxy that strips any client-supplied copies of these headers.

Terminal window
TRUST_PROXY=true

See Trusting your proxy for the full rationale.

ALLOWED_ORIGINS

Comma-separated list of additional browser origins allowed to POST to public, unauthenticated endpoints (/api/auth/login, /api/auth/signup, /api/setup/*). SERVER_URL is always trusted implicitly.

Terminal window
ALLOWED_ORIGINS=https://www.packages.example.com,https://packages.internal.example.com

Database (Metadata Store)

VariableRequiredDefaultDescription
DB_BACKENDNosqliteDatabase backend: sqlite or postgres
SQLITE_PATHNo/data/club.dbPath to SQLite database file
POSTGRES_URLConditionalPostgreSQL connection URL (required when DB_BACKEND=postgres)
Terminal window
DB_BACKEND=sqlite # Default: zero-dependency, great for small/medium deployments
DB_BACKEND=postgres # Larger deployments; requires POSTGRES_URL

SQLITE_PATH

Path to the SQLite database file. Only used when DB_BACKEND=sqlite.

Terminal window
SQLITE_PATH=/data/club.db # Default (Docker)
SQLITE_PATH=/var/lib/club/club.db # Custom path

POSTGRES_URL

Standard PostgreSQL connection URL. Required when DB_BACKEND=postgres.

Terminal window
POSTGRES_URL=postgres://club:secret@localhost:5432/club
POSTGRES_URL=postgres://club:secret@db.example.com:5432/club?sslmode=require

Blob Storage

VariableRequiredDefaultDescription
BLOB_BACKENDNofilesystemfilesystem, s3, or gcs
BLOB_PATHNo/data/packagesRoot directory for filesystem-backed storage
S3_BUCKETConditionalS3 bucket name (required for s3)
S3_REGIONConditionalS3 region (required for s3)
S3_ACCESS_KEYConditionalS3 access key ID (required for s3)
S3_SECRET_KEYConditionalS3 secret access key (required for s3)
S3_ENDPOINTOptionalS3-compatible endpoint (MinIO, R2, Spaces, B2, GCS interop)
GCS_BUCKETConditionalGCS bucket name (required for gcs)
GCS_CREDENTIALS_FILEOptionalPath to service-account JSON
GCS_CREDENTIALS_JSONOptionalInline service-account JSON

BLOB_BACKEND

Where to store package .tar.gz archives.

Terminal window
BLOB_BACKEND=filesystem # Default: local disk
BLOB_BACKEND=s3 # AWS S3 / R2 / MinIO / Spaces / B2 / GCS S3-interop
BLOB_BACKEND=gcs # Native Google Cloud Storage (service account / ADC)

BLOB_PATH

Root directory for package tarballs when BLOB_BACKEND=filesystem.

Terminal window
BLOB_PATH=/data/packages # Default (Docker)

S3 Configuration

S3_BUCKET, S3_REGION, S3_ACCESS_KEY, S3_SECRET_KEY are required when BLOB_BACKEND=s3. S3_ENDPOINT is optional for AWS but required for anything else.

Terminal window
# AWS S3
BLOB_BACKEND=s3
S3_BUCKET=club-packages
S3_REGION=us-east-1
S3_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE
S3_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# MinIO or other S3-compatible (Cloudflare R2, DO Spaces, Backblaze B2, GCS interop)
S3_ENDPOINT=http://minio:9000

See Docker with S3 storage for provider-specific guidance.

GCS Configuration

GCS_BUCKET is required when BLOB_BACKEND=gcs. Auth priority: GCS_CREDENTIALS_FILE > GCS_CREDENTIALS_JSON > Application Default Credentials.

Terminal window
BLOB_BACKEND=gcs
GCS_BUCKET=my-project.appspot.com
GCS_CREDENTIALS_FILE=/secrets/sa.json
# or:
# GCS_CREDENTIALS_JSON='{"type":"service_account",...}'
# or: leave both unset to use ADC (GCE/GKE/Cloud Run metadata server)

VariableRequiredDefaultDescription
SEARCH_BACKENDNosqlitesqlite (FTS5) or meilisearch
MEILISEARCH_URLConditionalMeilisearch URL (required when meilisearch)
MEILISEARCH_KEYConditionalMeilisearch API key (required when meilisearch)
Terminal window
SEARCH_BACKEND=sqlite # Default: SQLite FTS5, zero dependencies
SEARCH_BACKEND=meilisearch # Advanced search features or very large catalogs
MEILISEARCH_URL=http://meilisearch:7700
MEILISEARCH_KEY=your-meilisearch-api-key

Upload

VariableRequiredDefaultDescription
TEMP_DIRNo/tmp/club-uploadsTemporary directory for upload processing
MAX_UPLOAD_BYTESNo104857600Maximum tarball upload size in bytes (100 MiB)
DARTDOC_PATHNo/data/docsOutput directory for generated dartdoc
Terminal window
MAX_UPLOAD_BYTES=104857600 # Default: 100 MiB
MAX_UPLOAD_BYTES=524288000 # 500 MiB for large packages
MAX_UPLOAD_BYTES=10485760 # 10 MiB for strict limits

Scoring (pana Analysis)

Scoring is managed entirely from the admin UI — no environment variables needed. Go to Admin > Settings > Scoring to download a Flutter SDK and enable scoring. In Docker, the Flutter SDK and pub cache live under /data/sdks and /data/caches/pub-cache. See the package scoring guide for details.


Static files

VariableRequiredDefaultDescription
STATIC_FILES_PATHNoauto-detectPath to the SvelteKit static build output

Auto-detection probes, in order:

  1. /app/static/web (Docker default)
  2. packages/club_web/build (local dev, from repo root)

Override only if neither default matches your layout.


Config file

VariableRequiredDefaultDescription
CONFIGNo/etc/club/config.yamlPath to an optional YAML config file
Terminal window
CONFIG=/etc/club/config.yaml # Explicit path

If unset, club checks for /etc/club/config.yaml; if the file doesn’t exist, YAML loading is simply skipped. See YAML Config File for the file format.


Admin account

There are no ADMIN_EMAIL / ADMIN_PASSWORD environment variables. On first boot, club prints a one-time setup code to the server logs and exposes a web wizard at /setup. Visit that URL, paste the code, and create the initial admin account through the browser.

[INFO] Setup code: XXXX-XXXX-XXXX-XXXX
[INFO] Finish setup at: https://packages.example.com/setup

Once an admin exists, the setup wizard closes and the code is no longer valid.


Validation

The server validates configuration at startup and fails fast with a clear error message if anything is wrong:

RuleError Message
JWT_SECRET not setJWT_SECRET is required.
JWT_SECRET < 32 charsJWT_SECRET must be at least 32 characters.
DB_BACKEND=postgres without URLPOSTGRES_URL must be set when DB_BACKEND=postgres.
BLOB_BACKEND=s3 without bucket/keysS3_ACCESS_KEY and S3_SECRET_KEY are required when BLOB_BACKEND=s3.
BLOB_BACKEND=gcs without bucketGCS_BUCKET is required when BLOB_BACKEND=gcs.
SEARCH_BACKEND=meilisearch without URLMEILISEARCH_URL must be set when SEARCH_BACKEND=meilisearch.

Quick Reference by Profile

Minimal (Development)

Terminal window
SERVER_URL=http://localhost:8080
JWT_SECRET=dev-secret-at-least-32-characters-long

Finish admin setup via the one-time code printed to the logs.

Docker Default (SQLite + Filesystem)

Terminal window
SERVER_URL=https://packages.example.com
JWT_SECRET=$(openssl rand -hex 32)
TRUST_PROXY=true # when behind a reverse proxy

Production (PostgreSQL + S3)

Terminal window
SERVER_URL=https://packages.example.com
JWT_SECRET=$(openssl rand -hex 32)
TRUST_PROXY=true
DB_BACKEND=postgres
POSTGRES_URL=postgres://club:secret@db.example.com:5432/club
BLOB_BACKEND=s3
S3_BUCKET=club-packages
S3_REGION=us-east-1
S3_ACCESS_KEY=AKIA...
S3_SECRET_KEY=wJalrXUtnFEMI...