Remote Docker agent for Dockhand - manage Docker hosts anywhere.
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)
Download the latest release from GitHub Releases.
Standard Mode:
hawser --port 2376Standard Mode with Token Authentication (optional):
TOKEN=your-secret-token hawser --port 2376Standard Mode with TLS (optional):
TLS_CERT=/path/to/server.crt TLS_KEY=/path/to/server.key hawser --port 2376Standard 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 2376Edge Mode:
hawser --server wss://your-dockhand.example.com/api/hawser/connect --token your-tokenEdge Mode with Self-Signed Certificate:
CA_CERT=/path/to/dockhand-ca.crt hawser --server wss://your-dockhand.example.com/api/hawser/connect --token your-tokenEdge 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- 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/configExample config for Standard Mode:
# Standard mode - listen for connections
PORT=2376
# Optional: require token authentication
TOKEN=your-secret-tokenExample 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 hawserIf 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=60Manual 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 -fNote: 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:latestStandard 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:latestStandard 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:latestStandard 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:latestEdge 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:latestEdge 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:latestFor 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:localNote: The default Dockerfile is used by GoReleaser for release builds and expects a pre-built binary. Use Dockerfile.dev for building from source.
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 .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 | jqCustom 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:latestHawser 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 |
Hawser automatically detects the operational mode:
- If
DOCKHAND_SERVER_URLandTOKENare set → Edge Mode - Otherwise → Standard Mode
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:latestDebug mode logs all Docker API requests, which is useful for troubleshooting connectivity issues.
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
Hawser includes Docker Compose support for stack operations:
up- Deploy stackdown- Remove stackpull- Pull imagesps- List serviceslogs- View logs
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.
- Auto-reconnect: Edge mode automatically reconnects with exponential backoff
- Heartbeat: Regular keepalive messages maintain connection health
- Graceful shutdown: Clean shutdown on SIGTERM/SIGINT
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.
In Standard mode, Hawser proxies all Docker API endpoints plus:
| Endpoint | Description |
|---|---|
/_hawser/health |
Health check (no auth required) |
/_hawser/info |
Agent information |
# 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}-
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.
# Clone repository
git clone https://github.com/Finsys/hawser.git
cd hawser
# Build
go build -o hawser ./cmd/hawser
# Run
./hawser --port 2376docker build -t hawser .Contributions are welcome! Please read the contributing guidelines before submitting a pull request.
MIT License - see LICENSE for details.
- Dockhand - Modern Docker management application
- Docker Engine API - Docker API documentation
Made with ❤️ and mass amounts of ☕ by Finsys for Dockhand
