Skip to content

Configuration reference

HappyView takes its configuration from three places. When one value is set in more than one, the first in this list wins:

  1. Instance settings, saved in the dashboard (mostly under System > General) or through PUT /admin/settings/{key}. Only the keys listed below work this way.
  2. The process environment. A variable set to an empty value still counts as set.
  3. happyview.toml, for the few variables a project file can supply, marked in the tables.

Anything none of them sets takes its default. Running happyview with no arguments (serving) also loads a .env file into the environment; happyview dev, test, check and types don’t.

VariableDefaultWhat it does
PUBLIC_URLrequiredThe URL the instance is reached at. Boot fails without it.
HOST0.0.0.0Address to listen on.
PORT3000Port to listen on. An unreadable value means 3000. happyview.toml: [dev] port, under dev only.
BASE_PATHnoneServe under a path prefix, such as /happyview. A trailing / is trimmed; / alone means none. A value that doesn’t start with / stops boot.
STATIC_DIRthe built-in dashboardServe the dashboard from this directory instead.
HAPPYVIEW_PROJECTnoneA project directory to build and serve at boot. A directory that doesn’t exist stops boot.
HAPPYVIEW_USER_AGENTHappyView/<version> (+<PUBLIC_URL>)The User-Agent on outbound requests.
APP_NAMEnoneYour app’s name, shown on OAuth consent screens and linked-repo pages. happyview.toml: [instance] app_name. Instance setting app_name.
LOGO_URI, TOS_URI, POLICY_URInoneLinks published in OAuth client metadata. Instance settings logo_uri, tos_uri, policy_uri; an uploaded logo wins over logo_uri.
CLIENT_URInoneclient_uri in OAuth client metadata. Instance setting client_uri.
RUST_LOGsee belowThe log filter.

RUST_LOG’s default depends on the command: happyview=debug,tower_http=debug,sqlx=warn when serving, happyview=info,tower_http=warn,sqlx=warn under dev, warn for check and types, error for test.

VariableDefaultWhat it does
DATABASE_URLrequiredsqlite://… or postgres://…. Boot fails without it.
DATABASE_BACKENDfrom the URLsqlite or postgres.
DATABASE_MAX_CONNECTIONS16 (SQLite), 32 (Postgres)The main connection pool’s size.
BACKFILL_DATABASE_MAX_CONNECTIONSsized from the backfill concurrency, at most 16 (SQLite) or 256 (Postgres)The backfill pool’s size. At least 1.
SQLITE_JOURNAL_SIZE_LIMIT67108864 (64 MiB)Largest size the WAL is trimmed to after a checkpoint. -1 means no limit.
SQLITE_SYNCHRONOUSNORMALNORMAL or FULL.
SQLITE_CHECKPOINT_INTERVAL_SECS60Seconds between WAL checkpoints. 0 turns them off.
SQLITE_WAL_CHECKPOINT_BYTES64 MiBWAL size that triggers a checkpoint early. 0 turns it off.
SQLITE_TMPDIR, then TMPDIRthe system’sWhere a scheduled VACUUM’s free-space check looks, as SQLite does.
RECORD_COMPRESSIONzstdzstd or none. Compresses record bodies on SQLite.
ZSTD_DICT_TRAIN_AT5000Records a collection needs before a compression dictionary is trained for it.
RECORD_COMPRESSION_INTERVAL_SECS600Seconds between compression passes.
VariableDefaultWhat it does
SESSION_SECRETnoneSigns the dashboard’s session cookie. Must be at least 32 bytes; generate one with openssl rand -base64 48. When it’s unset, too short, or the placeholder change-me-in-production, the instance still starts, but nobody can sign in to the dashboard, and the dashboard shows why.
TOKEN_ENCRYPTION_KEYnoneBase64 of exactly 32 bytes (openssl rand -base64 32). Encrypts stored OAuth tokens and keys. Without a valid one, app sign-in, spaces and service identity don’t work; an invalid value is logged and ignored.
SUPERADMIN_DIDnoneA DID given the superadmin privilege at every boot. A value that isn’t a DID stops boot; empty means unset. Once set, the first person to sign in is no longer given superadmin. happyview.toml: [instance] superadmin.
PLATFORM_API_KEY_HASHnoneThe SHA-256, as 64 hex characters, of the key a hosting platform uses for /admin/platform. See Platform.
DEFAULT_RATE_LIMIT_CAPACITY100Request budget for a new API client.
DEFAULT_RATE_LIMIT_REFILL_RATE2.0Requests per second a new API client’s budget refills by.
ATTESTATION_PRIVATE_KEYstored, else generatedA hex secp256k1 key for attestation signing.
ATTESTATION_KEY_IDdid:web:<PUBLIC_URL host>#attestation; did:web:localhost#attestation when ATTESTATION_PRIVATE_KEY is setThe key’s id in signatures.
ATTESTATION_SIG_TYPEgames.gamesgamesgamesgames.attestationThe signature’s $type.
VariableDefaultWhat it does
JETSTREAM_URLwss://jetstream1.us-east.bsky.networkThe Jetstream to follow.
JETSTREAM_PROTOCOLautoauto, v2 or v1. happyview.toml: [jetstream] protocol.
JETSTREAM_COMPRESSIONtruetrue or false (also 1/0, yes/no, on/off). happyview.toml: [jetstream] compression.
JETSTREAM_WORKERS8Records processed in parallel, 1 to 64.
RELAY_URLhttps://bsky.networkThe relay backfill asks which accounts hold a collection.
PLC_URLhttps://plc.directoryThe PLC directory DIDs are resolved through.
VariableDefaultWhat it does
BACKFILL_CONCURRENT_PDS10PDSes fetched from at once. Instance setting backfill_concurrent_pds.
BACKFILL_CONCURRENT_DIDS_PER_PDS3Accounts fetched at once from one PDS. Instance setting backfill_concurrent_dids_per_pds.
BACKFILL_CONCURRENT_RESOLUTION100DIDs resolved at once. Instance setting backfill_concurrent_resolution.
BACKFILL_RETENTION_DAYS28Days a finished backfill’s per-account detail is kept. 0 keeps it. Instance setting backfill_retention_days.
BACKFILL_DISCOVERY_WINDOW50000Units of work discovered ahead of fetching. A unit is one account under one collection.
BACKFILL_HOOK_CONCURRENCY4Record scripts run at once for one batch of a backfill, 1 to 32. A value outside the range is moved inside it.
BACKFILL_SOURCEcrawlcrawl fetches from each PDS, replay reads a Jetstream archive, and auto replays when the Jetstream has an archive and otherwise crawls.
BACKFILL_REPLAY_CONCURRENCY8Archive segments read at once, 1 to 64.
BACKFILL_REPLAY_DIR<temp>/happyview-replayWhere archive segments are kept while replaying.
BACKFILL_REPLAY_MARKER_TAIL_HOURS12How far back from the archive’s newest data a network replay reads account and sync markers. 0 reads the job’s whole range.
JETSTREAM_API_KEYnoneKey for the Jetstream archive replay reads.

The three concurrency settings take effect on the next backfill; the backfill connection pool is sized from the environment at boot.

VariableDefaultWhat it does
PLUGIN_DIR./pluginsWhere installed plugins are kept. Under dev, <project>/.happyview/plugins.
PLUGIN_CACHE_DIRplugin-cache beside a SQLite database; none on PostgresWhere compiled plugins are cached on disk, so a restart doesn’t recompile them. It must belong to the user HappyView runs as and be private to it, or the cache stays in memory.
PLUGIN_REGISTRY_URLhttps://api.happyproto.atThe plugin registry. Empty or off stops HappyView reading a registry.
HAPPYVIEW_DEFAULT_PLUGINSnonePlugins to install on the first boot whose value lists them, separated by commas.
PLUGIN_URLSnonePlugins to load from URLs at boot, as id|url|sha256:<hash>, separated by commas.
PLUGIN_<ID>_<NAME>noneA plugin’s secret, used when the instance holds none for that plugin. <ID> is the plugin’s id upper-cased, with every other character as _.
VariableDefaultWhat it does
SCRIPT_INSTRUCTION_LIMIT1000000Instructions a query, procedure, record or label script may run, from 1000 to 1000000000. Instance setting script_instruction_limit.
SCRIPT_WALL_CLOCK_SECONDS10Seconds a query, procedure, record or label script may run, from 1 to 300. Instance setting script_wall_clock_seconds.
HAPPYVIEW_SCRIPT_ENV_FILEnoneA .env-style file whose values are added to scripts’ ctx.env, re-read on every run. dev sets it to <project>/.env, test to <project>/.env.test.
JOB_WORKER_CONCURRENCY1Background jobs run at once, up to 32.
HOSTNAMEhappyviewNames this instance’s job worker in each job’s claimed_by.
HAPPYVIEW_INSTANCE_IDHOSTNAME, then the system’s hostname, then a random idNames this process in stored script metrics, trimmed and cut to 128 characters. Give each instance sharing a database its own.
SCRIPT_METRICS_ENABLEDtruetrue or false. Whether scripts’ timings are recorded for the Script performance page. Instance setting script_metrics_enabled.
FEATURE_SPACES_ENABLEDfalsetrue turns on spaces. Instance setting feature.spaces_enabled.

An out-of-range script limit in the environment is logged and the default is used; one saved as an instance setting is refused when saved. See Limits.

VariableDefaultWhat it does
EVENT_LOG_RETENTION_DAYS30Days event log entries, job logs and stored script metrics are kept. 0 keeps them. Instance setting event_log_retention_days.
DEAD_LETTER_RETENTION_DAYS30Days a resolved dead letter is kept. 0 keeps them. An unresolved one is never removed.
RECORD_TOMBSTONE_RETENTION_HOURS72Hours a deleted record’s tombstone is kept. 0 keeps them.
VERBOSE_EVENT_LOGGINGfalsetrue logs every record script run and skip. It writes a lot. Instance setting verbose_event_logging.
TELEMETRY_COLLECTOR_URLhttps://telemetry.happyview.dev/v1/snapshotWhere telemetry reports go, when it’s turned on.
TELEMETRY_MANAGED_BYnoneSet only by a hosting platform: it turns telemetry on and locks its settings. Lowercase letters, digits and -, at most 64 characters; anything else stops boot.
VariableDefaultWhat it does
HAPPYVIEW_DEV_BACKFILLfalseWhether dev backfills. Exactly true or false. happyview.toml: [dev] backfill.
HAPPYVIEW_WATCH_POLL_MSfile eventsPoll for changes every this many milliseconds, 50 to 60000, instead of using file events. For dev and test --watch.
HAPPYVIEW_NETWORKnoneWhich network dev is on. hpy happyview dev --network local sets it to local; any other value prints a warning that writes reach your real PDS.

happyview dev lists the defaults dev fills in.

These keys can be saved as instance settings, and then win over the environment. System > General in the dashboard edits most of them; PUT /admin/settings/{key} sets any of them, and DELETE returns a key to its environment value. Both need settings:manage.

SettingEnvironment variable
app_nameAPP_NAME
logo_uri, tos_uri, policy_uri, client_uriLOGO_URI, TOS_URI, POLICY_URI, CLIENT_URI
backfill_concurrent_pds, backfill_concurrent_dids_per_pds, backfill_concurrent_resolutionBACKFILL_CONCURRENT_*
backfill_retention_daysBACKFILL_RETENTION_DAYS
event_log_retention_daysEVENT_LOG_RETENTION_DAYS
script_instruction_limit, script_wall_clock_secondsSCRIPT_INSTRUCTION_LIMIT, SCRIPT_WALL_CLOCK_SECONDS
script_metrics_enabledSCRIPT_METRICS_ENABLED
verbose_event_loggingVERBOSE_EVENT_LOGGING
feature.spaces_enabledFEATURE_SPACES_ENABLED

GET /admin/settings lists every setting with where its value came from: database, env or project. The logo, the XRPC proxy, rate-limit costs and telemetry are also stored as settings, through their own endpoints and dashboard pages.

A project’s happyview.toml. Every table is optional, and an unknown key anywhere is an error reported with its line. Project structure explains how they’re used.

KeyTypeDefaultWhat it does
[happyview] versionstringnoneThe HappyView version hpy runs. A different running version only warns.
[instance] app_namestringnoneSupplies APP_NAME.
[instance] superadminDIDnoneSupplies SUPERADMIN_DID.
[interpreters]."<language>"{ did, name, channel | version }noneAn interpreter, by language id. channel is latest, beta or alpha; version pins an exact one. Exactly one of them.
[libraries]."<namespace>"{ did, name, channel | version }noneA library, by namespace, as for interpreters.
[dev] portinteger, 1 to 65535noneSupplies PORT under dev.
[dev] backfillbooleanfalseSupplies HAPPYVIEW_DEV_BACKFILL under dev.
[network_lexicons] includelist of NSIDsemptyNetwork lexicons to track.
[labels] subscribelist of DIDsemptyLabelers to subscribe to.
[jetstream] protocolauto, v2 or v1noneSupplies JETSTREAM_PROTOCOL.
[jetstream] compressionbooleannoneSupplies JETSTREAM_COMPRESSION.
[lexicons."<NSID>"] backfillbooleanfalseBackfill this record lexicon’s collection once.
[lexicons."<NSID>"] target_collectionNSIDnoneThe collection a query or procedure works on.
[lexicons."<NSID>"] actioncreate, update, delete or upsertupsertWhat a procedure without a script does.
[lexicons."<NSID>"] indexedbooleantruefalse stops indexing the collection, keeping what’s indexed.
[lexicons."<NSID>"] token_costintegerthe cost set for the lexicon’s typeHow much of an API client’s rate-limit budget one call to this endpoint uses.
[scripts."<trigger>"] descriptionstringnoneShown with the script in the dashboard.
[scripts."<trigger>"] outbound_xrpcslist of stringsemptyThe XRPC methods the script calls, recorded with it and listed by the admin API. A service auth call to a procedure script is refused when the list names any method other than the one called.
[modules."<name>"] languagestringrequiredrust.
[modules."<name>"] pathpathrequiredThe module’s crate, relative to the project and inside it.
[modules."<name>"] capabilitieslist of capabilitiesemptyWhat the module is granted.

A deploy ignores [happyview], [instance], [interpreters], [libraries], [dev] and [jetstream]; see Deploying.