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
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,26 +118,27 @@ If you would like to add a new config, you can use the [service-template](templa
### 📊 Dashboards and Visualization

| 📊 Service | 📝 Description | 🔗 Link |
| -------------- | ------------------------------------------------------------------------------------ | ---------------------------- |
| -------------- | ------------------------------------------------------------------------------------ | ---------------------------- |
| 🧭 **Glance** | A concise, customizable dashboard for self-hosted services and personal metrics. | [Details](services/glance) |
| 🏠 **Homepage** | A modern, highly customizable homepage for organizing links and monitoring services. | [Details](services/homepage) |

### 🛠️ Development Tools

| 🛠️ Service | 📝 Description | 🔗 Link |
| ------------------------ | ------------------------------------------------------------------------------------------------------ | ----------------------------------- |
| 🧰 **Arcane** | A self-hosted Docker management UI for Compose stacks; this repo includes a Tailscale sidecar example. | [Details](services/arcane) |
| 🖥️ **Changedetection.io** | A tool for monitoring website changes. | [Details](services/changedetection) |
| 🛠️ **Coder** | Self-hosted cloud dev environments with browser IDEs, Terraform-managed workspaces. | [Details](services/coder) |
| 🔧 **Cyberchef** | A web app for encryption, encoding, compression, and data analysis. | [Details](services/cyberchef) |
| 🐳 **Dockhand** | A modern, lightweight Docker management UI for containers and Compose stacks. | [Details](services/dockhand) |
| 🖥️ **Dozzle** | A real-time log viewer for Docker containers. | [Details](services/dozzle) |
| 🖥️ **GitSave** | A self-hosted service to back up your GitHub repositories via a simple REST API and scheduled runs. | [Details](services/gitsave) |
| 🔁 **FossFLOW** | A self-hosted tool to make beautiful isometric infrastructure diagrams. | [Details](services/fossflow) |
| 🖥️ **GitSave** | A self-hosted service to back up your GitHub repositories via a simple REST API and scheduled runs. | [Details](services/gitsave) |
| 🖥️ **Gokapi** | A lightweight self-hosted file sharing platform. | [Details](services/gokapi) |
| 🖥️ **Homarr** | A sleek dashboard for all your Homelab services. | [Details](services/homarr) |
| 🖥️ **IT-Tools** | A collection of handy online tools for developers and sysadmins. | [Details](services/it-tools) |
| 🖥️ **Node-RED** | A flow-based development tool for visual programming. | [Details](services/nodered) |
| 🖥️ **Portainer** | A lightweight management UI which allows you to easily manage your Docker environments. | [Details](services/portainer) |
| 🧰 **Arcane** | A self-hosted Docker management UI for Compose stacks; this repo includes a Tailscale sidecar example. | [Details](services/arcane) |
| 🔍 **searXNG** | A free internet metasearch engine which aggregates results from various search services. | [Details](services/searxng) |

### 📈 Monitoring and Analytics
Expand Down
17 changes: 17 additions & 0 deletions services/dockhand/.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=dockhand # Service name (e.g., adguard). Used as hostname in Tailscale and for container naming (app-${SERVICE}).
IMAGE_URL=fnsys/dockhand:latest # Docker image URL from container registry (e.g., adguard/adguard-home).

# Network Configuration
SERVICEPORT=3000 # 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
# PUID=1000
38 changes: 38 additions & 0 deletions services/dockhand/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Dockhand with Tailscale Sidecar Configuration

This Docker Compose configuration sets up **Dockhand** with a Tailscale sidecar container, enabling secure access to your self-hosted Docker management interface over your private Tailscale network. With this setup, your Dockhand instance remains private and accessible only from authorized devices on your Tailnet, ensuring that container management and infrastructure controls are never exposed to the public internet.

## Dockhand

[**Dockhand**](https://github.com/Finsys/dockhand) is a modern, lightweight Docker management UI focused on real-time container operations and multi-environment orchestration. It provides an intuitive interface for managing containers, images, volumes, networks, and Docker Compose stacks across local or remote Docker hosts.

Dockhand is designed for operators and homelab environments that want a clean, responsive alternative to heavier container management platforms, while still retaining full control over their infrastructure.

## Key Features

- Container Management – Start, stop, restart, and inspect containers in real time.
- Compose Stack Support – Deploy and manage Docker Compose applications.
- Multi-Environment Support – Connect to and manage multiple Docker hosts.
- Live Logs & Terminal – Stream logs and access container terminals directly from the UI.
- File & Volume Access – Inspect volumes and container file systems.
- Git-Based Deployments – Deploy stacks from Git repositories with optional sync.
- Docker-Native – Built specifically for Docker environments.
- Open Source – Community-driven and self-hostable.

## Why Self-Host?

A Docker management interface has full control over your infrastructure. Exposing such a tool publicly significantly increases risk, as it can allow attackers to manipulate containers, access secrets, or pivot deeper into your network.

Self-hosting Dockhand ensures that you maintain full ownership and operational control. When combined with Tailscale, Dockhand becomes a secure, private control plane for your Docker environments, accessible only from authenticated devices within your Tailnet. This dramatically reduces the attack surface while preserving remote management convenience.

## Configuration Overview

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

```plain
network_mode: service:tailscale-dockhand
```

This configuration routes all inbound and outbound traffic through the Tailscale interface, ensuring that the Dockhand web interface and Docker API interactions are accessible only via your Tailscale network.

By avoiding public port mappings and relying exclusively on Tailnet access, you create a secure-by-default Docker management setup suitable for homelabs, remote infrastructure, and internal DevOps environments.
69 changes: 69 additions & 0 deletions services/dockhand/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
configs:
ts-serve:
content: |
{"TCP":{"443":{"HTTPS":true}},
"Web":{"$${TS_CERT_DOMAIN}:443":
{"Handlers":{"/":
{"Proxy":"http://127.0.0.1:3000"}}}},
"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
- TS_AUTH_ONCE=true
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 ${SERVICEPORT} 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:
- HOST_DATA_DIR=/app/data
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./dockhand-data:/app/data # Data directory for Dockhand - you may need to change the path
depends_on:
tailscale:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:41234/healthz"] # Check if ${SERVICE} is responding
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