Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions services/arcane/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#version=1.1
#URL=https://github.com/tailscale-dev/ScaleTail
#COMPOSE_PROJECT_NAME= # Optional: only use when running multiple deployments on the same infrastructure.

# Service Configuration
SERVICE=arcane # Service name (e.g., adguard). Used as hostname in Tailscale and for container naming (app-${SERVICE}).
IMAGE_URL=ghcr.io/getarcaneapp/arcane # Docker image URL from container registry (e.g., adguard/adguard-home).

# Network Configuration
SERVICEPORT=3552 # Port to expose to local network. Uncomment the "ports:" section in compose.yaml to enable.
DNS_SERVER=9.9.9.9 # Preferred DNS server for Tailscale. Uncomment the "dns:" section in compose.yaml to enable.

# Tailscale Configuration
TS_AUTHKEY= # Auth key from https://tailscale.com/admin/authkeys. See: https://tailscale.com/kb/1085/auth-keys#generate-an-auth-key for instructions.

# Optional Service variables
TAILNET_NAME= # for example: tail-scale
28 changes: 28 additions & 0 deletions services/arcane/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Arcane with Tailscale Sidecar Configuration

This Docker Compose configuration sets up **Arcane** with a Tailscale sidecar container, enabling secure access to your self-hosted Docker management interface over your private Tailscale network. With this setup, your Arcane instance remains **private and accessible only from authorized devices on your Tailnet**, keeping your Docker environment and operations shielded from public exposure.

## Arcane

[**Arcane**](https://getarcane.app/docs) is an open-source, self-hosted platform for **Docker container and Compose stack management** with a modern web interface. It allows users to manage containers, images, networks, volumes, remote environments, and projects—all without needing to rely on the Docker CLI. Arcane makes container operations approachable while providing powerful features for both homelab and production use.

## Key Features

* 🐳 **Containers** – Start, stop, inspect, and monitor containers from a unified web UI.
* 📦 **Images** – List, pull, and manage container images.
* 🌐 **Networks** – View and create Docker networks with driver and subnet information.
* 🗂 **Projects** – Manage Docker Compose stacks as first-class resources, with a Projects UI and Git syncing.
* 🔄 **Remote Environments** – Control containers on other hosts using Arcane Agents.
* 💾 **Volumes** – Browse and manage Docker volumes.
* 🧰 **Templates & Guides** – Built-in support for templates and guides to streamline deployment patterns.
* 🔐 **Extensible Configuration** – Support for environment variables, OIDC single sign-on, notifications, HTTP proxies, and analytics.

## Configuration Overview

In this deployment, a **Tailscale sidecar container** (for example `tailscale-arcane`) runs the Tailscale client and joins your private Tailscale network. The main `arcane` service uses:

```plain
network_mode: service:tailscale-arcane
```

This configuration routes all traffic through the Tailscale interface, ensuring that the Arcane web UI and API are accessible **only via your Tailscale network**. This provides a simple and secure way to access your Docker management console from all trusted devices while preventing public access to container controls.
76 changes: 76 additions & 0 deletions services/arcane/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
configs:
ts-serve:
content: |
{"TCP":{"443":{"HTTPS":true}},
"Web":{"$${TS_CERT_DOMAIN}:443":
{"Handlers":{"/":
{"Proxy":"http://127.0.0.1:3552"}}}},
"AllowFunnel":{"$${TS_CERT_DOMAIN}:443":false}}

services:
# Make sure you have updated/checked the .env file with the correct variables.
# All the ${ xx } need to be defined there.
# Tailscale Sidecar Configuration
tailscale:
image: tailscale/tailscale:latest # Image to be used
container_name: tailscale-${SERVICE} # Name for local container management
hostname: ${SERVICE} # Name used within your Tailscale environment
environment:
- TS_AUTHKEY=${TS_AUTHKEY}
- TS_STATE_DIR=/var/lib/tailscale
- TS_SERVE_CONFIG=/config/serve.json # Tailscale Serve configuration to expose the web interface on your local Tailnet - remove this line if not required
- TS_USERSPACE=false
- TS_ENABLE_HEALTH_CHECK=true # Enable healthcheck endpoint: "/healthz"
- TS_LOCAL_ADDR_PORT=127.0.0.1:41234 # The <addr>:<port> for the healthz endpoint
#- TS_ACCEPT_DNS=true # Uncomment when using MagicDNS
configs:
- source: ts-serve
target: /config/serve.json
volumes:
- ./config:/config # Config folder used to store Tailscale files - you may need to change the path
- ./ts/state:/var/lib/tailscale # Tailscale requirement - you may need to change the path
devices:
- /dev/net/tun:/dev/net/tun # Network configuration for Tailscale to work
cap_add:
- net_admin # Tailscale requirement
#ports:
# - 0.0.0.0:${SERVICEPORT}:${SERVICEPORT} # Binding port ${SERVICE}PORT to the local network - may be removed if only exposure to your Tailnet is required
# If any DNS issues arise, use your preferred DNS provider by uncommenting the config below
#dns:
# - ${DNS_SERVER}
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:41234/healthz"] # Check Tailscale has a Tailnet IP and is operational
interval: 1m # How often to perform the check
timeout: 10s # Time to wait for the check to succeed
retries: 3 # Number of retries before marking as unhealthy
start_period: 10s # Time to wait before starting health checks
restart: always

# ${SERVICE}
application:
image: ${IMAGE_URL} # Image to be used
network_mode: service:tailscale # Sidecar configuration to route ${SERVICE} through Tailscale
container_name: app-${SERVICE} # Name for local container management
environment:
- APP_URL=https://arcane.${TAILNET_NAME}.ts.net
- PUID=1000
- PGID=1000
- ENCRYPTION_KEY=verysecretkeythatshouldbereplaced # ENCRYPTION_KEY must be 32 bytes (raw/base64/hex). Use 'openssl rand -base64 32' in your CLI to generate a secure random key.
- JWT_SECRET=verysecretkeythatshouldbereplaced # JWT_SECRET should be a secure random string. Use 'openssl rand -base64 32' in your CLI to generate another secure random key.
- LOG_LEVEL=info # Optional
- LOG_JSON=false # Optional
- OIDC_ENABLED=false # Optional
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./${SERVICE}-data:/app/data
- ./opt/dockerdata:/app/data/projects # Optional volume for an existing Docker Compose directory.
depends_on:
tailscale:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3552/", "-s", "-o", "/dev/null"]
interval: 1m # How often to perform the check
timeout: 10s # Time to wait for the check to succeed
retries: 3 # Number of retries before marking as unhealthy
start_period: 30s # Time to wait before starting health checks
restart: always