Small two-service system for running a Factorio server on demand.
It allows a machine to stay offline by default, be woken remotely, used for a session, and automatically suspended when idle.
Runs on an always-on machine.
- Web UI + API
- Sends Wake-on-LAN packets
- WebSocket updates for live status
- Stores session history (SQLite)
Runs on the Factorio machine.
- Tails Factorio logs
- Suspends the machine when idle
- Tracks player join/leave events
- Reports sessions to dashboard
- Wake-on-LAN trigger
- Live machine + game status (TCP probes)
- Real-time updates via WebSockets
- Session tracking (join/leave events)
- Automatic suspend:
- no players joined → suspend after
FIRST_JOIN_TIMEOUT_SECONDS - players joined and left → suspend after
EMPTY_SERVER_TIMEOUT_SECONDS
- no players joined → suspend after
- Linux (systemd)
- Wake-on-LAN already configured and working
- Factorio server logs in standard format
- Two-machine setup:
- dashboard (always on)
- Factorio machine (sleep/wake)
- Local network (LAN)
- Enable Wake-on-LAN on the Factorio machine
- Configure
.envfiles for both services - Build:
cargo build --release - Deploy:
- dashboard on always-on machine
- run watcher on Factorio machine
- Register systemd services
- Allow watcher to suspend the machine (sudoers or root service)
- Ensure Factorio logs are accessible
cargo run -p dashboardcargo run -p watcher
cargo test
See .env.example in services/dashboard and services/watcher.
This is a minimal, opinionated setup. Not intended as a generic product.
This describes how the system is deployed in a typical two-machine setup.
- Enable WoL in BIOS
- Enable it in OS:
sudo ethtool -s <interface> wol g - Persist it via systemd or network configuration (required, otherwise WoL may reset after reboot)
git clone <repo>cd <repo>cargo build --release -p watcher- Configure environment. Create:
services/watcher/.env(see.env.example)LOG_PATH: path to Factorio logsDASHBOARD_URL: IP:PORT or hostname of dashboard (for internal API calls)INTERNAL_API_TOKEN: shared secret with dashboard to allow internal API callsFIRST_JOIN_TIMEOUT_SECONDS: seconds to wait for first player join before suspendingEMPTY_SERVER_TIMEOUT_SECONDS: seconds to wait for server after becoming empty before suspending
- Allow suspend
- Enable suspend for runtime user without a password (Recommended)
sudo visudo- Add this line at the end of the file:
<user> ALL=(root) NOPASSWD: /usr/bin/systemctl suspend
- Run watcher service as root.
- Enable suspend for runtime user without a password (Recommended)
- Create systemd service (
sudo nano /etc/systemd/system/factorio-watcher.service):
[Unit]
Description=Factorio Watcher
After=network.target
[Service]
Type=simple
User=<user>
Group=<user>
WorkingDirectory=/path/to/repo
ExecStart=/path/to/repo/target/release/watcher
Restart=on-failure
RestartSec=3
EnvironmentFile=/path/to/repo/services/watcher/.env
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reloadsudo systemctl enable factorio-watchersudo systemctl start factorio-watcher
When the machine suspends, both the watcher and Factorio server must be stopped cleanly, and started again on resume.
Create a systemd sleep hook:
- Create a systemd sleep hook:
sudo nano /usr/lib/systemd/system-sleep/factorio-sleep
#!/bin/sh
case "$1" in
pre)
/usr/bin/systemctl stop factorio-watcher.service
/usr/bin/systemctl stop factorio.service
;;
post)
/usr/bin/systemctl start factorio.service
/usr/bin/systemctl start factorio-watcher.service
;;
esac- Make it executable
sudo chmod +x /usr/lib/systemd/system-sleep/factorio-sleep
git clone <repo>cd <repo>cargo build --release -p dashboard- Configure environment. Create:
services/dashboard/.env(see.env.example)DB_PATH: path to sqlite databaseINTERNAL_API_TOKEN: shared secret with watcher to allow internal API callsBIND_ADDR: Binding target for HTTP serverTARGET_MAC: MAC address of the machine to wakeMACHINE_IP: IP address of the Factorio machineMACHINE_CHECK_PORT: TCP port to check if machine is upFACTORIO_CHECK_PORT: TCP port to check if Factorio is running
- Create systemd service (
sudo nano /etc/systemd/system/factorio-dashboard.service):
[Unit]
Description=Factorio Dashboard
After=network.target
[Service]
Type=simple
WorkingDirectory=/path/to/repo
ExecStart=/path/to/repo/target/release/dashboard
Restart=on-failure
RestartSec=3
EnvironmentFile=/path/to/repo/services/dashboard/.env
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reloadsudo systemctl enable factorio-dashboardsudo systemctl start factorio-dashboard
Expose dashboard behind nginx and add basic auth if needed. Not included here.
- Open dashboard in browser
- Trigger wake
- Machine should power on
- Factorio becomes reachable
- Join/leave events appear
- Machine suspends after idle