LANtern
Wake on LAN web app. PWA, PIN lock, Docker.
Install / Use
/learn @allxm4/LANternREADME
LANtern
Wake on LAN web app. Add devices, tap the power button, they wake up. Installable as a PWA on iOS and Android.
Built for homelabs running on Linux (Raspberry Pi, NAS, mini PC) on the same LAN as your devices.
Screenshots
<img width="571" height="981" alt="Image" src="https://github.com/user-attachments/assets/b06fd926-c92a-4286-b4d4-5e521b48fc93" /> <img width="571" height="981" alt="Image" src="https://github.com/user-attachments/assets/98da389a-9f78-48d8-8f2b-a2a816c1ff0e" /> <img width="571" height="981" alt="Image" src="https://github.com/user-attachments/assets/2f3ab3f8-c877-40e9-a923-6098923b6d04" /> <img width="571" height="981" alt="Image" src="https://github.com/user-attachments/assets/ca0c6f2b-a184-442b-ae90-cb14832844dc" /> <img width="571" height="981" alt="Image" src="https://github.com/user-attachments/assets/7b9d709e-9141-4f8d-8707-aa492709e180" />Why
There are great projects out there like Upsnap that handle WoL along with status monitoring, shutdown, and more. For my setup though, my homelab mini PCs are managed through MeshCentral via Intel AMT, which keeps a persistent connection alive, meaning they always show as online regardless of whether they're actually powered on. That made status-based tools less useful for my specific case.
LANtern does one thing: send a magic packet. Open the app, tap the button, done.
Security
LANtern has no built-in authentication beyond the optional PIN. If you expose this outside your local network, put it behind proper authentication. Cloudflare Zero Trust, a reverse proxy with basic auth, a VPN. The PIN alone is not enough for internet-facing deployments.
See Remote access below for options that work well with this setup.
Install on your phone
iOS: Open in Safari, tap the Share button, select "Add to Home Screen".
Android: Open in Chrome, tap the three-dot menu, select "Add to Home Screen".
Deploy
1. Clone and create config files
git clone https://github.com/allxm4/LANtern.git
cd LANtern
touch devices.json config.json
2. Start
docker compose up -d
3. Open
http://<your-server-ip>:3000
Devices and PIN config persist in devices.json and config.json next to docker-compose.yml.
Changing the port
If port 3000 is already in use, change PORT in docker-compose.yml:
environment:
- PORT=8080
Then run docker compose up -d and access the app at http://<your-server-ip>:8080.
Remote access
Cloudflare Tunnel
Zero open ports. Traffic goes through Cloudflare's network. Pair this with a Cloudflare Access policy to gate it behind authentication.
- one.dash.cloudflare.com → Networks → Tunnels → Create tunnel
- Choose Cloudflared, name it, copy the token
- In the tunnel's Public Hostname tab, point your domain to
http://localhost:3000 - Add to
.env:CLOUDFLARE_TOKEN=your-token - Uncomment the
cloudflaredblock indocker-compose.yml docker compose up -d
NetBird
Mesh VPN. The app is only reachable from devices enrolled in your NetBird network, with no public exposure.
- app.netbird.io → Setup Keys → Create setup key (reusable)
- Add to
.env:NETBIRD_SETUP_KEY=your-key - Uncomment the
netbirdblock and thevolumesblock indocker-compose.yml docker compose up -d- Find the assigned IP under Peers in the NetBird dashboard, open
http://<netbird-ip>:3000
PIN lock
Set a PIN from the gear icon in the app. Sessions last 8 hours, so you won't be asked again on the same device until the session expires. The TTL is configurable via SESSION_TTL_HOURS in docker-compose.yml.
Forgot your PIN:
docker exec LANtern node reset-pin.js # remove PIN
docker exec LANtern node reset-pin.js 1234 # set a new PIN
To immediately log out all active sessions:
docker compose restart LANtern
API
All endpoints require authentication if a PIN is set. First get a session token, then include it in subsequent requests.
Get a session token
# With PIN enabled
curl -s -X POST http://localhost:3000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"pin":"1234"}'
# -> {"token":"abc123..."}
# Without PIN, call the same endpoint with no body
curl -s -X POST http://localhost:3000/api/auth/login
Pass the token in the x-session-token header on all subsequent requests.
Wake by device ID
Device IDs are UUIDs assigned when you add a device. Retrieve them from:
curl -s http://localhost:3000/api/devices \
-H "x-session-token: <token>"
Then wake the device:
curl -s -X POST http://localhost:3000/api/wake/<device-id> \
-H "x-session-token: <token>"
Wake by MAC address (useful for iOS Shortcuts or home automation)
curl -s -X POST http://localhost:3000/api/wake/mac/AA:BB:CC:DD:EE:FF \
-H "Content-Type: application/json" \
-H "x-session-token: <token>" \
-d '{"broadcastAddress":"192.168.1.255"}'
broadcastAddress is optional, defaults to 255.255.255.255.
Health check (no auth required)
curl -s http://localhost:3000/api/health
