Arcane Docker Install: Self-Hosted Container Manager
Step-by-step guide to install Arcane with Docker Compose. Covers basic setup, socket proxy security, OIDC authentication, reverse proxy config, and remote host management.
I’ve been running Arcane on two of my servers for a few weeks now. It replaced Portainer on both, and I haven’t looked back. The whole thing runs on Go, which means it’s fast, light on memory, and doesn’t need a complicated runtime.
If you’re looking for a comparison with another newer Docker manager, check out my Arcane vs Dockhand article. But if you’ve already decided on Arcane and just want it running, this guide covers everything from basic install to socket proxy security.
What Arcane actually does
Arcane is a web-based Docker management UI. You get container management, compose stack editing, real-time logs, a web terminal, and GitOps all in one interface. It runs as a single container.
A few things that stood out to me after using it:
- REST API that you can script against directly
- CLI tool for terminal-based management alongside the web UI
- GitOps built in, not as an afterthought. Point it at a repo and your stacks sync automatically
- OIDC/SSO support for single sign-on
- Remote host management via the arcane-headless agent
- BSD-3-Clause license. Free, no paid tiers, no feature locks
The project has around 4,400 GitHub stars, 35 contributors, and has been actively developed since 2022. It’s not new software.
Prerequisites
Before you start, you need:
- A Linux server (VPS or local machine). I recommend Hetzner for VPS hosting
- Docker and Docker Compose installed
- Basic terminal knowledge
Or use a Mini PC as home server.
Install Docker
If you don’t have Docker yet:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
jammy stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-compose
Full walkthrough: Install Docker & Docker-compose for Ubuntu.
Install Arcane with Docker Compose
There are two ways to install Arcane. The convenience script is the fastest, but I prefer the compose method because you can see and control exactly what’s happening.
Quick install (convenience script)
If you want to get running in 30 seconds:
curl -fsSL https://getarcane.app/install.sh | bash
This pulls the image, generates secrets, and starts the container. Good for testing, but I wouldn’t use it for a permanent setup because you don’t control the compose file.
Docker Compose install (recommended)
First, create a directory for Arcane:
mkdir -p /opt/arcane
cd /opt/arcane
Generate the secrets you’ll need. Run this command twice, once for ENCRYPTION_KEY and once for JWT_SECRET:
docker run --rm ghcr.io/getarcaneapp/arcane:latest /app/arcane generate secret
Copy both values. Now create your compose.yaml:
services:
arcane:
image: ghcr.io/getarcaneapp/arcane:latest
container_name: arcane
ports:
- "3552:3552"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- arcane-data:/app/data
- /opt/stacks:/opt/stacks
environment:
- APP_URL=http://localhost:3552
- PUID=1000
- PGID=1000
- ENCRYPTION_KEY=your-generated-encryption-key
- JWT_SECRET=your-generated-jwt-secret
restart: unless-stopped
volumes:
arcane-data:
Replace the ENCRYPTION_KEY and JWT_SECRET values with the ones you generated. Set APP_URL to your actual server address if you’re accessing it remotely.
Start it up:
docker compose up -d
Open http://your-server-ip:3552 in your browser. Default login credentials are arcane / arcane-admin. Change the password immediately.
Volume paths matter
If you want Arcane to manage existing compose projects on your server, mount the directory with matching paths inside and outside the container. For example, if your stacks live at /opt/stacks, mount it as /opt/stacks:/opt/stacks, NOT as /opt/stacks:/app/data/projects. Compose files use relative paths, and they’ll break if the mount point doesn’t match. You can also set the PROJECTS_DIRECTORY environment variable to tell Arcane where to look.
Hardening: Docker socket proxy
Mounting the Docker socket directly gives Arcane full control over your Docker daemon. That’s a security risk. If Arcane gets compromised somehow, an attacker has root-equivalent access to your host.
The fix is a socket proxy that filters which Docker API calls Arcane can make.
Why use a socket proxy?
The Docker socket (/var/run/docker.sock) is essentially a root-level API. Any container with access to it can create privileged containers, mount the host filesystem, or run arbitrary commands as root on the host.
A socket proxy sits between Arcane and the Docker daemon. It intercepts API calls and only allows the ones you’ve explicitly permitted. You get the management functionality without handing over the keys to the kingdom.
This setup is recommended for any internet-facing server. For a homelab behind a firewall, direct socket mounting is probably fine.
Here’s a compose setup with Tecnativa’s docker-socket-proxy:
services:
arcane:
image: ghcr.io/getarcaneapp/arcane:latest
container_name: arcane
ports:
- "3552:3552"
volumes:
- arcane-data:/app/data
- /opt/stacks:/opt/stacks
environment:
- APP_URL=http://localhost:3552
- PUID=1000
- PGID=1000
- ENCRYPTION_KEY=your-generated-encryption-key
- JWT_SECRET=your-generated-jwt-secret
- DOCKER_HOST=tcp://docker-socket-proxy:2375
depends_on:
- docker-socket-proxy
networks:
- arcane-net
restart: unless-stopped
docker-socket-proxy:
image: tecnativa/docker-socket-proxy
container_name: arcane-socket-proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- CONTAINERS=1
- IMAGES=1
- NETWORKS=1
- VOLUMES=1
- SERVICES=1
- TASKS=1
- NODES=1
- BUILD=1
- EXEC=1
- SYSTEM=1
- INFO=1
- VERSION=1
- POST=1
- DELETE=1
networks:
- arcane-net
restart: unless-stopped
networks:
arcane-net:
driver: bridge
volumes:
arcane-data:
Notice that Arcane no longer mounts the Docker socket directly. Instead, it connects to the proxy via DOCKER_HOST=tcp://docker-socket-proxy:2375. The socket is mounted read-only on the proxy container, and both containers sit on an internal bridge network.
The environment variables on the proxy control which Docker API endpoints are accessible. The list above is fairly permissive since Arcane needs most of them to function. You can tighten it further if you don’t need certain features.
Setting up OIDC/SSO
If you’re already running an identity provider like Authentik, Keycloak, or Authelia, you can hook Arcane into it for single sign-on.
Go to Settings > Security > OIDC Authentication in Arcane. Fill in your client ID, client secret, and issuer URL. The redirect URI is:
https://your-arcane-url/auth/oidc/callbackSave and test the connection. Users who authenticate via OIDC are auto-provisioned on first login.
Add these to your compose file:
environment:
- OIDC_ENABLED=true
- OIDC_CLIENT_ID=your-client-id
- OIDC_CLIENT_SECRET=your-client-secret
- OIDC_ISSUER_URL=https://your-idp.example.com
- OIDC_ADMIN_CLAIM=groups
- OIDC_ADMIN_VALUE=arcane-adminsOIDC_ADMIN_CLAIM and OIDC_ADMIN_VALUE let you auto-assign admin privileges based on a claim from your identity provider. So if a user belongs to the arcane-admins group, they get admin access automatically.
If you want to disable local password login entirely once OIDC is working, that’s configurable too.
Reverse proxy setup
You’ll want a reverse proxy in front of Arcane for SSL and a clean domain name. Arcane uses WebSockets for real-time updates, so your proxy config needs to support that.
server {
listen 443 ssl http2;
server_name arcane.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://127.0.0.1:3552;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}The key lines are proxy_http_version 1.1 and the Upgrade / Connection headers. Without them, WebSocket connections fail and the UI won’t get live updates.
If you’re already running Traefik (and you probably should be for Docker setups), add labels to your Arcane service:
labels:
- "traefik.enable=true"
- "traefik.http.routers.arcane.rule=Host(`arcane.yourdomain.com`)"
- "traefik.http.routers.arcane.entrypoints=websecure"
- "traefik.http.routers.arcane.tls.certresolver=letsencrypt"
- "traefik.http.services.arcane.loadbalancer.server.port=3552"Traefik handles WebSocket upgrade automatically. Full Traefik setup guide: How to use Traefik as a reverse proxy in Docker.
If you don’t want to expose ports at all, Cloudflare Tunnels work well. Point a tunnel at http://localhost:3552 and Cloudflare handles SSL and routing. WebSocket support is automatic.
This is what I use on my homelab since I don’t want to open any ports on my router.
Update the APP_URL environment variable in your compose file to match your actual domain (e.g., https://arcane.yourdomain.com).
Managing remote hosts
Arcane can manage Docker on other machines through the arcane-headless agent. This is useful if you have multiple servers but want one dashboard.
On the remote machine, deploy the agent:
services:
arcane-agent:
image: ghcr.io/getarcaneapp/arcane:latest
container_name: arcane-agent
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- AGENT_MODE=true
- AGENT_TOKEN=your-agent-token
- MANAGER_API_URL=https://arcane.yourdomain.com
restart: unless-stopped
Generate the AGENT_TOKEN on your main Arcane instance, then paste it here. The agent connects outbound to your main instance, so you don’t need to open any ports on the remote machine.
Environment variables reference
Here are the most useful environment variables you can set:
| Variable | Default | What it does |
|---|---|---|
APP_URL | http://localhost:3552 | Public URL for the instance |
PUID / PGID | 1000 | User/group ID for file permissions |
ENCRYPTION_KEY | none | Required. 32-byte key for encrypting sensitive data |
JWT_SECRET | none | Required. Secret for signing auth tokens |
DOCKER_HOST | unix:///var/run/docker.sock | Docker connection. Use tcp:// for socket proxy |
DATABASE_URL | SQLite | External PostgreSQL connection string |
GPU_MONITORING_ENABLED | false | Enable NVIDIA/AMD GPU stats |
GPU_TYPE | none | nvidia or amd |
LOG_LEVEL | info | Logging verbosity |
UI_CONFIGURATION_DISABLED | false | Force config via env vars only |
Troubleshooting
Arcane can't see my existing compose stacks
This is almost always a volume mount path mismatch. If your compose files live at /opt/stacks/myapp/compose.yaml, mount that exact path:
volumes:
- /opt/stacks:/opt/stacksNot /opt/stacks:/some/other/path. The paths inside and outside the container must match. Also set PROJECTS_DIRECTORY=/opt/stacks in the environment.
WebSocket errors or UI not updating live
Your reverse proxy isn’t forwarding WebSocket connections. Make sure you have the upgrade headers set. For Nginx, you need:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; Permission denied on Docker socket
Either add your user to the docker group (sudo usermod -aG docker $USER) or make sure the PUID/PGID values in the compose file match a user with Docker access.
Can't generate secrets
The secret generation command requires pulling the Arcane image first. If it fails, pull manually:
docker pull ghcr.io/getarcaneapp/arcane:latest
docker run --rm ghcr.io/getarcaneapp/arcane:latest /app/arcane generate secret What I like and what’s missing
After a few weeks with Arcane, here’s where I’ve landed.
The GitOps integration is genuinely good. I keep my compose files in a private Git repo, and when I push changes, Arcane picks them up and redeploys. No webhook config, no CI pipeline needed. It just works.
The REST API is another strong point. I wrote a small script that checks container health and restarts anything that’s unhealthy. Took about 20 minutes because the API is straightforward.
What I wish it had: vulnerability scanning (Dockhand has this), scheduled auto-updates with rollback protection, and a file browser for containers. These aren’t dealbreakers, but they’d make Arcane the complete package.
If you want vulnerability scanning and some of those missing features, take a look at how to install Dockhand. There’s also UsulNet, a newer all-in-one Docker management platform that bundles Trivy scanning, backups, reverse proxy config, and multi-node orchestration into a single Go binary.
Related articles
- Best Portainer alternatives in 2026 - five Docker management UIs compared
- Arcane vs Dockhand - side-by-side comparison of both tools
- Install Dockhand - the other Docker manager worth trying
- Install UsulNet - all-in-one Docker management platform with scanning, backups, and multi-node
- Install Dockge - another Docker management UI
- Best Docker containers for home server - what to run once your manager is set up
- Best self-hosted panels - server management panels compared
- Traefik reverse proxy for Docker - proper reverse proxy setup
- Docker auto-update with Tugtainer - keep containers updated
- Server monitoring tools - monitoring your Docker host