The updater could install an unverified binary three ways: it skipped verification when no checksums URL was given, returned success when no checksum line matched the platform, and ignored the HTTP status of the checksums fetch (a 404 body parsed to an empty map → skipped). Since the updater runs as the agent process (root on packaged installs), that was a code-execution primitive that bypassed every feature gate. - Refuse to install without a checksums URL. - Extract a pure, fail-closed matchChecksum: empty/unparseable body, no entry for this GOOS/GOARCH, or a mismatch all error (was a silent skip). - Check the checksums fetch HTTP status. - requireSecureURL rejects non-HTTPS update/checksum URLs (dev override via SERVERKIT_INSECURE_TLS). - updater_test.go: 6 tests covering match/mismatch/no-entry/empty/case/https. Cryptographic release signing remains the recommended next layer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ServerKit Agent
A lightweight, cross-platform agent for remote server management. Connects to a ServerKit control plane to enable Docker management, system monitoring, and remote command execution.
Features
- Cross-Platform: Supports Linux (amd64, arm64, arm), Windows (amd64, arm64), and macOS (amd64, arm64)
- Lightweight: Single binary, ~15MB RAM typical usage
- Docker Integration: Full Docker API access for container management
- System Metrics: Real-time CPU, memory, disk, and network monitoring
- Secure Communication: TLS encryption with HMAC-SHA256 authentication
- Auto-Reconnect: Automatic reconnection with exponential backoff
- Self-Update: Built-in auto-update with periodic version checks
Quick Start
Linux (One-liner)
curl -fsSL https://your-serverkit.com/install.sh | sudo bash -s -- \
--token "sk_reg_your_token" \
--server "https://your-serverkit.com"
Windows (PowerShell as Administrator)
irm https://your-serverkit.com/install.ps1 | iex
Install-ServerKitAgent -Token "sk_reg_your_token" -Server "https://your-serverkit.com"
Most Windows users should install the MSI instead (see Package Installation below). The MSI registers the
ServerKitAgentWindows service and opens a native pairing wizard right after install — no token handling and no browser required.
Pairing (recommended)
Instead of baking a long registration token into an install command, you can adopt an agent with a short, human-friendly code:
serverkit-agent pair --server "https://your-serverkit.com"
The agent generates an Ed25519 keypair, prints a short pairing code (and passphrase), and waits. In the panel's Add Server screen, enter the code + passphrase and verify the displayed key fingerprint to approve the device. On Windows the MSI launches this wizard automatically. See ../docs/pairing.md for the full flow and security properties.
Docker (Recommended for containerized environments)
# Pull the image
docker pull serverkit/agent:latest
# Register the agent (one-time setup)
docker run --rm -v serverkit-agent-config:/etc/serverkit-agent \
serverkit/agent:latest register \
--token "sk_reg_your_token" \
--server "https://your-serverkit.com"
# Start the agent
docker run -d --name serverkit-agent \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v serverkit-agent-config:/etc/serverkit-agent \
serverkit/agent:latest
Or use Docker Compose:
# Clone and navigate to agent directory
cd agent
# Register (one-time setup)
docker compose run --rm agent register -s https://your-serverkit.com -t YOUR_TOKEN
# Start the agent
docker compose up -d
# View logs
docker compose logs -f
Package Installation
Debian/Ubuntu (.deb):
curl -LO https://github.com/jhd3197/ServerKit/releases/latest/download/serverkit-agent_VERSION_amd64.deb
sudo dpkg -i serverkit-agent_VERSION_amd64.deb
sudo serverkit-agent register --token "YOUR_TOKEN" --server "https://your-serverkit.com"
sudo systemctl start serverkit-agent
RHEL/CentOS/Fedora (.rpm):
sudo rpm -i https://github.com/jhd3197/ServerKit/releases/latest/download/serverkit-agent-VERSION-1.x86_64.rpm
sudo serverkit-agent register --token "YOUR_TOKEN" --server "https://your-serverkit.com"
sudo systemctl start serverkit-agent
Windows (.msi): Download and run the MSI installer from the releases page, then:
serverkit-agent register --token "YOUR_TOKEN" --server "https://your-serverkit.com"
Start-Service ServerKitAgent
Manual Installation
- Download the appropriate binary for your platform from the releases page
- Register the agent:
./serverkit-agent register --token "sk_reg_xxx" --server "https://your-serverkit.com" - Start the agent:
./serverkit-agent start
Building from Source
Prerequisites
- Go 1.23 or later (matches CI)
- Make (optional, for using Makefile)
Build
# Clone the repository (the agent lives in the ServerKit monorepo)
git clone https://github.com/jhd3197/ServerKit.git
cd ServerKit/agent
# Download dependencies
go mod download
# Build for current platform
make build
# Or build for all platforms
make build-all
Build Outputs
Binaries are placed in the dist/ directory:
serverkit-agent-{version}-linux-amd64serverkit-agent-{version}-linux-arm64serverkit-agent-{version}-windows-amd64.exeserverkit-agent-{version}-darwin-amd64serverkit-agent-{version}-darwin-arm64
Usage
Commands
serverkit-agent [command]
Available Commands:
start Start the agent service
register Register with a ServerKit instance (pre-shared token)
pair Pair with a panel using a short code (recommended)
setup Run the guided setup wizard
status Show agent status
config Configuration management
update Check for and apply self-updates
tray Run the system-tray app (desktop)
console Open the desktop console (WebView2)
version Show version information
help Help about any command
Run with no command to launch the desktop app: the pairing wizard if the agent
is not yet configured, otherwise the system tray.
Flags:
-c, --config string config file path
-d, --debug enable debug logging
-h, --help help for serverkit-agent
Register
serverkit-agent register \
--token "sk_reg_xxx" \
--server "https://your-serverkit.com" \
--name "my-server"
Start
# Foreground
serverkit-agent start
# With debug logging
serverkit-agent start --debug
Configuration
Configuration file location:
- Linux:
/etc/serverkit-agent/config.yaml - Windows:
C:\ProgramData\ServerKit\Agent\config.yaml
Example Configuration
server:
url: wss://your-serverkit.com/agent/ws
reconnect_interval: 5s
max_reconnect_interval: 5m
ping_interval: 30s
agent:
id: "auto-generated"
name: "my-server"
features:
docker: true
metrics: true
logs: true
file_access: false
exec: false
metrics:
enabled: true
interval: 10s
include_per_cpu: true
include_docker_stats: true
docker:
socket: /var/run/docker.sock
timeout: 30s
logging:
level: info
file: /var/log/serverkit-agent/agent.log
max_size_mb: 100
max_backups: 5
max_age_days: 30
compress: true
Security
Authentication
The agent uses HMAC-SHA256 signatures for authentication:
- During registration, the agent receives an API key and secret
- Each WebSocket connection is authenticated using HMAC-signed messages
- Session tokens are issued after successful authentication
Credentials Storage
Credentials are encrypted at rest using AES-256-GCM with a host-stable key derived from:
- Hostname
- Machine ID (Linux) / Computer name (Windows)
The key is deliberately independent of the logged-in user. On Windows this
lets the LocalSystem service decrypt credentials that were written during
user-context pairing. (Mixing in the Windows username broke exactly this and was
removed in 1.6.14.) Because the key is host-bound, a copied credential file
cannot be reused on another machine.
Treat
agent.keyas a host-equivalent secret. Anyone who can read this file on the host (or recreate the host-derived key) can recover the agent's API credentials. Combined with remote command execution (see below), a leaked key file is equivalent to full control of that host.
Network Security
- All communication uses TLS (WSS)
- Certificate validation is enforced in production
- Replay attack protection via timestamps and nonces
Systemd Service (Linux)
The installation script automatically creates a systemd service:
# Check status
systemctl status serverkit-agent
# View logs
journalctl -u serverkit-agent -f
# Restart
systemctl restart serverkit-agent
Windows Service & Desktop App
On Windows the agent has two cooperating parts:
1. The background service — a true Windows Service (ServerKitAgent)
registered through the Service Control Manager, running as LocalSystem and set
to start automatically. This is what stays connected to the panel.
# Check status
Get-Service ServerKitAgent
# View logs
Get-Content "C:\ProgramData\ServerKit\Agent\logs\agent.log" -Tail 50
# Restart
Restart-Service ServerKitAgent
2. The desktop app — an optional per-user UI auto-started via the HKCU\...\Run
key:
- Pairing/setup wizard — runs after install (or on first launch) to adopt the agent into a panel.
- System tray — shows connection status and quick actions.
- Desktop console — a WebView2-hosted view of status, logs, activity, and actions (no external browser required).
Windows limitations to be aware of: system metrics report a single volume (
C:\), and the remote file browser currently lists the agent's working drive rather than enumerating all drives. Multi-drive support is tracked for a future release.
Windows environment variables
| Variable | Purpose |
|---|---|
SERVERKIT_INSECURE_TLS |
Disable TLS certificate verification (dev/testing only) |
SERVERKIT_WS_COMPRESSION |
Enable WebSocket permessage-deflate (off by default; some tunnels corrupt compressed frames) |
SERVERKIT_AGENT_LEGACY_WIZARD |
Use the legacy native setup wizard instead of the WebView2 one |
Docker Deployment
Building the Image
cd agent
# Build with version info
docker build \
--build-arg VERSION=1.0.0 \
--build-arg BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
--build-arg GIT_COMMIT=$(git rev-parse --short HEAD) \
-t serverkit/agent:latest .
Running with Docker
# Register the agent first
docker run --rm \
-v serverkit-agent-config:/etc/serverkit-agent \
serverkit/agent:latest register \
--token "sk_reg_xxx" \
--server "https://your-serverkit.com" \
--name "my-server"
# Run the agent
docker run -d \
--name serverkit-agent \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v serverkit-agent-config:/etc/serverkit-agent \
-v serverkit-agent-logs:/var/log/serverkit-agent \
serverkit/agent:latest
Running with Docker Compose
# docker-compose.yml
services:
agent:
image: serverkit/agent:latest
container_name: serverkit-agent
restart: unless-stopped
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- serverkit-config:/etc/serverkit-agent
- serverkit-logs:/var/log/serverkit-agent
environment:
- TZ=UTC
volumes:
serverkit-config:
serverkit-logs:
# Register
docker compose run --rm agent register -s https://your-serverkit.com -t YOUR_TOKEN
# Start
docker compose up -d
# Logs
docker compose logs -f
# Stop
docker compose down
Environment Variables
| Variable | Description | Default |
|---|---|---|
TZ |
Timezone | UTC |
Volumes
| Path | Description |
|---|---|
/etc/serverkit-agent |
Configuration and credentials |
/var/log/serverkit-agent |
Log files |
/var/run/docker.sock |
Docker socket (mount read-only) |
Development
Project Structure
agent/
├── cmd/agent/ # Main entry point (+ Windows service/console glue)
├── internal/
│ ├── agent/ # Core agent logic & command handlers
│ ├── agentui/ # Desktop console UI (WebView2)
│ ├── auth/ # HMAC authentication
│ ├── capabilities/ # Host capability probing
│ ├── cloudflared/ # Cloudflare tunnel management
│ ├── config/ # Configuration management
│ ├── cron/ # Remote cron management
│ ├── docker/ # Docker client wrapper
│ ├── ipc/ # Local IPC (desktop UI <-> agent)
│ ├── jobs/ # Background job runner
│ ├── logger/ # Structured logging
│ ├── metrics/ # System metrics collection
│ ├── pairing/ # Pairing client & keypair enrollment
│ ├── setupui/ # First-run setup wizard (Windows)
│ ├── terminal/ # Remote terminal sessions
│ ├── transport/ # WebSocket + HTTP-poll transports
│ ├── tray/ # System tray integration
│ ├── updater/ # Self-update mechanism
│ └── ws/ # WebSocket client
├── pkg/protocol/ # Message protocol (shared contract with the panel)
├── packaging/ # MSI / deb / rpm packaging
├── scripts/ # Build and install scripts
├── ui/ # Agent desktop UI (React)
├── Makefile
└── go.mod
Running Tests
make test
Code Formatting
make fmt
Troubleshooting
Agent won't connect
- Check the server URL is correct
- Verify the registration token is valid
- Check firewall allows outbound WebSocket connections
- Review logs:
journalctl -u serverkit-agent -n 50
Docker commands fail
- Ensure Docker is installed and running
- Verify the agent user has Docker permissions:
sudo usermod -aG docker serverkit-agent - Check Docker socket permissions
High CPU/Memory usage
- Increase the metrics interval in config
- Disable per-CPU metrics if not needed
- Check for log rotation issues
License
MIT License - see LICENSE file for details.