How to make changes to this project and get them live.
server.js → Node.js app, port 3000, bound to 127.0.0.1
nginx-1.30.0/ → reverse proxy, port 80
Tailscale Funnel → public HTTPS at https://nbg3pc.taileeca1e.ts.net
Node.js must be manually restarted after any change to server.js.
nginx must be reloaded after any change to nginx.conf.
Tailscale Funnel is unaffected by app changes.
server.js)Open server.js in any editor and make your changes. The app logic is all in one file.
Key areas:
// Change what the page shows — edit the html() function
const html = (time) => `<!DOCTYPE html>...`;
// Add a new route
const server = http.createServer((req, res) => {
if (req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'ok' }));
return;
}
// existing handler...
});
// Change the port (also update nginx.conf if you do this)
const PORT = 3000;
netstat -ano | findstr :3000
Note the PID in the last column.
taskkill /PID <pid> /F
cd C:\Users\An.G3\Documents\GitHub\tswebclaude1
node server.js
curl http://127.0.0.1:3000
curl http://127.0.0.1:80
nginx-1.30.0\conf\nginx.conf)Make your changes to nginx.conf.
cd C:\Users\An.G3\Documents\GitHub\tswebclaude1\nginx-1.30.0
nginx.exe -t
If it says syntax is ok and test is successful, proceed. Never reload without testing first.
nginx.exe -s reload
This applies the new config without dropping existing connections.
# Check what's using port 80
netstat -ano | findstr :80
# Kill it
taskkill /PID <pid> /F
# Start nginx fresh
cd C:\Users\An.G3\Documents\GitHub\tswebclaude1\nginx-1.30.0
nginx.exe
Edit server.js, add a new if (req.url === '/newpage') block. Restart Node only.
Edit the html template string in server.js. Restart Node only.
PORT in server.jsproxy_pass in nginx.conf to match the new portlocation block in nginx.conf:location /app2/ {
proxy_pass http://127.0.0.1:3001/;
}
nginx.exe -t && nginx.exe -s reloadC:\Users\An.G3\Documents\GitHub\tswebclaude1\public\nginx.conf:location /static/ {
alias C:/Users/An.G3/Documents/GitHub/tswebclaude1/public/;
}
If something is broken and you want a clean restart:
# 1. Kill Node
netstat -ano | findstr :3000
taskkill /PID <pid> /F
# 2. Kill nginx
cd C:\Users\An.G3\Documents\GitHub\tswebclaude1\nginx-1.30.0
nginx.exe -s stop
# If that hangs, force-kill:
taskkill /IM nginx.exe /F
# 3. Start Node
cd C:\Users\An.G3\Documents\GitHub\tswebclaude1
node server.js
# 4. Start nginx
cd nginx-1.30.0
nginx.exe
# 5. Verify
curl http://127.0.0.1:3000
curl http://127.0.0.1:80
# Tailscale Funnel is always running — no action needed
# Is Node running?
netstat -ano | findstr :3000
# Is nginx running?
netstat -ano | findstr :80
# Is Tailscale Funnel active?
tailscale serve status
# End-to-end test
curl http://127.0.0.1:3000 # Node directly
curl http://127.0.0.1:80 # Through nginx
curl https://nbg3pc.taileeca1e.ts.net # Public URL
Right now Node must be manually restarted. PM2 is a process manager that handles this automatically — it restarts Node on crash and on reboot.
# Install PM2 globally
npm install -g pm2
# Start your app with PM2 (run from project folder)
pm2 start server.js --name webapp
# Auto-start on Windows boot
pm2 startup
# Follow the printed instruction — usually run one command as admin
pm2 save # save current process list
After this, the redeploy workflow becomes:
# Edit server.js, then:
pm2 restart webapp
# Or for zero-downtime (starts new, stops old):
pm2 reload webapp
# Check status
pm2 status
pm2 logs webapp
And nginx can be wrapped similarly with NSSM (see HOWTO.md) so both survive reboots without manual intervention.