And yes, your PHP queue workers, Go binaries, and Python bots can finally coexist in peace.**
Suggested hero image: Unsplash β Taylor Vick (Server Room)
The Itch I Couldn't Stop Scratching
If you've ever managed a VPS β especially with something like Virtualmin β you know the pain. You've got 14 users on a shared server. Dave is running a Laravel queue worker. Sarah has a Go API. And someone named admin3 (who no one remembers creating) is running a rogue Python Discord bot eating 90% of the RAM.
You SSH in. You nohup. You screen. You pray.
PM2? Great tool! ...if your entire universe is Node.js. But the moment you need to babysit a PHP artisan command or a compiled Go binary, PM2 looks at you like you just spoke Klingon.
I needed something that:
- Let non-root users manage their own processes (without calling me at 2 AM)
- Was language-agnostic β Go, PHP, Python, Rust, a bash script that plays elevator music β I don't judge
- Had real resource limits so one bad actor doesn't nuke the whole server
- Was dead simple to configure
So I built it. Meet PQPM β the Process Queue Process Manager.
Suggested image: Unsplash β Gabriel Heinzer (Terminal/Code)
What Even Is PQPM?
PQPM is a lightweight, system-level process manager written in Go. It runs as a daemon (pqpmd) on your Linux server and lets any user on the system manage their own long-running processes through a simple CLI (pqpm).
Think of it as a bouncer at a nightclub: the daemon has the master key (runs as root), but it immediately drops privileges to match the user who's requesting the action. User A can't touch User B's stuff. Period.
Here's the whole mental model:
-
The Daemon (
pqpmd) β runs as root, listens on a Unix socket -
The Config (
~/.pqpm.toml) β each user defines their services in a dead-simple TOML file -
The CLI (
pqpm) β users run commands likepqpm start my-workerwith zero sudo required -
The Magic β the daemon verifies the caller's identity using kernel-level socket credentials (
SO_PEERCRED), then spawns the process under that user's UID/GID
No sudo. No chmod 777 hacks. No "just run everything as root and hope for the best."
The Config File is Chef's Kiss π€
I'm a sucker for simple config files. XML can leave. YAML can take its "is this a string or a boolean" energy elsewhere. TOML just... makes sense.
Here's what a user's ~/.pqpm.toml looks like:
[service.my-worker]
command = "/usr/bin/php /home/user/public_html/artisan queue:work"
restart = "always"
max_memory = "512MB"
cpu_limit = "20%"
[service.api-server]
command = "/home/user/bin/api-server --port 8080"
restart = "on-failure"
max_memory = "1GB"
cpu_limit = "50%"
working_dir = "/home/user/api"
env = { NODE_ENV = "production", PORT = "8080" }
[service.python-bot]
command = "/usr/bin/python3 /home/user/bots/discord_bot.py"
restart = "always"
max_memory = "256MB"
cpu_limit = "10%"
Three services. Three languages. One config file. Zero drama.
Suggested image: Unsplash β Chinmay B (Gopher) or any Go mascot image from Gopherize.me
Why Go? Because Speed is Non-Negotiable
When your process manager is responsible for keeping other people's services alive, it better not be the thing that dies first.
Go gave me:
- Goroutines & channels for async, non-blocking process monitoring (each managed process gets its own goroutine β beautiful)
-
Static binaries β
pqpmdandpqpmare single-file executables. No runtime. No dependencies. Justcurl, extract, and go -
First-class syscall support β spawning processes, dropping privileges with
setuid/setgid, readingSO_PEERCREDfrom Unix sockets β Go'sgolang.org/x/syspackage is a dream -
Cross-compilation β building for
amd64andarm64in onemakecommand
The entire dependency tree is laughably small: BurntSushi/toml for config parsing, spf13/cobra for the CLI, and golang.org/x/sys for syscalls. That's it. Three dependencies. In 2025. I'll wait while you pick your jaw up off the floor.
Security: The Part I Lost Sleep Over (So You Don't Have To)
This is a process manager that runs as root. Let me say that louder for the people in the back: it runs as root. If the security isn't airtight, you might as well email your SSH keys to a stranger.
Here's how PQPM stays paranoid (in a healthy way):
π Identity via SO_PEERCRED
When the CLI connects to the daemon over a Unix Domain Socket, the daemon asks the kernel β not the user β "who is this?" The kernel responds with the UID, GID, and PID. No tokens. No passwords. No trust-me-bro headers. The kernel doesn't lie.
πͺ Immediate Privilege Drop
The daemon spawns the process as root but instantly drops to the target user's UID/GID. The spawned process never runs with elevated privileges. Not even for a millisecond... well, maybe a couple of nanoseconds. Go is fast.
π§± Resource Limits via cgroups
Each process can have hard limits on memory and CPU using Linux cgroups (v2). If Dave's queue worker decides to allocate 16 GB of RAM, cgroups will politely (and firmly) say no.
π Path Restrictions
Processes are locked to running within the user's authorized directories. No sneaky ../../etc/shadow business.
Suggested image: Unsplash β FlyD (Neon Lock)
The CLI: Boring On Purpose
I didn't want a CLI that requires a PhD to operate. Six commands. That's your entire vocabulary:
| Command | What It Does |
|---|---|
pqpm start <name> |
Fire up a service |
pqpm stop <name> |
Gracefully stop it |
pqpm restart <name> |
Stop + start (shocking, I know) |
pqpm status |
See what's running |
pqpm log <name> |
Tail logs for a service |
pqpm version |
Print the version |
That's it. No pqpm init --template advanced --with-monitoring --enable-clustering --sacrifice-goat. Just start, stop, restart, status, log, version. Done.
Installation: The One-Linerβ’
curl -sSL https://raw.githubusercontent.com/pqpm/pqpm/main/install.sh | sudo bash
This detects your architecture, pulls the latest release from GitHub, drops the binaries into /usr/local/bin, creates runtime directories, and sets up the systemd service. The whole thing takes about 5 seconds.
Want to build from source? Also easy:
git clone https://github.com/pqpm/pqpm.git
cd pqpm
make build && sudo make install
Updating? Run the one-liner again. Your managed processes keep running and get "re-adopted" by the daemon once it restarts. Like a responsible parent coming home from the grocery store.
Suggested image: Unsplash β SpaceX (Rocket Launch)
Who Is This For?
- VPS admins running shared hosting environments (especially Virtualmin/Webmin setups)
- Small teams where multiple developers deploy services on the same box
- Anyone tired of PM2 who runs more than just Node.js
- The sysadmin who wants their users to stop asking for root access to run a queue worker
- Solo devs running a $5 VPS with a Go API, a PHP backend, and a Python cron job β all at once
If you've ever typed nohup something & and then immediately regretted your life choices, PQPM is for you.
What's Next?
PQPM is at v0.2.3 and actively being developed. Here's what's on the roadmap (or at least, living rent-free in my head):
- π Web dashboard β because sometimes you want to click buttons instead of typing commands
- π Notifications β get pinged when a process dies (and auto-restarts)
- π Metrics export β Prometheus-compatible resource usage stats
- π³ Container-aware mode β playing nice with Docker environments
- π§ͺ More tests β always more tests
Suggested image: Unsplash β Annie Spratt (Team collaboration)
Give It a Spin β
PQPM is open-source (MIT licensed) and lives at github.com/pqpm/pqpm.
If it saves you even one sudo argument with a client, one 2 AM SSH session, or one "why is the server at 100% CPU" panic β I'll consider it a win.
Star the repo if you dig it. Open an issue if you find a bug. Submit a PR if you're feeling generous. Or just silently use it and never tell me β that's cool too. I'll never know. But my download counter will. π
Built with πΉ Go, β too much coffee, and a burning hatred for nohup.
Image Source Summary
Here's a quick reference for all the suggested images (all free to use via Unsplash):
| Section | Image | Source |
|---|---|---|
| Hero / Banner | Server room / data center | Unsplash β Taylor Vick |
| "What Is PQPM" | Terminal with code | Unsplash β Gabriel Heinzer |
| "Why Go?" | Go gopher / mascot | Gopherize.me or Unsplash |
| Security section | Neon lock / cybersecurity | Unsplash β FlyD |
| Installation | Rocket launch | Unsplash β SpaceX |
| Community / CTA | Team collaboration | Unsplash β Annie Spratt |
Top comments (0)