Install with Portainer
This page shows how to run Arclight as a Portainer stack: you paste a compose file into Portainer’s web editor, fill in environment variables, and deploy. It is for anyone who manages Docker through Portainer on a NAS or server and prefers clicking to typing commands. The example uses the published image, a VPN (Gluetun) and Arclight’s built-in torrent engine. Portainer’s menu names change slightly between versions, so look for the nearest label.
Before you start
Section titled “Before you start”-
Portainer running and connected to your Docker host (the “local” environment).
-
Folders on the host. Create one parent that holds everything:
/path/to/datadownloads/media/tv/movies//path/to/appdataOnly
/path/to/datais mounted into the containers, as/data. Do not mount downloads and media as separate volumes: Linux cannot hard-link across two mounts even on one disk, so every import becomes a full copy and seeding breaks. See folders-and-hardlinks.md. -
The folders must be writable by your
PUIDandPGID(runidon the host for yours). See permission denied. -
For the VPN: a Proton WireGuard key with port forwarding on (how). No VPN? Use the second example below.
-
A TMDB API key (free).
The Gluetun control key
Section titled “The Gluetun control key”Current Gluetun versions protect the control server with an API key. The repository helper script (scripts/gluetun-auth.sh) normally creates the key and the auth file under <CONFIG_ROOT>/gluetun/auth/config.toml. In Portainer you can run that script once on the host over SSH, or use a non-VPN stack. If you skip it, Arclight still runs, but its VPN status may show errors; see install-docker.md for the details.
Create the stack (VPN + built-in engine)
Section titled “Create the stack (VPN + built-in engine)”- In Portainer open Stacks > Add stack, name it
arclight, and choose the Web editor. - Paste this:
services: gluetun: image: qmcgaw/gluetun:latest container_name: gluetun cap_add: - NET_ADMIN devices: - /dev/net/tun:/dev/net/tun environment: - VPN_SERVICE_PROVIDER=protonvpn - VPN_TYPE=wireguard - WIREGUARD_PRIVATE_KEY=${PROTON_WIREGUARD_KEY} - SERVER_COUNTRIES=${VPN_COUNTRIES:-Netherlands} - VPN_PORT_FORWARDING=on - FIREWALL_OUTBOUND_SUBNETS=${LAN_SUBNET:-192.168.1.0/24} - HTTP_CONTROL_SERVER_ADDRESS=:8000 - HTTP_CONTROL_SERVER_LOG=off - TZ=${TZ:-Etc/UTC} volumes: - ${CONFIG_ROOT}/gluetun:/gluetun ports: - "7878:7878" # Arclight, published on gluetun healthcheck: test: ["CMD", "/gluetun-entrypoint", "healthcheck"] interval: 30s timeout: 10s start_period: 60s retries: 3 restart: unless-stopped
flaresolverr: image: ghcr.io/flaresolverr/flaresolverr:latest container_name: flaresolverr network_mode: "service:gluetun" environment: - LOG_LEVEL=info - TZ=${TZ:-Etc/UTC} restart: unless-stopped depends_on: gluetun: condition: service_healthy
arclight: image: ghcr.io/zacabrewer/arclight:latest container_name: arclight network_mode: "service:gluetun" environment: - PUID=${PUID:-1000} - PGID=${PGID:-1000} - TZ=${TZ:-Etc/UTC} - ARCLIGHT_VPN_CONTROL_URL=http://localhost:8000 - ARCLIGHT_VPN_API_KEY=${GLUETUN_API_KEY:-} - ARCLIGHT_FLARESOLVERR_URL=http://localhost:8191 volumes: - ${CONFIG_ROOT}/arclight:/config - ${DATA_ROOT}:/data healthcheck: test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:7878/api/v1/system/ping').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"] interval: 30s timeout: 5s start_period: 20s retries: 3 stop_grace_period: 30s restart: unless-stopped depends_on: gluetun: condition: service_healthy flaresolverr: condition: service_started- Scroll to Environment variables. Add each (Advanced mode lets you paste them as
NAME=valuelines):
| Variable | Example | Meaning |
|---|---|---|
PUID |
1000 |
Numeric user that owns your folders |
PGID |
1000 |
Numeric group |
TZ |
Etc/UTC |
Time zone, for example Europe/London |
CONFIG_ROOT |
/path/to/appdata |
Parent of each container’s config |
DATA_ROOT |
/path/to/data |
The single data mount, /data in the container |
PROTON_WIREGUARD_KEY |
<your-key> |
Proton WireGuard private key. Treat like a password |
VPN_COUNTRIES |
Netherlands |
Proton countries that allow P2P |
LAN_SUBNET |
192.168.1.0/24 |
Your home network, so you can reach the UI through the VPN firewall |
GLUETUN_API_KEY |
<your-key> |
Control-server key from the helper script; may be empty |
- Click Deploy the stack.
If you use the helper script’s auth file with a different key layout than this example, copy the extra lines from docker/docker-compose.release.yml in the repository (it also shows the optional fixed subnet and Whisper service).
No VPN: the simple stack
Section titled “No VPN: the simple stack”Replace the whole file with:
services: arclight: image: ghcr.io/zacabrewer/arclight:latest container_name: arclight environment: - PUID=${PUID:-1000} - PGID=${PGID:-1000} - TZ=${TZ:-Etc/UTC} - ARCLIGHT_FLARESOLVERR_URL=http://flaresolverr:8191 volumes: - ${CONFIG_ROOT}/arclight:/config - ${DATA_ROOT}:/data ports: - "7878:7878" - "6881:6881" - "6881:6881/udp" stop_grace_period: 30s restart: unless-stopped depends_on: - flaresolverr
flaresolverr: image: ghcr.io/flaresolverr/flaresolverr:latest container_name: flaresolverr environment: - LOG_LEVEL=info - TZ=${TZ:-Etc/UTC} restart: unless-stoppedIt needs only PUID, PGID, TZ, CONFIG_ROOT and DATA_ROOT. Leave Settings > VPN disabled in Arclight.
First start and checks
Section titled “First start and checks”- Under Stacks > arclight every container should show running (healthy for gluetun and arclight). Click a container and open Logs to read its output. The Arclight log has “Arclight starting as … (PUID:PGID)”.
- Browse to
http://<your-host>:7878. The wizard appears: first-run-wizard.md. Root folders:/data/media/tvand/data/media/movies. - Confirm Settings > Torrent Engine saves to
/data/downloads(the built-in engine’s default when/dataexists). In the VPN stack, in Settings > VPN choose provider Gluetun, enable monitoring, and in Settings > Torrent Engine keep Bind to VPN on. See vpn.md. - If the stack is stuck on gluetun, see VPN will not connect. A restart loop is covered in container restarting.
Updating the stack
Section titled “Updating the stack”- Open the stack and click Update the stack (or Editor, then Update).
- Turn on the option to re-pull the image (wording varies: “Re-pull image and redeploy”), then confirm. This downloads the newest
latestimage and recreates the containers. Your settings stay inCONFIG_ROOT. - To control the version, replace
latestwith a release tag such asv0.2.0in the file. - In a VPN stack, recreate the whole stack rather than one container: containers sharing gluetun’s network must be recreated whenever gluetun restarts.
Arclight can also update its own containers from Settings > Updates, but that needs the Docker socket mounted into it, which gives it full control of the host. It is off by default. See updating.md before enabling it. Back up first: backup-restore.md.
Gotchas
Section titled “Gotchas”| Symptom | Cause and fix |
|---|---|
| “Variable is not set” or blank value | Add it under Environment variables, not only in the YAML |
| Containers recreated but Arclight cannot reach the VPN | Redeploy the stack as a whole |
| Imports copy instead of linking | Downloads and media are mounted separately; use the single DATA_ROOT:/data mount |
| Empty library after redeploy | A different CONFIG_ROOT or DATA_ROOT value was used |
| Permission errors | Wrong PUID/PGID |