> ## Documentation Index
> Fetch the complete documentation index at: https://docs.altnautica.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

> Structure and key settings of the /etc/ados/config.yaml file.

# Configuration

The agent's configuration lives at `/etc/ados/config.yaml`. It is a single YAML file validated by Pydantic models at load time. Every field has a sensible default, so a minimal config (or no config file at all) produces a working agent.

## Config search order

When the agent starts, it looks for config in this order:

1. Path passed as argument or environment variable (`ADOS_CONFIG`)
2. `/etc/ados/config.yaml`
3. `./config.yaml` (current directory)
4. Pure defaults (no file needed)

## Full config structure

The config is organized into 16 top-level sections. Here is the complete structure with defaults:

```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
agent:
  device_id: ""           # Auto-generated on first boot
  name: "my-drone"        # Human-readable name
  tier: "auto"            # auto | 1 | 2 | 3 | 4
  profile: "auto"         # auto | drone | ground_station

mavlink:
  serial_port: ""         # Auto-detected if empty
  baud_rate: 57600        # Common: 57600, 115200, 921600
  system_id: 1
  component_id: 191
  # MAVLink v2 message signing is managed from the GCS. The key lives in
  # the browser; the agent holds no key material. See /drone-agent/mavlink-signing.
  endpoints:
    - type: websocket
      host: "0.0.0.0"
      port: 8765
      enabled: true

video:
  mode: "wfb"             # wfb | rtsp | disabled
  wfb:
    interface: ""          # RTL8812EU interface, auto-detected
    channel: 149           # 5 GHz channel
    tx_power: 25           # dBm
    fec_k: 8              # FEC data blocks
    fec_n: 12             # FEC total blocks (data + parity)
  camera:
    source: "csi"         # csi | usb | test
    codec: "h264"         # h264 | h265
    width: 1280
    height: 720
    fps: 30
    bitrate_kbps: 4000
  recording:
    enabled: false
    path: "/var/ados/recordings"
    max_duration_minutes: 30
  cloud_relay_url: ""

network:
  wifi_client:
    enabled: false
    ssid: ""
    password: ""
  cellular:
    enabled: false
    apn: ""
  hotspot:
    enabled: false
    ssid: "ADOS-{device_id}"
    password: "altnautica"
    channel: 6

server:
  mode: "local"           # cloud | self_hosted | local
  cloud:
    url: "https://your-convex.example.com:3211"   # Convex site origin (HTTP actions)
    mqtt_broker: "your-mqtt.example.com"
    mqtt_port: 443
  self_hosted:
    url: "https://your-convex.example.com:3211"   # Convex site origin (HTTP actions)
    mqtt_broker: "your-mqtt.example.com"
    mqtt_port: 8883
    api_key: ""
  telemetry_rate: 2       # Hz, MQTT publish rate
  heartbeat_interval: 5   # Seconds
  mqtt_transport: "websockets"  # websockets | tcp
  mqtt_username: "ados"
  mqtt_password: ""

remote_access:
  provider: "none"        # none | cloudflare
  public_urls: []
  cloudflare: {}          # Cloudflare Tunnel quick-install settings

security:
  tls:
    enabled: true
    cert_path: "/etc/ados/certs/device.crt"
    key_path: "/etc/ados/certs/device.key"
    ca_path: "/etc/ados/certs/ca.crt"
  wireguard:
    enabled: false
    config_path: "/etc/wireguard/ados.conf"
  api:
    api_key: ""
    cors_enabled: true
    cors_origins: []          # Built-in localhost defaults always apply
    cors_origins_extra: []    # Extra origins added on top of the defaults
  hmac_enabled: false
  hmac_secret: ""

api:
  rest:
    enabled: true
    host: "0.0.0.0"
    port: 8080
  mission_control_url: ""

logging:
  level: "info"           # debug | info | warning | error
  max_size_mb: 50
  keep_count: 5
  flight_log_dir: "/var/ados/logs/flights"

pairing:
  state_path: "/etc/ados/pairing.json"
  convex_url: ""
  beacon_interval: 30
  heartbeat_interval: 60
  code_ttl: 900

discovery:
  mdns_enabled: true
  service_type: "_ados._tcp.local."

vision:
  enabled: false
  backend: "auto"         # auto | rknn | tensorrt | opencv_dnn | tflite
  confidence_threshold: 0.5
  models_dir: "/opt/ados/models/vision"
  models_cache_max_mb: 500
  auto_download: true

swarm:
  enabled: false
  lora:
    interface: ""
    frequency: 915000000
    bandwidth: 125000
    spreading_factor: 7
  wifi_direct:
    enabled: false
    interface: ""
  role: "auto"
  default_formation: "line"
  default_spacing: 10

ground_station:
  share_uplink: false
  paired_drone_id: null
  paired_at: null
  ui:
    oled: {}
    buttons: {}
    screens: {}
  use_live_state_ipc: true

ui:
  theme: "dark"             # dark | light
```

## Key settings explained

### Agent profile

```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
agent:
  profile: "auto"  # auto | drone | ground_station
```

When set to `auto`, the agent fingerprints the hardware at boot. If it finds an OLED on I2C, GPIO buttons, an RTL8812EU in receive mode, and no flight controller, it picks `ground_station`. Otherwise it picks `drone`.

Force a specific profile by setting it explicitly.

### MAVLink serial port

```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
mavlink:
  serial_port: ""
  baud_rate: 57600
```

Leave `serial_port` empty for auto-detection. The agent scans `/dev/ttyS*`, `/dev/ttyAMA*`, and `/dev/ttyACM*` based on the board profile's `uart_paths`. It tries each port at the configured baud rate and looks for MAVLink heartbeats.

Common baud rates: 57600 (ArduPilot default), 115200 (PX4 default), 921600 (high-speed telemetry).

### Video codec

```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
video:
  camera:
    codec: "h264"
    bitrate_kbps: 4000
```

Use `h264` for maximum compatibility. Browser-based players (MSE, WebRTC) expect `avc1.640029` (H.264 High Profile Level 4.1). H.265 saves bandwidth but browser support is inconsistent for WebRTC.

### Cloud server mode

```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
server:
  mode: "local"  # cloud | self_hosted | local
```

* **cloud**: connects to the ADOS cloud backend.
* **self\_hosted**: connects to your own MQTT broker and Convex instance.
* **local**: no cloud connectivity; Mission Control reaches the agent over the LAN. Default.

<Warning>
  For both `cloud` and `self_hosted` modes, the `url` must point at the Convex **site** origin on port `:3211` (HTTP actions: pairing register, heartbeat, command poll), not the client API on `:3210`. If you paste the `:3210` URL, the register call lands on the wrong origin and returns a 404. The agent normalizes a known `:3210` URL to `:3211` as a safety net, but set `:3211` explicitly. See [Self-hosting the agent](/developers/self-hosting/agent).
</Warning>

### Vision backend

```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
vision:
  enabled: false
  backend: "auto"
```

When `auto`, the agent probes for available inference backends in order: RKNN (Rockchip NPU), TensorRT (NVIDIA), OpenCV DNN, TFLite. It picks the first one that initializes successfully.

## Reading and writing config

Use the setup webapp for common MAVLink, video, network, and remote-access
settings. Advanced users can edit `/etc/ados/config.yaml` directly or use the
REST API.

### From the REST API

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Read config
curl http://localhost:8080/api/config \
  -H "X-ADOS-Key: your_key"

# Write a value
curl -X PUT http://localhost:8080/api/config \
  -H "X-ADOS-Key: your_key" \
  -H "Content-Type: application/json" \
  -d '{"key": "video.camera.fps", "value": "25"}'
```

### Editing the file

You can edit `/etc/ados/config.yaml` directly with any text editor, then restart the affected service (see the tip at the end of this page). The terminal status page (`ados`) is read-only and does not edit config.

## Per-board overrides

The install script writes board-specific overrides into `/etc/ados/config.yaml` during installation. For example, a Raspberry Pi 4B gets:

```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
mavlink:
  serial_port: "/dev/ttyAMA0"
```

While a Radxa ROCK 5C Lite gets:

```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
mavlink:
  serial_port: "/dev/ttyS0"
  baud_rate: 921600
```

These overrides are merged on top of the built-in defaults. Your manual edits always take priority.

<Tip>
  After editing the config file manually, restart the affected service for changes to take effect. For example, `sudo systemctl restart ados-mavlink` after changing the baud rate.
</Tip>
