Skip to content

PM2

Use this when you run bunqueue on a box and want the dashboard to also manage the process (start / stop / restart with live logs). PM2 keeps the all-in-one server alive, restarts it on crash, and brings it back on reboot.

The all-in-one server (scripts/serve.ts) does three jobs in one process:

  1. serves the dashboard SPA,
  2. proxies /api/* to your bunqueue server same-origin (no CORS), and
  3. runs the control agent on 127.0.0.1 for Server Control.

Get the server

Pick one:

bash
# A) Install from npm (needs Bun), zero-dependency package.
bun add -g bunqueue-dashboard        # then: bunqueue-dashboard
# one-off, no install:  bunx bunqueue-dashboard

# B) Download a standalone binary from the GitHub Releases (no runtime needed).
#    Assets: bunqueue-dashboard-<tag>-<os>-<arch>  (linux/macos x64+arm64, windows x64)
#    Replace <tag> with the latest release tag, e.g. v0.0.15:
curl -L -o bunqueue-dashboard \
  https://github.com/egeominotti/bunqueue-dashboard/releases/latest/download/bunqueue-dashboard-<tag>-linux-x64
chmod +x bunqueue-dashboard

# C) Build the binary yourself (needs Bun).
bun run build:bin      # → ./bunqueue-dashboard

# D) Run from source (needs Bun).
bun run scripts/serve.ts

Configure it

All configuration is via environment variables:

VariableDefaultPurpose
PORT8080Port the dashboard + /api proxy listen on
BIND_ADDR127.0.0.1Interface the dashboard binds to; set 0.0.0.0 for direct LAN access (no reverse proxy)
BUNQUEUE_URLhttp://localhost:6790The bunqueue server to proxy to
AGENT_PORT6800Control agent port (always bound to 127.0.0.1)
AGENT_TOKENunsetBearer token required on state-changing agent requests
AGENT_ALLOWED_ORIGINSthe served originsExtra browser origins allowed to drive the agent
LOG_LEVELinfopino log level (debug / info / warn / error)

Secure the agent

The control agent can spawn processes. It only ever binds 127.0.0.1, but if the box is multi-user or the dashboard is public, set an AGENT_TOKEN so start / stop / restart requires it.

PM2 ecosystem file

Save as ecosystem.config.cjs next to the binary:

js
module.exports = {
  apps: [
    {
      name: 'bunqueue-dashboard',
      script: './bunqueue-dashboard', // the compiled binary
      env: {
        PORT: 8080,
        BUNQUEUE_URL: 'http://localhost:6790',
        AGENT_TOKEN: 'change-me',
      },
      autorestart: true,
      max_restarts: 10,
    },
  ],
};

Running from source or from the npm global install instead of the binary? Use Bun as the interpreter:

js
// from source:      script: 'scripts/serve.ts', interpreter: 'bun',
// from npm global:  script: 'bunqueue-dashboard', interpreter: 'bun',

Start, persist, boot

bash
pm2 start ecosystem.config.cjs
pm2 save          # remember the process list
pm2 startup       # print the command to start PM2 on boot, then run it

Useful day-to-day:

bash
pm2 logs bunqueue-dashboard     # tail logs
pm2 restart bunqueue-dashboard  # after a config change
pm2 status                      # health at a glance

Open http://localhost:8080 (or your reverse-proxied domain). Because /api is proxied same-origin, there is no CORS to configure, and Server Control works because the control agent runs in the same process.

Prefer systemd?

The binary is a plain executable, so a unit works just as well:

ini
[Unit]
Description=bunqueue dashboard
After=network.target

[Service]
ExecStart=/opt/bunqueue-dashboard/bunqueue-dashboard
Environment=PORT=8080
Environment=BUNQUEUE_URL=http://localhost:6790
Environment=AGENT_TOKEN=change-me
Restart=on-failure

[Install]
WantedBy=multi-user.target

Drives a bunqueue server over its public HTTP API plus a local control agent.