Skip to content

All settings

Every setting the server reads. Where says where it may be set: any means the environment, the settings file or Admin > Settings; env means the environment only. Live settings saved on the settings page apply without a restart. Every setting also accepts NAME_FILE (see secrets in files).

A check in CI keeps this page in step with the server: a setting missing here fails the build.

General

PUBLIC_URL

The address people open, such as https://tasks.example.com. Single sign-on uses it for the callback address, and links the server makes (login links, sharing) use it. Without it, the server uses the address each request came in on. Default: none. Where: any.

ACCOUNT_DELETE_GRACE_DAYS

Days a deleted account can still be restored. After that, the account and everything it owns are removed for good. 0 removes at the next hourly check. Default: 7. Where: any, live.

REGISTRATION

Who may make their own account with a username and password:

  • open: anyone who can reach the server, from Create an account on the sign-in page.
  • invite: only people with an invite link an admin made (Admin > Users > Invite).
  • closed: nobody; admins add people. Invite links stop working.

Single sign-on keeps its own switch, OIDC_<NAME>_AUTO_CREATE. An invite link also lets a new provider account in when that switch is off. With LOCAL_LOGIN disabled, people sign up only through a provider. Admins can always add accounts. Default: invite. Where: any, live. See adding people.

SIGNUP_RATE_LIMIT

How many accounts one address may make by signing up in an hour; 0 turns the limit off. Tries that make no account (a taken name, a short password) do not count, and the ten tries a minute every sign-in and sign-up route allows still apply on top. Further sign-ups answer 429 signup_limited until the hour has passed. Behind a proxy, set TRUSTED_PROXIES so the limit counts people, not the proxy. Default: 5. Where: any, live.

TZ

The server's time zone (an IANA name such as Europe/Berlin), used for months in stats and for the server's own "today". It is also the time zone people's apps start out in; each person can pick their own under Settings. Default: UTC in the image, the system's elsewhere. Where: env.

Sign-in

AUTH_MODE

local: accounts and sign-in. none: no sign-in at all; everyone who reaches the server is the same single owner. Default: local. Where: env.

ADMIN_PASSWORD

The admin account's first password, used only when the account is created at the first start (12 characters or more). Without it a password is generated and printed once. Default: generated. Where: env.

LOCAL_LOGIN

enabled or disabled. disabled turns password sign-in off when everyone uses single sign-on: the sign-in page has no password form, and the server refuses passwords on every route (POST /auth/login, sign-up and password changes answer 403 local_login_disabled). Password sessions already open end at once; provider sessions go on. To get an admin back in, make a one-time link with punchlist admin login-link. Needs at least one provider. shown and hidden, the names before 0.2.1, still work as enabled and disabled. Default: enabled. Where: any, live.

OIDC_PROVIDERS

The identity providers to offer, comma separated: pocket,keycloak. Names are letters, digits and dashes; each gets the settings below with its name in capitals and dashes as underscores (pocket-id becomes OIDC_POCKET_ID_...). Needs AUTH_MODE=local. Default: none. Where: any. Guide: single sign-on.

Per provider: OIDC_<NAME>_...

Setting Default Meaning
OIDC_<NAME>_AUTHORITY required The issuer URL (where /.well-known/openid-configuration lives).
OIDC_<NAME>_CLIENT_ID required The client id registered for Punchlist.
OIDC_<NAME>_CLIENT_SECRET none The client secret. None: a public client. PKCE is always used.
OIDC_<NAME>_DISPLAY_NAME the name The sign-in button's label ("Continue with ...").
OIDC_<NAME>_SCOPES openid profile email (+ groups) groups is added when a group setting is used. Set this for providers without a groups scope.
OIDC_<NAME>_GROUPS_CLAIM groups The claim holding group names.
OIDC_<NAME>_USERNAME_CLAIM preferred_username Where a new account's username comes from (else the email's first part).
OIDC_<NAME>_REQUIRED_GROUPS none (everyone) Comma list; signing in needs at least one. Checked at every sign-in.
OIDC_<NAME>_AUTO_CREATE false Make an account at a first sign-in. Off: the person waits for an admin's approval.
OIDC_<NAME>_LINK_BY_EMAIL false Join a first sign-in to the one existing account with the same verified email.
OIDC_<NAME>_LINK_BY_USERNAME false true: a first sign-in joins the same-named plain user account with no link to this provider. all: admins too.
OIDC_<NAME>_USER_MAP none provideruser=punchlistuser,...: that provider user always signs into that account, moving an existing link.
OIDC_<NAME>_ICON the provider's favicon An https address or a file: the icon shown on the profile picture of people signed in through it.
OIDC_<NAME>_ROLE_MAP none group=role,... with roles user, admin, superadmin. The highest match wins at every sign-in; no match means user.
OIDC_<NAME>_GROUP_MAP none group=Server group,..., or * to mirror every provider group as a server group.
OIDC_<NAME>_SIGN_OUT false Signing out of Punchlist also ends the provider session. Register <PUBLIC_URL>/login as a post-logout redirect URI first.
OIDC_<NAME>_SESSION_HOURS 12 How long a session from this provider lasts (0 to 720) before the app goes back through the provider. 0: 30 days, like passwords.

Backups

BACKUP_SCHEDULE

How often the server writes a full snapshot: off, hourly, daily or weekly. The older name SNAPSHOT_SCHEDULE still works. Default: daily. Where: any, live.

SNAPSHOT_KEEP

How many snapshots to keep; older ones are deleted. At least 1. Default: 14. Where: any, live.

SNAPSHOT_DIR

Where snapshots go. Default: snapshots next to the SQLite file (/data/snapshots in the image). Where: env.

Database

DB_PROVIDER

sqlite or postgres (PostgreSQL 15 or later). Default: sqlite. Where: env.

DB_PATH

The SQLite file. Default: /data/punchlist.db in the image, ./data/punchlist.db elsewhere. Where: env.

DB_CONNECTION_STRING

The PostgreSQL connection string, in Npgsql's format: Host=db;Username=punchlist;Password=...;Database=punchlist. Required with DB_PROVIDER=postgres. Where: env.

DB_MIGRATE_ON_START

Upgrade the database schema when a newer version starts. Turn off when the database user may not change the schema, and run the upgrade yourself. Default: true. Where: env.

Files

ATTACHMENT_MAX_MB

The largest file someone may attach to a task, in megabytes. Bigger uploads are refused and stay on the device that added them. Default: 25. Where: any, live.

UPDATE_CHECK

Look for newer Punchlist releases: twice a day the server reads the latest release from GitLab (one request, from the server only; people's browsers never call out). When one is newer than the server or someone's Android app, the menu shows a notice with the release page. Turn it off to make no such request. Default: true. Where: any, live.

API_DOCS

Serve the description of the HTTP API: the OpenAPI document at /api/openapi/v1.json and a Swagger UI page at /api/docs to read it and try calls with an API key (see the HTTP API). Both are public, like the source code; they show what the API offers, never anyone's data. Turn it off and both answer 404. Default: true. Where: any, live.

ATTACHMENT_DIR

Where attached files are kept, one file per content hash. Back this folder up with the database. Files no task uses any more are removed 30 days after the last task let go of them. It is the folder that grows, so it can sit on other storage than the database: the image keeps it in its own volume, /files. Default: attachments next to the SQLite file; /files in the image. Where: env.

Telemetry

What the daily usage report holds, and what it never holds: privacy.

TELEMETRY

Send the anonymous daily usage report: one request a day from the server to the project's collector, with counts in ranges and switches, never names, titles, addresses or anything people wrote. Turn it off and nothing is sent. The admin settings page shows the report exactly as it would go. Default: true. Where: any, live.

TELEMETRY_URL

Where the report goes. Default: https://telemetry.killswitch10.com/api/public/v1/ping (it moves to the app's own domain at 1.0). Where: any, live.

DO_NOT_TRACK

1 or true turns the report off, like TELEMETRY=false, for those who set this convention across all their tools. Default: false. Where: environment.

Demo server

A public trial server that resets every night: see run a demo server.

DEMO_MODE

true makes this a demo server. It shows a banner (the nightly reset, that anyone can sign up, and the demo accounts) and forces, whatever else is set: REGISTRATION open, ACCOUNT_DELETE_GRACE_DAYS 0, ATTACHMENT_MAX_MB at most 2, TELEMETRY and UPDATE_CHECK off. The server makes no calls out of its own (no usage report, release check or Web Push; reminders still show on the device). Only the identity providers and log servers you set up still get calls. Every answer carries X-Robots-Tag: noindex, nofollow and the page a robots meta tag. Needs AUTH_MODE=local. Default: false. Where: env.

DEMO_ACCOUNTS

Pre-made accounts the banner shows with their passwords, so visitors can try sharing without inviting anyone: demo-sam:try-punchlist-sam,demo-alex:try-punchlist-alex. Each start makes them, or puts them back as plain users with these passwords. Wrong guesses lock nobody out, and nobody can change their password. The names must match the accounts in the seed the nightly reset loads (the image's seed has demo-sam, demo-alex and demo-jordan); passwords need 12 characters or more. Needs DEMO_MODE. Default: none. Where: env.

DEMO_RESET_TIME

When the nightly reset runs (HH:mm, server time), as the banner says it. The reset itself is the job you schedule (see run a demo server); keep the two the same. Default: 04:00. Where: env.

Network

TRUSTED_PROXIES

The proxies allowed to set X-Forwarded-For and X-Forwarded-Proto: addresses or CIDR ranges, comma separated. Default: loopback and the private ranges (10/8, 172.16/12, 192.168/16, fc00::/7). Where: any. See reverse proxy.

ASPNETCORE_HTTP_PORTS

The port(s) the server listens on, on all addresses: 8080, or 8080;9090. Default: 8080 in the image and in the service examples; 5000 on localhost only when unset elsewhere. Where: env.

ASPNETCORE_URLS

Full listen addresses instead of ports: http://+:8080, or https://+:8443 with a certificate (ASPNETCORE_Kestrel__Certificates__Default__Path and ..._Password). Overrides ASPNETCORE_HTTP_PORTS. Where: env.

Logs

LOG_LEVEL

The least important entries written: trace, debug, information, warning, error or critical. Default: information. Where: any, live.

LOG_LEVEL_OVERRIDES

Levels for a category and those under it: Punchlist.Sync=debug,Microsoft=warning. Microsoft.AspNetCore and System.Net.Http.HttpClient start at warning; an override changes that. Default: Microsoft.AspNetCore=Warning. Where: any, live.

LOG_FORMAT

The console's format: readable text, or json (one object per line, for log collectors). Default: text. Where: any, live.

LOG_FILES

Also write JSON lines to files in LOG_DIR. Default: true. Where: any, live.

LOG_DIR

Where log files go. Default: logs next to the SQLite file (/data/logs). Where: env.

LOG_FILE_MAX_MB

A log file rolls over at midnight UTC or at this size; earlier files are gzipped. Default: 50. Where: any, live.

LOG_FILE_KEEP_DAYS

Archived log files older than this are deleted. Default: 14. Where: any, live.

Log servers

Any number of these at once. Each has its own queue (10,000 entries, retried with growing waits), so a log server that is down never holds Punchlist up. Guide: logs and audit. All are live.

Setting Meaning
LOG_OTLP_ENDPOINT OpenTelemetry collector, OTLP over HTTP (JSON): http://alloy:4318
LOG_OTLP_HEADERS Extra headers: Authorization=Basic%20...,X-Scope-OrgID=1 (secret)
LOG_LOKI_URL Grafana Loki: http://loki:3100
LOG_LOKI_USERNAME Loki basic auth user
LOG_LOKI_PASSWORD Loki basic auth password (secret)
LOG_LOKI_TENANT Loki tenant (X-Scope-OrgID)
LOG_GELF_ADDRESS Graylog GELF input: udp://graylog:12201, tcp://... or http://graylog:12201
LOG_ELASTIC_URL Elasticsearch or OpenSearch: https://es:9200
LOG_ELASTIC_INDEX Index or data stream. Default: logs-punchlist-default
LOG_ELASTIC_USERNAME Basic auth user
LOG_ELASTIC_PASSWORD Basic auth password (secret)
LOG_ELASTIC_API_KEY An API key instead of user and password (secret)
LOG_SYSLOG_ADDRESS Syslog (RFC 5424, facility local0): udp://rsyslog:514 or tcp://...

Access and event log

AUDIT_RETENTION_DAYS

Days the event log keeps entries (sign-ins, admin actions, ...). Default: 90. Where: any, live.

ACCESS_LOG_RETENTION_DAYS

Days the request log keeps entries. Default: 14. Where: any, live.

AUDIT_ARCHIVE

Before old entries are removed, write them to gzipped JSON lines in AUDIT_ARCHIVE_DIR. Default: false. Where: any, live.

AUDIT_ARCHIVE_DIR

Where those archives go (audit-<kind>-<time>.jsonl.gz). Default: audit next to the SQLite file. Where: env.

Settings sources

CONFIG_FILE

A settings file to read. Default: none. Where: env.

CONFIG_KEY

The key for enc:v1:... encrypted values; make one with punchlist config key. Prefer CONFIG_KEY_FILE. Default: none. Where: env.

Development

WEB_ROOT

Where the web app's files are. Default: wwwroot next to the server program. Only for development, to serve web/dist from a checkout. Where: env.