A lightning-fast, highly secure alternative to PM2 or Supervisor—built specifically for modern Debian/Ubuntu servers.
Stop wrestling with complex configurations, high RAM overhead, and insecure wrappers. Lynx gives you superpowers by natively combining the rock-solid reliability of systemd with a beautiful, modern CLI.
| Feature | 🦁 Lynx | 🐢 PM2 | 🦖 Supervisor |
|---|---|---|---|
| Technology | Compiled Go (Native) |
Node.js (V8 Engine) |
Python (Interpreted) |
| Base RAM Overhead | ~10 MB ⚡ | ~60-100+ MB 🐌 | ~50+ MB 🐢 |
| Daemon Engine | Native OS (systemd) 🛡️ |
Custom (PM2 Daemon) ❌ | Custom (supervisord) ❌ |
| Crash Resilience | Perfect (Apps outlive CLI) | Poor (Apps die with PM2) | Poor (Apps die with daemon) |
| Sandboxing & Security | DynamicUser isolation 🔒 | Root / User-space |
Root / User-space |
| Config Format | CLI / Lynxfile.yml |
Ecosystem.config.js |
ini files |
The most powerful feature of Lynx. Start an API fully isolated: no access to /home, no new privileges, and secrets are passed securely via systemd without writing them to global disk variables.
lynx start api.js \
--name max-security-api \
--isolation dynamic \
--env-file .env.productionIt is impossible to achieve this level of security with one command in other managers.
Getting your app running has never been this easy.
# Download the latest binary
curl -L -o lynx "$(curl -s https://api.github.com/repos/Jaro-c/Lynx/releases/latest \
| grep browser_download_url | grep 'lynx_linux_amd64"' | cut -d '"' -f 4)"
chmod +x lynx
# Install system-wide (requires sudo):
sudo mv lynx /usr/local/bin/
# OR install for your user only (no sudo):
mkdir -p ~/.local/bin && mv lynx ~/.local/bin/
# Make sure ~/.local/bin is in your PATHIf you have the .deb (built from source or from a previous release):
sudo apt install ./lynx-pm_*.deb
# Add yourself to the lynx admin group & enable the daemon
sudo usermod -aG lynxadm $USER
newgrp lynxadm
sudo systemctl enable --now lynx.lynxd
# (Optional) Make your dev tools (bun, node, go) visible to Lynx
sudo lynx install-tools
# Verify the daemon is running securely
sudo systemctl status lynx.lynxdThat's it! Let's bring your app to life in seconds:
# Start your program and keep it running 24/7 forever
lynx start "node server.js" --name ultra-api --restart always
# Watch the magic happen with real-time stats
lynx list
# Check your application logs in real-time
lynx logs ultra-api --followLynx is language-agnostic — it runs anything you can spawn as a Linux process. Common one-liners:
| Stack | Example |
|---|---|
| Node.js | lynx start server.js (auto-detected) |
| Bun | lynx start "bun run server.ts" |
| Deno | lynx start "deno run --allow-net server.ts" |
| Python (system) | lynx start app.py --runtime python3 |
| Python (venv) | lynx start "/srv/api/.venv/bin/python app.py" |
| Python (uv / uvx) | lynx start "uv run app.py" --cwd /srv/api |
| Go (source) | lynx start main.go (auto-detected) |
| Go (binary) | lynx start ./bin/api --cwd /srv/api |
| Rust | lynx start ./target/release/api |
| Ruby / Rails | lynx start "bundle exec rails server" --shell |
| Java / JVM | lynx start "java -jar app.jar" |
| Shell | lynx start /srv/api/start.sh |
See docs/RUNTIMES.md for the full playbook —
version-managed runtimes (fnm/nvm/pyenv/rbenv), virtualenvs, env-file
injection, clustering with --scale, and the isolation-mode picker.
Step-by-step tutorials for common frameworks (Next.js, Express, FastAPI,
Django, Go, Bun, Rust) plus production deploy, Lynxfile.yml, cron jobs,
and isolation modes: docs/TUTORIALS.md.
"Can I…?" FAQ — rapid-fire yes/no for every common question
(naming, env vars, limits, isolation, errors): docs/FAQ.md.
If lynxd can't find your interpreter run lynx install-tools (user
install to ~/.local/bin) or sudo lynx install-tools --system.
Lynx supports two modes of operation:
- Daemon: Runs as a system service (
lynxd), managed bysystemd. - User:
lynx(system user). - Socket:
/run/lynxd/lynx.sock. - Permissions: Restricted to
rootand members of thelynxadmgroup (mode0660). - Environment: Does not inherit system environment variables (to prevent leaking secrets). Whitelists safe variables (
PATH,LANG,XDG_*,LC_*). - Use Case: Production servers where a central daemon manages services.
- Setup: Add your user to the
lynxadmgroup:sudo usermod -aG lynxadm $USER newgrp lynxadm
- Daemon: Runs as a user service (
systemd --user). - User: The current logged-in user.
- Socket:
$XDG_RUNTIME_DIR/lynx/lynx.sock. - Permissions: Restricted to the owner (
0600). - Environment: Inherits the full user environment.
- Use Case: Development environments or per-user service management.
| Command | Description | Documentation |
|---|---|---|
start |
Start a new process with monitoring, scheduling, isolation, and restart policies. | Docs |
list |
List all managed processes (--json for machine-readable output). |
Docs |
logs |
View and follow process logs (stdout/stderr). | Docs |
show |
Show detailed information about a process. | Docs |
stop |
Stop one or more running processes. | Docs |
restart |
Restart one or more processes. | Docs |
reload |
Reload process configuration and restart. | Docs |
flush |
Truncate process log files. | Docs |
delete |
Delete one or more processes and their configurations. | Docs |
reset |
Zero the Restarts counter without touching the running process. | Docs |
scale |
Scale an app to N instances post-hoc. | Docs |
monit |
Live dashboard of all managed processes. | Docs |
apply |
Apply a declarative Lynxfile.yml and start apps. | Docs |
export |
Export a namespace to Lynxfile.yml. | Docs |
startup |
Enable system startup for the daemon (systemd). | Docs |
version |
Display CLI, Daemon, and Protocol version information (--json). |
Docs |
update |
Check for updates and apply them. | Docs |
install-tools |
Symlink dev tools to ~/.local/bin (or --system for /usr/local/bin). |
Docs |
completion |
Generate shell completion scripts (bash, zsh, fish). | Docs |
help |
Show help for any command. | Docs |
| Flag | Description |
|---|---|
-q, --quiet |
Suppress success messages; errors still go to stderr. |
| Flag | Description |
|---|---|
--isolation <mode> |
self (default), dynamic (DynamicUser), sandbox (landlock + user ns) |
--memory-max <size> |
Hard memory ceiling: 512M, 2G, or raw bytes |
--cpu-max <percent> |
CPU cap as percent of one core (100 = 1 core) |
--tasks-max <N> |
Max threads + subprocesses |
--stop-signal <name> |
Signal on stop: SIGTERM (default), SIGINT, SIGHUP, etc. |
--stop-timeout <ms> |
Grace before SIGKILL (default 10000) |
--dry-run / -n |
Preview the resolved spec without starting |
--scale <N> |
Start N instances (or use lynx scale post-hoc) |
If you prefer modifying the source code or building the binaries yourself:
# 1. Clone repository
git clone https://github.com/Jaro-c/Lynx.git
cd Lynx
# 2. Build binaries manually
GOOS=linux GOARCH=amd64 go build -v -o lynx_linux_amd64 ./cmd/lynx
GOOS=linux GOARCH=amd64 go build -v -o lynxd_linux_amd64 ./cmd/lynxd
# 3. Build & Install Debian Package locally
sudo apt-get update && sudo apt-get install -y build-essential debhelper
dpkg-buildpackage -us -uc -b
sudo dpkg -i ../lynx-pm_*.debIf you prefer per-user isolation without system-wide privileges:
# Run lynxd as your user in the background
lynxd &
# Then use lynx with the default user-mode socket ($XDG_RUNTIME_DIR/lynx-<uid>/lynx.sock)
lynx listNote (v0.5.0+): User mode requires
XDG_RUNTIME_DIRto be set (standard on systemd-logind sessions: SSH, desktop,su -l). Cron jobs and bare non-login shells must exportLYNX_SOCKETto an absolute path in a private directory instead.
Note on
--isolation dynamic: this mode usessystemd-run DynamicUser=yes, which requires the system systemd instance (not user-systemd). In system mode, the Polkit rule installed by the.debpackage lets thelynxuser call it without sudo. In user mode,DynamicUseris unavailable because synthetic users are a system-level primitive.
- Install Lynx using either Option A or B above.
- Add your user to
lynxadm(system mode) and re-login or runnewgrp lynxadm. - Verify daemon logs:
journalctl -u lynx.lynxd -f
- Start your application:
lynx start app.js --name my-api --restart on-failure
- Use secure isolation for production:
lynx start app.js --name my-api --isolation dynamic --env-file .env
- Inspect and follow logs:
lynx logs my-api --follow
- Manage lifecycle:
lynx list lynx show my-api lynx reload my-api lynx restart my-api lynx stop my-api lynx delete --purge my-api
Use the prebuilt .deb and enable lynxd as shown in the Installation section.
lynx start "node server.js" --name hello --restart on-failurelynx start "node server.js" --name hello --scale 3 --shellNote: --shell enables variable expansion. Ensure each instance binds to a unique port.
lynx monit
lynx logs hello --followecho "PORT=8080" > .env
lynx start server.js --name secure-hello --isolation dynamic --env-file .envlynx export --namespace default > Lynxfile.yml
lynx apply Lynxfile.ymlNote for Windows Developers:
Since Lynx is Linux-only, we recommend using VS Code Remote-WSL.
If you are editing on Windows, you may see false positive errors (e.g., "build constraints exclude all Go files").
To fix this in your editor settings, set the environment variable:
GOOS=linux
Lynx is designed to be installed as a native Debian package. See docs/BUILDING_UBUNTU_RELEASE.md for full instructions.
When using --isolation dynamic, Lynx uses systemd-run to spawn transient services. The lynxd daemon runs as the lynx user.
- Standard Setup: The Debian package (
lynx-pm) automatically installs a restrictive Polkit rule (/usr/share/polkit-1/rules.d/lynx-pm.polkit.rules). - Security: This rule ONLY allows the
lynxuser to manage units whose names start withlynx-.- ✅ Allowed:
systemctl stop lynx-app-123.service - ❌ Blocked:
systemctl stop sshd.service,systemctl stop docker.service
- ✅ Allowed:
- No Action Required: You do not need to configure anything manually. The installation script handles permissions for you securely.