Files
docudjeex/content/en/3.serveex/91.advanced/2.arcane.md
T

11 KiB

title, description
title description
Arcane Install Arcane, a modern Docker and Compose management web UI, as a more advanced alternative to Dockge with multi-host support and OIDC login.

:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}

Arcane is a self-hosted web UI for managing Docker containers, images, volumes, and Compose stacks, in the same spirit as Dockge. Compared to Dockge, Arcane is more full-featured: it can manage several remote Docker hosts from a single instance, and it supports OIDC login natively instead of relying on a separate forward-auth proxy.

Arcane

::note

Arcane needs access to the Docker socket to manage containers, which is effectively root access to your host. Instead of mounting the socket directly, this guide sits Docker Socket Proxy in front of it, only allowing the specific API permissions Arcane actually needs. Whatever you use, make sure Arcane itself is never reachable without authentication. ::

Installation

::file-tree

tree: /: - docker: - arcane: - compose.yaml - .env - data/

::

::steps{level="3"}

Generate an encryption key

openssl rand -base64 32

Keep the output, you'll need it for the .env file below.

Deploy the stack

Open Dockge, click compose, name the stack arcane, and add the following config. It includes the socket proxy: arcane never touches /var/run/docker.sock directly, only docker-socket-proxy does, and it only allows the specific permissions Arcane needs (containers, images, networks, volumes, exec, build/commit), on their own internal network:

---
services:
  arcane:
    image: ghcr.io/getarcaneapp/manager:latest
    container_name: arcane
    restart: unless-stopped
    cgroup: host
    env_file:
      - .env
    volumes:
      - /docker/arcane/data:/app/data
    networks:
      - arcane-internal
    ports:
      - 3552:3552
    depends_on:
      - docker-socket-proxy

  docker-socket-proxy:
    image: lscr.io/linuxserver/socket-proxy:latest
    container_name: arcane-docker-proxy
    security_opt:
      - no-new-privileges:true
    networks:
      - arcane-internal
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - CONTAINERS=1
      - IMAGES=1
      - NETWORKS=1
      - VOLUMES=1
      - EXEC=1
      - BUILD=1
      - COMMIT=1
      - INFO=1
      - SYSTEM=1
      - POST=1
      - ALLOW_START=1
      - ALLOW_STOP=1
      - ALLOW_RESTARTS=1
    restart: unless-stopped
    read_only: true
    tmpfs:
      - /run

networks:
  arcane-internal:
    name: arcane-internal

::note

POST=1 is the blanket write-enable needed for creating/removing containers, images, networks and volumes; ALLOW_START/ALLOW_STOP/ALLOW_RESTARTS cover container lifecycle actions separately. Everything else (Swarm, secrets, configs, auth) is left at its default 0, since this site doesn't use them. ::

::tip{icon=""} Add the Watchtower label to automate updates:

---
services:
  arcane:
    #...
    labels:
      - com.centurylinklabs.watchtower.enable=true

::

Set your environment variables

Fill in the .env file:

APP_URL=https://arcane.mydomain.com
ENCRYPTION_KEY=
DOCKER_HOST=tcp://docker-socket-proxy:2375
PUID=1000
PGID=1000
Variable Value Example
APP_URL{lang=properties} The public URL you'll use to reach Arcane (see exposure below), without a port https://arcane.mydomain.com
ENCRYPTION_KEY{lang=properties} The key generated above Q2pVEqsTNRkJSO9SkJzU3KZ2...
DOCKER_HOST{lang=properties} Points Arcane at the socket proxy instead of a mounted socket tcp://docker-socket-proxy:2375
PUID / PGID{lang=properties} Your user and group ID, from id yourusername 1000

Deploy the stack. The local interface is available at http://yourserverip:3552.

Done !

::

::caution

If it fails: check your firewall rules. ::

Exposing Arcane with SWAG

The main benefit of this setup is being able to access Arcane remotely from all your devices. We'll expose it using SWAG.

::warning

Arcane's own local login has no multi-factor authentication. Only expose it if you're using Pocket ID (see below) or Authentik for login. Otherwise, don't expose it with SWAG. Use a VPN like Wireguard instead, especially given the level of access Arcane has over your host. ::

::note

We assume you have the subdomain arcane.mydomain.com with a CNAME pointing to mydomain.com in your DNS zone. And of course, unless you use Cloudflare Zero Trust, your box's port 443 must be forwarded to your server's port 443 in NAT rules. ::

::steps{level="3"}

Add Arcane's network to SWAG

Go to Dockge and edit SWAG's compose file by adding Arcane's network:

---
services:
  swag:
     container_name: # ...
      # ... 
     networks:              # Attach container to custom network 
      # ...           
      - arcane              # Name of the declared network

networks:                   # Define the custom network
  # ...
  arcane:                   # Declared network name
    name: arcane_default    # Actual external network name
    external: true          # Marks it as externally defined

Redeploy the stack and wait for SWAG to be fully operational.

::note

Here we assume the Arcane network name is arcane_default. You can check the connection by visiting SWAG's dashboard at http://yourserverip:81. ::

Create the subdomain.conf file

In the Swag folders, create the file arcane.subdomain.conf:

::tip{icon=""} Tip: Use File Browser Quantum to navigate and edit files instead of using terminal commands. ::

sudo nano /docker/swag/config/nginx/proxy-confs/arcane.subdomain.conf

Paste the following configuration:

## Version 2023/12/19

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name arcane.*;

    include /config/nginx/ssl.conf;

    client_max_body_size 0;

    location / {
        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app arcane;
        set $upstream_port 3552;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

::note

Arcane's live updates run over a websocket, hence the Upgrade/Connection headers above, on top of the usual proxy.conf include. ::

Press :kbd{value="Ctrl+O"}, then :kbd{value="Enter"} to save, and :kbd{value="Ctrl+X"} to exit.

Done !

::

That's it! Arcane is now accessible from the internet.

Connecting a Remote Host

Arcane can manage several Docker hosts from a single instance. Each remote host runs a lightweight agent container that connects back to Arcane. Rather than exposing that connection to the internet, we'll route it over the WireGuard VPN already set up earlier, so the agent traffic never leaves your private network.

::note

This assumes both the Arcane host and the remote host already run their own WireGuard client, connected to your VPN as described in Client Server Setup. Note the VPN address wg-easy assigned to the Arcane host (e.g. 10.8.0.3); that's the address the remote agent will target below. ::

::steps{level="3"}

Add the remote environment in Arcane

In Arcane, go to Environments > Add Environment. Arcane generates a one-time Agent Token and the compose snippet to deploy on the remote host.

Deploy the agent on the remote host

On the remote host, open Dockge, click compose, name the stack arcane-agent, and add the following config, replacing the token with the one Arcane gave you and the URL with your Arcane host's VPN address:

---
services:
  arcane-agent:
    image: ghcr.io/getarcaneapp/agent:latest
    container_name: arcane-agent
    restart: unless-stopped
    environment:
      - EDGE_AGENT=true
      - EDGE_TRANSPORT=poll
      - AGENT_TOKEN=arc_yourtoken
      - MANAGER_API_URL=http://10.8.0.3:3552
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /docker/arcane-agent/data:/app/data

::note

This is "edge mode": the agent connects out to Arcane instead of the other way around, so it works from behind NAT without forwarding anything on the remote host's router. Using the VPN address instead of a public domain means that connection stays on the WireGuard tunnel even though the agent is technically in "edge" mode. Unlike the manager above, the agent needs the real Docker socket mounted directly, since it's the one actually running commands on that host; there's no documented socket-proxy option for it. ::

Deploy the stack.

Verify the connection

Back in Arcane, the new environment should show as connected within a few seconds. Switch to it from the environment picker to manage that host's containers and stacks.

Done !

::

Connecting Pocket ID

Arcane supports OIDC natively, so you can require a Pocket ID login before letting anyone manage your containers, instead of (or alongside) the app's own accounts.

::steps{level="3"}

Register Arcane as an OIDC client

Register an OIDC client in Pocket ID named arcane, with this callback URL:

https://arcane.mydomain.com/auth/oidc/callback

Enable OIDC in Arcane

Edit Arcane's .env file and add:

OIDC_ENABLED=true
OIDC_CLIENT_ID=
OIDC_CLIENT_SECRET=
OIDC_ISSUER_URL=https://id.mydomain.com
OIDC_SCOPES=openid email profile
OIDC_PROVIDER_NAME=Pocket ID
Variable Value
OIDC_CLIENT_ID{lang=properties} The client ID copied from Pocket ID
OIDC_CLIENT_SECRET{lang=properties} The client secret copied from Pocket ID
OIDC_ISSUER_URL{lang=properties} Pocket ID's public URL, no trailing slash; Arcane discovers the rest via .well-known/openid-configuration

Redeploy the stack.

::tip{icon=""} To skip straight to Pocket ID and hide the local login form, set OIDC_AUTO_REDIRECT_TO_PROVIDER=true, or disable local login entirely under Settings > Authentication for OIDC-only access. ::

Done !

::

That's it! Arcane now offers a "Login with Pocket ID" option alongside the local login form.

::tip{icon=""} You can use Authentik instead of Pocket ID:

  1. In Authentik, create an application and an OAuth2/OpenID Connect provider named Arcane, with a redirect URI (type Strict) of https://arcane.mydomain.com/auth/oidc/callback.
  2. Note the provider's Client ID and Client Secret.
  3. In Arcane's .env, set OIDC_ISSUER_URL=https://authentik.mydomain.com/application/o/arcane/, then fill in the Client ID and Client Secret. ::