e37ee990545c042d05e8d56e9bc9af5c7adac8df
Covers: connected clients popup, get_ap_clients/get_all_clients, new API endpoints, session recovery behaviour, reboot button locking, IP range filter, and sortable columns. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Omada AP Manager
A web-based tool for viewing and rebooting TP-Link Omada access points.
Secured via Authentik OIDC, with a full audit log exported as CSV.
Features
- Live AP list fetched from Omada Controller (status, uptime, model, IP, MAC)
- Single and bulk reboot with confirmation modal
- Full audit log (who rebooted which AP, when, and whether it succeeded)
- CSV export of the entire audit log
- Authentik OIDC login (Authorization Code Flow)
- Deployable as a Docker container via Portainer
Prerequisites
| Component | Version |
|---|---|
| Omada Controller | 5.x or later |
| Authentik | Any recent self-hosted version |
| Docker / Portainer | Docker 20+ |
| Nginx Proxy Manager | Any recent version |
1. Authentik: Create an OAuth2 Provider + Application
1.1 Create an OAuth2 Provider
- In Authentik, go to Admin → Providers → Create.
- Choose OAuth2/OpenID Provider.
- Fill in:
- Name:
qwe-salus - Authorization flow: your default authorization flow
- Client type:
Confidential - Client ID: auto-generated (copy it)
- Client Secret: auto-generated (copy it)
- Redirect URIs:
https://salus.qwe.stranto.com/auth/callback - Scopes:
openid,profile,email - Subject mode:
Based on the User's username(orhashed user ID)
- Name:
- Save.
1.2 Create an Application
- Go to Admin → Applications → Create.
- Fill in:
- Name:
Omada AP Manager - Slug:
qwe-salus - Provider: select the provider created above
- Name:
- Save.
1.3 Note the Issuer URL
The issuer URL follows the pattern:
https://<your-authentik-domain>/application/o/<application-slug>/
Example: https://auth.stranto.com/application/o/qwe-salus/
2. Omada Controller: Create an API User
- In Omada Controller, go to Settings → Administrators.
- Create a local admin account (not linked to OIDC):
- Username:
api-user - Password: a strong, unique password
- Role: Viewer is enough for listing APs; needs Administrator role to send reboot commands.
- Username:
- Note the username and password — these go into
OMADA_USERNAME/OMADA_PASSWORD.
Required permissions for the API user:
- Read access to site and AP data
- Execute device commands (for reboot)
If self-signed certs are used, set
OMADA_VERIFY_SSL=false.
3. Deploy via Portainer (Stack)
3.1 Build the image first (on the Docker host)
git clone <this-repo> qwe-salus
cd qwe-salus
docker build -t qwe-salus:latest .
Or add a build: . section in the stack (Portainer will build it if the source is available).
3.2 Create a Portainer Stack
- In Portainer, go to Stacks → Add stack.
- Paste the contents of
docker-compose.yml. - Fill in all environment variable values (see table below).
- Click Deploy the stack.
Environment Variables
| Variable | Description | Example |
|---|---|---|
OMADA_BASE_URL |
Base URL of the Omada Controller | https://192.168.1.1:8043 |
OMADA_USERNAME |
Local Omada admin username | api-user |
OMADA_PASSWORD |
Local Omada admin password | s3cr3t |
OMADA_SITE_NAME |
Site name in Omada | Default |
OMADA_VERIFY_SSL |
Set to false for self-signed certs |
false |
AUTHENTIK_ISSUER |
OIDC issuer URL from Authentik | https://auth.example.com/application/o/slug/ |
AUTHENTIK_CLIENT_ID |
OAuth2 client ID from Authentik | abc123... |
AUTHENTIK_CLIENT_SECRET |
OAuth2 client secret from Authentik | xyz789... |
AUTHENTIK_REDIRECT_URI |
Must match what Authentik has configured | https://salus.example.com/auth/callback |
SESSION_SECRET_KEY |
Random secret for cookie signing — change this! | openssl rand -hex 32 |
DB_PATH |
Path to the SQLite database inside the container | /data/audit.db |
Generating a SESSION_SECRET_KEY
openssl rand -hex 32
4. Nginx Proxy Manager Setup
- Add a Proxy Host:
- Domain Names:
salus.qwe.stranto.com - Forward Hostname / IP: the Docker host IP (or container name if on the same network)
- Forward Port:
8098 - Enable Websockets Support (optional but harmless)
- Domain Names:
- Under SSL, issue/select a Let's Encrypt certificate.
- Important: The app uses
--proxy-headersin uvicorn so it correctly handlesX-Forwarded-ForandX-Forwarded-Protofrom NPM.
5. Accessing the Audit Log CSV Export
Once logged in, navigate to Audit Log (top navigation) and click Export CSV.
The file is named audit_log_YYYY-MM-DD.csv and contains:
| Column | Description |
|---|---|
| Timestamp (UTC) | ISO 8601 timestamp |
| Username | OIDC preferred_username |
OIDC email claim |
|
| AP Name | Name as shown in Omada |
| MAC | AP MAC address |
| IP | AP IP address |
| Result | success or error |
| Error | Error message if result is error |
Local Development
# Create a .env file
cp .env.example .env # edit with your values
pip install -r requirements.txt
# SQLite DB will be written to /data/audit.db by default
# override for local dev:
export DB_PATH=./audit.db
uvicorn app.main:app --reload --port 8080
Project Structure
qwe-salus/
├── app/
│ ├── main.py # FastAPI routes
│ ├── auth.py # Authentik OIDC logic
│ ├── omada.py # Omada Controller API client
│ ├── database.py # SQLAlchemy models + DB init
│ ├── templates/
│ │ ├── base.html # Nav, toast system
│ │ ├── login.html # Login landing page
│ │ ├── index.html # AP list + reboot UI
│ │ └── audit.html # Audit log + CSV export
│ └── static/
├── Dockerfile
├── docker-compose.yml
└── requirements.txt
Description
Languages
HTML
61.2%
Python
37.7%
Dockerfile
1.1%