Simple and elegant reverse proxy for managing multiple web applications from Home Assistant.
- 🔀 Multi-application reverse proxy with categories
- 🔐 Token authentication (zigbee2mqtt-proxy compatible)
- 🔑 Secret/password protection per app (bcrypt-hashed, rate-limited)
- 👤 Admin-only app visibility
- 🎨 Modern interface with Home Assistant theme
- 📡 Native Home Assistant Ingress support
- 🌐 Full WebSocket support (Z-Wave JS UI, Zigbee2MQTT, Matter Bridge, etc.)
- 🔒 Self-signed SSL support
- 🐛 Debug mode with real-time logs
- 🖼️ Custom logos (emoji or image URL)
Multi-App Proxy is a Home Assistant add-on that allows accessing multiple web applications through a unified interface with native Ingress support.
- ✅ Multi-application proxy with elegant web interface
- ✅ Custom categories with automatic icons
- ✅ Debug mode with real-time logs
- ✅ Token authentication (zigbee2mqtt-proxy style)
- ✅ Secret/password protection per app (bcrypt, rate-limited)
- ✅ Admin-only app visibility
- ✅ Auto-signed SSL support
- ✅ Full WebSocket support (Z-Wave, Zigbee, Matter)
- ✅ Custom logos (emoji or image URL)
- ✅ Native Ingress Home Assistant
- ✅ Home Assistant internal DNS
- ✅ YAML order preserved
-
In Home Assistant, go to Settings → Add-ons → Add-on Store
-
Click ⋮ (menu) at the top right → Repositories
-
Add the URL:
https://github.com/Pulpyyyy/multiappproxy -
Click Add
-
Refresh the page and install Multi-App Proxy
-
Copy the
ha-addonfolder to/addons/multiappproxy/ -
Reload add-ons
-
Install Multi-App Proxy
apps:
- name: My Application
url: http://192.168.1.100:8080debug: true # Enable real-time logs
apps:
- name: Z-Wave JS UI
url: http://192.168.1.123:8091
description: Z-Wave management interface
icon: ⚡
logo: https://example.com/zwave-logo.png
path: /zwavejsui
rewrite: false
category: Protocols
- name: Zigbee2MQTT
url: https://zigbee2mqtt.example.com:8080
description: Zigbee to MQTT gateway
icon: 🐝
path: /z2m
token: SuperSecretToken?
rewrite: false
category: Protocols
- name: Matter Bridge
url: http://matter-bridge.local:8283
description: Matter gateway
icon: 🌉
logo: https://raw.githubusercontent.com/t0bst4r/matterbridge/main/frontend/public/matterbridge%2064x64.png
path: /matter
category: Protocols
- name: Admin Dashboard
url: http://192.168.1.50:9000
path: /admin-dash
admin: true # Only visible to HA admin users
secret: MyPassw0rd! # Also requires a password
category: Tools
- name: NSPanel Manager
url: http://192.168.1.60:8000
path: /nspm
csrf_fix: true # Django app: align Origin/Host to pass CSRF check
category: Automation
- name: Home Assistant App (ingress-aware)
url: http://192.168.1.70:8123
path: /ha-app
hassio_ingress_slug: my_other_addon # resolve HA ingress token via Supervisor API
category: Automation| Parameter | Type | Default | Description |
|---|---|---|---|
debug |
boolean | false |
Enable real-time logs on interface and error_log debug in Nginx |
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string | ✅ Yes | - | Display name on card |
url |
string | ✅ Yes | - | Backend application URL (http/https) |
path |
string | No | /app-name |
Access path in proxy |
description |
string | No | "" |
Description shown under name |
icon |
string | No | 📱 | Emoji to display (UTF-8) |
logo |
string | No | - | Image URL (takes priority over icon) |
category |
string | No | Others |
Grouping category |
admin |
boolean | No | false |
Show this app only to HA admin users |
secret |
string | No | - | Require a password to access the app (bcrypt-hashed server-side) |
token |
string | No | - | Authentication token (added as query string) |
rewrite |
boolean | No | auto | Force/disable full URL rewriting (auto-detected for Z-Wave/Zigbee by default) |
preserve_path |
boolean | No | false |
Forward requests without stripping the path prefix (HA ingress-aware apps) |
csrf_fix |
boolean | No | false |
Override Origin and Host with upstream URL (fixes Django CSRF check) |
ws_rewrite |
boolean | No | false |
Inject a JS patch to rewrite WebSocket URLs through the proxy |
hassio_ingress_slug |
string | No | - | HA addon slug; resolves the ingress token path dynamically via Supervisor API |
The following categories have automatic icons:
| Category | Icon | Usage |
|---|---|---|
Automation |
🏠 | Home automation applications |
Protocol or Protocols |
📡 | Z-Wave, Zigbee, Matter |
Media |
🎥 | Plex, Jellyfin, etc. |
Tools |
🔧 | Utilities |
Network |
🌐 | Network tools |
Security |
🔒 | Cameras, alarms |
Others |
📱 | Default |
- ✅
http://192.168.1.100:8080 - ✅
https://app.domain.com:8443 - ✅
http://hostname.local:3000 - ❌ No trailing slash
- ❌ No path in URL
- ✅
/myapp(no trailing slash) - ❌
/myapp/(with trailing slash) - ❌
/my/long/path(no sub-paths)
The token is automatically added as a query string:
token: MySecretToken123Generates: http://backend/?token=MySecretToken123
Special characters: Automatically URL-encoded
?→%3F&→%26=→%3D
Protect an app with a password that the user must enter before accessing it:
- name: Sensitive App
url: http://192.168.1.100:8080
path: /sensitive
secret: MyStrongPassword- The plain secret is never stored or sent to the client — only a bcrypt hash is kept server-side.
- Verification is rate-limited to 5 attempts/minute per IP (burst 3).
- The
/api/verify-secretendpoint handles the check.
Hide an app from non-admin HA users:
- name: Admin Panel
url: http://192.168.1.100:9000
admin: trueThe app card is not rendered at all for non-admin users. It can be combined with secret for double protection.
When proxying a Django application that enforces CSRF origin checks, set csrf_fix: true:
- name: NSPanel Manager
url: http://192.168.1.60:8000
csrf_fix: trueThis overrides the Origin and Host headers sent to the upstream so both match the upstream address, which satisfies Django's CSRF middleware without requiring CSRF_TRUSTED_ORIGINS on the upstream app.
For apps that build WebSocket URLs client-side using window.location.host (which would bypass the proxy), inject a transparent JS patch:
- name: MQTT Explorer
url: http://192.168.1.100:4000
ws_rewrite: trueA small <script> is injected before </body> that patches window.WebSocket to route /websocket/ and /wss?/ paths through the proxy location.
For apps that are themselves HA-ingress-aware and already embed the full path in their URLs:
- name: Ingress-aware App
url: http://192.168.1.100:8080
preserve_path: trueRequests are forwarded as-is (no prefix stripping, no sub_filter rewriting).
For HA addons whose HTML already contains absolute paths prefixed with their own HA ingress token, specify the addon slug and multiappproxy will resolve the token dynamically via the Supervisor API and replace it with its own proxy path:
- name: Other HA Addon
url: http://192.168.1.100:8080
hassio_ingress_slug: my_other_addonRequires SUPERVISOR_TOKEN to be available (automatically set by HA).
- name: Z-Wave JS UI
url: https://zwavejs.yourdomain.com:8091
icon: ⚡
path: /zwavejsui
category: ProtocolsNotes:
- Full WebSocket support
- Self-signed SSL supported
- No special configuration required
- name: Zigbee2MQTT
url: http://zigbee2mqtt.local:8080
icon: 🐝
path: /z2m
token: YourToken
category: ProtocolsZigbee2MQTT configuration required:
# In Zigbee2MQTT configuration.yaml
frontend:
url: /z2mNotes:
- Token automatically managed
frontend.urlconfiguration mandatory- Compatible with official zigbee2mqtt-proxy logic
- name: Matter Bridge
url: http://matter-bridge.local:8283
icon: 🌉
path: /matter
category: ProtocolsAny standard web application will work. Examples:
- Portainer:
http://portainer:9000 - Grafana:
http://grafana:3000 - Node-RED:
http://nodered:1880 - ESPHome:
http://esphome:6052
Solution: Enable debug mode
debug: truePossible causes:
- Incorrect backend URL
- Application not started
- DNS issue
Verification:
# From the add-on terminal
curl -I http://your-app:8080Cause: Application not configured for sub-path
Solution for Zigbee2MQTT:
# In Zigbee2MQTT configuration.yaml
frontend:
url: /z2mVerification:
debug: true # Enable logsLook in logs for: Token encoded: XXX... → YYY...
Nginx logs: Enable debug to see full requests
Solution: Already handled automatically by add-on
proxy_ssl_verify off;
proxy_ssl_server_name on;Verification: WebSocket headers are automatic
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";If issue persists, check backend URL.
- Nginx 1.28.2: Reverse proxy
- Python 3: Configuration scripts
- S6-overlay: Service supervision
Home Assistant Ingress
↓
/api/hassio_ingress/XXX/
↓
Nginx (port 8099)
↓
Backend Applications
- Home Assistant →
/data/options.json - sync_config.py → YAML ↔ JSON sync
- json_to_yaml.py →
/app/config.yml - generate_config.py →
/etc/nginx/nginx.conf+/app/apps.json - index.html → Loads
apps.jsonand displays interface
Automatic resolver on Home Assistant Supervisor DNS:
resolver 172.30.32.3 valid=10s;Allows using:
http://addon-name.localhttp://hostname.localhttp://192.168.1.X
Only Home Assistant Supervisor can access:
allow 172.30.32.2;
deny all;Automatic detection via $INGRESS_ENTRY:
- Interface detects the basePath
- Nginx configures locations correctly
- No manual configuration needed
/addon_configs/
└── xxxxx_multiappproxy/
└── multi-app-proxy.yaml # Config saved automatically
You can edit multi-app-proxy.yaml directly:
- Edit the file
- Restart the add-on
- Config will sync automatically
- Automatically URL-encoded
- Added as query string (
?token=XXXor&token=XXX) - Never exposed in logs (truncated)
add_header Cache-Control "no-store, no-cache, must-revalidate";
add_header Pragma "no-cache";
add_header Expires 0;- HTTPS backends support
- Self-signed certificates accepted
- No strict validation
Via emoji:
icon: 🐝Via image URL:
logo: https://example.com/logo.pngPriority: logo > icon > default (📱)
Automatic fallback: If logo fails to load, icon displays
Applications display in YAML declaration order.
Categories appear in order of the first app in each category.
debug: trueEffects:
- Shows logs on web interface
- Enables
error_log debugin Nginx - Detailed configuration generation logs
Web interface:
- Visible at top of page if
debug: true - Real-time logs during loading
Add-on logs:
- Home Assistant → Add-ons → Multi-App Proxy → Logs
Nginx logs:
# From add-on terminal
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log- Double slash in URL: Fixed in v1.0.4
- App order: Preserved since v1.0.4
- Token with special characters: Automatically URL-encoded
GitHub Issues: https://github.com/Pulpyyyy/multiappproxy/issues
Information to provide:
- Add-on version
- Logs with
debug: true - Anonymized configuration
- Application concerned
- ✅ YAML order preserved
- ✅ Debug mode with UI logs
- ✅ Custom logo support
- ✅ Material Design icon
- ✅ Complete documentation
- ✅ Trailing slash fix
- ✅ Token URL-encoding
- ✅ Collapsible categories
- ✅ Native Ingress support
- ✅ Auto-signed SSL
- ✅ Full WebSocket support
- ✅ Initial version
MIT License
- Inspired by zigbee2mqtt-proxy
- Material Design icons: https://materialdesignicons.com
- Home Assistant community
Maintained by: @Pulpyyyy
