Configuration (.env)
All settings of the panel, generated from example.env.
Copy that file to .env and adjust it. Email settings are made in the admin interface
(Settings), not here.
Proxmox connection
| Setting | Example / default | Description |
|---|---|---|
PVE_URL | https://pve.example.com:8006 | Proxmox VE |
PVE_TOKEN_ID | panel@pve!panel | see above |
PVE_TOKEN_SECRET | 00000000-0000-0000-0000-000000000000 | see above |
PVE_VERIFY_TLS | true | Keep true in production. Either use a trusted cert or point PVE_CA_FILE at /etc/pve/pve-root-ca.pem copied from your cluster. |
PVE_CA_FILE | – | see above |
PVE_POOL | customers | Pool that customer servers live in; servers customers create are added to it |
Panel, ports and security
| Setting | Example / default | Description |
|---|---|---|
INITIAL_ADMIN_EMAIL | – | First administrator, created on first start only if no accounts exist yet (for setups without a terminal, e.g. a NAS). Remove the password afterwards. |
INITIAL_ADMIN_PASSWORD | – | see above |
INITIAL_ADMIN_REQUIRE_2FA | false | see above |
PANEL_PUBLIC_URL | https://panel.example.com | The addresses browsers use; callbacks are |
ADMIN_PUBLIC_URL | http://localhost:3001 | see above |
PORT | 3000 | Customer panel |
HOST | 0.0.0.0 | see above |
ADMIN_PORT | 3001 | Admin interface: its own server and port. Default is local-only; reach it through an SSH tunnel or VPN. Only set ADMIN_HOST=0.0.0.0 behind a firewall. |
ADMIN_HOST | 127.0.0.1 | see above |
JWT_SECRET | change-me | Long random string: node -e "console.log(require('crypto').randomBytes(48).toString('hex'))" |
COOKIE_SECURE | true | Set to false only for local development over plain http |
DB_PATH | ./data/panel.db | see above |
Sign-in: passwords, passkeys and single sign-on
| Setting | Example / default | Description |
|---|---|---|
PASSKEYS_ENABLED | true | Passkeys (fingerprint, face, device PIN, security key). They need a domain name over https (or localhost); set PANEL_PUBLIC_URL / ADMIN_PUBLIC_URL for your domains. |
PASSWORD_LOGIN_CUSTOMER | true | Password sign-in per portal. Turning one off requires OIDC for that portal. |
PASSWORD_LOGIN_ADMIN | true | see above |
OIDC_ENABLED | false | |
OIDC_ISSUER | https://login.example.com/realms/example | |
OIDC_CLIENT_ID | – | |
OIDC_CLIENT_SECRET | – | |
OIDC_PORTALS | customer,admin | Which portals show the single sign-on button |
OIDC_BUTTON_LABEL | Sign in with single sign-on | see above |
OIDC_SCOPES | openid email profile | see above |
OIDC_ALLOWED_DOMAINS | – | Only these email domains may link or be created (empty = any) |
OIDC_REQUIRE_VERIFIED_EMAIL | true | First link by email only when the provider says it's verified |
OIDC_AUTO_CREATE | false | Create unknown users as customers (no rights until an admin grants them) |
OIDC_TRUST_IDP_MFA | true | Skip the panel's own 2FA when the provider confirms multi-factor sign-in (amr) |
OIDC_USE_PAR | auto | Pushed Authorization Requests: auto (when offered), always, never |
Customer networks
| Setting | Example / default | Description |
|---|---|---|
CUSTOMER_NETWORKS | false | Private network per customer (see the documentation, "Customer networks"). When enabled, every server a customer creates joins that customer's own SDN VNet. |
SDN_ZONE | panel | see above |
CUSTOMER_NET_PREFIX | 10.100 | Customers get |
CUSTOMER_NET_DNS | 1.1.1.1 | see above |
CUSTOMER_BLOCKED_NETS | 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10,169.254.0.0/16 | Destinations customer servers may NOT reach: your LAN, management and any other internal networks behind the Proxmox host. The public internet stays reachable. If CUSTOMER_NET_DNS is inside these ranges, DNS to it is allowed automatically. |
WireGuard VPN
| Setting | Example / default | Description |
|---|---|---|
VPN_ENABLED | false | VPN access through a central WireGuard gateway (see the documentation, "VPN access"). Needs CUSTOMER_NETWORKS=true. |
VPN_GATEWAY_VMID | – | VMID of the gateway VM prepared with docs/vpn/setup-gateway.sh |
VPN_ENDPOINT | vpn.example.com:51820 | What customers' WireGuard apps connect to: your public DNS name or IP + UDP port |
VPN_NET_PREFIX | 10.101 | Customer N's devices get |
VPN_MAX_DEVICES | 10 | see above |
Tailscale
| Setting | Example / default | Description |
|---|---|---|
TAILSCALE_ENABLED | false | Tailscale: customers can connect servers to their OWN Tailscale account (see the documentation, "Tailscale"). Works with or without the WireGuard VPN. |
Windows and guest agent
| Setting | Example / default | Description |
|---|---|---|
WINDOWS_OOBE_TIMEOUT_MINUTES | 15 | Windows: how long Windows may sit at its setup (welcome) screens before a server creation fails with a hint that the template's unattend.xml is incomplete |
AGENT_UNRESPONSIVE_SECONDS | 180 | How long the QEMU guest agent in a server may stop answering (e.g. while an installer runs) before a panel job gives up. Short stalls are waited out. |
Limits
| Setting | Example / default | Description |
|---|---|---|
MAX_SNAPSHOTS | 3 | Plan limits |
Branding and versions
| Setting | Example / default | Description |
|---|---|---|
SHOW_VERSION_TO_CUSTOMERS | true | Show the panel version to signed-in customers (sidebar and Account page). Only the number; commit, build date and update status stay in the admin interface. |
UPDATE_CHECK | true | Update check: the admin interface asks GitHub (at most every 6 hours) whether a newer release exists. Set to false to never contact GitHub. |
PANEL_NAME | PVE Panel | Product name shown on the sign-in pages, in the sidebar and in page titles |
BRANDING_DIR | – | Folder with own OS icons (os-windows.svg, os-linux.png …); default data/branding |
Server expiry
| Setting | Example / default | Description |
|---|---|---|
EXPIRY_CHECK_SECONDS | 300 | Server expiry (configured per customer/server in the admin interface): how often the panel checks expiry dates, in seconds. 0 = never automatically ("Check now" only). |
Docker
| Setting | Example / default | Description |
|---|---|---|
PANEL_IMAGE | ghcr.io/sebastianflint/pve-panel:latest | Using the ready-made image (deploy/docker-compose*.yml). Optional: the default is ghcr.io/sebastianflint/pve-panel:latest; set a release to pin it, e.g. ghcr.io/sebastianflint/pve-panel:1.2.0 (optional) |
PANEL_DOMAIN | panel.example.com | Docker with automatic HTTPS (docker compose --profile https): the public DNS name |