config.yaml reference
This is the complete reference for the add-on configuration file, generated
from the Supervisor's validation schema. The file may be config.yaml,
config.yml, or config.json.
Two general rules of the schema:
- Unknown keys are silently removed (
REMOVE_EXTRA), not rejected. A typo in a key name means the setting simply does not apply. - Several deprecated spellings are migrated on ingest with a logged warning (see Migrations and legacy keys).
Required keys
| Key | Type | Description |
|---|---|---|
name | string | Human-readable add-on name. |
version | version string | Add-on version; also used as the image tag for prebuilt images. |
slug | string matching [-_.A-Za-z0-9]+ | Unique identifier within the repository. Also the Docker container name suffix and the AppArmor profile name. |
description | string | Short description shown in the store. |
arch | list | Supported CPU architectures. Supported values: aarch64, amd64. The values armhf, armv7, i386 are still accepted but deprecated and trigger a warning. |
Identity and lifecycle
| Key | Type / values | Default | Description |
|---|---|---|---|
url | URL | — | Homepage of the add-on (rendered in the store; also stamped as the io.apexos.url image label). |
machine | list (unique) | — | Restrict to specific machine types. Allowed values: intel-nuc, khadas-vim3, generic-aarch64, generic-x86-64, odroid-c2, odroid-c4, odroid-m1, odroid-n2, odroid-xu, qemuarm-64, qemuarm, qemux86-64, qemux86, raspberrypi, raspberrypi2, raspberrypi3-64, raspberrypi3, raspberrypi4-64, raspberrypi4, raspberrypi5-64, yellow, green, tinker. Prefix with ! to exclude a machine. Several of these (odroid-xu, qemuarm, qemux86, raspberrypi–raspberrypi4, tinker) are deprecated and warn. |
startup | initialize | system | services | application | once | application | Startup phase ordering: initialize starts first (system-critical), then system (e.g. databases), then services (e.g. brokers), then application; once is for one-shot jobs that are not restarted. |
boot | auto | manual | manual_only | auto | Whether the add-on starts at device boot. manual_only forces manual boot and hides the user's auto-boot toggle (it is coerced to manual in user data). |
init | bool | true | Whether the container image's default init handling is used. Set false when your image ships its own init/service manager (all official add-ons using s6-overlay set init: false). |
stage | stable | experimental | deprecated | stable | Maturity flag surfaced in the store. |
apexos | version string | — | Minimum ApexOS Core version required by this add-on. |
timeout | int 10–300 | 10 | Seconds the Supervisor waits for the container to stop before killing it. |
breaking_versions | list of version strings | [] | Versions considered breaking: crossing one blocks unattended/auto updates so the user updates deliberately (zigbee2mqtt declares 2.0.0-1). |
legacy | bool | false | Compatibility mode for images without current metadata labels. When true, add-on options with scalar values are additionally injected as container environment variables. |
advanced | bool | false | Deprecated and ignored. Declaring it logs a warning. |
Network
| Key | Type | Default | Description |
|---|---|---|---|
ports | map "port/proto" → host port or null | — | Container ports exposed to the host. Keys look like 22/tcp; values are the host port (1–65535) or null for "disabled by default, user may assign one" (the ssh add-on ships 22/tcp: null). |
ports_description | map "port/proto" → string | — | Human-readable label per port, shown in the UI next to the port field. |
host_network | bool | false | Run on the host network namespace instead of the internal add-on network. ports mapping no longer applies; see security for the implications. |
webui | template string | — | URL template for the "Open Web UI" button. Must match ^(?:https?|[PROTO:<option>]):\/\/[HOST]:[PORT:<port>]...$ — e.g. http://[HOST]:[PORT:8080]/. [HOST] and [PORT:x] are resolved to the add-on's address and the actual host port mapped for container port x; [PROTO:option_name] switches to https when that boolean option is true. |
Ingress (embedded web UI)
Ingress serves the add-on's web interface through the ApexOS UI, authenticated by the platform — without exposing any host port.
| Key | Type | Default | Description |
|---|---|---|---|
ingress | bool | false | Enable ingress for this add-on. |
ingress_port | port or 0 | 8099 | Container port your web server listens on for ingress traffic. 0 requests a dynamically assigned port in the range 62000–65500, which the add-on must read at runtime from the Supervisor API. |
ingress_entry | string | — | Path appended to the generated ingress URL as the entry point. |
ingress_stream | bool | false | Stream request/response bodies through ingress (for long-lived/streaming endpoints). |
panel_icon | string | mdi:puzzle | Material Design Icons name for the sidebar panel. |
panel_title | string | add-on name | Sidebar panel title (the ssh add-on uses Terminal). |
panel_admin | bool | true | Restrict the sidebar panel to admin users. |
The ingress URL is generated as /api/supervisor_ingress/<token>/, where the
token is a per-installation secret. Requests arrive on ingress_port from the
Supervisor after the user session was validated.
Validation guard: an add-on with ingress_port: 0 must not map any
container port in the 62000–65500 range via ports: — the dynamically chosen
ingress port could collide with it and expose the ingress endpoint on the host,
bypassing ingress authentication. This combination is rejected outright.
Storage: map, tmpfs, and backups
Every add-on always gets its private data directory mounted read-write at
/data — no declaration needed. Anything else must be requested with map.
map
A list of shared folders to mount. Two forms are accepted:
- String form:
tokenortoken:rw— read-only unless:rwis given. - Dict form:
{type: <token>, read_only: <bool, default true>, path: <container path>}— additionally lets you choose the mount point inside the container.
# String form (samba)
map:
- addons:rw
- apexos_config:rw
- ssl:rw
# Dict form (zigbee2mqtt)
map:
- type: share
read_only: false
- type: apexos_config
read_only: false
path: /config
The full token list, with each token's default container path:
| Token | Default mount point | Contents |
|---|---|---|
data | /data | The add-on's own private storage (mounted anyway; the token only lets you change its path). |
apexos_config | /apexos | The ApexOS Core configuration directory. |
addon_config | /config | This add-on's public configuration folder (user-visible, kept across reinstalls). |
all_addon_configs | /addon_configs | The public configuration folders of all add-ons. |
ssl | /ssl | Shared TLS certificates/keys. |
addons | /addons | The local add-on repository (local development sources). |
backup | /backup | Backup archives. |
share | /share | General data shared between add-ons and ApexOS. Mounted with rslave propagation. |
media | /media | Local media files. Mounted with rslave propagation. |
config | /config | Deprecated. The old combined configuration mount; use apexos_config (and/or addon_config) instead. If config is present, addon_config and apexos_config are ignored with a warning. |
Invalid map entries (bad token, dict without type) are skipped with a logged
warning rather than failing installation.
Other storage keys
| Key | Type | Default | Description |
|---|---|---|---|
tmpfs | bool | false | Mount a tmpfs into the container. (The old string form with size/options is deprecated and coerced to true.) |
backup | hot | cold | hot | Backup mode. hot backs up while running; cold stops the add-on for the backup. Declaring backup_pre/backup_post together with cold warns — they only make sense for hot backups. |
backup_pre | string | — | Command run inside the container before a hot backup. |
backup_post | string | — | Command run inside the container after a hot backup. |
backup_exclude | list of strings | — | File patterns excluded from the add-on backup. |
Hardware and device access
| Key | Type | Default | Description |
|---|---|---|---|
devices | list of paths | — | Specific host device paths to expose (e.g. /dev/ttyAMA0). The old path:path:perm form is deprecated; only the path is used. |
uart | bool | false | Auto-expose serial/UART devices. (Old key auto_uart is migrated.) |
usb | bool | false | Auto-expose USB devices. |
gpio | bool | false | Expose GPIO. |
devicetree | bool | false | Expose the device tree. |
udev | bool | false | Take part in udev device handling (the zigbee2mqtt add-on sets this together with uart). |
kernel_modules | bool | false | Access to kernel module loading. Lowers the security rating. |
audio | bool | false | Attach the add-on to the audio subsystem (Pulse configuration is generated for it). |
video | bool | false | Expose video devices. |
full_access | bool | false | Full hardware access. Combining it with devices/uart/usb/gpio warns — it makes selective access redundant. Forces the lowest security rating and its effect additionally requires protection mode to be off. |
realtime | bool | false | Grant real-time CPU scheduling (a fixed runtime allocation sized for up to 5 concurrent RT containers). |
Host namespaces and privileges
| Key | Type | Default | Description |
|---|---|---|---|
privileged | list of capabilities | — | Additional Linux capabilities: BPF, CHECKPOINT_RESTORE, DAC_READ_SEARCH, IPC_LOCK, NET_ADMIN, NET_RAW, PERFMON, SYS_ADMIN, SYS_MODULE, SYS_NICE, SYS_PTRACE, SYS_RAWIO, SYS_RESOURCE, SYS_TIME. |
host_pid | bool | false | Share the host PID namespace. Only effective with protection mode disabled. |
host_ipc | bool | false | Share the host IPC namespace. |
host_uts | bool | false | Share the host UTS namespace (with SYS_ADMIN this allows setting the hostname). |
host_dbus | bool | false | Mount the host system D-Bus socket (the ssh add-on uses this). |
apparmor | bool | true | AppArmor confinement. true = Docker default profile, or your custom apparmor.txt if shipped; false = disabled (lowers the security rating). See security. |
journald | bool | false | Access the host system journal. |
Supervisor, Core, and service APIs
| Key | Type / values | Default | Description |
|---|---|---|---|
apexos_api | bool | false | Allow calling the Supervisor REST API (http://supervisor) with the injected SUPERVISOR_TOKEN. |
apexos_role | default | apexos | backup | manager | admin | default | Which Supervisor API surface the token may reach: default — info endpoints only; apexos — additionally Core API/proxy endpoints; backup — additionally backup endpoints; manager — most management endpoints (add-ons, host, network, store, ...); admin — everything. See security for the exact route map. |
apexos_core_api | bool | false | Allow calling the ApexOS Core API through the Supervisor proxy. |
auth_api | bool | false | Allow validating user credentials against the platform's authentication backend. |
docker_api | bool | false | Read access to the Docker API. Forces the lowest security rating and only takes effect with protection mode disabled. |
stdin | bool | false | Allow sending input to the container over the Supervisor's stdin API. |
services | list of service:rights | — | Declare service dependencies. Service may be mqtt or mysql; rights are provide (this add-on offers the service), want (uses it if present), or need (requires it) — e.g. mqtt:need in zigbee2mqtt. |
discovery | list of strings | — | Services this add-on announces to ApexOS Core via the discovery API. |
Environment and tokens
Every add-on container is started with:
SUPERVISOR_TOKEN— a per-installation secret used as the Bearer token for the Supervisor API (this same token also drives theX-Supervisor-Tokenheader). Access is only granted if the matchingapexos_api/apexos_core_api/ role settings allow it.TZ— the system timezone.
Additional static variables can be declared with:
| Key | Type | Description |
|---|---|---|
environment | map of name → string | Extra environment variables set on the container. |
Runtime supervision
| Key | Type | Default | Description |
|---|---|---|---|
watchdog | template string | — | Health-check URL template: ^(?:https?|[PROTO:<option>]|tcp)://[HOST]:(<port>|[PORT:<port>])...$, e.g. tcp://[HOST]:[PORT:22] or http://[HOST]:[PORT:8080]/health. When the user enables the watchdog toggle, the Supervisor probes this endpoint and restarts the add-on on failure (retry every 10 s, at most 5 attempts, throttled to 10 calls per 30 minutes). |
ulimits | map | {} | Resource limits. Simple form {nofile: 65535} or detailed form {nofile: {soft: 20000, hard: 40000}}. |
User options: options and schema
| Key | Type | Default | Description |
|---|---|---|---|
options | dict | {} | Default values for the add-on's user configuration. null marks an option the user must fill in. |
schema | dict or false | {} | Validation schema for options. Setting schema: false disables validation and the UI editor entirely. |
Schema values are strings from this element grammar (append ? to any of them
to make the option optional):
| Element | Meaning |
|---|---|
str / str(min,max) | String, optionally length-constrained. |
password / password(min,max) | String rendered as a password field. |
int / int(min,max) | Integer, optionally range-constrained. |
float / float(min,max) | Float, optionally range-constrained. |
bool | Boolean. |
email | E-mail address. |
url | URL. |
port | Network port (1–65535). |
match(<regex>) | String matching the regular expression. |
list(a|b|c) | One value out of the listed choices. |
device / device(subsystem=tty) | A host device path, optionally filtered by udev subsystem. |
Schemas nest: a value may itself be a dict of named elements, or a list of elements/dicts — but a list may not directly contain another list.
Real example (from zigbee2mqtt):
options:
data_path: /config/zigbee2mqtt
socat:
enabled: false
mqtt: {}
schema:
data_path: str
socat:
enabled: bool?
master: str?
mqtt:
server: str?
user: str?
password: str?
serial:
port: str?
adapter: match(zstack|deconz|zigate|ezsp|ember|zboss)?
baudrate: int?
Prebuilt images
| Key | Type | Description |
|---|---|---|
image | Docker image reference | Points the Supervisor at a prebuilt image to pull instead of building locally. {arch} is expanded to the device architecture; the tag is always the add-on version. Official convention: registry.apexinfosys.in/apexos/{arch}-addon-<slug> (see publishing). |
Migrations and legacy keys
The Supervisor migrates deprecated spellings on ingest and logs a warning for each:
startup: before→services,startup: after→applicationauto_uart→uartdevicesentries inpath:path:permform → path onlytmpfsstring form →truesnapshot*keys → the matchingbackup*keysmapentryconfig(combined mount) → preferapexos_config/addon_config
Legacy upstream aliases. Configuration files authored before the ApexOS
fork (and third-party add-ons still using the old wire names) declare API
access, role, and the core-configuration map target under legacy upstream key
names. These are normalized to the native keys on ingest — the native name wins
if both are present, and nothing persisted or served by the API ever contains
the legacy spellings. The schema itself accepts only the native names
(apexos_api, apexos_role, apexos_core_api, apexos, map target
apexos_config); without the ingest normalization the legacy keys would be
silently dropped. New add-ons must use the native keys.
Also note: a codenotary key is accepted but deprecated and ignored.
Keys managed per installation (not for config.yaml)
These are stored in the user portion of the add-on state and controlled through
the UI/API, not by the developer: auto_update, protected (protection mode,
default on), ingress_panel, watchdog on/off, per-user boot override,
network (user port overrides), audio_input/audio_output, and
system_managed/system_managed_config_entry.