Skip to content

Admin panel reference

The admin panel is at Admin in the top navigation (visible only to users with isAdmin: true). It is a peer of Settings, not a section of it: Settings is what belongs to your account, Admin is what belongs to the instance.

This page is the reference that maps every field to its effect. Help text in the panel hangs on the field it explains; anything with consequences — a restore replaces everything, a deactivated account keeps its data, debug logging costs disk — is standing text rather than a tooltip.

The basics. Most of these were set during the first-run wizard and rarely change afterwards.

FieldWhat it does
Instance nameBrowser title bar text, email subject prefix
Public URLUsed in email links (invitations, password reset) and as the address the Companion app is told. Crucial — if this is wrong, password-reset links go to the wrong host
Maximum usersCap on the user count. New registrations / invitations fail when reached. 0 = unlimited
Registration modepublic — anyone can sign up · invite — only invited users · closed — admin-created users only. With registration off, the login page hides its Register link; invitation links still work
Default UI languageNew users default to this
Beta featuresThe instance beta switch. Off by default. The panel lists every feature it turns on with a plain sentence, read from the same registry the application checks — so it cannot claim something the build does not do. Applies immediately, no reload. See Beta features
Country countingThe instance default for how strictly countries are counted: which evidence rung the headline starts from. Every user may override it. See Countries & passport
Anonymous usage statisticsOpt-in ping to the adoption-metrics service. See Anonymous usage statistics

Encrypted at rest with the auto-generated encryption key under /app/data/secrets/encryption.key. A user may enter their own key for most of these in their settings; the instance key is used when they have none.

FieldWhat it unlocksRequired?
AirLabs API keyLive flight enrichment (today’s flights primarily)No
Aviationstack API keyHistorical + future flight enrichmentNo
AeroDataBox API keyThe provider that answers for a past date — used for the one late check on a flight that landed without its actual timesNo
OpenSky Client ID + SecretReal-time tracking position fallbackNo
OpenAI API keyOpenAI Vision for boarding-pass scanning, and as a text-parser tierNo
Anthropic API keyClaude Vision for boarding-pass scanning, and as a text-parser tierNo
Ollama URLLocal LLM endpointNo — the built-in templates and the document auto-detection work without it
Ollama text model / vision modelModels for document parsing and boarding-pass vision (default text model gemma3:12b)No
Google Places API keyThe “what is here?” lookup in the map picker and place searchNo
Logostream keyPremium airline logos ahead of the keyless sourcesNo
Geocoder URLsWhich geocoding services fill in addresses; instance-configurableNo — defaults exist
ImmichAn instance-wide Immich connection users without their own fall back toNo
Dawarich (beta)An instance-wide Dawarich connection, offered only with the beta switch onNo

Each row has a Test button. Most hit the provider’s health endpoint and cost nothing. Two do not: the Google Places check sends one real, billed request and its result names the price (about 0.03 USD), and the logostream check spends one request of your quota. A test that costs money says so before you press it.

The pages Flight data APIs, Ollama, and Vision parsers walk through getting each key set up.

Conversion asks the European Central Bank first. For the currencies the ECB does not publish, a keyless public dataset is consulted — and this panel carries the switch that turns that fallback off entirely, for an instance that would rather report “no rate” than consult a third party. Amounts with no rate stay in their currency and are left out of totals, which say how many they left out. See Money & currencies.

Same fields as the SMTP page — host, port, encryption, username, password, from-address, plus a Send test button. Empty fields mean SMTP is disabled — invitations and password-resets fall back to the “ask the admin” message. A stored password can be deleted, not only overwritten, behind a confirmation that names the consequence.

FieldDefault
Enable automatic backupoff
Intervalweekly — daily, weekly or monthly, always at 02:00 UTC; there is no free cron field
Retention (days)30 — by age, not by count
WebDAV (under Settings)(empty — disabled)

Plus a Create backup now button and, per backup, Download, Restore and Sync to the WebDAV share. A backup is one .tar.gz holding the database dump, every upload directory and a metadata file. Full deep-dive on the Backups & Restore page.

A table of all user accounts with admin actions:

  • Create user — manual user creation (no email sent)
  • Send invitation — generates a single-use invite link, sends it via SMTP if configured
  • Promote to admin / Demote — toggle the isAdmin flag
  • Force password change — sets mustChangePassword; user must change at next login
  • Send reset email — generates a password-reset link, mails it via SMTP
  • Reset two-factor — the way back in for a user who lost their phone and their recovery codes. Clears the TOTP secret; the user signs in with the password alone and can set 2FA up again. Passkeys are not touched — a user removes those from their own security section
  • Deactivate — the account is refused a session on every path (login, registration, setup, two-factor verification, passkey assertion); its data stays
  • Delete user — cascades to their travel, achievements, tokens and photographs. Confirms with a typed-in-username challenge before destruction

The table shows username, name, email (if any), admin flag, whether two-factor is on, registration date, last login.

The instance-wide parser settings: the text and vision fallback chains (which provider is tried in which order), the airline template registry with its refresh button (an admin action — any account could once trigger it and spend the instance’s refresh quota), the user templates, and the parser statistics with their anonymised export.

Read-only tabular view of every mutation:

ColumnContains
TimestampUTC, ISO 8601
UserWho triggered the action (cookie or PAT-bearing user)
TokenWhich PAT, if PAT-authenticated
IPClient IP (anonymised after 7 days)
Method + pathThe HTTP request that was logged
ResourceWhat changed
ActionCREATE / UPDATE / DELETE
DiffPer-field before-and-after values

Filter by user, action, date range, resource. Export filtered results as CSV.

FieldDefaultDescription
Log levelinfoOne of error / warn / info / debug / trace. Persisted across restarts
Log retention (days)14Older log files are pruned by the daily cleanup job
Pino destination/app/data/logs/app.log, error.log, http.log, parser*.log

Raise to debug for one-off troubleshooting, drop back to info afterwards — debug adds a lot of volume.

Read-only “about” pane plus a few actions:

  • TravStats version, build date, Node and Postgres versions, database size, backup count, health status
  • Re-sync airports — pulls the current airport catalogue (this is how an existing install picks up new fields, such as the Antarctic ones)
  • Refresh airline logos — re-syncs the stored logos; a nightly sweep does the same
  • Diagnostic export — an anonymised bundle for filing issues; see Troubleshooting

In the top-right corner of every page TravStats displays an Update available badge when a newer stable release exists on GitHub. The check runs at most once per six hours, considers only stable releases (RC and pre-release tags are filtered out), strips a pre-release suffix from your own version before comparing, and fails silently on an air-gapped instance.

Some settings deliberately live in .env (deploy-time) rather than the admin UI (runtime):

  • DATABASE_URL — changing the database in flight is not a thing
  • JWT_SECRET — auto-generated, persisted to file, never editable in UI (rotation = delete file + restart, signs out everyone)
  • COOKIE_SECURE, CORS_ORIGIN — proxy-related; almost always auto-detected correctly
  • TZ — the container’s clock. Always UTC. The UI renders in user-local time
  • TRAVSTATS_STATS_ENDPOINT — the usage-statistics kill-switch; empty disables all sending regardless of the consent toggle

If you need to change any of these, edit .env and restart the stack. Everything else lives in the admin UI.