Skip to content

Admin access & split container

The admin area (everything under /admin) can be isolated from the user portal so a stolen super-admin account alone is not enough — the attacker also needs network access to the admin topology.

Three modes

Mode Who gets in Effort When to use
unrestricted (default) Anyone with a login none Single-person setup, no elevated threat
ip_allowlist Only IPs in your CIDR list 1 setting Office IP / VPN subnet — sufficient for most self-hosters
split_container Only callers reaching the admin hostname / VPN / SSH tunnel high IT firms with many tenants

unrestricted and ip_allowlist are toggled directly under Admin → Access → Access (the advanced tab next to Users/Roles/Tenants/2FA). split_container requires additional Compose work.

Which address belongs in the allowlist? The one the server sees you as — the tab shows it above the list ("The server sees you as …") with a button that adds it directly. For an instance on the internet that is your public address, not your PC's LAN address. The nginx of the Vesana stack is always trusted; if you run your own reverse proxy in front of it (a second nginx, Caddy, Traefik), add its network under Advanced. A list that would lock you out is not saved unless you explicitly confirm it.

Until recently, the first-run setup wizard still asked for this mode as its own step. It has since been removed from the wizard — the safe default (unrestricted) applies automatically on first start, and you set the mode you actually want any time afterwards under Admin → Access → Access.


Split container — a dedicated admin container

When you choose "Dedicated container", Vesana runs two API containers: one serves the user portal (without admin functions), the other the admin area under its own hostname or port. You set it up with the assistant under Admin → Access → Dedicated container — there is nothing to copy and no script you have to maintain yourself.

How the assistant works

  1. Detect — the assistant determines whether the nginx of the Vesana stack terminates TLS itself or whether a reverse proxy of your own sits in front (it compares the certificate on port 443 with the stack's). It also checks that the Compose file and images are recent enough — otherwise it stops right here.
  2. Address — subdomain (admin.<host>, recommended), a separate port, or both. DNS check and a cookie-domain suggestion included.
  3. Build — Vesana starts the admin container and verifies it internally. Nothing changes for the running instance; the admin area stays reachable as before. If a step fails, everything is rolled back and the reason is shown in plain language.
  4. Verify — what remains manual (with a reverse proxy in front: a vhost you get as a script; a certificate for the admin name) plus a reachability probe from your browser and from the server. Only when one of them reaches the admin container can you continue.
  5. Switch — only now is the mode set and the main container restarted without admin functions (the user portal is away for about half a minute). From then on the admin area is reachable only under the new address.

Safety net: after switching, a 30-minute window starts. If nobody logs in via the admin host in that time (the Access tab there confirms automatically), Vesana reverts the switch on its own — nobody stays locked out. The same happens if the restart fails.

The three setup profiles

Profile How the assistant recognises it Automated What you do
Stack nginx terminates TLS itself (default) port 443 presents the stack certificate everything up to the switch a certificate that also covers the admin name (step 4 shows the certbot path with the real file locations) — without it the browser merely warns
Reverse proxy in front (nginx, Caddy, Traefik …) port 443 presents a different certificate than the stack the whole stack part create the proxy vhost for the admin name — step 4 provides the nginx script with the correct stack port; translate for Caddy/Traefik
No Compose no Compose stack nothing run a second API process with VESANA_API_MODE=admin yourself

If detection is wrong, you can override the profile in step 1.

Going back

  • Before the switch: card "Dedicated admin container" in the Access tab → Cancel build.
  • Within the window: Revert switch — also possible from the user portal.
  • Afterwards: Deactivate — only via the admin host. A confirmed split cannot be lifted from the user portal; that is the protection.
  • Via the mode cards: choosing "Unrestricted" or "IP allowlist" and Save tears an active split down just as completely; the target mode is the chosen card. A mere build is cleaned up as well.
  • Emergency: docker compose exec api python -m api.app.cli.admin_recovery reset-mode unrestricted in the Vesana directory resets the mode immediately; then use Deactivate in the Access tab so the containers are torn down as well.

What runs on which host

After the switch both addresses serve the same instance, but not the same functions:

User portal Admin host
Devices, checks, alerting, maps, reports yes yes
Creating, renaming, copying, deleting tenants yes (with the required permissions) yes
Users, roles, updates, everything under /admin no — the notice links into the admin portal yes

If the user portal calls a pure administration route, Vesana answers with a clear message and code instead of "Method not allowed" (up to v1.9.447 that was exactly the error when creating a tenant).

The way back is offered in two places in the admin portal: the admin login page links to the normal user login, and the sidebar offers "Back to the user portal" next to "Log out".

Agent and collector install commands in the user portal again carry the gateway address and certificate fingerprint in split mode; portal layout, license notices and discovery defaults apply there as well.

Notes

  • Cookie domain: the assistant suggests the narrowest common domain (admin.app.example.com under app.example.comapp.example.com) so the login applies to both addresses without being shared with other services in the same zone. Leave it empty to log in again on the admin host.
  • Separate port instead of subdomain: browsers do not isolate cookies by port — the admin area is then protected by the permission check only, not by the browser origin. For instances reachable by IP only it is nevertheless the only option.

Further reading

  • Permissions: Roles & permissions — how the fine-grained audit_log.view_* / trash.view_* levels interact with the access modes.
  • 2FA: 2FA — an additional protection layer at the individual-user level rather than the whole admin area.