What Happens When a Service Is Missing?
You've created a project on the Stacker dashboard, deployed it to a cloud server, and everything looks good — except the main application container isn't there. Only the database is running. This usually happens when the project was set up without a proper application template, leaving you with a half-empty stack.
In this guide, we'll walk through a real scenario: an Umami analytics project that was deployed with only PostgreSQL and no Umami container. You'll learn how to inspect the deployment, add the missing app via the Stacker API, deploy it, and verify everything works — all from the command line.
Quick Answer
stacker agent status to inspect your
deployment, then register the missing app via the
Stacker API (POST /project/{id}/apps) and
deploy it with
stacker agent deploy-app.
Step 1: Inspect the Current Deployment
Start by checking what's actually running on your deployment
agent. Use the stacker agent status command
with your deployment hash:
stacker agent status --deployment deployment_c837325f-34b3-4d1f-b4a0-e55a49cf8926
This shows you the running containers, their images, and their states:
────────────────────────────────────────────────────────────────────────────────────────────
Agent: ● online
Heartbeat: 2026-07-01T18:31:56.563318Z
────────────────────────────────────────────────────────────────────────────────────────────
APP NAME IMAGE ENABLED
postgres postgres postgres:latest yes
────────────────────────────────────────────────────────────────────────────────────────────
CONTAINER STATE PORTS IMAGE
project-postgres-1 ⟳ restarting 5432 postgres:latest
statuspanel_agent ▶ running - registry-intl.eu-central-1.…
statuspanel ▶ running - registry-intl.eu-central-1.…
────────────────────────────────────────────────────────────────────────────────────────────
Notice only postgres appears in the APP list.
The Umami analytics container is completely absent.
Step 2: Get Detailed App Configuration
For more detail, use the --json flag. This
reveals the exact environment variables, port mappings,
volumes, and network configuration of the running apps:
stacker agent status --deployment deployment_c837325f-34b3-4d1f-b4a0-e55a49cf8926 --json
Look for the apps array in the JSON output. For
our postgres app:
{
"apps": [
{
"code": "postgres",
"image": "postgres:latest",
"environment": {
"POSTGRES_DB": "umami",
"POSTGRES_USER": "umami",
"POSTGRES_PASSWORD": "umami"
},
"ports": [{"host_port": 5432, "container_port": 5432}],
"networks": ["default_network"],
...
}
]
}
This tells us the database credentials (umami
for user, password, and database name) — exactly what we
need to configure the Umami container's
DATABASE_URL.
Step 3: Check If a Template Exists
See what templates are available in the marketplace:
stacker templates | grep -i umami
stacker catalog | grep -i umami
If nothing shows up, there's no Umami template you can simply install. You'll need to register the app manually.
Step 4: Create the App via the Stacker API
Apps are managed through the Stacker REST API. The endpoint
is a POST to /project/{project_id}/apps — and
it's an upsert, so you can safely run it multiple times.
First, find your project ID and get your auth token from
~/.config/stacker/credentials.json:
# List projects to find your project ID
stacker projects | grep umami
# Output: 243 umami 2026-06-30T08:49:12...
# Your access token is stored here
cat ~/.config/stacker/credentials.json
Now create the Umami app:
TOKEN="*******token*******"
curl -s -X POST "https://try.direct/stacker/project/243/apps" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "umami",
"name": "Umami Analytics",
"image": "ghcr.io/umami-software/umami:postgresql-latest",
"environment": {
"DATABASE_URL": "postgresql://umami:umami@postgres:5432/umami",
"HASH_SALT": "3b8e9f1a7c2d5e4f6a0b9c8d7e6f5a4b3c2d1e0f"
},
"ports": [
{"host_port": 3000, "container_port": 3000, "protocol": "tcp"}
],
"depends_on": ["postgres"],
"restart_policy": "always",
"enabled": true,
"deploy_order": 2
}'
Successful response:
{
"message": "OK",
"item": {
"id": 28,
"project_id": 243,
"code": "umami",
"name": "Umami Analytics",
"image": "ghcr.io/umami-software/umami:postgresql-latest",
"environment": {
"DATABASE_URL": "postgresql://umami:umami@postgres:5432/umami",
"HASH_SALT": "3b8e9f1a7c2d5e4f6a0b9c8d7e6f5a4b3c2d1e0f"
},
"ports": [{"container_port": 3000, "host_port": 3000, "protocol": "tcp"}],
"restart_policy": "always",
"enabled": true,
"deploy_order": 2,
"created_at": "2026-07-01T18:39:11.469030Z",
"updated_at": "2026-07-01T18:39:11.469030Z",
"config_version": 1
}
}
Step 5: Plan and Deploy the App
First, preview what deploy-app will do:
stacker agent deploy-app umami \
--deployment deployment_c837325f-34b3-4d1f-b4a0-e55a49cf8926 \
--plan
Expected plan output:
{
"hasChanges": true,
"actions": [
{
"kind": "redeploy_app",
"target": "app",
"appCode": "umami",
"reason": "explicit deploy-app plan targets a single app"
},
{
"kind": "sync_app_config",
"target": "app",
"appCode": "umami",
"reason": "app config version is ahead of the synced Vault/runtime version"
}
]
}
Apply the plan:
stacker agent deploy-app umami \
--deployment deployment_c837325f-34b3-4d1f-b4a0-e55a49cf8926
Successful deployment output:
Command: cmd_513774de-e91e-4357-b886-8565f3ce3ef2
Type: deploy_app
Status: ✓ completed
{
"app_code": "umami",
"container_state": "running",
"deployed_at": "2026-07-01T18:40:36Z",
"status": "deployed"
}
Step 6: Verify Everything Is Running
Check the status again:
stacker agent status --deployment deployment_c837325f-34b3-4d1f-b4a0-e55a49cf8926
────────────────────────────────────────────────────────────────────────────────────────────
Agent: ● online
Heartbeat: 2026-07-01T18:40:36.661528Z
────────────────────────────────────────────────────────────────────────────────────────────
APP NAME IMAGE ENABLED
postgres postgres postgres:latest yes
umami Umami Analytics ghcr.io/umami-software/umam… yes
────────────────────────────────────────────────────────────────────────────────────────────
CONTAINER STATE PORTS IMAGE
umami ▶ running - ghcr.io/umami-software/umam…
postgres ▶ running - postgres:latest
statuspanel_agent ▶ running - registry-intl.eu-central-1.…
statuspanel ▶ running - registry-intl.eu-central-1.…
────────────────────────────────────────────────────────────────────────────────────────────
Both postgres and umami are now
listed as apps and running. You can inspect the logs to
confirm the application started correctly:
stacker agent logs umami \
--deployment deployment_c837325f-34b3-4d1f-b4a0-e55a49cf8926
Look for key log lines:
✓ DATABASE_URL is defined.
✓ Database connection successful.
✓ Database is up to date.
> umami@3.2.0 start-server
> node server.js
▲ Next.js 16.2.6
- Local: http://localhost:3000
- Network: http://0.0.0.0:3000
✓ Ready in 0ms
Step 7: Configure a Domain
Set a public domain for the new app via the API:
curl -s -X PUT "https://try.direct/stacker/project/243/apps/umami/domain" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"domain": "umami.try.direct", "ssl_enabled": true}'
Then configure the reverse proxy on the agent:
stacker agent configure-proxy umami \
--domain umami.try.direct \
--port 3000 \
--ssl \
--deployment deployment_c837325f-34b3-4d1f-b4a0-e55a49cf8926 \
--force
Troubleshooting Common Issues
Issue 1: "service refers to undefined network"
If the existing app has networks configured but
the Docker Compose file lacks the network definition, update
the existing app to remove the network reference:
curl -s -X POST "https://try.direct/stacker/project/243/apps" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "code": "postgres", "image": "postgres:latest", ... }'
Omitting the networks field lets Docker Compose
use its default network, which all services can share.
Issue 2: "service refers to undefined volume"
Named volumes must be defined at the top level of the
Compose file. If the deploy-app command complains about
undefined volumes, remove the volumes
configuration from the app definition (the data persists on
disk via the existing container).
Issue 3: Vault is unavailable
Some operations (like configure-proxy) require
HashiCorp Vault for credential resolution. If Vault is
unavailable, the proxy configuration step will fail. In this
case, the app will still run and be accessible on its
internal port — you can configure DNS and SSL manually on
the server.
Key Commands Reference
| Command | Purpose |
|---|---|
stacker agent status --deployment
<hash>
| Inspect running containers and apps |
stacker agent status --deployment
<hash> --json
| Detailed JSON view with config |
stacker projects | grep <name>
| Find your project ID |
POST /project/{id}/apps | Register a new app (via API) |
stacker agent deploy-app <code>
--deployment <hash>
| Deploy the registered app to the agent |
stacker agent logs <code>
--deployment <hash>
| View container logs |
stacker agent configure-proxy <code>
--domain ... --port ...
| Set up reverse proxy and SSL |
How It All Fits Together
The Stacker platform separates app registration from app deployment (done through the CLI, which sends commands to the remote agent). This two-step process gives you full control:
- API — Define the Docker image, environment variables, port mappings, volumes, restart policy, and deployment order
- CLI — Push the configuration to the remote server, pull the image, create the container, and wire it into the existing Docker Compose project
This approach works for any containerized application, not just Umami. Whether you're adding Redis, a custom API, or a background worker, the workflow is identical.
The next time you find a project deployed without its main application container, you now have the exact steps to fix it — inspect, register, deploy, verify.