A very lightweight, self-contained Go service to automatically start and stop pm2-managed apps on-demand.
Perfect for dev servers or when hosting several (very) low-traffic sites, saving system resources by only running
the apps when accessed.
Keeping many apps running simultaneously, especially on a server with limited resources, is inefficient when they receive a very low traffic (like a family recipe website...). Each running app consumes memory (around 150 Mb per app), even when idle, while this tiny go service consumes only 10 Mb at most!
This Waker Service acts as a central manager. It keeps your apps stopped by default and only starts them when a request comes in.
If an app receives no traffic for a configurable period of time, the service automatically stops it again.
- User accesses a site (e.g.,
my-recipe-app.com). Its pm2 process is stopped. - Nginx returns a 502 error.
- Custom Nginx error rule calls the Waker Service’s
/startendpoint (e.g.,http://127.0.0.1:1234/start?app=my-recipe-app). - Waker Service starts the app with
pm2 start my-recipe-appand sets an inactivity timer. - Nginx automatically retries the request, which now works.
- On each successful request, Nginx sends a silent "ping" to reset the timer (e.g.,
http://127.0.0.1:1234/ping?app=my-recipe-app). - If the timer ends, the service stops the web app with
pm2 stop my-recipe-app.
- Go version 1.22+
- pm2 installed and configured
- Nginx
Clone this repository and build the Go binary:
git clone https://github.com/Crossoufire/go-waker.git
cd go-waker
go build -o wakerMove the binary and its config to a suitable location:
sudo mkdir -p /your/location/folder
cp waker /your/location/folder
cp config.json.example /your/location/folder/config.json- Edit the config file to define your apps and their idle timeout in seconds.
- The app name must match the name used in pm2.
/your/location/folder/config.json:
{
"my-recipe-app": 300,
"another-blog": 600,
"portfolio-site": 1800
}Create a systemd service file to run the Waker as a daemon:
sudo nano /etc/systemd/system/waker.service- Paste the following content.
- Change
UserandGroupto the user that runs your pm2 processes. - Change also the
WorkingDirectoryandExecStartlocations.
[Unit]
Description=Go Waker Service for PM2 Apps
After=network.target
[Service]
Type=simple
User=your_user
Group=your_user_group
WorkingDirectory=/opt/waker-service
ExecStart=/opt/waker-service/waker
Restart=on-failure
RestartSec=3s
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable waker.service
sudo systemctl start waker.service
# Check health status
sudo systemctl status waker.service
# Check logs in real time
sudo journalctl -u waker -fIf you do modification on the config.json file, you will need to restart the go Waker service:
sudo systemctl restart waker.serviceYou will need two Nginx snippets and then include them in your server blocks.
This snippet handles the wake-up call on a 502/504 error.
sudo nano /etc/nginx/snippets/waker-start.conf:
location @wakeup {
internal;
proxy_pass http://127.0.0.1:5555/start?app=$waker_app_name;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
error_page 502 504 =200 @wakeup;This snippet sends a ping after each successful request to reset the timer.
sudo nano /etc/nginx/snippets/waker-ping.conf:
location @ping_waker {
internal;
proxy_pass http://127.0.0.1:5555/ping?app=$waker_app_name;
proxy_set_header Host $host;
}Here is how to use the snippets in your site's Nginx config:
server {
listen 80;
server_name my-recipe-app.com;
# --- WAKER CONFIGURATION -------
# Set app name for waker service. This **MUST** match the name in your config.json and pm2.
set $waker_app_name "my-recipe-app";
include snippets/waker-start.conf;
include snippets/waker-ping.conf;
# -------------------------------
location / {
# --- WAKER PING ----------
# This executes @ping_waker after main request is finished.
post_action @ping_waker;
# -------------------------
# Your other proxy pass to the app
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
# ... other proxy headers
}
}Finally, test and reload your Nginx config:
sudo nginx -t
sudo systemctl reload nginx