Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration

A setting can come from four places. When more than one names the same setting, this is the order (highest wins):

CLI flag or its BIRDNET_* variable  >  the Settings page  >  /etc/birdnet/birdnet.conf  >  built-in default

That is one rule, and the rest of the manual means it: the Settings page says the same, and the code that does it is src/cli.rs and src/helpers/settings_overlay.rs.

  • A CLI flag and its BIRDNET_* variable are the same setting (the binary reads the variable when the flag is absent), so set one or the other. Either counts as explicit and beats the Settings page for good: a Docker station started with -e BIRDNET_SEGMENT_DURATION=30 keeps 30 whatever that field of the page says.
  • The Settings page is the SQLite settings table, edited at /admin/settings; it is also the canonical place for everything that has no flag or variable — the detection confidence threshold, per-species thresholds, sensitivity, email SMTP, quarantine rules, and so on. You do not need to touch any of these to get started. Each key in birdnet.conf (and each value passed as a flag or variable at install time) is copied into the table the first time the station sees it — insert-only, so nothing you saved on the page is ever overwritten. Once a key has a row there, editing that key in the file changes nothing: the page’s value is the one used. (That is why changing LATITUDE in the file does not move a station that has already started once: change it on the page.) Most values saved on the page take effect at the next restart.
  • birdnet.conf (kept for BirdNET-Pi compatibility) supplies the settings the page has no field for, and the first value of those it has.
  • A setting with no field on the page skips that level: the flag or variable, else the file, else the default.

Environment variables & CLI flags

The full list lives in birdnet-behavior --help, and .env.example documents every variable the binary reads; a test keeps the two and the code from drifting apart. Each row shows the environment variable, the matching CLI flag, and the birdnet.conf INI key (for BirdNET-Pi compatibility).

A key the station does not read is reported rather than ignored: a birdnet.conf line such as CONFIDENC=0.90, or an environment variable such as BIRDNET_LATITUD, is named at startup in the journal and by --doctor, with the nearest real name when one is close (“did you mean CONFIDENCE?”). Before this, a misspelt key was parsed, stored and silently left at its default.

Env varCLI flagbirdnet.conf keyDefault
BIRDNET_LATITUDE / BIRDNET_LONGITUDE--latitude / --longitudeLATITUDE / LONGITUDE—
BIRDNET_ALSA_DEVICE / BIRDNET_ALSA_DEVICES--alsa-device / --alsa-devicesALSA_CARD / ALSA_CARDS—
BIRDNET_PIPEWIRE_DEVICE--pipewire-device——
BIRDNET_RTSP_URL / BIRDNET_RTSP_URLS--rtsp-url / --rtsp-urlsRTSP_URL / RTSP_URLS—
BIRDNET_LISTEN--listen—0.0.0.0:8502
TZ——UTC in the container. An IANA zone name (Europe/Berlin); the container files detections under this zone’s local hours, and warns at start when it is unset or not a zone the image knows. quickstart.sh writes the host’s zone into .env; compose sets no default of its own. On a host, the zone comes from the system (timedatectl set-timezone).
BIRDNET_ANALYTICS_DB--analytics-dbANALYTICS_DB_PATH<database>.duckdb beside the SQLite file; --analytics-db "" turns analytics off
BIRDNET_SKIP_MIGRATION_BACKUP——unset. Any value but empty or 0 lets a history-rewriting migration run without the backup it otherwise takes first — for a station whose disk has no room for a copy of the database, accepting that the previous timestamps cannot be recovered
BIRDNET_RECORDING_SCHEDULE--recording-scheduleRECORDING_SCHEDULEall-day
BIRDNET_SEGMENT_DURATION--segment-durationSEGMENT_DURATION (BirdNET-Pi’s RECORDING_LENGTH is read as this when SEGMENT_DURATION is absent or blank)15
BIRDNET_OVERLAP--overlapOVERLAP0.0
BIRDNET_METADATA_MODEL--metadata-modelMETADATA_MODEL_PATHset by the installer / entrypoint
BIRDNET_METADATA_LABELS--metadata-labelsMETADATA_LABELS_PATHset by the installer / entrypoint
BIRDNET_SPECIES_ALIASES--species-aliasesSPECIES_ALIASES_PATH— (a tab-separated legacy<TAB>canonical scientific-name map, for species the geomodel and the classifier name differently and the automatic rules cannot connect — see tuning)
——WEATHER_PROVIDERopen-meteo; also met-no (MET Norway, keyless), pirate-weather (needs WEATHER_API_KEY) and wunderground (your own personal weather station). An unimplemented name does not start the poll — see the weather overlay
——WEATHER_STATION_ID— (wunderground only: the station’s Weather Underground id)
BIRDNET_WEATHER_API_KEY_FILE—WEATHER_API_KEY— (wunderground and pirate-weather; mountable from a file like the other credentials)
BIRDNET_EBIRD_API_KEY_FILE—EBIRD_API_KEY— (absent ⇒ eBird corroboration is off entirely; mountable from a file like the other credentials — see eBird)
——EBIRD_REGION— (empty ⇒ the station’s own LATITUDE/LONGITUDE are used, which is usually better)
——EBIRD_DIST_KM25 (0–50; the radius asked about when using coordinates)
——EBIRD_BACK_DAYS14 (1–30; days of eBird history to ask about)
BIRDNET_SF_THRESH--sf-threshSF_THRESH0.03 (no effect without a metadata model)
BIRDNET_PRIVACY_THRESHOLD--privacy-thresholdPRIVACY_THRESHOLD0.0 (off). The model’s confidence for a human sound at or above which a window is suppressed (typically 0.01–0.03). Not BirdNET-Pi’s PRIVACY_THRESHOLD, which is a percentage: use PRIVACY_RANK below for BirdNET-Pi’s rule
BIRDNET_PRIVACY_RANK--privacy-rankPRIVACY_RANK10 (0 = off, up to 12000). BirdNET-Pi’s human-sound rule: a window, and the windows either side of it, are suppressed when a human class ranks in the model’s top N classes, read before the detection threshold. On by default, including on a station that never set it. Either this rule or PRIVACY_THRESHOLD suppresses a window. A field on the Settings page (Privacy Rank, Detection); a flag or variable other than 10 beats it, while one left at 10 is the default and yields to the page. For a BirdNET-Pi PRIVACY_THRESHOLD of p, use max(10, 60 × p) here and 0 there — see Same audio, same detections
BIRDNET_NOISE_THRESHOLD--noise-thresholdNOISE_THRESHOLD0.0
BIRDNET_NOISE_CLASSES--noise-classesNOISE_CLASSESDog
——NOISE_REMEMBER_SECS0.0 (off; keeps suppressing the species a bark produced for this long after it — see tuning)
BIRDNET_CONFIRMATION_LEVEL--confirmation-levelCONFIRMATION_LEVELoff (needs OVERLAP)
BIRDNET_OFFSITE_BACKUP--offsite-backupOFFSITE_BACKUPoff; also s3, sftp and rsync (the --help text lists three)
BIRDNET_OFFSITE_PASSPHRASE— (deliberately no flag)OFFSITE_PASSPHRASE—
BIRDNET_OFFSITE_KEEP—OFFSITE_KEEP8
BIRDNET_OFFSITE_S3_ENDPOINT—OFFSITE_S3_ENDPOINT—
BIRDNET_OFFSITE_S3_BUCKET—OFFSITE_S3_BUCKET—
BIRDNET_OFFSITE_S3_PREFIX—OFFSITE_S3_PREFIX(none)
BIRDNET_OFFSITE_S3_REGION—OFFSITE_S3_REGIONus-east-1
BIRDNET_OFFSITE_S3_ACCESS_KEY—OFFSITE_S3_ACCESS_KEY—
BIRDNET_OFFSITE_S3_SECRET_KEY— (deliberately no flag)OFFSITE_S3_SECRET_KEY—
BIRDNET_OFFSITE_S3_ADDRESSING—OFFSITE_S3_ADDRESSINGauto
BIRDNET_OFFSITE_SFTP_HOST—OFFSITE_SFTP_HOST—
BIRDNET_OFFSITE_SFTP_PORT—OFFSITE_SFTP_PORT22
BIRDNET_OFFSITE_SFTP_USER—OFFSITE_SFTP_USER—
BIRDNET_OFFSITE_SFTP_DIR—OFFSITE_SFTP_DIR—
BIRDNET_OFFSITE_SFTP_IDENTITY—OFFSITE_SFTP_IDENTITY—
BIRDNET_OFFSITE_SFTP_KNOWN_HOSTS—OFFSITE_SFTP_KNOWN_HOSTSbeside the identity file
BIRDNET_OFFSITE_SFTP_HOST_KEY_POLICY—OFFSITE_SFTP_HOST_KEY_POLICYyes
BIRDNET_DUPLICATE_INTERVAL_SECS--duplicate-interval-secsDUPLICATE_INTERVAL_SECS0
BIRDNET_NIGHT_FILTER--night-filterNIGHT_FILTERoff
BIRDNET_NIGHT_MARGIN_MINS--night-margin-minsNIGHT_MARGIN_MINS60
BIRDNET_NIGHT_EXTRA_NOCTURNAL--night-extra-nocturnalNIGHT_EXTRA_NOCTURNAL—
BIRDNET_NOTIFY_URLS--notify-urlsNOTIFY_URLS—
BIRDNET_APPRISE_URL--apprise-urlAPPRISE_URL—
BIRDNET_NOTIFY_CONFIDENCE--notify-confidenceAPPRISE_MIN_CONFIDENCE0.8
BIRDNET_DEADMAN_HOURS--deadman-hoursDEADMAN_HOURS24 (0 = off)
BIRDNET_BIRDWEATHER_TOKEN--birdweather-tokenBIRDWEATHER_TOKEN—
BIRDNET_BIRDWEATHER_URL—BIRDWEATHER_URLpublic BirdWeather
BIRDNET_MQTT_HOST--mqtt-hostMQTT_HOST—
BIRDNET_MQTT_HA_DISCOVERY--mqtt-ha-discovery—disabled
BIRDNET_MAX_FILES_PER_SPECIES--max-files-per-speciesMAX_FILES_SPECIES0
BIRDNET_CLIP_RETENTION_DAYS--clip-retention-daysCLIP_RETENTION_DAYS0 (keep forever)
BIRDNET_DISK_PURGE_THRESHOLD--disk-purge-thresholdDISK_PURGE_THRESHOLD95 (BirdNET-Pi calls it PURGE_THRESHOLD)
——FULL_DISKpurge. What happens at that threshold: purge deletes the oldest clips of the most-recorded species (never below PURGE_SPECIES_FLOOR, never a locked one); keep stops recording, deletes nothing and records again by itself once usage is 2 points below the threshold, as BirdNET-Pi’s FULL_DISK=keep does
BIRDNET_PURGE_SPECIES_FLOOR--purge-species-floorPURGE_SPECIES_FLOOR5 (0 = no floor)
BIRDNET_STREAM_RETENTION_SECS--stream-retention-secsSTREAM_RETENTION_SECS600
BIRDNET_STREAM_MAX_MB--stream-max-mbSTREAM_MAX_MB512
BIRDNET_RAW_AUDIO_KEEP_EVERY--raw-audio-keep-everyRAW_AUDIO_KEEP_EVERY0 (keep no raw audio; 1 keeps every segment, N one in N)
CADDY_PWD / CADDY_USER—CADDY_PWD / CADDY_USERCADDY_PWD auto-set on bare-metal install; sign in as admin (CADDY_USER is environment-only — see Remote access)
BIRDNET_PRIVATE_MODE--private-modePRIVATE_MODEoff (viewing is open). true puts the whole station behind the sign-in; needs CADDY_PWD, or everything but the sign-in answers 503. See Hardening
BIRDNET_PUBLIC_ACCESS--public-accessPUBLIC_ACCESS— (nothing carved out). Comma-separated live_audio, share, metrics; no effect without private mode
BIRDNET_CORS_ALLOWED_ORIGINS——— (same-origin only)

Invalid settings are not run. On startup the station validates the configuration. If a value is out of range (e.g. a latitude outside ±90, or a malformed RECORDING_SCHEDULE), it runs on the last configuration that passed, or — when there is none — starts web-only, recording nothing, so the dashboard can still tell you what is wrong. Both are reported in the journal and by birdnet-behavior --doctor; run the doctor on a config before deploying it, or apply it with --apply-config, which refuses a file that does not validate.

BIRDNET_LISTEN binds all interfaces by default (0.0.0.0:8502), so the dashboard is reachable across your LAN out of the box. Viewing is open; anything that changes something requires a password — the /admin panel, and also deleting, relabelling, reviewing or locking a detection, or saving the onboarding wizard. A fresh bare-metal install auto-generates CADDY_PWD (username admin) and prints it once in the post-install summary — change it via CADDY_PWD in birdnet.conf. To restrict the dashboard to the local machine, set BIRDNET_LISTEN=127.0.0.1:8502. The authentication (CADDY_PWD) and cross-origin (BIRDNET_CORS_ALLOWED_ORIGINS) settings are covered in Remote Access & Security.

What the station connects to

Two connections are made on the station’s own initiative, with no configuration:

HostWhyTurn it off with
api.github.comOnce 60 s after start and every 24 h after: checks whether a newer release exists and logs the answer. It never installs anything; an update is applied with sudo bash install.sh update (a systemd station cannot replace its own binary, so the admin panel does not try).--no-update-check / BIRDNET_NO_UPDATE_CHECK=1
en.wikipedia.org, upload.wikimedia.orgDownloads a photo the first time a species is detected, then serves it from the local cache for ever.--image-cache-dir ""

One more can happen once, on a first run: if the bundled duckdb-behavioral extension cannot be loaded from the local cache or the copy embedded in the binary, DuckDB tries the community registry (extensions.duckdb.org). Release binaries carry the extension, so this normally never fires.

Everything else is off until you configure it, and configuring it is the consent: Apprise, BirdWeather, MQTT, SMTP e-mail, the heartbeat ping, and the weather poll (api.open-meteo.com by default; api.met.no, api.weather.com or api.pirateweather.net for the other WEATHER_PROVIDERs — itself opt-in via BNB_WEATHER_ENABLED=1). The location button calls ipwho.is (and get.geojs.io if that does not answer), over TLS and only when you press it. The request tells that service this station’s public IP address, which is how it finds the area; no station data is sent. You review the coordinates before saving them.

Offline mode

BIRDNET_OFFLINE=1        # or: --offline

Turns off both default-on connections at once — the update check and the image downloads — so the station makes no outbound connection you did not ask for. Integrations you configured explicitly keep working: offline mode is about unsolicited traffic, not about muting your alerts.

Use it on metered or cellular links, on air-gapped deployments, and wherever “what does this contact?” needs a single answer. Already-cached species images are still served; only new downloads stop.

birdnet-behavior --doctor reports the current posture under Outbound connections, so you can confirm it rather than infer it.

Web-UI-only settings

These are stored in the SQLite settings table and have no environment variable or command-line flag; a few also have a birdnet.conf key, noted beside them. That key is copied into the settings table the first time the station sees it; after that the value saved on the page is the one the station uses. Set them at /admin/settings — see Settings & Detection.

SettingWhereNote
Detection confidence thresholdDetectionAlso CONFIDENCE in birdnet.conf; default 0.70 (BirdNET-Pi’s; it was 0.75 up to v0.17.1). Per-species overrides also live here
Detection sensitivity (0.5–1.5)DetectionAlso SENSITIVITY in birdnet.conf; default 1.25. It means what it means in BirdNET-Pi on a V2.4 model and is ignored by V3.0 — see Settings
Email / SMTP notificationsNotifications
Rare-bird quarantine rulesSpecies
BirdWeather station detailsBirdWeatherToken can also be set via env var

Retention is off by default. Nothing is deleted by age unless you ask for it: set Keep Clip Audio (days) in the UI (CLIP_RETENTION_DAYS) to reclaim the audio of older detections. Independently of that, the disk manager purges the oldest recordings once the disk hits DISK_PURGE_THRESHOLD (default 95%) and keeps at most BIRDNET_MAX_FILES_PER_SPECIES per species. Pin clips you want to keep with the lock action on any detection — locked clips are never purged by either limit.

All three limits, plus the temporary streaming folder’s retention and size ceiling, can be set from Settings → General → System & Display in the web UI; you never have to edit a config file to change them. A value given on the command line or as a BIRDNET_* variable wins over the UI, which in turn wins over the config file (the order at the top of this page).

When a clip is purged the detection itself is kept — its filename and the date the audio was reclaimed stay on the record, so counts, species lists, trends and exports are unaffected. Only the audio goes.