Skip to content

Draft: not yet reviewed by a clinician

Use this page to prepare questions for your care team. It does not replace their advice. Your own targets and doses come from your nephrologist, diabetes team and renal dietitian.

Users and keys

From v0.3 every person has their own account, and nobody sees anyone else's log. As the admin you create the first account, invite the others, and decide which API keys to share (design note 07). Being admin does not give you a screen to read other people's data.

The first admin

On the first start of an empty (or v0.2) database the app creates no account by itself. It prints a one-time setup code to its log, valid for 60 minutes:

FIRST-RUN SETUP: open https://food.home.example.net/#/setup and enter the code 7KQ2-M9XD-PL4R-T6WN (valid 60 min; ...)
  1. Read it from the log: the line starts with FIRST-RUN SETUP (the command for each engine is in the deployment guide's first-run section).
  2. Open the address, enter the code, and choose the admin's user name and a password of at least 15 characters (NIST SP 800-63B-4).
  3. The setup screen also asks whether to switch on Open Food Facts barcode lookups (off by default).

Until setup is done, every API call except setup answers 503 Setup required. An expired code: restart, or run python -m app.admin setup-code in the container.

Alternatives (deployment guide):

  • GitOps: ADMIN_USERNAME plus ADMIN_PASSWORD_FILE create the admin on first start.
  • CLI: python -m app.admin create-admin USERNAME reads the password from stdin.
  • Upgrading from v0.2: the existing log becomes the admin's (user 1). A v0.2 APP_PASSWORD becomes that admin's password once; if it is shorter than 15 characters, you are asked to change it.

Invite people

Server administration → People → Invite. The app shows a link once: https://food.home.example.net/#/invite/…. Send it however you like; it works once and expires after 7 days. The secret part sits after #, which browsers never send to the server, so it stays out of proxy logs. Revoke unused invites from the same screen.

REGISTRATION_MODE Who can create an account
invite (default) people with an invite link
closed only the admin; each person sets their password from a one-time link
open anyone who reaches the page (HTTPS required; 3 sign-ups per address per hour)

Use HTTPS before you invite anyone. With two or more accounts the app refuses plain-HTTP sign-in from other machines (HTTPS for phones).

Roles

  • user: their own log, foods, meals and settings.
  • admin: also users and invites, sign-in settings, shared keys, usage counts, the activity log and server status. No impersonation and no log viewer.
  • An admin can issue a password-reset link for anyone. That signs the person out everywhere and tells them at their next sign-in, and it appears in their activity, so it cannot be done quietly (design note 07).
  • Open reset and setup links are listed under each account in Server administration → People, with who created them, and can be revoked there. A link someone made for your own account is flagged in your row.
  • If someone loses a device or you stop trusting a chat assistant, Server administration → People → Manage → Revoke tokens ends every token that person has, assistant tokens and phone shortcut tokens alike (it shows while assistant access or phone shortcuts is on and they have active ones). It appears in their activity; they can make new tokens in their settings.
  • Changing AUTH_MODE signs everybody out and revokes every assistant and phone shortcut token at the next start. With sign-in off, anyone who could reach the server could have made a token, so none is kept.
  • Removing an admin contains them: demoting, disabling or deleting an admin also deletes every unused invite and reset or setup link they created. A reset link also stops working once the account's password is changed another way, or the account is disabled.

Passwords and lock-outs

  • The app sends no e-mail, so there is no self-service reset. Server administration → People → Reset link (24 hours, single use), or python -m app.admin reset-password USERNAME. --stdin sets a password directly (break-glass; also unlocks a locked account).
  • Repeated wrong passwords slow that account down, then block the address for a while (refused attempts of any kind count, and an IPv6 network counts as one address). After 100 failures in a row an account needs an admin reset.
  • An account the admin creates gets a one-time setup link; the page it opens shows the username the admin chose, so the person (and their password manager) knows what to sign in with.
  • python -m app.admin list-users and revoke-sessions USERNAME (or --all) help after a lost phone.
  • Someone who uses two-step sign-in and lost both the phone and the recovery codes: python -m app.admin remove-two-step USERNAME. They sign in with the password alone and can turn it on again.
  • A lost or stolen device with a passkey: Server administration → People → Remove passkeys, or python -m app.admin remove-passkeys USERNAME. Passkeys need the server's name: set PUBLIC_URL to the address people open.
  • python -m app.admin export-user USERNAME export.zip gives you a person's data export when they cannot sign in (it holds their health data: hand it over privately and delete your copy), and disable-user USERNAME stops an account and signs out its devices; enable it again in Settings → People.

Shared keys and quotas

Key Set it as Daily limit per person
USDA FoodData Central USDA_API_KEY_FILE (locked), or Admin → Shared keys USDA_SHARED_DAILY_LIMIT, default 200
AI provider (v0.3) AI_* variables (locked), or Admin → AI providers AI_SHARED_DAILY_LIMIT, default 30
  • A USDA key is free and allows 1,000 requests an hour; the server stays under that (USDA API guide).
  • Per person you can switch shared use off ("can use shared keys").
  • People may add their own keys (on by default). Their own key is always used first, has no app quota, and is never swapped for the shared one when it fails.
  • Keys are write-only: the app shows "set, ends in 9xQz", never the key. A key set by environment shows "Set by the server" and cannot be changed in the app.
  • For a Hermes agent, paste the key of the dedicated tool-free profile, never your main one (design note 04).

The secret key

SECRET_KEY encrypts stored API keys (not passwords, not health data). Every shipped profile mounts it as SECRET_KEY_FILE from the engine's secret store, outside the data volume, and you should keep a copy in a password manager (operator security guide). Lose it, and stored keys must be entered again; nothing else is lost.

Rotate it (deployment guide):

  • auto-generated /data/secret.key: python -m app.admin rotate-secret-key, then restart;
  • mounted file: add a new first line, restart, python -m app.admin reencrypt, remove the old line, restart.

Server administration → About this server shows where the key comes from and whether any secret still uses an older key.

Proxy sign-in instead of passwords

With Authelia, Authentik or tailscale serve in front, AUTH_MODE=proxy takes the user name from a header. It needs TRUSTED_PROXY_USER_HEADER, a matching TRUSTED_PROXIES, and TRUSTED_PROXY_SECRET_FILE (a value the proxy sends as X-Proxy-Secret); without the secret the app refuses to start. Set-up details: Configuration and the deployment guide.

If something goes wrong

  • No FIRST-RUN SETUP line: an admin already exists, or ADMIN_PASSWORD_FILE was used. Check python -m app.admin list-users.
  • "Your account is not enabled here" in proxy mode: create the account first, or set PROXY_AUTO_CREATE_USERS=true.
  • The only admin is locked out: python -m app.admin reset-password USERNAME --stdin.
  • More: Troubleshooting.

Sources

Not yet reviewed by a clinician. Facts and sources last checked 2026-10-06.