Settings Visibility Matrix¶
This page shows, for every persisted setting, where it can be edited and how it behaves across the three deployment modes: Server hosted, Pi Hosted, and Pi Remote (a satellite).
It is derived directly from service/app/config.py, so it can be regenerated
when the lists there change. The three sources are:
_SAVEABLElists every setting that is persisted tosettings.json.SATELLITE_PULL_FIELDSlists the settings a Pi Remote pulls from its main server and mirrors locally. These are read-only on the satellite: edit them on the server and the satellite picks them up on its next sync.SECRET_SETTING_KEYSlists the settings that hold credentials. These are redacted from backups unless the operator opts in, and are never rendered back into the setup page.
How to read the behaviour column¶
- Editable means the setting is editable in the setup wizard or Settings page on that mode.
- Inherited (read-only) means the value is pulled from the main server on a Pi Remote and cannot be changed locally. Change it on the server.
- Device-local means the setting is in
_SAVEABLEbut not inSATELLITE_PULL_FIELDS, so it is editable on every mode and is never synced between devices. Each device keeps its own value. - Satellite-only means the setting only applies on a Pi Remote (it configures the link to the main server) and is not used on the other modes.
- Secret marks a setting that holds a credential and is redacted from backups by default.
A setting that is device-local behaves identically on all three modes.
AI and vision providers¶
These configure the vision/LLM provider used for photo recognition, barcode enrichment, and cook suggestions. All are pulled by a satellite from the server.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
vision_provider |
Editable | Editable | Inherited (read-only) | |
gemini_api_key |
Secret | Editable | Editable | Inherited (read-only) |
gemini_model |
Editable | Editable | Inherited (read-only) | |
ollama_base_url |
Editable | Editable | Inherited (read-only) | |
ollama_model |
Editable | Editable | Inherited (read-only) | |
openai_api_key |
Secret | Editable | Editable | Inherited (read-only) |
openai_model |
Editable | Editable | Inherited (read-only) | |
anthropic_api_key |
Secret | Editable | Editable | Inherited (read-only) |
anthropic_model |
Editable | Editable | Inherited (read-only) | |
ai_extra_keys |
Secret | Editable | Editable | Device-local |
ai_token_budget |
Editable | Editable | Device-local | |
cloud_base_url |
Device-local | Device-local | Device-local | |
cloud_instance_token |
Secret | Editable | Editable | Editable |
Note: ai_extra_keys is device-local. It is in _SAVEABLE and is a secret, but
it is not in SATELLITE_PULL_FIELDS, so each device keeps its own spare keys.
Note: the Forager link is per-device on purpose, and is a main-install
feature (server and pi_hosted): a satellite forwards AI from its main server
and has no local app of its own to sign in or expose, so it shows no Forager
page. On a main install each device signs in with the account email and
password (or a pairing code under the card's Advanced toggle, or Continue
with Google when Forager offers it) on the Forager page in Settings and holds
its own instance token, so it shows up as its own instance on the cloud
account. The password is forwarded
to the cloud during sign-in and never stored. A sign-in on a fresh install
also sets vision_provider and enrich_provider to cloud (an install with
a working provider keeps it), and qr_public_url follows the kitchen's
public web address whenever the platform supplies one (absent that, the
stored value is untouched). cloud_base_url is the cloud service address;
it has no settings
control and is only changed with the CLOUD_BASE_URL environment variable.
Barcode scanning and enrichment¶
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
scanner_type |
Editable | Editable | Device-local | |
scanner_uart_enabled |
Editable | Editable | Device-local | |
scanner_uart_port |
Editable | Editable | Device-local | |
scanner_uart_baud |
Editable | Editable | Device-local | |
barcode_global_capture |
Editable | Editable | Device-local | |
extra_api_key_names |
Editable | Editable | Device-local | |
barcode_enrichment |
Editable | Editable | Inherited (read-only) | |
barcode_llm_fallback |
Editable | Editable | Inherited (read-only) | |
barcode_autocheck_shopping |
Editable | Editable | Inherited (read-only) | |
llm_expiry_enabled |
Editable | Editable | Inherited (read-only) | |
enrich_provider |
Editable | Editable | Inherited (read-only) | |
enrich_model |
Editable | Editable | Inherited (read-only) |
scanner_uart_enabled, scanner_uart_port, and scanner_uart_baud (Settings,
Scanning & AI) read a serial (UART) barcode scanner wired to the device, for
example one on a Pi's GPIO serial pins. They stay device-local because the
scanner is physically attached to one machine, so each device sets its own port
(/dev/serial0 by default) and baud rate (9600 by default).
Community shelf life¶
Both switches live on the Inventory & Storage pane of a main install. They are not offered on a Pi Remote at all: pending scans, expiry suggestions, and commits all happen on the main server, so the server's setting is the one that matters. What they do (and exactly what is and is not shared) is on Community shelf life and privacy.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
use_community_expiry |
Editable | Editable | Not present | |
share_expiry_learning |
Editable (opt-in, off by default) | Editable (opt-in, off by default) | Not present |
Grocy (inventory backend)¶
A satellite talks to the server's Grocy directly, so it inherits these.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
grocy_base_url |
Editable | Editable | Inherited (read-only) | |
grocy_api_key |
Secret | Editable | Editable | Inherited (read-only) |
grocy_public_url |
Editable | Editable | Inherited (read-only) | |
grocy_admin_password |
Secret | Generated on first run | Generated on first run | Not present |
When a fresh Grocy still answers to its stock sign-in, Pantry Raider sets it
up by itself on first run: it creates its own API key and replaces the stock
admin password with a generated one, stored in grocy_admin_password and
revealed from the Inventory pane if you ever want to sign in to Grocy
directly.
Mealie (optional connector)¶
Recipes, the meal plan, and the shopping list are built into Pantry Raider; these settings only matter if you connect a Mealie you already use.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
mealie_base_url |
Editable | Editable | Inherited (read-only) | |
mealie_api_key |
Secret | Editable | Editable | Inherited (read-only) |
mealie_public_url |
Editable | Editable | Inherited (read-only) | |
mealie_admin_password |
Secret | Generated on first run | Generated on first run | Not present |
If you run a Mealie and it still answers to its stock sign-in, Pantry Raider
can connect itself to it: it creates its own API token, secures the account
with a generated password (stored in mealie_admin_password, revealed from
the Recipes pane), and adds a Groceries shopping list.
Recipe sources and suggestion tuning¶
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
recipe_source |
Editable | Editable | Inherited (read-only) | |
recipes_backend |
Editable | Editable | Inherited (read-only) | |
shopping_backend |
Editable | Editable | Inherited (read-only) | |
themealdb_api_key |
Secret | Editable | Editable | Inherited (read-only) |
spoonacular_api_key |
Secret | Editable | Editable | Inherited (read-only) |
staple_items |
Editable | Editable | Inherited (read-only) | |
cook_ai_context |
Editable | Editable | Inherited (read-only) | |
kitchen_appliances |
Editable | Editable | Inherited (read-only) | |
perishable_days |
Editable | Editable | Inherited (read-only) | |
expiring_soon_days |
Editable | Editable | Inherited (read-only) | |
suggest_per_tier |
Editable | Editable | Inherited (read-only) | |
custom_storage_categories |
Editable | Editable | Inherited (read-only) |
recipes_backend says where the recipe library lives: empty means automatic
(an install with Mealie connected keeps using it until you copy the recipes
over; everything else uses Pantry Raider's built-in store). shopping_backend
says where the shopping list lives: empty means automatic (the list stays
next to your inventory in Grocy, except while your recipes still come from
Mealie, which keeps the Mealie list you already use). A satellite inherits
both, so the whole fleet reads and writes the same library and list.
Navigation and custom tabs¶
Navigation order, hidden tabs, parent grouping, and custom tabs are device-local, so each device can arrange its own menu. The theme is inherited so the fleet shares one look.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
nav_order |
Editable | Editable | Device-local | |
nav_hidden |
Editable | Editable | Device-local | |
custom_nav_tabs |
Editable | Editable | Device-local | |
nav_parents |
Editable | Editable | Device-local |
Theme and interface¶
ui_theme is inherited so the fleet matches; the custom theme swatches, UI
scale, and display rotation are device-local hardware/look choices.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
ui_theme |
Editable | Editable | Inherited (read-only) | |
custom_theme_base |
Editable | Editable | Device-local | |
custom_theme_primary |
Editable | Editable | Device-local | |
custom_theme_accent |
Editable | Editable | Device-local | |
custom_theme_bg |
Editable | Editable | Device-local | |
custom_theme_surface |
Editable | Editable | Device-local | |
custom_theme_text |
Editable | Editable | Device-local | |
custom_themes |
Editable | Editable | Device-local | |
background_image_url |
Editable | Editable | Device-local | |
background_opacity |
Editable | Editable | Device-local | |
start_page_enabled |
Editable | Editable | Device-local | |
start_page_mode |
Editable | Editable | Device-local | |
start_page_keys |
Editable | Editable | Device-local | |
start_page_layout |
Editable | Editable | Device-local | |
ui_scale |
Editable | Editable | Device-local | |
display_rotation |
Editable | Editable | Device-local | |
display_type |
Editable | Editable | Device-local | |
quiet_mode |
Editable | Editable | Device-local | |
qr_url_mode |
Editable | Editable | Device-local | |
qr_public_url |
Editable | Editable | Device-local | |
convert_custom_rows |
Editable | Editable | Device-local |
Note: convert_custom_rows (the Conversions cheat-sheet rows) is intentionally
left device-local so each kiosk keeps its own reference list.
start_page_mode is the Home style switch (Settings, Start Page): glance
(the default) builds the home screen automatically from the pages in your
navigation, with live count pills for Review, Alerts, and Expiring; custom
keeps the hand-arranged launcher built from start_page_keys and
start_page_layout. It stays device-local so a kiosk can open on Glance while
another device keeps its custom grid.
qr_url_mode picks which address the "Add items from your phone" QR code
encodes: auto (the default) uses the device's own network address, so a
phone on the same network can open it even when the kiosk browses at
localhost; public encodes qr_public_url (or the active tunnel URL when
that field is empty). Both stay device-local so every kiosk's QR code points
at the device that shows it.
Display and peripherals¶
These describe the hardware attached to a Pi (display panel, touch, Stream Deck) and are device-local. They do not apply to a server install.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
device_hostname |
Editable | Editable | Device-local | |
lan_scan_cidr |
Editable | Editable | Device-local | |
has_streamdeck |
Not applicable | Editable | Device-local | |
streamdeck_key_count |
Not applicable | Editable | Device-local | |
streamdeck_rotation |
Not applicable | Editable | Device-local | |
display_touch |
Not applicable | Editable | Device-local | |
display_margin_top |
Not applicable | Editable | Device-local | |
display_margin_right |
Not applicable | Editable | Device-local | |
display_margin_bottom |
Not applicable | Editable | Device-local | |
display_margin_left |
Not applicable | Editable | Device-local | |
display_idle_timeout |
Not applicable | Editable | Device-local | |
wake_on_motion |
Not applicable | Editable | Device-local | |
wake_on_presence |
Not applicable | Editable | Device-local | |
presence_indicator_enabled |
Not applicable | Editable | Device-local | |
screensaver_minutes |
Editable | Editable | Device-local | |
screensaver_speed |
Editable | Editable | Device-local | |
screensaver_pill_scale |
Editable | Editable | Device-local | |
screensaver_photo_seconds |
Editable | Editable | Device-local | |
screensaver_ken_burns |
Editable | Editable | Device-local | |
screensaver_mode |
Editable | Editable | Device-local | |
photo_source |
Editable | Editable | Device-local | |
photo_folder |
Editable | Editable | Device-local | |
photo_urls |
Editable | Editable | Device-local | |
immich_base_url |
Editable | Editable | Device-local | |
immich_api_key |
Secret | Editable | Editable | Device-local |
immich_album_id |
Editable | Editable | Device-local | |
screensaver_all_clients |
Editable | Editable | Device-local | |
osk_enabled |
Editable | Editable | Device-local | |
kiosk_auto_home_enabled |
Editable | Editable | Device-local | |
kiosk_auto_home_seconds |
Editable | Editable | Device-local | |
kiosk_auto_home_exempt |
Editable | Editable | Device-local | |
kiosk_split_enabled |
Editable | Editable | Device-local | |
kiosk_split_primary |
Editable | Editable | Device-local | |
kiosk_split_secondary |
Editable | Editable | Device-local | |
kiosk_split_lock_primary |
Editable | Editable | Device-local | |
streamdeck_idle_timeout |
Not applicable | Editable | Device-local | |
streamdeck_logo_when_display_off |
Not applicable | Editable | Device-local |
The kiosk display cards (Settings, Display & Sleep) and the
Stream Deck editor (Settings, Stream Deck) are
shown only on the Pi modes (the peripherals feature flag is Pi-only).
device_hostname is offered on every mode (Settings, Network)
because it controls how browser links are built.
The Recovery hotspot card (Settings, Network) is Pi-only and its two values
(the hotspot name and password) live on the device host, not in the settings
store: the app writes them through the host bridge (POST /ap/config), which
lands them in /etc/hostapd/hostapd.conf, /etc/foodassistant/ap-ssid,
/etc/foodassistant/ap-passphrase, and the boot-partition
pantry-raider-hotspot.txt mirror. They never sync between devices; each
appliance's hotspot is its own.
display_margin_top / display_margin_right / display_margin_bottom /
display_margin_left are the Advanced display safe-area insets (pixels the
kiosk holds back from each edge). They stay device-local because every panel's
visible area differs: a rotated DSI panel can draw wider than it shows, and some
HDMI panels hide a rim behind the bezel. The kiosk already corrects the common
overscan on its own, so these usually stay 0 and are only dialed in for a panel
that still clips. Each is clamped to 0-200 px.
display_idle_timeout switches the panel itself off after the idle period;
screensaver_minutes is the softer on-screen layer (the page dims to a
floating clock, a touch brings it back) for panels that should stay powered.
screensaver_mode picks what that layer shows: the bouncing logo (the
default), a photo slideshow, or a retro canvas saver. photo_source picks
where the slideshow's pictures come from: the built-in USB drive folder, a
folder on the server (photo_folder, blank meaning the photos folder inside
the app's data directory), an Immich album (immich_base_url,
immich_api_key, immich_album_id), or a plain list of direct image links
(photo_urls). Google Photos and iCloud do not offer reliable access for
third-party apps, which is why they are not on that list. An empty or
unreachable source falls back to the logo, so the setting is always safe.
screensaver_all_clients widens where the saver runs: off (the default)
keeps the idle behaviour on kiosk browsers only, on lets every browser
viewing the install (a desktop or a phone included) dim to the screensaver
after the same idle minutes. Because of that wider reach, the screensaver
settings are also offered on a server install, not just the Pi modes.
wake_on_presence wakes the panel when the optional mmWave presence sensor
sees someone walk up (see the presence sensor hardware guide); auto turns it
on once the sensor has triggered at least once.
presence_indicator_enabled shows a small icon in the top corner of the
kiosk display when a presence sensor is fitted: faint while the room is
empty, lit while the sensor sees someone, so the sensor can be checked just
by walking up to the screen. On by default, and safe everywhere: a display
without a readable presence sensor never shows the icon at all.
wake_on_motion wakes a sleeping panel when the device is moved or bumped,
read from the LSM6DSOX accelerometer on kits that include one; auto (the
default) enables it exactly when the sensor is present. A screen touch or a
Stream Deck button press always wakes the display regardless of this setting.
osk_enabled controls the on-screen keyboard: in kiosk mode a touch
keyboard slides up from the bottom of the screen whenever a text field is
tapped, so names, barcodes, and searches can be typed without a physical
keyboard. On by default; turn it off on a kiosk with a keyboard attached.
Like the screensaver, it is offered on server installs too, because any
browser can be put in kiosk (touch) mode.
kiosk_auto_home_enabled is "Return to home when idle" (Settings, Display & Sleep):
after kiosk_auto_home_seconds without a touch, a kiosk drifts back to its
home page so the next person starts fresh. Pages named in
kiosk_auto_home_exempt (by default cook,current_recipe,weather,camera,timers,
the pages you actively watch) are left alone so the screen never jumps away
mid-cook. Off by default, and all three stay device-local so each screen keeps
its own idle behaviour. Like the screensaver, it is offered on every mode.
kiosk_split_enabled is the split screen (Settings, Display & Sleep): the
display shows two app pages at once, side by side on a wide panel and stacked
on a tall one, made for ultrawide and tall bar panels (a Waveshare 480x1920,
for example). kiosk_split_primary and kiosk_split_secondary pick the page
each pane starts on, and kiosk_split_lock_primary keeps the first pane on
its page (Glance as an always-on status panel is the natural pairing) while
the second pane browses the whole app normally; navigation inside a pane
stays inside that pane. When the split is on, a display that starts in kiosk
mode and lands on Glance opens the split view automatically, and it is always
available directly at /ui/split. All four stay device-local: the split
exists because of the panel's shape, and every panel differs.
streamdeck_logo_when_display_off puts the Pantry Raider logo across the
Stream Deck keys while the display is asleep, so the deck reads as resting
rather than showing stale buttons. Pressing any key or touching the screen
brings both surfaces back. On by default; the deck's own
streamdeck_idle_timeout still blanks the keys fully after its idle period.
Stream Deck¶
The Stream Deck weather widget, custom keys, cameras, and Home Assistant
credentials are pulled from the server so a custom button or camera built once
appears on every deck in the fleet. The per-deck visual style
(streamdeck_key_style, streamdeck_icon_color) is deliberately device-local so
each deck can pick its own look and keep it across syncs.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
streamdeck_key_overrides |
Editable | Editable | Inherited (read-only) | |
streamdeck_weather_location |
Editable | Editable | Inherited (read-only) | |
streamdeck_weather_units |
Editable | Editable | Inherited (read-only) | |
weather_api_base |
Editable | Editable | Device-local | |
streamdeck_key_style |
Editable | Editable | Device-local | |
streamdeck_icon_color |
Editable | Editable | Device-local | |
streamdeck_cameras |
Editable | Editable | Inherited (read-only) | |
streamdeck_ha_base_url |
Editable | Editable | Inherited (read-only) | |
streamdeck_ha_token |
Secret | Editable | Editable | Inherited (read-only) |
streamdeck_ha_slots (legacy) |
Kept, no editor | Kept, no editor | Inherited (read-only) |
streamdeck_ha_slots is legacy: the fixed HA 1 to HA 5 slot editor was retired
in favor of custom Home Assistant keys built with the entity picker. Slots a
device already has keep working and still sync to satellites; there is just no
way to create new ones.
On-screen Home Assistant events¶
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
ha_events_enabled |
Editable | Editable | Inherited (read-only) | |
ha_camera_popup_seconds |
Editable | Editable | Inherited (read-only) |
Floating navigation bar and timer chips¶
The on-screen navigation bar position and orientation are device-local server
defaults; a drag on the device overrides them per-device via localStorage.
timer_chips controls the floating per-timer countdown chips shown on every
page while timers run: on, off, or auto (auto hides them at large and
extra-large interface scale, resolved per device the same way nav_visibility
is).
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
floating_nav_position |
Editable | Editable | Device-local | |
floating_nav_orientation |
Editable | Editable | Device-local | |
floating_nav_autohide_streamdeck |
Editable | Editable | Device-local | |
nav_visibility |
Editable | Editable | Device-local | |
timer_chips |
Editable | Editable | Device-local |
Timezone, clock format, scheduled reboot, and update bookkeeping¶
timezone sets how timestamps read across the fleet: set it once on the main
server (or a standalone install) and a Pi Remote inherits it and applies it to
its own clock on each sync. clock_format rides with it: Auto, 12-hour, or
24-hour reading for the screensaver clock, the weather page, and timestamps,
also set once on the main server and inherited by every Pi Remote. The scheduled reboot (Settings, Display
& Sleep) applies only to a Pi appliance; the frequency can be Off,
Nightly, or Weekly with a day-of-week picker. The update_last_* fields record
the most recent update check and are maintained by the app.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
timezone |
Editable | Editable | Inherited (read-only) | |
clock_format |
Editable | Editable | Inherited (read-only) | |
scheduled_reboot_time |
Not applicable | Editable | Device-local | |
scheduled_reboot_frequency |
Not applicable | Editable | Device-local | |
scheduled_reboot_day |
Not applicable | Editable | Device-local | |
update_last_checked |
Auto | Auto | Device-local (bookkeeping) | |
update_last_latest |
Auto | Auto | Device-local (bookkeeping) | |
update_last_available |
Auto | Auto | Device-local (bookkeeping) |
Deployment and the satellite link¶
These pick the deployment mode and, on a satellite, wire it to its main server. The upstream link fields apply only on a Pi Remote.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
deployment_mode |
Editable | Editable | Editable | |
remote_server_url |
Not applicable | Not applicable | Editable (satellite-only) | |
remote_server_ip |
Not applicable | Not applicable | Cached automatically (satellite-only) | |
remote_server_host |
Not applicable | Not applicable | Cached automatically (satellite-only) | |
upstream_api_key |
Not applicable | Not applicable | Editable (satellite-only) | |
kiosk_pin |
Secret | Not applicable | Not applicable | Editable (satellite-only) |
kiosk_readonly_when_locked |
Not applicable | Not applicable | Editable (satellite-only) | |
satellite_sync_minutes |
Not applicable | Not applicable | Editable (satellite-only) | |
satellite_last_sync |
Not applicable | Not applicable | Written automatically (satellite-only) | |
hosted_stack_parked |
Not applicable | Written automatically | Written automatically | |
hosted_config_snapshot |
Secret | Not applicable | Written automatically | Written automatically |
device_id |
Auto-generated | Auto-generated | Auto-generated |
device_id is generated once on first run on every mode and persisted so the
device keeps a stable identity. remote_server_ip, remote_server_host, and
satellite_last_sync are written by the sync process, not edited by hand.
hosted_stack_parked and hosted_config_snapshot back the mode switch on a Pi
Hosted appliance (Settings, Advanced, "Run as a satellite"). Switching
pauses the local Grocy/Mealie containers (data kept on the device), snapshots
the backend settings the satellite sync will overwrite, and flips the mode to
pi_remote. On a switched device the Advanced section offers "Switch back to
full stack", which restarts the paused stack and restores the snapshot. A
device flashed as a plain Pi Remote never has either field set and cannot be
switched to hosting.
Authentication and security¶
Auth is device-local on purpose: the main server owns access control, and a satellite usually runs with the UI password off behind a PIN. The secret key, password, TOTP secret, and API keys are never synced.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
auth_required |
Editable | Editable | Device-local | |
auth_password |
Secret | Editable | Editable | Device-local |
viewer_password |
Secret | Editable | Editable | Device-local |
totp_secret |
Secret | Editable | Editable | Device-local |
local_totp_secret |
Secret | Editable | Editable | Device-local |
local_totp_enabled |
Toggle | Editable | Editable | Device-local |
local_totp_recovery |
Secret | Editable | Editable | Device-local |
api_key |
Secret | Editable | Editable | Device-local |
extra_api_keys |
Secret | Editable | Editable | Device-local |
secret_key |
Secret | Auto-generated | Auto-generated | Auto-generated |
local_device_pairing_enabled |
Editable | Editable | Not applicable |
secret_key is auto-generated on first run on every mode and persisted so
sessions survive a restart.
local_device_pairing_enabled (default on) lets a new Pi Remote on the same
network request its own API key from this server during its setup wizard: the
device and the server both display a short code, and nothing is issued until a
signed-in user confirms the codes match under Settings, Bandit Remotes. Requests are
only accepted from private (LAN) addresses. Turn it off to require creating
and pasting keys by hand. Not applicable on a satellite, which hands out no
keys of its own.
viewer_password is an optional second password for the household: it logs in
to a session that can use every kitchen page (inventory, timers, scanning,
recipes) but not Settings, backups, or updates, which stay behind the main
password. Leaving it blank turns the feature off. Like the main password it is
stored hashed and never synced between devices.
local_totp_secret, local_totp_enabled, and local_totp_recovery are this
device's own two-factor authentication for the login password (the counterpart
to a Forager account's 2FA). The secret and the hashed recovery codes are
device-local secrets, never shown back to the browser and redacted from the
support bundle; totp_secret is the earlier single-secret form, still honoured
so an install that turned 2FA on before this feature keeps working.
Backups (rclone and USB drive)¶
usb_backup_interval_hours schedules backups to an attached USB flash drive
(0 turns it off). Each device backs up its own data: a Pi Hosted box saves a
full stack snapshot, a Pi Remote saves its device config, and a server saves
the app-data zip. usb_backup_last records the last successful run and is
maintained by the app, not edited directly.
rclone_remote must be a plain rclone destination, either remote:path (for
example s3:mybucket/pantry) or an absolute path; anything else is rejected
on save.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
rclone_remote |
Editable | Editable | Device-local | |
rclone_schedule_hours |
Editable | Editable | Device-local | |
usb_backup_interval_hours |
Editable | Editable | Device-local | |
usb_backup_last |
Auto-maintained | Auto-maintained | Auto-maintained |
Printing (labels and recipes)¶
Every device on the network can see every other device's shared printer, so a
printer attached to one device is usable from all of them (the print stack turns
on CUPS sharing and runs cups-browsed, which makes a peer's shared printer show
up as a local queue). printing_enabled is the master switch, off by default and
device-local: each device decides whether it prints, and a device without a
printer keeps printing off no matter what the server does.
Printers are set once on the main server: label_printer_queue and
document_printer_queue are the server's (and a standalone Pi Hosted box's)
own printer choices. A Pi Remote does not pick its own printer; it always
prints through the server's queues, and if it has a printer attached (over
Bluetooth or its network) that printer is shared up and chosen on the server
instead. label_width_in, label_height_in, label_dpi, label_shape
(rectangle, square, or round stock), label_layout_presets (named saved
designs), and the document_page_size / document_color_mode /
document_duplex document-printer options all describe a printer's label
stock and print settings, so they are set and shown only on the server (and a
standalone Pi Hosted box); the Printing pane hides the Label size and label
designer sections entirely on a Pi Remote.
The label design itself travels with the fleet: label_layout_json (the
saved design) and label_show_logo are designed once on the main server and
pulled by every satellite, so a satellite that prints (on its own attached
printer or the fleet queue) prints the layout you set up centrally instead of
a plain fallback. The design stores its field positions proportionally and
re-fits itself to whatever label stock the printing device is loaded with, so
the physical label size (label_width_in, label_height_in, label_dpi)
stays with each device and is never synced.
The main server also picks a fleet default with fleet_label_printer_queue
and fleet_document_printer_queue, which is what a satellite falls back to
for identifying its own resolved printer before it forwards a print job to
the server.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
printing_enabled |
Device-local | Device-local | Device-local | |
label_printer_queue |
Editable | Editable | Not shown (prints through the server) | |
document_printer_queue |
Editable | Editable | Not shown (prints through the server) | |
fleet_label_printer_queue |
Set here (fleet default) | Set here (fleet default) | Inherited from server | |
fleet_document_printer_queue |
Set here (fleet default) | Set here (fleet default) | Inherited from server | |
label_width_in |
Editable | Editable | Device-local (no editor; not synced) | |
label_height_in |
Editable | Editable | Device-local (no editor; not synced) | |
label_dpi |
Editable | Editable | Device-local (no editor; not synced) | |
label_shape |
Editable | Editable | Not shown (server-only) | |
label_layout_json |
Editable | Editable | Inherited (read-only) | |
label_layout_presets |
Editable | Editable | Not shown (server-only) | |
label_show_logo |
Editable | Editable | Inherited (read-only) | |
document_page_size |
Editable | Editable | Not shown (server-only) | |
document_color_mode |
Editable | Editable | Not shown (server-only) | |
document_duplex |
Editable | Editable | Not shown (server-only) |
The print stack itself (CUPS, Bluetooth, and printer drivers) is off by default
and installed only when you ask for it: choose it during install, or press
Install now under Settings, Printing on a device without a printer set up yet.
That step writes two markers into the stack's environment file (not the settings
above): CUPS_SERVER, which points the app at the local print server, and
PRINTING_ENABLED, which the update process reads so an update keeps printing
working. Both are device-local and managed for you; you do not edit them by hand.
See Printing labels and documents for the everyday walkthrough and Label printing hardware for the in-app Bluetooth printer setup panel.
Bluetooth thermometers (probes)¶
Bluetooth kitchen thermometers (Inkbird, ThermoPro including the TempSpike, Combustion, ThermoWorks BlueDOT, and Govee grill thermometers) show live probe temperatures on the Timers page and raise on-screen alerts, plus a matching Home Assistant event, when a probe reaches its target. Settings, Thermometers is the management surface in every mode (server, Pi Hosted, Pi Remote): the feature toggle, the reader status, adding, renaming, and removing thermometers, per-probe role overrides, and the Home Assistant source (including Discover grills, which groups a grill's several HA entities into one device) all live there; day-to-day temperatures, doneness presets, and targets stay on the Timers page.
Readings can come from two sources, together or alone:
- The Bluetooth reader. The radio belongs to the host, not the app
container, so a small host-side reader service reads the thermometers and
reports to the app. On a Pi appliance the Thermometers & Sensors pane sets it up in
one click (Set up for me, through the host bridge, offered from the Probes
and Accessories sections alike); it also installs itself at provision time
when a plug-in accessory is detected (
ENABLE_GADGETS=auto, the default; force withtrue/false) or by hand (sudo foodassistant-gadgets-setup). On a plain server the reader is a host-side install: runscripts/image-build/foodassistant-gadgets-setupon a host with a Bluetooth radio (seegadgets/README.md); the pane shows those steps. A satellite (Pi Remote) with its own radio reads the same way and forwards what it finds to the main server, so those probes show up on both the server's Timers page and the satellite's own kiosk. - Home Assistant. If Home Assistant already sees the thermometers (directly or through Bluetooth proxies), the app reads their temperature entities over the Home Assistant connection it already stores, so a server with no Bluetooth radio still gets probes and target alerts.
gadgets_enabled is the master switch, off by default; adding your first
thermometer (from Timers or Settings) turns it on. gadget_devices holds the
added thermometers, their names, per-probe role overrides, and per-probe
targets. gadget_ha_enabled turns the Home Assistant source on (adding an
entity does it for you) and gadget_ha_entities lists the entity ids read as
probes. gadget_esp_enabled turns the ESPHome source on (adding a device does
it for you) and gadget_esp_devices lists the ESP devices polled over WiFi,
each an entry with a host, a sensor id, and a name. All are device-local: a
thermometer lives near one device's radio (or is forwarded from a satellite
that owns the radio), and the Home Assistant entities and ESP devices are
polled by the device that lists them.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
gadgets_enabled |
Device-local | Device-local | Device-local | |
gadget_devices |
Device-local | Device-local | Device-local | |
gadget_ha_enabled |
Device-local | Device-local | Device-local | |
gadget_ha_entities |
Device-local | Device-local | Device-local | |
gadget_esp_enabled |
Device-local | Device-local | Device-local | |
gadget_esp_devices |
Device-local | Device-local | Device-local |
Hygrometers (fridge, freezer, pantry, and room temperature + humidity
sensors: Govee H5075-class, Xiaomi LYWSD03MMC on the community ATC firmware,
SwitchBot Meter, Inkbird IBS-TH) are a separate device class read by the same
Bluetooth reader, with their own section in Settings, Thermometers & Sensors and their
own block on the Time & Temp page. hygrometers_enabled is the class's own
switch, off by default; adding your first hygrometer turns it on.
hygrometer_devices holds the added sensors with their names, location
labels, min/max alarm ranges, and alarm timing (the out-of-range grace
period and the optional stopped-reporting window; a reading outside its
range for longer than the grace raises an on-screen alarm that clears on
recovery). gadget_ha_hygrometers lists Home Assistant temperature +
humidity entity pairs read as hygrometers (under the same
gadget_ha_enabled toggle). Door contact sensors (Shelly BLU Door/Window
and other unencrypted BTHome v2 broadcasters, the SwitchBot Contact Sensor,
unencrypted Xiaomi door sensors) are their own class with the same shape:
contacts_enabled is the switch (adding the first sensor turns it on) and
contact_devices holds each sensor's name, location, and how long its door
may stay open before the alarm. All device-local, like the thermometer
fields.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
hygrometers_enabled |
Device-local | Device-local | Device-local | |
hygrometer_devices |
Device-local | Device-local | Device-local | |
gadget_ha_hygrometers |
Device-local | Device-local | Device-local | |
contacts_enabled |
Device-local | Device-local | Device-local | |
contact_devices |
Device-local | Device-local | Device-local |
Shelf buttons (stick-anywhere BLE push buttons: BTHome v2 devices like the
Shelly BLU Button1, unencrypted Xiaomi MiBeacon switches) are read by the
same Bluetooth reader, with their own Shelf buttons section in Settings,
Thermometers. buttons_enabled is the class's own switch, off by default;
adding your first button turns it on. button_devices holds the added
buttons with their names and the per-press-type mappings (single, double,
and long press each mapped to a shopping-list product or an action token).
Both device-local, like the thermometer fields.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
buttons_enabled |
Device-local | Device-local | Device-local | |
button_devices |
Device-local | Device-local | Device-local |
Plug-in accessories (STEMMA QT / Qwiic boards that connect straight to a Pi
appliance, starting with the NeoKey 1x4 scan-mode selector) have their own
Accessories section in Settings, Thermometers & Sensors. stemma_enabled is
the class's own switch, off by default; adding your first accessory turns it
on. stemma_devices holds the added boards, each keyed by its bus and
address (i2c:1:0x30), with a name and per-kind options (a NeoKey carries
its four key assignments, each a scanner mode, a page to open, or a timer
action, plus its LED brightness). Both are device-local
and, unlike the Bluetooth classes, are never pulled from or mirrored to a
main server: a board is plugged into one device, so it belongs to that
device. A server has nothing to plug a board into, so the section renders but
reports no connection.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
stemma_enabled |
Device-local (no bus) | Device-local | Device-local | |
stemma_devices |
Device-local (no bus) | Device-local | Device-local | |
neokey_rest_color |
Device-local (no bus) | Device-local | Device-local | |
neokey_timer_color |
Device-local (no bus) | Device-local | Device-local |
The two colors are what the keys wear: neokey_rest_color (default the brand
pink, #F2006E) away from the Manage screen, and neokey_timer_color
(default red, #FF0000) for the timer countdown bar and its finished-timer
flash. Both are picked on the device the pad is plugged into; a satellite
sends its own choice along with the LED poll, so the server never overrides
it.
A satellite usually stands in the kitchen with the Bluetooth radio while the
main server sits in a closet with none, so by default a satellite hands every
reading it hears to its server: the server then owns the sensor list, the
alarms, and the button actions for the whole house, and the satellite's own
screen shows the server's alarms too. relay_gadgets_upstream (on by default)
is the satellite's opt-out; it only renders on a Pi Remote, since nothing else
has a main server to relay to. upstream_gadget_config is the copy of the
server's sensor lists that the satellite mirrors on each sync, written by the
sync process rather than edited.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
relay_gadgets_upstream |
Not shown | Not shown | Editable (satellite-only) | |
upstream_gadget_config |
Not applicable | Not applicable | Written automatically (satellite-only) |
Bandit Cubs¶
What a Bandit Cub (a small companion display) shows is decided on the
server it polls, never on the device. cub_default_view is the idle view;
the takeover switches let running timers, an armed thermometer probe, or a
live fridge/door alarm seize the display (cub_alerts_take_over, on by
default, since spoiling groceries outrank everything); cub_rotation and
the two second-counts shape the idle rotation and the poll interval. These
live on a main install; a satellite's Cubs pair with the main server, so
the section does not render on Pi Remote.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
cub_default_view |
Editable | Editable | Not shown | |
cub_timers_take_over |
Editable | Editable | Not shown | |
cub_probes_take_over |
Editable | Editable | Not shown | |
cub_alerts_take_over |
Editable | Editable | Not shown | |
cub_rotation |
Editable | Editable | Not shown | |
cub_rotate_seconds |
Editable | Editable | Not shown | |
cub_poll_seconds |
Editable | Editable | Not shown | |
cub_auto_update |
Editable | Editable | Not shown | |
cub_ble_advertise |
Editable | Editable | Not shown | |
cub_ble_relay |
Not shown (config/env) | Not shown (config/env) | Not shown |
cub_auto_update (on by default, matching auto_update for the app itself)
lets a Cub keep its own firmware current: it checks the server it is paired
with for the firmware that goes with this install's version and flashes it
when the kitchen is quiet. Turn it off and a Cub only updates when someone
asks it to. Per-Cub overrides work here like the rest of this section, so one
Cub can sit still while the rest of the fleet follows along. The switch lives
in the Bandit Cubs panel of the Bandit Remotes pane, and each Cub's card has a
"Firmware updates" choice that either follows the fleet or overrides it.
cub_ble_relay (off by default) is the beacon's mirror image: instead of a
device broadcasting to Cubs, the Cubs listen for the kitchen sensors and
forward what they hear to this server, which decodes it. That is what gives a
server with no Bluetooth radio the fridge and freezer sensors, door sensors,
and shelf buttons standing near a Cub. It needs no radio on the server (the
point of it), but it does need a Cub flashed with the relay build option on,
and the server hands each Cub the list of sensors it can read, so the flag is
the only thing to set. No settings-pane row yet.
cub_ble_advertise (off by default) turns on the Bluetooth status beacon: a
device running the thermometer reader broadcasts the Cub summary's numbers
(counts, soonest timer, one probe temperature; never names) for battery
displays in radio range. It takes a Bluetooth radio and the reader to
broadcast, in practice a Pi appliance, but the flag is editable on a Docker
server too: a server's Bandits pull it down with the rest of the gadget
config, so a radio-less server is what turns its kitchen Bandit's beacon on.
Beszel monitoring hub¶
beszel_enabled and beszel_url control the optional link to a
Beszel hub (a separate, self-hosted
monitoring dashboard with history and graphs) from the Resources pane, above
the always-available built-in live snapshot; see
Device resources. One hub serves the whole fleet, so
both fields are set once on the main server and pulled by satellites, same as
the fleet auto-update flag.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
beszel_enabled |
Editable | Editable | Inherited (read-only) | |
beszel_url |
Editable | Editable | Inherited (read-only) |
Remote access tunnel¶
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
tunnel_mode |
Editable | Editable | Device-local | |
tunnel_token |
Editable | Editable | Device-local | |
tunnel_url |
Editable | Editable | Device-local | |
tunnel_enabled |
Editable | Editable | Device-local |
tunnel_mode is the single source of truth for remote access, chosen on the
Forager page in Settings (a main-install feature): "" (off), "cloudflare"
(the cloudflared container, keyed by tunnel_token), or "forager" (the
WireGuard hub tunnel). A legacy stored "subscription" reads as "forager".
tunnel_enabled tracks the Forager (WireGuard) tunnel and moves in step with
tunnel_mode == "forager". That tunnel is offered only on a Pi appliance,
which runs the host bridge that owns the WireGuard endpoint; the private key
stays on the device, so nothing secret is kept app-side.
Logging and updates¶
debug_logging is a per-device support toggle. auto_update and
update_channel are fleet-wide: both are pulled by satellites so a main server
and its remotes update (or hold) together, from the same source. The channel is
main (every change) or stable (releases only); main is the default for
now, with stable the recommended choice from release 0.8.0 on. check_for_updates
(FoodAssistant-31v4) is device-local, unlike auto_update: it controls only
whether THIS device's passive update-notice poller ever contacts GitHub on its
own. On by default; turning it off never disables the manual "Check for
updates" button, which is always a user-initiated, one-off check.
| Setting | Secret | Server | Pi Hosted | Pi Remote |
|---|---|---|---|---|
debug_logging |
Editable | Editable | Device-local | |
auto_update |
Editable | Editable | Inherited (read-only) | |
update_channel |
Editable | Editable | Inherited (read-only) | |
check_for_updates |
Editable | Editable | Device-local |