Configuration

Everything lives in one YAML file: /app/config.yaml in the container, or the path in --config or PLANESNITCH_CONFIG. The repository’s config.yaml.example is a working starting point.

planesnitch re-reads the file at the start of every poll. A valid change applies on the next poll without a restart, and a change also reloads the CSV watchlists. Every value is checked when the file loads. If an edited file is broken, planesnitch logs config reload failed, keeping current: <reason> and keeps running with the last good config. A broken file at startup stops it instead; see Troubleshooting.

Top level

Key Default Meaning
locations required Named places to watch
sources required Where aircraft data comes from
watchlists required What to look for, see Watchlists
alerts required Rules that connect watchlists to notification targets
notifications required Telegram and webhook targets, see Notifications
poll_interval 15 (seconds) Time between polls. A duration
display_units aviation Units in alert text and webhook payloads

All five required keys must be present, even if watchlists or notifications is empty.

Units

Any distance or altitude takes a unit suffix: km, mi, nm, ft or m, with or without a space. radius: 100mi and max_altitude: 1km both work. A plain number means km for distances and ft for altitudes.

Instead of a suffix you can use a suffixed key: radius_km, radius_mi or radius_nm for distances, and max_altitude_ft or max_altitude_m for altitudes. Set only one form per value. An unparseable value fails with invalid value for ..., and two forms of the same value fail with conflicting keys.

Durations

poll_interval and alert cooldown take plain seconds (90) or hours, minutes and seconds in that order: 90s, 5m, 2h, 1h30m.

Display units

display_units Altitude Distance Speed
aviation ft nm kts
metric m km km/h
imperial ft mi mph

Any other value stops startup.

Locations

locations:
  home:
    name: "Home"
    lat: 38.8719
    lon: -77.0563
    radius: 150km
  area51:
    name: "Area 51"
    lat: 37.2350
    lon: -115.8111
    radius: 50nm
Key Default Meaning
lat, lon required Decimal degrees
radius 150km Watch radius. Aircraft farther away never match, whatever the watchlist
name the key Shown in alerts and webhook payloads

At least one location is required. Locations close together are fetched with one request; see How it works.

Sources

sources:
  - type: adsb_lol
  - type: adsb_fi
  - type: airplanes_live
  - type: adsb_one
  - type: ultrafeeder
    url: http://ultrafeeder:80/data/aircraft.json
type Data Notes
adsb_lol Raw ADS-B fields adsb.lol public API
adsb_fi Adds type name, owner/operator, year adsb.fi open data API
airplanes_live Adds type name, owner/operator, year airplanes.live API
adsb_one Adds type name, owner/operator, year adsb.one API
ultrafeeder Raw fields from your own receiver Needs url, a readsb/tar1090 aircraft.json

Use several. Every source is queried each poll and the results are merged per aircraft, keeping the entry with the most filled-in fields. An unknown type is skipped.

Alerts

alerts:
  - name: "Military Spotter"
    watchlists: [military, government]
    locations: [home]
    cooldown: 5m
    notify: [tg_main, my_webhook]
Key Default Meaning
name required Rule name, shown in the alert. Must be unique: cooldowns are tracked by name
watchlists [] Watchlist names to check, in order
locations all locations Only check these location keys
cooldown 5m After a rule fires for an aircraft, the same rule ignores that aircraft for this long
notify [] Notification target names

Each rule fires at most once per aircraft per poll: the first watchlist and location that match win. Different rules are independent, so one aircraft can trigger several rules. Cooldowns live in memory and reset on restart.

Notifications

Targets are named, and rules refer to them by name. Full details and the payload format are on Notifications.

notifications:
  tg_main:
    type: telegram
    bot_token: "123456:ABC-DEF"
    chat_id: "-100123456789"
    attach_image: true

  my_webhook:
    type: webhook
    url: "https://example.com/hook"
    headers:
      Authorization: "Bearer xxx"
    attach_image: false
Key Type Default Meaning
type both required telegram or webhook
bot_token, chat_id telegram required Bot token and target chat. If either is empty, alerts for this target are skipped with a warning
url webhook required Where to POST
headers webhook none Extra request headers
attach_image both true Include the aircraft-type photo

Environment variables

Variable Default Meaning
PLANESNITCH_CONFIG config.yaml Config file path when --config is not given. The image’s command passes --config /app/config.yaml, so in Docker mount your file there or override the command
PLANESNITCH_CSV_DIR /csv Directory icao_csv watchlists read from
PLANESNITCH_IMAGES_DIR /images Aircraft-type photo cache
LOG_LEVEL INFO DEBUG logs every request, aircraft and match decision