Module options
The services.panel NixOS options below configure a panel deployment.
services.panel.enable
Whether to enable Service configuration for panel.
Type: boolean
Default:
false
Example:
true
Declared by:
services.panel.apiBaseUrl
Base URL at which api/'s HTTP surface is reachable, used from both ends.
The browser reads it from <body data-api-base-url> for the
deployment form’s schema and rename-table fetches and the
Deploy/Delete calls. api/ serves those routes and the panel does not,
so leaving this empty sends them same-origin to the panel, they 404,
and the form never mounts.
The panel process uses it for its own server-side calls: the
deployment-state poll behind the Deploy/Destroy spinners, the
config-diff baseline, and the deployment list proxy. Left empty those
fall back to http://127.0.0.1:8088, which resolves only while api/
is colocated.
Normally an absolute origin, since api/ lives on its own registrable domain for white-labelling. It is only ever used as a string prefix, never parsed as a URL, so a panel-proxied path prefix works too.
Type: string
Default:
""
Declared by:
services.panel.apiDocsUrl
URL of a Swagger UI page for api/. The account page links to it next to the button that copies an API token. Empty shows no link.
Type: string
Default:
""
Example:
"https://swagger.example.org"
Declared by:
services.panel.centrifugo.enable
Whether the pages subscribe to the events of api/ on a Centrifugo
server. The server is not part of this module: the NixOS module of
api/ runs it, with its proxy endpoints pointed at the
/api/centrifugo/{connect,subscribe,publish}/ views of the panel.
Type: boolean
Default:
false
Declared by:
services.panel.centrifugo.wsDomain
Public hostname browsers use to reach Centrifugo over WebSocket.
Defaults to an events. subdomain so the panel session cookie
(scoped to the parent domain) is sent on the WS handshake.
Type: string
Default:
"events.\${cfg.domain}"
Declared by:
services.panel.domain
Public domain the panel is served on. Used for the nginx virtual host,
the session-cookie domain, and the default ALLOWED_HOSTS.
Type: string
Declared by:
services.panel.domainTermsNotice.enable
Whether to enable the daily manage notify_domain_terms run, which sends an email about
domain terms that an operator did not accept. It needs EMAIL_HOST in
settings, EMAIL_HOST_PASSWORD in the environment of the unit, and
API_SERVICE_TOKEN in secrets
.
Type: boolean
Default:
false
Example:
true
Declared by:
services.panel.extra-settings
Django configuration written in Python verbatim.
Contents will be appended to the definitions in settings.
Type: strings concatenated with “\n”
Default:
""
Declared by:
services.panel.host
Bind address for the panel’s ASGI (uvicorn) server.
Type: string
Default:
"127.0.0.1"
Declared by:
services.panel.oidc.enable
Whether to enable single sign-on (OpenID Connect) login for the panel UI.
Type: boolean
Default:
false
Example:
true
Declared by:
services.panel.oidc.clientID
Client ID the panel is registered under with the provider.
Type: string
Default:
"panel"
Declared by:
services.panel.oidc.clientSecretFile
Path to a file holding the client secret. Read by a privileged
oneshot (panel-oidc-secret.service) which stages a
panel-readable copy, so the file itself need not be readable by the
panel user and may appear, or change, only after boot: a path
unit re-stages it on every write and restarts the panel when the
copy changed. Empty (or a file that never appears) leaves SSO
unusable but still starts the panel on password login.
Type: string
Default:
""
Declared by:
services.panel.oidc.displayName
Name of the identity provider as shown on the login page’s “Log in with …” button.
Type: string
Default:
"single sign-on"
Declared by:
services.panel.oidc.issuer
OIDC issuer URL. The panel discovers every endpoint from
${issuer}/.well-known/openid-configuration, so nothing else about
the provider needs configuring.
Type: string
Default:
""
Declared by:
services.panel.oidc.scopes
OIDC scopes the panel requests.
Type: list of string
Default:
[
"openid"
"profile"
"email"
]
Declared by:
services.panel.oidc.superuserGroups
The groups of the identity provider whose members are superusers of
the panel. Each SSO login sets the superuser and staff flags of the
user from the groups claim, so the scopes must include groups.
The empty list leaves the flags as they are.
Type: list of string
Default:
[ ]
Declared by:
services.panel.port
Bind port for the panel’s ASGI (uvicorn) server.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
8000
Declared by:
services.panel.production
Whether this is a production deployment. Sets forceSSL and HSTS on
the nginx virtual host of the panel, marks the session, CSRF and language
cookies Secure, and connects to Centrifugo over wss://.
The certificate is not configured here: the ssl resource writes
sslCertificate/sslCertificateKey onto the virtual host from the
tls.ssl.domains request of the component. A standalone user of this
module sets them.
Type: boolean
Default:
true
Declared by:
services.panel.restart
systemd restart behavior
Type: one of “no”, “on-success”, “on-failure”, “on-abnormal”, “on-abort”, “always”
Default:
"always"
Declared by:
services.panel.secrets
Secrets to stage for the panel service via systemd LoadCredential,
as a mapping from credential name to source file path. SECRET_KEY
is populated by default from the generated panel secret. With
AUTHZ_CALLBACK_TOKEN set, the authz callback refuses a request that
does not carry that token as its bearer; api/ must send the same
token, through services.fediversity-api.authz.callbackTokenFile or
its AUTHZ_CALLBACK_TOKEN environment variable. The panel component
generates this token and gives it to api/ through OpenBao. With
API_SERVICE_TOKEN set, manage notify_domain_terms calls api/ with
that token as the service; api/ must accept the same token, through
services.fediversity-api.authz.serviceTokenFile or its
API_SERVICE_TOKEN environment variable. The panel component also
generates this token and gives it to api/ through OpenBao.
Type: attribute set of absolute path
Default:
{ }
Declared by:
services.panel.securityTxt
The /.well-known/security.txt of the panel domain, with the contact of
the hosting provider for vulnerability reports. null serves no file.
Type: null or (submodule)
Default:
null
Declared by:
services.panel.securityTxt.contact
URIs for vulnerability reports. Each URI gives one Contact field.
Type: non-empty (list of string matching the pattern (mailto|https|tel):.+)
Example:
[
"mailto:security@example.org"
]
Declared by:
services.panel.securityTxt.encryption
URL of the OpenPGP key for reports, which the Encryption field gives. null gives no field.
Type: null or HTTPS URL
Default:
null
Example:
"https://example.org/.well-known/pgp-key.txt"
Declared by:
services.panel.securityTxt.expires
The Expires field, in UTC. RFC 9116 recommends a date less than
one year ahead. Set it again before that date: after it, the
file is stale.
Type: string matching the pattern [0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?Z
Example:
"2027-10-17T00:00:00.000Z"
Declared by:
services.panel.securityTxt.policy
URL of the security policy, which the Policy field gives. null gives no field.
Type: null or HTTPS URL
Default:
null
Example:
"https://example.org/security-policy"
Declared by:
services.panel.settings
Django configuration as an attribute set. Name-value pairs will be converted to Python variable assignments.
Type: attribute set of anything
Default:
{
STATIC_ROOT = "/var/lib/panel/static";
DEBUG = false;
ALLOWED_HOSTS = [ cfg.domain cfg.host "localhost" "[::1]" ]
++ lib.optional cfg.centrifugo.enable cfg.centrifugo.wsDomain;
CSRF_TRUSTED_ORIGINS = [ "https://${cfg.domain}" ]
++ lib.optional cfg.centrifugo.enable "https://${cfg.centrifugo.wsDomain}";
COMPRESS_OFFLINE = true;
LIBSASS_OUTPUT_STYLE = "compressed";
SESSION_COOKIE_SECURE = cfg.production;
CSRF_COOKIE_SECURE = cfg.production;
LANGUAGE_COOKIE_SECURE = cfg.production;
}
Declared by:
services.panel.shellEnv
The environment from which to execute the manage script.
Type: attribute set
Default:
{ }
Declared by:
services.panel.wallet.enable
Whether to enable log-in with an EU Digital Identity Wallet.
Type: boolean
Default:
false
Example:
true
Declared by:
services.panel.wallet.clientID
Client ID the panel is registered under with the wallet verifier.
Type: string
Default:
"panel"
Declared by:
services.panel.wallet.clientSecretFile
Path to a file holding the client secret. Staged as for
oidc.clientSecretFile, by panel-wallet-secret.service.
Type: string
Default:
""
Declared by:
services.panel.wallet.issuer
OIDC issuer URL of the wallet verifier. The sub claim that the
verifier gives must stay the same for each person, because the panel
links an account to this value. The callback of the panel is
/oauth/complete/wallet/.
Type: string
Default:
""
Declared by:
services.panel.wallet.scopes
OIDC scopes the panel requests from the wallet verifier.
Type: list of string
Default:
[
"openid"
]
Declared by: