relife2 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +210 -0
- package/dist/cli.js +4778 -0
- package/dist/cli.js.map +7 -0
- package/package.json +39 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 relife2 contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# relife2 — your apps stay up. Period.
|
|
2
|
+
|
|
3
|
+
**The PM2 you wish you had from day one — without the gotchas.**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/relife2) [](./LICENSE)   
|
|
6
|
+
|
|
7
|
+
> You run 5–10 apps on one VPS. PM2 was great — until `pm2 update` silently spawned a second daemon, `pm2 save` was forgotten after a reboot, and bun apps ran as `node` with extra overhead. **relife2 is the fix.**
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
### Why teams switch from PM2
|
|
12
|
+
|
|
13
|
+
| PM2 pain you know | relife2 answer |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `pm2 update` duplicates the God daemon → 2→4→8 daemons, OOM | **Exactly one daemon, always.** Socket bind + `flock`. Second daemon can't start. `daemon-upgrade` is explicit and locked. |
|
|
16
|
+
| Reboot wipes everything if you forgot `pm2 save` | **Autosave on by default.** Every change hits `snapshot.json` + journal. Reboot → `systemd` + linger → all apps back. |
|
|
17
|
+
| `interpreter: bun` actually runs as node | **Bun is first-class.** `bun <script>` directly, auto-detect via `bun.lockb`/`bun.lock`, `bun --hot` in dev. |
|
|
18
|
+
| Log files grow forever (needs pm2-logrotate) | **Built-in rotation:** `rotate --max-size --retain` with gzip, no plugin. |
|
|
19
|
+
| Unknown config fields silently ignored | **Honest errors:** warnings for unknown fields, errors for incompatible combos. |
|
|
20
|
+
| Daemon is heavy (God ~60–90 MB) | **Light:** ~20–30 MB RSS daemon, no God overhead. |
|
|
21
|
+
|
|
22
|
+
> **One command to prove it:**
|
|
23
|
+
> `relife2 doctor` — checks snapshot, lock, orphans, transport, uptime. PM2 has no equivalent.
|
|
24
|
+
|
|
25
|
+
### Who is it for
|
|
26
|
+
|
|
27
|
+
- **Solo dev / small team** with 5–15 apps on a single Oracle Linux 9 / Debian / Ubuntu VPS (the primary target — developed on Windows, but **Linux-first**)
|
|
28
|
+
- You use **Caddy** for TLS/reverse proxy and want real supervision for the upstreams
|
|
29
|
+
- You ship **Bun + Node** mix (Nuxt, Astro, bots, Java services, Rust binaries)
|
|
30
|
+
- You are tired of babysitting processes
|
|
31
|
+
|
|
32
|
+
If you run Kubernetes for everything, you don't need this. If you run a VPS and want `systemd`-grade reliability without writing unit files by hand — you do.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### 30-second demo
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
npm i -g relife2 # or: curl single binary → /usr/local/bin/relife2
|
|
40
|
+
relife2 start ecosystem.config.cjs
|
|
41
|
+
relife2 list
|
|
42
|
+
relife2 logs web -f # follow
|
|
43
|
+
relife2 doctor # 5 checks, exit 1 on error
|
|
44
|
+
relife2 startup # systemd user unit + loginctl enable-linger
|
|
45
|
+
# reboot → everything is back. No pm2 save dance.
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Migrate from PM2 in one line:**
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
relife2 import-pm2 ~/.pm2/dump.pm2 && relife2 list # reads PM2 dump, starts via relife2
|
|
52
|
+
relife2 from-caddy /etc/caddy/Caddyfile --dry-run # Caddyfile → relife2.config.cjs
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Find forgotten configs (the PM2 paper trail):**
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
relife2 find # scans $HOME depth 6
|
|
59
|
+
relife2 find --root /opt --depth 8 --json | jq .
|
|
60
|
+
relife2 find start # starts every stopped config it found
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### Features that sell themselves
|
|
66
|
+
|
|
67
|
+
- **Single binary deploy:** `bun build --compile` → `relife2-linux-x64` (~40–60 MB). No Node/Bun on the VPS. `tar.gz` / `.rpm` / `.deb` ready.
|
|
68
|
+
- **Forgotten-path healing:** moved from `/home/debian` to `/opt`? Configs with stale `cwd`/`script` auto-fix (tries `~/tail`, `sourceDir`, basename search) and logs `not found → auto-fixed` instead of crash-looping.
|
|
69
|
+
- **Caddy-native:** `from-caddy` parses `reverse_proxy`/`php_fastcgi` loopback upstreams, generates one app per port with `HOST`/`PORT`/`SITE_URL`, finds entry (`Nuxt .output/server/index.mjs` etc.), `--dry-run` plan before writing.
|
|
70
|
+
- **Dev that doesn't fight you:** `relife2 dev ./server.ts --watch ./src --hot` → `bun --hot` for `.ts`, `fs.watch` otherwise. `q` to quit.
|
|
71
|
+
- **Upgrade without drama:** `relife2 daemon-upgrade` — `save → shutdown old → spawn new → resurrect` under lock, protocol version checked. No silent second daemon.
|
|
72
|
+
- **Observability out of the box:** `list` / `describe` / `metrics` (daemon + per-app RSS) / `monit` TUI / `logs --lines -f`.
|
|
73
|
+
- **PM2-compatible config surface:** `ecosystem.config.{js,cjs,mjs,json}` + `relife2.config.ts`, all 8 `example/` configs work without edits (golden tests).
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### Installation
|
|
78
|
+
|
|
79
|
+
**npm (any OS, Node ≥20):**
|
|
80
|
+
```sh
|
|
81
|
+
npm i -g relife2
|
|
82
|
+
relife2 --version # relife2 1.0.0 (node)
|
|
83
|
+
rl2 --version # alias
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Single binary (VPS — recommended, no runtime on target):**
|
|
87
|
+
```sh
|
|
88
|
+
npm run build:single:linux # → dist/relife2-linux-x64
|
|
89
|
+
scp dist/relife2-linux-x64 vps:/usr/local/bin/relife2
|
|
90
|
+
ssh vps 'chmod +x /usr/local/bin/relife2 && relife2 --version'
|
|
91
|
+
# or from GitHub Releases:
|
|
92
|
+
curl -L https://github.com/<org>/relife2/releases/latest/download/relife2-linux-x64 -o /usr/local/bin/relife2
|
|
93
|
+
chmod +x /usr/local/bin/relife2
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**tar.gz / rpm / deb:**
|
|
97
|
+
```sh
|
|
98
|
+
npm run dist:tar # → dist/relife2-1.0.0-linux-x64.tar.gz (binary + README + LICENSE)
|
|
99
|
+
npm run dist:rpm # → dist/relife2-1.0.0-1.x86_64.rpm (needs fpm)
|
|
100
|
+
npm run dist:deb # → dist/relife2_1.0.0_amd64.deb (uses dpkg-deb or fpm)
|
|
101
|
+
sudo dnf install ./dist/relife2-*.rpm # Oracle Linux / RHEL / Fedora
|
|
102
|
+
sudo apt install ./dist/relife2_*_amd64.deb # Debian / Ubuntu
|
|
103
|
+
```
|
|
104
|
+
All packages install `/usr/bin/relife2` + `/usr/bin/rl2`; autostart is still `relife2 startup` (user unit) so it respects `XDG_RUNTIME_DIR`.
|
|
105
|
+
|
|
106
|
+
**Autostart (Linux):**
|
|
107
|
+
```sh
|
|
108
|
+
relife2 startup # writes ~/.config/systemd/user/relife2.service + loginctl enable-linger
|
|
109
|
+
systemctl --user daemon-reload && systemctl --user enable --now relife2
|
|
110
|
+
systemctl --user status relife2
|
|
111
|
+
relife2 doctor
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### Quick Start
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
# 1. From a config (PM2-compatible)
|
|
120
|
+
relife2 start ecosystem.config.cjs
|
|
121
|
+
relife2 list
|
|
122
|
+
relife2 logs myapp --lines 100
|
|
123
|
+
relife2 doctor
|
|
124
|
+
|
|
125
|
+
# 2. Single script
|
|
126
|
+
relife2 start ./server.js --name myapp -- --port 3000
|
|
127
|
+
|
|
128
|
+
# 3. Auto-discover relife2.config.* / ecosystem.config.* in cwd
|
|
129
|
+
relife2 start
|
|
130
|
+
|
|
131
|
+
# 4. Zero-downtime reload / scale
|
|
132
|
+
relife2 reload myapp
|
|
133
|
+
relife2 start --instances max --exec-mode cluster --env production
|
|
134
|
+
|
|
135
|
+
# 5. Find & rescue forgotten configs
|
|
136
|
+
relife2 find --root /opt --depth 8
|
|
137
|
+
relife2 find start
|
|
138
|
+
|
|
139
|
+
# 6. Caddyfile → relife2
|
|
140
|
+
relife2 from-caddy /etc/caddy/Caddyfile --dry-run
|
|
141
|
+
relife2 from-caddy /etc/caddy/Caddyfile -o relife2.config.cjs && relife2 start relife2.config.cjs
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
More → [docs/CLI.md](./docs/CLI.md) · [docs/CONFIG.md](./docs/CONFIG.md) · [docs/INSTALL.md](./docs/INSTALL.md)
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### Config at a glance
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
// ecosystem.config.cjs — same file you use for PM2
|
|
152
|
+
module.exports = {
|
|
153
|
+
apps: [{
|
|
154
|
+
name: "web",
|
|
155
|
+
script: "./dist/server/entry.mjs",
|
|
156
|
+
cwd: __dirname,
|
|
157
|
+
interpreter: "bun", // "bun" | "node" | "none" | "/usr/bin/python"
|
|
158
|
+
args: ["--port", "3000"], // string or string[]
|
|
159
|
+
instances: "max", // number | "max" (= cpu count)
|
|
160
|
+
exec_mode: "cluster",
|
|
161
|
+
env: { NODE_ENV: "production", PORT: "3000" },
|
|
162
|
+
env_production: { PORT: "4000" }, // merged with --env production
|
|
163
|
+
env_file: "./.env", // dotenv, does NOT override real env
|
|
164
|
+
out_file: "./logs/web-out.log",
|
|
165
|
+
error_file: "./logs/web-err.log",
|
|
166
|
+
merge_logs: true,
|
|
167
|
+
time: true,
|
|
168
|
+
log_date_format: "YYYY-MM-DD HH:mm:ss Z",
|
|
169
|
+
autorestart: true,
|
|
170
|
+
max_restarts: 15,
|
|
171
|
+
restart_delay: 3000,
|
|
172
|
+
min_uptime: "10s",
|
|
173
|
+
kill_timeout: 5000,
|
|
174
|
+
max_memory_restart: "512M",
|
|
175
|
+
cron_restart: "0 4 * * *",
|
|
176
|
+
watch: false, // true | false | ["./src", ".env"]
|
|
177
|
+
watch_delay: 1000,
|
|
178
|
+
wait_ready: false, // wait for process.send('ready')
|
|
179
|
+
}]
|
|
180
|
+
};
|
|
181
|
+
```
|
|
182
|
+
Full matrix → [docs/CONFIG.md](./docs/CONFIG.md). CLI overrides: `relife2 start --env production --instances max`.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### Bun, Caddy, Linux — first-class
|
|
187
|
+
|
|
188
|
+
- **Bun:** `interpreter: "bun"` spawns `bun` directly; auto-detect via `bun.lockb`/`bun.lock` or `.ts` script; `relife2 dev ./app.ts` uses `bun --hot` (HMR); `bun relife2 ...` works (CI matrix `node`+`bun`).
|
|
189
|
+
- **Caddy:** Caddy does TLS/static/proxy, relife2 does supervision. `from-caddy` + `# relife2: dir=… name=…` hints.
|
|
190
|
+
- **Linux:** XDG-first data (`$XDG_DATA_HOME/relife2`) + runtime (`$XDG_RUNTIME_DIR/relife2`), `RELIFE2_DIR` override for tests, `/proc` RSS, `setsid` process groups, systemd `Restart=always` + `KillMode=process`. SELinux enforcing = experimental (default contexts, no custom policy — author has it disabled).
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### Development & benchmark
|
|
195
|
+
|
|
196
|
+
```sh
|
|
197
|
+
npm install
|
|
198
|
+
npm run build # → dist/cli.js (esbuild, single ESM, shebang)
|
|
199
|
+
npm run typecheck && npm run lint && npm test # 67 tests (m7 integrity inside)
|
|
200
|
+
bun dist/cli.js --version
|
|
201
|
+
npm run bench # startup latency + daemon RSS
|
|
202
|
+
npm run bench -- --pm2 # compare with PM2 (if installed)
|
|
203
|
+
```
|
|
204
|
+
See [docs/BENCHMARK.md](./docs/BENCHMARK.md) — numbers are host-dependent, run on your VPS for truth.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
### License
|
|
209
|
+
|
|
210
|
+
MIT — see [LICENSE](./LICENSE). Roadmap → [TODO.md](./TODO.md), decisions → [docs/DECISIONS.md](./docs/DECISIONS.md).
|