Skip to content

Configuring ARM

Actionbot edited this page Oct 13, 2026 · 17 revisions

Configuration

ARM v3 has two places config lives, and they do different jobs:

  1. ~/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 requires armctl up to take effect.
  2. 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 .env file

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 up

The UI Settings page

Open Settings (/settings) in the web UI. These values live in the database and apply immediately. The full set:

Metadata / identification

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.

Rip / transcode behaviour

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.

Notifications

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.


Rip presets, transcode presets, and sessions

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.


Ripper-only installs

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-only

This 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.


File ownership

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 (mode 2775) 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.

Clone this wiki locally