Compare commits

..

1 commit

Author SHA1 Message Date
e5710979ba
fix typo 2025-07-17 19:00:41 +02:00
74 changed files with 284 additions and 2173 deletions

View file

@ -1,5 +1,4 @@
on: on:
workflow_dispatch: # allows manual triggering
pull_request: pull_request:
types: types:
- opened - opened
@ -10,8 +9,50 @@ on:
- main - main
jobs: jobs:
check-pre-commit:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix-build -A tests
check-data-model: check-data-model:
runs-on: native runs-on: native
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- run: nix-shell --run 'nix-unit ./deployment/data-model-test.nix' - run: nix-shell --run 'nix-unit ./deployment/data-model-test.nix'
check-mastodon:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.test-mastodon-service -L
check-peertube:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.test-peertube-service -L
check-panel:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix-build -A tests.panel
check-deployment-basic:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.deployment-basic -L
check-deployment-cli:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.deployment-cli -L
check-deployment-panel:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.deployment-panel -L

View file

@ -1,61 +0,0 @@
#!/bin/sh
set -euC
cd "$(dirname "$0")" || exit 3
nix_eval () { nix eval --impure --raw --expr "with builtins; $1"; }
system=$(nix_eval "currentSystem")
checks=$(nix_eval "toJSON (attrNames (getFlake (toString ../..)).checks.$system)")
output=$(mktemp)
{
cat <<EOF
name: Nix flake checks
on:
pull_request:
types:
- opened
- synchronize
- reopened
push:
branches:
- main
jobs:
_checks:
needs: $checks
runs-on: native
steps:
- run: true
_complete:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix-shell --run '.forgejo/workflows/nix-flake-check.sh check'
EOF
for check in $(echo "$checks" | jq -r .[]); do
cat <<EOF
$check:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.$system.$check -vL
EOF
done
} >| "$output"
target=$(basename "$0" .sh).yaml
if [ $# -eq 1 ] && [ "$1" = "check" ]; then
if ! diff_output=$(diff --color=always "$target" "$output"); then
printf >&2 'Changes detected (\e[31m< current\e[0m | \e[32m> generated\e[0m):\n%s\n' "$diff_output"
exit 1
fi
else
mv "$output" "$target"
fi

View file

@ -1,294 +0,0 @@
name: Nix flake checks
on:
pull_request:
types:
- opened
- synchronize
- reopened
push:
branches:
- main
jobs:
_checks:
needs: ["deployment-basic","deployment-cli","deployment-model-nixops4","deployment-model-ssh","deployment-model-tf","deployment-panel","nixops-deployment-providers-default","nixops-deployment-providers-fedi200","nixops-deployment-providers-fedi201","nixops-deployment-providers-forgejo-ci","nixops-deployment-providers-test","nixops-deployment-providers-vm02116","nixops-deployment-providers-vm02187","nixosConfigurations-fedi200","nixosConfigurations-fedi201","nixosConfigurations-forgejo-ci","nixosConfigurations-test01","nixosConfigurations-test02","nixosConfigurations-test03","nixosConfigurations-test04","nixosConfigurations-test05","nixosConfigurations-test06","nixosConfigurations-test11","nixosConfigurations-test12","nixosConfigurations-test13","nixosConfigurations-test14","nixosConfigurations-vm02116","nixosConfigurations-vm02187","panel","pre-commit","proxmox-basic","test-mastodon-service","test-peertube-service","vmOptions-fedi200","vmOptions-fedi201","vmOptions-test01","vmOptions-test02","vmOptions-test03","vmOptions-test04","vmOptions-test05","vmOptions-test06","vmOptions-test11","vmOptions-test12","vmOptions-test13","vmOptions-test14"]
runs-on: native
steps:
- run: true
_complete:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix-shell --run '.forgejo/workflows/nix-flake-check.sh check'
deployment-basic:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.deployment-basic -vL
deployment-cli:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.deployment-cli -vL
deployment-model-nixops4:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.deployment-model-nixops4 -vL
deployment-model-ssh:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.deployment-model-ssh -vL
deployment-model-tf:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.deployment-model-tf -vL
deployment-panel:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.deployment-panel -vL
nixops-deployment-providers-default:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixops-deployment-providers-default -vL
nixops-deployment-providers-fedi200:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixops-deployment-providers-fedi200 -vL
nixops-deployment-providers-fedi201:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixops-deployment-providers-fedi201 -vL
nixops-deployment-providers-forgejo-ci:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixops-deployment-providers-forgejo-ci -vL
nixops-deployment-providers-test:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixops-deployment-providers-test -vL
nixops-deployment-providers-vm02116:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixops-deployment-providers-vm02116 -vL
nixops-deployment-providers-vm02187:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixops-deployment-providers-vm02187 -vL
nixosConfigurations-fedi200:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-fedi200 -vL
nixosConfigurations-fedi201:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-fedi201 -vL
nixosConfigurations-forgejo-ci:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-forgejo-ci -vL
nixosConfigurations-test01:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-test01 -vL
nixosConfigurations-test02:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-test02 -vL
nixosConfigurations-test03:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-test03 -vL
nixosConfigurations-test04:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-test04 -vL
nixosConfigurations-test05:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-test05 -vL
nixosConfigurations-test06:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-test06 -vL
nixosConfigurations-test11:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-test11 -vL
nixosConfigurations-test12:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-test12 -vL
nixosConfigurations-test13:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-test13 -vL
nixosConfigurations-test14:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-test14 -vL
nixosConfigurations-vm02116:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-vm02116 -vL
nixosConfigurations-vm02187:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.nixosConfigurations-vm02187 -vL
panel:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.panel -vL
pre-commit:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.pre-commit -vL
proxmox-basic:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.proxmox-basic -vL
test-mastodon-service:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.test-mastodon-service -vL
test-peertube-service:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.test-peertube-service -vL
vmOptions-fedi200:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-fedi200 -vL
vmOptions-fedi201:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-fedi201 -vL
vmOptions-test01:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-test01 -vL
vmOptions-test02:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-test02 -vL
vmOptions-test03:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-test03 -vL
vmOptions-test04:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-test04 -vL
vmOptions-test05:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-test05 -vL
vmOptions-test06:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-test06 -vL
vmOptions-test11:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-test11 -vL
vmOptions-test12:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-test12 -vL
vmOptions-test13:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-test13 -vL
vmOptions-test14:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.vmOptions-test14 -vL

View file

@ -13,7 +13,7 @@ jobs:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Update pins - name: Update pins
run: nix-shell --run "npins --verbose update" run: nix-shell --run "npins update"
- name: Create PR - name: Create PR
uses: https://github.com/KiaraGrouwstra/gitea-create-pull-request@f9f80aa5134bc5c03c38f5aaa95053492885b397 uses: https://github.com/KiaraGrouwstra/gitea-create-pull-request@f9f80aa5134bc5c03c38f5aaa95053492885b397
with: with:

View file

@ -146,9 +146,8 @@ details as to what they are for. As an overview:
- [`keys/`](./keys) contains the public keys of the contributors to this project - [`keys/`](./keys) contains the public keys of the contributors to this project
as well as the systems that we administrate. as well as the systems that we administrate.
- [`machines/`](./machines) contains the code of our machines for internal infra and test VMs. - [`matrix/`](./matrix) contains everything having to do with setting up a
fully-featured Matrix server.
- [`panel/`](./panel) contains the code of our front-end.
- [`secrets/`](./secrets) contains the secrets that need to get injected into - [`secrets/`](./secrets) contains the secrets that need to get injected into
machine configurations. machine configurations.

View file

@ -11,8 +11,7 @@ let
; ;
inherit (pkgs) lib; inherit (pkgs) lib;
inherit (import sources.flake-inputs) import-flake; inherit (import sources.flake-inputs) import-flake;
inputs = (import-flake { src = ./.; }).inputs; inherit ((import-flake { src = ./.; }).inputs) nixops4;
inherit (inputs) nixops4;
panel = import ./panel { inherit sources system; }; panel = import ./panel { inherit sources system; };
pre-commit-check = pre-commit-check =
(import "${git-hooks}/nix" { (import "${git-hooks}/nix" {
@ -65,7 +64,6 @@ in
pkgs.openssh pkgs.openssh
pkgs.httpie pkgs.httpie
pkgs.jq pkgs.jq
pkgs.diffutils
pkgs.nix-unit pkgs.nix-unit
test-loop test-loop
nixops4.packages.${system}.default nixops4.packages.${system}.default
@ -80,7 +78,6 @@ in
# re-export inputs so they can be overridden granularly # re-export inputs so they can be overridden granularly
# (they can't be accessed from the outside any other way) # (they can't be accessed from the outside any other way)
inherit inherit
inputs
sources sources
system system
pkgs pkgs

View file

@ -5,5 +5,4 @@
]; ];
pathToRoot = ../../..; pathToRoot = ../../..;
pathFromRoot = ./.; pathFromRoot = ./.;
useFlake = true;
} }

View file

@ -10,10 +10,5 @@ runNixOSTest {
./nixosTest.nix ./nixosTest.nix
]; ];
_module.args = { inherit inputs sources; }; _module.args = { inherit inputs sources; };
inherit (import ./constants.nix) inherit (import ./constants.nix) targetMachines pathToRoot pathFromRoot;
targetMachines
pathToRoot
pathFromRoot
useFlake
;
} }

View file

@ -1,9 +1,4 @@
{ { inputs, lib, ... }:
inputs,
lib,
config,
...
}:
{ {
_class = "nixosTest"; _class = "nixosTest";
@ -13,7 +8,6 @@
sourceFileset = lib.fileset.unions [ sourceFileset = lib.fileset.unions [
./constants.nix ./constants.nix
./deployment.nix ./deployment.nix
(config.pathToCwd + "/flake-under-test.nix")
]; ];
nodes.deployer = nodes.deployer =

View file

@ -8,5 +8,4 @@
pathToRoot = ../../..; pathToRoot = ../../..;
pathFromRoot = ./.; pathFromRoot = ./.;
enableAcme = true; enableAcme = true;
useFlake = true;
} }

View file

@ -15,6 +15,5 @@ runNixOSTest {
pathToRoot pathToRoot
pathFromRoot pathFromRoot
enableAcme enableAcme
useFlake
; ;
} }

View file

@ -1,7 +1,6 @@
{ {
inputs, inputs,
hostPkgs, hostPkgs,
config,
lib, lib,
... ...
}: }:
@ -20,7 +19,6 @@ in
sourceFileset = lib.fileset.unions [ sourceFileset = lib.fileset.unions [
./constants.nix ./constants.nix
./deployments.nix ./deployments.nix
(config.pathToCwd + "/flake-under-test.nix")
# REVIEW: I would like to be able to grab all of `/deployment` minus # REVIEW: I would like to be able to grab all of `/deployment` minus
# `/deployment/check`, but I can't because there is a bunch of other files # `/deployment/check`, but I can't because there is a bunch of other files

View file

@ -1,25 +0,0 @@
{
lib,
...
}:
let
inherit (lib) mkOption types;
in
{
options = {
host = mkOption {
type = types.str;
description = "name of the host to deploy to";
};
targetSystem = mkOption {
type = types.str;
description = "name of the host to deploy to";
};
sshOpts = mkOption {
description = "Extra SSH options (`-o`) to use.";
type = types.listOf types.str;
default = [ ];
example = "ConnectTimeout=60";
};
};
}

View file

@ -1,256 +0,0 @@
{
config,
system,
inputs ? (import ../../../default.nix { }).inputs, # XXX can't be serialized
sources ? import ../../../npins,
...
}@args:
let
# having this module's location (`self`) and (serializable) `args`, we know
# enough to make it re-call itself to extract different info elsewhere later.
# we use this to make a deployment script using the desired nixos config,
# which would otherwise not be serializable, while nix also makes it hard to
# produce its derivation to pass thru without a `nix-instantiate` call,
# which in turn would need to be passed the (unserializable) nixos config.
self = "deployment/check/common/data-model.nix";
inherit (sources) nixpkgs;
pkgs = import nixpkgs { inherit system; };
inherit (pkgs) lib;
deployment-config = config;
inherit (deployment-config)
nodeName
pathToRoot
targetSystem
sshOpts
;
inherit (lib) mkOption types;
eval =
module:
(lib.evalModules {
specialArgs = {
inherit pkgs inputs;
};
modules = [
module
../../data-model.nix
];
}).config;
fediversity = eval (
{ config, ... }:
{
config = {
resources.login-shell = {
description = "The operator needs to be able to log into the shell";
request =
{ ... }:
{
_class = "fediversity-resource-request";
options = {
wheel = mkOption {
description = "Whether the login user needs root permissions";
type = types.bool;
default = false;
};
packages = mkOption {
description = "Packages that need to be available in the user environment";
type = with types; attrsOf package;
};
};
};
policy =
{ config, ... }:
{
_class = "fediversity-resource-policy";
options = {
username = mkOption {
description = "Username for the operator";
type = types.str; # TODO: use the proper constraints from NixOS
};
wheel = mkOption {
description = "Whether to allow login with root permissions";
type = types.bool;
default = false;
};
};
config = {
resource-type = types.raw; # TODO: splice out the user type from NixOS
apply =
requests:
let
# Filter out requests that need wheel if policy doesn't allow it
validRequests = lib.filterAttrs (
_name: req: !req.login-shell.wheel || config.wheel
) requests.resources;
in
lib.optionalAttrs (validRequests != { }) {
${config.username} = {
isNormalUser = true;
packages =
with lib;
attrValues (concatMapAttrs (_name: request: request.login-shell.packages) validRequests);
extraGroups = lib.optional config.wheel "wheel";
};
};
};
};
};
applications.hello =
{ ... }:
{
description = ''Command-line tool that will print "Hello, world!" on the terminal'';
module =
{ ... }:
{
options.enable = lib.mkEnableOption "Hello in the shell";
};
implementation = cfg: {
resources = lib.optionalAttrs cfg.enable {
hello.login-shell.packages.hello = pkgs.hello;
};
};
};
environments =
let
mkNixosConfiguration =
environment: requests:
{ ... }:
{
imports = [
./data-model-options.nix
../common/sharedOptions.nix
../common/targetNode.nix
"${nixpkgs}/nixos/modules/profiles/qemu-guest.nix"
];
users.users = environment.config.resources."operator-environment".login-shell.apply {
resources = lib.filterAttrs (_name: value: value ? login-shell) (
lib.concatMapAttrs (
k': req: lib.mapAttrs' (k: lib.nameValuePair "${k'}.${k}") req.resources
) requests
);
};
};
in
{
single-nixos-vm-ssh = environment: {
resources."operator-environment".login-shell.username = "operator";
implementation =
{
required-resources,
deployment-name,
}:
{
ssh-host = {
nixos-configuration = mkNixosConfiguration environment required-resources;
system = targetSystem;
ssh = {
username = "root";
host = nodeName;
key-file = null;
inherit sshOpts;
};
module = self;
inherit args deployment-name;
root-path = pathToRoot;
};
};
};
single-nixos-vm-nixops4 = environment: {
resources."operator-environment".login-shell.username = "operator";
implementation =
{
required-resources,
...
}:
{
nixops4 =
{ providers, ... }:
{
providers = {
inherit (inputs.nixops4.modules.nixops4Provider) local;
};
resources.${nodeName} = {
type = providers.local.exec;
imports = [
inputs.nixops4-nixos.modules.nixops4Resource.nixos
../common/targetResource.nix
];
nixos.module = mkNixosConfiguration environment required-resources;
_module.args = { inherit inputs sources; };
inherit (deployment-config) nodeName pathToRoot pathFromRoot;
};
};
};
};
single-nixos-vm-tf = environment: {
resources."operator-environment".login-shell.username = "operator";
implementation =
{
required-resources,
deployment-name,
}:
{
tf-host = {
nixos-configuration = mkNixosConfiguration environment required-resources;
system = targetSystem;
ssh = {
username = "root";
host = nodeName;
key-file = null;
inherit sshOpts;
};
module = self;
inherit args deployment-name;
root-path = pathToRoot;
};
};
};
};
};
options = {
"example-configuration" = mkOption {
type = config.configuration;
default = {
enable = true;
applications.hello.enable = true;
};
};
"ssh-deployment" =
let
env = config.environments."single-nixos-vm-ssh";
in
mkOption {
type = env.resource-mapping.output-type;
default = env.deployment {
deployment-name = "ssh-deployment";
configuration = config."example-configuration";
};
};
"nixops4-deployment" =
let
env = config.environments."single-nixos-vm-nixops4";
in
mkOption {
type = env.resource-mapping.output-type;
default = env.deployment {
deployment-name = "nixops4-deployment";
configuration = config."example-configuration";
};
};
"tf-deployment" =
let
env = config.environments."single-nixos-vm-tf";
in
mkOption {
type = env.resource-mapping.output-type;
default = env.deployment {
deployment-name = "tf-deployment";
configuration = config."example-configuration";
};
};
};
}
);
in
fediversity

View file

@ -59,7 +59,6 @@ in
inputs.nixpkgs inputs.nixpkgs
sources.flake-parts sources.flake-parts
sources.nixpkgs
sources.flake-inputs sources.flake-inputs
sources.git-hooks sources.git-hooks

View file

@ -48,8 +48,7 @@ in
extraTestScript = mkOption { }; extraTestScript = mkOption { };
sourceFileset = mkOption { sourceFileset = mkOption {
## FIXME: grab `lib.types.fileset` from NixOS, once upstreaming PR ## REVIEW: Upstream to nixpkgs?
## https://github.com/NixOS/nixpkgs/pull/428293 lands.
type = types.mkOptionType { type = types.mkOptionType {
name = "fileset"; name = "fileset";
description = "fileset"; description = "fileset";
@ -76,6 +75,8 @@ in
./sharedOptions.nix ./sharedOptions.nix
./targetNode.nix ./targetNode.nix
./targetResource.nix ./targetResource.nix
(config.pathToCwd + "/flake-under-test.nix")
]; ];
acmeNodeIP = config.nodes.acme.networking.primaryIPAddress; acmeNodeIP = config.nodes.acme.networking.primaryIPAddress;
@ -162,9 +163,6 @@ in
deployer.succeed(f"echo '{host_key}' > ${config.pathFromRoot}/${tm}_host_key.pub") deployer.succeed(f"echo '{host_key}' > ${config.pathFromRoot}/${tm}_host_key.pub")
'')} '')}
${
if config.useFlake then
''
## NOTE: This is super slow. It could probably be optimised in Nix, for ## NOTE: This is super slow. It could probably be optimised in Nix, for
## instance by allowing to grab things directly from the host's store. ## instance by allowing to grab things directly from the host's store.
## ##
@ -190,10 +188,6 @@ in
--override-input nixops4-nixos/git-hooks-nix ${emptyFlake} \ --override-input nixops4-nixos/git-hooks-nix ${emptyFlake} \
; ;
""") """)
''
else
""
}
${optionalString config.enableAcme '' ${optionalString config.enableAcme ''
with subtest("Set up handmade DNS"): with subtest("Set up handmade DNS"):

View file

@ -32,11 +32,11 @@ in
}; };
pathFromRoot = mkOption { pathFromRoot = mkOption {
type = types.either types.path types.str; type = types.path;
description = '' description = ''
Path from the root of the repository to the working directory. Path from the root of the repository to the working directory.
''; '';
apply = x: if lib.isString x then x else lib.path.removePrefix config.pathToRoot x; apply = x: lib.path.removePrefix config.pathToRoot x;
}; };
pathToCwd = mkOption { pathToCwd = mkOption {
@ -64,7 +64,5 @@ in
during the test to the correct value. during the test to the correct value.
''; '';
}; };
useFlake = lib.mkEnableOption "Use a flake in the test.";
}; };
} }

View file

@ -28,8 +28,6 @@ in
system.switch.enable = true; system.switch.enable = true;
nix = { nix = {
# short-cut network time-outs
settings.download-attempts = 1;
## Not used; save a large copy operation ## Not used; save a large copy operation
channel.enable = false; channel.enable = false;
registry = lib.mkForce { }; registry = lib.mkForce { };

View file

@ -1,9 +0,0 @@
{
targetMachines = [
"nixops4"
];
pathToRoot = ../../..;
pathFromRoot = ./.;
enableAcme = true;
useFlake = true;
}

View file

@ -1,22 +0,0 @@
{
runNixOSTest,
inputs,
sources,
}:
runNixOSTest {
imports = [
../../data-model.nix
../../function.nix
../common/nixosTest.nix
./nixosTest.nix
];
_module.args = { inherit inputs sources; };
inherit (import ./constants.nix)
targetMachines
pathToRoot
pathFromRoot
enableAcme
useFlake
;
}

View file

@ -1,29 +0,0 @@
{
inputs = {
nixops4.follows = "nixops4-nixos/nixops4";
nixops4-nixos.url = "github:nixops4/nixops4-nixos";
};
outputs =
inputs:
import ./mkFlake.nix inputs (
{ inputs, ... }:
let
system = "x86_64-linux";
in
{
imports = [
inputs.nixops4.modules.flake.default
];
nixops4Deployments.check-deployment-model =
(import ./deployment/check/common/data-model.nix {
inherit system inputs;
config = {
inherit (import ./deployment/check/data-model-nixops4/constants.nix) pathToRoot pathFromRoot;
nodeName = "nixops4";
};
})."nixops4-deployment".nixops4;
}
);
}

View file

@ -1,52 +0,0 @@
{
lib,
config,
inputs,
...
}:
{
_class = "nixosTest";
imports = [
../common/data-model-options.nix
];
name = "deployment-model";
sourceFileset = lib.fileset.unions [
../../data-model.nix
../../function.nix
../common/data-model.nix
../common/data-model-options.nix
./constants.nix
(config.pathToCwd + "/flake-under-test.nix")
];
nodes.deployer =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
inputs.nixops4.packages.${system}.default
jq
];
# FIXME: sad times
system.extraDependencies = with pkgs; [
jq
jq.inputDerivation
];
system.extraDependenciesFromModule =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
hello
];
};
};
extraTestScript = ''
with subtest("nixops4"):
nixops4.fail("hello 1>&2")
deployer.succeed("nixops4 apply check-deployment-model --show-trace --verbose --no-interactive 1>&2")
nixops4.succeed("su - operator -c hello 1>&2")
'';
}

View file

@ -1,12 +0,0 @@
{
targetMachines = [
"ssh"
];
# stablize path, as just the path would yield distinct paths when applied multiple times
pathToRoot = builtins.path {
path = ../../..;
name = "root";
};
pathFromRoot = "/deployment/check/data-model-ssh";
enableAcme = true;
}

View file

@ -1,21 +0,0 @@
{
runNixOSTest,
inputs,
sources,
}:
runNixOSTest {
imports = [
../../data-model.nix
../../function.nix
../common/nixosTest.nix
./nixosTest.nix
];
_module.args = { inherit inputs sources; };
inherit (import ./constants.nix)
targetMachines
pathToRoot
pathFromRoot
enableAcme
;
}

View file

@ -1,68 +0,0 @@
{
lib,
pkgs,
...
}:
let
inherit (import ./constants.nix) pathToRoot pathFromRoot;
inherit (pkgs) system;
deployment-config = {
inherit pathToRoot pathFromRoot;
nodeName = "ssh";
targetSystem = system;
sshOpts = [ ];
};
deploy =
(import ../common/data-model.nix {
inherit system;
config = deployment-config;
# opt not to pass `inputs`, as we could only pass serializable arguments through to its self-call
})."ssh-deployment".ssh-host.run;
in
{
_class = "nixosTest";
imports = [
../common/data-model-options.nix
];
name = "deployment-model";
sourceFileset = lib.fileset.unions [
../../data-model.nix
../../function.nix
../../nixos.nix
../../run/ssh-single-host/run.sh
../../../npins/default.nix
../../../npins/sources.json
../common/data-model.nix
../common/data-model-options.nix
./constants.nix
];
nodes.deployer =
{ ... }:
{
environment.systemPackages = [
deploy
];
system.extraDependenciesFromModule =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
hello
];
};
};
extraTestScript = ''
with subtest("Check the status before deployment"):
ssh.fail("hello 1>&2")
with subtest("Run the deployment"):
deployer.succeed("""
${lib.getExe deploy}
""")
ssh.wait_for_unit("multi-user.target")
ssh.succeed("su - operator -c hello 1>&2")
'';
}

View file

@ -1,11 +0,0 @@
{
targetMachines = [
"target"
];
pathToRoot = builtins.path {
path = ../../..;
name = "root";
};
pathFromRoot = "/deployment/check/data-model-tf";
enableAcme = true;
}

View file

@ -1,21 +0,0 @@
{
runNixOSTest,
inputs,
sources,
}:
runNixOSTest {
imports = [
../../data-model.nix
../../function.nix
../common/nixosTest.nix
./nixosTest.nix
];
_module.args = { inherit inputs sources; };
inherit (import ./constants.nix)
targetMachines
pathToRoot
pathFromRoot
enableAcme
;
}

View file

@ -1,61 +0,0 @@
{
lib,
pkgs,
...
}:
let
inherit (import ./constants.nix) pathToRoot pathFromRoot;
inherit (pkgs) system;
deployment-config = {
inherit pathToRoot pathFromRoot;
nodeName = "target";
targetSystem = system;
sshOpts = [ ];
};
deploy =
(import ../common/data-model.nix {
inherit system;
config = deployment-config;
# opt not to pass `inputs`, as we could only pass serializable arguments through to its self-call
})."tf-deployment".tf-host.run;
in
{
_class = "nixosTest";
imports = [
../common/data-model-options.nix
];
name = "deployment-model";
sourceFileset = lib.fileset.unions [
../../run/tf-single-host/run.sh
];
nodes.deployer =
{ ... }:
{
environment.systemPackages = [
deploy
];
# needed only when building from deployer
system.extraDependenciesFromModule =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
hello
];
};
};
extraTestScript = ''
with subtest("Check the status before deployment"):
target.fail("hello 1>&2")
with subtest("Run the deployment"):
deployer.succeed("""
${lib.getExe deploy}
""")
target.wait_for_unit("multi-user.target")
target.succeed("su - operator -c hello 1>&2")
'';
}

View file

@ -8,5 +8,4 @@
pathToRoot = ../../..; pathToRoot = ../../..;
pathFromRoot = ./.; pathFromRoot = ./.;
enableAcme = true; enableAcme = true;
useFlake = true;
} }

View file

@ -15,6 +15,5 @@ runNixOSTest {
pathToRoot pathToRoot
pathFromRoot pathFromRoot
enableAcme enableAcme
useFlake
; ;
} }

View file

@ -128,7 +128,6 @@ in
sourceFileset = lib.fileset.unions [ sourceFileset = lib.fileset.unions [
./constants.nix ./constants.nix
./deployment.nix ./deployment.nix
(config.pathToCwd + "/flake-under-test.nix")
# REVIEW: I would like to be able to grab all of `/deployment` minus # REVIEW: I would like to be able to grab all of `/deployment` minus
# `/deployment/check`, but I can't because there is a bunch of other files # `/deployment/check`, but I can't because there is a bunch of other files

View file

@ -1,37 +0,0 @@
{
runNixOSTest,
sources,
system,
}:
let
pkgs = import sources.nixpkgs-stable {
inherit system;
overlays = [ overlay ];
};
overlay = _: _: {
inherit
(import "${sources.proxmox-nixos}/pkgs" {
craneLib = pkgs.callPackage "${sources.crane}/lib" { };
# breaks from https://github.com/NixOS/nixpkgs/commit/06b354eb2dc535c57e9b4caaa16d79168f117a26,
# which updates libvncserver to 0.9.15, which was not yet patched at https://git.proxmox.com/?p=vncterm.git.
inherit pkgs;
# not so picky about version for our purposes
pkgs-unstable = pkgs;
})
proxmox-ve
pve-ha-manager
;
};
in
runNixOSTest {
node.specialArgs = {
inherit
sources
pkgs
;
};
imports = [
./proxmoxTest.nix
];
}

View file

@ -1,87 +0,0 @@
# https://github.com/SaumonNet/proxmox-nixos/blob/main/tests/vm.nix
{
pkgs,
...
}:
let
# tracking non-tarball downloads seems unsupported still in npins:
# https://github.com/andir/npins/issues/163
minimalIso = pkgs.fetchurl {
url = "https://releases.nixos.org/nixos/24.05/nixos-24.05.7139.bcba2fbf6963/nixos-minimal-24.05.7139.bcba2fbf6963-x86_64-linux.iso";
hash = "sha256-plre/mIHdIgU4xWU+9xErP+L4i460ZbcKq8iy2n4HT8=";
};
in
{
name = "proxmox-basic";
nodes.mypve =
{ sources, ... }:
{
imports = [
"${sources.proxmox-nixos}/modules/proxmox-ve"
];
services.proxmox-ve = {
enable = true;
ipAddress = "192.168.1.1";
vms = {
myvm1 = {
vmid = 100;
memory = 1024;
cores = 1;
sockets = 1;
kvm = true;
scsi = [ { file = "local:16"; } ];
cdrom = "local:iso/minimal.iso";
};
};
};
virtualisation = {
additionalPaths = [ minimalIso ];
diskSize = 4096;
memorySize = 2048;
};
};
testScript = ''
machine.start()
machine.wait_for_unit("pveproxy.service")
assert "running" in machine.succeed("pveproxy status")
# Copy Iso
machine.succeed("mkdir -p /var/lib/vz/template/iso/")
machine.succeed("cp ${minimalIso} /var/lib/vz/template/iso/minimal.iso")
# Declarative VM creation
machine.wait_for_unit("multi-user.target")
machine.succeed("qm stop 100 --timeout 0")
# Seabios VM creation
machine.succeed(
"qm create 101 --kvm 0 --bios seabios -cdrom local:iso/minimal.iso",
"qm start 101",
"qm stop 101 --timeout 0"
)
# Legacy ovmf vm creation
machine.succeed(
"qm create 102 --kvm 0 --bios ovmf -cdrom local:iso/minimal.iso",
"qm start 102",
"qm stop 102 --timeout 0"
)
# UEFI ovmf vm creation
machine.succeed(
"qm create 103 --kvm 0 --bios ovmf --efidisk0 local:4,efitype=4m -cdrom local:iso/minimal.iso",
"qm start 103",
"qm stop 103 --timeout 0"
)
# UEFI ovmf vm creation with secure boot
machine.succeed(
"qm create 104 --kvm 0 --bios ovmf --efidisk0 local:4,efitype=4m,pre-enrolled-keys=1 -cdrom local:iso/minimal.iso",
"qm start 104",
"qm stop 104 --timeout 0"
)
'';
}

View file

@ -1,94 +1,29 @@
let let
inherit (import ../default.nix { }) pkgs inputs; inherit (import ../default.nix { }) pkgs inputs;
inherit (pkgs) lib; inherit (pkgs) lib;
inherit (lib) mkOption types; inherit (lib) mkOption;
eval = eval =
module: module:
(lib.evalModules { (lib.evalModules {
specialArgs = { specialArgs = {
inherit pkgs inputs; inherit inputs;
}; };
modules = [ modules = [
module module
./data-model.nix ./data-model.nix
]; ];
}).config; }).config;
inherit (inputs.nixops4.lib) mkDeployment;
in in
{ {
_class = "nix-unit"; _class = "nix-unit";
test-eval = { test-eval = {
/**
This tests a very simple arrangement that features all ingredients of the Fediversity business logic:
application, resource, environment, deployment; and wires it all up in one end-to-end exercise.
- The dummy resource is a login shell made available for some user.
- The dummy application is `hello` that requires a shell to be deployed.
- The dummy environment is a single NixOS VM that hosts one login shell, for the operator.
- The dummy configuration enables the `hello` application.
This will produce a NixOps4 deployment for a NixOS VM with a login shell for the operator and `hello` available.
*/
expr = expr =
let let
fediversity = eval ( fediversity = eval (
{ config, ... }: { config, ... }:
{ {
config = { config = {
resources.login-shell = {
description = "The operator needs to be able to log into the shell";
request =
{ ... }:
{
_class = "fediversity-resource-request";
options = {
wheel = mkOption {
description = "Whether the login user needs root permissions";
type = types.bool;
default = false;
};
packages = mkOption {
description = "Packages that need to be available in the user environment";
type = with types; attrsOf package;
};
};
};
policy =
{ config, ... }:
{
_class = "fediversity-resource-policy";
options = {
username = mkOption {
description = "Username for the operator";
type = types.str; # TODO: use the proper constraints from NixOS
};
wheel = mkOption {
description = "Whether to allow login with root permissions";
type = types.bool;
default = false;
};
};
config = {
resource-type = types.raw; # TODO: splice out the user type from NixOS
apply =
requests:
let
# Filter out requests that need wheel if policy doesn't allow it
validRequests = lib.filterAttrs (
_name: req: !req.login-shell.wheel || config.wheel
) requests.resources;
in
lib.optionalAttrs (validRequests != { }) {
${config.username} = {
isNormalUser = true;
packages =
with lib;
attrValues (concatMapAttrs (_name: request: request.login-shell.packages) validRequests);
extraGroups = lib.optional config.wheel "wheel";
};
};
};
};
};
applications.hello = applications.hello =
{ ... }: { ... }:
{ {
@ -96,49 +31,19 @@ in
module = module =
{ ... }: { ... }:
{ {
options.enable = lib.mkEnableOption "Hello in the shell"; options = {
}; enable = lib.mkEnableOption "Hello in the shell";
implementation = cfg: {
resources = lib.optionalAttrs cfg.enable {
hello.login-shell.packages.hello = pkgs.hello;
}; };
}; };
}; implementation =
environments.single-nixos-vm = cfg:
{ config, ... }: lib.optionalAttrs cfg.enable {
{ dummy.login-shell.packages.hello = pkgs.hello;
resources."operator-environment".login-shell.username = "operator";
implementation = requests: {
nixops4 = (
{ providers, ... }:
{
providers = {
inherit (inputs.nixops4.modules.nixops4Provider) local;
};
resources.the-machine = {
type = providers.local.exec;
imports = [
inputs.nixops4-nixos.modules.nixops4Resource.nixos
];
nixos.module =
{ ... }:
{
users.users = config.resources."operator-environment".login-shell.apply {
resources = lib.filterAttrs (_name: value: value ? login-shell) (
lib.concatMapAttrs (
k': req: lib.mapAttrs' (k: lib.nameValuePair "${k'}.${k}") req.resources
) requests
);
};
};
};
}
);
}; };
}; };
}; };
options = { options = {
"example-configuration" = mkOption { example-configuration = mkOption {
type = config.configuration; type = config.configuration;
readOnly = true; readOnly = true;
default = { default = {
@ -146,66 +51,20 @@ in
applications.hello.enable = true; applications.hello.enable = true;
}; };
}; };
"example-deployment" = mkOption {
type = config.environments.single-nixos-vm.resource-mapping.output-type;
readOnly = true;
default = config.environments.single-nixos-vm.deployment config."example-configuration";
};
}; };
} }
); );
resources =
fediversity.applications.hello.resources
fediversity."example-configuration".applications.hello;
hello-shell = resources.resources.hello.login-shell;
environment = fediversity.environments.single-nixos-vm.resources."operator-environment".login-shell;
result = mkDeployment {
modules = [
(fediversity.environments.single-nixos-vm.deployment fediversity."example-configuration")
];
};
in in
{ {
number-of-resources = with lib; length (attrNames fediversity.resources); inherit (fediversity)
inherit (fediversity) example-configuration; example-configuration
hello-package-exists = hello-shell.packages ? hello; ;
wheel-required = hello-shell.wheel;
wheel-allowed = environment.wheel;
operator-shell =
let
operator = (environment.apply resources).operator;
in
{
inherit (operator) isNormalUser;
packages = map (p: "${p.pname}") operator.packages;
extraGroups = operator.extraGroups;
};
deployment = {
inherit (result) _type;
deploymentFunction = lib.isFunction result.deploymentFunction;
getProviders = lib.isFunction result.getProviders;
};
}; };
expected = { expected = {
number-of-resources = 1;
example-configuration = { example-configuration = {
enable = true; enable = true;
applications.hello.enable = true; applications.hello.enable = true;
}; };
hello-package-exists = true;
wheel-required = false;
wheel-allowed = false;
operator-shell = {
isNormalUser = true;
packages = [ "hello" ];
extraGroups = [ ];
};
deployment = {
_type = "nixops4Deployment";
deploymentFunction = true;
getProviders = true;
};
}; };
}; };
} }

View file

@ -1,303 +1,33 @@
{ {
lib, lib,
config, config,
inputs,
pkgs,
sources ? import ../npins,
... ...
}: }:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (lib.types) inherit (lib.types)
attrTag
attrsOf attrsOf
attrTag
deferredModuleWith deferredModuleWith
functionTo
nullOr
optionType
raw
str
submodule submodule
optionType
functionTo
; ;
toBash =
v:
lib.replaceStrings [ "\"" ] [ "\\\"" ] (
if lib.isPath v || builtins.isNull v then
toString v
else if lib.isString v then
v
else
lib.strings.toJSON v
);
functionType = submodule ./function.nix; functionType = import ./function.nix;
application-resources = submodule { application-resources = {
options.resources = mkOption { options.resources = mkOption {
# TODO: maybe transpose, and group the resources by type instead # TODO: maybe transpose, and group the resources by type instead
type = attrsOf ( type = attrsOf (
attrTag ( attrTag (lib.mapAttrs (_name: resource: mkOption { type = resource.request; }) config.resources)
lib.mapAttrs (_name: resource: mkOption { type = submodule resource.request; }) config.resources
)
); );
}; };
}; };
nixops4Deployment = types.deferredModuleWith { in
staticModules = [
inputs.nixops4.modules.nixops4Deployment.default
{ {
_class = "nixops4Deployment"; _class = "nixops4Deployment";
_module.args = {
resourceProviderSystem = pkgs.system;
resources = { };
};
}
];
};
nixos-configuration = mkOption {
description = "A NixOS configuration.";
type = raw;
};
host-ssh = mkOption {
description = "SSH connection info to connect to a single host.";
type = submodule {
options = { options = {
host = mkOption {
description = "the host to access by SSH";
type = str;
};
username = mkOption {
description = "the SSH user to use";
type = nullOr str;
default = null;
};
key-file = mkOption {
description = "path to the user's SSH private key";
type = nullOr str;
example = "/root/.ssh/id_ed25519";
};
sshOpts = mkOption {
description = "Extra SSH options (`-o`) to use.";
type = types.listOf str;
default = [ ];
example = "ConnectTimeout=60";
};
};
};
};
deployment-type = attrTag {
ssh-host = mkOption {
description = "A deployment by SSH to update a single existing NixOS host.";
type = submodule (ssh-host: {
options = {
system = mkOption {
description = "The architecture of the system to deploy to.";
type = types.str;
};
inherit nixos-configuration;
ssh = host-ssh;
module = mkOption {
description = "The module to call to obtain the NixOS configuration from.";
type = types.str;
};
args = mkOption {
description = "The arguments with which to call the module to obtain the NixOS configuration.";
type = types.attrs;
};
deployment-name = mkOption {
description = "The name of the deployment for which to obtain the NixOS configuration.";
type = types.str;
};
root-path = mkOption {
description = "The path to the root of the repository.";
type = types.path;
};
run = mkOption {
type = types.package;
# error: The option `ssh-deployment.ssh-host.run' is read-only, but it's set multiple times.
# readOnly = true;
default =
let
inherit (ssh-host.config)
system
ssh
module
args
deployment-name
root-path
;
inherit (ssh)
host
username
key-file
sshOpts
;
environment = {
key_file = key-file;
deployment_name = deployment-name;
root_path = root-path;
ssh_opts = sshOpts;
inherit
system
host
username
module
args
;
deployment_type = "ssh-host";
};
in
pkgs.writers.writeBashBin "deploy-sh.sh"
{
makeWrapperArgs = [
"--prefix"
"PATH"
":"
"${lib.makeBinPath [
pkgs.jq
]}"
];
}
''
env ${
toString (lib.mapAttrsToList (k: v: "${k}=\"${toBash v}\"") environment)
} bash ./deployment/run/ssh-single-host/run.sh
'';
};
};
});
};
nixops4 = mkOption {
description = "A NixOps4 NixOS deployment. For an example, see https://github.com/nixops4/nixops4-nixos/blob/main/example/deployment.nix.";
type = nixops4Deployment;
};
tf-host = mkOption {
description = "A Terraform deployment by SSH to update a single existing NixOS host.";
type = submodule (tf-host: {
options = {
system = mkOption {
description = "The architecture of the system to deploy to.";
type = types.str;
};
inherit nixos-configuration;
ssh = host-ssh;
module = mkOption {
description = "The module to call to obtain the NixOS configuration from.";
type = types.str;
};
args = mkOption {
description = "The arguments with which to call the module to obtain the NixOS configuration.";
type = types.attrs;
};
deployment-name = mkOption {
description = "The name of the deployment for which to obtain the NixOS configuration.";
type = types.str;
};
root-path = mkOption {
description = "The path to the root of the repository.";
type = types.path;
};
run = mkOption {
type = types.package;
# error: The option `tf-deployment.tf-host.run' is read-only, but it's set multiple times.
# readOnly = true;
default =
let
inherit (tf-host.config)
system
ssh
module
args
deployment-name
root-path
;
inherit (ssh)
host
username
key-file
sshOpts
;
environment = {
key_file = key-file;
deployment_name = deployment-name;
root_path = root-path;
ssh_opts = sshOpts;
inherit
system
host
username
module
args
;
deployment_type = "tf-host";
};
tf-env = pkgs.callPackage ./run/tf-single-host/tf-env.nix { };
in
pkgs.writers.writeBashBin "deploy-tf.sh"
{
makeWrapperArgs = [
"--prefix"
"PATH"
":"
"${lib.makeBinPath [
pkgs.jq
(pkgs.callPackage ./run/tf-single-host/tf.nix { inherit sources; })
]}"
];
}
''
env ${toString (lib.mapAttrsToList (k: v: "TF_VAR_${k}=\"${toBash v}\"") environment)} \
tf_env=${tf-env} bash ./deployment/run/tf-single-host/run.sh
'';
};
};
});
};
};
in
{
options = {
resources = mkOption {
description = "Collection of deployment resources that can be required by applications and policed by hosting providers";
type = attrsOf (
submodule (
{ ... }:
{
_class = "fediversity-resource";
options = {
description = mkOption {
description = "Description of the resource to help application module authors and hosting providers to work with it";
type = types.str;
};
request = mkOption {
description = "Options for declaring resource requirements by an application, a description of how the resource is consumed or accessed";
type = deferredModuleWith { staticModules = [ { _class = "fediversity-resource-request"; } ]; };
};
policy = mkOption {
description = "Options for configuring the resource policy for the hosting provider, a description of how the resource is made available";
type = deferredModuleWith {
staticModules = [
(policy: {
_class = "fediversity-resource-policy";
options.resource-type = mkOption {
description = "The type of resource this policy configures";
type = types.optionType;
};
# TODO(@fricklerhandwerk): we may want to make the function type explicit here: `application-resources -> resource-type`
# and then also rename this to be consistent with the application's resource mapping
options.apply = mkOption {
description = "Apply the policy to a request";
type = functionTo policy.config.resource-type;
};
})
];
};
};
};
}
)
);
};
applications = mkOption { applications = mkOption {
description = "Collection of Fediversity applications"; description = "Collection of Fediversity applications";
type = attrsOf ( type = attrsOf (
@ -318,110 +48,23 @@ in
}; };
resources = mkOption { resources = mkOption {
description = "Compute resources required by an application"; description = "Compute resources required by an application";
type = application.config.config-mapping.function-type; type = functionTo application.config.config-mapping.output-type;
readOnly = true; readOnly = true;
default = application.config.config-mapping.apply; default = input: (application.config.implementation input).output;
}; };
# TODO(@fricklerhandwerk): this needs a better name
config-mapping = mkOption { config-mapping = mkOption {
description = "Function type for the mapping from application configuration to required resources"; description = "Function type for the mapping from application configuration to required resources";
type = functionType; type = submodule functionType;
readOnly = true; readOnly = true;
default = { default = {
input-type = submodule application.config.module; input-type = application.config.module;
output-type = application-resources; output-type = application-resources;
implementation = application.config.implementation;
}; };
}; };
}; };
}) })
); );
}; };
environments = mkOption {
description = "Run-time environments for Fediversity applications to be deployed to";
type = attrsOf (
submodule (environment: {
_class = "fediversity-environment";
options = {
resources = mkOption {
description = ''
Resources made available by the hosting provider, and their policies.
Setting this is optional, but provides a place to declare that information for programmatic use in the resource mapping.
'';
# TODO: maybe transpose, and group the resources by type instead
type = attrsOf (
attrTag (
lib.mapAttrs (_name: resource: mkOption { type = submodule resource.policy; }) config.resources
)
);
};
implementation = mkOption {
description = "Mapping of resources required by applications to available resources; the result can be deployed";
type = environment.config.resource-mapping.function-type;
};
resource-mapping = mkOption {
description = "Function type for the mapping from resources to a deployment";
type = functionType;
readOnly = true;
default = {
input-type = submodule {
options = {
deployment-name = mkOption {
type = types.str;
};
required-resources = mkOption {
type = attrsOf application-resources;
};
};
};
output-type = deployment-type;
implementation = environment.config.implementation;
};
};
config-mapping = mkOption {
description = "Mapping from a configuration to a deployment";
type = functionType;
readOnly = true;
default = {
input-type = submodule {
options = {
deployment-name = mkOption {
type = types.str;
};
configuration = mkOption {
type = config.configuration;
};
};
};
output-type = deployment-type;
implementation =
{
deployment-name,
configuration,
}:
# TODO: check cfg.enable.true
let
required-resources = lib.mapAttrs (
name: application-settings: config.applications.${name}.resources application-settings
) configuration.applications;
in
environment.config.resource-mapping.apply { inherit required-resources deployment-name; };
};
};
# TODO(@fricklerhandwerk): maybe this should be a separate thing such as `fediversity-setup`,
# which makes explicit which applications and environments are available.
# then the deployments can simply be the result of the function application baked into this module.
deployment = mkOption {
description = "Generate a deployment from a configuration, by applying an environment's resource policies to the applications' resource mappings";
type = environment.config.config-mapping.function-type;
readOnly = true;
default = environment.config.config-mapping.apply;
};
};
})
);
};
configuration = mkOption { configuration = mkOption {
description = "Configuration type declaring options to be set by operators"; description = "Configuration type declaring options to be set by operators";
type = optionType; type = optionType;

View file

@ -4,14 +4,9 @@
_class = "flake"; _class = "flake";
perSystem = perSystem =
{ pkgs, system, ... }: { pkgs, ... }:
{ {
checks = { checks = {
proxmox-basic = import ./check/proxmox {
inherit (pkgs.testers) runNixOSTest;
inherit sources system;
};
deployment-basic = import ./check/basic { deployment-basic = import ./check/basic {
inherit (pkgs.testers) runNixOSTest; inherit (pkgs.testers) runNixOSTest;
inherit inputs sources; inherit inputs sources;
@ -26,21 +21,6 @@
inherit (pkgs.testers) runNixOSTest; inherit (pkgs.testers) runNixOSTest;
inherit inputs sources; inherit inputs sources;
}; };
deployment-model-ssh = import ./check/data-model-ssh {
inherit (pkgs.testers) runNixOSTest;
inherit inputs sources;
};
deployment-model-nixops4 = import ./check/data-model-nixops4 {
inherit (pkgs.testers) runNixOSTest;
inherit inputs sources;
};
deployment-model-tf = import ./check/data-model-tf {
inherit (pkgs.testers) runNixOSTest;
inherit inputs sources;
};
}; };
}; };
} }

View file

@ -5,6 +5,7 @@
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (types) inherit (types)
deferredModule
submodule submodule
functionTo functionTo
optionType optionType
@ -13,46 +14,24 @@ in
{ {
options = { options = {
input-type = mkOption { input-type = mkOption {
type = optionType; type = deferredModule;
}; };
output-type = mkOption { output-type = mkOption {
type = optionType; type = deferredModule;
}; };
function-type = mkOption { function-type = mkOption {
type = optionType;
readOnly = true;
default = functionTo config.output-type;
};
wrapper-type = mkOption {
type = optionType; type = optionType;
readOnly = true; readOnly = true;
default = functionTo (submodule { default = functionTo (submodule {
options = { options = {
input = mkOption { input = mkOption {
type = config.input-type; type = submodule config.input-type;
}; };
output = mkOption { output = mkOption {
type = config.output-type; type = submodule config.output-type;
}; };
}; };
}); });
}; };
implementation = mkOption {
type = config.function-type;
default = _: { };
};
wrapper = mkOption {
type = config.wrapper-type;
readOnly = true;
default = input: fn: {
inherit input;
output = config.implementation fn.config.input;
};
};
apply = mkOption {
type = config.function-type;
readOnly = true;
default = input: (config.wrapper input).output;
};
}; };
} }

View file

@ -1,25 +0,0 @@
{
configuration,
system,
sources ? import ../npins,
}:
let
eval = import "${sources.nixpkgs}/nixos/lib/eval-config.nix" {
inherit system;
specialArgs = {
inherit sources;
};
modules = [ configuration ];
};
toplevel =
{
inherit (eval) pkgs config options;
system = eval.config.system.build.toplevel;
inherit (eval.config.system.build) vm vmWithBootLoader;
}
.config.system.build.toplevel;
in
{
drv_path = toplevel.drvPath;
out_path = toplevel;
}

View file

@ -1,49 +0,0 @@
#! /usr/bin/env bash
set -xeuo pipefail
declare username host system module args deployment_name deployment_type key_file root_path ssh_opts
IFS=" " read -r -a ssh_opts <<< "$( (echo "$ssh_opts" | jq -r '@sh') | tr -d \'\")"
# DEPLOY
sshOpts=(
-o BatchMode=yes
-o StrictHostKeyChecking=no
)
for ssh_opt in "${ssh_opts[@]}"; do
sshOpts+=(
-o "$ssh_opt"
)
done
if [[ -n "$key_file" ]]; then
sshOpts+=(
-i "$key_file"
)
fi
destination="$username@$host"
command=(nix-instantiate --show-trace --expr "
import $root_path/deployment/nixos.nix {
system = \"$system\";
configuration = (import \"$root_path/$module\" (builtins.fromJSON ''$args'')).$deployment_name.$deployment_type.nixos-configuration;
}
")
# INSTANTIATE
# instantiate the config in /nix/store
"${command[@]}" -A out_path
# get the realized derivation to deploy
outPath=$(nix-store --realize "$("${command[@]}" --show-trace --eval --strict --json | jq -r '.drv_path')")
# deploy the config by nix-copy-closure
NIX_SSHOPTS="${sshOpts[*]}" nix-copy-closure --to "$destination" "$outPath" --gzip --use-substitutes
# switch the remote host to the config
# shellcheck disable=SC2029
ssh "${sshOpts[@]}" "$destination" "nix-env --profile /nix/var/nix/profiles/system --set $outPath"
# shellcheck disable=SC2029
output=$(ssh -o "ConnectTimeout=1" -o "ServerAliveInterval=1" "${sshOpts[@]}" "$destination" "nohup $outPath/bin/switch-to-configuration switch &" 2>&1) || echo "status code: $?"
echo "output: $output"
if [[ $output != *"Timeout, server $host not responding"* ]]; then
echo "non-timeout error: $output"
exit 1
else
exit 0
fi

View file

@ -1,52 +0,0 @@
# hash of our code directory, used to trigger re-deploy
# FIXME calculate separately to reduce false positives
data "external" "hash" {
program = ["sh", "-c", "echo \"{\\\"hash\\\":\\\"$(nix-hash ../../..)\\\"}\""]
}
# TF resource to build and deploy NixOS instances.
resource "terraform_data" "nixos" {
# trigger rebuild/deploy if (FIXME?) any potentially used config/code changed,
# preventing these (20+s, build being bottleneck) when nothing changed.
# terraform-nixos separates these to only deploy if instantiate changed,
# yet building even then - which may be not as bad using deploy on remote.
# having build/deploy one resource reflects wanting to prevent no-op rebuilds
# over preventing (with less false positives) no-op deployments,
# as i could not find a way to do prevent no-op rebuilds without merging them:
# - generic resources cannot have outputs, while we want info from the instantiation (unless built on host?).
# - `data` always runs, which is slow for deploy and especially build.
triggers_replace = [
data.external.hash.result,
var.host,
var.module,
var.args,
var.root_path,
var.deployment_type,
]
provisioner "local-exec" {
# directory to run the script from. we use the TF project root dir,
# here as a path relative from where TF is run from,
# matching calling modules' expectations on config_nix locations.
# note that absolute paths can cause false positives in triggers,
# so are generally discouraged in TF.
working_dir = path.root
environment = {
system = var.system
username = var.username
host = var.host
module = var.module
host = var.host
args = var.args
key_file = var.key_file
deployment_name = var.deployment_name
root_path = var.root_path
ssh_opts = var.ssh_opts
deployment_type = var.deployment_type
}
# TODO: refactor back to command="ignoreme" interpreter=concat([]) to protect sensitive data from error logs?
# TODO: build on target?
command = "sh ../ssh-single-host/run.sh"
}
}

View file

@ -1,9 +0,0 @@
#! /usr/bin/env bash
set -xeuo pipefail
declare tf_env
export TF_LOG=info
cd "${tf_env}/deployment/run/tf-single-host"
# parallelism=1: limit OOM risk
tofu apply --auto-approve -lock=false -parallelism=1

View file

@ -1,16 +0,0 @@
{
pkgs,
lib,
sources,
}:
pkgs.writeScriptBin "setup" ''
set -xe
# calculated pins
echo '${lib.strings.toJSON sources}' > ./.npins.json
# generate TF lock for nix's TF providers
rm -rf .terraform/
rm -f .terraform.lock.hcl
# suppress warning on architecture-specific generated lock file:
# `Warning: Incomplete lock file information for providers`.
tofu init -input=false 1>/dev/null
''

View file

@ -1,31 +0,0 @@
{
lib,
pkgs,
sources ? import ../../../npins,
}:
pkgs.stdenv.mkDerivation {
name = "tf-repo";
src =
with lib.fileset;
toSource {
root = ../../../.;
# don't copy ignored files
fileset = intersection (gitTracked ../../../.) ../../../.;
};
buildInputs = [
(pkgs.callPackage ./tf.nix { })
(pkgs.callPackage ./setup.nix { inherit sources; })
];
buildPhase = ''
runHook preBuild
pushd deployment/run/tf-single-host
source setup
popd
runHook postBuild
'';
installPhase = ''
runHook preInstall
cp -r . $out
runHook postInstall
'';
}

View file

@ -1,11 +0,0 @@
# FIXME: use overlays so this gets imported just once?
{
pkgs,
...
}:
let
tf = pkgs.opentofu;
in
tf.withPlugins (p: [
p.external
])

View file

@ -1,54 +0,0 @@
variable "system" {
description = "The architecture of the system to deploy to."
type = string
default = "x86_64-linux"
}
variable "username" {
description = "the SSH user to use"
type = string
default = "root"
}
variable "host" {
description = "the host to access by SSH"
type = string
}
variable "module" {
description = "The module to call to obtain the NixOS configuration from."
type = string
}
variable "args" {
description = "The arguments with which to call the module to obtain the NixOS configuration."
type = string
default = "{}"
}
variable "key_file" {
description = "path to the user's SSH private key"
type = string
}
variable "deployment_name" {
description = "The name of the deployment for which to obtain the NixOS configuration."
type = string
}
variable "root_path" {
description = "The path to the root of the repository."
type = string
}
variable "ssh_opts" {
description = "Extra SSH options (`-o`) to use."
type = string
default = "[]"
}
variable "deployment_type" {
description = "A `deployment-type` from the Fediversity data model, for grabbing the desired NixOS configuration."
type = string
default = "tf-host"
}

View file

@ -6,13 +6,7 @@
outputs = outputs =
inputs: inputs:
{ import ./mkFlake.nix inputs (
nixConfig = {
extra-trusted-substituters = "https://cache.saumon.network/proxmox-nixos";
extra-trusted-public-keys = "proxmox-nixos:D9RYSWpQQC/msZUWphOY2I5RLH5Dd6yQcaHIuug7dWM=";
};
}
// import ./mkFlake.nix inputs (
{ inputs, sources, ... }: { inputs, sources, ... }:
{ {
imports = [ imports = [

View file

@ -20,13 +20,16 @@ in
''; '';
}; };
isFediversityVm = mkOption { proxmox = mkOption {
type = types.bool; type = types.nullOr (
types.enum [
"procolix"
"fediversity"
]
);
description = '' description = ''
Whether the machine is a Fediversity VM or not. This is used to The Proxmox instance. This is used for provisioning only and should be
determine whether the machine should be provisioned via Proxmox or not. set to `null` if the machine is not a VM.
Machines that are _not_ Fediversity VM could be physical machines, or
VMs that live outside Fediversity, eg. on Procolix's Proxmox.
''; '';
}; };

View file

@ -1,14 +1,10 @@
{ ... }: { sources, ... }:
{ {
_class = "nixos"; _class = "nixos";
## FIXME: It would be nice, but the following leads to infinite recursion imports = [
## in the way we currently plug `sources` in. "${sources.nixpkgs}/nixos/modules/profiles/qemu-guest.nix"
## ];
# imports = [
# "${sources.nixpkgs}/nixos/modules/profiles/qemu-guest.nix"
# ];
boot = { boot = {
initrd = { initrd = {

View file

@ -2,6 +2,7 @@
inputs, inputs,
lib, lib,
config, config,
sources,
keys, keys,
secrets, secrets,
... ...
@ -32,9 +33,10 @@ in
## should go into the `./nixos` subdirectory. ## should go into the `./nixos` subdirectory.
nixos.module = { nixos.module = {
imports = [ imports = [
"${sources.agenix}/modules/age.nix"
"${sources.disko}/module.nix"
./options.nix ./options.nix
./nixos ./nixos
./proxmox-qemu-vm.nix
]; ];
## Inject the shared options from the resource's `config` into the NixOS ## Inject the shared options from the resource's `config` into the NixOS

View file

@ -14,38 +14,53 @@ let
mkOption mkOption
evalModules evalModules
filterAttrs filterAttrs
mapAttrs'
deepSeq
; ;
inherit (lib.attrsets) genAttrs; inherit (lib.attrsets) genAttrs;
commonResourceModule = { ## Given a machine's name and whether it is a test VM, make a resource module,
# TODO(@fricklerhandwerk): this is terrible but IMO we should just ditch ## except for its missing provider. (Depending on the use of that resource, we
# flake-parts and have our own data model for how the project is organised ## will provide a different one.)
# internally makeResourceModule =
{ vmName, isTestVm }:
{
# TODO(@fricklerhandwerk): this is terrible but IMO we should just ditch flake-parts and have our own data model for how the project is organised internally
_module.args = { _module.args = {
inherit inherit
inputs inputs
keys keys
secrets secrets
sources
; ;
}; };
## FIXME: It would be preferrable to have those `sources`-related imports in
## the modules that use them. However, doing so triggers infinite recursions
## because of the way we propagate `sources`. `sources` must be propagated by
## means of `specialArgs`, but this requires a bigger change.
nixos.module.imports = [ nixos.module.imports = [
"${sources.nixpkgs}/nixos/modules/profiles/qemu-guest.nix" ./common/proxmox-qemu-vm.nix
"${sources.agenix}/modules/age.nix"
"${sources.disko}/module.nix"
"${sources.home-manager}/nixos"
]; ];
imports = [ nixos.specialArgs = {
inherit sources;
};
imports =
[
./common/resource.nix ./common/resource.nix
]
++ (
if isTestVm then
[
../machines/operator/${vmName}
{
nixos.module.users.users.root.openssh.authorizedKeys.keys = [
# allow our panel vm access to the test machines
keys.panel
]; ];
}
]
else
[
../machines/dev/${vmName}
]
);
fediversityVm.name = vmName;
}; };
## Given a list of machine names, make a deployment with those machines' ## Given a list of machine names, make a deployment with those machines'
@ -54,16 +69,34 @@ let
vmNames: vmNames:
{ providers, ... }: { providers, ... }:
{ {
# XXX: this type merge is for adding `specialArgs` to resource modules
options.resources = mkOption {
type =
with lib.types;
lazyAttrsOf (submoduleWith {
class = "nixops4Resource";
modules = [ ];
# TODO(@fricklerhandwerk): we may want to pass through all of `specialArgs`
# once we're sure it's sane. leaving it here for better control during refactoring.
specialArgs = {
inherit sources;
};
});
};
config = {
providers.local = inputs.nixops4.modules.nixops4Provider.local; providers.local = inputs.nixops4.modules.nixops4Provider.local;
resources = genAttrs vmNames (vmName: { resources = genAttrs vmNames (vmName: {
type = providers.local.exec; type = providers.local.exec;
imports = [ imports = [
inputs.nixops4-nixos.modules.nixops4Resource.nixos inputs.nixops4-nixos.modules.nixops4Resource.nixos
commonResourceModule (makeResourceModule {
../machines/dev/${vmName} inherit vmName;
isTestVm = false;
})
]; ];
}); });
}; };
};
makeDeployment' = vmName: makeDeployment [ vmName ]; makeDeployment' = vmName: makeDeployment [ vmName ];
## Given an attrset of test configurations (key = test machine name, value = ## Given an attrset of test configurations (key = test machine name, value =
@ -77,29 +110,21 @@ let
fediversity = import ../services/fediversity; fediversity = import ../services/fediversity;
} }
{ {
garageConfigurationResource = { garageConfigurationResource = makeResourceModule {
imports = [ vmName = "test01";
commonResourceModule isTestVm = true;
../machines/operator/test01
];
}; };
mastodonConfigurationResource = { mastodonConfigurationResource = makeResourceModule {
imports = [ vmName = "test06"; # somehow `test02` has a problem - use test06 instead
commonResourceModule isTestVm = true;
../machines/operator/test06 # somehow `test02` has a problem - use test06 instead
];
}; };
peertubeConfigurationResource = { peertubeConfigurationResource = makeResourceModule {
imports = [ vmName = "test05";
commonResourceModule isTestVm = true;
../machines/operator/test05
];
}; };
pixelfedConfigurationResource = { pixelfedConfigurationResource = makeResourceModule {
imports = [ vmName = "test04";
commonResourceModule isTestVm = true;
../machines/operator/test04
];
}; };
}; };
@ -112,63 +137,54 @@ let
## this is only needed to expose NixOS configurations for provisioning ## this is only needed to expose NixOS configurations for provisioning
## purposes, and eventually all of this should be handled by NixOps4. ## purposes, and eventually all of this should be handled by NixOps4.
options = { options = {
nixos.module = mkOption { type = lib.types.deferredModule; }; # NOTE: not just `nixos` otherwise merging will go wrong nixos.module = mkOption { }; # NOTE: not just `nixos` otherwise merging will go wrong
nixpkgs = mkOption { }; nixpkgs = mkOption { };
ssh = mkOption { }; ssh = mkOption { };
}; };
}; };
makeResourceConfig = makeResourceConfig =
{ vmName, isTestVm }: vm:
(evalModules { (evalModules {
modules = [ modules = [
nixops4ResourceNixosMockOptions nixops4ResourceNixosMockOptions
commonResourceModule (makeResourceModule vm)
(if isTestVm then ../machines/operator/${vmName} else ../machines/dev/${vmName})
]; ];
}).config; }).config;
## Given a VM name, make a NixOS configuration for this machine. ## Given a VM name, make a NixOS configuration for this machine.
makeConfiguration = makeConfiguration =
isTestVm: vmName: isTestVm: vmName:
import "${sources.nixpkgs}/nixos" { let
configuration = (makeResourceConfig { inherit vmName isTestVm; }).nixos.module; inherit (sources) nixpkgs;
system = "x86_64-linux"; in
import "${nixpkgs}/nixos" {
modules = [
(makeResourceConfig { inherit vmName isTestVm; }).nixos.module
];
}; };
makeVmOptions = makeVmOptions = isTestVm: vmName: {
isTestVm: vmName: inherit ((makeResourceConfig { inherit vmName isTestVm; }).fediversityVm)
let proxmox
config = (makeResourceConfig { inherit vmName isTestVm; }).fediversityVm;
in
if config.isFediversityVm then
{
inherit (config)
vmId vmId
description description
sockets sockets
cores cores
memory memory
diskSize diskSize
hostPublicKey hostPublicKey
unsafeHostPrivateKey unsafeHostPrivateKey
; ;
} };
else
null;
listSubdirectories = path: attrNames (filterAttrs (_: type: type == "directory") (readDir path)); listSubdirectories = path: attrNames (filterAttrs (_: type: type == "directory") (readDir path));
machines = listSubdirectories ../machines/dev; machines = listSubdirectories ../machines/dev;
testMachines = listSubdirectories ../machines/operator; testMachines = listSubdirectories ../machines/operator;
nixosConfigurations =
genAttrs machines (makeConfiguration false)
// genAttrs testMachines (makeConfiguration true);
vmOptions =
filterAttrs (_: value: value != null) # Filter out non-Fediversity VMs
(genAttrs machines (makeVmOptions false) // genAttrs testMachines (makeVmOptions true));
in in
{ {
_class = "flake"; _class = "flake";
@ -192,23 +208,10 @@ in
) )
); );
}; };
flake = { inherit nixosConfigurations vmOptions; }; flake.nixosConfigurations =
genAttrs machines (makeConfiguration false)
perSystem = // genAttrs testMachines (makeConfiguration true);
{ pkgs, ... }: flake.vmOptions =
{ genAttrs machines (makeVmOptions false)
checks = // genAttrs testMachines (makeVmOptions true);
mapAttrs' (name: nixosConfiguration: {
name = "nixosConfigurations-${name}";
value = nixosConfiguration.config.system.build.toplevel;
}) nixosConfigurations
// mapAttrs' (name: vmOptions: {
name = "vmOptions-${name}";
## Check that VM options builds/evaluates correctly. `deepSeq e1
## e2` evaluates `e1` strictly in depth before returning `e2`. We
## use this trick because checks need to be derivations, which VM
## options are not.
value = deepSeq vmOptions pkgs.hello;
}) vmOptions;
};
} }

View file

@ -179,9 +179,15 @@ grab_vm_options () {
--log-format raw --quiet --log-format raw --quiet
) )
proxmox=$(echo "$options" | jq -r .proxmox)
vm_id=$(echo "$options" | jq -r .vmId) vm_id=$(echo "$options" | jq -r .vmId)
description=$(echo "$options" | jq -r .description) description=$(echo "$options" | jq -r .description)
if [ "$proxmox" != fediversity ]; then
die "I do not know how to provision things that are not Fediversity VMs,
but I got proxmox = '%s' for VM %s." "$proxmox" "$vm_name"
fi
sockets=$(echo "$options" | jq -r .sockets) sockets=$(echo "$options" | jq -r .sockets)
cores=$(echo "$options" | jq -r .cores) cores=$(echo "$options" | jq -r .cores)
memory=$(echo "$options" | jq -r .memory) memory=$(echo "$options" | jq -r .memory)

View file

@ -167,10 +167,16 @@ grab_vm_options () {
--log-format raw --quiet --log-format raw --quiet
) )
proxmox=$(echo "$options" | jq -r .proxmox)
vm_id=$(echo "$options" | jq -r .vmId) vm_id=$(echo "$options" | jq -r .vmId)
printf 'done grabing VM options for VM %s. Got id: %d.\n' \ if [ "$proxmox" != fediversity ]; then
"$vm_name" "$vm_id" die "I do not know how to remove things that are not Fediversity VMs,
but I got proxmox = '%s' for VM %s." "$proxmox" "$vm_name"
fi
printf 'done grabing VM options for VM %s. Found VM %d on %s Proxmox.\n' \
"$vm_name" "$vm_id" "$proxmox"
fi fi
} }

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "fedi200";
isFediversityVm = true;
vmId = 200; vmId = 200;
proxmox = "fediversity";
description = "Testing machine for Hans"; description = "Testing machine for Hans";
domain = "abundos.eu"; domain = "abundos.eu";
@ -17,4 +16,10 @@
gateway = "2a00:51c0:13:1305::1"; gateway = "2a00:51c0:13:1305::1";
}; };
}; };
nixos.module = {
imports = [
../../../infra/common/proxmox-qemu-vm.nix
];
};
} }

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "fedi201";
isFediversityVm = true;
vmId = 201; vmId = 201;
proxmox = "fediversity";
description = "FediPanel"; description = "FediPanel";
domain = "abundos.eu"; domain = "abundos.eu";
@ -20,6 +19,7 @@
nixos.module = { nixos.module = {
imports = [ imports = [
../../../infra/common/proxmox-qemu-vm.nix
./fedipanel.nix ./fedipanel.nix
]; ];
}; };

View file

@ -1,5 +1,6 @@
{ {
config, config,
sources,
... ...
}: }:
let let
@ -10,6 +11,7 @@ in
imports = [ imports = [
(import ../../../panel { }).module (import ../../../panel { }).module
"${sources.home-manager}/nixos"
]; ];
security.acme = { security.acme = {

View file

@ -20,9 +20,7 @@ in
ssh.host = mkForce "forgejo-ci"; ssh.host = mkForce "forgejo-ci";
fediversityVm = { fediversityVm = {
name = "forgejo-ci";
domain = "procolix.com"; domain = "procolix.com";
isFediversityVm = false;
ipv4 = { ipv4 = {
interface = "enp1s0f0"; interface = "enp1s0f0";

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "vm02116";
isFediversityVm = false;
vmId = 2116; vmId = 2116;
proxmox = "procolix";
description = "Forgejo"; description = "Forgejo";
ipv4.address = "185.206.232.34"; ipv4.address = "185.206.232.34";
@ -15,6 +14,7 @@
{ lib, ... }: { lib, ... }:
{ {
imports = [ imports = [
../../../infra/common/proxmox-qemu-vm.nix
./forgejo.nix ./forgejo.nix
]; ];

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "vm02187";
isFediversityVm = false;
vmId = 2187; vmId = 2187;
proxmox = "procolix";
description = "Wiki"; description = "Wiki";
ipv4.address = "185.206.232.187"; ipv4.address = "185.206.232.187";
@ -15,6 +14,7 @@
{ lib, ... }: { lib, ... }:
{ {
imports = [ imports = [
../../../infra/common/proxmox-qemu-vm.nix
./wiki.nix ./wiki.nix
]; ];

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "test01";
isFediversityVm = true;
vmId = 7001; vmId = 7001;
proxmox = "fediversity";
hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub; hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub;
unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key; unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key;

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "test02";
isFediversityVm = true;
vmId = 7002; vmId = 7002;
proxmox = "fediversity";
hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub; hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub;
unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key; unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key;

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "test03";
isFediversityVm = true;
vmId = 7003; vmId = 7003;
proxmox = "fediversity";
hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub; hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub;
unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key; unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key;

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "test04";
isFediversityVm = true;
vmId = 7004; vmId = 7004;
proxmox = "fediversity";
hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub; hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub;
unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key; unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key;

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "test05";
isFediversityVm = true;
vmId = 7005; vmId = 7005;
proxmox = "fediversity";
hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub; hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub;
unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key; unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key;

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "test06";
isFediversityVm = true;
vmId = 7006; vmId = 7006;
proxmox = "fediversity";
hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub; hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub;
unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key; unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key;

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "test11";
isFediversityVm = true;
vmId = 7011; vmId = 7011;
proxmox = "fediversity";
hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub; hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub;
unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key; unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key;

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "test12";
isFediversityVm = true;
vmId = 7012; vmId = 7012;
proxmox = "fediversity";
hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub; hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub;
unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key; unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key;

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "test13";
isFediversityVm = true;
vmId = 7013; vmId = 7013;
proxmox = "fediversity";
hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub; hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub;
unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key; unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key;

View file

@ -2,9 +2,8 @@
_class = "nixops4Resource"; _class = "nixops4Resource";
fediversityVm = { fediversityVm = {
name = "test14";
isFediversityVm = true;
vmId = 7014; vmId = 7014;
proxmox = "fediversity";
hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub; hostPublicKey = builtins.readFile ./ssh_host_ed25519_key.pub;
unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key; unsafeHostPrivateKey = builtins.readFile ./ssh_host_ed25519_key;

View file

@ -1,4 +0,0 @@
host=192.168.51.81
verify_ssl=0
user=kiara@ProcoliX
password=

View file

@ -25,22 +25,6 @@
"url": null, "url": null,
"hash": "1w2gsy6qwxa5abkv8clb435237iifndcxq0s79wihqw11a5yb938" "hash": "1w2gsy6qwxa5abkv8clb435237iifndcxq0s79wihqw11a5yb938"
}, },
"crane": {
"type": "GitRelease",
"repository": {
"type": "GitHub",
"owner": "ipetkov",
"repo": "crane"
},
"pre_releases": false,
"version_upper_bound": null,
"release_prefix": null,
"submodules": false,
"version": "v0.20.3",
"revision": "8468a0c46f81d806fd643ffe389fa80328b21cf4",
"url": "https://api.github.com/repos/ipetkov/crane/tarball/v0.20.3",
"hash": "0zw4275c3a6572w6vjmn850yddw6n3qagwfcq6ns247cx72fdfx0"
},
"disko": { "disko": {
"type": "GitRelease", "type": "GitRelease",
"repository": { "repository": {
@ -166,32 +150,6 @@
"revision": "f33a4d26226c05d501b9d4d3e5e60a3a59991921", "revision": "f33a4d26226c05d501b9d4d3e5e60a3a59991921",
"url": "https://github.com/nixos/nixpkgs/archive/f33a4d26226c05d501b9d4d3e5e60a3a59991921.tar.gz", "url": "https://github.com/nixos/nixpkgs/archive/f33a4d26226c05d501b9d4d3e5e60a3a59991921.tar.gz",
"hash": "1b6dm1sn0bdpcsmxna0zzspjaixa2dald08005fry5jrbjvwafdj" "hash": "1b6dm1sn0bdpcsmxna0zzspjaixa2dald08005fry5jrbjvwafdj"
},
"nixpkgs-stable": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "nixos",
"repo": "nixpkgs"
},
"branch": "nixos-25.05",
"submodules": false,
"revision": "a1ae8ef72f64a845ecce5c6dcf65d546bf7deeb4",
"url": "https://github.com/nixos/nixpkgs/archive/a1ae8ef72f64a845ecce5c6dcf65d546bf7deeb4.tar.gz",
"hash": "0d7lp30wyy5647gpm8rnihvdcpmgmfr9c5yg4fhl31lsg8mlbg16"
},
"proxmox-nixos": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "SaumonNet",
"repo": "proxmox-nixos"
},
"branch": "main",
"submodules": false,
"revision": "48f39fbe2e8f90f9ac160dd4b6929f3ac06d8223",
"url": "https://github.com/SaumonNet/proxmox-nixos/archive/48f39fbe2e8f90f9ac160dd4b6929f3ac06d8223.tar.gz",
"hash": "0606qcs8x1jwckd1ivf52rqdmi3lkn66iiqh6ghd4kqx0g2bw3nv"
} }
}, },
"version": 5 "version": 5

View file

@ -218,7 +218,6 @@ in
cfg.nixops4Package cfg.nixops4Package
pkgs.nix pkgs.nix
pkgs.openssh pkgs.openssh
pkgs.git
]; ];
preStart = '' preStart = ''
# Auto-migrate on first run or if the package has changed # Auto-migrate on first run or if the package has changed

View file

@ -13,14 +13,14 @@ buildPythonPackage rec {
_class = "package"; _class = "package";
pname = "drf-pydantic"; pname = "drf-pydantic";
version = "v2.9.0"; version = "v2.7.1";
pyproject = true; pyproject = true;
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "KiaraGrouwstra"; owner = "georgebv";
repo = pname; repo = pname;
rev = "d21c879543bd106242bd7f86e79da1f668109579"; rev = version;
hash = "sha256-pk0/6BphIiXxR3cewBJ5nKii3kj3lDHLO9U9xqXDxI8="; hash = "sha256-ABtSoxj/+HHq4hj4Yb6bEiyOl00TCO/9tvBzhv6afxM=";
}; };
nativeBuildInputs = [ nativeBuildInputs = [

View file

@ -75,9 +75,6 @@ in
services.peertube = { services.peertube = {
enable = true; enable = true;
localDomain = config.fediversity.peertube.domain; localDomain = config.fediversity.peertube.domain;
serviceEnvironmentFile = pkgs.writeText "password-init-root" ''
PT_INITIAL_ROOT_PASSWORD=changeme
'';
# TODO: in most of nixpkgs, these are true by default. upstream that unless there's a good reason not to. # TODO: in most of nixpkgs, these are true by default. upstream that unless there's a good reason not to.
redis.createLocally = true; redis.createLocally = true;

View file

@ -7,6 +7,7 @@
{ {
checks = { checks = {
test-mastodon-service = pkgs.testers.runNixOSTest ./mastodon.nix; test-mastodon-service = pkgs.testers.runNixOSTest ./mastodon.nix;
test-pixelfed-garage-service = pkgs.testers.runNixOSTest ./pixelfed-garage.nix;
test-peertube-service = pkgs.testers.runNixOSTest ./peertube.nix; test-peertube-service = pkgs.testers.runNixOSTest ./peertube.nix;
}; };
}; };