Repository navigation
Configuring ARM
ARM v3 has two places config lives, and they do different jobs:
-
~/arm/.armctl/.env— bootstrap and infrastructure values read at container start: secrets, file ownership, image tags, GPU toggle. Generated by the installer; you rarely edit it. Changing it requiresarmctl upto take effect. - The UI Settings page (stored in the database) — everything you tune at runtime: API keys, rip/transcode behaviour, notifications. Changes apply live; no restart.
There is no arm.yaml in v3. If you're editing a YAML config file, that's
v2.
The installer writes ~/arm/.armctl/.env with secure defaults. Most fields you should
never touch; the ones you might are flagged editable below.
| Key | What it is |
|---|---|
POSTGRES_USER / POSTGRES_DB
|
Database name/user. Don't change post-install. |
POSTGRES_PASSWORD |
Random DB password (openssl rand -hex 24). Changing it means re-creating the DB. |
ARM_SERVICE_TOKEN |
Shared secret the rippers/transcoders use to authenticate to the backend (openssl rand -hex 32). Changing it requires restarting every service. |
PUID / PGID
|
Editable. UID/GID that owns everything ARM writes to raw/media. Match your media server (Plex/Jellyfin) so it can read the files. A fresh install sets your own account; re-running armctl install keeps whatever is there. See File ownership. |
CDROM_GID |
The host's optical group GID, detected via stat -c %g /dev/sr0 (usually 44 on Debian/Ubuntu, 19 on Arch). Lets the ripper read the drive. |
ARM_LOG_LEVEL |
Editable. info (default) or debug. Set debug before reproducing a bug. |
ARM_ALLOWED_ORIGINS |
Editable. Comma-separated allowlist of extra origins the WebSocket endpoint accepts from browsers. Same-origin connections are accepted automatically, so this stays empty unless the UI sits behind your own reverse proxy on a different origin — e.g. https://arm.example.com. |
MAX_PARALLEL_TRANSCODES |
Editable. How many transcoder containers may run at once. Default 1 (a 1080p HandBrake job pegs every core). |
ARM_TRANSCODE_CAPABLE |
Editable. Whether this deployment can run a transcode container at all. Default true. A ripper-only setup writes false here, see Ripper-only installs below. Encode sessions are refused while this is false; passthrough (no-preset) sessions still run, in-process, on the backend. Setting ARM_TRANSCODE_DOCKER_HOST implies true no matter what this is set to. |
ARM_IMAGE_PREFIX / ARM_IMAGE_TAG
|
Registry path + image tag. armctl upgrade moves ARM_IMAGE_TAG for you — see Upgrading. ARM_RIPPER_IMAGE and the ARM_TRANSCODE_IMAGE* keys move with it while they hold the value armctl wrote; change one and armctl keeps your value on every install and upgrade (and says so), so updating it is then up to you. |
ARM_TRANSCODE_IMAGE |
The base image the backend spawns for CPU/NVENC work (the registry also publishes it under a -nvidia tag: same image). Its -intel / -amd tag variants serve QSV / VAAPI GPUs automatically; see Hardware Transcoding § Image variants for the naming convention and the per-vendor override vars. |
ARM_HOST_*_PATH |
Host paths (raw/media/logs/certs) the backend hands to the Docker daemon when spawning rippers and transcoders. armctl install writes them; do not edit them here. To move raw rips or finished media to another folder, run armctl install --raw-path <dir> --media-path <dir>, which rewrites both these values and the backend's own mounts. Editing only .env would leave the backend on the old folders. |
ARM_HOST_ISO_LIBRARY_PATH |
Editable. Host folder of .iso files you want to rip from. armctl install sets it to <arm>/iso-library, or to the folder you give with --iso-library-path <dir>. To use a NAS mount instead, edit it here and run armctl up. It must be an absolute path such as /srv/arm/iso-library; a relative value like ./iso-library is ignored. It enables the gear menu's Rip from ISO picker (GET /api/iso/library); the backend mounts it read-only. Leave it empty and the picker reports the feature as not configured. See 10-iso-source-ripping.md. |
ARM_GPUS / ARM_GPUS_MANUAL
|
ARM_GPUS is the GPU list, rewritten from host detection on every armctl install, up and upgrade. The backend reads it only to fill an empty GPU list in Settings > GPUs; once that list has rows, delete them there and restart the backend to re-seed. Editable only with ARM_GPUS_MANUAL=true, which keeps your list as written; see Hardware Transcoding. |
ARM_DOCKER_NETWORK |
The compose network a spawned transcoder joins to reach the backend (armv3_default). |
COMPOSE_FILE |
Not used by armctl. armctl names its Compose files itself, so this value and a docker-compose.override.yml beside the install are both ignored. This release has no supported way to add your own Compose override. GPUs need no overlay; see Hardware Transcoding. |
MAKEMKV_KEY |
Editable (add it yourself), fallback only. A permanent/operator MakeMKV key. Prefer setting this in the UI (Config → MakeMKV key), which overrides this var and survives a recreate; this env var is used only when the UI key is blank. When both are unset, the ripper scrapes the monthly free beta. See MakeMKV. |
After editing .env, apply it with:
armctl upOpen Settings (/settings) in the web UI. These values live in the database
and apply immediately. The full set:
| Setting | Default | Effect |
|---|---|---|
| TMDb API key | empty | Enables TMDb movie/TV lookups. Get one free at https://www.themoviedb.org/settings/api. |
| OMDb API key | empty | Enables OMDb lookups. Get one at https://www.omdbapi.com/apikey.aspx. |
| MusicBrainz user-agent | armv3 |
The UA string ARM sends to MusicBrainz for audio-CD lookups. No key needed. |
ARM identifies video discs in this order: the community CRC64 database (no key, tried first) → TMDb (movie, then TV) → OMDb. Audio CDs use MusicBrainz. Data discs skip identification entirely. So ARM works with no keys at all, but TMDb/OMDb dramatically improve naming hit rates.
| Setting | Default | Effect |
|---|---|---|
| Auto-rip on insert | on | Start a rip automatically when a disc is detected. Turn off to require a manual start from Jobs → Manual. |
| Block on identification miss | on | When a video disc can't be identified, pause and ask you to confirm/search before ripping. Turn off to rip immediately to raw/ and resolve identity later (no file is ever renamed retroactively). |
| When a disc was ripped before | hold | What ARM does with a disc whose fingerprint matches an earlier rip (status ripped, partial, or ripped awaiting a title) on any drive. Hold for me parks it on the dashboard as Already ripped with no countdown until you press Rip again or Discard. Reject and eject creates no job, ejects the disc, notes it on the drive card and in the inbox. Rip again rips it without asking. Failed and abandoned jobs don't count, and deleting the earlier job lets the disc rip normally. Rip again on the page of any earlier rip of the disc lets the next insert through once (or starts a held copy if one is waiting). |
| Auto-transcode on idle | off | Automatically queue a transcode session when the stack is idle, vs. waiting for you to start one. |
| Transcoding | on | Master switch for encode work (Settings → Transcoding). Turning it off holds any queued encode sessions instead of dropping them, and lets already-running transcodes finish; passthrough (no-preset) sessions keep running either way. Can only be switched on if the deployment is transcode-capable, see ARM_TRANSCODE_CAPABLE above and Ripper-only installs below. |
| Default retention policy | keep raw | What happens to the intermediate raw/ files after a session — keep them or prune. |
| Max parallel ISO rips | 1 | How many ISO-source rips (Settings → Ripping) may run at once, 1 to 8. Only matters when ARM_HOST_ISO_LIBRARY_PATH is set. |
| Setting | Default | Effect |
|---|---|---|
| Notifications enabled | off | Master on/off switch. |
| Apprise URLs | empty | One or more Apprise target URLs (Discord, Slack, Telegram, Gotify, e-mail, …). Validated when you save. |
When enabled, ARM fires a notification on these events: rip completed /
failed / partial and session (transcode) completed / failed / partial.
Apprise URL formats for every service are in the
Apprise wiki; for example a Discord
webhook is discord://webhook_id/webhook_token.
Beyond the global settings above, v3 models how a disc is ripped and transcoded as reusable objects you manage in the UI:
- Rip presets — how MakeMKV (or the ISO dump) pulls titles off the disc.
- Transcode presets — the HandBrake/abcde profile applied to the raw output (e.g. H.265 1080p, music to FLAC or MP3).
- Sessions — a named bundle of transcode work you apply to a job; a drive can have a default session so finished rips transcode automatically.
ARM seeds sensible built-in presets on first boot, so you don't have to create any to get started. See Web UI for the pages that manage them.
If this box only rips discs and hands the raw files off elsewhere to encode (no GPU, or transcoding runs on a separate machine), a dev checkout can skip the transcode side entirely:
bash devtools/setup-dev.sh --ripper-onlyThis skips the arm-transcode image build and GPU detection, and writes
ARM_TRANSCODE_CAPABLE=false to .env (see the table above). There is no
install-time hardware-encoder probe any more: the Backend probes each GPU
row for real with a test encode after boot, so a ripper-only box simply
never gets one, since ARM_GPUS stays []. Encode sessions are then
refused everywhere in the UI and API;
passthrough (no-preset, ISO/data-copy) sessions still run normally, in-process
on the backend, so raw-and-ship workflows are unaffected.
In a dev checkout the flag is not sticky. Every run of the script without --ripper-only
writes ARM_TRANSCODE_CAPABLE=true and (with up) builds the
arm-transcode image, so to turn a ripper-only box into a transcode-capable
one, re-run the script without the flag, then switch Transcoding on in
Settings. Keep passing --ripper-only on every re-run for as long as the box
should stay ripper-only.
A ripper-only install is the ripper-only profile: choose it when the installer asks, or run armctl install --profile ripper-only. Unlike the dev flag, the profile is remembered: later runs of armctl install keep it until you pick another.
ARM writes every file under raw/ and media/ as PUID:PGID from .env
(the linuxserver.io pattern). Set these to match the account your media server
runs as so Plex/Jellyfin can read the library with no chown afterward.
Two rules worth knowing:
- ARM never
chown -Rs your mounted volumes. If ownership is wrong at startup, the container logs a clear error and exits rather than rewriting your files. Fix the host-side ownership and restart. - The output roots are created
setgid(mode2775) so subdirectories inherit the group and stay group-writable.
If raw/ and media/ live on different storage with different owners (common
when media/ is a NAS share), reconcile at the mount layer rather than asking
the container to span two identities — mount CIFS with
uid=$PUID,gid=$PGID,forceuid,forcegid, or NFS with a squash that maps to
PUID. Full detail in
docs/developers/architecture/06-deployment.md § File ownership.
Getting Started
Using ARM
Troubleshooting
Project