Fleet
Enables management of Docker Compose applications, including container deployment, service control, and log retrieval through the MCP interface.
Manages environment variables and application secrets by importing, exporting, and validating .env files with encrypted storage.
Provides tools for managing local Git workflows, allowing for branch creation, staging, and committing of changes directly within managed application directories.
Facilitates GitHub repository management including onboarding, branch protection rules, and pull request workflows using the GitHub CLI.
Offers specific Nginx configuration templates optimized for Next.js deployments, handling proxying and static asset serving.
Automates the generation and management of Nginx server blocks, supporting reverse proxies, SPAs, and specialized configurations for modern web frameworks.
Integrates with Telegram for remote server management via a specialized bot and provides automated health monitoring alerts.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Fleetshow the status and health of all my services"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
fleet
Docker production management CLI + MCP server
Manage Docker Compose apps on a single server -- systemd orchestration, nginx routing, age-encrypted secrets, health monitoring, dependency tracking, Git workflows, and an MCP server for AI-assisted operations.
Documentation -- npm -- GitHub
Architecture
graph TD
CLI["fleet CLI"]
TUI["TUI Dashboard"]
MCP["MCP Server"]
BOT["fleet-bot (Go)"]
CLI --> Core
TUI --> Core
MCP --> Core
BOT -->|"via MCP"| Core
subgraph Core["Core Modules"]
Registry["Registry"]
Docker["Docker Compose"]
Systemd["systemd"]
Nginx["nginx"]
Secrets["Secrets Vault"]
Health["Health Checks"]
Git["Git / GitHub"]
Deps["Dependency Monitor"]
end
Docker --> Containers["Containers"]
Systemd --> Services["systemd Services"]
Nginx --> Proxy["Reverse Proxy"]
Secrets --> Vault["vault/*.age"]
Secrets --> Runtime["/run/fleet-secrets"]
Health --> Alerts["Telegram / iMessage"]Each Docker Compose app is registered with its compose path, domains, port, and container names. Fleet generates systemd units so apps start on boot in the correct order. Secrets are encrypted at rest with age and decrypted to a tmpfs on boot.
Install
npm install -g @matthesketh/fleetRequires Node.js 20+, Docker Compose v2, systemd, nginx, and age. See the full setup guide for details.
Key Features
Deploy and manage apps -- fleet deploy <app-dir> registers, builds, and starts an app in one command. Control services with start, stop, restart, and logs.
Encrypted secrets -- age-encrypted vault with automatic backups, pre-seal validation, drift detection, and atomic rollback. Decrypted to tmpfs at boot -- secrets never touch disk.
Nginx routing -- Generate proxy, SPA, or Next.js server blocks with fleet nginx add. Automatic config testing and reload.
Health monitoring -- Three-layer checks (systemd + container + HTTP) with fleet health. The watchdog command runs on cron and sends alerts on failure.
Dependency scanning -- Detects outdated packages, CVEs (via OSV), Docker image updates, and runtime EOL across all registered apps.
Git workflows -- Onboard apps to GitHub, manage branches, PRs, and releases from the CLI.
Interactive dashboard -- Run bare fleet to launch a full-screen TUI with real-time status.
See the CLI reference for the complete command list.
Secrets Flow
graph LR
Import["fleet secrets import"]
Set["fleet secrets set"]
Import --> Encrypt["age encrypt"]
Set --> Encrypt
Encrypt --> Vault["vault/*.age"]
Vault -->|"boot / fleet secrets unseal"| Decrypt["age decrypt"]
Decrypt --> Runtime["/run/fleet-secrets (tmpfs)"]
Runtime -->|"env_file / secrets"| Containers["Docker Containers"]
Runtime -->|"fleet secrets seal"| Encrypt
Vault -.->|"drift detection"| RuntimeSecrets are imported or set individually, encrypted with age, and stored in the vault. On boot (or manually), they are decrypted to a tmpfs mount that Docker containers reference. Sealing writes runtime changes back to the vault. Drift detection compares vault vs runtime to catch unsaved changes.
Per-secret rotation (v1.6)
Each secret carries metadata (lastRotated, provider, strategy) so fleet knows when it's stale and how to safely rotate it.
fleet secrets ages [<app>] # what's stale, who owns it, when last rotated
fleet secrets ages --motd # MOTD-formatted summary
fleet secrets motd-init # install /etc/update-motd.d/99-fleet-secrets
fleet secrets rotate <app> [<KEY>] # interactive walkthrough, [--dry-run] [--no-restart]
fleet secrets rollback <app> # restore latest snapshot, [--to <ts>]
fleet secrets snapshots <app> # list available snapshots
fleet secrets rotate-key # legacy: rotate the AGE master keyRotation strategies (auto-detected from secret name, see src/core/secrets-providers.ts):
Strategy | Examples | Behaviour |
|
| Replace value, old dies |
|
| New becomes primary, so existing user sessions stay valid through grace period (your app must read both for verification) |
|
| Refused unless |
|
| Refused — rotate per-user inside your app |
Safety rails on every rotation:
Pre-rotation snapshot to
vault/.snapshots/<app>-<ts>.env.age(atomic copy+rename)Hidden input prompt; new value never echoed in full (only
prefix…suffix (N chars)for confirmation)Format validation against provider regex (catches paste typos)
Entropy check rejects placeholders (
changeme,password, all-same-char, < 8 chars)Auto-rollback on any failure during reseal
Restart + 5s healthcheck gate after re-unseal; manual
fleet rollbackalways availableAppend-only audit log at
~/.local/share/fleet/audit.jsonl(mode 0600, never logs values)
Log lifecycle (v1.6)
fleet logs setup <app> # interactive: retention/size/level
fleet logs setup --all # bulk default (7d / 100MB / info)
fleet logs status [<app>] # per-container size, driver, policy applied
fleet logs prune <app> # vacuum journald + truncate runaway json-file logs
fleet logs <app> --since 30m --grep err --level warn # filtered tailfleet logs setup writes <composePath>/.fleet/logging.override.yml with json-file driver options for rotation. To activate, include the override in your compose start command (or fleet's systemd unit).
MCP tools — all token-conservative with small defaults and truncated flags:
fleet_logs_recent(app, lines=50, level=warn, sinceMinutes=15)— bounded tailfleet_logs_summary(app, sinceMinutes=60)— counts + top 10 distinct error messagesfleet_logs_search(app, query, sinceMinutes=60, maxResults=20)— bounded grepfleet_logs_status(app?)— driver + size per containerfleet_egress_snapshot(app)— outbound destinations + violations
Egress observation (v1.6)
fleet egress observe <app> # snapshot current outbound flows via nsenter+ss
fleet egress show <app> # show config + allowlist
fleet egress allow <app> <host> # add to allowlist (supports *.host wildcards)v1 is observe-only — it never blocks packets, so zero risk of breaking apps. Reads each container's network namespace via nsenter so it sees real container egress (not just host-side NAT'd flows). Reverse-resolves remote IPs to hostnames best-effort. RFC1918 destinations don't count as violations.
enforce mode (actual default-deny via nftables) is deferred to a future phase — by design, it requires the operator to explicitly promote a shadow-clean app, never auto-promotes.
Deployment Flow
graph TD
Deploy["fleet deploy app-dir"]
Deploy --> Register{"Already\nregistered?"}
Register -->|No| Add["Register app"]
Register -->|Yes| Build
Add --> Build["docker compose build"]
Build --> Start{"Service\nrunning?"}
Start -->|No| StartSvc["systemctl start"]
Start -->|Yes| Restart["systemctl restart"]
StartSvc --> Healthy["App deployed"]
Restart --> HealthyBoot Refresh
On every systemd start — including reboots — Fleet pulls the latest code from GitHub and rebuilds the image if needed, before starting the container. The flow is entirely fail-safe: any failure at any step (dirty working tree, no remote, fetch error, non-fast-forward merge, build failure, or a 900-second wall-clock timeout) is logged and falls through to a plain docker compose up with the existing image. The container will always start.
New commands
Command | Description |
| Entry point systemd now invokes ( |
| Re-tags |
| Rewrites |
| Restores all |
Kill switch
To disable boot refresh entirely — next systemctl start goes straight to docker compose up:
sudo touch /etc/fleet/no-auto-refreshRemove the file to re-enable.
Registry field: lastBuiltCommit
Each app in the registry stores the Git commit that was last built. Fleet sets this on fleet deploy and on every successful boot-refresh build. Boot refresh skips docker compose build when HEAD already matches this value, keeping boots fast when no code has changed.
First boot after upgrade
Any app with lastBuiltCommit unset will trigger a full rebuild the first time it boots after upgrading to this version. Expect a longer first boot for those apps.
Recovery escape hatches
Situation | Action |
One app misbehaving after a build |
|
Registry corrupted | Auto-loads |
Broad issue with boot-start behaviour |
|
Worst case — revert all unit files |
|
MCP Server
Fleet exposes 36 tools via the Model Context Protocol for AI-assisted server management. Run fleet mcp to start the stdio server, or install it into Claude Code:
sudo fleet install-mcpTools cover the full surface area: app lifecycle, secrets, nginx, Git, health checks, and dependency monitoring. See the MCP documentation for the complete tool list.
fleet-bot
A Go companion bot (bot/) that provides remote server management through Telegram or iMessage. It runs Claude Code sessions with access to fleet's MCP tools for hands-free operations.
See the bot documentation for setup instructions.
Self-update
When fleet's TUI launches it does a non-blocking git fetch against origin/develop. If the local repo is behind, a banner appears under the header:
↑ Update available: 3 commits ahead — feat: ... Press U to install.Pressing U runs git pull --ff-only then npm run build (refused if the working tree is dirty). The new binary is live for the next fleet … invocation. Recheck happens every 30 minutes for long-running TUI sessions.
Testing
npm test # unit + mocked tests (1106 passing)
FLEET_INTEGRATION=1 npm test # also runs boot-refresh integration tests (1156 passing, 0 skipped)Set FLEET_INTEGRATION=1 to opt into integration tests that hit real systemd / docker. Skipped by default in CI.
Development
git clone https://github.com/wrxck/fleet.git
cd fleet
npm install
npm test # vitest
npm run build # compile TypeScript to dist/
npm run dev # run with tsx (no build needed)License
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/wrxck/fleet'
If you have feedback or need assistance with the MCP directory API, please join our Discord server