Skip to content

A very lightweight Go service that manages PM2-driven apps, starting them on-demand via Nginx and stopping them after inactivity.

License

Notifications You must be signed in to change notification settings

Crossoufire/go-waker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PM2 Waker Service

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.

The Problem

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!

The Solution

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.

How It Works

  1. User accesses a site (e.g., my-recipe-app.com). Its pm2 process is stopped.
  2. Nginx returns a 502 error.
  3. Custom Nginx error rule calls the Waker Service’s /start endpoint (e.g., http://127.0.0.1:1234/start?app=my-recipe-app).
  4. Waker Service starts the app with pm2 start my-recipe-app and sets an inactivity timer.
  5. Nginx automatically retries the request, which now works.
  6. 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).
  7. If the timer ends, the service stops the web app with pm2 stop my-recipe-app.

Installation

1. Prerequisites

  • Go version 1.22+
  • pm2 installed and configured
  • Nginx

2. Build the App

Clone this repository and build the Go binary:

git clone https://github.com/Crossoufire/go-waker.git
cd go-waker
go build -o waker

3. Install the Service

Move 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

4. Configure Your Apps

  • 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
}

5. Set up Systemd Service

Create a systemd service file to run the Waker as a daemon:

sudo nano /etc/systemd/system/waker.service
  • Paste the following content.
  • Change User and Group to the user that runs your pm2 processes.
  • Change also the WorkingDirectory and ExecStart locations.
[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.target

6. Enable and Start the Service

sudo 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 -f

If you do modification on the config.json file, you will need to restart the go Waker service:

sudo systemctl restart waker.service

Nginx Config

You will need two Nginx snippets and then include them in your server blocks.

1. Error Handler Snippet

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;

2. Ping Snippet

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;
}

3. Example Server Block

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

About

A very lightweight Go service that manages PM2-driven apps, starting them on-demand via Nginx and stopping them after inactivity.

Topics

Resources

License

Stars

Watchers

Forks

Languages