# 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 1. **pi-gen pipeline** (for future builds): - `pi-gen/stageDangerousPi/01-Wireless-AP/00-run-chroot.sh` 2. **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 ```bash # 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: ```nginx # =========================================== # 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 'SuccessSuccess'; add_header Content-Type text/html; } # iOS alternate path location = /library/test/success.html { return 200 'SuccessSuccess'; 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 'Kindle81ce4465-7167-4dcb-835b-dcc9e44c112a'; add_header Content-Type text/html; } # =========================================== # END CAPTIVE PORTAL DETECTION # =========================================== ``` Then reload nginx: ```bash sudo nginx -t && sudo systemctl reload nginx ``` ## Testing ### Test from a mobile device 1. Forget the "Dangerous-Pi" network on your phone 2. Reconnect to "Dangerous-Pi" WiFi 3. You should see a captive portal popup automatically 4. Clicking it should open the Dangerous Pi web interface ### Test manually with curl ```bash # 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 1. **DNS**: dnsmasq already redirects ALL DNS queries to 192.168.4.1 (`address=/#/192.168.4.1`) 2. **HTTP**: When the OS checks connectivity URLs, nginx now responds correctly 3. **Detection**: OS sees the expected response and knows internet is available 4. **Popup**: Because DNS resolved to the AP but responses are correct, OS triggers captive portal UI ## Troubleshooting ### No popup appears 1. Check nginx is running: `sudo systemctl status nginx` 2. Check nginx config: `sudo nginx -t` 3. Check dnsmasq is running: `sudo systemctl status dnsmasq` 4. Verify DNS redirect: `nslookup google.com` (should resolve to 192.168.4.1) ### Popup appears but shows error 1. Check frontend is running: `curl http://localhost:3000` 2. Check backend is running: `curl http://localhost:8000/api/health` 3. 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 `/` (requires `if` statement) - [ ] Monitor nginx access logs to discover new detection URLs