# UniFi Guest Portal A custom external portal server for UniFi guest WiFi networks with a modern, responsive design. ## Features - 🎨 Modern, mobile-responsive design - 🔒 Secure authentication with UniFi Controller - ⚡ Fast and lightweight - 🎯 Easy to customize - ⏱️ Configurable access duration (default: 24 hours) ## Prerequisites - Node.js 16+ installed - UniFi Controller with admin credentials - Proxmox LXC container (or any Linux server) - Reverse proxy with SSL (Zoraxy in your case) - Local DNS resolution (Pi-hole) ## Installation ### 1. Create LXC Container on Proxmox ```bash # Create Ubuntu/Debian container # Assign static IP (e.g., 192.168.1.100) # Update the system apt update && apt upgrade -y # Install Node.js curl -fsSL https://deb.nodesource.com/setup_20.x | bash - apt install -y nodejs git # Verify installation node --version npm --version ``` ### 2. Deploy the Portal Application ```bash # Upload the unifi-portal folder to your container # Or clone from your git repository cd /opt # Copy the unifi-portal folder here # Navigate to project directory cd unifi-portal # Install dependencies npm install # Configure environment variables cp .env.example .env nano .env # Edit with your actual credentials ``` ### 3. Configure UniFi Controller Credentials Edit `server.js` and update these values: ```javascript const UNIFI_USERNAME = 'your-unifi-admin-username'; const UNIFI_PASSWORD = 'your-unifi-admin-password'; const UNIFI_SITE = 'default'; // or your site name ``` ### 4. Test the Application ```bash # Start the server npm start # Test from another machine curl http://192.168.1.100:3000/health ``` ### 5. Set up as a System Service Create a systemd service file: ```bash nano /etc/systemd/system/unifi-portal.service ``` Add this content: ```ini [Unit] Description=UniFi Guest Portal After=network.target [Service] Type=simple User=root WorkingDirectory=/opt/unifi-portal ExecStart=/usr/bin/node server.js Restart=always RestartSec=10 [Install] WantedBy=multi-user.target ``` Enable and start the service: ```bash systemctl daemon-reload systemctl enable unifi-portal systemctl start unifi-portal systemctl status unifi-portal ``` ### 6. Configure Pi-hole DNS Add a local DNS record in Pi-hole: - Domain: `portal.yourdomain.local` (or whatever you prefer) - IP: `192.168.1.100` (your LXC container IP) ### 7. Configure Zoraxy Reverse Proxy In Zoraxy: 1. Create a new proxy rule 2. Domain: `portal.yourdomain.local` 3. Target: `http://192.168.1.100:3000` 4. Enable SSL (use self-signed cert or Let's Encrypt) 5. Save and test ### 8. Configure UniFi Controller 1. Log into your UniFi Controller at `https://192.168.1.1` 2. Go to **Settings** → **Guest Control** 3. Create or edit a Guest Hotspot/Portal 4. Set **Authentication** to **External Portal Server** 5. **External Portal Server URL**: `https://portal.yourdomain.local` 6. Set **HTTPS Redirection**: Enabled 7. Save settings ## Testing 1. Connect a device to your guest WiFi network 2. Open a browser - you should be redirected to your custom portal 3. Click "Connect to WiFi" 4. You should get internet access and be redirected ## Customization ### Change the Design Edit `public/index.html` to customize: - Colors (gradient, buttons, etc.) - Logo (change the emoji or add an image) - Text and messaging - Add form fields (email capture, terms checkbox, etc.) ### Adjust Access Duration In `server.js`, modify the minutes parameter: ```javascript minutes: 1440 // 24 hours (1440 minutes) ``` Common values: - 60 = 1 hour - 480 = 8 hours - 1440 = 24 hours - 10080 = 1 week ### Add Email Collection You can add a form field to collect emails before authorization. Example modification to `public/index.html`: ```html ``` And modify the `/authorize` endpoint in `server.js` to save the email. ## Troubleshooting ### Portal doesn't redirect - Check UniFi Controller external portal URL is correct - Verify DNS resolution: `nslookup portal.yourdomain.local` - Check Zoraxy proxy rule is active ### "Authorization failed" - Verify UniFi credentials in `server.js` - Check UniFi Controller is accessible from container: `curl -k https://192.168.1.1` - Review logs: `journalctl -u unifi-portal -f` ### SSL Certificate errors - UniFi Controller uses self-signed cert by default (expected) - The code ignores cert errors with `rejectUnauthorized: false` - For production, consider proper SSL certificates ### Check logs ```bash # View service logs journalctl -u unifi-portal -f # Or if running manually npm start ``` ## Security Notes 1. The portal server needs admin credentials to the UniFi Controller 2. Store credentials securely (consider using environment variables) 3. Use HTTPS for your portal (required for most mobile devices) 4. The code currently disables SSL verification for the UniFi Controller (common for self-signed certs) 5. Consider implementing rate limiting to prevent abuse ## Project Structure ``` unifi-portal/ ├── server.js # Main Express server with UniFi API integration ├── package.json # Node.js dependencies ├── public/ │ └── index.html # Custom landing page ├── .env.example # Environment variables template └── README.md # This file ``` ## API Endpoints - `GET /` - Main portal page (receives UniFi redirect parameters) - `POST /authorize` - Authorizes guest device with UniFi Controller - `GET /health` - Health check endpoint ## UniFi API Reference The portal uses these UniFi Controller API endpoints: - `POST /api/login` - Authenticate to controller - `POST /api/s/{site}/cmd/stamgr` - Authorize guest device - `POST /api/logout` - Logout from controller ## License MIT ## Support For issues or questions, check: - UniFi API documentation - Node.js/Express.js documentation - Your network configuration (DNS, firewall, routing)