Skip to content
Hoody.com

Hoody Daemons is a process manager you drive over HTTP. It supervises any executable: Node.js, Python, Go, Rust, compiled binaries, and shell scripts. There is no CLI to install and no language-specific tooling, and a REST API creates programs, starts and stops them, and reports their state.

  • Program management - Create, configure, and delete daemon programs
  • Process control - Start, stop, enable, and disable programs
  • Status monitoring - Read process state, uptime, and PID
  • Auto-restart - Choose whether a program restarts always, never, or only after an unexpected exit
  • Priority control - Set the startup order so dependencies come up first
  • Logging - Point stdout and stderr at log files
  • User isolation - Run each process as a specific system user
  • Environment - Set custom environment variables per program

All endpoints are relative to your Daemon Manager service URL:

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

Program management:

Process control:

Monitoring:

Logs:

Quick start (ephemeral programs):

Enable → Start → Stop → Disable → Remove

Terminal window
# Create a daemon program (required fields are passed as flags)
hoody daemon programs create --name web-server \
--command '/usr/bin/node /app/server.js' --user www-data -c my-container-id
# Enable and start (use the numeric Program ID returned by create/list)
hoody daemon programs enable <program-id> -c my-container-id
hoody daemon programs start <program-id> -c my-container-id
# Check status
hoody daemon programs status <program-id> -c my-container-id
# Stop and remove
hoody daemon programs stop <program-id> -c my-container-id
hoody daemon programs disable <program-id> -c my-container-id
hoody daemon programs delete <program-id> -c my-container-id --yes

enabled defaults to true, so a program you add starts running the moment supervisord picks it up. Pass enabled: false to add it without starting it, check the configuration, then enable and start it deliberately:

Terminal window
hoody daemon programs create --name web-server \
--command '/usr/bin/node /app/server.js' --user www-data \
--no-enabled --autorestart true --directory /app -c my-container-id

Then enable, start, and monitor it as shown in the lifecycle example above.

Enable is a configuration change:

  • Makes the program available to supervisord
  • Does not start the process
  • Required before starting

Start is a runtime action:

  • Launches the process
  • Only works if the program is enabled
  • Creates a running process with a 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 through the 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:

{
"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 a startup priority if there are dependencies, and monitor them through the status endpoint.

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

Run custom application services, workers, and scripts with a defined startup order and auto-restart policy. 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 the configuration before enabling, test manually before setting boot: true, and turn on auto-restart only after stability testing.

Stop the process first, then disable the program so auto-restart does not bring it back. Edit the configuration, enable and start it again, and verify the new configuration works before cleaning up.

Always configure stdout and stderr logs, use absolute paths for log files, rotate logs to manage disk space, and watch them for errors and warnings.

Run each program as an appropriate system user, never as root unless it is required. Create a dedicated user per service type and give it only the privileges it needs.

Use the priority field for startup ordering: low numbers (1-5) for core services, higher numbers (10-20) for dependent services. Test the boot sequence thoroughly.

Poll the /status endpoint regularly, alert on BACKOFF or FATAL states, track uptime for reliability metrics, and run health checks through 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 or sockets in the command, different data directories, and distinct priority values.

Q: Can I see process output? Configure stdout_logfile and stderr_logfile, then read the logs from the filesystem or through the Files service, which can tail them in real time with the Files API.

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

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

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

Cause: autorestart: "false" or program disabled. Solution: Set autorestart: "true", make sure the program is enabled, check it is not in FATAL state, and review the supervisord logs.

Cause: Command exits normally, missing keep-alive loop, process detaches. Solution: Verify the command stays running rather than finishing as a one-shot task, add a keep-alive loop if needed, and check the logs for errors on startup.

Cause: Boot delay not set, priority too similar. Solution: Add delay_seconds between priorities, keep priority numbers at least 5 apart, and check that all programs have boot: true.

Cause: Status cache or supervisord mismatch. Solution: Refresh the status endpoint, check supervisord directly, restart the daemon manager if the mismatch persists, and confirm with ps whether the program is actually running.