Architecture
This part shows the system context of Fediversity and the containers of one installation of a hosting provider. It also shows the components of each deployment, with the services that each component requests and provides.
System context
flowchart TB operator["<b>Operator</b><br/>[Person]<br/>Has a deployment with applications"] user["<b>Application user</b><br/>[Person]<br/>Uses an application of an operator"] provider["<b>Hosting provider</b><br/>[Person]<br/>Runs the infrastructure and manages the accounts"] maintainer["<b>Maintainer</b><br/>[Person]<br/>Changes and releases the code"] fediversity["<b>Fediversity</b><br/>[Software system]<br/>Installs, configures and updates applications, manages users, moves deployments between hosting providers"] registrar["<b>Domain registrar</b><br/>[External system]<br/>OpenProvider, INWX or Porkbun"] dns["<b>DNS service</b><br/>[External system]<br/>Authoritative DNS that is not in the deployment, for example deSEC or PowerDNS"] acme["<b>ACME certificate authority</b><br/>[External system]<br/>Issues TLS certificates"] relay["<b>Mail relay</b><br/>[External system]<br/>SMTP submission service of a third party"] upstream["<b>Upstream sources</b><br/>[External system]<br/>nixpkgs and the other pinned sources"] other["<b>Other hosting provider</b><br/>[Software system]<br/>A different installation of Fediversity"] operator -->|"configures and deploys, HTTPS"| fediversity user -->|"uses the applications, HTTPS"| fediversity provider -->|"configures, deploys and monitors"| fediversity maintainer -->|"releases code and pins"| fediversity fediversity -->|"registers and transfers domains"| registrar fediversity -->|"publishes DNS records"| dns fediversity -->|"requests certificates"| acme fediversity -->|"sends mail"| relay fediversity -->|"gets packages and modules"| upstream fediversity -->|"exports and imports a deployment"| other classDef external stroke-dasharray: 5 5 class registrar,dns,acme,relay,upstream,other external
Each external system is a selection of the hosting provider, not a fixed part:
- Registrars:
core/effects/tf/registrars.nixhas one entry for each registrar, and the steps that each registrar can do. - DNS: the
dnsresource has a provider for a BIND node in the deployment (core/resources/dns/self-hosted.nix) and a provider for a service that the hosting provider already has (core/resources/dns/external.nix). Thecore/effects/octodnseffect publishes the records. Choose where the DNS zones are gives the selection. - Certificates: the
sslresource has an ACME provider, an OpenBao PKI provider and a self-signed provider (core/resources/ssl/). - Mail: the
smtpresource has a provider that runs a mail server in the deployment and a provider for an external relay (core/resources/smtp/). - Upstream sources:
npins/sources.jsonpins nixpkgs and each other source. The SBOM page tells how to find the software of a node.
The threat model gives the trust boundaries between these parties, and data protection gives the parties that get personal data.
Containers
The diagram shows the parts of one installation of a hosting provider. The
architecture page of the panel
has the container and component views of panel, and the
site of the API has those of api.
flowchart TB
browser["<b>Browser of the operator</b><br/>[Person and browser]"]
subgraph frontend["Front end"]
panel["<b>panel</b><br/>[Container: Django]<br/>Accounts, ownership of deployments, configuration form"]
panelDb[("<b>Panel database</b><br/>[Container: PostgreSQL or SQLite]")]
end
subgraph apiSide["API"]
api["<b>api</b><br/>[Container: FastAPI]<br/>Validates, queues builds, runs deployments"]
apiDb[("<b>API state store</b><br/>[Container: PostgreSQL or SQLite]")]
centrifugo["<b>Centrifugo</b><br/>[Container]<br/>Sends progress events"]
jobs["<b>Job runner</b><br/>[Container: subprocess or Windmill]<br/>Runs a build or a deployment"]
end
subgraph coreSide["core"]
programs["<b>Deployment programs</b><br/>[Container: Nix and OpenTofu]<br/>Change a configuration into machines, records and secrets"]
schema["<b>Schema and catalog</b><br/>[Container: Nix]<br/>JSON Schema of the options, list of applications"]
end
subgraph providerSide["Deployment of the hosting provider"]
services["<b>Shared services</b><br/>[Containers]<br/>See the diagrams below"]
incus["<b>Incus hypervisor</b><br/>[Container]<br/>Runs the machines of the deployments"]
end
subgraph operatorSide["Deployment of an operator"]
apps["<b>Applications and their services</b><br/>[Containers]<br/>See the diagrams below"]
end
browser -->|"HTTPS"| panel
browser -->|"HTTPS, bearer token"| api
centrifugo -->|"WebSocket"| browser
panel --> panelDb
api -->|"authorization callback, HTTPS"| panel
api --> apiDb
api -->|"publishes events"| centrifugo
api -->|"reads"| schema
api -->|"starts a job"| jobs
jobs -->|"runs"| programs
programs -->|"creates and changes machines"| incus
programs -->|"reads and writes state, secrets and addresses"| services
incus -->|"runs"| apps
apps -->|"use"| services
Notes for the diagram:
apiruns a deployment program as anixsubprocess, directly or in a Windmill job (api/src/fediversity_api/_runner.py,api/src/fediversity_api/deployment.py).apiandpanelare also components of the data model (api/nix/component/,panel/nix/component/), thus the deployment programs ofcorecan deploy them the same as each other service.- Configuration data flow shows how a configuration becomes a
deployment in
core. - Flake attributes lists the deployment programs.
Components of a deployment of an operator
The build makes the two diagrams and the two tables below from the code. They
show the components of the operator group and of the hosting-provider group
of core/setups/groups, each with its default settings. A node shows the
resources that the component provides (wiring.provides in
core/components/wiringProperties.nix). An arrow goes from a component to the
component that answers its request, and its label gives the resources. A
request goes to a component of the same group. If the group has no such
component, the request goes to the component of the hosting-provider group.
Two requests have a name that is different from the name of the backend that
answers them: a generateFiles request goes to varsBackend, and a garage
request goes to objectStore. A request without an arrow has no service
component that provides it. Examples are nixos-module and firewall, which
change the machine itself, and ssl, which has three providers.
Hosting resources describes each resource.
flowchart LR
subgraph applications["Applications that the operator selects"]
applications_mastodon["<b>mastodon<br/>peertube<br/>pixelfed</b>"]
end
subgraph own["Service components of the operator group"]
own_authelia["<b>authelia</b><br/>provides: oidc"]
own_grafana["<b>grafana</b>"]
own_lldap["<b>lldap</b><br/>provides: ldap"]
own_smtp["<b>smtp</b><br/>provides: smtp"]
own_valkey["<b>valkey</b><br/>provides: redis"]
end
subgraph central["Service components of the hosting-provider group"]
central_garage["<b>garage</b><br/>provides: objectStore"]
central_openbao["<b>openbao</b><br/>provides: varsBackend, pki"]
central_postgresql["<b>postgresql</b><br/>provides: postgresql"]
central_spire["<b>spire</b><br/>provides: spiffe"]
end
applications_mastodon -->|"garage"| central_garage
applications_mastodon -->|"generateFiles"| central_openbao
applications_mastodon -->|"postgresql"| central_postgresql
applications_mastodon -->|"spiffe"| central_spire
applications_mastodon -->|"oidc"| own_authelia
applications_mastodon -->|"ldap"| own_lldap
applications_mastodon -->|"smtp"| own_smtp
applications_mastodon -->|"redis"| own_valkey
own_authelia -->|"garage"| central_garage
own_authelia -->|"generateFiles"| central_openbao
own_authelia -->|"postgresql"| central_postgresql
own_authelia -->|"spiffe"| central_spire
own_authelia -->|"redis"| own_valkey
own_grafana -->|"generateFiles"| central_openbao
own_grafana -->|"spiffe"| central_spire
own_grafana -->|"oidc"| own_authelia
own_lldap -->|"garage"| central_garage
own_lldap -->|"generateFiles"| central_openbao
own_lldap -->|"postgresql"| central_postgresql
own_lldap -->|"spiffe"| central_spire
own_lldap -->|"oidc"| own_authelia
own_smtp -->|"spiffe"| central_spire
own_valkey -->|"spiffe"| central_spire
own_valkey -->|"oidc"| own_authelia
| Component | Kind | Provides | Requests |
|---|---|---|---|
authelia |
service | oidc |
garage, postgresql, generateFiles, redis, nixos-module, spiffe, firewall |
grafana |
service | -- | nixos-module, oidc, spiffe, ssl, generateFiles, firewall |
lldap |
service | ldap |
garage, postgresql, oidc, nixos-module, spiffe, generateFiles |
mastodon |
application | -- | nixos-module, garage, redis, postgresql, oidc, ldap, smtp, generateFiles, pod-roles, spiffe, ssl, firewall |
peertube |
application | -- | nixos-module, firewall, generateFiles, garage, redis, postgresql, oidc, ldap, smtp, spiffe, ssl |
pixelfed |
application | -- | nixos-module, generateFiles, garage, redis, postgresql, oidc, ldap, smtp, spiffe, ssl, firewall |
smtp |
service | smtp |
spiffe |
valkey |
service | redis |
nixos-module, oidc, spiffe, redis |
Components of the deployment of the hosting provider
flowchart LR
subgraph own["Service components of the hosting-provider group"]
own_authelia["<b>authelia</b><br/>provides: oidc"]
own_bind["<b>bind</b>"]
own_garage["<b>garage</b><br/>provides: objectStore"]
own_incus["<b>incus</b><br/>provides: instances"]
own_lldap["<b>lldap</b><br/>provides: ldap"]
own_netbox["<b>netbox</b><br/>provides: netbox"]
own_openbao["<b>openbao</b><br/>provides: varsBackend, pki"]
own_otel_collector["<b>otel-collector</b><br/>provides: otel"]
own_overview["<b>overview</b><br/>provides: uiIndex"]
own_postgresql["<b>postgresql</b><br/>provides: postgresql"]
own_smtp["<b>smtp</b><br/>provides: smtp"]
own_spire["<b>spire</b><br/>provides: spiffe"]
own_telemetry["<b>telemetry</b><br/>provides: otelBackend"]
own_terraform_backend["<b>terraform-backend</b><br/>provides: tfState"]
own_valkey["<b>valkey</b><br/>provides: redis"]
own_windmill["<b>windmill</b>"]
end
own_authelia -->|"garage"| own_garage
own_authelia -->|"generateFiles"| own_openbao
own_authelia -->|"postgresql"| own_postgresql
own_authelia -->|"spiffe"| own_spire
own_authelia -->|"redis"| own_valkey
own_bind -->|"garage"| own_garage
own_bind -->|"generateFiles"| own_openbao
own_bind -->|"spiffe"| own_spire
own_garage -->|"oidc"| own_authelia
own_garage -->|"spiffe"| own_spire
own_incus -->|"oidc"| own_authelia
own_incus -->|"generateFiles"| own_openbao
own_incus -->|"spiffe"| own_spire
own_lldap -->|"oidc"| own_authelia
own_lldap -->|"garage"| own_garage
own_lldap -->|"generateFiles"| own_openbao
own_lldap -->|"postgresql"| own_postgresql
own_lldap -->|"spiffe"| own_spire
own_netbox -->|"oidc"| own_authelia
own_netbox -->|"garage"| own_garage
own_netbox -->|"generateFiles"| own_openbao
own_netbox -->|"otel"| own_otel_collector
own_netbox -->|"postgresql"| own_postgresql
own_netbox -->|"smtp"| own_smtp
own_netbox -->|"spiffe"| own_spire
own_openbao -->|"oidc"| own_authelia
own_openbao -->|"garage"| own_garage
own_openbao -->|"spiffe"| own_spire
own_otel_collector -->|"generateFiles"| own_openbao
own_otel_collector -->|"spiffe"| own_spire
own_overview -->|"spiffe"| own_spire
own_postgresql -->|"oidc"| own_authelia
own_postgresql -->|"garage"| own_garage
own_postgresql -->|"generateFiles"| own_openbao
own_postgresql -->|"spiffe"| own_spire
own_smtp -->|"spiffe"| own_spire
own_telemetry -->|"oidc"| own_authelia
own_telemetry -->|"garage"| own_garage
own_telemetry -->|"generateFiles"| own_openbao
own_telemetry -->|"smtp"| own_smtp
own_telemetry -->|"spiffe"| own_spire
own_terraform_backend -->|"garage"| own_garage
own_terraform_backend -->|"generateFiles"| own_openbao
own_terraform_backend -->|"spiffe"| own_spire
own_valkey -->|"oidc"| own_authelia
own_valkey -->|"spiffe"| own_spire
own_windmill -->|"oidc"| own_authelia
own_windmill -->|"garage"| own_garage
own_windmill -->|"netbox"| own_netbox
own_windmill -->|"generateFiles"| own_openbao
own_windmill -->|"otel"| own_otel_collector
own_windmill -->|"postgresql"| own_postgresql
own_windmill -->|"smtp"| own_smtp
own_windmill -->|"spiffe"| own_spire
| Component | Kind | Provides | Requests |
|---|---|---|---|
authelia |
service | oidc |
garage, postgresql, generateFiles, redis, nixos-module, spiffe, firewall |
bind |
service | -- | garage, nixos-module, spiffe, generateFiles |
garage |
service | objectStore |
nixos-module, oidc, spiffe, firewall |
incus |
service | instances |
nixos-module, generateFiles, oidc, spiffe, ssl |
lldap |
service | ldap |
garage, postgresql, oidc, nixos-module, spiffe, generateFiles |
netbox |
service | netbox |
nixos-module, garage, postgresql, oidc, smtp, otel, generateFiles, spiffe, ssl |
openbao |
service | varsBackend, pki |
nixos-module, garage, oidc, spiffe, ssl |
otel-collector |
service | otel |
nixos-module, spiffe, generateFiles |
overview |
service | uiIndex |
nixos-module, spiffe, ssl, firewall |
postgresql |
service | postgresql |
nixos-module, oidc, garage, spiffe, generateFiles |
smtp |
service | smtp |
spiffe |
spire |
service | spiffe |
nixos-module |
telemetry |
service | otelBackend |
generateFiles, nixos-module, garage, spiffe, oidc, smtp, ssl |
terraform-backend |
service | tfState |
nixos-module, generateFiles, spiffe, garage, ssl |
valkey |
service | redis |
nixos-module, oidc, spiffe, redis |
windmill |
service | -- | generateFiles, nixos-module, dns, netbox, otel, spiffe, ssl, garage, postgresql, smtp, oidc |
api and panel are not in this table, because their component definitions
are outside core.