A production-ready Jelastic / Virtuozzo Application Platform JPS package that deploys SwarmClaw — a self-hosted AI agent runtime and multi-agent framework — onto a single Docker Engine node, end to end, in one import.
On import, the manifest:
- Creates a new environment with one Docker Engine node.
- Ensures Docker Engine + Compose,
git,curl,openssl,ca-certificates. - Clones SwarmClaw into
/opt/swarmclaw. - Creates persistent
/opt/swarmclaw/dataand/opt/swarmclaw/.env.local. - Generates unique credentials (
ACCESS_KEY,CREDENTIAL_SECRET) — platform-generated, with anopensslfallback. - Stores them in
/opt/swarmclaw/.deployment-secrets(chmod 600) and writes them to.env.local(chmod 600). - Starts SwarmClaw with Docker Compose (
docker compose up -d --build), using the repo's own compose file, and installs the Claude Code + OpenAI Codex provider CLIs into the container. - Ensures the container restarts after reboot (
restart: unless-stopped). - Exposes SwarmClaw via the environment URL (host
:80→ container:3456). - Health-checks
http://127.0.0.1:3456/api/healthz. - Emails the customer the deployment details.
- Shows a success panel in the dashboard.
┌──────────────────────────────────────────────┐
│ Jelastic / Virtuozzo Environment │
│ │
│ nodeGroup: cp │
│ ┌──────────────────────────────────────┐ │
│ │ Docker Engine node │ │
│ │ │ │
│ │ /opt/swarmclaw (git checkout) │ │
│ │ ├─ docker-compose.yml (upstream) │ │
│ │ ├─ docker-compose.override.yml │ │
│ │ ├─ .env.local (600) │ │
│ │ ├─ .deployment-secrets (600) │ │
│ │ ├─ data/ (persistent) │ │
│ │ └─ scripts/ (install/start/…) │ │
│ │ │ │
│ │ docker compose ─► container │ │
│ │ swarmclaw host :80 → :3456 │ │
│ └──────────────────────────────────────┘ │
└──────────────────────────────────────────────┘
▲
│ ${env.url} (dashboard "Open in Browser" → host :80)
└── customer browser
Single node, no Kubernetes, no HA (v1). Docker provides Node.js 22.6+ inside the container, so the host OS version is irrelevant.
- Push this repository to a Git host where the files are reachable as raw URLs (e.g. GitHub).
baseUrlinmanifest.jpsis already set for this repo:https://raw.githubusercontent.com/stackharbor-devops/jps-swarmclaw/main(the installer fetchesscripts/*.shfrom${baseUrl}/scripts/...). If you fork or rename the repo/branch, update it to match.- In the dashboard: Import → URL → paste:
https://raw.githubusercontent.com/stackharbor-devops/jps-swarmclaw/main/manifest.jps→ Import. - Pick an environment name + region when prompted → Install.
- When it finishes, read the success panel and the email sent to your account address.
baseUrlmust match where the manifest is hosted, or script fetching fails.
| Assumption | Detail / fallback |
|---|---|
| Node type | dockerengine (Docker Engine CE). If unavailable, set nodeType: vps (Ubuntu); install.sh installs Docker/Compose itself. |
cmd runs as root |
True on Docker Engine / VPS nodes. Scripts also fall back to sudo -n. |
| Env URL routing | The app is published on host :80; the environment URL / "Open in Browser" must route to the node on port 80 (default for a single-node env). See Exposing SwarmClaw for public-IP / Endpoint alternatives. |
| Outbound internet | Needed to pull the SwarmClaw repo, base image and packages. |
Sent via message.email.Send to ${user.email}. Requires the platform's outgoing SMTP to be configured (default on most installs). |
|
| App URL macro | ${env.url} (always resolves; this is what the dashboard "Open in Browser" uses). |
This package is intentionally one-click — the platform prompts only for the
environment name and region. Behaviour can be tuned via environment variables
honoured by the scripts (override in manifest.jps or when running manually):
| Variable | Default | Purpose |
|---|---|---|
SWARMCLAW_APP_DIR |
/opt/swarmclaw |
Install directory |
SWARMCLAW_PORT |
3456 |
Container app port (health checks) |
SWARMCLAW_REPO_URL |
upstream repo | SwarmClaw git source |
SWARMCLAW_BRANCH |
main (→ master) |
Branch/ref to deploy |
SWARMCLAW_BASE_URL |
— | Raw base URL of this package (script fetch) |
SWARMCLAW_ACCESS_KEY / SWARMCLAW_CREDENTIAL_SECRET |
— | Pre-set credentials (the manifest passes the platform-generated globals here) |
SWARMCLAW_NO_BUILD |
0 |
1 = pull prebuilt image instead of building |
SWARMCLAW_INSTALL_CLIS |
1 |
Install provider CLIs in the container (0 to skip) |
SWARMCLAW_CLI_SPECS |
@anthropic-ai/claude-code:claude @openai/codex:codex |
pkg:binary list of CLIs to install |
SWARMCLAW_REF |
current branch | update.sh: ref to update to |
- URL: the environment URL (
${env.url}), shown in the success panel and email; the dashboard Open in Browser button opens it too. - Access Key: in the email, the success panel, and
/opt/swarmclaw/.deployment-secrets. - Open the URL, authenticate with your Access Key, then configure providers, agents, Hermes Agent, tools, schedules and credentials in the SwarmClaw UI.
docker-compose.override.yml publishes the container on host port 80, so the
single-node environment URL (port 80, via the platform resolver/SLB) reaches
SwarmClaw — which also makes Open in Browser work. The container ports
3456/3457 remain published on the host as well.
Alternatives if you need a fixed public :3456, or port 80 is taken on the node:
-
Public IP: add
extip: trueto the node and usehttp://<public-ip>:3456(open TCP 3456 in the environment Firewall). Public-IP /extIPsplaceholder support is version-dependent. -
TCP Endpoint: map 3456 to a public port via the API:
- api: environment.binder.AddEndPoint nodeId: ${nodes.cp.first.id} name: swarmclaw privatePort: 3456 protocol: TCP
SwarmClaw also listens on 3457 (secondary). If a browser feature needs it and you front the app on port 80 only, publish/route 3457 too.
Every deployment pre-installs two CLI-based providers inside the container so the
default Assistant agent (and any claude-code / codex agent) works without
manual setup:
- Claude Code —
@anthropic-ai/claude-code(claude) - OpenAI Codex —
@openai/codex(codex)
start.sh installs them on every deploy — idempotent, best-effort (a failure never
breaks the app). Toggle with SWARMCLAW_INSTALL_CLIS=0; customise the list with
SWARMCLAW_CLI_SPECS.
Credentials are still required. Installing the CLIs fixes "Claude CLI not found", but each backend needs auth before it answers. Add an API key in the SwarmClaw UI (Providers / Secrets), or set it in
/opt/swarmclaw/.env.local(ANTHROPIC_API_KEY,OPENAI_API_KEY) thendocker compose restart. SwarmClaw's built-in OpenAI / Anthropic API providers need only a key (no CLI).
Add the CLIs to an already-running instance (no redeploy needed):
docker compose -f /opt/swarmclaw/docker-compose.yml exec -u root -T \
swarmclaw npm install -g @anthropic-ai/claude-code @openai/codex- Generated by the platform (
${fn.password}) and passed into the installer;generate-credentials.shfalls back toopenssl rand -base64 32for manual runs. Never hardcoded, never committed. - Stored in
/opt/swarmclaw/.deployment-secretsand/opt/swarmclaw/.env.local, bothchmod 600. .gitignoreexcludes.env.local,.deployment-secrets,data/.- Idempotent: re-running install/update reuses existing on-disk secrets — keys are not rotated.
- Secrets are surfaced only in the final customer email and success output (the permitted exception); scripts otherwise never print secret values.
CREDENTIAL_SECRETis set explicitly in.env.local, which is the stable, first resolution source SwarmClaw uses for credential encryption.
Rotate by editing the two keys in
.deployment-secretsand.env.local(keep them in sync), thenbash /opt/swarmclaw/scripts/start.sh. Re-encrypting stored credentials after rotatingCREDENTIAL_SECRETis handled in the SwarmClaw UI.
bash /opt/swarmclaw/scripts/update.sh # latest of current branch
SWARMCLAW_REF=v1.2.3 bash /opt/swarmclaw/scripts/update.sh # pin a tagPulls the latest source, rebuilds, restarts, and health-checks. .env.local,
.deployment-secrets and data/ are preserved.
cd /opt/swarmclaw
docker compose restart # restart in place
docker compose down && docker compose up -d # full recreate
bash /opt/swarmclaw/scripts/start.sh # idempotent (re)startThe container auto-restarts after a node reboot (restart: unless-stopped).
cd /opt/swarmclaw
docker compose ps # container status
docker compose logs -f --tail=100 # follow logs
docker compose config # effective merged compose config (incl. override)
bash scripts/healthcheck.sh # probe :3456/api/healthz
curl -i http://127.0.0.1:3456/api/healthz
curl -i http://127.0.0.1:80/ # verify the host :80 → :3456 publish
cat /var/log/swarmclaw-install.log # full install log (redirected here from the JPS bootstrap)
systemctl status docker # docker daemon- Install fails with
org.hibernate.exception.DataException: the install command must not stream large output back to the platform — this package redirects it to/var/log/swarmclaw-install.logand returns only a status line. If you customise the manifest, keep thecmdoutput small. - Port 80 already allocated: another container/service holds host :80. Change
"80:3456"indocker-compose.override.yml, or use a public IP / Endpoint instead. - If the build is killed (OOM), raise
flexibleCloudletson the node or setSWARMCLAW_NO_BUILD=1to pull the prebuilt image.
- Liveness:
GET http://127.0.0.1:3456/api/healthz(used byhealthcheck.shand the upstream composeHEALTHCHECK). - Container:
docker compose psshould showswarmclawasrunning/healthy. healthcheck.shretries for ~150s and dumps the last logs on failure.
.
├── manifest.jps # JPS manifest (import this)
├── README.md
├── docker-compose.override.yml # installed to node: host :80 routing + restart policy
├── .gitignore
└── scripts/
├── install.sh # full first-time deploy (orchestrator)
├── generate-credentials.sh # create/persist ACCESS_KEY & CREDENTIAL_SECRET
├── start.sh # docker compose up + restart policy
├── healthcheck.sh # probe :3456/api/healthz
└── update.sh # pull + rebuild + restart + health
On the node (/opt/swarmclaw): the SwarmClaw checkout plus docker-compose.override.yml,
.env.local (600), .deployment-secrets (600), data/ (persistent) and scripts/.
- Single node, no HA (v1). No clustering, load balancing or failover.
- Vertical scaling only via node cloudlets.
- Plain HTTP on port 80. Served over the environment URL without TLS/custom domain out of the box — front it with a reverse proxy / Let's Encrypt add-on for HTTPS. Routing assumes the env URL reaches the node on port 80 (true for a single-node env).
- Persistence is node-local.
data/lives on the node's disk (survives reboots and container recreation), but is not replicated off-node — snapshot/back updata/. - Hermes Agent is not auto-deployed (see below).
- Upstream-driven. Tracks the SwarmClaw repo; a breaking upstream change to the compose file or env vars may require package updates.
This package deploys SwarmClaw itself. It does not automatically provision a
separate Hermes Agent runtime. SwarmClaw integrates Hermes as a backend/provider
through its OpenAI-compatible API — point SwarmClaw at a reachable Hermes /v1
endpoint (local or remote) from the SwarmClaw UI/config after deployment. The
deployed instance is ready for that configuration; no extra package steps are needed.
- Multi-node SwarmClaw with a shared/replicated data backend and a load balancer.
- Managed reverse proxy + automatic TLS (Let's Encrypt) and custom domains.
- Optional co-deployment of a Hermes Agent runtime node, wired to SwarmClaw automatically.
- Horizontal auto-scaling triggers and scheduled off-node backups of
data/.
- App: SwarmClaw by SwarmClaw AI.
- JPS style modelled on
jelastic-jps/wordpress-clusterandjelastic-jps/minio. - Packaged by Stack Harbor.