Compare commits

...

6 commits

Author SHA1 Message Date
0919db08f7 wip: handle infra by TF 2025-04-18 19:09:03 +02:00
754bf4d8f9 switch dependency management to npins, closes #279 2025-04-18 17:41:11 +02:00
ad65fb944d clean out nixops bits 2025-04-18 17:41:11 +02:00
09899c7f3a move gitignore to apply to infra dir 2025-04-18 17:41:11 +02:00
65393abf9c clean documentation 2025-04-18 17:41:11 +02:00
173518ed90 setup: reset lock file, prevents Error: Failed to install provider
error example:

```
Error while installing hashicorp/external v2.3.4: the local package for
registry.opentofu.org/hashicorp/external 2.3.4 doesn't match any of the
checksums previously recorded in the dependency lock file (this might be
because the available checksums are for packages targeting different
platforms); for more information:
https://opentofu.org/docs/language/files/dependency-lock/#checksum-verification
```
2025-04-18 17:35:43 +02:00
37 changed files with 386 additions and 1789 deletions

View file

@ -32,3 +32,9 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: cd launch && nix-build -A tests
check-infra:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: cd infra && nix-build -A tests

6
.gitignore vendored
View file

@ -1,3 +1,9 @@
.npins.json
.terraform/
.terraform.lock.hcl
.terraform.tfstate.lock.info
terraform.tfstate*
.auto.tfvars.json
.DS_Store
.idea
*.log

View file

@ -1,8 +1,7 @@
# The Fediversity project
This repository contains all the code and code-related files having to do with
[the Fediversity project](https://fediversity.eu/), with the notable exception
of [NixOps4 that is hosted on GitHub](https://github.com/nixops4/nixops4).
[the Fediversity project](https://fediversity.eu/).
## Goals
@ -81,27 +80,15 @@ Not everyone has the expertise and time to run their own server.
The software includes technical configuration that links software components.
Most user-facing configuration remains untouched by the deployment process.
> Example: NixOps4 is used to deploy [Pixelfed](https://pixelfed.org).
> Example: OpenTofu is used to deploy [Pixelfed](https://pixelfed.org).
- Migrate
Move service configurations and user data to a different hosting provider.
- [NixOps4](https://github.com/nixops4/nixops4)
- [OpenTofu](https://opentofu.org/)
A tool for deploying and managing resources through the Nix language.
NixOps4 development is supported by the Fediversity project
- Resource
A [resource for NixOps4](https://nixops.dev/manual/development/concept/resource.html) is any external entity that can be declared with NixOps4 expressions and manipulated with NixOps4, such as a virtual machine, an active NixOS configuration, a DNS entry, or customer database.
- Resource provider
A resource provider for NixOps4 is an executable that communicates between a resource and NixOps4 using a standardised protocol, allowing [CRUD operations](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) on the resources to be performed by NixOps4.
Refer to the [NixOps4 manual](https://nixops.dev/manual/development/resource-provider/index.html) for details.
> Example: We need a resource provider for obtaining deployment secrets from a database.
An infrastructure-as-code tool, and open-source (MPL 2.0) fork of Terraform.
## Development
@ -118,9 +105,6 @@ Contact the project team if you have questions or suggestions, or if you're inte
Most of the directories in this repository have their own README going into more
details as to what they are for. As an overview:
- [`deployment/`](./deployment) contains work to generate a full Fediversity
deployment from a minimal configuration.
- [`infra/`](./infra) contains the configurations for the various VMs that are
in production for the project, for instance the Git instances or the Wiki, as
well as means to provision and set up new ones.
@ -128,14 +112,8 @@ details as to what they are for. As an overview:
- [`keys/`](./keys) contains the public keys of the contributors to this project
as well as the systems that we administrate.
- [`matrix/`](./matrix) contains everything having to do with setting up a
fully-featured Matrix server.
- [`secrets/`](./secrets) contains the secrets that need to get injected into
machine configurations.
- [`services/`](./services) contains our effort to make Fediverse applications
work seemlessly together in our specific setting.
- [`website/`](./website) contains the framework and the content of [the
Fediversity website](https://fediversity.eu/)

1431
flake.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,21 +1,14 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11";
flake-parts.url = "github:hercules-ci/flake-parts";
git-hooks.url = "github:cachix/git-hooks.nix";
home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
agenix.url = "github:ryantm/agenix";
disko.url = "github:nix-community/disko";
nixops4.url = "github:nixops4/nixops4";
nixops4-nixos.url = "github:nixops4/nixops4-nixos";
};
outputs =
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
{ self, ... }:
let
sources = import ./npins;
inherit (sources) nixpkgs flake-parts git-hooks;
pkgs = import nixpkgs;
inherit (pkgs) lib;
flake-parts-lib = import "${flake-parts}/lib.nix" { inherit lib; };
in
flake-parts-lib.mkFlake { inherit self; } {
systems = [
"x86_64-linux"
"aarch64-linux"
@ -24,9 +17,7 @@
];
imports = [
inputs.git-hooks.flakeModule
inputs.nixops4.modules.flake.default
(import "${git-hooks}/flake-module.nix")
./infra/flake-part.nix
./services/flake-part.nix
];
@ -36,7 +27,6 @@
config,
pkgs,
lib,
inputs',
...
}:
{
@ -62,14 +52,10 @@
devShells.default = pkgs.mkShell {
packages = [
pkgs.nil
inputs'.agenix.packages.default
(pkgs.callPackage "${agenix}/pkgs/agenix.nix" { })
pkgs.openssh
pkgs.httpie
pkgs.jq
# exposing this env var as a hack to pass info in from form
(inputs'.nixops4.packages.default.overrideAttrs {
impureEnvVars = [ "DEPLOYMENT" ];
})
];
shellHook = config.pre-commit.installationScript;
};

View file

@ -3,11 +3,33 @@
This directory contains the definition of [the VMs](machines.md) that host our
infrastructure.
## requirements
- [nix](https://nix.dev/)
## usage
### development
before using other commands, if not using direnv:
```sh
nix-shell
```
then to initialize, or after updating pins or TF providers:
```sh
setup
```
then, one can use the `tofu` CLI.
## Provisioning VMs with an initial configuration
NOTE[Niols]: This is very manual and clunky. Two things will happen. In the near
future, I will improve the provisioning script to make this a bit less clunky.
In the far future, NixOps4 will be able to communicate with Proxmox directly and
In the future, orchestration will be able to communicate with Proxmox directly and
everything will become much cleaner.
1. Choose names for your VMs. It is recommended to choose `fediXXX`, with `XXX`
@ -15,8 +37,7 @@ everything will become much cleaner.
2. Add a basic configuration for the machine. These typically go in
`infra/machines/<name>/default.nix`. You can look at other `fediXXX` VMs to
find inspiration. You probably do not need a `nixos.module` option at this
point.
find inspiration.
2. Add a file for each of those VM's public keys, eg.
```
@ -59,40 +80,6 @@ everything will become much cleaner.
FIXME: Figure out why the full configuration isn't on the machine at this
point and fix it.
## Updating existing VM configurations
Their configuration can be updated via NixOps4. Run
```sh
nixops4 deployments list
```
to see the available deployments.
This should be done from the root of the repository,
otherwise NixOps4 will fail with something like:
```
nixops4 error: evaluation: error:
… while calling the 'getFlake' builtin
error: path '/nix/store/05nn7krhvi8wkcyl6bsysznlv60g5rrf-source/flake.nix' does not exist, evaluation: error:
… while calling the 'getFlake' builtin
error: path '/nix/store/05nn7krhvi8wkcyl6bsysznlv60g5rrf-source/flake.nix' does not exist
```
Then, given a deployment (eg. `fedi200`), run
```sh
nixops4 apply <deployment>
```
Alternatively, to run the `default` deployment, which contains all the VMs, run
```sh
nixops4 apply
```
## Removing an existing VM
See `infra/proxmox-remove.sh --help`.

22
infra/TODO.md Normal file
View file

@ -0,0 +1,22 @@
# differences
differences between TF modules among JIT services (`launch/`) vs infra:
- TF input variables (initialUser vs [host]domain) [including in triggers]
- for_each (objects containing machines and their stuff)
- nix modules
- nix options
- nix config
- nix config passed in as TF
- own dir with:
- TF config
- TF state
- TF lock
- `setup` process (document running per project)
# todo
what should be done to consolidate these:
- abstract out common TF logic to a separate TF module
- thru nix add as custom provider

View file

@ -93,7 +93,7 @@ in
description = ''
The IP address of the machine, version 4. It will be injected as a
value in `networking.interfaces.eth0`, but it will also be used to
communicate with the machine via NixOps4.
communicate with the machine.
'';
};
@ -118,7 +118,7 @@ in
description = ''
The IP address of the machine, version 6. It will be injected as a
value in `networking.interfaces.eth0`, but it will also be used to
communicate with the machine via NixOps4.
communicate with the machine.
'';
};
@ -141,7 +141,7 @@ in
hostPublicKey = mkOption {
description = ''
The ed25519 host public key of the machine. It is used to filter Age
secrets and only keep the relevant ones, and to feed to NixOps4.
secrets and only keep the relevant ones, and to feed to TF.
'';
};

View file

@ -1,64 +0,0 @@
{
inputs,
lib,
config,
...
}:
let
inherit (lib) attrValues elem mkDefault;
inherit (lib.attrsets) concatMapAttrs optionalAttrs;
inherit (lib.strings) removeSuffix;
secretsPrefix = ../../secrets;
secrets = import (secretsPrefix + "/secrets.nix");
keys = import ../../keys;
in
{
imports = [ ./options.nix ];
fediversityVm.hostPublicKey = mkDefault keys.systems.${config.fediversityVm.name};
ssh = {
host = config.fediversityVm.ipv4.address;
hostPublicKey = config.fediversityVm.hostPublicKey;
};
nixpkgs = inputs.nixpkgs;
## The configuration of the machine. We strive to keep in this file only the
## options that really need to be injected from the resource. Everything else
## should go into the `./nixos` subdirectory.
nixos.module = {
imports = [
inputs.agenix.nixosModules.default
inputs.disko.nixosModules.default
inputs.home-manager.nixosModules.home-manager
./options.nix
./nixos
];
## Inject the shared options from the resource's `config` into the NixOS
## configuration.
fediversityVm = config.fediversityVm;
## Read all the secrets, filter the ones that are supposed to be readable
## with this host's public key, and add them correctly to the configuration
## as `age.secrets.<name>.file`.
age.secrets = concatMapAttrs (
name: secret:
optionalAttrs (elem config.fediversityVm.hostPublicKey secret.publicKeys) ({
${removeSuffix ".age" name}.file = secretsPrefix + "/${name}";
})
) secrets;
## FIXME: Remove direct root authentication once the NixOps4 NixOS provider
## supports users with password-less sudo.
users.users.root.openssh.authorizedKeys.keys = attrValues keys.contributors ++ [
# allow our panel vm access to the test machines
keys.panel
];
};
}

33
infra/default.nix Normal file
View file

@ -0,0 +1,33 @@
{
system ? builtins.currentSystem,
sources ? import ../npins,
pkgs ? import sources.nixpkgs { inherit system; },
}:
let
inherit (pkgs) lib;
setup = pkgs.writeScriptBin "setup" ''
echo '${lib.strings.toJSON sources}' > .npins.json
rm -rf .terraform/
tofu init
'';
in
{
# shell for testing TF directly
shell = pkgs.mkShellNoCC {
packages = [
(import ./../launch/tf.nix { inherit lib pkgs; })
pkgs.jaq
setup
];
};
tests = pkgs.callPackage ./tests.nix { };
# re-export inputs so they can be overridden granularly
# (they can't be accessed from the outside any other way)
inherit
sources
system
pkgs
;
}

View file

@ -1,116 +1,3 @@
{
inputs,
lib,
...
}:
let
inherit (builtins) readDir;
inherit (lib)
attrNames
mkOption
evalModules
filterAttrs
;
inherit (lib.attrsets) genAttrs;
## Given a machine's name, make a resource module,
## except for its missing provider. (Depending on the use of that resource, we
## will provide a different one.)
makeResourceModule =
{ vmName }:
{
_module.args = { inherit inputs; };
imports = [
./common/resource.nix
./machines/${vmName}
];
fediversityVm.name = vmName;
};
## Given a list of machine names, make a deployment with those machines'
## configurations as resources.
makeDeployment =
vmNames:
{ providers, ... }:
{
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;
})
];
});
};
makeDeployment' = vmName: makeDeployment [ vmName ];
nixops4ResourceNixosMockOptions = {
## NOTE: We allow the use of a few options from
## `inputs.nixops4-nixos.modules.nixops4Resource.nixos` such that we can
## reuse modules that make use of them.
##
## REVIEW: We can probably do much better and cleaner. On the other hand,
## this is only needed to expose NixOS configurations for provisioning
## purposes, and eventually all of this should be handled by NixOps4.
options = {
nixos.module = mkOption { }; # NOTE: not just `nixos` otherwise merging will go wrong
nixpkgs = mkOption { };
ssh = mkOption { };
};
};
makeResourceConfig =
vm:
(evalModules {
modules = [
nixops4ResourceNixosMockOptions
(makeResourceModule vm)
];
}).config;
## Given a VM name, make a NixOS configuration for this machine.
makeConfiguration =
vmName:
inputs.nixpkgs.lib.nixosSystem {
modules = [
(makeResourceConfig { inherit vmName; }).nixos.module
];
};
makeVmOptions = vmName: {
inherit ((makeResourceConfig { inherit vmName; }).fediversityVm)
proxmox
vmId
description
sockets
cores
memory
diskSize
hostPublicKey
unsafeHostPrivateKey
;
};
listSubdirectories = path: attrNames (filterAttrs (_: type: type == "directory") (readDir path));
machines = listSubdirectories ./machines;
in
{
_: {
flake.lib.makeInstallerIso = import ./makeInstallerIso.nix;
## - Each machine gets a NixOS configuration.
## - Each machine gets a VM options entry.
## - Each machine gets a deployment.
## - We add a “default” deployment with all infra machines.
nixops4Deployments = genAttrs machines makeDeployment' // {
default = makeDeployment machines;
};
flake.nixosConfigurations = genAttrs machines makeConfiguration;
flake.vmOptions = genAttrs machines makeVmOptions;
}

View file

@ -0,0 +1,2 @@
_: {
}

View file

@ -14,10 +14,4 @@
gateway = "2a00:51c0:13:1305::1";
};
};
nixos.module = {
imports = [
./fedipanel.nix
];
};
}

View file

@ -1,3 +1,4 @@
{ lib, ... }:
{
fediversityVm = {
vmId = 2116;
@ -8,31 +9,23 @@
ipv6.address = "2a00:51c0:12:1201::20";
};
nixos.module =
{ lib, ... }:
{
imports = [
./forgejo.nix
];
## vm02116 is running on old hardware based on a Xen VM environment, so it
## needs these extra options. Once the VM gets moved to a newer node, these
## two options can safely be removed.
boot.initrd.availableKernelModules = [ "xen_blkfront" ];
services.xe-guest-utilities.enable = true;
## vm02116 is running on old hardware based on a Xen VM environment, so it
## needs these extra options. Once the VM gets moved to a newer node, these
## two options can safely be removed.
boot.initrd.availableKernelModules = [ "xen_blkfront" ];
services.xe-guest-utilities.enable = true;
## NOTE: This VM was created manually, which requires us to override the
## default disko-based `fileSystems` definition.
fileSystems = lib.mkForce {
"/" = {
device = "/dev/disk/by-uuid/3802a66d-e31a-4650-86f3-b51b11918853";
fsType = "ext4";
};
"/boot" = {
device = "/dev/disk/by-uuid/2CE2-1173";
fsType = "vfat";
};
};
## NOTE: This VM was created manually, which requires us to override the
## default disko-based `fileSystems` definition.
fileSystems = lib.mkForce {
"/" = {
device = "/dev/disk/by-uuid/3802a66d-e31a-4650-86f3-b51b11918853";
fsType = "ext4";
};
"/boot" = {
device = "/dev/disk/by-uuid/2CE2-1173";
fsType = "vfat";
};
};
}

View file

@ -1,3 +1,4 @@
{ lib, ... }:
{
fediversityVm = {
vmId = 2187;
@ -8,29 +9,21 @@
ipv6.address = "2a00:51c0:12:1201::187";
};
nixos.module =
{ lib, ... }:
{
imports = [
./wiki.nix
];
## NOTE: This VM was created manually, which requires us to override the
## default disko-based `fileSystems` definition.
fileSystems = lib.mkForce {
"/" = {
device = "/dev/disk/by-uuid/a46a9c46-e32b-4216-a4aa-8819b2cd0d49";
fsType = "ext4";
};
"/boot" = {
device = "/dev/disk/by-uuid/6AB5-4FA8";
fsType = "vfat";
options = [
"fmask=0022"
"dmask=0022"
];
};
};
## NOTE: This VM was created manually, which requires us to override the
## default disko-based `fileSystems` definition.
fileSystems = lib.mkForce {
"/" = {
device = "/dev/disk/by-uuid/a46a9c46-e32b-4216-a4aa-8819b2cd0d49";
fsType = "ext4";
};
"/boot" = {
device = "/dev/disk/by-uuid/6AB5-4FA8";
fsType = "vfat";
options = [
"fmask=0022"
"dmask=0022"
];
};
};
}

123
infra/main.tf Normal file
View file

@ -0,0 +1,123 @@
locals {
system = "x86_64-linux"
# dependency paths pre-calculated from npins
pins = jsondecode(file("${path.root}/.npins.json"))
# nix path: expose pins, use nixpkgs in flake commands (`nix run`)
nix_path = "${join(":", [for name, path in local.pins : "${name}=${path}"])}:flake=${local.pins["nixpkgs"]}:flake"
}
# 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" {
for_each = {
dns = "fedi200"
demo = "fedi201"
wiki = "vm02187"
forgejo = "vm02116"
}
# 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.domain,
local.system,
each.key,
each.value,
]
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.
# note that absolute paths can cause false positives in triggers,
# so are generally discouraged in TF.
working_dir = path.root
environment = {
# nix path used on build, lets us refer to e.g. nixpkgs like `<nixpkgs>`
NIX_PATH = local.nix_path
}
# TODO: refactor back to command="ignoreme" interpreter=concat([]) to protect sensitive data from error logs?
# TODO: build on target?
command = <<-EOF
set -euo pipefail
# INSTANTIATE
command=(
nix-instantiate
--expr
'let
os = import <nixpkgs/nixos> {
system = "${local.system}";
configuration = {
# note interpolations here TF ones
imports = [
# shared NixOS config
${path.root}/../launch/shared.nix
# FIXME: separate template options by service
${path.root}/options.nix
# FIXME: get VM details from TF
${path.root}/machines/${each.value}
# for service `forgejo` import `forgejo.nix`
${path.root}/machines/${each.value}/${each.key}.nix
];
# nix path for debugging
nix.nixPath = [ "${local.nix_path}" ];
} //
# template parameters passed in from TF thru json
builtins.fromJSON "${replace(jsonencode({
terraform = {
domain = var.domain
hostname = each.value
}
}), "\"", "\\\"")}";
};
in
# info we want to get back out
{
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;
}'
)
# instantiate the config in /nix/store
"$${command[@]}" -A out_path
# get the other info
json="$("$${command[@]}" --eval --strict --json)"
# DEPLOY
declare substituters trusted_public_keys drv_path
# set our variables using the json object
eval "export $(echo $json | jaq -r 'to_entries | map("\(.key)=\(.value)") | @sh')"
host="root@${each.value}.${var.domain}" # FIXME: #24
buildArgs=(
--option extra-binary-caches https://cache.nixos.org/
--option substituters $substituters
--option trusted-public-keys $trusted_public_keys
)
sshOpts=(
-o BatchMode=yes
-o StrictHostKeyChecking=no
)
# get the realized derivation to deploy
outPath=$(nix-store --realize "$drv_path" "$${buildArgs[@]}")
# deploy the config by nix-copy-closure
NIX_SSHOPTS="$${sshOpts[*]}" nix-copy-closure --to "$host" "$outPath" --gzip --use-substitutes
# 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"
EOF
}
}

28
infra/options.nix Normal file
View file

@ -0,0 +1,28 @@
# TODO: could (part of) this be generated somehow? c.f #275
{
lib,
...
}:
let
inherit (lib) types mkOption;
inherit (types) str enum;
in
{
options.terraform = {
domain = mkOption {
type = enum [
"fediversity.net"
];
description = ''
Apex domain under which the services will be deployed.
'';
default = "fediversity.net";
};
hostname = mkOption {
type = str;
description = ''
Internal name of the host, e.g. test01
'';
};
};
}

View file

@ -4,7 +4,7 @@ let
## and will end up in the Nix store. We don't care as they are only ever
## used for testing anyway.
##
## FIXME: Generate and store in NixOps4's state.
## FIXME: Generate and store in state.
mastodonS3KeyConfig =
{ pkgs, ... }:
{

View file

@ -13,7 +13,7 @@ in
enable = true;
## NOTE: Only ever used for testing anyway.
##
## FIXME: Generate and store in NixOps4's state.
## FIXME: Generate and store in state.
secretsFile = pkgs.writeText "secret" "574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24";
};
};

View file

@ -12,6 +12,6 @@ in
mastodon = mastodonS3KeyConfig { inherit pkgs; } // {
enable = true;
};
temp.cores = 1; # FIXME: should come from NixOps4 eventually
temp.cores = 1; # FIXME: should come from TF eventually
};
}

29
infra/tests.nix Normal file
View file

@ -0,0 +1,29 @@
{ lib, pkgs }:
let
defaults = {
virtualisation = {
memorySize = 2048;
cores = 2;
};
};
tf = pkgs.callPackage ./../launch/tf.nix {
inherit lib pkgs;
dir = "infra/";
};
tfEnv = pkgs.callPackage ./../launch/tf-env.nix { };
in
lib.mapAttrs (name: test: pkgs.testers.runNixOSTest (test // { inherit name; })) {
tf-validate = {
inherit defaults;
nodes.server = {
environment.systemPackages = [
tf
tfEnv
];
};
testScript = ''
server.wait_for_unit("multi-user.target")
server.succeed("${lib.getExe tf} -chdir='${tfEnv}/infra' validate")
'';
};
}

4
infra/variables.tf Normal file
View file

@ -0,0 +1,4 @@
variable "domain" {
type = string
default = "abundos.eu"
}

View file

@ -14,7 +14,7 @@ overwrite a secret without knowing its contents.)
In infra management, the systems' keys are used for security reasons; they
identify the machine that we are talking to. The contributor keys are used to
give access to the `root` user on these machines, which allows, among other
things, to deploy their configurations with NixOps4.
things, to deploy their configurations.
## Adding a contributor

7
launch/.gitignore vendored
View file

@ -1,7 +0,0 @@
# generated
.auto.tfvars.json
.npins.json
.terraform/
.terraform.lock.hcl
.terraform.tfstate.lock.info
terraform.tfstate*

View file

@ -22,6 +22,8 @@ then to initialize, or after updating pins or TF providers:
setup
```
then, one can use the `tofu` CLI.
## implementing
proper documentation TODO.

View file

@ -1,19 +1,13 @@
{
system ? builtins.currentSystem,
sources ? import ../npins,
# match the same versions we deploy locally
inputs ? import sources.flake-inputs {
root = ../.;
},
# match the same version of opentofu that is deployed by the root flake
pkgs ? import inputs.nixpkgs {
inherit system;
},
pkgs ? import sources.nixpkgs { inherit system; },
}:
let
inherit (pkgs) lib;
setup = pkgs.writeScriptBin "setup" ''
echo '${lib.strings.toJSON sources}' > .npins.json
rm -f .terraform.lock.hcl
rm -rf .terraform/
tofu init
'';

View file

@ -5,7 +5,7 @@
}:
let
inherit (lib) attrValues elem mkDefault;
inherit (lib) elem mkDefault;
inherit (lib.attrsets) concatMapAttrs optionalAttrs;
inherit (lib.strings) removeSuffix;
@ -34,10 +34,4 @@ in
${removeSuffix ".age" name}.file = secretsPrefix + "/${name}";
}
) secrets;
## FIXME: switch root authentication to users with password-less sudo, see #24
users.users.root.openssh.authorizedKeys.keys = attrValues keys.contributors ++ [
# allow our panel vm access to the test machines
keys.panel
];
}

View file

@ -7,7 +7,10 @@ let
};
};
tf = pkgs.callPackage ./tf.nix { };
tfEnv = pkgs.callPackage ./tf-env.nix { };
tfEnv = pkgs.callPackage ./tf-env.nix {
inherit lib pkgs;
dir = "launch/";
};
in
lib.mapAttrs (name: test: pkgs.testers.runNixOSTest (test // { inherit name; })) {
tf-validate = {

View file

@ -1,6 +1,7 @@
{
lib,
pkgs,
path,
sources ? import ../npins,
...
}:
@ -18,7 +19,7 @@ pkgs.stdenv.mkDerivation {
];
buildPhase = ''
runHook preBuild
pushd launch/
pushd ${path}
# calculated pins
echo '${lib.strings.toJSON sources}' > .npins.json
# generate TF lock for nix's TF providers

View file

@ -42,6 +42,32 @@
"url": "https://github.com/fricklerhandwerk/flake-inputs/archive/559574c9cbb8af262f3944b67d60fbf0f6ad03c3.tar.gz",
"hash": "0gbhmp6x2vdzvfnsvqzal3g8f8hx2ia6r73aibc78kazf78m67x6"
},
"flake-parts": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "hercules-ci",
"repo": "flake-parts"
},
"branch": "main",
"submodules": false,
"revision": "c621e8422220273271f52058f618c94e405bb0f5",
"url": "https://github.com/hercules-ci/flake-parts/archive/c621e8422220273271f52058f618c94e405bb0f5.tar.gz",
"hash": "09j2dafd75ydlcw8v48vcpfm2mw0j6cs8286x2hha2lr08d232w4"
},
"git-hooks": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "cachix",
"repo": "git-hooks.nix"
},
"branch": "master",
"submodules": false,
"revision": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
"url": "https://github.com/cachix/git-hooks.nix/archive/dcf5072734cb576d2b0c59b2ac44f5050b5eac82.tar.gz",
"hash": "1jmdxmx29xghjiaks6f5amnxld8w3kmxb2zv8lk2yzpgp6kr60qg"
},
"htmx": {
"type": "GitRelease",
"repository": {

View file

@ -29,7 +29,10 @@ let
((pkgs.formats.pythonVars { }).generate "settings.py" cfg.settings)
(builtins.toFile "extra-settings.py" cfg.extra-settings)
];
REPO_DIR = import ../../launch/tf-env.nix { inherit lib pkgs; };
REPO_DIR = import ../../launch/tf-env.nix {
inherit lib pkgs;
dir = "launch/";
};
};
python-environment = pkgs.python3.withPackages (

View file

@ -60,7 +60,12 @@ python3.pkgs.buildPythonPackage {
cp -v ${src}/manage.py $out/bin/manage.py
chmod +x $out/bin/manage.py
wrapProgram $out/bin/manage.py \
--set REPO_DIR "${import ../../launch/tf-env.nix { inherit lib pkgs; }}" \
--set REPO_DIR "${
import ../../launch/tf-env.nix {
inherit lib pkgs;
dir = "launch/";
}
}" \
--prefix PYTHONPATH : "$PYTHONPATH"
cp ${sources.htmx}/dist/htmx.min.js* $out/${python3.sitePackages}/panel/static/
'';

View file

@ -241,6 +241,6 @@ if user_settings_file is not None:
# PATH to expose to launch button
bin_path=env['BIN_PATH']
# path of the root flake to trigger nixops from, see #94.
# path of the root flake to deploy from
# to deploy this should be specified, for dev just use a relative path.
repo_dir = env["REPO_DIR"]

View file

@ -22,7 +22,7 @@ As an example, let us add a secret in a file “cheeses” whose content should
extension); this will open your `$EDITOR` ; enter “best ones come
unpasteurised”, save and close.
3. If you are doing something flake-related such as NixOps4, remember to commit
3. If you are doing something flake-related, remember to commit
or at least stage the secret.
4. In the machine's configuration, load our `ageSecrets` NixOS module, declare the machine's host key and start using your secrets, eg.:

View file

@ -31,7 +31,7 @@ in
type = types.submodule {
options = {
cores = mkOption {
description = "number of cores; should be obtained from NixOps4";
description = "number of cores; should be obtained from TF";
type = types.int;
};

View file

@ -20,7 +20,7 @@ in
description = ''
Internal option change at your own risk
FIXME: should it be provided by NixOps4?
FIXME: should it be provided by TF?
or maybe we should just ask for a main secret from which to derive all the others?
'';
};