Latest commit

History

1,990 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DiscordVersionLicense



Build, deploy, and manage containerised applications with a single config file.


Deploying Directus (Node + Postgres) to an existing server with Stacker

Real deploys, one command each. See stacker-project-examples.

More demos — n8n · Gotify

n8n (workflow automation, Node + Postgres)

Deploying n8n with Stacker

Gotify (push-notification server, single container)

Deploying Gotify with Stacker

Stacker is a platform for turning any project into a deployable Docker stack. Add a stacker.yml to your repo, and Stacker generates Dockerfiles, docker-compose definitions, reverse-proxy configs, and deploys locally or to cloud providers — optionally with AI assistance.

v0.3.0 highlights: generate stacker.yml from any GitHub repo with stacker init --from-github, infra-service healthcheck inference, remote Vault-backed secrets for deployable service/app targets, paused or failed cloud/server installs retain discovered IP addresses, and cloud-provider firewalls can be managed without SSH.

Quick Start

Install the CLI

curl -fsSL https://raw.githubusercontent.com/trydirect/stacker/main/install.sh | bash

Create & deploy a project

cd my-project
stacker init # auto-detects project type, generates stacker.yml
stacker deploy # builds and runs locally via docker compose
stacker status # check running containers

Deploy from any GitHub repo

Generate a stacker.yml from a GitHub repository — no clone required. For the best results (port mappings, env vars, service context inferred from README and source), use --with-ai:

# AI-powered (recommended — reads README, compose, source files)
stacker init --from-github owner/repo --with-ai
# Template-based (project type + Dockerfile detection only)
stacker init -g https://github.com/ArchiveBox/ArchiveBox

With --with-ai, Stacker shallow-clones the repo, then uses an LLM (Ollama by default) to scan project files and generate a context-aware stacker.yml with services, ports, env vars, and healthchecks. Falls back to template detection if the AI provider is unreachable.

When environment variables are in the compose file, .env.example and scripts/generate-secrets.sh are also generated.

AI-powered init (optional)

Stacker can scan your project files and use an LLM to generate a tailored stacker.yml:

# Local AI with Ollama (free, private, default)
stacker init --with-ai
# OpenAI
stacker init --with-ai --ai-provider openai --ai-api-key sk-...
# Anthropic (key from env)export ANTHROPIC_API_KEY=sk-ant-...
stacker init --with-ai --ai-provider anthropic

If the AI provider is unreachable, Stacker falls back to template-based generation automatically.

When the project looks like a simple HTML or Next.js website and the configured Ollama model is qwen2.5-code or qwen2.5-coder, stacker init --with-ai can also bootstrap a website deployment scenario. The bootstrap seeds values from the generated stacker.yml, asks only for the missing deploy inputs, and saves scenario state under .stacker/scenarios/qwen2.5-code/website-deploy/ for later continuation with stacker ai.

AI deployment workflows

For the canonical AI/MCP deployment flow — inspect state, explain topology or env provenance, preview a plan, apply it safely, and recover with events or rollback — see AI deployment workflows.

For the qwen-specific website scenario flow, including --scenario and --step continuation, see the same guide.


stacker.yml example

name: my-appapp:
type: nodepath: ./srcports:
- "8080:3000"environment:
NODE_ENV: productionservices:
- name: postgresimage: postgres:16environment:
POSTGRES_DB: myappPOSTGRES_PASSWORD: ${DB_PASSWORD}proxy:
type: nginxauto_detect: truedomains:
- domain: app.example.comssl: autoupstream: app:3000deploy:
target: local # or: cloud, serverai:
enabled: trueprovider: ollamamodel: llama3monitoring:
status_panel: truehealthcheck:
endpoint: /healthinterval: 30salerts: # container-down alarm for `stacker monitor` (0.3.2)interval: 30target:
terminal: true # or: { url: "https://ntfy.example.com/alerts" }

Full schema reference: docs/STACKER_YML_REFERENCE.md


Three components

ComponentWhat it doesBinary
Stacker CLIDeveloper tool — init, deploy, monitor from the terminalstacker-cli
Stacker ServerREST API + Stack Builder UI + deployment orchestration + MCP Serverserver
Status Panel AgentDeployed alongside your app on the target server — executes commands, streams logs, reports health(separate repo)
┌──────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ Stacker CLI │────────►│ Stacker Server │────────►│ Status Panel Agent │
│ │ REST │ │ queue │ (on target server) │
│ stacker.yml │ API │ Stack Builder UI│ pull │ │
│ init/deploy │ │ 85+ MCP tools │◄────────│ health / logs / │
│ status/logs │ │ Vault · AMQP │ HMAC │ restart / exec / │
└──────────────┘ └──────────────────┘ │ deploy_app / proxy │
│ └─────────────────────┘
▼
Terraform + Ansible ──► Cloud
(Hetzner, DO, AWS, Linode)

1. Stacker CLI

The end-user tool. No server required for local deploys.

Commands

CommandDescription
stacker initDetect project type, generate stacker.yml + .stacker/ artifacts
stacker deployBuild & deploy the stack (local, cloud, or server). Cloud deploys also install a local SSH backup key when possible. --runtime kata|runc selects container runtime
stacker statusShow running containers and health
stacker logsView container logs (--follow, --service, --tail)
stacker deployment state / stacker deployment statusShow canonical deployment state (defaults to latest; --pinned uses stacker.yml hash)
stacker deployment eventsShow structured deployment events (--pinned uses stacker.yml hash)
stacker deployment rollbackPreview or apply a deployment rollback
stacker secretsManage local .env secrets or remote Vault-backed service / server secrets
stacker list deployments / stacker deployments / stacker psList deployments on the Stacker server
stacker list servers / stacker serversList saved servers
stacker list clouds / stacker clouds / stacker keys / stacker cloud keysList saved cloud credentials
stacker list ssh-keys / stacker ssh-keysList per-server SSH key status
stacker destroyTear down the deployed stack
stacker config validateValidate stacker.yml syntax
stacker config showShow resolved configuration
stacker config examplePrint a full commented reference
stacker config setup cloudGuided cloud deployment setup
stacker config setup aiConfigure AI provider, endpoint, model, and tasks
stacker ai ask "question"Ask the AI about your stack
stacker proxy addAdd a reverse-proxy domain entry
stacker proxy detectAuto-detect existing reverse-proxy containers
stacker cloud firewall addOpen cloud-provider firewall ports without SSH, for example --public-ports 8000/tcp on Hetzner
stacker cloud firewall removeRemove Stacker-managed cloud-provider firewall rules
stacker cloud firewall listList cloud-provider firewall rules for a server
stacker ssh-key generateGenerate a new SSH key pair for a server (Vault-backed)
stacker ssh-key showDisplay the public SSH key for a server
stacker ssh-key uploadUpload an existing SSH key pair for a server
stacker ssh-key injectRepair Vault-key trust by using an already-working private key to update authorized_keys
stacker service addAdd a service from the template catalog to stacker.yml
stacker service listList available service templates (20+ built-in)
stacker agent healthCheck Status Panel agent connectivity and health
stacker agent statusDisplay agent snapshot — containers, versions, uptime
stacker agent list apps / stacker agent appsList apps for the target deployment
stacker agent list containers / stacker agent containersList containers on the target server
stacker agent logs <app>Retrieve container logs from the remote agent
stacker agent restart <app>Restart a container via the agent
stacker agent deploy-appDeploy or update an app container on the target server. --runtime kata|runc selects container runtime; --env <name> selects the deploy environment/profile
stacker agent remove-appRemove an app container (with optional volume/image cleanup)
stacker agent configure-proxyConfigure Nginx Proxy Manager via the agent; use --no-ssl for plain HTTP hosts (credentials are resolved from Vault and are auto-seeded for managed Status Panel + NPM deploys)
stacker agent configure-firewallConfigure guest OS firewall rules via the Status Panel agent; use stacker cloud firewall for provider firewalls
stacker agent historyShow recent command execution history
stacker agent execExecute a raw agent command with JSON parameters
stacker pipe scanDiscover local endpoints/resources from running containers (when target is local)
stacker pipe scan --containers [filter]Discover local endpoints/resources for matching containers
stacker pipe scan --app <app>Probe a remote app for API endpoints
stacker pipe create <src> <tgt>Create a data pipe between two containers (interactive; or non-interactive with --source-endpoint/--target-endpoint/--name — added in 0.3.2). --retry/--on-failure/--on-success attach a retry policy + lifecycle handlers
stacker pipe diffCompare the declared pipes: block against deployed pipes (added in 0.3.2)
stacker pipe applyReconcile declared pipes into the deployment; --prune removes orphans, --dry-run previews (added in 0.3.2)
stacker pipe listList pipe instances for the current deployment
stacker pipe activate <id>Activate a pipe (start listening for triggers)
stacker pipe deactivate <id>Pause an active pipe
stacker pipe trigger <id>One-shot pipe execution with optional input data
stacker pipe deploy <id>Promote a local pipe to a remote deployment
stacker pipe history <id>View execution history for a pipe
stacker pipe replay <exec-id>Re-run a previous pipe execution
stacker monitorWatch container health and alert on problems (added in 0.3.2); --once for a single check (cron-friendly). Configure via monitoring.alerts in stacker.yml
stacker target [local|cloud|server]Switch deployment target mode
stacker env [local|dev|prod]Show or persist the active deploy environment/profile used by app-only updates
stacker whoamiShow the active login, subscription plan, and current project deployment context
stacker submitPackage current stack and submit to marketplace for review
stacker marketplace statusCheck submission status for your marketplace templates
stacker marketplace logs <name>Show review comments and history for a submission
stacker loginAuthenticate with the TryDirect platform
stacker updateCheck for updates and self-update

Deploy targets

stacker deploy --target local# docker compose up (default)
stacker deploy --target cloud # Terraform + Ansible → cloud provider
stacker deploy --target server # deploy to existing server via SSH
stacker deploy --dry-run # preview generated files without executing

After a successful cloud deploy, Stacker creates or reuses a local backup key at ~/.config/stacker/ssh/server-<id>_ed25519 (or under $XDG_CONFIG_HOME) and authorizes its public key on the server when possible. The CLI prints a normal ssh -i ... command, while the Vault private key remains server-side.

When a cloud/server deploy includes deploy.registry credentials (or the equivalent STACKER_DOCKER_* environment variables), Stacker stores that registry auth securely and reuses it for later Status-managed image refreshes such as stacker agent deploy-app. This keeps private-image redeploys working without depending on host-level docker login state or mounting /root/.docker into the agent container.

Secrets workflow

# Local project .env secret
stacker secrets set DB_PASSWORD=supersecret
# Discover valid remote deployable service/app targets first
stacker secrets apps
# Remote service secret used at render/deploy time for one target
stacker secrets set S3_SECRET_KEY \
--scope service \
--service uploader \
--body supersecret
# Remote server secret for future host-level consumers
stacker secrets set NPM_TOKEN \
--scope server \
--server-id 42 \
--body-file .npm-token
# Remote reads are metadata-only in v1
stacker secrets list --scope service --service uploader --json
stacker secrets get S3_SECRET_KEY --scope service --service uploader --json
# Push stored remote secrets into the target's runtime env
stacker secrets push --service uploader
stacker secrets push --service uploader --env prod
# Aliases: stacker secrets deploy --service uploader# stacker secrets apply --service uploader
  • Local mode remains the default and reads/writes the project .env file.
  • Remote mode is enabled only with --scope service or --scope server.
  • Service-scoped remote commands default --project from stacker.yml -> project.identity; --project still overrides it explicitly.
  • Service-scoped secrets target deployable service/app codes listed by stacker secrets apps, including registered stacker.yml services and supported image-backed Compose services after a deploy/update sync.
  • Service-scoped secrets are merged only into the matching rendered service/app env at deploy time.
  • stacker secrets push --service <target> applies stored service secrets to the remote runtime env without changing secret values. Use --env <name> for a one-off environment selection, or stacker env <name> to persist the active environment/profile for future app-only updates. Use --force only when the remote env drift check reports an out-of-band change.
  • Remote get and list do not return plaintext values in v1.
  • MCP env inspection now exposes explicit secure metadata for Vault-backed variables: get_app_env_vars keeps the redacted environment_variables object for compatibility and also returns environment_entries[] with secure, redacted, and source fields.

Remote deploys render runtime env into one canonical host file: /home/trydirect/project/.env. Generated compose uses env_file: .env, so the path is relative to the deployed compose file. To inspect paths and contributing layers without exposing values, run:

stacker config show --resolved

For app-only updates, stacker agent deploy-app <target> resolves the deploy environment from --env, then .stacker/active-env, then stacker.yml. If <target>/docker/<env>/compose.yml exists, Stacker uses the app-local service definition for that target but merges it into the full project-level compose file before sending it to the agent. This prevents app-only updates from replacing the remote stack compose with a single-service compose file. Any app-local .env referenced by that compose file is uploaded in the config bundle, and Stacker appends the Vault-rendered service secrets for the same target to that file before the agent writes it on the server. Repeated app-only updates replace the prior # stacker-render ... block in that file instead of stacking duplicate rendered secret sections.

Marketplace workflow (for stack developers)

stacker deploy --target local# 1. test locally
stacker deploy --target server # 2. test on remote server
stacker submit # 3. submit for marketplace review
stacker marketplace status # 4. check review status# Stack is auto-published once approved by the review team

Marketplace install (for buyers)

# Option A: Deploy from your laptop to a remote server
stacker deploy my-stack --target server --host 1.2.3.4
# Option B: Run directly on the target server (one-liner)
curl -sL https://marketplace.try.direct/<purchase-token>/install.sh | sh

Key features

  • Auto-detection — identifies Node, Python, Rust, Go, PHP, static sites from project files
  • Dockerfile generation — produces optimised multi-stage Dockerfiles per app type
  • Docker Compose generation — wires app + services + proxy + monitoring
  • Remote service secrets — Vault-backed service/app target secrets are metadata-only when read and isolated to the selected service
  • AI-assisted config — scans project, calls LLM to generate tailored stacker.yml
  • AI troubleshooting — on deploy failure, suggests fixes via AI or deterministic fallback hints
  • Service catalog — 20+ built-in service templates (Postgres, Redis, WordPress, etc.) — add with stacker service add
  • AI service addition — ask stacker ai ask --write "add wordpress" and the AI uses the template catalog
  • Agent controlstacker agent subcommand to manage remote Status Panel agents (health, logs, restart, deploy, proxy) with --json output
  • SSH key management — generate, view, upload, and repair server SSH keys (Vault-backed), with automatic local backup SSH access after cloud deploy
  • Reverse proxy — Traefik (labels), Caddy (Caddyfile), and Nginx Proxy Manager, platform-managed and driven by proxy.domains end-to-end (0.3.2)
  • Container-health alarmstacker monitor watches container health and alerts on problems (terminal, webhook, or pipe), configured via monitoring.alerts (0.3.2)
  • Declarative pipes (IaC) — declare pipes in stacker.yml and reconcile with stacker pipe diff / pipe apply [--prune] (0.3.2)
  • Cloud deployment — Hetzner, DigitalOcean, AWS, Linode, with provider firewall operations and paused/failed install IP retention
  • MCP Server — 85+ tools, including deployment, agent control, config, proxy, firewall, and remote service secret management
  • Marketplace — submit stacks for review, auto-publish on approval, check status from CLI
  • Buyer install — purchase tokens, one-liner install scripts, agent self-registration

2. Stacker Server

The backend platform powering the Stack Builder UI, REST API, deployment orchestration, and MCP server for AI agents.

Setup

cp configuration.yaml.dist configuration.yaml # edit database, vault, AMQP settings
cp access_control.conf.dist access_control.conf
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/stacker
sqlx migrate run
cargo run --bin server # http://127.0.0.1:8000

Key API endpoints

EndpointDescription
POST /projectCreate a project from a stack definition
POST /{id}/deploy/{cloud_id}Deploy to a cloud provider
GET /project/{id}/appsList apps in a project
DELETE /project/{id}/apps/{code}Remove an app from a project
PUT /project/{id}/apps/{code}/envUpdate app environment variables
GET /project/{id}/apps/{code}/secretsList service-scoped secret metadata for an app
PUT /project/{id}/apps/{code}/secrets/{name}Create or update a Vault-backed service secret
PUT /project/{id}/apps/{code}/portsUpdate port mappings
PUT /project/{id}/apps/{code}/domainUpdate domain / SSL settings
GET /server/{id}/secretsList server-scoped secret metadata
PUT /server/{id}/secrets/{name}Create or update a Vault-backed server secret
POST /api/v1/commandsEnqueue a command for the Status Panel agent
POST /api/templatesCreate or update a marketplace template (creator)
POST /api/templates/{id}/submitSubmit template for marketplace review
GET /api/templates/mineList current user's template submissions
GET /api/v1/marketplace/install/{token}Generate install.sh script for buyers
GET /api/v1/marketplace/download/{token}Download stack archive (purchase token validated)
POST /api/v1/marketplace/agents/registerAgent self-registration after install
POST /api/v1/pipes/templatesCreate a reusable pipe template (source→target mapping)
GET /api/v1/pipes/templatesList pipe templates (with optional filters)
POST /api/v1/pipes/instancesCreate a pipe instance for a deployment
GET /api/v1/pipes/instancesList pipe instances by deployment hash
PUT /api/v1/pipes/instances/{id}/statusUpdate pipe instance status (active/paused)

MCP Server

Stacker exposes 52+ Model Context Protocol tools over WebSocket, enabling AI agents (Claude, GPT, etc.) to manage infrastructure programmatically:

  • Project & deployment management
  • Container operations (start, stop, restart, exec)
  • Log analysis & error summaries
  • Vault config read/write
  • Proxy configuration
  • App environment & port management
  • Server resource monitoring
  • Docker Compose generation & preview
  • Agent control (deploy app, remove app, configure proxy, get status)
  • Firewall management (iptables rules via Status Panel or SSH)

Key integrations

  • HashiCorp Vault — secrets and config storage, synced to deployments
  • RabbitMQ — deployment status updates, event-driven orchestration
  • TryDirect User Service — OAuth, marketplace templates, payment validation
  • Marketplace — publish and deploy community stacks

3. Status Panel Agent

A lightweight agent deployed alongside your application on the target server. It runs as a Docker container and communicates with Stacker Server using a pull-only architecture — the agent polls for commands, Stacker never dials out.

How it works

1. UI/API creates a command → POST /api/v1/commands
2. Command stored in DB queue → commands + command_queue tables
3. Agent polls for work → GET /api/v1/agent/commands/wait/{hash}
4. Agent executes locally → Docker API on the host
5. Agent reports result → POST /api/v1/agent/commands/report

All agent requests are HMAC-signed (X-Agent-Signature header) using a token stored in Vault.

Supported commands

CommandDescription
healthCheck container health status (single or all)
logsFetch container logs (stdout/stderr, with limits)
restartRestart a container
deploy_appDeploy or update an app container
remove_appRemove an app container
configure_proxyCreate/update/delete reverse-proxy entries
configure_firewallConfigure iptables firewall rules (add/remove/list/flush)
stacker.execExecute a command inside a running container (with security blocklist)
stacker.server_resourcesCollect server resource metrics (CPU, memory, disk, network)
apply_configPull config from Vault and apply to a running container
probe_endpointsDiscover API endpoints on containers (OpenAPI, REST, HTML forms, GraphQL)
activate_pipeActivate a pipe instance — start polling/webhook triggers
deactivate_pipeDeactivate a running pipe instance
trigger_pipeOne-shot pipe execution: fetch source data → map fields → post to target

Agent registration

# Agent self-registers on first boot (no auth required)
POST /api/v1/agent/register
{ "deployment_hash": "abc123", "capabilities": [...], "system_info": {...} }
→ { "agent_id": "...", "agent_token": "..." }

Token rotation

cargo run --bin console -- Agent rotate-token \
--deployment-hash <hash> \
--new-token <NEW_TOKEN>

Database migrations

sqlx migrate run # apply
sqlx migrate revert # rollback

Testing

cargo test# all tests (772+ unit, 69 security integration)
cargo test user_service_client # User Service connector
cargo test marketplace_webhook # Marketplace webhook flows
cargo test deployment_validator # Deployment validation
cargo test --test security_cli # CLI endpoint IDOR security tests
SQLX_OFFLINE=true cargo test --lib -- proxy_domains 2>&1| tail -10

Kata Containers (Hardware Isolation)

Stacker supports Kata Containers as an alternative runtime, providing VM-level isolation for each container using hardware virtualization (KVM).

KVM requirement — Kata needs nested or bare-metal KVM. Hetzner dedicated-CPU servers (CCX line) expose /dev/kvm out of the box, making them an ideal deployment target.

stacker deploy --runtime kata # deploy the current stack with Kata isolation
stacker agent deploy-app --runtime kata # deploy a single app container with Kata

See docs/kata/ for the full setup guide, network constraints, and monitoring reference. Automated provisioning (Ansible + Terraform for Hetzner CCX) is available via the TFA infrastructure toolkit.


Documentation


License

MIT

About

Orchestrate dockerized apps from cli, control, monitor, install apps on own servers and in the cloud

Topics

Resources

Security policy

Stars

6 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

1,990 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DiscordVersionLicense



Build, deploy, and manage containerised applications with a single config file.


Deploying Directus (Node + Postgres) to an existing server with Stacker

Real deploys, one command each. See stacker-project-examples.

More demos — n8n · Gotify

n8n (workflow automation, Node + Postgres)

Deploying n8n with Stacker

Gotify (push-notification server, single container)

Deploying Gotify with Stacker

Stacker is a platform for turning any project into a deployable Docker stack. Add a stacker.yml to your repo, and Stacker generates Dockerfiles, docker-compose definitions, reverse-proxy configs, and deploys locally or to cloud providers — optionally with AI assistance.

v0.3.0 highlights: generate stacker.yml from any GitHub repo with stacker init --from-github, infra-service healthcheck inference, remote Vault-backed secrets for deployable service/app targets, paused or failed cloud/server installs retain discovered IP addresses, and cloud-provider firewalls can be managed without SSH.

Quick Start

Install the CLI

curl -fsSL https://raw.githubusercontent.com/trydirect/stacker/main/install.sh | bash

Create & deploy a project

cd my-project
stacker init # auto-detects project type, generates stacker.yml
stacker deploy # builds and runs locally via docker compose
stacker status # check running containers

Deploy from any GitHub repo

Generate a stacker.yml from a GitHub repository — no clone required. For the best results (port mappings, env vars, service context inferred from README and source), use --with-ai:

# AI-powered (recommended — reads README, compose, source files)
stacker init --from-github owner/repo --with-ai
# Template-based (project type + Dockerfile detection only)
stacker init -g https://github.com/ArchiveBox/ArchiveBox

With --with-ai, Stacker shallow-clones the repo, then uses an LLM (Ollama by default) to scan project files and generate a context-aware stacker.yml with services, ports, env vars, and healthchecks. Falls back to template detection if the AI provider is unreachable.

When environment variables are in the compose file, .env.example and scripts/generate-secrets.sh are also generated.

AI-powered init (optional)

Stacker can scan your project files and use an LLM to generate a tailored stacker.yml:

# Local AI with Ollama (free, private, default)
stacker init --with-ai
# OpenAI
stacker init --with-ai --ai-provider openai --ai-api-key sk-...
# Anthropic (key from env)export ANTHROPIC_API_KEY=sk-ant-...
stacker init --with-ai --ai-provider anthropic

If the AI provider is unreachable, Stacker falls back to template-based generation automatically.

When the project looks like a simple HTML or Next.js website and the configured Ollama model is qwen2.5-code or qwen2.5-coder, stacker init --with-ai can also bootstrap a website deployment scenario. The bootstrap seeds values from the generated stacker.yml, asks only for the missing deploy inputs, and saves scenario state under .stacker/scenarios/qwen2.5-code/website-deploy/ for later continuation with stacker ai.

AI deployment workflows

For the canonical AI/MCP deployment flow — inspect state, explain topology or env provenance, preview a plan, apply it safely, and recover with events or rollback — see AI deployment workflows.

For the qwen-specific website scenario flow, including --scenario and --step continuation, see the same guide.


stacker.yml example

name: my-appapp:
type: nodepath: ./srcports:
- "8080:3000"environment:
NODE_ENV: productionservices:
- name: postgresimage: postgres:16environment:
POSTGRES_DB: myappPOSTGRES_PASSWORD: ${DB_PASSWORD}proxy:
type: nginxauto_detect: truedomains:
- domain: app.example.comssl: autoupstream: app:3000deploy:
target: local # or: cloud, serverai:
enabled: trueprovider: ollamamodel: llama3monitoring:
status_panel: truehealthcheck:
endpoint: /healthinterval: 30salerts: # container-down alarm for `stacker monitor` (0.3.2)interval: 30target:
terminal: true # or: { url: "https://ntfy.example.com/alerts" }

Full schema reference: docs/STACKER_YML_REFERENCE.md


Three components

ComponentWhat it doesBinary
Stacker CLIDeveloper tool — init, deploy, monitor from the terminalstacker-cli
Stacker ServerREST API + Stack Builder UI + deployment orchestration + MCP Serverserver
Status Panel AgentDeployed alongside your app on the target server — executes commands, streams logs, reports health(separate repo)
┌──────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ Stacker CLI │────────►│ Stacker Server │────────►│ Status Panel Agent │
│ │ REST │ │ queue │ (on target server) │
│ stacker.yml │ API │ Stack Builder UI│ pull │ │
│ init/deploy │ │ 85+ MCP tools │◄────────│ health / logs / │
│ status/logs │ │ Vault · AMQP │ HMAC │ restart / exec / │
└──────────────┘ └──────────────────┘ │ deploy_app / proxy │
│ └─────────────────────┘
▼
Terraform + Ansible ──► Cloud
(Hetzner, DO, AWS, Linode)

1. Stacker CLI

The end-user tool. No server required for local deploys.

Commands

CommandDescription
stacker initDetect project type, generate stacker.yml + .stacker/ artifacts
stacker deployBuild & deploy the stack (local, cloud, or server). Cloud deploys also install a local SSH backup key when possible. --runtime kata|runc selects container runtime
stacker statusShow running containers and health
stacker logsView container logs (--follow, --service, --tail)
stacker deployment state / stacker deployment statusShow canonical deployment state (defaults to latest; --pinned uses stacker.yml hash)
stacker deployment eventsShow structured deployment events (--pinned uses stacker.yml hash)
stacker deployment rollbackPreview or apply a deployment rollback
stacker secretsManage local .env secrets or remote Vault-backed service / server secrets
stacker list deployments / stacker deployments / stacker psList deployments on the Stacker server
stacker list servers / stacker serversList saved servers
stacker list clouds / stacker clouds / stacker keys / stacker cloud keysList saved cloud credentials
stacker list ssh-keys / stacker ssh-keysList per-server SSH key status
stacker destroyTear down the deployed stack
stacker config validateValidate stacker.yml syntax
stacker config showShow resolved configuration
stacker config examplePrint a full commented reference
stacker config setup cloudGuided cloud deployment setup
stacker config setup aiConfigure AI provider, endpoint, model, and tasks
stacker ai ask "question"Ask the AI about your stack
stacker proxy addAdd a reverse-proxy domain entry
stacker proxy detectAuto-detect existing reverse-proxy containers
stacker cloud firewall addOpen cloud-provider firewall ports without SSH, for example --public-ports 8000/tcp on Hetzner
stacker cloud firewall removeRemove Stacker-managed cloud-provider firewall rules
stacker cloud firewall listList cloud-provider firewall rules for a server
stacker ssh-key generateGenerate a new SSH key pair for a server (Vault-backed)
stacker ssh-key showDisplay the public SSH key for a server
stacker ssh-key uploadUpload an existing SSH key pair for a server
stacker ssh-key injectRepair Vault-key trust by using an already-working private key to update authorized_keys
stacker service addAdd a service from the template catalog to stacker.yml
stacker service listList available service templates (20+ built-in)
stacker agent healthCheck Status Panel agent connectivity and health
stacker agent statusDisplay agent snapshot — containers, versions, uptime
stacker agent list apps / stacker agent appsList apps for the target deployment
stacker agent list containers / stacker agent containersList containers on the target server
stacker agent logs <app>Retrieve container logs from the remote agent
stacker agent restart <app>Restart a container via the agent
stacker agent deploy-appDeploy or update an app container on the target server. --runtime kata|runc selects container runtime; --env <name> selects the deploy environment/profile
stacker agent remove-appRemove an app container (with optional volume/image cleanup)
stacker agent configure-proxyConfigure Nginx Proxy Manager via the agent; use --no-ssl for plain HTTP hosts (credentials are resolved from Vault and are auto-seeded for managed Status Panel + NPM deploys)
stacker agent configure-firewallConfigure guest OS firewall rules via the Status Panel agent; use stacker cloud firewall for provider firewalls
stacker agent historyShow recent command execution history
stacker agent execExecute a raw agent command with JSON parameters
stacker pipe scanDiscover local endpoints/resources from running containers (when target is local)
stacker pipe scan --containers [filter]Discover local endpoints/resources for matching containers
stacker pipe scan --app <app>Probe a remote app for API endpoints
stacker pipe create <src> <tgt>Create a data pipe between two containers (interactive; or non-interactive with --source-endpoint/--target-endpoint/--name — added in 0.3.2). --retry/--on-failure/--on-success attach a retry policy + lifecycle handlers
stacker pipe diffCompare the declared pipes: block against deployed pipes (added in 0.3.2)
stacker pipe applyReconcile declared pipes into the deployment; --prune removes orphans, --dry-run previews (added in 0.3.2)
stacker pipe listList pipe instances for the current deployment
stacker pipe activate <id>Activate a pipe (start listening for triggers)
stacker pipe deactivate <id>Pause an active pipe
stacker pipe trigger <id>One-shot pipe execution with optional input data
stacker pipe deploy <id>Promote a local pipe to a remote deployment
stacker pipe history <id>View execution history for a pipe
stacker pipe replay <exec-id>Re-run a previous pipe execution
stacker monitorWatch container health and alert on problems (added in 0.3.2); --once for a single check (cron-friendly). Configure via monitoring.alerts in stacker.yml
stacker target [local|cloud|server]Switch deployment target mode
stacker env [local|dev|prod]Show or persist the active deploy environment/profile used by app-only updates
stacker whoamiShow the active login, subscription plan, and current project deployment context
stacker submitPackage current stack and submit to marketplace for review
stacker marketplace statusCheck submission status for your marketplace templates
stacker marketplace logs <name>Show review comments and history for a submission
stacker loginAuthenticate with the TryDirect platform
stacker updateCheck for updates and self-update

Deploy targets

stacker deploy --target local# docker compose up (default)
stacker deploy --target cloud # Terraform + Ansible → cloud provider
stacker deploy --target server # deploy to existing server via SSH
stacker deploy --dry-run # preview generated files without executing

After a successful cloud deploy, Stacker creates or reuses a local backup key at ~/.config/stacker/ssh/server-<id>_ed25519 (or under $XDG_CONFIG_HOME) and authorizes its public key on the server when possible. The CLI prints a normal ssh -i ... command, while the Vault private key remains server-side.

When a cloud/server deploy includes deploy.registry credentials (or the equivalent STACKER_DOCKER_* environment variables), Stacker stores that registry auth securely and reuses it for later Status-managed image refreshes such as stacker agent deploy-app. This keeps private-image redeploys working without depending on host-level docker login state or mounting /root/.docker into the agent container.

Secrets workflow

# Local project .env secret
stacker secrets set DB_PASSWORD=supersecret
# Discover valid remote deployable service/app targets first
stacker secrets apps
# Remote service secret used at render/deploy time for one target
stacker secrets set S3_SECRET_KEY \
--scope service \
--service uploader \
--body supersecret
# Remote server secret for future host-level consumers
stacker secrets set NPM_TOKEN \
--scope server \
--server-id 42 \
--body-file .npm-token
# Remote reads are metadata-only in v1
stacker secrets list --scope service --service uploader --json
stacker secrets get S3_SECRET_KEY --scope service --service uploader --json
# Push stored remote secrets into the target's runtime env
stacker secrets push --service uploader
stacker secrets push --service uploader --env prod
# Aliases: stacker secrets deploy --service uploader# stacker secrets apply --service uploader
  • Local mode remains the default and reads/writes the project .env file.
  • Remote mode is enabled only with --scope service or --scope server.
  • Service-scoped remote commands default --project from stacker.yml -> project.identity; --project still overrides it explicitly.
  • Service-scoped secrets target deployable service/app codes listed by stacker secrets apps, including registered stacker.yml services and supported image-backed Compose services after a deploy/update sync.
  • Service-scoped secrets are merged only into the matching rendered service/app env at deploy time.
  • stacker secrets push --service <target> applies stored service secrets to the remote runtime env without changing secret values. Use --env <name> for a one-off environment selection, or stacker env <name> to persist the active environment/profile for future app-only updates. Use --force only when the remote env drift check reports an out-of-band change.
  • Remote get and list do not return plaintext values in v1.
  • MCP env inspection now exposes explicit secure metadata for Vault-backed variables: get_app_env_vars keeps the redacted environment_variables object for compatibility and also returns environment_entries[] with secure, redacted, and source fields.

Remote deploys render runtime env into one canonical host file: /home/trydirect/project/.env. Generated compose uses env_file: .env, so the path is relative to the deployed compose file. To inspect paths and contributing layers without exposing values, run:

stacker config show --resolved

For app-only updates, stacker agent deploy-app <target> resolves the deploy environment from --env, then .stacker/active-env, then stacker.yml. If <target>/docker/<env>/compose.yml exists, Stacker uses the app-local service definition for that target but merges it into the full project-level compose file before sending it to the agent. This prevents app-only updates from replacing the remote stack compose with a single-service compose file. Any app-local .env referenced by that compose file is uploaded in the config bundle, and Stacker appends the Vault-rendered service secrets for the same target to that file before the agent writes it on the server. Repeated app-only updates replace the prior # stacker-render ... block in that file instead of stacking duplicate rendered secret sections.

Marketplace workflow (for stack developers)

stacker deploy --target local# 1. test locally
stacker deploy --target server # 2. test on remote server
stacker submit # 3. submit for marketplace review
stacker marketplace status # 4. check review status# Stack is auto-published once approved by the review team

Marketplace install (for buyers)

# Option A: Deploy from your laptop to a remote server
stacker deploy my-stack --target server --host 1.2.3.4
# Option B: Run directly on the target server (one-liner)
curl -sL https://marketplace.try.direct/<purchase-token>/install.sh | sh

Key features

  • Auto-detection — identifies Node, Python, Rust, Go, PHP, static sites from project files
  • Dockerfile generation — produces optimised multi-stage Dockerfiles per app type
  • Docker Compose generation — wires app + services + proxy + monitoring
  • Remote service secrets — Vault-backed service/app target secrets are metadata-only when read and isolated to the selected service
  • AI-assisted config — scans project, calls LLM to generate tailored stacker.yml
  • AI troubleshooting — on deploy failure, suggests fixes via AI or deterministic fallback hints
  • Service catalog — 20+ built-in service templates (Postgres, Redis, WordPress, etc.) — add with stacker service add
  • AI service addition — ask stacker ai ask --write "add wordpress" and the AI uses the template catalog
  • Agent controlstacker agent subcommand to manage remote Status Panel agents (health, logs, restart, deploy, proxy) with --json output
  • SSH key management — generate, view, upload, and repair server SSH keys (Vault-backed), with automatic local backup SSH access after cloud deploy
  • Reverse proxy — Traefik (labels), Caddy (Caddyfile), and Nginx Proxy Manager, platform-managed and driven by proxy.domains end-to-end (0.3.2)
  • Container-health alarmstacker monitor watches container health and alerts on problems (terminal, webhook, or pipe), configured via monitoring.alerts (0.3.2)
  • Declarative pipes (IaC) — declare pipes in stacker.yml and reconcile with stacker pipe diff / pipe apply [--prune] (0.3.2)
  • Cloud deployment — Hetzner, DigitalOcean, AWS, Linode, with provider firewall operations and paused/failed install IP retention
  • MCP Server — 85+ tools, including deployment, agent control, config, proxy, firewall, and remote service secret management
  • Marketplace — submit stacks for review, auto-publish on approval, check status from CLI
  • Buyer install — purchase tokens, one-liner install scripts, agent self-registration

2. Stacker Server

The backend platform powering the Stack Builder UI, REST API, deployment orchestration, and MCP server for AI agents.

Setup

cp configuration.yaml.dist configuration.yaml # edit database, vault, AMQP settings
cp access_control.conf.dist access_control.conf
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/stacker
sqlx migrate run
cargo run --bin server # http://127.0.0.1:8000

Key API endpoints

EndpointDescription
POST /projectCreate a project from a stack definition
POST /{id}/deploy/{cloud_id}Deploy to a cloud provider
GET /project/{id}/appsList apps in a project
DELETE /project/{id}/apps/{code}Remove an app from a project
PUT /project/{id}/apps/{code}/envUpdate app environment variables
GET /project/{id}/apps/{code}/secretsList service-scoped secret metadata for an app
PUT /project/{id}/apps/{code}/secrets/{name}Create or update a Vault-backed service secret
PUT /project/{id}/apps/{code}/portsUpdate port mappings
PUT /project/{id}/apps/{code}/domainUpdate domain / SSL settings
GET /server/{id}/secretsList server-scoped secret metadata
PUT /server/{id}/secrets/{name}Create or update a Vault-backed server secret
POST /api/v1/commandsEnqueue a command for the Status Panel agent
POST /api/templatesCreate or update a marketplace template (creator)
POST /api/templates/{id}/submitSubmit template for marketplace review
GET /api/templates/mineList current user's template submissions
GET /api/v1/marketplace/install/{token}Generate install.sh script for buyers
GET /api/v1/marketplace/download/{token}Download stack archive (purchase token validated)
POST /api/v1/marketplace/agents/registerAgent self-registration after install
POST /api/v1/pipes/templatesCreate a reusable pipe template (source→target mapping)
GET /api/v1/pipes/templatesList pipe templates (with optional filters)
POST /api/v1/pipes/instancesCreate a pipe instance for a deployment
GET /api/v1/pipes/instancesList pipe instances by deployment hash
PUT /api/v1/pipes/instances/{id}/statusUpdate pipe instance status (active/paused)

MCP Server

Stacker exposes 52+ Model Context Protocol tools over WebSocket, enabling AI agents (Claude, GPT, etc.) to manage infrastructure programmatically:

  • Project & deployment management
  • Container operations (start, stop, restart, exec)
  • Log analysis & error summaries
  • Vault config read/write
  • Proxy configuration
  • App environment & port management
  • Server resource monitoring
  • Docker Compose generation & preview
  • Agent control (deploy app, remove app, configure proxy, get status)
  • Firewall management (iptables rules via Status Panel or SSH)

Key integrations

  • HashiCorp Vault — secrets and config storage, synced to deployments
  • RabbitMQ — deployment status updates, event-driven orchestration
  • TryDirect User Service — OAuth, marketplace templates, payment validation
  • Marketplace — publish and deploy community stacks

3. Status Panel Agent

A lightweight agent deployed alongside your application on the target server. It runs as a Docker container and communicates with Stacker Server using a pull-only architecture — the agent polls for commands, Stacker never dials out.

How it works

1. UI/API creates a command → POST /api/v1/commands
2. Command stored in DB queue → commands + command_queue tables
3. Agent polls for work → GET /api/v1/agent/commands/wait/{hash}
4. Agent executes locally → Docker API on the host
5. Agent reports result → POST /api/v1/agent/commands/report

All agent requests are HMAC-signed (X-Agent-Signature header) using a token stored in Vault.

Supported commands

CommandDescription
healthCheck container health status (single or all)
logsFetch container logs (stdout/stderr, with limits)
restartRestart a container
deploy_appDeploy or update an app container
remove_appRemove an app container
configure_proxyCreate/update/delete reverse-proxy entries
configure_firewallConfigure iptables firewall rules (add/remove/list/flush)
stacker.execExecute a command inside a running container (with security blocklist)
stacker.server_resourcesCollect server resource metrics (CPU, memory, disk, network)
apply_configPull config from Vault and apply to a running container
probe_endpointsDiscover API endpoints on containers (OpenAPI, REST, HTML forms, GraphQL)
activate_pipeActivate a pipe instance — start polling/webhook triggers
deactivate_pipeDeactivate a running pipe instance
trigger_pipeOne-shot pipe execution: fetch source data → map fields → post to target

Agent registration

# Agent self-registers on first boot (no auth required)
POST /api/v1/agent/register
{ "deployment_hash": "abc123", "capabilities": [...], "system_info": {...} }
→ { "agent_id": "...", "agent_token": "..." }

Token rotation

cargo run --bin console -- Agent rotate-token \
--deployment-hash <hash> \
--new-token <NEW_TOKEN>

Database migrations

sqlx migrate run # apply
sqlx migrate revert # rollback

Testing

cargo test# all tests (772+ unit, 69 security integration)
cargo test user_service_client # User Service connector
cargo test marketplace_webhook # Marketplace webhook flows
cargo test deployment_validator # Deployment validation
cargo test --test security_cli # CLI endpoint IDOR security tests
SQLX_OFFLINE=true cargo test --lib -- proxy_domains 2>&1| tail -10

Kata Containers (Hardware Isolation)

Stacker supports Kata Containers as an alternative runtime, providing VM-level isolation for each container using hardware virtualization (KVM).

KVM requirement — Kata needs nested or bare-metal KVM. Hetzner dedicated-CPU servers (CCX line) expose /dev/kvm out of the box, making them an ideal deployment target.

stacker deploy --runtime kata # deploy the current stack with Kata isolation
stacker agent deploy-app --runtime kata # deploy a single app container with Kata

See docs/kata/ for the full setup guide, network constraints, and monitoring reference. Automated provisioning (Ansible + Terraform for Hetzner CCX) is available via the TFA infrastructure toolkit.


Documentation


License

MIT

About

Orchestrate dockerized apps from cli, control, monitor, install apps on own servers and in the cloud

Topics

Resources

Security policy

Stars

6 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1,990 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DiscordVersionLicense



Build, deploy, and manage containerised applications with a single config file.


Deploying Directus (Node + Postgres) to an existing server with Stacker

Real deploys, one command each. See stacker-project-examples.

More demos — n8n · Gotify

n8n (workflow automation, Node + Postgres)

Deploying n8n with Stacker

Gotify (push-notification server, single container)

Deploying Gotify with Stacker

Stacker is a platform for turning any project into a deployable Docker stack. Add a stacker.yml to your repo, and Stacker generates Dockerfiles, docker-compose definitions, reverse-proxy configs, and deploys locally or to cloud providers — optionally with AI assistance.

v0.3.0 highlights: generate stacker.yml from any GitHub repo with stacker init --from-github, infra-service healthcheck inference, remote Vault-backed secrets for deployable service/app targets, paused or failed cloud/server installs retain discovered IP addresses, and cloud-provider firewalls can be managed without SSH.

Quick Start

Install the CLI

curl -fsSL https://raw.githubusercontent.com/trydirect/stacker/main/install.sh | bash

Create & deploy a project

cd my-project
stacker init # auto-detects project type, generates stacker.yml
stacker deploy # builds and runs locally via docker compose
stacker status # check running containers

Deploy from any GitHub repo

Generate a stacker.yml from a GitHub repository — no clone required. For the best results (port mappings, env vars, service context inferred from README and source), use --with-ai:

# AI-powered (recommended — reads README, compose, source files)
stacker init --from-github owner/repo --with-ai
# Template-based (project type + Dockerfile detection only)
stacker init -g https://github.com/ArchiveBox/ArchiveBox

With --with-ai, Stacker shallow-clones the repo, then uses an LLM (Ollama by default) to scan project files and generate a context-aware stacker.yml with services, ports, env vars, and healthchecks. Falls back to template detection if the AI provider is unreachable.

When environment variables are in the compose file, .env.example and scripts/generate-secrets.sh are also generated.

AI-powered init (optional)

Stacker can scan your project files and use an LLM to generate a tailored stacker.yml:

# Local AI with Ollama (free, private, default)
stacker init --with-ai
# OpenAI
stacker init --with-ai --ai-provider openai --ai-api-key sk-...
# Anthropic (key from env)export ANTHROPIC_API_KEY=sk-ant-...
stacker init --with-ai --ai-provider anthropic

If the AI provider is unreachable, Stacker falls back to template-based generation automatically.

When the project looks like a simple HTML or Next.js website and the configured Ollama model is qwen2.5-code or qwen2.5-coder, stacker init --with-ai can also bootstrap a website deployment scenario. The bootstrap seeds values from the generated stacker.yml, asks only for the missing deploy inputs, and saves scenario state under .stacker/scenarios/qwen2.5-code/website-deploy/ for later continuation with stacker ai.

AI deployment workflows

For the canonical AI/MCP deployment flow — inspect state, explain topology or env provenance, preview a plan, apply it safely, and recover with events or rollback — see AI deployment workflows.

For the qwen-specific website scenario flow, including --scenario and --step continuation, see the same guide.


stacker.yml example

name: my-appapp:
type: nodepath: ./srcports:
- "8080:3000"environment:
NODE_ENV: productionservices:
- name: postgresimage: postgres:16environment:
POSTGRES_DB: myappPOSTGRES_PASSWORD: ${DB_PASSWORD}proxy:
type: nginxauto_detect: truedomains:
- domain: app.example.comssl: autoupstream: app:3000deploy:
target: local # or: cloud, serverai:
enabled: trueprovider: ollamamodel: llama3monitoring:
status_panel: truehealthcheck:
endpoint: /healthinterval: 30salerts: # container-down alarm for `stacker monitor` (0.3.2)interval: 30target:
terminal: true # or: { url: "https://ntfy.example.com/alerts" }

Full schema reference: docs/STACKER_YML_REFERENCE.md


Three components

ComponentWhat it doesBinary
Stacker CLIDeveloper tool — init, deploy, monitor from the terminalstacker-cli
Stacker ServerREST API + Stack Builder UI + deployment orchestration + MCP Serverserver
Status Panel AgentDeployed alongside your app on the target server — executes commands, streams logs, reports health(separate repo)
┌──────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ Stacker CLI │────────►│ Stacker Server │────────►│ Status Panel Agent │
│ │ REST │ │ queue │ (on target server) │
│ stacker.yml │ API │ Stack Builder UI│ pull │ │
│ init/deploy │ │ 85+ MCP tools │◄────────│ health / logs / │
│ status/logs │ │ Vault · AMQP │ HMAC │ restart / exec / │
└──────────────┘ └──────────────────┘ │ deploy_app / proxy │
│ └─────────────────────┘
▼
Terraform + Ansible ──► Cloud
(Hetzner, DO, AWS, Linode)

1. Stacker CLI

The end-user tool. No server required for local deploys.

Commands

CommandDescription
stacker initDetect project type, generate stacker.yml + .stacker/ artifacts
stacker deployBuild & deploy the stack (local, cloud, or server). Cloud deploys also install a local SSH backup key when possible. --runtime kata|runc selects container runtime
stacker statusShow running containers and health
stacker logsView container logs (--follow, --service, --tail)
stacker deployment state / stacker deployment statusShow canonical deployment state (defaults to latest; --pinned uses stacker.yml hash)
stacker deployment eventsShow structured deployment events (--pinned uses stacker.yml hash)
stacker deployment rollbackPreview or apply a deployment rollback
stacker secretsManage local .env secrets or remote Vault-backed service / server secrets
stacker list deployments / stacker deployments / stacker psList deployments on the Stacker server
stacker list servers / stacker serversList saved servers
stacker list clouds / stacker clouds / stacker keys / stacker cloud keysList saved cloud credentials
stacker list ssh-keys / stacker ssh-keysList per-server SSH key status
stacker destroyTear down the deployed stack
stacker config validateValidate stacker.yml syntax
stacker config showShow resolved configuration
stacker config examplePrint a full commented reference
stacker config setup cloudGuided cloud deployment setup
stacker config setup aiConfigure AI provider, endpoint, model, and tasks
stacker ai ask "question"Ask the AI about your stack
stacker proxy addAdd a reverse-proxy domain entry
stacker proxy detectAuto-detect existing reverse-proxy containers
stacker cloud firewall addOpen cloud-provider firewall ports without SSH, for example --public-ports 8000/tcp on Hetzner
stacker cloud firewall removeRemove Stacker-managed cloud-provider firewall rules
stacker cloud firewall listList cloud-provider firewall rules for a server
stacker ssh-key generateGenerate a new SSH key pair for a server (Vault-backed)
stacker ssh-key showDisplay the public SSH key for a server
stacker ssh-key uploadUpload an existing SSH key pair for a server
stacker ssh-key injectRepair Vault-key trust by using an already-working private key to update authorized_keys
stacker service addAdd a service from the template catalog to stacker.yml
stacker service listList available service templates (20+ built-in)
stacker agent healthCheck Status Panel agent connectivity and health
stacker agent statusDisplay agent snapshot — containers, versions, uptime
stacker agent list apps / stacker agent appsList apps for the target deployment
stacker agent list containers / stacker agent containersList containers on the target server
stacker agent logs <app>Retrieve container logs from the remote agent
stacker agent restart <app>Restart a container via the agent
stacker agent deploy-appDeploy or update an app container on the target server. --runtime kata|runc selects container runtime; --env <name> selects the deploy environment/profile
stacker agent remove-appRemove an app container (with optional volume/image cleanup)
stacker agent configure-proxyConfigure Nginx Proxy Manager via the agent; use --no-ssl for plain HTTP hosts (credentials are resolved from Vault and are auto-seeded for managed Status Panel + NPM deploys)
stacker agent configure-firewallConfigure guest OS firewall rules via the Status Panel agent; use stacker cloud firewall for provider firewalls
stacker agent historyShow recent command execution history
stacker agent execExecute a raw agent command with JSON parameters
stacker pipe scanDiscover local endpoints/resources from running containers (when target is local)
stacker pipe scan --containers [filter]Discover local endpoints/resources for matching containers
stacker pipe scan --app <app>Probe a remote app for API endpoints
stacker pipe create <src> <tgt>Create a data pipe between two containers (interactive; or non-interactive with --source-endpoint/--target-endpoint/--name — added in 0.3.2). --retry/--on-failure/--on-success attach a retry policy + lifecycle handlers
stacker pipe diffCompare the declared pipes: block against deployed pipes (added in 0.3.2)
stacker pipe applyReconcile declared pipes into the deployment; --prune removes orphans, --dry-run previews (added in 0.3.2)
stacker pipe listList pipe instances for the current deployment
stacker pipe activate <id>Activate a pipe (start listening for triggers)
stacker pipe deactivate <id>Pause an active pipe
stacker pipe trigger <id>One-shot pipe execution with optional input data
stacker pipe deploy <id>Promote a local pipe to a remote deployment
stacker pipe history <id>View execution history for a pipe
stacker pipe replay <exec-id>Re-run a previous pipe execution
stacker monitorWatch container health and alert on problems (added in 0.3.2); --once for a single check (cron-friendly). Configure via monitoring.alerts in stacker.yml
stacker target [local|cloud|server]Switch deployment target mode
stacker env [local|dev|prod]Show or persist the active deploy environment/profile used by app-only updates
stacker whoamiShow the active login, subscription plan, and current project deployment context
stacker submitPackage current stack and submit to marketplace for review
stacker marketplace statusCheck submission status for your marketplace templates
stacker marketplace logs <name>Show review comments and history for a submission
stacker loginAuthenticate with the TryDirect platform
stacker updateCheck for updates and self-update

Deploy targets

stacker deploy --target local# docker compose up (default)
stacker deploy --target cloud # Terraform + Ansible → cloud provider
stacker deploy --target server # deploy to existing server via SSH
stacker deploy --dry-run # preview generated files without executing

After a successful cloud deploy, Stacker creates or reuses a local backup key at ~/.config/stacker/ssh/server-<id>_ed25519 (or under $XDG_CONFIG_HOME) and authorizes its public key on the server when possible. The CLI prints a normal ssh -i ... command, while the Vault private key remains server-side.

When a cloud/server deploy includes deploy.registry credentials (or the equivalent STACKER_DOCKER_* environment variables), Stacker stores that registry auth securely and reuses it for later Status-managed image refreshes such as stacker agent deploy-app. This keeps private-image redeploys working without depending on host-level docker login state or mounting /root/.docker into the agent container.

Secrets workflow

# Local project .env secret
stacker secrets set DB_PASSWORD=supersecret
# Discover valid remote deployable service/app targets first
stacker secrets apps
# Remote service secret used at render/deploy time for one target
stacker secrets set S3_SECRET_KEY \
--scope service \
--service uploader \
--body supersecret
# Remote server secret for future host-level consumers
stacker secrets set NPM_TOKEN \
--scope server \
--server-id 42 \
--body-file .npm-token
# Remote reads are metadata-only in v1
stacker secrets list --scope service --service uploader --json
stacker secrets get S3_SECRET_KEY --scope service --service uploader --json
# Push stored remote secrets into the target's runtime env
stacker secrets push --service uploader
stacker secrets push --service uploader --env prod
# Aliases: stacker secrets deploy --service uploader# stacker secrets apply --service uploader
  • Local mode remains the default and reads/writes the project .env file.
  • Remote mode is enabled only with --scope service or --scope server.
  • Service-scoped remote commands default --project from stacker.yml -> project.identity; --project still overrides it explicitly.
  • Service-scoped secrets target deployable service/app codes listed by stacker secrets apps, including registered stacker.yml services and supported image-backed Compose services after a deploy/update sync.
  • Service-scoped secrets are merged only into the matching rendered service/app env at deploy time.
  • stacker secrets push --service <target> applies stored service secrets to the remote runtime env without changing secret values. Use --env <name> for a one-off environment selection, or stacker env <name> to persist the active environment/profile for future app-only updates. Use --force only when the remote env drift check reports an out-of-band change.
  • Remote get and list do not return plaintext values in v1.
  • MCP env inspection now exposes explicit secure metadata for Vault-backed variables: get_app_env_vars keeps the redacted environment_variables object for compatibility and also returns environment_entries[] with secure, redacted, and source fields.

Remote deploys render runtime env into one canonical host file: /home/trydirect/project/.env. Generated compose uses env_file: .env, so the path is relative to the deployed compose file. To inspect paths and contributing layers without exposing values, run:

stacker config show --resolved

For app-only updates, stacker agent deploy-app <target> resolves the deploy environment from --env, then .stacker/active-env, then stacker.yml. If <target>/docker/<env>/compose.yml exists, Stacker uses the app-local service definition for that target but merges it into the full project-level compose file before sending it to the agent. This prevents app-only updates from replacing the remote stack compose with a single-service compose file. Any app-local .env referenced by that compose file is uploaded in the config bundle, and Stacker appends the Vault-rendered service secrets for the same target to that file before the agent writes it on the server. Repeated app-only updates replace the prior # stacker-render ... block in that file instead of stacking duplicate rendered secret sections.

Marketplace workflow (for stack developers)

stacker deploy --target local# 1. test locally
stacker deploy --target server # 2. test on remote server
stacker submit # 3. submit for marketplace review
stacker marketplace status # 4. check review status# Stack is auto-published once approved by the review team

Marketplace install (for buyers)

# Option A: Deploy from your laptop to a remote server
stacker deploy my-stack --target server --host 1.2.3.4
# Option B: Run directly on the target server (one-liner)
curl -sL https://marketplace.try.direct/<purchase-token>/install.sh | sh

Key features

  • Auto-detection — identifies Node, Python, Rust, Go, PHP, static sites from project files
  • Dockerfile generation — produces optimised multi-stage Dockerfiles per app type
  • Docker Compose generation — wires app + services + proxy + monitoring
  • Remote service secrets — Vault-backed service/app target secrets are metadata-only when read and isolated to the selected service
  • AI-assisted config — scans project, calls LLM to generate tailored stacker.yml
  • AI troubleshooting — on deploy failure, suggests fixes via AI or deterministic fallback hints
  • Service catalog — 20+ built-in service templates (Postgres, Redis, WordPress, etc.) — add with stacker service add
  • AI service addition — ask stacker ai ask --write "add wordpress" and the AI uses the template catalog
  • Agent controlstacker agent subcommand to manage remote Status Panel agents (health, logs, restart, deploy, proxy) with --json output
  • SSH key management — generate, view, upload, and repair server SSH keys (Vault-backed), with automatic local backup SSH access after cloud deploy
  • Reverse proxy — Traefik (labels), Caddy (Caddyfile), and Nginx Proxy Manager, platform-managed and driven by proxy.domains end-to-end (0.3.2)
  • Container-health alarmstacker monitor watches container health and alerts on problems (terminal, webhook, or pipe), configured via monitoring.alerts (0.3.2)
  • Declarative pipes (IaC) — declare pipes in stacker.yml and reconcile with stacker pipe diff / pipe apply [--prune] (0.3.2)
  • Cloud deployment — Hetzner, DigitalOcean, AWS, Linode, with provider firewall operations and paused/failed install IP retention
  • MCP Server — 85+ tools, including deployment, agent control, config, proxy, firewall, and remote service secret management
  • Marketplace — submit stacks for review, auto-publish on approval, check status from CLI
  • Buyer install — purchase tokens, one-liner install scripts, agent self-registration

2. Stacker Server

The backend platform powering the Stack Builder UI, REST API, deployment orchestration, and MCP server for AI agents.

Setup

cp configuration.yaml.dist configuration.yaml # edit database, vault, AMQP settings
cp access_control.conf.dist access_control.conf
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/stacker
sqlx migrate run
cargo run --bin server # http://127.0.0.1:8000

Key API endpoints

EndpointDescription
POST /projectCreate a project from a stack definition
POST /{id}/deploy/{cloud_id}Deploy to a cloud provider
GET /project/{id}/appsList apps in a project
DELETE /project/{id}/apps/{code}Remove an app from a project
PUT /project/{id}/apps/{code}/envUpdate app environment variables
GET /project/{id}/apps/{code}/secretsList service-scoped secret metadata for an app
PUT /project/{id}/apps/{code}/secrets/{name}Create or update a Vault-backed service secret
PUT /project/{id}/apps/{code}/portsUpdate port mappings
PUT /project/{id}/apps/{code}/domainUpdate domain / SSL settings
GET /server/{id}/secretsList server-scoped secret metadata
PUT /server/{id}/secrets/{name}Create or update a Vault-backed server secret
POST /api/v1/commandsEnqueue a command for the Status Panel agent
POST /api/templatesCreate or update a marketplace template (creator)
POST /api/templates/{id}/submitSubmit template for marketplace review
GET /api/templates/mineList current user's template submissions
GET /api/v1/marketplace/install/{token}Generate install.sh script for buyers
GET /api/v1/marketplace/download/{token}Download stack archive (purchase token validated)
POST /api/v1/marketplace/agents/registerAgent self-registration after install
POST /api/v1/pipes/templatesCreate a reusable pipe template (source→target mapping)
GET /api/v1/pipes/templatesList pipe templates (with optional filters)
POST /api/v1/pipes/instancesCreate a pipe instance for a deployment
GET /api/v1/pipes/instancesList pipe instances by deployment hash
PUT /api/v1/pipes/instances/{id}/statusUpdate pipe instance status (active/paused)

MCP Server

Stacker exposes 52+ Model Context Protocol tools over WebSocket, enabling AI agents (Claude, GPT, etc.) to manage infrastructure programmatically:

  • Project & deployment management
  • Container operations (start, stop, restart, exec)
  • Log analysis & error summaries
  • Vault config read/write
  • Proxy configuration
  • App environment & port management
  • Server resource monitoring
  • Docker Compose generation & preview
  • Agent control (deploy app, remove app, configure proxy, get status)
  • Firewall management (iptables rules via Status Panel or SSH)

Key integrations

  • HashiCorp Vault — secrets and config storage, synced to deployments
  • RabbitMQ — deployment status updates, event-driven orchestration
  • TryDirect User Service — OAuth, marketplace templates, payment validation
  • Marketplace — publish and deploy community stacks

3. Status Panel Agent

A lightweight agent deployed alongside your application on the target server. It runs as a Docker container and communicates with Stacker Server using a pull-only architecture — the agent polls for commands, Stacker never dials out.

How it works

1. UI/API creates a command → POST /api/v1/commands
2. Command stored in DB queue → commands + command_queue tables
3. Agent polls for work → GET /api/v1/agent/commands/wait/{hash}
4. Agent executes locally → Docker API on the host
5. Agent reports result → POST /api/v1/agent/commands/report

All agent requests are HMAC-signed (X-Agent-Signature header) using a token stored in Vault.

Supported commands

CommandDescription
healthCheck container health status (single or all)
logsFetch container logs (stdout/stderr, with limits)
restartRestart a container
deploy_appDeploy or update an app container
remove_appRemove an app container
configure_proxyCreate/update/delete reverse-proxy entries
configure_firewallConfigure iptables firewall rules (add/remove/list/flush)
stacker.execExecute a command inside a running container (with security blocklist)
stacker.server_resourcesCollect server resource metrics (CPU, memory, disk, network)
apply_configPull config from Vault and apply to a running container
probe_endpointsDiscover API endpoints on containers (OpenAPI, REST, HTML forms, GraphQL)
activate_pipeActivate a pipe instance — start polling/webhook triggers
deactivate_pipeDeactivate a running pipe instance
trigger_pipeOne-shot pipe execution: fetch source data → map fields → post to target

Agent registration

# Agent self-registers on first boot (no auth required)
POST /api/v1/agent/register
{ "deployment_hash": "abc123", "capabilities": [...], "system_info": {...} }
→ { "agent_id": "...", "agent_token": "..." }

Token rotation

cargo run --bin console -- Agent rotate-token \
--deployment-hash <hash> \
--new-token <NEW_TOKEN>

Database migrations

sqlx migrate run # apply
sqlx migrate revert # rollback

Testing

cargo test# all tests (772+ unit, 69 security integration)
cargo test user_service_client # User Service connector
cargo test marketplace_webhook # Marketplace webhook flows
cargo test deployment_validator # Deployment validation
cargo test --test security_cli # CLI endpoint IDOR security tests
SQLX_OFFLINE=true cargo test --lib -- proxy_domains 2>&1| tail -10

Kata Containers (Hardware Isolation)

Stacker supports Kata Containers as an alternative runtime, providing VM-level isolation for each container using hardware virtualization (KVM).

KVM requirement — Kata needs nested or bare-metal KVM. Hetzner dedicated-CPU servers (CCX line) expose /dev/kvm out of the box, making them an ideal deployment target.

stacker deploy --runtime kata # deploy the current stack with Kata isolation
stacker agent deploy-app --runtime kata # deploy a single app container with Kata

See docs/kata/ for the full setup guide, network constraints, and monitoring reference. Automated provisioning (Ansible + Terraform for Hetzner CCX) is available via the TFA infrastructure toolkit.


Documentation


License

MIT

About

Orchestrate dockerized apps from cli, control, monitor, install apps on own servers and in the cloud

Topics

Resources

Security policy

Stars

6 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1,990 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DiscordVersionLicense



Build, deploy, and manage containerised applications with a single config file.


Deploying Directus (Node + Postgres) to an existing server with Stacker

Real deploys, one command each. See stacker-project-examples.

More demos — n8n · Gotify

n8n (workflow automation, Node + Postgres)

Deploying n8n with Stacker

Gotify (push-notification server, single container)

Deploying Gotify with Stacker

Stacker is a platform for turning any project into a deployable Docker stack. Add a stacker.yml to your repo, and Stacker generates Dockerfiles, docker-compose definitions, reverse-proxy configs, and deploys locally or to cloud providers — optionally with AI assistance.

v0.3.0 highlights: generate stacker.yml from any GitHub repo with stacker init --from-github, infra-service healthcheck inference, remote Vault-backed secrets for deployable service/app targets, paused or failed cloud/server installs retain discovered IP addresses, and cloud-provider firewalls can be managed without SSH.

Quick Start

Install the CLI

curl -fsSL https://raw.githubusercontent.com/trydirect/stacker/main/install.sh | bash

Create & deploy a project

cd my-project
stacker init # auto-detects project type, generates stacker.yml
stacker deploy # builds and runs locally via docker compose
stacker status # check running containers

Deploy from any GitHub repo

Generate a stacker.yml from a GitHub repository — no clone required. For the best results (port mappings, env vars, service context inferred from README and source), use --with-ai:

# AI-powered (recommended — reads README, compose, source files)
stacker init --from-github owner/repo --with-ai
# Template-based (project type + Dockerfile detection only)
stacker init -g https://github.com/ArchiveBox/ArchiveBox

With --with-ai, Stacker shallow-clones the repo, then uses an LLM (Ollama by default) to scan project files and generate a context-aware stacker.yml with services, ports, env vars, and healthchecks. Falls back to template detection if the AI provider is unreachable.

When environment variables are in the compose file, .env.example and scripts/generate-secrets.sh are also generated.

AI-powered init (optional)

Stacker can scan your project files and use an LLM to generate a tailored stacker.yml:

# Local AI with Ollama (free, private, default)
stacker init --with-ai
# OpenAI
stacker init --with-ai --ai-provider openai --ai-api-key sk-...
# Anthropic (key from env)export ANTHROPIC_API_KEY=sk-ant-...
stacker init --with-ai --ai-provider anthropic

If the AI provider is unreachable, Stacker falls back to template-based generation automatically.

When the project looks like a simple HTML or Next.js website and the configured Ollama model is qwen2.5-code or qwen2.5-coder, stacker init --with-ai can also bootstrap a website deployment scenario. The bootstrap seeds values from the generated stacker.yml, asks only for the missing deploy inputs, and saves scenario state under .stacker/scenarios/qwen2.5-code/website-deploy/ for later continuation with stacker ai.

AI deployment workflows

For the canonical AI/MCP deployment flow — inspect state, explain topology or env provenance, preview a plan, apply it safely, and recover with events or rollback — see AI deployment workflows.

For the qwen-specific website scenario flow, including --scenario and --step continuation, see the same guide.


stacker.yml example

name: my-appapp:
type: nodepath: ./srcports:
- "8080:3000"environment:
NODE_ENV: productionservices:
- name: postgresimage: postgres:16environment:
POSTGRES_DB: myappPOSTGRES_PASSWORD: ${DB_PASSWORD}proxy:
type: nginxauto_detect: truedomains:
- domain: app.example.comssl: autoupstream: app:3000deploy:
target: local # or: cloud, serverai:
enabled: trueprovider: ollamamodel: llama3monitoring:
status_panel: truehealthcheck:
endpoint: /healthinterval: 30salerts: # container-down alarm for `stacker monitor` (0.3.2)interval: 30target:
terminal: true # or: { url: "https://ntfy.example.com/alerts" }

Full schema reference: docs/STACKER_YML_REFERENCE.md


Three components

ComponentWhat it doesBinary
Stacker CLIDeveloper tool — init, deploy, monitor from the terminalstacker-cli
Stacker ServerREST API + Stack Builder UI + deployment orchestration + MCP Serverserver
Status Panel AgentDeployed alongside your app on the target server — executes commands, streams logs, reports health(separate repo)
┌──────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ Stacker CLI │────────►│ Stacker Server │────────►│ Status Panel Agent │
│ │ REST │ │ queue │ (on target server) │
│ stacker.yml │ API │ Stack Builder UI│ pull │ │
│ init/deploy │ │ 85+ MCP tools │◄────────│ health / logs / │
│ status/logs │ │ Vault · AMQP │ HMAC │ restart / exec / │
└──────────────┘ └──────────────────┘ │ deploy_app / proxy │
│ └─────────────────────┘
▼
Terraform + Ansible ──► Cloud
(Hetzner, DO, AWS, Linode)

1. Stacker CLI

The end-user tool. No server required for local deploys.

Commands

CommandDescription
stacker initDetect project type, generate stacker.yml + .stacker/ artifacts
stacker deployBuild & deploy the stack (local, cloud, or server). Cloud deploys also install a local SSH backup key when possible. --runtime kata|runc selects container runtime
stacker statusShow running containers and health
stacker logsView container logs (--follow, --service, --tail)
stacker deployment state / stacker deployment statusShow canonical deployment state (defaults to latest; --pinned uses stacker.yml hash)
stacker deployment eventsShow structured deployment events (--pinned uses stacker.yml hash)
stacker deployment rollbackPreview or apply a deployment rollback
stacker secretsManage local .env secrets or remote Vault-backed service / server secrets
stacker list deployments / stacker deployments / stacker psList deployments on the Stacker server
stacker list servers / stacker serversList saved servers
stacker list clouds / stacker clouds / stacker keys / stacker cloud keysList saved cloud credentials
stacker list ssh-keys / stacker ssh-keysList per-server SSH key status
stacker destroyTear down the deployed stack
stacker config validateValidate stacker.yml syntax
stacker config showShow resolved configuration
stacker config examplePrint a full commented reference
stacker config setup cloudGuided cloud deployment setup
stacker config setup aiConfigure AI provider, endpoint, model, and tasks
stacker ai ask "question"Ask the AI about your stack
stacker proxy addAdd a reverse-proxy domain entry
stacker proxy detectAuto-detect existing reverse-proxy containers
stacker cloud firewall addOpen cloud-provider firewall ports without SSH, for example --public-ports 8000/tcp on Hetzner
stacker cloud firewall removeRemove Stacker-managed cloud-provider firewall rules
stacker cloud firewall listList cloud-provider firewall rules for a server
stacker ssh-key generateGenerate a new SSH key pair for a server (Vault-backed)
stacker ssh-key showDisplay the public SSH key for a server
stacker ssh-key uploadUpload an existing SSH key pair for a server
stacker ssh-key injectRepair Vault-key trust by using an already-working private key to update authorized_keys
stacker service addAdd a service from the template catalog to stacker.yml
stacker service listList available service templates (20+ built-in)
stacker agent healthCheck Status Panel agent connectivity and health
stacker agent statusDisplay agent snapshot — containers, versions, uptime
stacker agent list apps / stacker agent appsList apps for the target deployment
stacker agent list containers / stacker agent containersList containers on the target server
stacker agent logs <app>Retrieve container logs from the remote agent
stacker agent restart <app>Restart a container via the agent
stacker agent deploy-appDeploy or update an app container on the target server. --runtime kata|runc selects container runtime; --env <name> selects the deploy environment/profile
stacker agent remove-appRemove an app container (with optional volume/image cleanup)
stacker agent configure-proxyConfigure Nginx Proxy Manager via the agent; use --no-ssl for plain HTTP hosts (credentials are resolved from Vault and are auto-seeded for managed Status Panel + NPM deploys)
stacker agent configure-firewallConfigure guest OS firewall rules via the Status Panel agent; use stacker cloud firewall for provider firewalls
stacker agent historyShow recent command execution history
stacker agent execExecute a raw agent command with JSON parameters
stacker pipe scanDiscover local endpoints/resources from running containers (when target is local)
stacker pipe scan --containers [filter]Discover local endpoints/resources for matching containers
stacker pipe scan --app <app>Probe a remote app for API endpoints
stacker pipe create <src> <tgt>Create a data pipe between two containers (interactive; or non-interactive with --source-endpoint/--target-endpoint/--name — added in 0.3.2). --retry/--on-failure/--on-success attach a retry policy + lifecycle handlers
stacker pipe diffCompare the declared pipes: block against deployed pipes (added in 0.3.2)
stacker pipe applyReconcile declared pipes into the deployment; --prune removes orphans, --dry-run previews (added in 0.3.2)
stacker pipe listList pipe instances for the current deployment
stacker pipe activate <id>Activate a pipe (start listening for triggers)
stacker pipe deactivate <id>Pause an active pipe
stacker pipe trigger <id>One-shot pipe execution with optional input data
stacker pipe deploy <id>Promote a local pipe to a remote deployment
stacker pipe history <id>View execution history for a pipe
stacker pipe replay <exec-id>Re-run a previous pipe execution
stacker monitorWatch container health and alert on problems (added in 0.3.2); --once for a single check (cron-friendly). Configure via monitoring.alerts in stacker.yml
stacker target [local|cloud|server]Switch deployment target mode
stacker env [local|dev|prod]Show or persist the active deploy environment/profile used by app-only updates
stacker whoamiShow the active login, subscription plan, and current project deployment context
stacker submitPackage current stack and submit to marketplace for review
stacker marketplace statusCheck submission status for your marketplace templates
stacker marketplace logs <name>Show review comments and history for a submission
stacker loginAuthenticate with the TryDirect platform
stacker updateCheck for updates and self-update

Deploy targets

stacker deploy --target local# docker compose up (default)
stacker deploy --target cloud # Terraform + Ansible → cloud provider
stacker deploy --target server # deploy to existing server via SSH
stacker deploy --dry-run # preview generated files without executing

After a successful cloud deploy, Stacker creates or reuses a local backup key at ~/.config/stacker/ssh/server-<id>_ed25519 (or under $XDG_CONFIG_HOME) and authorizes its public key on the server when possible. The CLI prints a normal ssh -i ... command, while the Vault private key remains server-side.

When a cloud/server deploy includes deploy.registry credentials (or the equivalent STACKER_DOCKER_* environment variables), Stacker stores that registry auth securely and reuses it for later Status-managed image refreshes such as stacker agent deploy-app. This keeps private-image redeploys working without depending on host-level docker login state or mounting /root/.docker into the agent container.

Secrets workflow

# Local project .env secret
stacker secrets set DB_PASSWORD=supersecret
# Discover valid remote deployable service/app targets first
stacker secrets apps
# Remote service secret used at render/deploy time for one target
stacker secrets set S3_SECRET_KEY \
--scope service \
--service uploader \
--body supersecret
# Remote server secret for future host-level consumers
stacker secrets set NPM_TOKEN \
--scope server \
--server-id 42 \
--body-file .npm-token
# Remote reads are metadata-only in v1
stacker secrets list --scope service --service uploader --json
stacker secrets get S3_SECRET_KEY --scope service --service uploader --json
# Push stored remote secrets into the target's runtime env
stacker secrets push --service uploader
stacker secrets push --service uploader --env prod
# Aliases: stacker secrets deploy --service uploader# stacker secrets apply --service uploader
  • Local mode remains the default and reads/writes the project .env file.
  • Remote mode is enabled only with --scope service or --scope server.
  • Service-scoped remote commands default --project from stacker.yml -> project.identity; --project still overrides it explicitly.
  • Service-scoped secrets target deployable service/app codes listed by stacker secrets apps, including registered stacker.yml services and supported image-backed Compose services after a deploy/update sync.
  • Service-scoped secrets are merged only into the matching rendered service/app env at deploy time.
  • stacker secrets push --service <target> applies stored service secrets to the remote runtime env without changing secret values. Use --env <name> for a one-off environment selection, or stacker env <name> to persist the active environment/profile for future app-only updates. Use --force only when the remote env drift check reports an out-of-band change.
  • Remote get and list do not return plaintext values in v1.
  • MCP env inspection now exposes explicit secure metadata for Vault-backed variables: get_app_env_vars keeps the redacted environment_variables object for compatibility and also returns environment_entries[] with secure, redacted, and source fields.

Remote deploys render runtime env into one canonical host file: /home/trydirect/project/.env. Generated compose uses env_file: .env, so the path is relative to the deployed compose file. To inspect paths and contributing layers without exposing values, run:

stacker config show --resolved

For app-only updates, stacker agent deploy-app <target> resolves the deploy environment from --env, then .stacker/active-env, then stacker.yml. If <target>/docker/<env>/compose.yml exists, Stacker uses the app-local service definition for that target but merges it into the full project-level compose file before sending it to the agent. This prevents app-only updates from replacing the remote stack compose with a single-service compose file. Any app-local .env referenced by that compose file is uploaded in the config bundle, and Stacker appends the Vault-rendered service secrets for the same target to that file before the agent writes it on the server. Repeated app-only updates replace the prior # stacker-render ... block in that file instead of stacking duplicate rendered secret sections.

Marketplace workflow (for stack developers)

stacker deploy --target local# 1. test locally
stacker deploy --target server # 2. test on remote server
stacker submit # 3. submit for marketplace review
stacker marketplace status # 4. check review status# Stack is auto-published once approved by the review team

Marketplace install (for buyers)

# Option A: Deploy from your laptop to a remote server
stacker deploy my-stack --target server --host 1.2.3.4
# Option B: Run directly on the target server (one-liner)
curl -sL https://marketplace.try.direct/<purchase-token>/install.sh | sh

Key features

  • Auto-detection — identifies Node, Python, Rust, Go, PHP, static sites from project files
  • Dockerfile generation — produces optimised multi-stage Dockerfiles per app type
  • Docker Compose generation — wires app + services + proxy + monitoring
  • Remote service secrets — Vault-backed service/app target secrets are metadata-only when read and isolated to the selected service
  • AI-assisted config — scans project, calls LLM to generate tailored stacker.yml
  • AI troubleshooting — on deploy failure, suggests fixes via AI or deterministic fallback hints
  • Service catalog — 20+ built-in service templates (Postgres, Redis, WordPress, etc.) — add with stacker service add
  • AI service addition — ask stacker ai ask --write "add wordpress" and the AI uses the template catalog
  • Agent controlstacker agent subcommand to manage remote Status Panel agents (health, logs, restart, deploy, proxy) with --json output
  • SSH key management — generate, view, upload, and repair server SSH keys (Vault-backed), with automatic local backup SSH access after cloud deploy
  • Reverse proxy — Traefik (labels), Caddy (Caddyfile), and Nginx Proxy Manager, platform-managed and driven by proxy.domains end-to-end (0.3.2)
  • Container-health alarmstacker monitor watches container health and alerts on problems (terminal, webhook, or pipe), configured via monitoring.alerts (0.3.2)
  • Declarative pipes (IaC) — declare pipes in stacker.yml and reconcile with stacker pipe diff / pipe apply [--prune] (0.3.2)
  • Cloud deployment — Hetzner, DigitalOcean, AWS, Linode, with provider firewall operations and paused/failed install IP retention
  • MCP Server — 85+ tools, including deployment, agent control, config, proxy, firewall, and remote service secret management
  • Marketplace — submit stacks for review, auto-publish on approval, check status from CLI
  • Buyer install — purchase tokens, one-liner install scripts, agent self-registration

2. Stacker Server

The backend platform powering the Stack Builder UI, REST API, deployment orchestration, and MCP server for AI agents.

Setup

cp configuration.yaml.dist configuration.yaml # edit database, vault, AMQP settings
cp access_control.conf.dist access_control.conf
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/stacker
sqlx migrate run
cargo run --bin server # http://127.0.0.1:8000

Key API endpoints

EndpointDescription
POST /projectCreate a project from a stack definition
POST /{id}/deploy/{cloud_id}Deploy to a cloud provider
GET /project/{id}/appsList apps in a project
DELETE /project/{id}/apps/{code}Remove an app from a project
PUT /project/{id}/apps/{code}/envUpdate app environment variables
GET /project/{id}/apps/{code}/secretsList service-scoped secret metadata for an app
PUT /project/{id}/apps/{code}/secrets/{name}Create or update a Vault-backed service secret
PUT /project/{id}/apps/{code}/portsUpdate port mappings
PUT /project/{id}/apps/{code}/domainUpdate domain / SSL settings
GET /server/{id}/secretsList server-scoped secret metadata
PUT /server/{id}/secrets/{name}Create or update a Vault-backed server secret
POST /api/v1/commandsEnqueue a command for the Status Panel agent
POST /api/templatesCreate or update a marketplace template (creator)
POST /api/templates/{id}/submitSubmit template for marketplace review
GET /api/templates/mineList current user's template submissions
GET /api/v1/marketplace/install/{token}Generate install.sh script for buyers
GET /api/v1/marketplace/download/{token}Download stack archive (purchase token validated)
POST /api/v1/marketplace/agents/registerAgent self-registration after install
POST /api/v1/pipes/templatesCreate a reusable pipe template (source→target mapping)
GET /api/v1/pipes/templatesList pipe templates (with optional filters)
POST /api/v1/pipes/instancesCreate a pipe instance for a deployment
GET /api/v1/pipes/instancesList pipe instances by deployment hash
PUT /api/v1/pipes/instances/{id}/statusUpdate pipe instance status (active/paused)

MCP Server

Stacker exposes 52+ Model Context Protocol tools over WebSocket, enabling AI agents (Claude, GPT, etc.) to manage infrastructure programmatically:

  • Project & deployment management
  • Container operations (start, stop, restart, exec)
  • Log analysis & error summaries
  • Vault config read/write
  • Proxy configuration
  • App environment & port management
  • Server resource monitoring
  • Docker Compose generation & preview
  • Agent control (deploy app, remove app, configure proxy, get status)
  • Firewall management (iptables rules via Status Panel or SSH)

Key integrations

  • HashiCorp Vault — secrets and config storage, synced to deployments
  • RabbitMQ — deployment status updates, event-driven orchestration
  • TryDirect User Service — OAuth, marketplace templates, payment validation
  • Marketplace — publish and deploy community stacks

3. Status Panel Agent

A lightweight agent deployed alongside your application on the target server. It runs as a Docker container and communicates with Stacker Server using a pull-only architecture — the agent polls for commands, Stacker never dials out.

How it works

1. UI/API creates a command → POST /api/v1/commands
2. Command stored in DB queue → commands + command_queue tables
3. Agent polls for work → GET /api/v1/agent/commands/wait/{hash}
4. Agent executes locally → Docker API on the host
5. Agent reports result → POST /api/v1/agent/commands/report

All agent requests are HMAC-signed (X-Agent-Signature header) using a token stored in Vault.

Supported commands

CommandDescription
healthCheck container health status (single or all)
logsFetch container logs (stdout/stderr, with limits)
restartRestart a container
deploy_appDeploy or update an app container
remove_appRemove an app container
configure_proxyCreate/update/delete reverse-proxy entries
configure_firewallConfigure iptables firewall rules (add/remove/list/flush)
stacker.execExecute a command inside a running container (with security blocklist)
stacker.server_resourcesCollect server resource metrics (CPU, memory, disk, network)
apply_configPull config from Vault and apply to a running container
probe_endpointsDiscover API endpoints on containers (OpenAPI, REST, HTML forms, GraphQL)
activate_pipeActivate a pipe instance — start polling/webhook triggers
deactivate_pipeDeactivate a running pipe instance
trigger_pipeOne-shot pipe execution: fetch source data → map fields → post to target

Agent registration

# Agent self-registers on first boot (no auth required)
POST /api/v1/agent/register
{ "deployment_hash": "abc123", "capabilities": [...], "system_info": {...} }
→ { "agent_id": "...", "agent_token": "..." }

Token rotation

cargo run --bin console -- Agent rotate-token \
--deployment-hash <hash> \
--new-token <NEW_TOKEN>

Database migrations

sqlx migrate run # apply
sqlx migrate revert # rollback

Testing

cargo test# all tests (772+ unit, 69 security integration)
cargo test user_service_client # User Service connector
cargo test marketplace_webhook # Marketplace webhook flows
cargo test deployment_validator # Deployment validation
cargo test --test security_cli # CLI endpoint IDOR security tests
SQLX_OFFLINE=true cargo test --lib -- proxy_domains 2>&1| tail -10

Kata Containers (Hardware Isolation)

Stacker supports Kata Containers as an alternative runtime, providing VM-level isolation for each container using hardware virtualization (KVM).

KVM requirement — Kata needs nested or bare-metal KVM. Hetzner dedicated-CPU servers (CCX line) expose /dev/kvm out of the box, making them an ideal deployment target.

stacker deploy --runtime kata # deploy the current stack with Kata isolation
stacker agent deploy-app --runtime kata # deploy a single app container with Kata

See docs/kata/ for the full setup guide, network constraints, and monitoring reference. Automated provisioning (Ansible + Terraform for Hetzner CCX) is available via the TFA infrastructure toolkit.


Documentation


License

MIT

About

Orchestrate dockerized apps from cli, control, monitor, install apps on own servers and in the cloud

Topics

Resources

Security policy

Stars

6 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

1,990 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DiscordVersionLicense



Build, deploy, and manage containerised applications with a single config file.


Deploying Directus (Node + Postgres) to an existing server with Stacker

Real deploys, one command each. See stacker-project-examples.

More demos — n8n · Gotify

n8n (workflow automation, Node + Postgres)

Deploying n8n with Stacker

Gotify (push-notification server, single container)

Deploying Gotify with Stacker

Stacker is a platform for turning any project into a deployable Docker stack. Add a stacker.yml to your repo, and Stacker generates Dockerfiles, docker-compose definitions, reverse-proxy configs, and deploys locally or to cloud providers — optionally with AI assistance.

v0.3.0 highlights: generate stacker.yml from any GitHub repo with stacker init --from-github, infra-service healthcheck inference, remote Vault-backed secrets for deployable service/app targets, paused or failed cloud/server installs retain discovered IP addresses, and cloud-provider firewalls can be managed without SSH.

Quick Start

Install the CLI

curl -fsSL https://raw.githubusercontent.com/trydirect/stacker/main/install.sh | bash

Create & deploy a project

cd my-project
stacker init # auto-detects project type, generates stacker.yml
stacker deploy # builds and runs locally via docker compose
stacker status # check running containers

Deploy from any GitHub repo

Generate a stacker.yml from a GitHub repository — no clone required. For the best results (port mappings, env vars, service context inferred from README and source), use --with-ai:

# AI-powered (recommended — reads README, compose, source files)
stacker init --from-github owner/repo --with-ai
# Template-based (project type + Dockerfile detection only)
stacker init -g https://github.com/ArchiveBox/ArchiveBox

With --with-ai, Stacker shallow-clones the repo, then uses an LLM (Ollama by default) to scan project files and generate a context-aware stacker.yml with services, ports, env vars, and healthchecks. Falls back to template detection if the AI provider is unreachable.

When environment variables are in the compose file, .env.example and scripts/generate-secrets.sh are also generated.

AI-powered init (optional)

Stacker can scan your project files and use an LLM to generate a tailored stacker.yml:

# Local AI with Ollama (free, private, default)
stacker init --with-ai
# OpenAI
stacker init --with-ai --ai-provider openai --ai-api-key sk-...
# Anthropic (key from env)export ANTHROPIC_API_KEY=sk-ant-...
stacker init --with-ai --ai-provider anthropic

If the AI provider is unreachable, Stacker falls back to template-based generation automatically.

When the project looks like a simple HTML or Next.js website and the configured Ollama model is qwen2.5-code or qwen2.5-coder, stacker init --with-ai can also bootstrap a website deployment scenario. The bootstrap seeds values from the generated stacker.yml, asks only for the missing deploy inputs, and saves scenario state under .stacker/scenarios/qwen2.5-code/website-deploy/ for later continuation with stacker ai.

AI deployment workflows

For the canonical AI/MCP deployment flow — inspect state, explain topology or env provenance, preview a plan, apply it safely, and recover with events or rollback — see AI deployment workflows.

For the qwen-specific website scenario flow, including --scenario and --step continuation, see the same guide.


stacker.yml example

name: my-appapp:
type: nodepath: ./srcports:
- "8080:3000"environment:
NODE_ENV: productionservices:
- name: postgresimage: postgres:16environment:
POSTGRES_DB: myappPOSTGRES_PASSWORD: ${DB_PASSWORD}proxy:
type: nginxauto_detect: truedomains:
- domain: app.example.comssl: autoupstream: app:3000deploy:
target: local # or: cloud, serverai:
enabled: trueprovider: ollamamodel: llama3monitoring:
status_panel: truehealthcheck:
endpoint: /healthinterval: 30salerts: # container-down alarm for `stacker monitor` (0.3.2)interval: 30target:
terminal: true # or: { url: "https://ntfy.example.com/alerts" }

Full schema reference: docs/STACKER_YML_REFERENCE.md


Three components

ComponentWhat it doesBinary
Stacker CLIDeveloper tool — init, deploy, monitor from the terminalstacker-cli
Stacker ServerREST API + Stack Builder UI + deployment orchestration + MCP Serverserver
Status Panel AgentDeployed alongside your app on the target server — executes commands, streams logs, reports health(separate repo)
┌──────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ Stacker CLI │────────►│ Stacker Server │────────►│ Status Panel Agent │
│ │ REST │ │ queue │ (on target server) │
│ stacker.yml │ API │ Stack Builder UI│ pull │ │
│ init/deploy │ │ 85+ MCP tools │◄────────│ health / logs / │
│ status/logs │ │ Vault · AMQP │ HMAC │ restart / exec / │
└──────────────┘ └──────────────────┘ │ deploy_app / proxy │
│ └─────────────────────┘
▼
Terraform + Ansible ──► Cloud
(Hetzner, DO, AWS, Linode)

1. Stacker CLI

The end-user tool. No server required for local deploys.

Commands

CommandDescription
stacker initDetect project type, generate stacker.yml + .stacker/ artifacts
stacker deployBuild & deploy the stack (local, cloud, or server). Cloud deploys also install a local SSH backup key when possible. --runtime kata|runc selects container runtime
stacker statusShow running containers and health
stacker logsView container logs (--follow, --service, --tail)
stacker deployment state / stacker deployment statusShow canonical deployment state (defaults to latest; --pinned uses stacker.yml hash)
stacker deployment eventsShow structured deployment events (--pinned uses stacker.yml hash)
stacker deployment rollbackPreview or apply a deployment rollback
stacker secretsManage local .env secrets or remote Vault-backed service / server secrets
stacker list deployments / stacker deployments / stacker psList deployments on the Stacker server
stacker list servers / stacker serversList saved servers
stacker list clouds / stacker clouds / stacker keys / stacker cloud keysList saved cloud credentials
stacker list ssh-keys / stacker ssh-keysList per-server SSH key status
stacker destroyTear down the deployed stack
stacker config validateValidate stacker.yml syntax
stacker config showShow resolved configuration
stacker config examplePrint a full commented reference
stacker config setup cloudGuided cloud deployment setup
stacker config setup aiConfigure AI provider, endpoint, model, and tasks
stacker ai ask "question"Ask the AI about your stack
stacker proxy addAdd a reverse-proxy domain entry
stacker proxy detectAuto-detect existing reverse-proxy containers
stacker cloud firewall addOpen cloud-provider firewall ports without SSH, for example --public-ports 8000/tcp on Hetzner
stacker cloud firewall removeRemove Stacker-managed cloud-provider firewall rules
stacker cloud firewall listList cloud-provider firewall rules for a server
stacker ssh-key generateGenerate a new SSH key pair for a server (Vault-backed)
stacker ssh-key showDisplay the public SSH key for a server
stacker ssh-key uploadUpload an existing SSH key pair for a server
stacker ssh-key injectRepair Vault-key trust by using an already-working private key to update authorized_keys
stacker service addAdd a service from the template catalog to stacker.yml
stacker service listList available service templates (20+ built-in)
stacker agent healthCheck Status Panel agent connectivity and health
stacker agent statusDisplay agent snapshot — containers, versions, uptime
stacker agent list apps / stacker agent appsList apps for the target deployment
stacker agent list containers / stacker agent containersList containers on the target server
stacker agent logs <app>Retrieve container logs from the remote agent
stacker agent restart <app>Restart a container via the agent
stacker agent deploy-appDeploy or update an app container on the target server. --runtime kata|runc selects container runtime; --env <name> selects the deploy environment/profile
stacker agent remove-appRemove an app container (with optional volume/image cleanup)
stacker agent configure-proxyConfigure Nginx Proxy Manager via the agent; use --no-ssl for plain HTTP hosts (credentials are resolved from Vault and are auto-seeded for managed Status Panel + NPM deploys)
stacker agent configure-firewallConfigure guest OS firewall rules via the Status Panel agent; use stacker cloud firewall for provider firewalls
stacker agent historyShow recent command execution history
stacker agent execExecute a raw agent command with JSON parameters
stacker pipe scanDiscover local endpoints/resources from running containers (when target is local)
stacker pipe scan --containers [filter]Discover local endpoints/resources for matching containers
stacker pipe scan --app <app>Probe a remote app for API endpoints
stacker pipe create <src> <tgt>Create a data pipe between two containers (interactive; or non-interactive with --source-endpoint/--target-endpoint/--name — added in 0.3.2). --retry/--on-failure/--on-success attach a retry policy + lifecycle handlers
stacker pipe diffCompare the declared pipes: block against deployed pipes (added in 0.3.2)
stacker pipe applyReconcile declared pipes into the deployment; --prune removes orphans, --dry-run previews (added in 0.3.2)
stacker pipe listList pipe instances for the current deployment
stacker pipe activate <id>Activate a pipe (start listening for triggers)
stacker pipe deactivate <id>Pause an active pipe
stacker pipe trigger <id>One-shot pipe execution with optional input data
stacker pipe deploy <id>Promote a local pipe to a remote deployment
stacker pipe history <id>View execution history for a pipe
stacker pipe replay <exec-id>Re-run a previous pipe execution
stacker monitorWatch container health and alert on problems (added in 0.3.2); --once for a single check (cron-friendly). Configure via monitoring.alerts in stacker.yml
stacker target [local|cloud|server]Switch deployment target mode
stacker env [local|dev|prod]Show or persist the active deploy environment/profile used by app-only updates
stacker whoamiShow the active login, subscription plan, and current project deployment context
stacker submitPackage current stack and submit to marketplace for review
stacker marketplace statusCheck submission status for your marketplace templates
stacker marketplace logs <name>Show review comments and history for a submission
stacker loginAuthenticate with the TryDirect platform
stacker updateCheck for updates and self-update

Deploy targets

stacker deploy --target local# docker compose up (default)
stacker deploy --target cloud # Terraform + Ansible → cloud provider
stacker deploy --target server # deploy to existing server via SSH
stacker deploy --dry-run # preview generated files without executing

After a successful cloud deploy, Stacker creates or reuses a local backup key at ~/.config/stacker/ssh/server-<id>_ed25519 (or under $XDG_CONFIG_HOME) and authorizes its public key on the server when possible. The CLI prints a normal ssh -i ... command, while the Vault private key remains server-side.

When a cloud/server deploy includes deploy.registry credentials (or the equivalent STACKER_DOCKER_* environment variables), Stacker stores that registry auth securely and reuses it for later Status-managed image refreshes such as stacker agent deploy-app. This keeps private-image redeploys working without depending on host-level docker login state or mounting /root/.docker into the agent container.

Secrets workflow

# Local project .env secret
stacker secrets set DB_PASSWORD=supersecret
# Discover valid remote deployable service/app targets first
stacker secrets apps
# Remote service secret used at render/deploy time for one target
stacker secrets set S3_SECRET_KEY \
--scope service \
--service uploader \
--body supersecret
# Remote server secret for future host-level consumers
stacker secrets set NPM_TOKEN \
--scope server \
--server-id 42 \
--body-file .npm-token
# Remote reads are metadata-only in v1
stacker secrets list --scope service --service uploader --json
stacker secrets get S3_SECRET_KEY --scope service --service uploader --json
# Push stored remote secrets into the target's runtime env
stacker secrets push --service uploader
stacker secrets push --service uploader --env prod
# Aliases: stacker secrets deploy --service uploader# stacker secrets apply --service uploader
  • Local mode remains the default and reads/writes the project .env file.
  • Remote mode is enabled only with --scope service or --scope server.
  • Service-scoped remote commands default --project from stacker.yml -> project.identity; --project still overrides it explicitly.
  • Service-scoped secrets target deployable service/app codes listed by stacker secrets apps, including registered stacker.yml services and supported image-backed Compose services after a deploy/update sync.
  • Service-scoped secrets are merged only into the matching rendered service/app env at deploy time.
  • stacker secrets push --service <target> applies stored service secrets to the remote runtime env without changing secret values. Use --env <name> for a one-off environment selection, or stacker env <name> to persist the active environment/profile for future app-only updates. Use --force only when the remote env drift check reports an out-of-band change.
  • Remote get and list do not return plaintext values in v1.
  • MCP env inspection now exposes explicit secure metadata for Vault-backed variables: get_app_env_vars keeps the redacted environment_variables object for compatibility and also returns environment_entries[] with secure, redacted, and source fields.

Remote deploys render runtime env into one canonical host file: /home/trydirect/project/.env. Generated compose uses env_file: .env, so the path is relative to the deployed compose file. To inspect paths and contributing layers without exposing values, run:

stacker config show --resolved

For app-only updates, stacker agent deploy-app <target> resolves the deploy environment from --env, then .stacker/active-env, then stacker.yml. If <target>/docker/<env>/compose.yml exists, Stacker uses the app-local service definition for that target but merges it into the full project-level compose file before sending it to the agent. This prevents app-only updates from replacing the remote stack compose with a single-service compose file. Any app-local .env referenced by that compose file is uploaded in the config bundle, and Stacker appends the Vault-rendered service secrets for the same target to that file before the agent writes it on the server. Repeated app-only updates replace the prior # stacker-render ... block in that file instead of stacking duplicate rendered secret sections.

Marketplace workflow (for stack developers)

stacker deploy --target local# 1. test locally
stacker deploy --target server # 2. test on remote server
stacker submit # 3. submit for marketplace review
stacker marketplace status # 4. check review status# Stack is auto-published once approved by the review team

Marketplace install (for buyers)

# Option A: Deploy from your laptop to a remote server
stacker deploy my-stack --target server --host 1.2.3.4
# Option B: Run directly on the target server (one-liner)
curl -sL https://marketplace.try.direct/<purchase-token>/install.sh | sh

Key features

  • Auto-detection — identifies Node, Python, Rust, Go, PHP, static sites from project files
  • Dockerfile generation — produces optimised multi-stage Dockerfiles per app type
  • Docker Compose generation — wires app + services + proxy + monitoring
  • Remote service secrets — Vault-backed service/app target secrets are metadata-only when read and isolated to the selected service
  • AI-assisted config — scans project, calls LLM to generate tailored stacker.yml
  • AI troubleshooting — on deploy failure, suggests fixes via AI or deterministic fallback hints
  • Service catalog — 20+ built-in service templates (Postgres, Redis, WordPress, etc.) — add with stacker service add
  • AI service addition — ask stacker ai ask --write "add wordpress" and the AI uses the template catalog
  • Agent controlstacker agent subcommand to manage remote Status Panel agents (health, logs, restart, deploy, proxy) with --json output
  • SSH key management — generate, view, upload, and repair server SSH keys (Vault-backed), with automatic local backup SSH access after cloud deploy
  • Reverse proxy — Traefik (labels), Caddy (Caddyfile), and Nginx Proxy Manager, platform-managed and driven by proxy.domains end-to-end (0.3.2)
  • Container-health alarmstacker monitor watches container health and alerts on problems (terminal, webhook, or pipe), configured via monitoring.alerts (0.3.2)
  • Declarative pipes (IaC) — declare pipes in stacker.yml and reconcile with stacker pipe diff / pipe apply [--prune] (0.3.2)
  • Cloud deployment — Hetzner, DigitalOcean, AWS, Linode, with provider firewall operations and paused/failed install IP retention
  • MCP Server — 85+ tools, including deployment, agent control, config, proxy, firewall, and remote service secret management
  • Marketplace — submit stacks for review, auto-publish on approval, check status from CLI
  • Buyer install — purchase tokens, one-liner install scripts, agent self-registration

2. Stacker Server

The backend platform powering the Stack Builder UI, REST API, deployment orchestration, and MCP server for AI agents.

Setup

cp configuration.yaml.dist configuration.yaml # edit database, vault, AMQP settings
cp access_control.conf.dist access_control.conf
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/stacker
sqlx migrate run
cargo run --bin server # http://127.0.0.1:8000

Key API endpoints

EndpointDescription
POST /projectCreate a project from a stack definition
POST /{id}/deploy/{cloud_id}Deploy to a cloud provider
GET /project/{id}/appsList apps in a project
DELETE /project/{id}/apps/{code}Remove an app from a project
PUT /project/{id}/apps/{code}/envUpdate app environment variables
GET /project/{id}/apps/{code}/secretsList service-scoped secret metadata for an app
PUT /project/{id}/apps/{code}/secrets/{name}Create or update a Vault-backed service secret
PUT /project/{id}/apps/{code}/portsUpdate port mappings
PUT /project/{id}/apps/{code}/domainUpdate domain / SSL settings
GET /server/{id}/secretsList server-scoped secret metadata
PUT /server/{id}/secrets/{name}Create or update a Vault-backed server secret
POST /api/v1/commandsEnqueue a command for the Status Panel agent
POST /api/templatesCreate or update a marketplace template (creator)
POST /api/templates/{id}/submitSubmit template for marketplace review
GET /api/templates/mineList current user's template submissions
GET /api/v1/marketplace/install/{token}Generate install.sh script for buyers
GET /api/v1/marketplace/download/{token}Download stack archive (purchase token validated)
POST /api/v1/marketplace/agents/registerAgent self-registration after install
POST /api/v1/pipes/templatesCreate a reusable pipe template (source→target mapping)
GET /api/v1/pipes/templatesList pipe templates (with optional filters)
POST /api/v1/pipes/instancesCreate a pipe instance for a deployment
GET /api/v1/pipes/instancesList pipe instances by deployment hash
PUT /api/v1/pipes/instances/{id}/statusUpdate pipe instance status (active/paused)

MCP Server

Stacker exposes 52+ Model Context Protocol tools over WebSocket, enabling AI agents (Claude, GPT, etc.) to manage infrastructure programmatically:

  • Project & deployment management
  • Container operations (start, stop, restart, exec)
  • Log analysis & error summaries
  • Vault config read/write
  • Proxy configuration
  • App environment & port management
  • Server resource monitoring
  • Docker Compose generation & preview
  • Agent control (deploy app, remove app, configure proxy, get status)
  • Firewall management (iptables rules via Status Panel or SSH)

Key integrations

  • HashiCorp Vault — secrets and config storage, synced to deployments
  • RabbitMQ — deployment status updates, event-driven orchestration
  • TryDirect User Service — OAuth, marketplace templates, payment validation
  • Marketplace — publish and deploy community stacks

3. Status Panel Agent

A lightweight agent deployed alongside your application on the target server. It runs as a Docker container and communicates with Stacker Server using a pull-only architecture — the agent polls for commands, Stacker never dials out.

How it works

1. UI/API creates a command → POST /api/v1/commands
2. Command stored in DB queue → commands + command_queue tables
3. Agent polls for work → GET /api/v1/agent/commands/wait/{hash}
4. Agent executes locally → Docker API on the host
5. Agent reports result → POST /api/v1/agent/commands/report

All agent requests are HMAC-signed (X-Agent-Signature header) using a token stored in Vault.

Supported commands

CommandDescription
healthCheck container health status (single or all)
logsFetch container logs (stdout/stderr, with limits)
restartRestart a container
deploy_appDeploy or update an app container
remove_appRemove an app container
configure_proxyCreate/update/delete reverse-proxy entries
configure_firewallConfigure iptables firewall rules (add/remove/list/flush)
stacker.execExecute a command inside a running container (with security blocklist)
stacker.server_resourcesCollect server resource metrics (CPU, memory, disk, network)
apply_configPull config from Vault and apply to a running container
probe_endpointsDiscover API endpoints on containers (OpenAPI, REST, HTML forms, GraphQL)
activate_pipeActivate a pipe instance — start polling/webhook triggers
deactivate_pipeDeactivate a running pipe instance
trigger_pipeOne-shot pipe execution: fetch source data → map fields → post to target

Agent registration

# Agent self-registers on first boot (no auth required)
POST /api/v1/agent/register
{ "deployment_hash": "abc123", "capabilities": [...], "system_info": {...} }
→ { "agent_id": "...", "agent_token": "..." }

Token rotation

cargo run --bin console -- Agent rotate-token \
--deployment-hash <hash> \
--new-token <NEW_TOKEN>

Database migrations

sqlx migrate run # apply
sqlx migrate revert # rollback

Testing

cargo test# all tests (772+ unit, 69 security integration)
cargo test user_service_client # User Service connector
cargo test marketplace_webhook # Marketplace webhook flows
cargo test deployment_validator # Deployment validation
cargo test --test security_cli # CLI endpoint IDOR security tests
SQLX_OFFLINE=true cargo test --lib -- proxy_domains 2>&1| tail -10

Kata Containers (Hardware Isolation)

Stacker supports Kata Containers as an alternative runtime, providing VM-level isolation for each container using hardware virtualization (KVM).

KVM requirement — Kata needs nested or bare-metal KVM. Hetzner dedicated-CPU servers (CCX line) expose /dev/kvm out of the box, making them an ideal deployment target.

stacker deploy --runtime kata # deploy the current stack with Kata isolation
stacker agent deploy-app --runtime kata # deploy a single app container with Kata

See docs/kata/ for the full setup guide, network constraints, and monitoring reference. Automated provisioning (Ansible + Terraform for Hetzner CCX) is available via the TFA infrastructure toolkit.


Documentation


License

MIT

About

Orchestrate dockerized apps from cli, control, monitor, install apps on own servers and in the cloud

Topics

Resources

Security policy

Stars

6 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1,990 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DiscordVersionLicense



Build, deploy, and manage containerised applications with a single config file.


Deploying Directus (Node + Postgres) to an existing server with Stacker

Real deploys, one command each. See stacker-project-examples.

More demos — n8n · Gotify

n8n (workflow automation, Node + Postgres)

Deploying n8n with Stacker

Gotify (push-notification server, single container)

Deploying Gotify with Stacker

Stacker is a platform for turning any project into a deployable Docker stack. Add a stacker.yml to your repo, and Stacker generates Dockerfiles, docker-compose definitions, reverse-proxy configs, and deploys locally or to cloud providers — optionally with AI assistance.

v0.3.0 highlights: generate stacker.yml from any GitHub repo with stacker init --from-github, infra-service healthcheck inference, remote Vault-backed secrets for deployable service/app targets, paused or failed cloud/server installs retain discovered IP addresses, and cloud-provider firewalls can be managed without SSH.

Quick Start

Install the CLI

curl -fsSL https://raw.githubusercontent.com/trydirect/stacker/main/install.sh | bash

Create & deploy a project

cd my-project
stacker init # auto-detects project type, generates stacker.yml
stacker deploy # builds and runs locally via docker compose
stacker status # check running containers

Deploy from any GitHub repo

Generate a stacker.yml from a GitHub repository — no clone required. For the best results (port mappings, env vars, service context inferred from README and source), use --with-ai:

# AI-powered (recommended — reads README, compose, source files)
stacker init --from-github owner/repo --with-ai
# Template-based (project type + Dockerfile detection only)
stacker init -g https://github.com/ArchiveBox/ArchiveBox

With --with-ai, Stacker shallow-clones the repo, then uses an LLM (Ollama by default) to scan project files and generate a context-aware stacker.yml with services, ports, env vars, and healthchecks. Falls back to template detection if the AI provider is unreachable.

When environment variables are in the compose file, .env.example and scripts/generate-secrets.sh are also generated.

AI-powered init (optional)

Stacker can scan your project files and use an LLM to generate a tailored stacker.yml:

# Local AI with Ollama (free, private, default)
stacker init --with-ai
# OpenAI
stacker init --with-ai --ai-provider openai --ai-api-key sk-...
# Anthropic (key from env)export ANTHROPIC_API_KEY=sk-ant-...
stacker init --with-ai --ai-provider anthropic

If the AI provider is unreachable, Stacker falls back to template-based generation automatically.

When the project looks like a simple HTML or Next.js website and the configured Ollama model is qwen2.5-code or qwen2.5-coder, stacker init --with-ai can also bootstrap a website deployment scenario. The bootstrap seeds values from the generated stacker.yml, asks only for the missing deploy inputs, and saves scenario state under .stacker/scenarios/qwen2.5-code/website-deploy/ for later continuation with stacker ai.

AI deployment workflows

For the canonical AI/MCP deployment flow — inspect state, explain topology or env provenance, preview a plan, apply it safely, and recover with events or rollback — see AI deployment workflows.

For the qwen-specific website scenario flow, including --scenario and --step continuation, see the same guide.


stacker.yml example

name: my-appapp:
type: nodepath: ./srcports:
- "8080:3000"environment:
NODE_ENV: productionservices:
- name: postgresimage: postgres:16environment:
POSTGRES_DB: myappPOSTGRES_PASSWORD: ${DB_PASSWORD}proxy:
type: nginxauto_detect: truedomains:
- domain: app.example.comssl: autoupstream: app:3000deploy:
target: local # or: cloud, serverai:
enabled: trueprovider: ollamamodel: llama3monitoring:
status_panel: truehealthcheck:
endpoint: /healthinterval: 30salerts: # container-down alarm for `stacker monitor` (0.3.2)interval: 30target:
terminal: true # or: { url: "https://ntfy.example.com/alerts" }

Full schema reference: docs/STACKER_YML_REFERENCE.md


Three components

ComponentWhat it doesBinary
Stacker CLIDeveloper tool — init, deploy, monitor from the terminalstacker-cli
Stacker ServerREST API + Stack Builder UI + deployment orchestration + MCP Serverserver
Status Panel AgentDeployed alongside your app on the target server — executes commands, streams logs, reports health(separate repo)
┌──────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ Stacker CLI │────────►│ Stacker Server │────────►│ Status Panel Agent │
│ │ REST │ │ queue │ (on target server) │
│ stacker.yml │ API │ Stack Builder UI│ pull │ │
│ init/deploy │ │ 85+ MCP tools │◄────────│ health / logs / │
│ status/logs │ │ Vault · AMQP │ HMAC │ restart / exec / │
└──────────────┘ └──────────────────┘ │ deploy_app / proxy │
│ └─────────────────────┘
▼
Terraform + Ansible ──► Cloud
(Hetzner, DO, AWS, Linode)

1. Stacker CLI

The end-user tool. No server required for local deploys.

Commands

CommandDescription
stacker initDetect project type, generate stacker.yml + .stacker/ artifacts
stacker deployBuild & deploy the stack (local, cloud, or server). Cloud deploys also install a local SSH backup key when possible. --runtime kata|runc selects container runtime
stacker statusShow running containers and health
stacker logsView container logs (--follow, --service, --tail)
stacker deployment state / stacker deployment statusShow canonical deployment state (defaults to latest; --pinned uses stacker.yml hash)
stacker deployment eventsShow structured deployment events (--pinned uses stacker.yml hash)
stacker deployment rollbackPreview or apply a deployment rollback
stacker secretsManage local .env secrets or remote Vault-backed service / server secrets
stacker list deployments / stacker deployments / stacker psList deployments on the Stacker server
stacker list servers / stacker serversList saved servers
stacker list clouds / stacker clouds / stacker keys / stacker cloud keysList saved cloud credentials
stacker list ssh-keys / stacker ssh-keysList per-server SSH key status
stacker destroyTear down the deployed stack
stacker config validateValidate stacker.yml syntax
stacker config showShow resolved configuration
stacker config examplePrint a full commented reference
stacker config setup cloudGuided cloud deployment setup
stacker config setup aiConfigure AI provider, endpoint, model, and tasks
stacker ai ask "question"Ask the AI about your stack
stacker proxy addAdd a reverse-proxy domain entry
stacker proxy detectAuto-detect existing reverse-proxy containers
stacker cloud firewall addOpen cloud-provider firewall ports without SSH, for example --public-ports 8000/tcp on Hetzner
stacker cloud firewall removeRemove Stacker-managed cloud-provider firewall rules
stacker cloud firewall listList cloud-provider firewall rules for a server
stacker ssh-key generateGenerate a new SSH key pair for a server (Vault-backed)
stacker ssh-key showDisplay the public SSH key for a server
stacker ssh-key uploadUpload an existing SSH key pair for a server
stacker ssh-key injectRepair Vault-key trust by using an already-working private key to update authorized_keys
stacker service addAdd a service from the template catalog to stacker.yml
stacker service listList available service templates (20+ built-in)
stacker agent healthCheck Status Panel agent connectivity and health
stacker agent statusDisplay agent snapshot — containers, versions, uptime
stacker agent list apps / stacker agent appsList apps for the target deployment
stacker agent list containers / stacker agent containersList containers on the target server
stacker agent logs <app>Retrieve container logs from the remote agent
stacker agent restart <app>Restart a container via the agent
stacker agent deploy-appDeploy or update an app container on the target server. --runtime kata|runc selects container runtime; --env <name> selects the deploy environment/profile
stacker agent remove-appRemove an app container (with optional volume/image cleanup)
stacker agent configure-proxyConfigure Nginx Proxy Manager via the agent; use --no-ssl for plain HTTP hosts (credentials are resolved from Vault and are auto-seeded for managed Status Panel + NPM deploys)
stacker agent configure-firewallConfigure guest OS firewall rules via the Status Panel agent; use stacker cloud firewall for provider firewalls
stacker agent historyShow recent command execution history
stacker agent execExecute a raw agent command with JSON parameters
stacker pipe scanDiscover local endpoints/resources from running containers (when target is local)
stacker pipe scan --containers [filter]Discover local endpoints/resources for matching containers
stacker pipe scan --app <app>Probe a remote app for API endpoints
stacker pipe create <src> <tgt>Create a data pipe between two containers (interactive; or non-interactive with --source-endpoint/--target-endpoint/--name — added in 0.3.2). --retry/--on-failure/--on-success attach a retry policy + lifecycle handlers
stacker pipe diffCompare the declared pipes: block against deployed pipes (added in 0.3.2)
stacker pipe applyReconcile declared pipes into the deployment; --prune removes orphans, --dry-run previews (added in 0.3.2)
stacker pipe listList pipe instances for the current deployment
stacker pipe activate <id>Activate a pipe (start listening for triggers)
stacker pipe deactivate <id>Pause an active pipe
stacker pipe trigger <id>One-shot pipe execution with optional input data
stacker pipe deploy <id>Promote a local pipe to a remote deployment
stacker pipe history <id>View execution history for a pipe
stacker pipe replay <exec-id>Re-run a previous pipe execution
stacker monitorWatch container health and alert on problems (added in 0.3.2); --once for a single check (cron-friendly). Configure via monitoring.alerts in stacker.yml
stacker target [local|cloud|server]Switch deployment target mode
stacker env [local|dev|prod]Show or persist the active deploy environment/profile used by app-only updates
stacker whoamiShow the active login, subscription plan, and current project deployment context
stacker submitPackage current stack and submit to marketplace for review
stacker marketplace statusCheck submission status for your marketplace templates
stacker marketplace logs <name>Show review comments and history for a submission
stacker loginAuthenticate with the TryDirect platform
stacker updateCheck for updates and self-update

Deploy targets

stacker deploy --target local# docker compose up (default)
stacker deploy --target cloud # Terraform + Ansible → cloud provider
stacker deploy --target server # deploy to existing server via SSH
stacker deploy --dry-run # preview generated files without executing

After a successful cloud deploy, Stacker creates or reuses a local backup key at ~/.config/stacker/ssh/server-<id>_ed25519 (or under $XDG_CONFIG_HOME) and authorizes its public key on the server when possible. The CLI prints a normal ssh -i ... command, while the Vault private key remains server-side.

When a cloud/server deploy includes deploy.registry credentials (or the equivalent STACKER_DOCKER_* environment variables), Stacker stores that registry auth securely and reuses it for later Status-managed image refreshes such as stacker agent deploy-app. This keeps private-image redeploys working without depending on host-level docker login state or mounting /root/.docker into the agent container.

Secrets workflow

# Local project .env secret
stacker secrets set DB_PASSWORD=supersecret
# Discover valid remote deployable service/app targets first
stacker secrets apps
# Remote service secret used at render/deploy time for one target
stacker secrets set S3_SECRET_KEY \
--scope service \
--service uploader \
--body supersecret
# Remote server secret for future host-level consumers
stacker secrets set NPM_TOKEN \
--scope server \
--server-id 42 \
--body-file .npm-token
# Remote reads are metadata-only in v1
stacker secrets list --scope service --service uploader --json
stacker secrets get S3_SECRET_KEY --scope service --service uploader --json
# Push stored remote secrets into the target's runtime env
stacker secrets push --service uploader
stacker secrets push --service uploader --env prod
# Aliases: stacker secrets deploy --service uploader# stacker secrets apply --service uploader
  • Local mode remains the default and reads/writes the project .env file.
  • Remote mode is enabled only with --scope service or --scope server.
  • Service-scoped remote commands default --project from stacker.yml -> project.identity; --project still overrides it explicitly.
  • Service-scoped secrets target deployable service/app codes listed by stacker secrets apps, including registered stacker.yml services and supported image-backed Compose services after a deploy/update sync.
  • Service-scoped secrets are merged only into the matching rendered service/app env at deploy time.
  • stacker secrets push --service <target> applies stored service secrets to the remote runtime env without changing secret values. Use --env <name> for a one-off environment selection, or stacker env <name> to persist the active environment/profile for future app-only updates. Use --force only when the remote env drift check reports an out-of-band change.
  • Remote get and list do not return plaintext values in v1.
  • MCP env inspection now exposes explicit secure metadata for Vault-backed variables: get_app_env_vars keeps the redacted environment_variables object for compatibility and also returns environment_entries[] with secure, redacted, and source fields.

Remote deploys render runtime env into one canonical host file: /home/trydirect/project/.env. Generated compose uses env_file: .env, so the path is relative to the deployed compose file. To inspect paths and contributing layers without exposing values, run:

stacker config show --resolved

For app-only updates, stacker agent deploy-app <target> resolves the deploy environment from --env, then .stacker/active-env, then stacker.yml. If <target>/docker/<env>/compose.yml exists, Stacker uses the app-local service definition for that target but merges it into the full project-level compose file before sending it to the agent. This prevents app-only updates from replacing the remote stack compose with a single-service compose file. Any app-local .env referenced by that compose file is uploaded in the config bundle, and Stacker appends the Vault-rendered service secrets for the same target to that file before the agent writes it on the server. Repeated app-only updates replace the prior # stacker-render ... block in that file instead of stacking duplicate rendered secret sections.

Marketplace workflow (for stack developers)

stacker deploy --target local# 1. test locally
stacker deploy --target server # 2. test on remote server
stacker submit # 3. submit for marketplace review
stacker marketplace status # 4. check review status# Stack is auto-published once approved by the review team

Marketplace install (for buyers)

# Option A: Deploy from your laptop to a remote server
stacker deploy my-stack --target server --host 1.2.3.4
# Option B: Run directly on the target server (one-liner)
curl -sL https://marketplace.try.direct/<purchase-token>/install.sh | sh

Key features

  • Auto-detection — identifies Node, Python, Rust, Go, PHP, static sites from project files
  • Dockerfile generation — produces optimised multi-stage Dockerfiles per app type
  • Docker Compose generation — wires app + services + proxy + monitoring
  • Remote service secrets — Vault-backed service/app target secrets are metadata-only when read and isolated to the selected service
  • AI-assisted config — scans project, calls LLM to generate tailored stacker.yml
  • AI troubleshooting — on deploy failure, suggests fixes via AI or deterministic fallback hints
  • Service catalog — 20+ built-in service templates (Postgres, Redis, WordPress, etc.) — add with stacker service add
  • AI service addition — ask stacker ai ask --write "add wordpress" and the AI uses the template catalog
  • Agent controlstacker agent subcommand to manage remote Status Panel agents (health, logs, restart, deploy, proxy) with --json output
  • SSH key management — generate, view, upload, and repair server SSH keys (Vault-backed), with automatic local backup SSH access after cloud deploy
  • Reverse proxy — Traefik (labels), Caddy (Caddyfile), and Nginx Proxy Manager, platform-managed and driven by proxy.domains end-to-end (0.3.2)
  • Container-health alarmstacker monitor watches container health and alerts on problems (terminal, webhook, or pipe), configured via monitoring.alerts (0.3.2)
  • Declarative pipes (IaC) — declare pipes in stacker.yml and reconcile with stacker pipe diff / pipe apply [--prune] (0.3.2)
  • Cloud deployment — Hetzner, DigitalOcean, AWS, Linode, with provider firewall operations and paused/failed install IP retention
  • MCP Server — 85+ tools, including deployment, agent control, config, proxy, firewall, and remote service secret management
  • Marketplace — submit stacks for review, auto-publish on approval, check status from CLI
  • Buyer install — purchase tokens, one-liner install scripts, agent self-registration

2. Stacker Server

The backend platform powering the Stack Builder UI, REST API, deployment orchestration, and MCP server for AI agents.

Setup

cp configuration.yaml.dist configuration.yaml # edit database, vault, AMQP settings
cp access_control.conf.dist access_control.conf
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/stacker
sqlx migrate run
cargo run --bin server # http://127.0.0.1:8000

Key API endpoints

EndpointDescription
POST /projectCreate a project from a stack definition
POST /{id}/deploy/{cloud_id}Deploy to a cloud provider
GET /project/{id}/appsList apps in a project
DELETE /project/{id}/apps/{code}Remove an app from a project
PUT /project/{id}/apps/{code}/envUpdate app environment variables
GET /project/{id}/apps/{code}/secretsList service-scoped secret metadata for an app
PUT /project/{id}/apps/{code}/secrets/{name}Create or update a Vault-backed service secret
PUT /project/{id}/apps/{code}/portsUpdate port mappings
PUT /project/{id}/apps/{code}/domainUpdate domain / SSL settings
GET /server/{id}/secretsList server-scoped secret metadata
PUT /server/{id}/secrets/{name}Create or update a Vault-backed server secret
POST /api/v1/commandsEnqueue a command for the Status Panel agent
POST /api/templatesCreate or update a marketplace template (creator)
POST /api/templates/{id}/submitSubmit template for marketplace review
GET /api/templates/mineList current user's template submissions
GET /api/v1/marketplace/install/{token}Generate install.sh script for buyers
GET /api/v1/marketplace/download/{token}Download stack archive (purchase token validated)
POST /api/v1/marketplace/agents/registerAgent self-registration after install
POST /api/v1/pipes/templatesCreate a reusable pipe template (source→target mapping)
GET /api/v1/pipes/templatesList pipe templates (with optional filters)
POST /api/v1/pipes/instancesCreate a pipe instance for a deployment
GET /api/v1/pipes/instancesList pipe instances by deployment hash
PUT /api/v1/pipes/instances/{id}/statusUpdate pipe instance status (active/paused)

MCP Server

Stacker exposes 52+ Model Context Protocol tools over WebSocket, enabling AI agents (Claude, GPT, etc.) to manage infrastructure programmatically:

  • Project & deployment management
  • Container operations (start, stop, restart, exec)
  • Log analysis & error summaries
  • Vault config read/write
  • Proxy configuration
  • App environment & port management
  • Server resource monitoring
  • Docker Compose generation & preview
  • Agent control (deploy app, remove app, configure proxy, get status)
  • Firewall management (iptables rules via Status Panel or SSH)

Key integrations

  • HashiCorp Vault — secrets and config storage, synced to deployments
  • RabbitMQ — deployment status updates, event-driven orchestration
  • TryDirect User Service — OAuth, marketplace templates, payment validation
  • Marketplace — publish and deploy community stacks

3. Status Panel Agent

A lightweight agent deployed alongside your application on the target server. It runs as a Docker container and communicates with Stacker Server using a pull-only architecture — the agent polls for commands, Stacker never dials out.

How it works

1. UI/API creates a command → POST /api/v1/commands
2. Command stored in DB queue → commands + command_queue tables
3. Agent polls for work → GET /api/v1/agent/commands/wait/{hash}
4. Agent executes locally → Docker API on the host
5. Agent reports result → POST /api/v1/agent/commands/report

All agent requests are HMAC-signed (X-Agent-Signature header) using a token stored in Vault.

Supported commands

CommandDescription
healthCheck container health status (single or all)
logsFetch container logs (stdout/stderr, with limits)
restartRestart a container
deploy_appDeploy or update an app container
remove_appRemove an app container
configure_proxyCreate/update/delete reverse-proxy entries
configure_firewallConfigure iptables firewall rules (add/remove/list/flush)
stacker.execExecute a command inside a running container (with security blocklist)
stacker.server_resourcesCollect server resource metrics (CPU, memory, disk, network)
apply_configPull config from Vault and apply to a running container
probe_endpointsDiscover API endpoints on containers (OpenAPI, REST, HTML forms, GraphQL)
activate_pipeActivate a pipe instance — start polling/webhook triggers
deactivate_pipeDeactivate a running pipe instance
trigger_pipeOne-shot pipe execution: fetch source data → map fields → post to target

Agent registration

# Agent self-registers on first boot (no auth required)
POST /api/v1/agent/register
{ "deployment_hash": "abc123", "capabilities": [...], "system_info": {...} }
→ { "agent_id": "...", "agent_token": "..." }

Token rotation

cargo run --bin console -- Agent rotate-token \
--deployment-hash <hash> \
--new-token <NEW_TOKEN>

Database migrations

sqlx migrate run # apply
sqlx migrate revert # rollback

Testing

cargo test# all tests (772+ unit, 69 security integration)
cargo test user_service_client # User Service connector
cargo test marketplace_webhook # Marketplace webhook flows
cargo test deployment_validator # Deployment validation
cargo test --test security_cli # CLI endpoint IDOR security tests
SQLX_OFFLINE=true cargo test --lib -- proxy_domains 2>&1| tail -10

Kata Containers (Hardware Isolation)

Stacker supports Kata Containers as an alternative runtime, providing VM-level isolation for each container using hardware virtualization (KVM).

KVM requirement — Kata needs nested or bare-metal KVM. Hetzner dedicated-CPU servers (CCX line) expose /dev/kvm out of the box, making them an ideal deployment target.

stacker deploy --runtime kata # deploy the current stack with Kata isolation
stacker agent deploy-app --runtime kata # deploy a single app container with Kata

See docs/kata/ for the full setup guide, network constraints, and monitoring reference. Automated provisioning (Ansible + Terraform for Hetzner CCX) is available via the TFA infrastructure toolkit.


Documentation


License

MIT

About

Orchestrate dockerized apps from cli, control, monitor, install apps on own servers and in the cloud

Topics

Resources

Security policy

Stars

6 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1,990 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DiscordVersionLicense



Build, deploy, and manage containerised applications with a single config file.


Deploying Directus (Node + Postgres) to an existing server with Stacker

Real deploys, one command each. See stacker-project-examples.

More demos — n8n · Gotify

n8n (workflow automation, Node + Postgres)

Deploying n8n with Stacker

Gotify (push-notification server, single container)

Deploying Gotify with Stacker

Stacker is a platform for turning any project into a deployable Docker stack. Add a stacker.yml to your repo, and Stacker generates Dockerfiles, docker-compose definitions, reverse-proxy configs, and deploys locally or to cloud providers — optionally with AI assistance.

v0.3.0 highlights: generate stacker.yml from any GitHub repo with stacker init --from-github, infra-service healthcheck inference, remote Vault-backed secrets for deployable service/app targets, paused or failed cloud/server installs retain discovered IP addresses, and cloud-provider firewalls can be managed without SSH.

Quick Start

Install the CLI

curl -fsSL https://raw.githubusercontent.com/trydirect/stacker/main/install.sh | bash

Create & deploy a project

cd my-project
stacker init # auto-detects project type, generates stacker.yml
stacker deploy # builds and runs locally via docker compose
stacker status # check running containers

Deploy from any GitHub repo

Generate a stacker.yml from a GitHub repository — no clone required. For the best results (port mappings, env vars, service context inferred from README and source), use --with-ai:

# AI-powered (recommended — reads README, compose, source files)
stacker init --from-github owner/repo --with-ai
# Template-based (project type + Dockerfile detection only)
stacker init -g https://github.com/ArchiveBox/ArchiveBox

With --with-ai, Stacker shallow-clones the repo, then uses an LLM (Ollama by default) to scan project files and generate a context-aware stacker.yml with services, ports, env vars, and healthchecks. Falls back to template detection if the AI provider is unreachable.

When environment variables are in the compose file, .env.example and scripts/generate-secrets.sh are also generated.

AI-powered init (optional)

Stacker can scan your project files and use an LLM to generate a tailored stacker.yml:

# Local AI with Ollama (free, private, default)
stacker init --with-ai
# OpenAI
stacker init --with-ai --ai-provider openai --ai-api-key sk-...
# Anthropic (key from env)export ANTHROPIC_API_KEY=sk-ant-...
stacker init --with-ai --ai-provider anthropic

If the AI provider is unreachable, Stacker falls back to template-based generation automatically.

When the project looks like a simple HTML or Next.js website and the configured Ollama model is qwen2.5-code or qwen2.5-coder, stacker init --with-ai can also bootstrap a website deployment scenario. The bootstrap seeds values from the generated stacker.yml, asks only for the missing deploy inputs, and saves scenario state under .stacker/scenarios/qwen2.5-code/website-deploy/ for later continuation with stacker ai.

AI deployment workflows

For the canonical AI/MCP deployment flow — inspect state, explain topology or env provenance, preview a plan, apply it safely, and recover with events or rollback — see AI deployment workflows.

For the qwen-specific website scenario flow, including --scenario and --step continuation, see the same guide.


stacker.yml example

name: my-appapp:
type: nodepath: ./srcports:
- "8080:3000"environment:
NODE_ENV: productionservices:
- name: postgresimage: postgres:16environment:
POSTGRES_DB: myappPOSTGRES_PASSWORD: ${DB_PASSWORD}proxy:
type: nginxauto_detect: truedomains:
- domain: app.example.comssl: autoupstream: app:3000deploy:
target: local # or: cloud, serverai:
enabled: trueprovider: ollamamodel: llama3monitoring:
status_panel: truehealthcheck:
endpoint: /healthinterval: 30salerts: # container-down alarm for `stacker monitor` (0.3.2)interval: 30target:
terminal: true # or: { url: "https://ntfy.example.com/alerts" }

Full schema reference: docs/STACKER_YML_REFERENCE.md


Three components

ComponentWhat it doesBinary
Stacker CLIDeveloper tool — init, deploy, monitor from the terminalstacker-cli
Stacker ServerREST API + Stack Builder UI + deployment orchestration + MCP Serverserver
Status Panel AgentDeployed alongside your app on the target server — executes commands, streams logs, reports health(separate repo)
┌──────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ Stacker CLI │────────►│ Stacker Server │────────►│ Status Panel Agent │
│ │ REST │ │ queue │ (on target server) │
│ stacker.yml │ API │ Stack Builder UI│ pull │ │
│ init/deploy │ │ 85+ MCP tools │◄────────│ health / logs / │
│ status/logs │ │ Vault · AMQP │ HMAC │ restart / exec / │
└──────────────┘ └──────────────────┘ │ deploy_app / proxy │
│ └─────────────────────┘
▼
Terraform + Ansible ──► Cloud
(Hetzner, DO, AWS, Linode)

1. Stacker CLI

The end-user tool. No server required for local deploys.

Commands

CommandDescription
stacker initDetect project type, generate stacker.yml + .stacker/ artifacts
stacker deployBuild & deploy the stack (local, cloud, or server). Cloud deploys also install a local SSH backup key when possible. --runtime kata|runc selects container runtime
stacker statusShow running containers and health
stacker logsView container logs (--follow, --service, --tail)
stacker deployment state / stacker deployment statusShow canonical deployment state (defaults to latest; --pinned uses stacker.yml hash)
stacker deployment eventsShow structured deployment events (--pinned uses stacker.yml hash)
stacker deployment rollbackPreview or apply a deployment rollback
stacker secretsManage local .env secrets or remote Vault-backed service / server secrets
stacker list deployments / stacker deployments / stacker psList deployments on the Stacker server
stacker list servers / stacker serversList saved servers
stacker list clouds / stacker clouds / stacker keys / stacker cloud keysList saved cloud credentials
stacker list ssh-keys / stacker ssh-keysList per-server SSH key status
stacker destroyTear down the deployed stack
stacker config validateValidate stacker.yml syntax
stacker config showShow resolved configuration
stacker config examplePrint a full commented reference
stacker config setup cloudGuided cloud deployment setup
stacker config setup aiConfigure AI provider, endpoint, model, and tasks
stacker ai ask "question"Ask the AI about your stack
stacker proxy addAdd a reverse-proxy domain entry
stacker proxy detectAuto-detect existing reverse-proxy containers
stacker cloud firewall addOpen cloud-provider firewall ports without SSH, for example --public-ports 8000/tcp on Hetzner
stacker cloud firewall removeRemove Stacker-managed cloud-provider firewall rules
stacker cloud firewall listList cloud-provider firewall rules for a server
stacker ssh-key generateGenerate a new SSH key pair for a server (Vault-backed)
stacker ssh-key showDisplay the public SSH key for a server
stacker ssh-key uploadUpload an existing SSH key pair for a server
stacker ssh-key injectRepair Vault-key trust by using an already-working private key to update authorized_keys
stacker service addAdd a service from the template catalog to stacker.yml
stacker service listList available service templates (20+ built-in)
stacker agent healthCheck Status Panel agent connectivity and health
stacker agent statusDisplay agent snapshot — containers, versions, uptime
stacker agent list apps / stacker agent appsList apps for the target deployment
stacker agent list containers / stacker agent containersList containers on the target server
stacker agent logs <app>Retrieve container logs from the remote agent
stacker agent restart <app>Restart a container via the agent
stacker agent deploy-appDeploy or update an app container on the target server. --runtime kata|runc selects container runtime; --env <name> selects the deploy environment/profile
stacker agent remove-appRemove an app container (with optional volume/image cleanup)
stacker agent configure-proxyConfigure Nginx Proxy Manager via the agent; use --no-ssl for plain HTTP hosts (credentials are resolved from Vault and are auto-seeded for managed Status Panel + NPM deploys)
stacker agent configure-firewallConfigure guest OS firewall rules via the Status Panel agent; use stacker cloud firewall for provider firewalls
stacker agent historyShow recent command execution history
stacker agent execExecute a raw agent command with JSON parameters
stacker pipe scanDiscover local endpoints/resources from running containers (when target is local)
stacker pipe scan --containers [filter]Discover local endpoints/resources for matching containers
stacker pipe scan --app <app>Probe a remote app for API endpoints
stacker pipe create <src> <tgt>Create a data pipe between two containers (interactive; or non-interactive with --source-endpoint/--target-endpoint/--name — added in 0.3.2). --retry/--on-failure/--on-success attach a retry policy + lifecycle handlers
stacker pipe diffCompare the declared pipes: block against deployed pipes (added in 0.3.2)
stacker pipe applyReconcile declared pipes into the deployment; --prune removes orphans, --dry-run previews (added in 0.3.2)
stacker pipe listList pipe instances for the current deployment
stacker pipe activate <id>Activate a pipe (start listening for triggers)
stacker pipe deactivate <id>Pause an active pipe
stacker pipe trigger <id>One-shot pipe execution with optional input data
stacker pipe deploy <id>Promote a local pipe to a remote deployment
stacker pipe history <id>View execution history for a pipe
stacker pipe replay <exec-id>Re-run a previous pipe execution
stacker monitorWatch container health and alert on problems (added in 0.3.2); --once for a single check (cron-friendly). Configure via monitoring.alerts in stacker.yml
stacker target [local|cloud|server]Switch deployment target mode
stacker env [local|dev|prod]Show or persist the active deploy environment/profile used by app-only updates
stacker whoamiShow the active login, subscription plan, and current project deployment context
stacker submitPackage current stack and submit to marketplace for review
stacker marketplace statusCheck submission status for your marketplace templates
stacker marketplace logs <name>Show review comments and history for a submission
stacker loginAuthenticate with the TryDirect platform
stacker updateCheck for updates and self-update

Deploy targets

stacker deploy --target local# docker compose up (default)
stacker deploy --target cloud # Terraform + Ansible → cloud provider
stacker deploy --target server # deploy to existing server via SSH
stacker deploy --dry-run # preview generated files without executing

After a successful cloud deploy, Stacker creates or reuses a local backup key at ~/.config/stacker/ssh/server-<id>_ed25519 (or under $XDG_CONFIG_HOME) and authorizes its public key on the server when possible. The CLI prints a normal ssh -i ... command, while the Vault private key remains server-side.

When a cloud/server deploy includes deploy.registry credentials (or the equivalent STACKER_DOCKER_* environment variables), Stacker stores that registry auth securely and reuses it for later Status-managed image refreshes such as stacker agent deploy-app. This keeps private-image redeploys working without depending on host-level docker login state or mounting /root/.docker into the agent container.

Secrets workflow

# Local project .env secret
stacker secrets set DB_PASSWORD=supersecret
# Discover valid remote deployable service/app targets first
stacker secrets apps
# Remote service secret used at render/deploy time for one target
stacker secrets set S3_SECRET_KEY \
--scope service \
--service uploader \
--body supersecret
# Remote server secret for future host-level consumers
stacker secrets set NPM_TOKEN \
--scope server \
--server-id 42 \
--body-file .npm-token
# Remote reads are metadata-only in v1
stacker secrets list --scope service --service uploader --json
stacker secrets get S3_SECRET_KEY --scope service --service uploader --json
# Push stored remote secrets into the target's runtime env
stacker secrets push --service uploader
stacker secrets push --service uploader --env prod
# Aliases: stacker secrets deploy --service uploader# stacker secrets apply --service uploader
  • Local mode remains the default and reads/writes the project .env file.
  • Remote mode is enabled only with --scope service or --scope server.
  • Service-scoped remote commands default --project from stacker.yml -> project.identity; --project still overrides it explicitly.
  • Service-scoped secrets target deployable service/app codes listed by stacker secrets apps, including registered stacker.yml services and supported image-backed Compose services after a deploy/update sync.
  • Service-scoped secrets are merged only into the matching rendered service/app env at deploy time.
  • stacker secrets push --service <target> applies stored service secrets to the remote runtime env without changing secret values. Use --env <name> for a one-off environment selection, or stacker env <name> to persist the active environment/profile for future app-only updates. Use --force only when the remote env drift check reports an out-of-band change.
  • Remote get and list do not return plaintext values in v1.
  • MCP env inspection now exposes explicit secure metadata for Vault-backed variables: get_app_env_vars keeps the redacted environment_variables object for compatibility and also returns environment_entries[] with secure, redacted, and source fields.

Remote deploys render runtime env into one canonical host file: /home/trydirect/project/.env. Generated compose uses env_file: .env, so the path is relative to the deployed compose file. To inspect paths and contributing layers without exposing values, run:

stacker config show --resolved

For app-only updates, stacker agent deploy-app <target> resolves the deploy environment from --env, then .stacker/active-env, then stacker.yml. If <target>/docker/<env>/compose.yml exists, Stacker uses the app-local service definition for that target but merges it into the full project-level compose file before sending it to the agent. This prevents app-only updates from replacing the remote stack compose with a single-service compose file. Any app-local .env referenced by that compose file is uploaded in the config bundle, and Stacker appends the Vault-rendered service secrets for the same target to that file before the agent writes it on the server. Repeated app-only updates replace the prior # stacker-render ... block in that file instead of stacking duplicate rendered secret sections.

Marketplace workflow (for stack developers)

stacker deploy --target local# 1. test locally
stacker deploy --target server # 2. test on remote server
stacker submit # 3. submit for marketplace review
stacker marketplace status # 4. check review status# Stack is auto-published once approved by the review team

Marketplace install (for buyers)

# Option A: Deploy from your laptop to a remote server
stacker deploy my-stack --target server --host 1.2.3.4
# Option B: Run directly on the target server (one-liner)
curl -sL https://marketplace.try.direct/<purchase-token>/install.sh | sh

Key features

  • Auto-detection — identifies Node, Python, Rust, Go, PHP, static sites from project files
  • Dockerfile generation — produces optimised multi-stage Dockerfiles per app type
  • Docker Compose generation — wires app + services + proxy + monitoring
  • Remote service secrets — Vault-backed service/app target secrets are metadata-only when read and isolated to the selected service
  • AI-assisted config — scans project, calls LLM to generate tailored stacker.yml
  • AI troubleshooting — on deploy failure, suggests fixes via AI or deterministic fallback hints
  • Service catalog — 20+ built-in service templates (Postgres, Redis, WordPress, etc.) — add with stacker service add
  • AI service addition — ask stacker ai ask --write "add wordpress" and the AI uses the template catalog
  • Agent controlstacker agent subcommand to manage remote Status Panel agents (health, logs, restart, deploy, proxy) with --json output
  • SSH key management — generate, view, upload, and repair server SSH keys (Vault-backed), with automatic local backup SSH access after cloud deploy
  • Reverse proxy — Traefik (labels), Caddy (Caddyfile), and Nginx Proxy Manager, platform-managed and driven by proxy.domains end-to-end (0.3.2)
  • Container-health alarmstacker monitor watches container health and alerts on problems (terminal, webhook, or pipe), configured via monitoring.alerts (0.3.2)
  • Declarative pipes (IaC) — declare pipes in stacker.yml and reconcile with stacker pipe diff / pipe apply [--prune] (0.3.2)
  • Cloud deployment — Hetzner, DigitalOcean, AWS, Linode, with provider firewall operations and paused/failed install IP retention
  • MCP Server — 85+ tools, including deployment, agent control, config, proxy, firewall, and remote service secret management
  • Marketplace — submit stacks for review, auto-publish on approval, check status from CLI
  • Buyer install — purchase tokens, one-liner install scripts, agent self-registration

2. Stacker Server

The backend platform powering the Stack Builder UI, REST API, deployment orchestration, and MCP server for AI agents.

Setup

cp configuration.yaml.dist configuration.yaml # edit database, vault, AMQP settings
cp access_control.conf.dist access_control.conf
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/stacker
sqlx migrate run
cargo run --bin server # http://127.0.0.1:8000

Key API endpoints

EndpointDescription
POST /projectCreate a project from a stack definition
POST /{id}/deploy/{cloud_id}Deploy to a cloud provider
GET /project/{id}/appsList apps in a project
DELETE /project/{id}/apps/{code}Remove an app from a project
PUT /project/{id}/apps/{code}/envUpdate app environment variables
GET /project/{id}/apps/{code}/secretsList service-scoped secret metadata for an app
PUT /project/{id}/apps/{code}/secrets/{name}Create or update a Vault-backed service secret
PUT /project/{id}/apps/{code}/portsUpdate port mappings
PUT /project/{id}/apps/{code}/domainUpdate domain / SSL settings
GET /server/{id}/secretsList server-scoped secret metadata
PUT /server/{id}/secrets/{name}Create or update a Vault-backed server secret
POST /api/v1/commandsEnqueue a command for the Status Panel agent
POST /api/templatesCreate or update a marketplace template (creator)
POST /api/templates/{id}/submitSubmit template for marketplace review
GET /api/templates/mineList current user's template submissions
GET /api/v1/marketplace/install/{token}Generate install.sh script for buyers
GET /api/v1/marketplace/download/{token}Download stack archive (purchase token validated)
POST /api/v1/marketplace/agents/registerAgent self-registration after install
POST /api/v1/pipes/templatesCreate a reusable pipe template (source→target mapping)
GET /api/v1/pipes/templatesList pipe templates (with optional filters)
POST /api/v1/pipes/instancesCreate a pipe instance for a deployment
GET /api/v1/pipes/instancesList pipe instances by deployment hash
PUT /api/v1/pipes/instances/{id}/statusUpdate pipe instance status (active/paused)

MCP Server

Stacker exposes 52+ Model Context Protocol tools over WebSocket, enabling AI agents (Claude, GPT, etc.) to manage infrastructure programmatically:

  • Project & deployment management
  • Container operations (start, stop, restart, exec)
  • Log analysis & error summaries
  • Vault config read/write
  • Proxy configuration
  • App environment & port management
  • Server resource monitoring
  • Docker Compose generation & preview
  • Agent control (deploy app, remove app, configure proxy, get status)
  • Firewall management (iptables rules via Status Panel or SSH)

Key integrations

  • HashiCorp Vault — secrets and config storage, synced to deployments
  • RabbitMQ — deployment status updates, event-driven orchestration
  • TryDirect User Service — OAuth, marketplace templates, payment validation
  • Marketplace — publish and deploy community stacks

3. Status Panel Agent

A lightweight agent deployed alongside your application on the target server. It runs as a Docker container and communicates with Stacker Server using a pull-only architecture — the agent polls for commands, Stacker never dials out.

How it works

1. UI/API creates a command → POST /api/v1/commands
2. Command stored in DB queue → commands + command_queue tables
3. Agent polls for work → GET /api/v1/agent/commands/wait/{hash}
4. Agent executes locally → Docker API on the host
5. Agent reports result → POST /api/v1/agent/commands/report

All agent requests are HMAC-signed (X-Agent-Signature header) using a token stored in Vault.

Supported commands

CommandDescription
healthCheck container health status (single or all)
logsFetch container logs (stdout/stderr, with limits)
restartRestart a container
deploy_appDeploy or update an app container
remove_appRemove an app container
configure_proxyCreate/update/delete reverse-proxy entries
configure_firewallConfigure iptables firewall rules (add/remove/list/flush)
stacker.execExecute a command inside a running container (with security blocklist)
stacker.server_resourcesCollect server resource metrics (CPU, memory, disk, network)
apply_configPull config from Vault and apply to a running container
probe_endpointsDiscover API endpoints on containers (OpenAPI, REST, HTML forms, GraphQL)
activate_pipeActivate a pipe instance — start polling/webhook triggers
deactivate_pipeDeactivate a running pipe instance
trigger_pipeOne-shot pipe execution: fetch source data → map fields → post to target

Agent registration

# Agent self-registers on first boot (no auth required)
POST /api/v1/agent/register
{ "deployment_hash": "abc123", "capabilities": [...], "system_info": {...} }
→ { "agent_id": "...", "agent_token": "..." }

Token rotation

cargo run --bin console -- Agent rotate-token \
--deployment-hash <hash> \
--new-token <NEW_TOKEN>

Database migrations

sqlx migrate run # apply
sqlx migrate revert # rollback

Testing

cargo test# all tests (772+ unit, 69 security integration)
cargo test user_service_client # User Service connector
cargo test marketplace_webhook # Marketplace webhook flows
cargo test deployment_validator # Deployment validation
cargo test --test security_cli # CLI endpoint IDOR security tests
SQLX_OFFLINE=true cargo test --lib -- proxy_domains 2>&1| tail -10

Kata Containers (Hardware Isolation)

Stacker supports Kata Containers as an alternative runtime, providing VM-level isolation for each container using hardware virtualization (KVM).

KVM requirement — Kata needs nested or bare-metal KVM. Hetzner dedicated-CPU servers (CCX line) expose /dev/kvm out of the box, making them an ideal deployment target.

stacker deploy --runtime kata # deploy the current stack with Kata isolation
stacker agent deploy-app --runtime kata # deploy a single app container with Kata

See docs/kata/ for the full setup guide, network constraints, and monitoring reference. Automated provisioning (Ansible + Terraform for Hetzner CCX) is available via the TFA infrastructure toolkit.


Documentation


License

MIT

About

Orchestrate dockerized apps from cli, control, monitor, install apps on own servers and in the cloud

Topics

Resources

Security policy

Stars

6 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

1,990 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DiscordVersionLicense



Build, deploy, and manage containerised applications with a single config file.


Deploying Directus (Node + Postgres) to an existing server with Stacker

Real deploys, one command each. See stacker-project-examples.

More demos — n8n · Gotify

n8n (workflow automation, Node + Postgres)

Deploying n8n with Stacker

Gotify (push-notification server, single container)

Deploying Gotify with Stacker

Stacker is a platform for turning any project into a deployable Docker stack. Add a stacker.yml to your repo, and Stacker generates Dockerfiles, docker-compose definitions, reverse-proxy configs, and deploys locally or to cloud providers — optionally with AI assistance.

v0.3.0 highlights: generate stacker.yml from any GitHub repo with stacker init --from-github, infra-service healthcheck inference, remote Vault-backed secrets for deployable service/app targets, paused or failed cloud/server installs retain discovered IP addresses, and cloud-provider firewalls can be managed without SSH.

Quick Start

Install the CLI

curl -fsSL https://raw.githubusercontent.com/trydirect/stacker/main/install.sh | bash

Create & deploy a project

cd my-project
stacker init # auto-detects project type, generates stacker.yml
stacker deploy # builds and runs locally via docker compose
stacker status # check running containers

Deploy from any GitHub repo

Generate a stacker.yml from a GitHub repository — no clone required. For the best results (port mappings, env vars, service context inferred from README and source), use --with-ai:

# AI-powered (recommended — reads README, compose, source files)
stacker init --from-github owner/repo --with-ai
# Template-based (project type + Dockerfile detection only)
stacker init -g https://github.com/ArchiveBox/ArchiveBox

With --with-ai, Stacker shallow-clones the repo, then uses an LLM (Ollama by default) to scan project files and generate a context-aware stacker.yml with services, ports, env vars, and healthchecks. Falls back to template detection if the AI provider is unreachable.

When environment variables are in the compose file, .env.example and scripts/generate-secrets.sh are also generated.

AI-powered init (optional)

Stacker can scan your project files and use an LLM to generate a tailored stacker.yml:

# Local AI with Ollama (free, private, default)
stacker init --with-ai
# OpenAI
stacker init --with-ai --ai-provider openai --ai-api-key sk-...
# Anthropic (key from env)export ANTHROPIC_API_KEY=sk-ant-...
stacker init --with-ai --ai-provider anthropic

If the AI provider is unreachable, Stacker falls back to template-based generation automatically.

When the project looks like a simple HTML or Next.js website and the configured Ollama model is qwen2.5-code or qwen2.5-coder, stacker init --with-ai can also bootstrap a website deployment scenario. The bootstrap seeds values from the generated stacker.yml, asks only for the missing deploy inputs, and saves scenario state under .stacker/scenarios/qwen2.5-code/website-deploy/ for later continuation with stacker ai.

AI deployment workflows

For the canonical AI/MCP deployment flow — inspect state, explain topology or env provenance, preview a plan, apply it safely, and recover with events or rollback — see AI deployment workflows.

For the qwen-specific website scenario flow, including --scenario and --step continuation, see the same guide.


stacker.yml example

name: my-appapp:
type: nodepath: ./srcports:
- "8080:3000"environment:
NODE_ENV: productionservices:
- name: postgresimage: postgres:16environment:
POSTGRES_DB: myappPOSTGRES_PASSWORD: ${DB_PASSWORD}proxy:
type: nginxauto_detect: truedomains:
- domain: app.example.comssl: autoupstream: app:3000deploy:
target: local # or: cloud, serverai:
enabled: trueprovider: ollamamodel: llama3monitoring:
status_panel: truehealthcheck:
endpoint: /healthinterval: 30salerts: # container-down alarm for `stacker monitor` (0.3.2)interval: 30target:
terminal: true # or: { url: "https://ntfy.example.com/alerts" }

Full schema reference: docs/STACKER_YML_REFERENCE.md


Three components

ComponentWhat it doesBinary
Stacker CLIDeveloper tool — init, deploy, monitor from the terminalstacker-cli
Stacker ServerREST API + Stack Builder UI + deployment orchestration + MCP Serverserver
Status Panel AgentDeployed alongside your app on the target server — executes commands, streams logs, reports health(separate repo)
┌──────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ Stacker CLI │────────►│ Stacker Server │────────►│ Status Panel Agent │
│ │ REST │ │ queue │ (on target server) │
│ stacker.yml │ API │ Stack Builder UI│ pull │ │
│ init/deploy │ │ 85+ MCP tools │◄────────│ health / logs / │
│ status/logs │ │ Vault · AMQP │ HMAC │ restart / exec / │
└──────────────┘ └──────────────────┘ │ deploy_app / proxy │
│ └─────────────────────┘
▼
Terraform + Ansible ──► Cloud
(Hetzner, DO, AWS, Linode)

1. Stacker CLI

The end-user tool. No server required for local deploys.

Commands

CommandDescription
stacker initDetect project type, generate stacker.yml + .stacker/ artifacts
stacker deployBuild & deploy the stack (local, cloud, or server). Cloud deploys also install a local SSH backup key when possible. --runtime kata|runc selects container runtime
stacker statusShow running containers and health
stacker logsView container logs (--follow, --service, --tail)
stacker deployment state / stacker deployment statusShow canonical deployment state (defaults to latest; --pinned uses stacker.yml hash)
stacker deployment eventsShow structured deployment events (--pinned uses stacker.yml hash)
stacker deployment rollbackPreview or apply a deployment rollback
stacker secretsManage local .env secrets or remote Vault-backed service / server secrets
stacker list deployments / stacker deployments / stacker psList deployments on the Stacker server
stacker list servers / stacker serversList saved servers
stacker list clouds / stacker clouds / stacker keys / stacker cloud keysList saved cloud credentials
stacker list ssh-keys / stacker ssh-keysList per-server SSH key status
stacker destroyTear down the deployed stack
stacker config validateValidate stacker.yml syntax
stacker config showShow resolved configuration
stacker config examplePrint a full commented reference
stacker config setup cloudGuided cloud deployment setup
stacker config setup aiConfigure AI provider, endpoint, model, and tasks
stacker ai ask "question"Ask the AI about your stack
stacker proxy addAdd a reverse-proxy domain entry
stacker proxy detectAuto-detect existing reverse-proxy containers
stacker cloud firewall addOpen cloud-provider firewall ports without SSH, for example --public-ports 8000/tcp on Hetzner
stacker cloud firewall removeRemove Stacker-managed cloud-provider firewall rules
stacker cloud firewall listList cloud-provider firewall rules for a server
stacker ssh-key generateGenerate a new SSH key pair for a server (Vault-backed)
stacker ssh-key showDisplay the public SSH key for a server
stacker ssh-key uploadUpload an existing SSH key pair for a server
stacker ssh-key injectRepair Vault-key trust by using an already-working private key to update authorized_keys
stacker service addAdd a service from the template catalog to stacker.yml
stacker service listList available service templates (20+ built-in)
stacker agent healthCheck Status Panel agent connectivity and health
stacker agent statusDisplay agent snapshot — containers, versions, uptime
stacker agent list apps / stacker agent appsList apps for the target deployment
stacker agent list containers / stacker agent containersList containers on the target server
stacker agent logs <app>Retrieve container logs from the remote agent
stacker agent restart <app>Restart a container via the agent
stacker agent deploy-appDeploy or update an app container on the target server. --runtime kata|runc selects container runtime; --env <name> selects the deploy environment/profile
stacker agent remove-appRemove an app container (with optional volume/image cleanup)
stacker agent configure-proxyConfigure Nginx Proxy Manager via the agent; use --no-ssl for plain HTTP hosts (credentials are resolved from Vault and are auto-seeded for managed Status Panel + NPM deploys)
stacker agent configure-firewallConfigure guest OS firewall rules via the Status Panel agent; use stacker cloud firewall for provider firewalls
stacker agent historyShow recent command execution history
stacker agent execExecute a raw agent command with JSON parameters
stacker pipe scanDiscover local endpoints/resources from running containers (when target is local)
stacker pipe scan --containers [filter]Discover local endpoints/resources for matching containers
stacker pipe scan --app <app>Probe a remote app for API endpoints
stacker pipe create <src> <tgt>Create a data pipe between two containers (interactive; or non-interactive with --source-endpoint/--target-endpoint/--name — added in 0.3.2). --retry/--on-failure/--on-success attach a retry policy + lifecycle handlers
stacker pipe diffCompare the declared pipes: block against deployed pipes (added in 0.3.2)
stacker pipe applyReconcile declared pipes into the deployment; --prune removes orphans, --dry-run previews (added in 0.3.2)
stacker pipe listList pipe instances for the current deployment
stacker pipe activate <id>Activate a pipe (start listening for triggers)
stacker pipe deactivate <id>Pause an active pipe
stacker pipe trigger <id>One-shot pipe execution with optional input data
stacker pipe deploy <id>Promote a local pipe to a remote deployment
stacker pipe history <id>View execution history for a pipe
stacker pipe replay <exec-id>Re-run a previous pipe execution
stacker monitorWatch container health and alert on problems (added in 0.3.2); --once for a single check (cron-friendly). Configure via monitoring.alerts in stacker.yml
stacker target [local|cloud|server]Switch deployment target mode
stacker env [local|dev|prod]Show or persist the active deploy environment/profile used by app-only updates
stacker whoamiShow the active login, subscription plan, and current project deployment context
stacker submitPackage current stack and submit to marketplace for review
stacker marketplace statusCheck submission status for your marketplace templates
stacker marketplace logs <name>Show review comments and history for a submission
stacker loginAuthenticate with the TryDirect platform
stacker updateCheck for updates and self-update

Deploy targets

stacker deploy --target local# docker compose up (default)
stacker deploy --target cloud # Terraform + Ansible → cloud provider
stacker deploy --target server # deploy to existing server via SSH
stacker deploy --dry-run # preview generated files without executing

After a successful cloud deploy, Stacker creates or reuses a local backup key at ~/.config/stacker/ssh/server-<id>_ed25519 (or under $XDG_CONFIG_HOME) and authorizes its public key on the server when possible. The CLI prints a normal ssh -i ... command, while the Vault private key remains server-side.

When a cloud/server deploy includes deploy.registry credentials (or the equivalent STACKER_DOCKER_* environment variables), Stacker stores that registry auth securely and reuses it for later Status-managed image refreshes such as stacker agent deploy-app. This keeps private-image redeploys working without depending on host-level docker login state or mounting /root/.docker into the agent container.

Secrets workflow

# Local project .env secret
stacker secrets set DB_PASSWORD=supersecret
# Discover valid remote deployable service/app targets first
stacker secrets apps
# Remote service secret used at render/deploy time for one target
stacker secrets set S3_SECRET_KEY \
--scope service \
--service uploader \
--body supersecret
# Remote server secret for future host-level consumers
stacker secrets set NPM_TOKEN \
--scope server \
--server-id 42 \
--body-file .npm-token
# Remote reads are metadata-only in v1
stacker secrets list --scope service --service uploader --json
stacker secrets get S3_SECRET_KEY --scope service --service uploader --json
# Push stored remote secrets into the target's runtime env
stacker secrets push --service uploader
stacker secrets push --service uploader --env prod
# Aliases: stacker secrets deploy --service uploader# stacker secrets apply --service uploader
  • Local mode remains the default and reads/writes the project .env file.
  • Remote mode is enabled only with --scope service or --scope server.
  • Service-scoped remote commands default --project from stacker.yml -> project.identity; --project still overrides it explicitly.
  • Service-scoped secrets target deployable service/app codes listed by stacker secrets apps, including registered stacker.yml services and supported image-backed Compose services after a deploy/update sync.
  • Service-scoped secrets are merged only into the matching rendered service/app env at deploy time.
  • stacker secrets push --service <target> applies stored service secrets to the remote runtime env without changing secret values. Use --env <name> for a one-off environment selection, or stacker env <name> to persist the active environment/profile for future app-only updates. Use --force only when the remote env drift check reports an out-of-band change.
  • Remote get and list do not return plaintext values in v1.
  • MCP env inspection now exposes explicit secure metadata for Vault-backed variables: get_app_env_vars keeps the redacted environment_variables object for compatibility and also returns environment_entries[] with secure, redacted, and source fields.

Remote deploys render runtime env into one canonical host file: /home/trydirect/project/.env. Generated compose uses env_file: .env, so the path is relative to the deployed compose file. To inspect paths and contributing layers without exposing values, run:

stacker config show --resolved

For app-only updates, stacker agent deploy-app <target> resolves the deploy environment from --env, then .stacker/active-env, then stacker.yml. If <target>/docker/<env>/compose.yml exists, Stacker uses the app-local service definition for that target but merges it into the full project-level compose file before sending it to the agent. This prevents app-only updates from replacing the remote stack compose with a single-service compose file. Any app-local .env referenced by that compose file is uploaded in the config bundle, and Stacker appends the Vault-rendered service secrets for the same target to that file before the agent writes it on the server. Repeated app-only updates replace the prior # stacker-render ... block in that file instead of stacking duplicate rendered secret sections.

Marketplace workflow (for stack developers)

stacker deploy --target local# 1. test locally
stacker deploy --target server # 2. test on remote server
stacker submit # 3. submit for marketplace review
stacker marketplace status # 4. check review status# Stack is auto-published once approved by the review team

Marketplace install (for buyers)

# Option A: Deploy from your laptop to a remote server
stacker deploy my-stack --target server --host 1.2.3.4
# Option B: Run directly on the target server (one-liner)
curl -sL https://marketplace.try.direct/<purchase-token>/install.sh | sh

Key features

  • Auto-detection — identifies Node, Python, Rust, Go, PHP, static sites from project files
  • Dockerfile generation — produces optimised multi-stage Dockerfiles per app type
  • Docker Compose generation — wires app + services + proxy + monitoring
  • Remote service secrets — Vault-backed service/app target secrets are metadata-only when read and isolated to the selected service
  • AI-assisted config — scans project, calls LLM to generate tailored stacker.yml
  • AI troubleshooting — on deploy failure, suggests fixes via AI or deterministic fallback hints
  • Service catalog — 20+ built-in service templates (Postgres, Redis, WordPress, etc.) — add with stacker service add
  • AI service addition — ask stacker ai ask --write "add wordpress" and the AI uses the template catalog
  • Agent controlstacker agent subcommand to manage remote Status Panel agents (health, logs, restart, deploy, proxy) with --json output
  • SSH key management — generate, view, upload, and repair server SSH keys (Vault-backed), with automatic local backup SSH access after cloud deploy
  • Reverse proxy — Traefik (labels), Caddy (Caddyfile), and Nginx Proxy Manager, platform-managed and driven by proxy.domains end-to-end (0.3.2)
  • Container-health alarmstacker monitor watches container health and alerts on problems (terminal, webhook, or pipe), configured via monitoring.alerts (0.3.2)
  • Declarative pipes (IaC) — declare pipes in stacker.yml and reconcile with stacker pipe diff / pipe apply [--prune] (0.3.2)
  • Cloud deployment — Hetzner, DigitalOcean, AWS, Linode, with provider firewall operations and paused/failed install IP retention
  • MCP Server — 85+ tools, including deployment, agent control, config, proxy, firewall, and remote service secret management
  • Marketplace — submit stacks for review, auto-publish on approval, check status from CLI
  • Buyer install — purchase tokens, one-liner install scripts, agent self-registration

2. Stacker Server

The backend platform powering the Stack Builder UI, REST API, deployment orchestration, and MCP server for AI agents.

Setup

cp configuration.yaml.dist configuration.yaml # edit database, vault, AMQP settings
cp access_control.conf.dist access_control.conf
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/stacker
sqlx migrate run
cargo run --bin server # http://127.0.0.1:8000

Key API endpoints

EndpointDescription
POST /projectCreate a project from a stack definition
POST /{id}/deploy/{cloud_id}Deploy to a cloud provider
GET /project/{id}/appsList apps in a project
DELETE /project/{id}/apps/{code}Remove an app from a project
PUT /project/{id}/apps/{code}/envUpdate app environment variables
GET /project/{id}/apps/{code}/secretsList service-scoped secret metadata for an app
PUT /project/{id}/apps/{code}/secrets/{name}Create or update a Vault-backed service secret
PUT /project/{id}/apps/{code}/portsUpdate port mappings
PUT /project/{id}/apps/{code}/domainUpdate domain / SSL settings
GET /server/{id}/secretsList server-scoped secret metadata
PUT /server/{id}/secrets/{name}Create or update a Vault-backed server secret
POST /api/v1/commandsEnqueue a command for the Status Panel agent
POST /api/templatesCreate or update a marketplace template (creator)
POST /api/templates/{id}/submitSubmit template for marketplace review
GET /api/templates/mineList current user's template submissions
GET /api/v1/marketplace/install/{token}Generate install.sh script for buyers
GET /api/v1/marketplace/download/{token}Download stack archive (purchase token validated)
POST /api/v1/marketplace/agents/registerAgent self-registration after install
POST /api/v1/pipes/templatesCreate a reusable pipe template (source→target mapping)
GET /api/v1/pipes/templatesList pipe templates (with optional filters)
POST /api/v1/pipes/instancesCreate a pipe instance for a deployment
GET /api/v1/pipes/instancesList pipe instances by deployment hash
PUT /api/v1/pipes/instances/{id}/statusUpdate pipe instance status (active/paused)

MCP Server

Stacker exposes 52+ Model Context Protocol tools over WebSocket, enabling AI agents (Claude, GPT, etc.) to manage infrastructure programmatically:

  • Project & deployment management
  • Container operations (start, stop, restart, exec)
  • Log analysis & error summaries
  • Vault config read/write
  • Proxy configuration
  • App environment & port management
  • Server resource monitoring
  • Docker Compose generation & preview
  • Agent control (deploy app, remove app, configure proxy, get status)
  • Firewall management (iptables rules via Status Panel or SSH)

Key integrations

  • HashiCorp Vault — secrets and config storage, synced to deployments
  • RabbitMQ — deployment status updates, event-driven orchestration
  • TryDirect User Service — OAuth, marketplace templates, payment validation
  • Marketplace — publish and deploy community stacks

3. Status Panel Agent

A lightweight agent deployed alongside your application on the target server. It runs as a Docker container and communicates with Stacker Server using a pull-only architecture — the agent polls for commands, Stacker never dials out.

How it works

1. UI/API creates a command → POST /api/v1/commands
2. Command stored in DB queue → commands + command_queue tables
3. Agent polls for work → GET /api/v1/agent/commands/wait/{hash}
4. Agent executes locally → Docker API on the host
5. Agent reports result → POST /api/v1/agent/commands/report

All agent requests are HMAC-signed (X-Agent-Signature header) using a token stored in Vault.

Supported commands

CommandDescription
healthCheck container health status (single or all)
logsFetch container logs (stdout/stderr, with limits)
restartRestart a container
deploy_appDeploy or update an app container
remove_appRemove an app container
configure_proxyCreate/update/delete reverse-proxy entries
configure_firewallConfigure iptables firewall rules (add/remove/list/flush)
stacker.execExecute a command inside a running container (with security blocklist)
stacker.server_resourcesCollect server resource metrics (CPU, memory, disk, network)
apply_configPull config from Vault and apply to a running container
probe_endpointsDiscover API endpoints on containers (OpenAPI, REST, HTML forms, GraphQL)
activate_pipeActivate a pipe instance — start polling/webhook triggers
deactivate_pipeDeactivate a running pipe instance
trigger_pipeOne-shot pipe execution: fetch source data → map fields → post to target

Agent registration

# Agent self-registers on first boot (no auth required)
POST /api/v1/agent/register
{ "deployment_hash": "abc123", "capabilities": [...], "system_info": {...} }
→ { "agent_id": "...", "agent_token": "..." }

Token rotation

cargo run --bin console -- Agent rotate-token \
--deployment-hash <hash> \
--new-token <NEW_TOKEN>

Database migrations

sqlx migrate run # apply
sqlx migrate revert # rollback

Testing

cargo test# all tests (772+ unit, 69 security integration)
cargo test user_service_client # User Service connector
cargo test marketplace_webhook # Marketplace webhook flows
cargo test deployment_validator # Deployment validation
cargo test --test security_cli # CLI endpoint IDOR security tests
SQLX_OFFLINE=true cargo test --lib -- proxy_domains 2>&1| tail -10

Kata Containers (Hardware Isolation)

Stacker supports Kata Containers as an alternative runtime, providing VM-level isolation for each container using hardware virtualization (KVM).

KVM requirement — Kata needs nested or bare-metal KVM. Hetzner dedicated-CPU servers (CCX line) expose /dev/kvm out of the box, making them an ideal deployment target.

stacker deploy --runtime kata # deploy the current stack with Kata isolation
stacker agent deploy-app --runtime kata # deploy a single app container with Kata

See docs/kata/ for the full setup guide, network constraints, and monitoring reference. Automated provisioning (Ansible + Terraform for Hetzner CCX) is available via the TFA infrastructure toolkit.


Documentation


License

MIT

About

Orchestrate dockerized apps from cli, control, monitor, install apps on own servers and in the cloud

Topics

Resources

Security policy

Stars

6 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages