Compare commits

..

35 commits

Author SHA1 Message Date
50e1a768e7
qemu guest 2025-08-24 18:32:12 +02:00
5a02027d48
grub 2025-08-24 18:31:34 +02:00
2af6817cd8
auto login 2025-08-24 18:30:52 +02:00
20557422e9
networking 2025-08-24 18:30:43 +02:00
4b85628ab1
users 2025-08-24 18:27:19 +02:00
03cbb4738d
handle test outcome 2025-08-24 18:26:42 +02:00
9769e1714c
specialArgs: sources 2025-08-24 18:25:00 +02:00
10ba2ee1e6
nix in tests: download-attempts = 1 2025-08-24 18:21:38 +02:00
b7cf39534f
ensure inputs 2025-08-24 18:19:53 +02:00
ee6b990144
rm paste 2025-08-24 18:18:49 +02:00
fe0edd897b
move stuff not needed in test out 2025-08-24 18:18:26 +02:00
081ae1ad07
ensure availability of needed inputs 2025-08-24 18:15:36 +02:00
3ae1235461
reduce download attempts in test 2025-08-24 18:14:26 +02:00
85cbdd945b
settle for hello, ditching cowsay 2025-08-24 18:13:22 +02:00
d51f8fcf16
move imports from paste to targetNode to increase parity between paste and nixosTest 2025-08-24 17:52:06 +02:00
ae06cfc417
ditch superfluous substituters 2025-08-24 17:52:06 +02:00
b7e34de835
pasteable command for trying without rebuilding vm 2025-08-24 17:52:06 +02:00
458e565e4e
add keys 2025-08-24 17:52:06 +02:00
0d36f32190
wip: use ssh in test 2025-08-24 17:52:06 +02:00
5c47da3b0b
add deployment method: ssh 2025-08-24 17:52:06 +02:00
8e50fd675f
un-nixops 2025-08-24 17:52:06 +02:00
b29b8bfb84
scaffold deployment/check/data-model from ./basic
modelify
2025-08-24 17:52:06 +02:00
d67f5a2b7d
allow different deployment types 2025-08-24 17:51:37 +02:00
4262a92741
Merge pull request 'move nixops4Deployment class' (#6) from kiara/Fediversity:data-model-fix-root-class into deployment-data-model-with-tests
Reviewed-on: #6
Reviewed-by: Valentin Gagarin <valentin.gagarin@tweag.io>
2025-08-24 17:51:37 +02:00
e5b08faa1b
put config stuff in an attrset 2025-08-24 17:51:37 +02:00
c0b8dbbeeb
move nixops4Deployment class 2025-08-24 17:51:37 +02:00
1048ac674e
fix linter gripes 2025-08-24 17:51:37 +02:00
d1d152d2df
add explanatory comment 2025-08-24 17:51:37 +02:00
76a07a17ad
implement and test data model for runtime environments 2025-08-24 17:51:37 +02:00
f76d953b1f
generalize function type 2025-08-24 17:51:37 +02:00
1f99a4c6c3 listToAttrs o map o attrsToListmapAttrs' (#489)
Reviewed-on: Fediversity/Fediversity#489
Reviewed-by: kiara Grouwstra <kiara@procolix.eu>
Co-authored-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
Co-committed-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
2025-08-01 13:09:26 +02:00
588bb77a94 Infra: expose and use checks for vmOptions and nixosConfigurations (#488)
Following Fediversity/Fediversity#478 (comment), here is a PR that plugs the infra's `vmOptions` and `nixosConfigurations` outputs into flake checks, instead of calling random Nix commands from the CI. There is still a bit of magic in the CI, but that's because we don't have yet a Nix-aware CI that exposes one job per flake check.

Reviewed-on: Fediversity/Fediversity#488
Reviewed-by: kiara Grouwstra <kiara@procolix.eu>
Co-authored-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
Co-committed-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
2025-07-31 15:41:02 +02:00
df3a070fa4 Infra: get rid of makeResourceModule (#485)
Reviewed-on: Fediversity/Fediversity#485
Reviewed-by: Valentin Gagarin <valentin.gagarin@tweag.io>
Reviewed-by: kiara Grouwstra <kiara@procolix.eu>
Co-authored-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
Co-committed-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
2025-07-31 00:49:00 +02:00
be72b82875 Link to upstreaming PR for lib.types.fileset (#487)
Reviewed-on: Fediversity/Fediversity#487
Reviewed-by: kiara Grouwstra <kiara@procolix.eu>
Co-authored-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
Co-committed-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
2025-07-30 13:25:22 +02:00
1b66028f32 Fix infra and add more tests (#478)
This PR contains a bunch of small fixes having to do with infra code. The goal is not to fix everything as that would require a full rewrite. Instead, we fix just what is necessary to get some testing going on. Once that is available, we will be able to work on a full refactor with more guarantees. Something of note is that most of the difficulty was to find code that would make both `nixops4 apply` _and_ `nix build .#nixosConfigurations.<machine>` happy. The takeaway is that the tests that we are adding now will not catch a whole class of tests having to do with how NixOps4 wires up the resources. Still, this is probably less significant as we are supposed to use NixOps4 every now and then.

The commits should be read separately.

Reviewed-on: Fediversity/Fediversity#478
Reviewed-by: kiara Grouwstra <kiara@procolix.eu>
Co-authored-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
Co-committed-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
2025-07-30 12:31:03 +02:00
29 changed files with 309 additions and 270 deletions

View file

@ -62,3 +62,29 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.deployment-model -L - run: nix build .#checks.x86_64-linux.deployment-model -L
## NOTE: NixOps4 does not provide a good “dry run” mode, so we instead check
## proxies for resources, namely whether their `.#vmOptions.<machine>` and
## `.#nixosConfigurations.<machine>` outputs evaluate and build correctly, and
## whether we can dry run `infra/proxmox-*.sh` on them. This will not catch
## everything, and in particular not issues in how NixOps4 wires up the
## resources, but that is still something.
check-resources:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: |
set -euC
echo ==================== [ VM Options ] ====================
machines=$(nix eval --impure --raw --expr 'with builtins; toString (attrNames (getFlake (toString ./.)).vmOptions)')
for machine in $machines; do
echo ~~~~~~~~~~~~~~~~~~~~~: $machine :~~~~~~~~~~~~~~~~~~~~~
nix build .#checks.x86_64-linux.vmOptions-$machine
done
echo
echo ==================== [ NixOS Configurations ] ====================
machines=$(nix eval --impure --raw --expr 'with builtins; toString (attrNames (getFlake (toString ./.)).nixosConfigurations)')
for machine in $machines; do
echo ~~~~~~~~~~~~~~~~~~~~~: $machine :~~~~~~~~~~~~~~~~~~~~~
nix build .#checks.x86_64-linux.nixosConfigurations-$machine
done

View file

@ -49,6 +49,7 @@ in
substituters = mkForce [ ]; substituters = mkForce [ ];
hashed-mirrors = null; hashed-mirrors = null;
connect-timeout = 1; connect-timeout = 1;
download-attempts = 1;
extra-experimental-features = "flakes"; extra-experimental-features = "flakes";
}; };
@ -61,6 +62,10 @@ in
pkgs.stdenv pkgs.stdenv
pkgs.stdenvNoCC pkgs.stdenvNoCC
pkgs.automake
pkgs.autoconf
pkgs.binutils
pkgs.bison
] ]
++ ( ++ (
let let
@ -92,7 +97,35 @@ in
machine.system.build.vm.inputDerivation machine.system.build.vm.inputDerivation
machine.system.build.bootStage1.inputDerivation machine.system.build.bootStage1.inputDerivation
machine.system.build.bootStage2.inputDerivation machine.system.build.bootStage2.inputDerivation
pkgs.automake.inputDerivation
pkgs.autoconf.inputDerivation
pkgs.bash.inputDerivation
pkgs.binutils.inputDerivation
pkgs.bison.inputDerivation
] ]
++ concatLists (
lib.lists.map (
pkg:
if
pkg ? inputDerivation
# error: output '/nix/store/dki9d3vldafg9ydrfm7x0g0rr0qljk98-sudo-1.9.16p2' is not allowed to refer to the following paths:
# /nix/store/2xdmps65ryklmbf025bm4pxv16gb8ajv-sudo-1.9.16p2.tar.gz
# /nix/store/58br4vk3q5akf4g8lx0pqzfhn47k3j8d-bash-5.2p37
# /nix/store/8v6k283dpbc0qkdq81nb6mrxrgcb10i1-gcc-wrapper-14-20241116
# /nix/store/9r1nl9ksiyszy4qzzg6y2gcdkca0xmhy-stdenv-linux
# /nix/store/a4rmp6in7igbl1wbz9pli5nq0wiclq0y-groff-1.23.0
# /nix/store/dki9d3vldafg9ydrfm7x0g0rr0qljk98-sudo-1.9.16p2
# /nix/store/f5y58qz2fzpzgkhp0nizixi10x04ppyy-linux-pam-1.6.1
# /nix/store/shkw4qm9qcw5sc5n1k5jznc83ny02r39-default-builder.sh
# /nix/store/vj1c3wf9c11a0qs6p3ymfvrnsdgsdcbq-source-stdenv.sh
# /nix/store/yh6qg1nsi5h2xblcr67030pz58fsaxx3-coreutils-9.6
&& !(lib.strings.hasInfix "sudo" (builtins.toString pkg))
then
[ pkg.inputDerivation ]
else
[ ]
) machine.environment.systemPackages
)
++ concatLists ( ++ concatLists (
lib.mapAttrsToList ( lib.mapAttrsToList (
_k: v: if v ? source.inputDerivation then [ v.source.inputDerivation ] else [ ] _k: v: if v ? source.inputDerivation then [ v.source.inputDerivation ] else [ ]

View file

@ -48,7 +48,8 @@ in
extraTestScript = mkOption { }; extraTestScript = mkOption { };
sourceFileset = mkOption { sourceFileset = mkOption {
## REVIEW: Upstream to nixpkgs? ## FIXME: grab `lib.types.fileset` from NixOS, once upstreaming PR
## https://github.com/NixOS/nixpkgs/pull/428293 lands.
type = types.mkOptionType { type = types.mkOptionType {
name = "fileset"; name = "fileset";
description = "fileset"; description = "fileset";

View file

@ -18,6 +18,7 @@ in
(modulesPath + "/profiles/qemu-guest.nix") (modulesPath + "/profiles/qemu-guest.nix")
(modulesPath + "/../lib/testing/nixos-test-base.nix") (modulesPath + "/../lib/testing/nixos-test-base.nix")
./sharedOptions.nix ./sharedOptions.nix
../../../infra/common/nixos/users.nix
]; ];
config = mkMerge [ config = mkMerge [
@ -31,6 +32,9 @@ in
## 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 { };
settings = {
download-attempts = 1;
};
}; };
services.openssh = { services.openssh = {
@ -38,22 +42,46 @@ in
settings.PermitRootLogin = "yes"; settings.PermitRootLogin = "yes";
}; };
networking.firewall.allowedTCPPorts = [ 22 ]; networking = {
firewall.enable = false;
enableIPv6 = false;
};
services.getty.autologinUser = lib.mkForce "root";
## Test VMs don't have a bootloader by default. ## Test VMs don't have a bootloader by default.
boot.loader.grub.enable = false; # boot.loader = {
# # GRUB enabled: installation of GRUB on /dev/disk/by-id/virtio-root failed: No such file or directory
# grub.enable = false;
# # systemd boot enabled: '/boot' is not a mounted partition. Is the path configured correctly?
# systemd-boot.enable = true;
# efi.canTouchEfiVariables = true;
# };
# # same issue as no bootloader
# boot.loader.generic-extlinux-compatible.enable = false;
# builds but won't boot back up
boot.loader.grub.forceInstall = true;
# # builds but won't boot back up
# # to be used with --no-bootloader, which i could only find for flakes
# boot.loader.grub.enable = false;
users.users.root.openssh.authorizedKeys.keys = users.mutableUsers = false;
let users.users.root = {
keys = import ../../../keys; password = "password";
in hashedPassword = null;
lib.attrValues keys.contributors hashedPasswordFile = null;
++ [ openssh.authorizedKeys.keys =
# allow our panel vm access to the test machines let
keys.panel keys = import ../../../keys;
# allow continuous deployment access in
keys.cd lib.attrValues keys.contributors
]; ++ [
# allow our panel vm access to the test machines
keys.panel
# allow continuous deployment access
keys.cd
];
};
} }
(mkIf config.enableAcme { (mkIf config.enableAcme {

View file

@ -1,7 +1,6 @@
{ {
targetMachines = [ targetMachines = [
"hello" "hello"
"cowsay"
]; ];
pathToRoot = ../../..; pathToRoot = ../../..;
pathFromRoot = ./.; pathFromRoot = ./.;

View file

@ -25,12 +25,16 @@ in
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
jq jq
automake
autoconf
]; ];
# FIXME: sad times # FIXME: sad times
system.extraDependencies = with pkgs; [ system.extraDependencies = with pkgs; [
jq jq
jq.inputDerivation jq.inputDerivation
automake
autoconf
]; ];
system.extraDependenciesFromModule = system.extraDependenciesFromModule =
@ -39,6 +43,8 @@ in
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
hello hello
cowsay cowsay
automake
autoconf
]; ];
}; };
}; };
@ -46,7 +52,6 @@ in
extraTestScript = '' extraTestScript = ''
with subtest("Check the status before deployment"): with subtest("Check the status before deployment"):
hello.fail("hello 1>&2") hello.fail("hello 1>&2")
cowsay.fail("cowsay 1>&2")
${lib.concatStringsSep "\n" ( ${lib.concatStringsSep "\n" (
lib.lists.map (nodeName: '' lib.lists.map (nodeName: ''
@ -61,31 +66,45 @@ in
' '
let let
system = builtins.currentSystem; args = builtins.fromJSON "${
lib.replaceStrings [ "\"" ] [ "\\\\\"" ] (
lib.strings.toJSON {
inherit sources;
}
)
}";
inherit (args) sources;
configuration = { pkgs, config, ... }: { configuration = { pkgs, config, ... }: {
imports = [ imports = [
${pathToRoot}/deployment/check/common/sharedOptions.nix ${pathToRoot}/deployment/check/common/sharedOptions.nix
${pathToRoot}/deployment/check/common/targetNode.nix ${pathToRoot}/deployment/check/common/targetNode.nix
${sources.nixpkgs}/nixos/modules/profiles/qemu-guest.nix
]; ];
_module.args = builtins.fromJSON "${
lib.replaceStrings [ "\"" ] [ "\\\\\"" ] (
lib.strings.toJSON {
inherit sources;
}
)
}";
enableAcme = ${lib.strings.toJSON config.enableAcme}; enableAcme = ${lib.strings.toJSON config.enableAcme};
acmeNodeIP = if config.enableAcme then config.nodes.acme.networking.primaryIPAddress else null; acmeNodeIP = if config.enableAcme then config.nodes.acme.networking.primaryIPAddress else null;
# environment.systemPackages = [ pkgs.hello ]; environment.systemPackages = with pkgs; [
hello
automake
autoconf
];
};
eval = import "${sources.nixpkgs}/nixos/lib/eval-config.nix" {
system = builtins.currentSystem;
specialArgs = {
inherit sources;
};
modules = [ configuration ];
};
os = {
inherit (eval) pkgs config options;
system = eval.config.system.build.toplevel;
inherit (eval.config.system.build) vm vmWithBootLoader;
}; };
os = import "${sources.nixpkgs}/nixos" { inherit system configuration; };
in in
# import "${pathToRoot}/deployment/nixos.nix" {} # import "${pathToRoot}/deployment/nixos.nix" {}
{ {
substituters = builtins.concatStringsSep " " os.config.nix.settings.substituters;
trusted_public_keys = builtins.concatStringsSep " " os.config.nix.settings.trusted-public-keys;
drv_path = os.config.system.build.toplevel.drvPath; drv_path = os.config.system.build.toplevel.drvPath;
out_path = os.config.system.build.toplevel; out_path = os.config.system.build.toplevel;
} }
@ -97,31 +116,36 @@ in
json="$("''${command[@]}" --eval --strict --json)" json="$("''${command[@]}" --eval --strict --json)"
# DEPLOY # DEPLOY
declare substituters trusted_public_keys drv_path declare drv_path
# set our variables using the json object # set our variables using the json object
eval "export $(echo $json | jq -r 'to_entries | map("\(.key)=\(.value)") | @sh')" eval "export $(echo $json | jq -r 'to_entries | map("\(.key)=\(.value)") | @sh')"
host="root@${nodeName}" host="root@${nodeName}"
buildArgs=(
--option extra-binary-caches https://cache.nixos.org/
--option substituters $substituters
--option trusted-public-keys $trusted_public_keys
)
sshOpts=( sshOpts=(
-o BatchMode=yes -o BatchMode=yes
-o StrictHostKeyChecking=no -o StrictHostKeyChecking=no
-o "ConnectionAttempts=1"
-o "ConnectTimeout=1"
-o "ServerAliveCountMax=1"
-o "ServerAliveInterval=1"
) )
# get the realized derivation to deploy # get the realized derivation to deploy
outPath=$(nix-store --realize "$drv_path" "''${buildArgs[@]}") outPath=$(nix-store --realize "$drv_path")
# deploy the config by nix-copy-closure # deploy the config by nix-copy-closure
NIX_SSHOPTS="''${sshOpts[*]}" nix-copy-closure --to "$host" "$outPath" --gzip --use-substitutes NIX_SSHOPTS="''${sshOpts[*]}" nix-copy-closure --to "$host" "$outPath" --gzip --use-substitutes
# switch the remote host to the config # switch the remote host to the config
ssh "''${sshOpts[@]}" "$host" "nix-env --profile /nix/var/nix/profiles/system --set $outPath; $outPath/bin/switch-to-configuration switch" output=$(ssh "''${sshOpts[@]}" "$host" "nix-env --profile /nix/var/nix/profiles/system --set $outPath; nohup $outPath/bin/switch-to-configuration switch &" 2>&1) || echo "status code: $?"
echo "output: $output"
if [[ $output != *"Timeout, server ${nodeName} not responding"* ]]; then
echo "non-timeout error: $output"
exit 1
else
exit 0
fi
""") """)
${nodeName}.wait_for_unit("multi-user.target")
${nodeName}.succeed("systemctl is-active sshd")
${nodeName}.succeed("${nodeName} 1>&2")
'') targetMachines '') targetMachines
)} )}
with subtest("Check the deployment"):
hello.succeed("hello 1>&2")
cowsay.succeed("cowsay hi 1>&2")
''; '';
} }

View file

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

View file

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

View file

@ -2,7 +2,6 @@
inputs, inputs,
lib, lib,
config, config,
sources,
keys, keys,
secrets, secrets,
... ...
@ -33,10 +32,9 @@ 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,90 +14,55 @@ let
mkOption mkOption
evalModules evalModules
filterAttrs filterAttrs
mapAttrs'
deepSeq
; ;
inherit (lib.attrsets) genAttrs; inherit (lib.attrsets) genAttrs;
## Given a machine's name and whether it is a test VM, make a resource module, commonResourceModule = {
## except for its missing provider. (Depending on the use of that resource, we # TODO(@fricklerhandwerk): this is terrible but IMO we should just ditch
## will provide a different one.) # flake-parts and have our own data model for how the project is organised
makeResourceModule = # internally
{ vmName, isTestVm }: _module.args = {
{ inherit
nixos.module.imports = [ inputs
./common/proxmox-qemu-vm.nix keys
]; secrets
sources
nixos.specialArgs = { ;
inherit
sources
inputs
keys
secrets
;
};
imports =
[
./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;
}; };
## 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 = [
"${sources.nixpkgs}/nixos/modules/profiles/qemu-guest.nix"
"${sources.agenix}/modules/age.nix"
"${sources.disko}/module.nix"
"${sources.home-manager}/nixos"
];
imports = [
./common/resource.nix
];
};
## Given a list of machine names, make a deployment with those machines' ## Given a list of machine names, make a deployment with those machines'
## configurations as resources. ## configurations as resources.
makeDeployment = makeDeployment =
vmNames: vmNames:
{ providers, ... }: { providers, ... }:
{ {
# XXX: this type merge is for adding `specialArgs` to resource modules providers.local = inputs.nixops4.modules.nixops4Provider.local;
options.resources = mkOption { resources = genAttrs vmNames (vmName: {
type = type = providers.local.exec;
with lib.types; imports = [
lazyAttrsOf (submoduleWith { inputs.nixops4-nixos.modules.nixops4Resource.nixos
class = "nixops4Resource"; commonResourceModule
modules = [ ]; ../machines/dev/${vmName}
# 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
inputs
keys
secrets
;
};
});
};
config = {
providers.local = inputs.nixops4.modules.nixops4Provider.local;
resources = genAttrs vmNames (vmName: {
type = providers.local.exec;
imports = [
inputs.nixops4-nixos.modules.nixops4Resource.nixos
(makeResourceModule {
inherit vmName;
isTestVm = false;
})
];
});
};
}; };
makeDeployment' = vmName: makeDeployment [ vmName ]; makeDeployment' = vmName: makeDeployment [ vmName ];
@ -112,21 +77,29 @@ let
fediversity = import ../services/fediversity; fediversity = import ../services/fediversity;
} }
{ {
garageConfigurationResource = makeResourceModule { garageConfigurationResource = {
vmName = "test01"; imports = [
isTestVm = true; commonResourceModule
../machines/operator/test01
];
}; };
mastodonConfigurationResource = makeResourceModule { mastodonConfigurationResource = {
vmName = "test06"; # somehow `test02` has a problem - use test06 instead imports = [
isTestVm = true; commonResourceModule
../machines/operator/test06 # somehow `test02` has a problem - use test06 instead
];
}; };
peertubeConfigurationResource = makeResourceModule { peertubeConfigurationResource = {
vmName = "test05"; imports = [
isTestVm = true; commonResourceModule
../machines/operator/test05
];
}; };
pixelfedConfigurationResource = makeResourceModule { pixelfedConfigurationResource = {
vmName = "test04"; imports = [
isTestVm = true; commonResourceModule
../machines/operator/test04
];
}; };
}; };
@ -139,54 +112,63 @@ 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 { }; # NOTE: not just `nixos` otherwise merging will go wrong nixos.module = mkOption { type = lib.types.deferredModule; }; # NOTE: not just `nixos` otherwise merging will go wrong
nixpkgs = mkOption { }; nixpkgs = mkOption { };
ssh = mkOption { }; ssh = mkOption { };
}; };
}; };
makeResourceConfig = makeResourceConfig =
vm: { vmName, isTestVm }:
(evalModules { (evalModules {
modules = [ modules = [
nixops4ResourceNixosMockOptions nixops4ResourceNixosMockOptions
(makeResourceModule vm) commonResourceModule
(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:
let import "${sources.nixpkgs}/nixos" {
inherit (sources) nixpkgs; configuration = (makeResourceConfig { inherit vmName isTestVm; }).nixos.module;
in system = "x86_64-linux";
import "${nixpkgs}/nixos" {
modules = [
(makeResourceConfig { inherit vmName isTestVm; }).nixos.module
];
}; };
makeVmOptions = isTestVm: vmName: { makeVmOptions =
inherit ((makeResourceConfig { inherit vmName isTestVm; }).fediversityVm) isTestVm: vmName:
proxmox let
vmId config = (makeResourceConfig { inherit vmName isTestVm; }).fediversityVm;
description in
if config.isFediversityVm then
sockets {
cores inherit (config)
memory vmId
diskSize description
sockets
hostPublicKey cores
unsafeHostPrivateKey memory
; diskSize
}; hostPublicKey
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";
@ -210,10 +192,23 @@ in
) )
); );
}; };
flake.nixosConfigurations = flake = { inherit nixosConfigurations vmOptions; };
genAttrs machines (makeConfiguration false)
// genAttrs testMachines (makeConfiguration true); perSystem =
flake.vmOptions = { pkgs, ... }:
genAttrs machines (makeVmOptions false) {
// genAttrs testMachines (makeVmOptions true); checks =
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,15 +179,9 @@ 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,16 +167,10 @@ 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)
if [ "$proxmox" != fediversity ]; then printf 'done grabing VM options for VM %s. Got id: %d.\n' \
die "I do not know how to remove things that are not Fediversity VMs, "$vm_name" "$vm_id"
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,8 +2,9 @@
_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";
@ -16,10 +17,4 @@
gateway = "2a00:51c0:13:1305::1"; gateway = "2a00:51c0:13:1305::1";
}; };
}; };
nixos.module = {
imports = [
../../../infra/common/proxmox-qemu-vm.nix
];
};
} }

View file

@ -2,8 +2,9 @@
_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";
@ -19,7 +20,6 @@
nixos.module = { nixos.module = {
imports = [ imports = [
../../../infra/common/proxmox-qemu-vm.nix
./fedipanel.nix ./fedipanel.nix
]; ];
}; };

View file

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

View file

@ -20,7 +20,9 @@ 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,8 +2,9 @@
_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";
@ -14,7 +15,6 @@
{ lib, ... }: { lib, ... }:
{ {
imports = [ imports = [
../../../infra/common/proxmox-qemu-vm.nix
./forgejo.nix ./forgejo.nix
]; ];

View file

@ -2,8 +2,9 @@
_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";
@ -14,7 +15,6 @@
{ lib, ... }: { lib, ... }:
{ {
imports = [ imports = [
../../../infra/common/proxmox-qemu-vm.nix
./wiki.nix ./wiki.nix
]; ];

View file

@ -2,8 +2,9 @@
_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,8 +2,9 @@
_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,8 +2,9 @@
_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,8 +2,9 @@
_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,8 +2,9 @@
_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,8 +2,9 @@
_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,8 +2,9 @@
_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,8 +2,9 @@
_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,8 +2,9 @@
_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,8 +2,9 @@
_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;

59
paste
View file

@ -1,59 +0,0 @@
declare substituters trusted_public_keys drv_path
host="root@fedi203.abundos.eu"
sshOpts=(
-o BatchMode=yes
-o StrictHostKeyChecking=no
)
command=(nix-instantiate --expr '
let
sources = import ./npins;
configuration = {
imports = [
./infra/common/proxmox-qemu-vm.nix
./infra/common/nixos/users.nix
./deployment/check/common/sharedOptions.nix
./deployment/check/common/targetNode.nix
"${sources.disko}/module.nix"
];
};
eval = import "${sources.nixpkgs}/nixos/lib/eval-config.nix" {
system = builtins.currentSystem;
specialArgs = {
inherit sources;
};
modules = [ configuration ];
};
os = {
inherit (eval) pkgs config options;
system = eval.config.system.build.toplevel;
inherit (eval.config.system.build) vm vmWithBootLoader;
};
in
{
substituters = builtins.concatStringsSep " " os.config.nix.settings.substituters;
trusted_public_keys = builtins.concatStringsSep " " os.config.nix.settings.trusted-public-keys;
drv_path = os.config.system.build.toplevel.drvPath;
out_path = os.config.system.build.toplevel;
}
')
buildArgs=(
--option extra-binary-caches https://cache.nixos.org/
--option substituters "$substituters"
--option trusted-public-keys "$trusted_public_keys"
)
"${command[@]}" -A out_path
json="$("${command[@]}" --eval --strict --json)"
eval "export $(echo $json | jq -r 'to_entries | map("\(.key)=\(.value)") | @sh')"
outPath=$(nix-store --realize "$drv_path" "${buildArgs[@]}")
NIX_SSHOPTS="${sshOpts[*]}" nix-copy-closure --to "$host" "$outPath" --gzip --use-substitutes
ssh "${sshOpts[@]}" "$host" "nix-env --profile /nix/var/nix/profiles/system --set $outPath; $outPath/bin/switch-to-configuration switch"