Carsten Graf ea863e8b10 Gitignore
2026-02-11 23:15:43 +01:00
2026-02-11 23:15:43 +01:00
2026-02-11 23:13:25 +01:00
2026-02-11 23:15:43 +01:00
2026-02-11 23:13:25 +01:00
2026-02-11 23:13:25 +01:00
2026-02-11 23:13:25 +01:00
2026-02-11 23:13:25 +01:00

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

# 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

# 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:

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

# 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:

nano /etc/systemd/system/unifi-portal.service

Add this content:

[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:

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 SettingsGuest 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:

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:

<input type="email" id="guestEmail" placeholder="Enter your email" required>

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

# 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)
Description
No description provided
Readme 56 KiB
Languages
HTML 68.8%
JavaScript 31.2%