Helm for home.
You're the captain of your homelab. 40 containers. Traefik. Secrets everywhere. You shouldn't have to swab the deck yourself. That's what the bosun is for.
git push -> bosun receives orders -> crew deployed -> yacht runs smooth
No Kubernetes. No drama. Just smooth sailing.
+------------------------------------------------------------------------------+
| Your Yacht (Server) |
| |
| +------------------------------------------------------------------------+ |
| | Bosun | |
| | +---------+ +---------+ +---------+ +---------+ +---------+ | |
| | | Radio |->| Fetch |->| Decrypt |->| Prep |->| Deploy | | |
| | |(Webhook)| | Orders | | Secrets | | Configs | | Crew | | |
| | +---------+ +---------+ +---------+ +---------+ +---------+ | |
| +------------------------------------------------------------------------+ |
| ^ | |
| | v |
| +-----+-----+ +--------------+ |
| | Tailscale | | Your Crew | |
| | Funnel | | (Containers) | |
| +-----+-----+ +--------------+ |
+--------|---------------------------------------------------------------------+
|
v
+----------+
| Captain |
| (GitHub) |
+----------+
curl -fsSL https://raw.githubusercontent.com/cameronsjo/bosun/main/scripts/install.sh | bashThis downloads the latest release, verifies the SHA256 checksum, and installs to /usr/local/bin.
# Go install
go install github.com/cameronsjo/bosun/cmd/bosun@latest
# From source
git clone https://github.com/cameronsjo/bosun.git
cd bosun && make build
./build/bosun --versionbosun update # Download and install latest
bosun update --check # Check for updates without installingReleases are signed with cosign and include SLSA provenance.
# Verify checksum signature
cosign verify-blob --certificate checksums.txt.pem \
--signature checksums.txt.sig checksums.txt
# Verify build provenance
gh attestation verify bosun_*.tar.gz --owner cameronsjo# 1. Generate encryption key
age-keygen -o ~/.config/sops/age/keys.txt
# 2. Create .sops.yaml with your public key
cat > .sops.yaml << 'EOF'
creation_rules:
- path_regex: .*\.yaml$
age: <your-public-key>
EOF
# 3. Initialize your yacht
bosun init
# 4. Check if everything is seaworthy
bosun doctor
# 5. Start the yacht
bosun yacht upRun bosun as a long-running daemon for production GitOps:
# Generate systemd unit files
bosun init --systemd
# Install and start
cd systemd && sudo ./install.sh
# Or run directly
bosun daemonThe daemon provides:
- Unix socket API - Primary interface at
/var/run/bosun.sock - Multi-provider webhooks - GitHub, GitLab, Gitea, Bitbucket
- Polling - Configurable interval reconciliation
- Health endpoints -
/health,/readyfor orchestrators
bosun daemon # Run the daemon
bosun trigger # Trigger reconciliation
bosun daemon-status # Show daemon health
bosun validate # Validate configuration
bosun webhook # Run standalone webhook receiver| Variable | Description | Default |
|---|---|---|
BOSUN_REPO_URL |
Git repository URL | Required |
BOSUN_REPO_BRANCH |
Branch to track | main |
BOSUN_POLL_INTERVAL |
Poll interval in seconds | 3600 |
BOSUN_SOCKET_PATH |
Unix socket path | /var/run/bosun.sock |
WEBHOOK_SECRET |
Webhook signature validation | Optional |
See docs/architecture/daemon-split.md for the full daemon architecture.
| Command | Description |
|---|---|
init |
Interactive setup wizard (--systemd for unit files) |
doctor |
Pre-flight checks |
validate |
Validate config and daemon connectivity |
status |
Health dashboard |
| Command | Description |
|---|---|
daemon |
Run the GitOps daemon |
trigger |
Trigger reconciliation via daemon |
daemon-status |
Show daemon health and state |
webhook |
Run standalone webhook receiver |
| Command | Description |
|---|---|
yacht up/down/restart/status |
Manage Docker Compose services |
crew list/logs/inspect/restart |
Manage individual containers |
| Command | Description |
|---|---|
provision [stack] |
Render manifest to compose/traefik/gatus |
provisions |
List available provisions |
create <template> <name> |
Scaffold new service |
lint |
Validate manifests |
drift |
Detect config drift |
| Command | Description |
|---|---|
reconcile |
Run GitOps workflow (one-shot) |
radio test/status |
Test webhook and Tailscale |
mayday |
Show errors, rollback snapshots |
See docs/commands.md for the full command reference.
Bosun looks for configuration in the following locations:
bosun.yamlin the current directory.bosun.yamlin the current directory$HOME/.config/bosun/config.yaml
Example configuration:
# bosun.yaml
root: .
manifest_dir: manifest
compose_file: docker-compose.yml| Variable | Description | Default |
|---|---|---|
REPO_URL |
Git repository URL (for reconcile) | Required for reconcile |
REPO_BRANCH |
Git branch to track | main |
SOPS_AGE_KEY_FILE |
Path to age key file | ~/.config/sops/age/keys.txt |
DEPLOY_TARGET |
Remote host for deployment | Local if unset |
| Component | Role |
|---|---|
| Bosun CLI | Single binary managing Docker, manifests, and GitOps |
| Manifest System | Write 10 lines, generate compose + Traefik + Gatus configs |
| Provisions | Reusable config templates - batteries included, all swappable |
- Commands Reference - Full command documentation
- Daemon Architecture - Unix socket API, webhooks, security
- Alerting Configuration - Discord, SendGrid, Twilio notifications
- GitOps Workflow - Reconciliation, polling, triggers
- Migration Guide - Migrating from bash/Python version
- Concepts - Architecture, components, diagrams
| ADR | Status | Summary |
|---|---|---|
| Daemon Architecture | Accepted | Unix socket API, multi-provider webhooks |
| Council Review | Approved | Security-first daemon design (9/10) |
| 0001: Manifest System | Accepted | DRY crew provisioning |
| 0008: Container vs Daemon | Accepted | When to use systemd |
| 0010: Go Rewrite | Accepted | Single-binary CLI |
- Go 1.24+ (for building from source)
- Docker + Docker Compose v2
- Linux or macOS (tested: Unraid, Debian, Ubuntu, macOS)
- Git (for reconcile workflow)
- SOPS + Age (for secret encryption)
# Build
make build
# Run tests
make test
# Run with coverage
make test-cover
# Build for all platforms
make build-all
# Development build (no optimizations)
make devRun the same CI pipeline locally that runs in GitHub Actions:
# Full CI pipeline (test + lint + build)
make ci
# Individual stages
make dagger-test # Run tests in container
make dagger-lint # Run linter in container
make dagger-build # Build all platforms in container
make dagger-release-dry-run # Test goreleaser
# Or use dagger directly
dagger call ci --source .
dagger call test --source .
dagger call lint --source .See docs/ci.md for the full CI pipeline documentation.
MIT