README
¶
Hawser
Remote Docker agent for Dockhand - manage Docker hosts anywhere.
Overview
Hawser is a lightweight Go agent that enables Dockhand to manage Docker hosts in various network configurations. It supports two operational modes:
- Standard Mode: Agent listens for incoming connections (ideal for LAN/homelab with static IPs)
- Edge Mode: Agent initiates outbound WebSocket connection to Dockhand (ideal for VPS, NAT, dynamic IP)
Quick Start
Binary
Download the latest release from GitHub Releases.
Standard Mode:
hawser --port 2376
Standard Mode with Token Authentication (optional):
TOKEN=your-secret-token hawser --port 2376
Standard Mode with TLS (optional):
TLS_CERT=/path/to/server.crt TLS_KEY=/path/to/server.key hawser --port 2376
Standard Mode with TLS and Token (recommended for production):
TLS_CERT=/path/to/server.crt TLS_KEY=/path/to/server.key TOKEN=your-secret-token hawser --port 2376
Edge Mode:
hawser --server wss://your-dockhand.example.com/api/hawser/connect --token your-token
Edge Mode with Self-Signed Certificate:
CA_CERT=/path/to/dockhand-ca.crt hawser --server wss://your-dockhand.example.com/api/hawser/connect --token your-token
Edge Mode with TLS Skip Verify (insecure, for testing):
TLS_SKIP_VERIFY=true hawser --server wss://your-dockhand.example.com/api/hawser/connect --token your-token
Systemd Service
Quick Install
- Download and install the binary:
curl -fsSL https://raw.githubusercontent.com/Finsys/hawser/main/scripts/install.sh | bash
- Configure the service:
sudo nano /etc/hawser/config
Example config for Standard Mode:
# Standard mode - listen for connections
PORT=2376
# Optional: require token authentication
TOKEN=your-secret-token
Example config for Edge Mode:
# Edge mode - connect to Dockhand server
DOCKHAND_SERVER_URL=wss://your-dockhand.example.com/api/hawser/connect
TOKEN=your-agent-token
- Start the service:
sudo systemctl enable --now hawser
Full Systemd Service File
If you prefer to set up the systemd service manually, here's the complete service file:
/etc/systemd/system/hawser.service
[Unit]
Description=Hawser - Remote Docker Agent for Dockhand
Documentation=https://github.com/Finsys/hawser
After=network-online.target docker.service
Wants=network-online.target
Requires=docker.service
[Service]
Type=simple
ExecStart=/usr/local/bin/hawser
Restart=always
RestartSec=10
EnvironmentFile=/etc/hawser/config
# Security hardening
NoNewPrivileges=false
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/run/docker.sock /data/stacks
[Install]
WantedBy=multi-user.target
/etc/hawser/config (Standard Mode example):
# Hawser Configuration
# See https://github.com/Finsys/hawser for documentation
# Standard Mode
PORT=2376
# Docker socket path
DOCKER_SOCKET=/var/run/docker.sock
# Agent identification (optional)
# AGENT_NAME=my-server
# Token authentication (optional)
# TOKEN=your-secret-token
# TLS configuration (optional)
# TLS_CERT=/etc/hawser/server.crt
# TLS_KEY=/etc/hawser/server.key
/etc/hawser/config (Edge Mode example):
# Hawser Configuration
# See https://github.com/Finsys/hawser for documentation
# Edge Mode - connect to Dockhand server
DOCKHAND_SERVER_URL=wss://your-dockhand.example.com/api/hawser/connect
TOKEN=your-agent-token
# Docker socket path
DOCKER_SOCKET=/var/run/docker.sock
# Agent identification (optional)
# AGENT_NAME=my-server
# TLS configuration for self-signed Dockhand (optional)
# CA_CERT=/etc/hawser/dockhand-ca.crt
# TLS_SKIP_VERIFY=false
# Connection settings (optional)
# HEARTBEAT_INTERVAL=30
# RECONNECT_DELAY=1
# MAX_RECONNECT_DELAY=60
Manual installation steps:
# 1. Download binary
curl -fsSL https://github.com/Finsys/hawser/releases/latest/download/hawser_linux_amd64.tar.gz | tar xz
sudo install -m 755 hawser /usr/local/bin/hawser
# 2. Create config directory
sudo mkdir -p /etc/hawser
# 3. Create config file (edit with your settings)
sudo tee /etc/hawser/config << 'EOF'
PORT=2376
DOCKER_SOCKET=/var/run/docker.sock
EOF
# 4. Create systemd service file
sudo tee /etc/systemd/system/hawser.service << 'EOF'
[Unit]
Description=Hawser - Remote Docker Agent for Dockhand
Documentation=https://github.com/Finsys/hawser
After=network-online.target docker.service
Wants=network-online.target
Requires=docker.service
[Service]
Type=simple
ExecStart=/usr/local/bin/hawser
Restart=always
RestartSec=10
EnvironmentFile=/etc/hawser/config
NoNewPrivileges=false
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/run/docker.sock /data/stacks
[Install]
WantedBy=multi-user.target
EOF
# 5. Enable and start the service
sudo systemctl daemon-reload
sudo systemctl enable --now hawser
# 6. Check status
sudo systemctl status hawser
sudo journalctl -u hawser -f
Docker
Note: Hawser stores compose stack files in
/data/stacks. This is declared as aVOLUMEin the image, so it's always writable. For persistent stack files, mount a host directory to this path.
Standard Mode - Agent listens for connections:
docker run -d \
--name hawser \
-v /var/run/docker.sock:/var/run/docker.sock \
-v hawser_stacks:/data/stacks \
-p 2376:2376 \
ghcr.io/finsys/hawser:latest
Standard Mode with Token Authentication (optional):
docker run -d \
--name hawser \
-v /var/run/docker.sock:/var/run/docker.sock \
-v hawser_stacks:/data/stacks \
-p 2376:2376 \
-e TOKEN=your-secret-token \
ghcr.io/finsys/hawser:latest
Standard Mode with TLS (optional):
docker run -d \
--name hawser \
-v /var/run/docker.sock:/var/run/docker.sock \
-v hawser_stacks:/data/stacks \
-v /path/to/certs:/certs:ro \
-p 2376:2376 \
-e TLS_CERT=/certs/server.crt \
-e TLS_KEY=/certs/server.key \
ghcr.io/finsys/hawser:latest
Standard Mode with TLS and Token (recommended for production):
docker run -d \
--name hawser \
-v /var/run/docker.sock:/var/run/docker.sock \
-v hawser_stacks:/data/stacks \
-v /path/to/certs:/certs:ro \
-p 2376:2376 \
-e TLS_CERT=/certs/server.crt \
-e TLS_KEY=/certs/server.key \
-e TOKEN=your-secret-token \
ghcr.io/finsys/hawser:latest
Edge Mode - Agent connects to Dockhand:
docker run -d \
--name hawser \
-v /var/run/docker.sock:/var/run/docker.sock \
-v hawser_stacks:/data/stacks \
-e DOCKHAND_SERVER_URL=wss://your-dockhand.example.com/api/hawser/connect \
-e TOKEN=your-agent-token \
ghcr.io/finsys/hawser:latest
Edge Mode with Self-Signed Certificate:
docker run -d \
--name hawser \
-v /var/run/docker.sock:/var/run/docker.sock \
-v hawser_stacks:/data/stacks \
-v /path/to/dockhand-ca.crt:/certs/ca.crt:ro \
-e DOCKHAND_SERVER_URL=wss://your-dockhand.example.com/api/hawser/connect \
-e TOKEN=your-agent-token \
-e CA_CERT=/certs/ca.crt \
ghcr.io/finsys/hawser:latest
Building Docker image locally
For local development or custom builds, use the multi-stage Dockerfile.dev which builds from source:
# Clone repository
git clone https://github.com/Finsys/hawser.git
cd hawser
# Build from source (recommended for local development)
docker build -f Dockerfile.dev -t hawser:local .
# Run locally built image - Standard mode
docker run -d \
--name hawser \
-v /var/run/docker.sock:/var/run/docker.sock \
-v hawser_stacks:/data/stacks \
-p 2376:2376 \
hawser:local
# Run locally built image - Edge mode
docker run -d \
--name hawser \
-v /var/run/docker.sock:/var/run/docker.sock \
-v hawser_stacks:/data/stacks \
-e DOCKHAND_SERVER_URL=wss://your-dockhand.example.com/api/hawser/connect \
-e TOKEN=your-agent-token \
hawser:local
Note: The default Dockerfile is used by GoReleaser for release builds and expects a pre-built binary. Use Dockerfile.dev for building from source.
Multi-architecture builds
The official images on ghcr.io/finsys/hawser are multi-arch (amd64 + arm64). For local multi-arch builds:
# Create a builder (first time only)
docker buildx create --name mybuilder --use
# Build for multiple platforms
docker buildx build -f Dockerfile.dev \
--platform linux/amd64,linux/arm64 \
-t hawser:local \
--load .
Docker health check
The Hawser Docker image includes a built-in health check that verifies Docker connectivity. This works in both Standard and Edge modes.
How it works:
- The container runs
wgetagainst the/_hawser/healthendpoint every 30 seconds - Both modes expose a minimal HTTP server on the configured port (default: 2376) for health checks
- The health check verifies that Hawser can communicate with the Docker daemon
Health check response:
# Standard mode
curl http://localhost:2376/_hawser/health
{"status":"healthy"}
# Edge mode (includes connection status)
curl http://localhost:2376/_hawser/health
{"status":"healthy","mode":"edge","connected":true}
Container status:
# Check container health status
docker inspect --format='{{.State.Health.Status}}' hawser
# healthy
# View health check logs
docker inspect --format='{{json .State.Health}}' hawser | jq
Custom health check (optional):
If you need custom health check settings, you can override the built-in health check:
docker run -d \
--name hawser \
-v /var/run/docker.sock:/var/run/docker.sock \
-e DOCKHAND_SERVER_URL=wss://your-dockhand.example.com/api/hawser/connect \
-e TOKEN=your-agent-token \
--health-cmd="wget -q --spider http://localhost:2376/_hawser/health || exit 1" \
--health-interval=30s \
--health-timeout=5s \
--health-retries=3 \
--health-start-period=10s \
ghcr.io/finsys/hawser:latest
Configuration
Hawser is configured via environment variables:
| Variable | Description | Default |
|---|---|---|
DOCKHAND_SERVER_URL |
WebSocket URL for Edge mode | - |
TOKEN |
Authentication token | - |
CA_CERT |
Path to CA certificate for Edge mode (self-signed Dockhand) | - |
TLS_SKIP_VERIFY |
Skip TLS verification for Edge mode (insecure) | false |
PORT |
HTTP server port (Standard mode) | 2376 |
TLS_CERT |
Path to TLS certificate (Standard mode server cert) | - |
TLS_KEY |
Path to TLS private key (Standard mode server key) | - |
DOCKER_SOCKET |
Docker socket path | /var/run/docker.sock |
STACKS_DIR |
Directory for compose stack files (requires Dockhand 1.0.5+) | /tmp/stacks |
AGENT_ID |
Unique agent identifier | Auto-generated UUID |
AGENT_NAME |
Human-readable agent name | Hostname |
HEARTBEAT_INTERVAL |
Heartbeat interval in seconds | 30 |
REQUEST_TIMEOUT |
Request timeout in seconds | 30 |
RECONNECT_DELAY |
Initial reconnect delay (Edge mode) | 1 |
MAX_RECONNECT_DELAY |
Maximum reconnect delay | 60 |
LOG_LEVEL |
Logging level: debug, info, warn, error |
info |
SKIP_DF_COLLECTION |
Skip disk usage collection (see below) | - |
Mode Detection
Hawser automatically detects the operational mode:
- If
DOCKHAND_SERVER_URLandTOKENare set → Edge Mode - Otherwise → Standard Mode
Log Levels
The LOG_LEVEL environment variable controls verbosity:
| Level | Description |
|---|---|
debug |
All messages including Docker API calls (method, path, status codes) |
info |
Standard operational messages (connections, startup, shutdown) |
warn |
Warnings only |
error |
Errors only |
Example: Debug mode
# Binary
LOG_LEVEL=debug hawser --port 2376
# Docker
docker run -d \
--name hawser \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 2376:2376 \
-e LOG_LEVEL=debug \
ghcr.io/finsys/hawser:latest
Debug mode logs all Docker API requests, which is useful for troubleshooting connectivity issues.
Features
Docker API Proxy
Hawser provides full access to the Docker API:
- Container management (create, start, stop, remove)
- Image operations (pull, list, remove)
- Volume and network management
- Log streaming
- Interactive exec sessions
Docker Compose Support
Hawser includes Docker Compose support for stack operations:
up- Deploy stackdown- Remove stackpull- Pull imagesps- List serviceslogs- View logs
Host Metrics
Hawser collects and reports host metrics:
- CPU usage (per-core and total)
- Memory (total, used, available)
- Disk usage (Docker data directory)
- Network I/O statistics
Metrics are sent every 30 seconds in Edge mode.
Disabling Disk Usage Collection
On some systems, particularly NAS devices (Synology, QNAP, TrueNAS) or hosts with many mounted volumes, the disk usage collection can cause performance issues. The statfs system call used to check disk space can be slow when there are many mounted filesystems or network mounts.
To disable disk usage collection, set the SKIP_DF_COLLECTION environment variable to any non-empty value:
# Binary
SKIP_DF_COLLECTION=1 hawser --port 2376
# Docker
docker run -d \
--name hawser \
-v /var/run/docker.sock:/var/run/docker.sock \
-e SKIP_DF_COLLECTION=1 \
ghcr.io/finsys/hawser:latest
# Systemd config (/etc/hawser/config)
SKIP_DF_COLLECTION=1
When disabled, disk metrics will show as 0 in Dockhand (displayed as "N/A").
Reliability
- Auto-reconnect: Edge mode automatically reconnects with exponential backoff
- Heartbeat: Regular keepalive messages maintain connection health
- Graceful shutdown: Clean shutdown on SIGTERM/SIGINT
Docker API Version Compatibility
Hawser automatically negotiates the Docker API version with the daemon. When running Docker Compose operations, Hawser sets the DOCKER_API_VERSION environment variable to match the daemon's reported API version. This ensures compatibility when the Docker CLI version differs from the daemon version - for example, when using an older Docker CLI with a newer Docker daemon that requires a higher minimum API version.
API Endpoints
Standard Mode
In Standard mode, Hawser proxies all Docker API endpoints plus:
| Endpoint | Description |
|---|---|
/_hawser/health |
Health check (no auth required) |
/_hawser/info |
Agent information |
Health Check
# Standard mode
curl http://localhost:2376/_hawser/health
# {"status":"healthy"}
# Edge mode (includes WebSocket connection status)
curl http://localhost:2376/_hawser/health
# {"status":"healthy","mode":"edge","connected":true}
Security Considerations
-
Docker Socket Access: Hawser requires access to the Docker socket, which provides full control over Docker. Run with appropriate access controls.
-
Network Security:
- Standard mode: Use TLS and/or token authentication
- Edge mode: Use WSS (TLS-encrypted WebSocket)
-
Token Security: Tokens should be strong, randomly generated strings. In Dockhand, tokens are shown only once when generated.
Building from Source
# Clone repository
git clone https://github.com/Finsys/hawser.git
cd hawser
# Build
go build -o hawser ./cmd/hawser
# Run
./hawser --port 2376
Docker Build
docker build -t hawser .
Contributing
Contributions are welcome! Please read the contributing guidelines before submitting a pull request.
License
MIT License - see LICENSE for details.
Related
- Dockhand - Modern Docker management application
- Docker Engine API - Docker API documentation
Made with ❤️ and mass amounts of ☕ by Finsys for Dockhand