unitup v0.0.11
⚡ Zero-Daemon · Systemd-Native · Multi-Runtime

Systemd Service Management,Simplified for Any App.

unitup is a zero-dependency CLI & library to run Node.js, Python, Ruby, PHP, Bun, Deno, Go, Elixir, Shell scripts, and compiled native executables as native OS systemd user services without requiring sudo.

Quick Start (30-second try) bash
npm install -g unitup

# Add & start Node.js server
unitup add server.js --start
unitup status server
unitup logs server --follow

# Multi-runtime & Native executables
unitup add worker.py --runtime python --start
unitup add ./server --runtime native --name api --start

Core Promises

⚡ No Resident Daemon

Exits immediately after configuring services. Zero persistent memory or CPU overhead from unitup itself.

🌐 Multi-Runtime

Out-of-the-box support for Node.js, Python, Ruby, PHP, Bun, Deno, Go, Elixir, Shell, and native binaries.

🔒 Safe & Transparent

Avoids shell execution (shell: false). Saves standard text unit files directly to ~/.config/systemd/user/.

🛠️ Absolute Pathing

Resolves absolute binary & script paths and automatically injects proper PATH environment into unit files.

📦 Zero Dependencies

Built strictly with Node.js standard library modules. Extremely lightweight ESM & CJS footprint.

🔄 100% Backward Compatible

Full support for existing Node.js configurations and legacy metadata formats without breaking changes.

unitup vs PM2

unitup is not a PM2 replacement or an independent process manager. While PM2 runs its own master daemon, unitup is strictly a thin, transparent CLI layer on top of Linux OS systemd.

Feature unitup PM2
Background Process (Daemon) No resident daemon. Systemd directly supervises processes. Runs a persistent process-management daemon.
System Integration Native Linux OS systemd user service (~/.config/systemd/user/). Custom process monitoring via PM2's internal daemon.
Multi-Runtime Support Node, Python, Ruby, PHP, Bun, Deno, Go, Elixir, Shell, Native Binaries. Node.js-focused process manager with support for running other commands.
Privileges Required Does not require sudo for normal service creation and management. Boot integration commonly requires running PM2 startup with elevated privileges.
Dependencies 0 Runtime Dependencies (Node.js standard modules only). Dozens of 3rd party npm packages.
Log Management Delegates 100% to native Linux journald system (journalctl). Manages .pm2/logs files (requires pm2-logrotate plugin).
Boot Startup Native systemd lingering (loginctl enable-linger). Custom startup script launching PM2 master daemon.

Core Architecture

At its core, unitup generates systemd service unit files directly from a generic command + args model rather than being hardcoded to Node.js:

JSON Execution Model

{
  "command": "/usr/bin/python3",
  "args": ["/home/user/apps/worker.py"],
  "cwd": "/home/user/apps",
  "env": {
    "APP_ENV": "production"
  }
}

Generated Unit File (unitup-worker.service)

[Unit]
Description=unitup service: worker
After=network.target

[Service]
Type=simple
SyslogIdentifier=unitup-worker
WorkingDirectory=/home/user/apps
ExecStart=/usr/bin/python3 /home/user/apps/worker.py
Restart=on-failure
RestartSec=3
Environment=PATH="/usr/bin:/usr/local/bin:/bin"
Environment=APP_ENV="production"

[Install]
WantedBy=default.target

Supported Runtimes & Auto-Detection

Runtime Extension / Auto-Detection Command Executed
Node.js .js, .mjs, .cjs or shebang #!/usr/bin/env node node <script>
Python .py or shebang #!/usr/bin/env python3 python3 <script>
Ruby .rb or shebang #!/usr/bin/env ruby ruby <script>
PHP .php or shebang #!/usr/bin/env php php <script> (Supports -S 0.0.0.0:8080)
Bun Explicit --runtime bun or shebang #!/usr/bin/env bun bun <script>
Deno Explicit --runtime deno or shebang #!/usr/bin/env deno deno run <script>
Go .go or shebang #!/usr/bin/env go go run <script>
Elixir .ex, .exs or shebang #!/usr/bin/env elixir elixir <script>
Shell .sh or shebang #!/bin/bash / #!/bin/sh bash <script>
Native Executable Explicit --runtime native Direct binary execution (./server)
💡 Go Production Recommendation: For production deployments, compiling the Go application and registering the resulting native binary (unitup add ./server --runtime native) is recommended instead of go run.

CLI Reference

unitup doctor

Runs system readiness diagnostics (Linux OS, systemd PID 1, user bus, lingering, unit directory permissions, and detected runtimes).

unitup doctor

unitup add <script|exec> [options]

Generates and registers a new systemd user service unit file.

# Flags:
# --name         Service name (default: script basename)
# --runtime      Specify runtime (node, python, ruby, php, bun, deno, shell, go, elixir, native)
# --runtime-arg  Argument passed to binary (e.g. -S 0.0.0.0:8080 or --allow-net)
# --command     Explicit binary executable (bypasses auto-detection)
# --arg          Argument to pass to command
# --group      Assign service to group (default: default)
# --env KEY=val       Set environment variable
# --env-file    Load environment file
# --start             Enable and start service immediately
# --force, -f         Force overwrite of currently running service

unitup add worker.py --name worker --group backend --env APP_ENV=production --start

unitup list / unitup ls

Lists all managed services in a clean aligned table.

unitup list --group backend

unitup inspect <name>

Displays full service configuration overview (Command, Arguments, Working directory, Unit file) without revealing secrets or environment variables.

unitup inspect worker

unitup start / stop / restart <name|@group>

Controls service state individually or in batch using @group syntax.

unitup start @backend --enable
unitup restart worker
unitup stop @backend

unitup limits <name> [options]

Configures native systemd memory limits for a service or resets limits back to system defaults.

unitup limits api --memory-high 400M --memory-max 512M --swap-max 256M
unitup limits api --reset-memory

unitup status / logs <name>

Inspects process status with live memory metrics or streams journalctl logs with advanced filtering.

unitup status worker
unitup logs worker --follow --since 1h --priority err --json

unitup journal <action> [options]

Performs safe journalctl storage maintenance (disk-usage, rotate, vacuum by size, time, or file count).

unitup journal disk-usage
unitup journal rotate
unitup journal vacuum --size 500M --yes
unitup journal vacuum --time 14d --dry-run

unitup remove <name|@group> [--force]

Stops, disables, and deletes a service or group. Active running services require --force / -f to prevent accidental deletion.

unitup remove worker
unitup remove @backend --force

Programmatic API

unitup exports full ESM and CommonJS interfaces with TypeScript declarations (index.d.ts).

ESM / TypeScript Example

import {
  createService,
  startService,
  stopService,
  restartService,
  getServiceStatus,
  listServices,
  isSystemdAvailable
} from "unitup";

import type {
  CreateServiceOptions,
  ServiceStatus
} from "unitup";

if (await isSystemdAvailable()) {
  // Add service with explicit command + args
  await createService({
    name: "worker",
    command: "/usr/bin/python3",
    args: ["/home/user/apps/worker.py"],
    cwd: "/home/user/apps",
    restart: "on-failure",
    start: true
  });

  const status: ServiceStatus = await getServiceStatus("worker");
  console.log(`PID: ${status.pid}, Status: ${status.status}`);
}

CommonJS Support

const {
  createService,
  startService,
  getServiceStatus
} = require("unitup");

await createService({
  name: "api",
  script: "./server.js",
  start: true
});

Declarative Stack Configuration (Roadmap Preview)

Define your entire application stack declaratively using unitup.yml or unitup.json:

unitup.yml Spec

apps:
  api:
    runtime: node
    script: ./server.js
    env:
      NODE_ENV: production
      PORT: 3000
    start: true

  worker:
    runtime: python
    script: ./worker.py
    env:
      APP_ENV: production

  native-service:
    runtime: native
    command: ./server

Planned Declarative Commands

# Preview differences against active units
unitup diff

# Apply unitup.yml configuration
unitup apply

# Perform batch operations on group
unitup restart @default

*Note: Relative script, command, cwd, and env-file paths in unitup.yml are resolved relative to the configuration file.

Troubleshooting & User Lingering

Enable User Lingering (Persistent Services)

Depending on the Linux distribution and systemd-logind configuration, user services may stop after logout. Enable lingering to allow them to continue running without an active login session:

loginctl enable-linger $USER

Verify lingering state anytime with unitup doctor. unitup will warn if lingering is disabled but will never prompt for sudo automatically.