🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5.7 KiB
5.7 KiB
Captive Portal Deployment Notes
Date: 2026-01-06 Status: Ready to deploy on live Pi
Summary
Added captive portal detection to nginx configuration. This enables automatic popup on devices when they connect to the Dangerous-Pi WiFi network.
What Was Changed
Files Modified
-
pi-gen pipeline (for future builds):
pi-gen/stageDangerousPi/01-Wireless-AP/00-run-chroot.sh
-
Local nginx config (reference):
nginx/dangerous-pi.conf
Changes Made
Added OS connectivity check endpoints to nginx:
| Endpoint | OS/Browser | Response |
|---|---|---|
/generate_204 |
Android/Chrome | 204 No Content |
/gen_204 |
Android alternate | 204 No Content |
/connectivitycheck/gstatic/generate_204 |
Google services | 204 No Content |
/hotspot-detect.html |
iOS/macOS | 200 + HTML |
/library/test/success.html |
iOS alternate | 200 + HTML |
/connecttest.txt |
Windows 10/11 | 200 + text |
/ncsi.txt |
Windows NCSI | 200 + text |
/success.txt |
Firefox | 200 + text |
/kindle-wifi/wifistub.html |
Kindle/Amazon | 200 + HTML |
Deploy on Live Pi
Option 1: Copy nginx config directly
# SSH into the Pi
ssh dt@dangerous-pi.local
# Backup existing config
sudo cp /etc/nginx/sites-available/dangerous-pi.conf /etc/nginx/sites-available/dangerous-pi.conf.bak
# Copy the new config (from your dev machine)
# On dev machine:
scp nginx/dangerous-pi.conf dt@dangerous-pi.local:/tmp/
# On Pi:
sudo cp /tmp/dangerous-pi.conf /etc/nginx/sites-available/dangerous-pi.conf
# Test nginx config
sudo nginx -t
# Reload nginx
sudo systemctl reload nginx
Option 2: Manual edit on Pi
Add the following block to /etc/nginx/sites-available/dangerous-pi.conf before the location /api/ block:
# ===========================================
# CAPTIVE PORTAL DETECTION
# ===========================================
# These endpoints respond to OS connectivity checks.
# When a device connects to the AP, the OS checks these URLs.
# By responding correctly, we trigger the captive portal popup.
# Android / Chrome OS connectivity check
location = /generate_204 {
return 204;
}
# Additional Android check paths
location = /gen_204 {
return 204;
}
# Google connectivity check
location = /connectivitycheck/gstatic/generate_204 {
return 204;
}
# iOS / macOS captive portal detection
location = /hotspot-detect.html {
return 200 '<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>';
add_header Content-Type text/html;
}
# iOS alternate path
location = /library/test/success.html {
return 200 '<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>';
add_header Content-Type text/html;
}
# Windows 10/11 connectivity check
location = /connecttest.txt {
return 200 'Microsoft Connect Test';
add_header Content-Type text/plain;
}
# Windows NCSI check
location = /ncsi.txt {
return 200 'Microsoft NCSI';
add_header Content-Type text/plain;
}
# Firefox / Mozilla connectivity check
location = /success.txt {
return 200 'success';
add_header Content-Type text/plain;
}
# Kindle / Amazon devices
location = /kindle-wifi/wifistub.html {
return 200 '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html><head><title>Kindle</title></head><body>81ce4465-7167-4dcb-835b-dcc9e44c112a</body></html>';
add_header Content-Type text/html;
}
# ===========================================
# END CAPTIVE PORTAL DETECTION
# ===========================================
Then reload nginx:
sudo nginx -t && sudo systemctl reload nginx
Testing
Test from a mobile device
- Forget the "Dangerous-Pi" network on your phone
- Reconnect to "Dangerous-Pi" WiFi
- You should see a captive portal popup automatically
- Clicking it should open the Dangerous Pi web interface
Test manually with curl
# Android check (should return empty 204)
curl -v http://192.168.4.1/generate_204
# iOS check (should return HTML)
curl -v http://192.168.4.1/hotspot-detect.html
# Windows check (should return "Microsoft Connect Test")
curl -v http://192.168.4.1/connecttest.txt
# Firefox check (should return "success")
curl -v http://192.168.4.1/success.txt
How It Works
- DNS: dnsmasq already redirects ALL DNS queries to 192.168.4.1 (
address=/#/192.168.4.1) - HTTP: When the OS checks connectivity URLs, nginx now responds correctly
- Detection: OS sees the expected response and knows internet is available
- Popup: Because DNS resolved to the AP but responses are correct, OS triggers captive portal UI
Troubleshooting
No popup appears
- Check nginx is running:
sudo systemctl status nginx - Check nginx config:
sudo nginx -t - Check dnsmasq is running:
sudo systemctl status dnsmasq - Verify DNS redirect:
nslookup google.com(should resolve to 192.168.4.1)
Popup appears but shows error
- Check frontend is running:
curl http://localhost:3000 - Check backend is running:
curl http://localhost:8000/api/health - Check nginx logs:
sudo tail -f /var/log/nginx/error.log
Some devices don't show popup
Different devices use different detection URLs. The current config covers:
- Android (all versions)
- iOS / macOS
- Windows 10/11
- Firefox
- Kindle
If a specific device doesn't work, check its connectivity check URL and add it to nginx.
Future Improvements
- Add Samsung-specific detection URLs if needed
- Consider adding a redirect for unknown hosts to
/(requiresifstatement) - Monitor nginx access logs to discover new detection URLs