Configuration
whiz.pub uses a three-tier configuration model. Secrets live in environment variables, application defaults are defined in a YAML file, and runtime settings are stored in the database.
Overview
| Source | Contains | When used |
|---|---|---|
.env |
Secrets and infrastructure settings | Always (read from environment) |
whiz.yaml |
Application defaults (domain, limits, etc.) | First startup only (seeds the DB) |
DB settings table |
All runtime configuration | Every request (authoritative) |
On first startup, values from whiz.yaml (or hardcoded defaults if the file is absent) are written into the database settings table. After that, the database is the single source of truth. Changes made in the admin panel at /admin/config take effect immediately.
Setup
cp .env.example .env
cp whiz.yaml.example whiz.yaml
Edit .env with your database credentials and any optional service keys. Edit whiz.yaml only if you need to change defaults before first startup.
Environment Variables (.env)
These are read from the process environment. They are never stored in the database.
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
Yes | -- | PostgreSQL connection string |
PORT |
No | 8080 |
HTTP listen port |
WHIZ_CONFIG |
No | ./whiz.yaml |
Path to the app config file |
PLUNK_API_URL |
No | -- | Plunk transactional email API URL |
PLUNK_SECRET_KEY |
No | -- | Plunk API secret key |
S3_ENDPOINT |
No | -- | S3/R2 endpoint for asset storage |
S3_REGION |
No | auto |
S3/R2 region |
S3_BUCKET |
No | -- | S3/R2 bucket name |
S3_ACCESS_KEY |
No | -- | S3/R2 access key |
S3_SECRET_KEY |
No | -- | S3/R2 secret key |
ASSETS_CDN_URL |
No | -- | Public CDN URL (e.g. https://cdn.whiz.pub) |
CUSTOM_DOMAIN_CNAME_TARGET |
No | proxy.<base_domain> |
Initial custom-domain CNAME target seed |
If PLUNK_SECRET_KEY is empty, transactional emails are logged to stdout instead of sent. This is useful during local development.
If the S3_* variables are not set, favicon upload is disabled.
App Config (whiz.yaml)
This file is read once on first startup to seed the database. After seeding, changes to whiz.yaml have no effect -- use the admin panel instead.
| Key | Default | Description |
|---|---|---|
base_domain |
localhost:8080 |
Platform base domain |
site_name |
whiz.pub |
Display name for branding |
custom_domain_cname_target |
empty | CNAME target shown to users for custom domains. Empty uses proxy.<base_domain>. |
session_ttl |
720h |
Session duration (Go duration format) |
max_title_length |
200 |
Max post title characters |
max_content_bytes |
102400 |
Max post content size in bytes (100 KB) |
max_tag_length |
50 |
Max characters per tag |
max_tags |
10 |
Max tags per post |
summary_length |
200 |
Auto-summary truncation length |
default_page_size |
20 |
Default pagination size |
max_page_size |
100 |
Maximum pagination size |
cache_max_age |
60 |
Cache-Control max-age in seconds |
body_limit |
4194304 |
HTTP request body limit in bytes (4 MB) |
from_name |
whiz.pub |
Sender name for transactional emails |
from_email |
[email protected] |
Sender email address |
Example whiz.yaml
base_domain: whiz.pub
site_name: whiz.pub
session_ttl: 720h
max_title_length: 200
max_content_bytes: 102400
max_tag_length: 50
max_tags: 10
summary_length: 200
default_page_size: 20
max_page_size: 100
cache_max_age: 60
body_limit: 4194304
from_name: whiz.pub
from_email: [email protected]
Database Settings
After first startup, all configuration lives in the settings table in PostgreSQL. This is the authoritative source for every request.
Admin Panel
The admin panel at /admin/config provides a live editor for all settings. Changes take effect immediately without a server restart.
How it works
- On first startup, whiz reads
whiz.yamland inserts each key-value pair into thesettingstable. - If a key already exists in the database, it is not overwritten.
- On every request, the server reads settings from the database (with caching).
- The admin panel reads and writes directly to the
settingstable.
This means you can safely redeploy without worrying about config drift -- the database always wins.