Configuration
Gooseplicant has two kinds of configuration, on purpose. Deployment settings (secrets, URLs, mail transport) come from the environment and are set by whoever runs it. Workspace settings (stages, sites, templates, retention, modules) live in the database and HR edits them in the app, without a redeploy.
Node.js and Docker#
Environment variables, validated at startup. Every problem is listed by name and the process exits before opening a port. The kit's apps/node/.env.example has the same list.
| Variable | Default | Notes |
|---|---|---|
PUBLIC_URL | required | Public origin, e.g. https://ats.example.com. Used for links in emails and the CSRF origin check. |
INGEST_SECRET | required | At least 32 characters. Shared with the website that posts applications. |
PROXY_SECRET | required with AUTH_MODE=proxy | At least 16 characters. Your auth proxy must send it on every request it forwards. |
BASE_PATH | /ats | UI at ${BASE_PATH}/, API at ${BASE_PATH}/api, intake at ${BASE_PATH}/ingest. |
PORT / HOST | 3000 / 0.0.0.0 | Use HOST=127.0.0.1 when the proxy runs on the same machine. |
INGEST_PORT | off | Optional intake-only listener: serves only ${BASE_PATH}/ingest and ${BASE_PATH}/api/health, everything else is a 404. Must differ from PORT. See Public intake, private app. |
INGEST_HOST | HOST | Interface for the intake-only listener. |
MAIN_INGEST | true | false: PORT answers 404 for ${BASE_PATH}/ingest, so applications arrive only on INGEST_PORT (required). |
DATA_DIR | ./data | Holds ats.db (SQLite, WAL mode) and files/. The Docker image sets /data. |
BOOTSTRAP_ADMINS | empty | Comma-separated emails that are always admins, even on an empty database. |
AUTH_MODE | proxy | proxy, or dev for local development (requires NODE_ENV=development; signs everyone in as DEV_USER_EMAIL). |
PROXY_EMAIL_HEADER | x-forwarded-email | Header with the signed-in user's email. Authelia: remote-email. |
PROXY_NAME_HEADER | none | Optional display-name header, e.g. remote-name. |
PROXY_SECRET_HEADER | x-ats-proxy-secret | Header that carries PROXY_SECRET. |
TRUST_PROXY | false | true: audit-log IP from the right-most X-Forwarded-For entry. |
MAIL_FROM + SMTP_URL | none | SMTP mail, e.g. smtps://user:pass@smtp.example.com:465. MAIL_FROM is required with SMTP_URL. |
GRAPH_TENANT_ID, GRAPH_CLIENT_ID, GRAPH_CLIENT_SECRET, GRAPH_MAILBOX | none | Microsoft Graph instead of SMTP: set all four or none, and not together with SMTP_URL. |
MAX_FILE_BYTES | 10485760 | Maximum size per uploaded file (10 MiB). For imports, the source email or PDF may be three times that, and one import request four times plus 1 MiB. |
EDITION | full | full: the Gooseplicant HR app at ${BASE_PATH}/, with Gosling alongside at ${BASE_PATH}/lite/. lite: Gosling only; ${BASE_PATH}/ redirects to /lite/, full-only API routes answer 404 not_in_edition, only the audit and retention modules run. Switching back to full keeps all data. See Gosling. |
UI_DIST | packages/ui/dist | Where the built web app lives. |
NODE_ENV | none | Anything other than development gives JSON-line logs. The Docker image sets production. |
DEV_USER_EMAIL | admin@example.com | Only with AUTH_MODE=dev. |
SEED_ADMIN_EMAIL | none | Admin created by npm run seed in proxy mode (demo data only). |
Without SMTP_URL or the Graph variables, Gooseplicant runs without sending mail. To keep the app on your own network and publish only the intake, see Public intake, private app.
Cloudflare#
Bindings and [vars] go in apps/cloudflare/wrangler.toml; secrets go in with npx wrangler secret put NAME. Invalid configuration is reported by variable name (never by value) in the Worker logs, and every request gets a generic 500 until it is fixed.
| Name | Kind | Notes |
|---|---|---|
DB | D1 binding | The database (wrangler d1 create ats). |
FILES | R2 binding | Uploaded files (bucket ats-files). |
ASSETS | assets binding | The prebuilt web app, ../../packages/ui/dist. |
PUBLIC_URL | var | Public origin for links and the CSRF origin check. |
BASE_PATH | var | /ats; must match the route. |
ACCESS_TEAM_DOMAIN, ACCESS_AUD | var | Your Zero Trust team domain and the Access application's AUD tag. Required outside local dev. |
BOOTSTRAP_ADMINS | var | Comma-separated emails that are always admins. |
MAIL_FROM, GRAPH_TENANT_ID, GRAPH_CLIENT_ID, GRAPH_MAILBOX | var | Optional Microsoft Graph mail: an app registration with Mail.Send, ideally restricted with an application access policy. |
MAX_FILE_BYTES | var | Optional; default 10 MiB per file (an import's source email or PDF may be three times that). |
EDITION | var | full (default in the shipped wrangler.toml): the HR app with Gosling alongside at /lite/. lite: Gosling only, as described in Gosling. Data is the same either way. |
INGEST_SECRET | secret | At least 32 characters. |
GRAPH_CLIENT_SECRET | secret | Only with Graph mail. |
ENVIRONMENT, DEV_USER_EMAIL | .dev.vars only | Local development identity instead of Access. Never set ENVIRONMENT in production. |
The Worker also needs a routes entry for your hostname and a Cron Trigger (crons = ["0 * * * *"], hourly), both already in the shipped wrangler.toml.
In the app: Settings#
Admins change these in Settings; they apply immediately and are stored in the database. A fresh install starts with sensible defaults, so nothing here is required before the first application arrives.
| Tab | What it controls |
|---|---|
| General | Company name (used in email templates) and theme. |
| Pipeline stages | Stage names, colors and kind (open, hired, rejected). Defaults: New, Screening, Interview, Offer, Hired, Not moving forward. |
| Sites | Your locations or brands, with aliases (Also known as) that help the importer sort old applications. New site ids from submissions are added automatically. |
| Import | Bring in past applications from .msg, .eml and PDF files. See Import old applications. |
| Email templates | Subject and body with {{firstName}}, {{lastName}}, {{position}}, {{siteName}}, {{companyName}} placeholders. |
| Modules | Turn optional features on or off and tune them (below). |
| Sensitive fields | Answer keys to mask, exact or prefix*. Default: convicted*, work_auth*. |
| Users & access | People, their role (viewer, recruiter, admin) and the sites they may see. |
| Audit log | Browse the compliance trail. |
Modules#
| Module | Default | Settings |
|---|---|---|
audit | on | Keep entries for keepDays (default 730, minimum 30), then prune. |
retention | on | Delete candidates with no activity for months (24), or talentPoolMonths (36) if they joined the talent pool; keepHired (on) never auto-deletes people who were hired. |
talentPool | on | requireConsent (on): only recommend people who opted in. maxAgeMonths (24): ignore older applicants. |
candidateEmail | off | Template sent automatically on receipt (default: "Application received"), and templates sent when an application enters a stage. Needs mail configured. |
hrNotify | off | Email HR about new applications: default recipients plus per-site overrides. Needs mail configured. |
In EDITION=lite only audit and retention run; the others stay off whatever is stored here. Gosling has its own, smaller Admin area: Locations, Users, General, and Retention & audit.
Per-person preferences, such as row density and last-used inbox filters, are saved for each user. Light or dark is chosen per browser.