Skip to content

Think PM2, but for ANY program via HTTP. Hoody Daemons is a universal process manager that works with Node.js, Python, Go, Rust, compiled binaries, shell scripts—literally any executable. No CLI needed, no language-specific tools, just a simple REST API to keep any program running forever.

  • 🚀 Program Management - Create, configure, and delete daemon programs
  • ▶️ Process Control - Start, stop, enable, disable running processes
  • 📊 Status Monitoring - Track process state, uptime, and PID
  • 🔄 Auto-Restart - Configure automatic restart on crashes
  • 🎯 Priority Control - Set startup order for dependencies
  • 📝 Logging - Configure stdout/stderr log files
  • 🔐 User Isolation - Run each process as specific system user
  • ⚙️ Environment - Set custom environment variables per program

All endpoints accessed relative to your Daemon Manager service URL:

https://PROJECT_ID-CONTAINER_ID-daemon-1.SERVER.containers.hoody.icu

Program Management:

Process Control:

Monitoring:

Logs:

Quick Start (Ephemeral Programs):

Enable → Start → Stop → Disable → Remove

Terminal window
# Create a daemon program
hoody daemon programs create \
--name "web-server" \
--command "/usr/bin/node /app/server.js" \
--user "www-data" \
--autorestart true \
--directory "/app"
# Enable and start
hoody daemon programs enable 1
hoody daemon programs start 1
# Check status
hoody daemon programs status 1
# Stop and remove
hoody daemon programs stop 1
hoody daemon programs disable 1
hoody daemon programs delete 1

Creating and Running a Daemon:

1. Add program (explicitly disabled — default is enabled: true):

POST Add a new daemon program
/api/v1/daemon/programs/add
Click "Run" to execute the request

2. Enable program:

POST Enable the daemon program
/api/v1/daemon/programs/1/enable
Click "Run" to execute the request

3. Start process:

POST Start the daemon process
/api/v1/daemon/programs/1/start
Click "Run" to execute the request

4. Monitor status:

GET Get daemon process status
/api/v1/daemon/status/1
Click "Run" to execute the request

Stopping and Removing:

1. Stop process:

POST Stop the daemon process
/api/v1/daemon/programs/1/stop
Click "Run" to execute the request

2. Disable program:

POST Disable the daemon program
/api/v1/daemon/programs/1/disable
Click "Run" to execute the request

3. Remove configuration:

POST Remove daemon program configuration
/api/v1/daemon/programs/remove/1
Click "Run" to execute the request

Critical Distinction:

Enable = Configuration change

  • Makes program available to supervisord
  • Doesn’t start the process
  • Required before starting

Start = Runtime action

  • Launches the actual process
  • Only works if program is enabled
  • Creates running process with PID

Example:

Terminal window
# This sequence is REQUIRED:
POST /programs/{id}/enable # Configuration: "program can run"
POST /programs/{id}/start # Runtime: "start the process"
# This FAILS:
POST /programs/{id}/start # Error: program not enabled

Configure how programs behave on crashes:

{
"name": "critical-service",
"command": "/usr/bin/service",
"user": "service",
"autorestart": "true" // Always restart on exit
}

Options:

  • "true" - Always restart (recommended for services)
  • "false" - Never restart (one-time tasks)
  • "unexpected" - Restart only on crashes (not clean exits)

Full program example:

{
"name": "api-server",
"description": "Main REST API server",
"command": "/usr/bin/node /app/api/server.js",
"user": "api",
"enabled": true,
"boot": true,
"autorestart": "true",
"directory": "/app/api",
"priority": 10,
"stdout_logfile": "/var/log/api/stdout.log",
"stderr_logfile": "/var/log/api/stderr.log",
"environment": {
"NODE_ENV": "production",
"PORT": "3000",
"DB_HOST": "localhost"
}
}

Monitor process health via status endpoint:

  • RUNNING ✅ - Process running normally with PID
  • STOPPED ⏸️ - Process not running (expected)
  • STARTING ⏳ - Currently launching (temporary)
  • STOPPING ⏳ - Gracefully shutting down (temporary)
  • BACKOFF ⚠️ - Failed to start, retrying
  • FATAL 💀 - Failed to start after retries, manual intervention needed

Status Response:

{
"statusCode": 200,
"message": "OK",
"data": {
"success": true,
"status": {
"id": 1,
"status": "RUNNING",
"pid": 12345,
"uptime": "2:15:30"
}
}
}

Control boot order when multiple programs depend on each other:

[
{
"name": "database",
"priority": 1, // Starts first
"boot": true
},
{
"name": "cache",
"priority": 5, // Starts second
"boot": true
},
{
"name": "web-server",
"priority": 10, // Starts last
"boot": true
}
]

Lower priority number = starts earlier.

Run Node.js, Python, or Go servers as daemons with auto-restart, configure logging for debugging, set startup priority if dependencies exist, monitor with status endpoint.

Queue processors (Bull, Sidekiq, Celery), scheduled task runners, data sync services, cleanup jobs.

Run custom application services, workers, and scripts with proper startup order and auto-restart policies. Do not use Hoody Daemon to manage package-installed system services such as PostgreSQL, MySQL, Redis, MongoDB, nginx, or apache — use the system service manager (systemd, OpenRC) for those.

Prometheus exporters, log shippers, health check agents, metrics collectors.

Hot-reload dev servers, file watchers, test runners, development proxies.

Independent service processes, inter-service communication, graceful shutdown coordination, centralized process management.

Always add programs with enabled: false, verify configuration before enabling, test manually before setting boot: true, enable auto-restart only after stability testing.

Stop the process first, disable program to prevent auto-restart, edit configuration, enable and start with new config, verify new configuration works before cleanup.

Always configure stdout and stderr logs, use absolute paths for log files, implement log rotation to manage disk space, monitor logs for errors and warnings.

Run each program as appropriate system user, never run services as root unless required, create dedicated users for each service type, use principle of least privilege.

Use priority field for startup ordering, lower priority (1-5) for core services, higher priority (10-20) for dependent services, test boot sequence thoroughly.

Poll /status endpoint regularly, alert on BACKOFF or FATAL states, track uptime for reliability metrics, implement health checks via other services.

Q: What’s the difference between enable and start? Enable is configuration (“program can run”), start is runtime action (“launch the process”). You must enable before starting.

Q: How do I make a program start on boot? Set boot: true in the configuration. The program will auto-start when the daemon service initializes.

Q: Can I update a running program? You must stop and disable it first, then edit, then enable and start again. Changes don’t apply to running processes.

Q: What happens if a process crashes? Depends on autorestart: "true" restarts immediately, "false" stays stopped, "unexpected" restarts only on crashes.

Q: How do I run multiple instances of the same program? Create separate program configurations with different names, unique ports/sockets in command, different data directories, distinct priority values.

Q: Can I see process output? Configure stdout_logfile and stderr_logfile, access logs via file system or Files service, tail logs in real-time with Files API.

Q: How do I check if a program is running? Call GET /status/{id} - look for status: "RUNNING" and presence of pid field.

Cause: Command fails, port already in use, missing dependencies, wrong user permissions. Solution: Check stderr log file, verify command works manually, ensure port is available, confirm user exists and has permissions, run command directly as that user to test.

Cause: Changes don’t apply to running processes. Solution: Follow proper sequence - stop, disable, edit, enable, start. Supervisord only reloads config on enable/disable.

Cause: autorestart: "false" or program disabled. Solution: Set autorestart: "true", ensure program is enabled, check it’s not in FATAL state, review supervisord logs.

Cause: Command exits normally, missing keep-alive loop, process detaches. Solution: Verify command stays running (not a one-shot task), add keep-alive loop if needed, check for immediate errors in logs.

Cause: Boot delay not set, priority too similar. Solution: Add delay_seconds between priorities, ensure priority numbers differ by 5+, check all programs have boot: true.

Cause: Status cache or supervisord mismatch. Solution: Refresh status endpoint, check supervisord directly, restart daemon manager if persistent, verify program actually running with ps.