getkaze/keel has 33 GitHub stars and 0 forks. GitHot measured 0 stars in 24 hours, 0 in 7 days, and 0 in 15 days. Last checked 2026-11-10 01:13 UTC. Last push 2026-04-06.
Self-hosted Docker dashboard. One binary. Zero dependencies.
Measured star growth
- in 24h
- 0
- in 7 days
- 0
- in 15 days
- 0
- in 1 month
- Update delayed
Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.
README.md
Original
One binary. Zero dependencies. Full Docker control.
Prerequisites · Install · Usage · Features · Seeders · Dev Mode · Remote Targets · Service Config · Stack · Build · Data Directory
What is Keel
Keel (the keel of a ship — the hidden structure that keeps everything aligned) is a self-hosted web dashboard for managing Docker environments — local or remote via SSH — from a single Go binary (~10MB, no external dependencies).
keel
That's it. Open http://localhost:60000 and you have a full dashboard with live status, logs, terminal, metrics, and container management.
Prerequisites
- Docker — local install or remote host with Docker via SSH
- SSH key pair — required for remote targets
- sudo — only for
keel hosts setup(modifies/etc/hosts)
Install
curl -fsSL https://getkaze.dev/keel/install.sh | sudo bash
This installs the binary to ~/.local/bin/keel and creates the data directory at /var/lib/keel. The binary is owned by your user, enabling self-update from the dashboard without sudo. The installer automatically adds ~/.local/bin to your PATH (supports zsh, bash, and fish).
Usage
# Start the dashboard (default: http://localhost:60000)
keel
# Container operations
keel start # start all services
keel start redis mysql # start specific services
keel start infra # start all services in a group
keel stop # stop all services
keel stop traefik # stop specific service
keel stop tools # stop all services in a group
keel restart # restart all services (stop + start)
keel restart redis mysql # restart specific services
keel reset --all # destroy and recreate all containers
keel reset redis # recreate a single service
# Remote targets
keel target # show active target
keel target ec2 # switch to remote target
# Dev mode — mount local code into a container with hot reload
keel dev api ~/projects/api
# Seeders — run data seeding scripts inside containers
keel seed # run all seeders
keel seed mysql-init # run a single seeder
# Updates
keel update # check for updates and install latest
# Hosts — manage /etc/hosts entries from Traefik config
keel hosts setup # add service domains to /etc/hosts
keel hosts setup --ip 10.0.0.5 # use custom IP
keel hosts remove # remove keel entries
# Maintenance
keel purge # remove all containers + network + data directory
keel version
keel help
Flags
| Flag | Default | Description |
|---|---|---|
-port |
60000 |
HTTP port |
-bind |
127.0.0.1 |
Bind address |
-keel-dir |
/var/lib/keel (Linux) or ~/.keel (macOS) |
Data directory |
-dev |
false |
Serve web assets from filesystem |
Override the data directory with KEEL_DIR environment variable.
Features
Dashboard
Live grid view of all containers with real-time status polling. Group services by category. Start, stop, restart, and update containers directly from the UI.
Logs
SSE-based streaming from docker logs or container files. Supports host-path logs — read log files directly from the host filesystem even when the container is crashed or stopped.
Terminal
Full interactive terminal in the browser via WebSocket + PTY. Ctrl+` to toggle. Multi-tab support — a fixed Local tab is always available, and each docker exec connection opens in its own tab. Click CONNECT on any running container to open a shell session.
Metrics
Real-time CPU, memory, disk, load average, uptime, and per-container Docker stats (CPU%, RAM, network I/O, block I/O).
Config Editor
Inline JSON editor for each service. Edit, save, and the config is written atomically with backup.
Dashboard URL
Services can define a dashboard_url in their JSON config. When set, an OPEN button appears on both the overview card and detail page, linking to the service's web UI (e.g., RedisInsight, DBGate, pgAdmin).
{
"name": "redisinsight",
"dashboard_url": "http://localhost:5540"
}
Health Checks
HTTP or command-based health checks with configurable interval, retries, and start period.
Seeders
Run data seeding scripts inside running containers — database migrations, fixture data, initial configs.
Each seeder is a JSON file in data/seeders/:
{
"name": "mysql-init",
"target": "db-seeder",
"description": "Create localdev databases, users, and seed data",
"order": 1,
"commands": [
{ "name": "Install dependencies", "command": "pip install mysql-connector-python" },
{ "name": "Seed data", "command": "python3 seed.py --env localdev" }
]
}
| Field | Description |
|---|---|
target |
Container name to exec into |
order |
Execution order (lower = first) |
commands |
Ordered list of steps (see below) |
Each command entry supports:
| Field | Description |
|---|---|
name |
Step identifier |
command |
Single command to execute via docker exec |
script |
Filename of a script in the seeders directory (alternative to command) |
interpreter |
Interpreter to pipe the script into — e.g. bash, python3 (used with script) |
http |
HTTP request to execute via curl inside the target container (alternative to command/script) |
Seeders can be run from the UI (Seeders page) or via CLI:
keel seed # run all seeders in order
keel seed mysql-init # run a single seeder
Dev Mode
Run a service locally with your source code mounted and hot reload enabled.
keel dev <service> <local-path>
How it works:
- Reads
dev.dockerfilefrom the service JSON and builds a dev image - Stops the existing container
- Runs the dev container in foreground with your local code mounted as a volume
- Streams stdout/stderr to your terminal — Ctrl+C to stop
Requirement: local target only (not supported over SSH).
Example service config:
{
"dev": {
"dockerfile": [
"FROM golang:1.24",
"RUN go install github.com/air-verse/air@latest",
"WORKDIR /app",
"COPY go.mod go.sum ./",
"RUN go mod download"
],
"command": ["air"],
"cap_add": ["NET_BIND_SERVICE"]
}
}
Remote Targets
Keel supports multiple Docker targets — local or remote via SSH tunnel.
{
"targets": {
"local": { "host": "127.0.0.1" },
"ec2": {
"host": "1.2.3.4",
"ssh_user": "ubuntu",
"ssh_key": "~/.ssh/id_ed25519",
"ssh_jump": "[email protected]",
"external_ip": "1.2.3.4",
"port_bind": "0.0.0.0",
"description": "AWS EC2 Ubuntu"
}
},
"default": "local"
}
| Field | Description |
|---|---|
host |
IP address or hostname |
ssh_user |
SSH user for remote targets (omit for local) |
ssh_key |
Path to SSH private key (supports ~/) |
ssh_jump |
Bastion/jump host for multi-hop SSH |
external_ip |
External IP used by keel hosts setup |
port_bind |
Bind interface for ports — 127.0.0.1 (default) or 0.0.0.0 |
description |
Human-readable target label |
default |
Root-level field — default target name |
keel target ec2 # switch to remote
keel start # commands now execute on ec2 via SSH
keel target local # switch back
For remote targets, an SSH tunnel is opened automatically, forwarding the remote Docker socket to a local Unix socket (/tmp/keel-docker-<target>.sock). The tunnel is monitored with automatic reconnection and exponential backoff — a live status dot in the topbar shows the connection state via SSE.
Service Config
Each service is a JSON file in data/services/. Full example:
{
"name": "redis",
"group": "database",
"hostname": "keel-redis",
"image": "redis:7",
"network": "keel-net",
"ports": { "internal": 6379, "external": 6379 },
"environment": { "REDIS_ARGS": "--maxmemory 256mb" },
"volumes": ["keel-redis-data:/data"],
"command": "redis-server --save 60 1",
"files": ["data/config/redis.conf:/etc/redis/redis.conf"],
"start_order": 1,
"ram_estimate_mb": 256,
"dashboard_url": "http://localhost:8001",
"health_check": {
"type": "command",
"command": "redis-cli ping",
"interval": 5,
"retries": 10,
"start_period": 5
},
"logs": [
{ "name": "redis", "type": "docker" },
{ "name": "slow", "type": "file", "path": "/var/log/redis-slow.log", "host_path": "/applog/redis/slow.log" }
],
"dev": {
"dockerfile": ["FROM redis:7", "WORKDIR /data"],
"command": ["redis-server", "--loglevel", "debug"]
}
}
| Field | Description |
|---|---|
name |
Unique service identifier |
group |
Logical grouping — infra starts first, then seeders, then the rest |
hostname |
Docker container hostname |
image |
Docker image name:tag |
registry |
ghcr — auto-login with stored credentials; local — skip pull for locally built images (omit for public images) |
network |
Docker network (defaults to keel-net) |
ports |
{ internal, external } primary port mapping |
extra_ports |
Additional { internal, external } port mappings |
environment |
Environment variables passed to the container |
volumes |
Volume mounts — named volumes, bind mounts, or config files |
command |
Override container CMD |
files |
Config files mounted read-only into the container; synced via scp on remote targets (local:container) |
platform |
Force a specific platform for the image (e.g. linux/amd64) — useful for cross-architecture hosts |
start_order |
Startup priority (lower = earlier, 0 = last) |
ram_estimate_mb |
Display hint for the dashboard |
dashboard_url |
External URL — shows an OPEN button in the UI |
health_check |
HTTP or command-based health check config |
logs |
Log sources — docker or file with optional host_path |
network_aliases |
Docker network aliases — enables virtual hostname resolution within the network |
dev |
Development mode config — dockerfile, command, cap_add |
Stack
| Layer | Technology |
|---|---|
| Backend | Go 1.24, stdlib net/http, gorilla/websocket, creack/pty |
| Frontend | HTMX 2.0, Alpine.js 3.x, xterm.js |
| Design | Kaze design system — Inter variable font |
| Assets | go:embed — single binary, ~10MB |
| Icons | Lucide v0.469.0 (self-hosted SVG sprite) |
| Metrics | gopsutil v4, docker stats, remote cache (10s) |
Build
make build # current platform
make build-linux # Linux amd64
make build-linux-arm64 # Linux arm64
make build-all # all targets
Binaries are output to bin/.
Development
# Build and install locally
make build
sudo bash install-dev.sh
# Run with live asset reloading
keel -dev
# Run tests (155 unit tests)
go test ./...
# Run with race detection
go test -race ./...
Data Directory
| Platform | Default Path | Override |
|---|---|---|
| Linux | /var/lib/keel/ |
KEEL_DIR or -keel-dir |
| macOS | ~/.keel/ |
KEEL_DIR or -keel-dir |
/var/lib/keel/ # Linux (or ~/.keel/ on macOS)
data/
config.json # global config (network, subnet)
targets.json # Docker targets (local + SSH)
services/
redis.json # one file per container
traefik.json
seeders/
mysql-init.json
config/
traefik/
dynamic.yml # Traefik routing rules (used by "keel hosts")
state/
target # active target name
ghcr-user # GHCR credentials (chmod 600)
ghcr-pat
Star History
License
MIT — see LICENSE.
Explore related projects
awesome-selfhosted/awesome-selfhosted
A list of Free Software network services and web applications which can be hosted on your own servers
335,889 starsimmich-app/immich
High performance self-hosted photo and video management solution.
118,645 starsStirling-Tools/Stirling-PDF
#1 PDF Application on GitHub that lets you edit PDFs on any device anywhere
96,149 starslouislam/uptime-kuma
A fancy self-hosted monitoring tool
93,425 stars