Fediversity/deployment/default.nix
Valentin Gagarin 6100b278b6 generate Python data models from module options (#285)
this shows a proof of concept for generating Django forms from NixOS modules

note that the form behavior is still rather clumsy and doesn't exactly map to the module semantics:
- since forms can only be sent wholesale, empty form fields will show up as empty strings
  and break validation without additional cleanup (not done here)
- it's not possible to faithfully translate `type = submodule { /* ... */}; default = {};`, since the default
  is translated to an empty dict `{}`. this is because the JSON schema converter does not preserve type information.
  this can be added by making it use `$defs` [1], but that would likely amount to half a rewrite
- there's a glitch in enum default values that needs to be fixed in `datamodel-code-generator` [0]

[0]: dd44480359/src/datamodel_code_generator/parser/base.py (L1015)
[1]: https://json-schema.org/understanding-json-schema/structuring#defs

a generated file will be placed into the source (by the development shell and the package respectively)
that declares Pydantic types from which to render the form. it looks something like this:

```python
from __future__ import annotations

from enum import Enum
from typing import Optional

from pydantic import BaseModel, Extra, Field
from drf_pydantic import BaseModel

class Domain(Enum):
    fediversity_net = 'fediversity.net'

# ...

class Model(BaseModel):
    class Config:
        extra = Extra.forbid

    domain: Optional[Domain] = Field(
        'fediversity.net',
        description='Apex domain under which the services will be deployed.\n',
    )

  # ...
```
2025-05-01 01:26:52 +02:00

194 lines
6.9 KiB
Nix

## `makeMakeDeployment` -- Function to help hosting providers make a
## `makeDeployment` function.
##
## https://factoryfactoryfactory.net/
## Generic utilities used in this function, eg. nixpkgs, NixOps4 providers, etc.
## REVIEW: We should maybe be more specific than just `inputs`.
{
lib,
nixops4,
nixops4-nixos,
fediversity,
}:
## Information on the hosting provider's infrastructure. This is where we inform
## this function of where it can find eg. Proxmox.
{
## Four NixOS configuration resource modules for four services. Those are VMs
## that are already deployed and on which we will push our configurations.
##
## - Ultimately, we just want a pool of VMs, or even just a Proxmox.
## - Each machine is flagged for a certain use case until we control DNS.
garageConfigurationResource,
mastodonConfigurationResource,
peertubeConfigurationResource,
pixelfedConfigurationResource,
}:
## From the hosting provider's perspective, the function is meant to be
## partially applied only until here.
## Information on the specific deployment that we request. This is the
## information coming from the FediPanel.
##
## FIXME: lock step the interface with the definitions in the FediPanel
panelConfig:
let
inherit (lib) mkIf;
in
## Regular arguments of a NixOps4 deployment module.
{ providers, ... }:
{
options = {
deployment = lib.mkOption {
description = ''
Configuration to be deployed
'';
# XXX(@fricklerhandwerk):
# misusing this will produce obscure errors that will be truncated by NixOps4
type = lib.types.submodule ./options.nix;
};
};
config = {
providers = { inherit (nixops4.modules.nixops4Provider) local; };
resources =
let
## NOTE: All of these secrets are publicly available in this source file
## and will end up in the Nix store. We don't care as they are only ever
## used for testing anyway.
##
## FIXME: Generate and store in NixOps4's state.
mastodonS3KeyConfig =
{ pkgs, ... }:
{
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK3515373e4c851ebaad366558";
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34";
};
peertubeS3KeyConfig =
{ pkgs, ... }:
{
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK1f9feea9960f6f95ff404c9b";
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395";
};
pixelfedS3KeyConfig =
{ pkgs, ... }:
{
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b";
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987";
};
makeConfigurationResource = resourceModule: config: {
type = providers.local.exec;
imports = [
nixops4-nixos.modules.nixops4Resource.nixos
resourceModule
{
## NOTE: With NixOps4, there are several levels and all of them live
## in the NixOS module system:
##
## 1. Each NixOps4 deployment is a module.
## 2. Each NixOps4 resource is a module. This very comment is
## inside an attrset imported as a module in a resource.
## 3. Each NixOps4 'configuration' resource contains an attribute
## 'nixos.module', itself a NixOS configuration module.
nixos.module =
{ ... }:
{
imports = [
config
fediversity
];
};
}
];
};
in
{
garage-configuration = makeConfigurationResource garageConfigurationResource (
{ pkgs, ... }:
mkIf (panelConfig.mastodon.enable || panelConfig.peertube.enable || panelConfig.pixelfed.enable) {
fediversity = {
inherit (panelConfig) domain;
garage.enable = true;
pixelfed = pixelfedS3KeyConfig { inherit pkgs; };
mastodon = mastodonS3KeyConfig { inherit pkgs; };
peertube = peertubeS3KeyConfig { inherit pkgs; };
};
}
);
mastodon-configuration = makeConfigurationResource mastodonConfigurationResource (
{ pkgs, ... }:
mkIf panelConfig.mastodon.enable {
fediversity = {
inherit (panelConfig) domain;
temp.initialUser = {
inherit (panelConfig.initialUser) username email displayName;
# FIXME: disgusting, but nvm, this is going to be replaced by
# proper central authentication at some point
passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
};
mastodon = mastodonS3KeyConfig { inherit pkgs; } // {
enable = true;
};
temp.cores = 1; # FIXME: should come from NixOps4 eventually
};
}
);
peertube-configuration = makeConfigurationResource peertubeConfigurationResource (
{ pkgs, ... }:
mkIf panelConfig.peertube.enable {
fediversity = {
inherit (panelConfig) domain;
temp.initialUser = {
inherit (panelConfig.initialUser) username email displayName;
# FIXME: disgusting, but nvm, this is going to be replaced by
# proper central authentication at some point
passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
};
peertube = peertubeS3KeyConfig { inherit pkgs; } // {
enable = true;
## NOTE: Only ever used for testing anyway.
##
## FIXME: Generate and store in NixOps4's state.
secretsFile = pkgs.writeText "secret" "574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24";
};
};
}
);
pixelfed-configuration = makeConfigurationResource pixelfedConfigurationResource (
{ pkgs, ... }:
mkIf panelConfig.pixelfed.enable {
fediversity = {
inherit (panelConfig) domain;
temp.initialUser = {
inherit (panelConfig.initialUser) username email displayName;
# FIXME: disgusting, but nvm, this is going to be replaced by
# proper central authentication at some point
passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
};
pixelfed = pixelfedS3KeyConfig { inherit pkgs; } // {
enable = true;
};
};
}
);
};
};
}