Options
The services.fediversity-api NixOS options below configure an API deployment.
services.fediversity-api.enable
Whether to enable Fediversity API HTTP service.
Type: boolean
Default:
false
Example:
true
Declared by:
services.fediversity-api.auditHead.interval
When to send the head, as a systemd OnCalendar value.
Type: string
Default:
"hourly"
Declared by:
services.fediversity-api.auditHead.publishCommand
A command that sends the head of the audit chain to a store off the
fleet. Each interval, the unit fediversity-api-audit-head runs
fediversity-api-audit-verify --json and writes its output, one
JSON object with events, seq, hash and time, to the stdin of
this command. The command runs as the user of the service. A later
head that does not continue an earlier one shows a changed or
removed event, also when the writers of the database changed the
chain too. null sends the head nowhere.
Type: null or string
Default:
null
Example:
"/run/current-system/sw/bin/logger -t audit-head"
Declared by:
services.fediversity-api.auditRetentionDays
The number of days that api/ keeps an audit event: who started an
action on a deployment, and the result. An audit event holds the
account key of the actor, which is personal data, so keep it only as
long as necessary. 0 keeps all audit events.
Type: unsigned integer, meaning >=0
Default:
365
Declared by:
services.fediversity-api.authz.allowAll
Without callbackUrl, allow every request. For development and
tests only. When callbackUrl is empty and this is false, the
service refuses to start.
Type: boolean
Default:
false
Declared by:
services.fediversity-api.authz.callbackTokenFile
Path to a file that contains a static token that api/ sends to the
callback as Authorization: Bearer <token>. The callback can then
refuse requests that do not come from api/. Empty sends no token,
unless the AUTHZ_CALLBACK_TOKEN environment variable holds one,
for example from an environmentFiles entry. This file has
precedence over that variable.
Type: string
Default:
""
Declared by:
services.fediversity-api.authz.callbackUrl
HTTP endpoint called per request for dynamic authorization. The
api/ POSTs {procedure, scope, headers} and expects
{allow: bool, sub?: string, deployment_ids?: string[]}. With
deployment_ids, GET /deployments lists only those
deployments. Empty disables the callback: the
service then starts only if allowAll is set.
Type: string
Default:
""
Declared by:
services.fediversity-api.authz.serviceTokenFile
Path to a file that contains a static token for internal calls from
a trusted backend, for example the hosting provider’s own backend.
A request with
Authorization: Bearer <token> goes to the callback with
internal: true and without the token. The callback then decides
on behalf of whom the call runs. Empty disables internal calls.
Type: string
Default:
""
Declared by:
services.fediversity-api.centrifugo.enable
Whether to enable a Centrifugo server for the events of api/.
Type: boolean
Default:
false
Example:
true
Declared by:
services.fediversity-api.centrifugo.allowedOrigins
Browser origins that may open a WebSocket. The Origin of the
handshake is the document origin (the front-end), not the WebSocket
host, and Centrifugo refuses a handshake from an origin not in the
list. The default has the AsyncAPI page, whose “Try it out” subscribes
to the channels that it documents.
Type: list of string
Default:
config.services.fediversity-api.frontendOrigins
++ lib.optional (config.services.fediversity-api.docs.asyncapiDomain != null)
"https://${config.services.fediversity-api.docs.asyncapiDomain}"
Declared by:
services.fediversity-api.centrifugo.apiKeyFile
Path to a file containing Centrifugo’s HTTP API admin key. systemd
gives it to the fediversity-api service as a credential. With
centrifugo.enable, the server reads the same file.
Type: string
Default:
""
Declared by:
services.fediversity-api.centrifugo.apiUrl
Base HTTP URL of Centrifugo’s /api/* endpoint (e.g.
http://events:8090/api). Empty disables Centrifugo publishes
(events are dropped). With centrifugo.enable, the default is the
HTTP API of that server.
Type: string
Default:
""
Declared by:
services.fediversity-api.centrifugo.domain
Public hostname browsers use to reach Centrifugo over WebSocket. When set, nginx terminates TLS on this name and proxies to Centrifugo. Empty leaves Centrifugo loopback-only.
The certificate is not configured here, as for domain: forceSSL is
set and the TLS material comes from the ssl resource or from the
user of this module.
A front-end that authorizes browsers by a session cookie needs a name that the cookie domain covers.
Type: string
Default:
""
Example:
"events.example.com"
Declared by:
services.fediversity-api.centrifugo.host
Bind address for Centrifugo’s HTTP server.
Type: string
Default:
"127.0.0.1"
Declared by:
services.fediversity-api.centrifugo.port
Bind port for Centrifugo’s HTTP server.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
8090
Declared by:
services.fediversity-api.centrifugo.proxyBaseUrl
Base URL of the proxy views of the front-end. Centrifugo forwards the
Cookie and Host headers of each connect, subscribe and publish
to <proxyBaseUrl>/<verb>/, and the front-end allows or refuses it.
null sets no proxy, so no client can connect.
Type: null or string
Default:
null
Example:
"http://127.0.0.1:8000/api/centrifugo"
Declared by:
services.fediversity-api.deployment.attribute
The attribute pointing to the deployment’s dev shell
(devShells.<system>.<ATTRIBUTE>). There is no default: the
hosting provider sets its deployment program.
Type: string
Declared by:
services.fediversity-api.deployment.destroyExecutable
The executable for destroy operations, as exposed inside the shell
named attribute.
Type: string
Default:
"tf-destroy.sh"
Declared by:
services.fediversity-api.deployment.env
The deploy-env value-map forwarded verbatim into the render-eval
subprocess. Its keys are the core-declared deploy-env key-set
(core.lib.deployEnvKeys), which is exactly what core’s render eval
consumes (SSH_PRIVATE_KEY_FILE, PUBLISHED_HOSTS/INTERNAL_HOSTS,
ENVIRONMENTS, TF_HTTP_ADDRESS/BOOTSTRAP, NETBOX_*, …). api/
forwards these without interpreting them, so it names no effect var:
a new effect adds its keys to its envKeys and this map grows with
no api/ edit. The deployer sets whichever values apply.
Type: attribute set of string
Default:
{ }
Declared by:
services.fediversity-api.deployment.executable
The executable to trigger as exposed inside the shell named
attribute.
Type: string
Default:
"tf-run.sh"
Declared by:
services.fediversity-api.deployment.migrationExecutable
The executable for the migration mint, as exposed inside the shell
named nodeEffectAttribute.
Type: string
Default:
"mint-migration-snapshot.sh"
Declared by:
services.fediversity-api.deployment.moduleType
The type of the option module to expose to the user.
Type: optionType
Declared by:
services.fediversity-api.deployment.nixpkgs
The nixpkgs instance for NIX_PATH.
Type: string
Default:
"/nix/store/nic9x1akidq8w8khp8gc7plvav3pps2v-source"
Declared by:
services.fediversity-api.deployment.nodeEffectAttribute
The attribute pointing to the node effects dev shell
(devShells.<system>.<ATTRIBUTE>), whose executables reach the running
Incus containers of a deployment: the migration mint and the
operations of an application.
Type: string
Default:
"operator-node-effects-all"
Declared by:
services.fediversity-api.deployment.openbao.address
The OpenBao address (VAULT_ADDR form) the api writes the state pointers of a migration import to, for the restore step of the operator deploy. Empty refuses a migration import that has state to restore.
Type: string
Default:
""
Declared by:
services.fediversity-api.deployment.openbao.caCertFile
The CA of the certificate of address. Empty uses the system trust store.
Type: string
Default:
""
Declared by:
services.fediversity-api.deployment.renamesLog
The accumulated rename harvest for moduleType, as
{ from; to; since; } entries oldest first. A rename is recoverable
from the option tree only while the pinned tree carries its
mkRenamedOptionModule marker, so the log is what lets the served
table reach past the current pin; see
core/lib/renames-for-source.nix.
The default is this tree’s own log, which pairs with the default
moduleType. A moduleType layered on from outside declares renames
no log of ours carries, which is a build error – handing the log in
is the claim that it covers the type – so such a deployment supplies
its own log, or null for none: no history, and no gate.
Type: null or (list of attribute set of anything)
Default:
lib.importJSON ../../core/renames-log.json
Example:
lib.importJSON ../../core/renames-log.json
++ [
{
from = [ "apps" ];
to = [ "applications" ];
since = 1;
}
]
Declared by:
services.fediversity-api.deployment.root_path
The path to the flake containing the deployment. There is no default: the hosting provider sets its deployment program.
Type: absolute path
Declared by:
services.fediversity-api.deployment.secretEnvKeys
Which of the deploy-env variables this unit runs with hold a
credential. Windmill writes a job’s arguments to its job table in
clear and shows them to everyone who can open the job, so
deployment.py drops these from the job it submits and the windmill
worker reads its own copy of each from OpenBao instead
(deploySecrets in
core/components/hosting-provider/windmill/windmill.nix). The
in-process subprocess route keeps them: it starts the deploy itself
and writes no job row.
A name here that the windmill node does not render reaches the deploy
as nothing at all, so the two are stated once and read by both
(core/components/hosting-provider/deploy-credentials.nix).
Type: list of string
Default:
[ ]
Declared by:
services.fediversity-api.deployment.selfModuleSource
A fetchTree-compatible pin of api/'s own source revision,
surfaced to the service as SELF_MODULE_SOURCE. When a deployment is
submitted with no module_source, api/ freezes it to this pin rather
than storing a bare null, so the “old” schema for the change view
stays the one actually deployed under instead of floating to whatever
api/ is later rebuilt against.
The revision is a property of the deploy, not the source tree –
recording it in-tree would be self-referential, since writing the
revision changes the tree and thus the revision – so it is threaded
in here rather than baked into the package. The deployer must set it
to the built revision, including a narHash so the fetch is
hash-pinned; see api/docs/guides/schema-pins.md. null keeps the floating
behaviour, acceptable for a dirty local build whose working tree is
not reproducible via fetchTree anyway.
Type: null or (attribute set of anything)
Default:
null
Example:
{
narHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
rev = "0000000000000000000000000000000000000000";
type = "git";
url = "https://git.fediversity.eu/fediversity/fediversity";
}
Declared by:
services.fediversity-api.deployment.stateAddressVars
Terraform variables that get the state address of an other deploy.
For each <name> = <suffix>, a deploy gets
TF_VAR_<name> = <base>-<suffix>, where <base> is the
TF_HTTP_ADDRESS before the scope of the deployment. The scope
moves the state address of the deploy, so a deployment program that
reads the state of an other deploy gets that address here.
Type: attribute set of string
Default:
{ }
Example:
{
peer_state_address = "peer";
}
Declared by:
services.fediversity-api.docs.asyncapiDomain
FQDN of the rendered AsyncAPI specification of the events of this
api/, or null for no page. nginx serves the page on this name. The
page sends no request to api/, so it needs no CORS entry. With
centrifugo.enable and a centrifugo.domain, the page names that
domain as the server of the events, and its “Try it out” subscribes
to the channels there. centrifugo.allowedOrigins has the origin of
the page by default. Centrifugo authorizes the subscriptions by the
session cookie of the front-end, so “Try it out” works only for a
reader who is logged in to the front-end, on a page that is on the
same site as the front-end.
Requires domain. As for domain, the certificate comes from the
ssl resource, or from the user of this module.
Type: null or string
Default:
null
Example:
"asyncapi.example.org"
Declared by:
services.fediversity-api.docs.swaggerDomain
FQDN of a Swagger UI page for this api/, or null for no page.
nginx serves the page on this name. Its OpenAPI spec comes from the
package of this node, with domain as its only server, so the “Try
it out” button sends its requests to this api/. The origin of the
page is added to docsOrigins, so the browser lets the page read
the replies.
Requires domain. As for domain, the certificate comes from the
ssl resource, or from the user of this module.
Type: null or string
Default:
null
Example:
"swagger.example.org"
Declared by:
services.fediversity-api.docsOrigins
Extra browser origins allowed to call api/ via CORS, without being
trusted in the other direction. Deliberately not folded into
frontendOrigins: that list doubles as the destroy-reconcile callback
allowlist, and a static documentation host must never become a legal
authorization oracle.
The use is a published Swagger UI bundle whose “Try it out” button
issues browser calls to this api/. That is safe because CORS restricts
browsers only – anyone holding a token could always call from outside
one – and because allow_credentials is off, so a browser attaches no
ambient cookies; api/ does no bearer validation of its own and answers
a tokenless call with 403. Without a token, a docs reader can call only
the public endpoints, such as GET /schema. With a token of the
front-end, pasted under “Authorize”, the reader calls as the user of
that token, as the front-end could.
docs.swaggerDomain adds the origin of its own page here.
Type: list of string
Default:
[ ]
Declared by:
services.fediversity-api.domain
api/'s browser-facing FQDN. When set, nginx terminates TLS on this name
and proxies to the loopback-bound FastAPI server, giving api/ a
browser-reachable origin: the panel’s deployment form fetches its schema
and rename table straight from api/ (GET /schema,
GET /schema/migrations), and the Deploy/Delete buttons call it
directly too. Empty leaves api/ loopback-only – no vhost, no ingress.
The certificate is not configured here: forceSSL is set and the ssl
resource writes sslCertificate/sslCertificateKey (and enableACME
for a publicly-issued leaf) onto this vhost from the application’s
tls.ssl.domains request, as it does for the panel. A standalone user
of this module setting domain must supply that TLS material itself.
Type: string
Default:
""
Declared by:
services.fediversity-api.domainTerms
The domain terms of the hosting provider. When set, api/ refuses a
submit or an import that takes a domain without the acceptance of the
current version, and records the accepted version in the audit event
and on the deployment. An automatic update does not check the terms.
null: a registration needs no acceptance.
Type: null or (submodule)
Default:
null
Declared by:
services.fediversity-api.domainTerms.effective
The date from which the current version applies, as
YYYY-MM-DD. api/ shows it with the terms. null: api/ shows
no date.
Type: null or string
Default:
null
Declared by:
services.fediversity-api.domainTerms.url
Where an operator reads the domain terms.
Type: string
Declared by:
services.fediversity-api.domainTerms.version
The current version of the domain terms. A deployment that
takes a domain accepts this version. A deployment that has its
domain stays at the version that it accepted, and GET /domains
shows the acceptance as pending.
Type: string
Declared by:
services.fediversity-api.environmentFiles
EnvironmentFile= entries of the service, for example the
runtime-discovered TF_VAR_image_fingerprint that then rides the
windmill job payload. A leading - makes a file optional. A file must
not set TF_VAR_incus_config_dir: systemd applies an EnvironmentFile
after Environment=, so a stale path there would beat the
StateDirectory one that the service sets.
Type: list of string
Default:
[ ]
Example:
[
"-/var/lib/example/tf-env"
]
Declared by:
services.fediversity-api.frontendOrigins
Browser origins (scheme + host + optional port) allowed to call api/ directly via CORS. The front-end lives on a different registrable domain than api/ (white-labelling), so cross-origin requests need an explicit allowlist. Empty disables CORS (no browser-direct access).
This list doubles as the allowlist for the destroy reconcile callback:
the browser supplies a callback URL on the DELETE request and api/ only
POSTs it back, on destroy-success, when its origin is in this list. The
set of front-ends api/ may call back is exactly the set trusted to call
in, so it is one list. See api/docs/design/deployments.md (Two-store model and deletion).
Type: list of string
Default:
[ ]
Declared by:
services.fediversity-api.hostingConfig
The hosting provider’s curation of the deployment form, as data: the
HOSTING_CONFIG model documented in api/docs/reference/environment.md, with its
environments and effect-defaults sections. null leaves the form
uncurated, offering every operator-facing field.
Taken as an attrset rather than a path so the values stay
module-composable and no relative import has to survive a copy into
the store; it is rendered to one JSON file here.
That one file reaches all three consumers that must agree – the
build-time schema prune (api/package.nix’s hostingLeaves), the
per-module_source schema re-eval (HOSTING_CONFIG in the unit
environment), and the deploy eval (HOSTING_CONFIG in deploy_env) –
so a leaf pruned from the form is exactly a leaf baked as a value, and
the operator can neither see nor override it.
Type: null or (attribute set of anything)
Default:
null
Example:
{
effect-defaults = {
tf-incus-operator-hosts = {
host = "10.0.100.1";
port = 8443;
};
};
}
Declared by:
services.fediversity-api.http.listenAddr
Bind address for the FastAPI HTTP server. Loopback by default even
when domain publishes api/ to browsers: nginx fronts it on the same
node, so the FastAPI server itself stays off the network.
Type: string
Default:
"127.0.0.1"
Declared by:
services.fediversity-api.http.listenPort
Bind port for the FastAPI HTTP server. 8081 collides with
terraform-backend’s metrics endpoint when both run on the same
host; pick something further out by default.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
8088
Declared by:
services.fediversity-api.logRetentionDays
The number of days that api/ keeps the log of a build and a run of an
operation, after the build or the run finished. A build log and the
output of an operation can hold personal data, and a run holds the
account key of the actor. api/ keeps the build row itself, because
the usage records come from it. 0 keeps all logs and runs.
Type: unsigned integer, meaning >=0
Default:
30
Declared by:
services.fediversity-api.openbao.address
The address of the OpenBao server that keeps the secrets that the
operator gives in the settings of an application, such as the API
key of a translation service. On a submit, api/ writes each such
secret to the KV entry of the deployment and keeps only its name in
the stored configuration. The token comes from the environment as
TF_VAR_openbao_token. An empty address keeps no secrets: api/
refuses a submit that gives one.
Type: string
Default:
""
Example:
"https://openbao.example.org:8200"
Declared by:
services.fediversity-api.openbao.kvDeployments
The path in openbao.kvMount below which each deployment has its
vars entries, as <kvDeployments>/<deployment id>.
Type: string
Default:
"vars/operator-deployments"
Declared by:
services.fediversity-api.openbao.kvMount
The KV version 2 mount of the secrets in openbao.address.
Type: string
Default:
"secret"
Declared by:
services.fediversity-api.pinEffect
Collapse the served deployment-method union to this single member: the
served schema loses deployment-method entirely and carries that
effect’s settings at its root, so the form has no method picker and
renders those settings as ordinary fields. Names any union member – a
deployment method or a standalone effect. The module-option counterpart
of the PIN_EFFECT build variable documented in api/docs/guides/schema-pins.md; an
undeclared name fails the build, as does a setting whose name a
top-level option already takes.
null bakes the whole union, the form where the operator picks the
method.
Type: null or string
Default:
null
Example:
"tf-incus-operator-hosts"
Declared by:
services.fediversity-api.registrarSnapshot
The snapshot of the registrar account that registrar-domains writes
(services.fediversity-registrar-domains.snapshotFile). The unit
fediversity-api-domain-renewals compares it with the domain events,
and records the renewals and the releases of the domains of the
deployments. A new snapshot starts the unit. GET /domains reads
the expiry and the renewal of a domain from it. null records no
renewal and no release, and GET /domains gives the expiry and the
renewal of the last deploy.
Type: null or string
Default:
null
Example:
"/run/registrar-domains/registrar.json"
Declared by:
services.fediversity-api.registryTermsFile
The JSON table of the terms of the registries whose extensions need an
acceptance at a registration or a transfer, by extension. The operator
graph sends the acceptance to the registrar from the same table. api/
refuses a submit or an import that registers a domain with such an
extension without the acceptance of these terms, together with the
terms of domainTerms, and refuses an extension of the table without
documents. null: no registry terms.
Type: null or absolute path
Default:
../../core/effects/tf/incus/operator/registry-terms.json
Declared by:
services.fediversity-api.restart
systemd restart behavior
Type: one of “no”, “on-success”, “on-failure”, “on-abnormal”, “on-abort”, “always”
Default:
"always"
Declared by:
services.fediversity-api.schemaBuildTimeout
Deadline in seconds for one on-demand nix fetch-and-build of a
module_source’s schema or rename table, described under “Cost and
latency” in api/docs/design/schema-and-sources.md, and for the eval of the nodes of a
submitted configuration. A cold build fetches the source and
may evaluate IFD dependencies, so it takes minutes; overrunning this is
killed and answered with a 504 fediversity.error.build_timeout.
This value also sizes the ingress: nginx must give a request at least
as long as api/ may spend inside it, or its own 504 – which carries
none of the CORS headers the app sets – replaces the app’s answer and
the browser sees an opaque network error.
Type: positive integer, meaning >0
Default:
300
Declared by:
services.fediversity-api.trustedSourceUrls
Exact module_source repo URLs api/ will fetch and deploy. A submitted
source passes when its url equals one of these, after tolerating a
trailing .git//. A sibling repo or a /../ traversal that merely
shares a prefix does not pass. This is the hosting provider’s trust
lever, not the Fediversity project gatekeeping forks.
In a trusted repo, the source must also select a branch: a git source
whose ref is absent, HEAD, a branch name or refs/heads/*, with no
allRefs and no ?query or #fragment on the url. A rev must be a
full commit id that the named branch (or, with no ref, any branch)
contains; api/ asks the repo with git. Thus anyone who can open a pull
request cannot deploy its refs/pull/* commits. Pushing a branch needs
write access. api/ rejects any other source with HTTP 400 before
fetchTree.
The default is our repo only. An explicit empty list [ ] allows any
source, with no branch check. A null module_source (the built-in
default module) is always allowed; it is not a caller-named fork.
Type: list of string
Default:
[
"https://git.fediversity.eu/fediversity/fediversity"
]
Declared by:
services.fediversity-api.windmill.baseUrl
Base HTTP URL of the Windmill instance.
Type: string
Default:
""
Declared by:
services.fediversity-api.windmill.workspace
Windmill workspace identifier.
Type: string
Default:
"fediversity"
Declared by:
services.fediversity-api.zoneFollow.probeLabels
The labels below a deSEC zone that api follows after a migration
export, which the follow also asks the new nameservers for when it
copies the zone by queries: when no new nameserver gives a zone
transfer or a walk of the NSEC chain. The copy then also has such a
name that only the target holds. The default is the labels under
which Fediversity writes records with the default settings.
Type: list of string
Default:
import ../../core/components/standard-labels.nix { inherit lib; }
Example:
[
"mastodon"
"_dmarc"
]
Declared by:
services.fediversity-api.zoneFollow.whoamiUrls
The HTTPS URLs that give the address of the client, as plain text or
as JSON with data.ip. A migration export of a deployment whose zone
the provider holds at deSEC puts the global addresses of api in
the migration string, thus the target lets the follow in api
transfer the zone. For each IP version, api takes the local
address of its route to other networks. When that address is not
global, for example behind NAT, the export asks these URLs in order,
over that IP version, and takes the first global address of that
version. The service then sees the address of api. An empty list
asks no URL: the export then gives no address for that IP version.
Type: list of string
Default:
[
"https://stat.ripe.net/data/whats-my-ip/data.json"
"https://am.i.mullvad.net/ip"
]
Example:
[ ]
Declared by: