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: