forked from fediversity/fediversity
move stuff around, utterly untested
This commit is contained in:
parent
0919db08f7
commit
7b985c0b81
87 changed files with 353 additions and 506 deletions
|
|
@ -13,13 +13,13 @@ jobs:
|
|||
runs-on: native
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: nix build .#checks.x86_64-linux.pre-commit -L
|
||||
- run: nix-build -A tests
|
||||
|
||||
check-peertube:
|
||||
check-services:
|
||||
runs-on: native
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: nix build .#checks.x86_64-linux.peertube -L
|
||||
- run: cd services && nix-build -A tests
|
||||
|
||||
check-panel:
|
||||
runs-on: native
|
||||
|
|
|
|||
52
default.nix
Normal file
52
default.nix
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
system ? builtins.currentSystem,
|
||||
sources ? import ./npins,
|
||||
pkgs ? import sources.nixpkgs { inherit system; },
|
||||
}:
|
||||
let
|
||||
inherit (sources) nixpkgs git-hooks gitignore;
|
||||
inherit (pkgs) lib;
|
||||
pre-commit-check =
|
||||
(import "${git-hooks}/nix" {
|
||||
inherit nixpkgs system;
|
||||
gitignore-nix-src = gitignore;
|
||||
}).run
|
||||
{
|
||||
src = ./.;
|
||||
hooks =
|
||||
let
|
||||
## Add a directory here if pre-commit hooks shouldn't apply to it.
|
||||
optout = [
|
||||
"npins"
|
||||
"**/.terraform"
|
||||
];
|
||||
excludes = map (dir: "^${dir}/") optout;
|
||||
addExcludes = lib.mapAttrs (_: c: c // { inherit excludes; });
|
||||
in
|
||||
addExcludes {
|
||||
nixfmt-rfc-style.enable = true;
|
||||
deadnix.enable = true;
|
||||
trim-trailing-whitespace.enable = true;
|
||||
shellcheck.enable = true;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
# shell for testing TF directly
|
||||
shell = pkgs.mkShellNoCC {
|
||||
inherit (pre-commit-check) shellHook;
|
||||
buildInputs = pre-commit-check.enabledPackages;
|
||||
};
|
||||
|
||||
tests = {
|
||||
inherit pre-commit-check;
|
||||
};
|
||||
|
||||
# re-export inputs so they can be overridden granularly
|
||||
# (they can't be accessed from the outside any other way)
|
||||
inherit
|
||||
sources
|
||||
system
|
||||
pkgs
|
||||
;
|
||||
}
|
||||
64
flake.nix
64
flake.nix
|
|
@ -1,64 +0,0 @@
|
|||
{
|
||||
outputs =
|
||||
{ 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"
|
||||
"x86_64-darwin"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
|
||||
imports = [
|
||||
(import "${git-hooks}/flake-module.nix")
|
||||
./infra/flake-part.nix
|
||||
./services/flake-part.nix
|
||||
];
|
||||
|
||||
perSystem =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
formatter = pkgs.nixfmt-rfc-style;
|
||||
|
||||
pre-commit.settings.hooks =
|
||||
let
|
||||
## Add a directory here if pre-commit hooks shouldn't apply to it.
|
||||
optout = [
|
||||
"npins"
|
||||
"launch/.terraform"
|
||||
];
|
||||
excludes = map (dir: "^${dir}/") optout;
|
||||
addExcludes = lib.mapAttrs (_: c: c // { inherit excludes; });
|
||||
in
|
||||
addExcludes {
|
||||
nixfmt-rfc-style.enable = true;
|
||||
deadnix.enable = true;
|
||||
trim-trailing-whitespace.enable = true;
|
||||
shellcheck.enable = true;
|
||||
};
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = [
|
||||
pkgs.nil
|
||||
(pkgs.callPackage "${agenix}/pkgs/agenix.nix" { })
|
||||
pkgs.openssh
|
||||
pkgs.httpie
|
||||
pkgs.jq
|
||||
];
|
||||
shellHook = config.pre-commit.installationScript;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
# Infra
|
||||
# service deployment
|
||||
|
||||
This directory contains the definition of [the VMs](machines.md) that host our
|
||||
infrastructure.
|
||||
deploys [NixOS](https://nixos.org/) templates using [OpenTofu](https://opentofu.org/).
|
||||
|
||||
## requirements
|
||||
|
||||
|
|
@ -25,61 +24,7 @@ setup
|
|||
|
||||
then, one can use the `tofu` CLI.
|
||||
|
||||
## Provisioning VMs with an initial configuration
|
||||
## implementing
|
||||
|
||||
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 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`
|
||||
above 100. For instance, `fedi117`.
|
||||
|
||||
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.
|
||||
|
||||
2. Add a file for each of those VM's public keys, eg.
|
||||
```
|
||||
touch keys/systems/fedi117.pub
|
||||
```
|
||||
Those files need to exist during provisioning, but their content matters only
|
||||
when updating the machines' configuration.
|
||||
|
||||
FIXME: Remove this step by making the provisioning script not fail with the
|
||||
public key does not exist yet.
|
||||
|
||||
3. Run the provisioning script:
|
||||
```
|
||||
sh infra/proxmox-provision.sh fedi117
|
||||
```
|
||||
The script can take several ids at the same time. It requires some
|
||||
authentication options and provides several more. See `--help`.
|
||||
|
||||
4. (Optional) Add a DNS entry for the machine; for instance `fedi117.abundos.eu
|
||||
A 95.215.187.117`.
|
||||
|
||||
5. Grab the public host keys for the machines in question, and add it to the
|
||||
repository. For instance:
|
||||
```
|
||||
ssh fedi117.abundos.eu 'sudo cat /etc/ssh/ssh_host_ed25519_key.pub' > keys/systems/fedi117.pub
|
||||
```
|
||||
|
||||
FIXME: Make the provisioning script do that for us.
|
||||
|
||||
7. Regenerate the list of machines:
|
||||
```
|
||||
sh infra/machines.md.sh
|
||||
```
|
||||
Commit it with the machine's configuration, public key, etc.
|
||||
|
||||
8. At this point, the machine contains a very basic configuration that contains
|
||||
just enough for it to boot and be reachable. Go on to the next section to
|
||||
update the machine and put an actual configuration.
|
||||
|
||||
FIXME: Figure out why the full configuration isn't on the machine at this
|
||||
point and fix it.
|
||||
|
||||
## Removing an existing VM
|
||||
|
||||
See `infra/proxmox-remove.sh --help`.
|
||||
proper documentation TODO.
|
||||
until then, a reference implementation may be found in [`panel/`](https://git.fediversity.eu/Fediversity/Fediversity/src/branch/main/panel).
|
||||
|
|
|
|||
|
|
@ -1,22 +1,19 @@
|
|||
# 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
|
||||
refactor:
|
||||
- account for moves of
|
||||
- machines
|
||||
- proxmox
|
||||
- launch
|
||||
- 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
|
||||
- symlink thru nix
|
||||
|
||||
test:
|
||||
- services tests
|
||||
- root test
|
||||
- root hook
|
||||
- secret shell
|
||||
- ci
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
let
|
||||
inherit (pkgs) lib;
|
||||
setup = pkgs.writeScriptBin "setup" ''
|
||||
echo '${lib.strings.toJSON sources}' > .npins.json
|
||||
echo '${lib.strings.toJSON sources}' > module/.npins.json
|
||||
rm -f .terraform.lock.hcl
|
||||
rm -rf .terraform/
|
||||
tofu init
|
||||
'';
|
||||
|
|
|
|||
41
infra/dev/main.tf
Normal file
41
infra/dev/main.tf
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
module "nixos" {
|
||||
source = "./deploy"
|
||||
|
||||
hostname = each.value.hostname
|
||||
config_nix = each.value.config_nix
|
||||
config_tf = each.value.config_nix
|
||||
|
||||
for_each = { for name, inst in {
|
||||
wiki = "vm02187"
|
||||
forgejo = "vm02116"
|
||||
# TODO: move these to a separate `host` dir
|
||||
dns = "fedi200"
|
||||
demo = "fedi201"
|
||||
} : name => {
|
||||
hostname = inst
|
||||
config_nix = {
|
||||
terraform = {
|
||||
domain = local.vm_domain
|
||||
hostname = inst
|
||||
}
|
||||
}
|
||||
config_nix = <<-EOF
|
||||
{
|
||||
# note interpolations here TF ones
|
||||
imports = [
|
||||
# shared NixOS config
|
||||
${path.root}/../launch/shared.nix
|
||||
# FIXME: separate template options by service
|
||||
${path.root}/options.nix
|
||||
# for service `forgejo` import `forgejo.nix`
|
||||
${path.root}/machines/${inst}/${name}.nix
|
||||
# FIXME: get VM details from TF
|
||||
${path.root}/machines/${inst}
|
||||
];
|
||||
# nix path for debugging
|
||||
nix.nixPath = [ "${local.nix_path}" ];
|
||||
}
|
||||
EOF
|
||||
}
|
||||
}
|
||||
}
|
||||
1
infra/dev/variables.tf
Normal file
1
infra/dev/variables.tf
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
_: {
|
||||
flake.lib.makeInstallerIso = import ./makeInstallerIso.nix;
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
<!-- This file is auto-generated by `machines.md.sh` from the machines'
|
||||
configuration. -->
|
||||
|
||||
# Machines
|
||||
|
||||
Currently, this repository keeps track of the following VMs:
|
||||
|
||||
Machine | Proxmox | Description
|
||||
--------|---------|-------------
|
||||
[`fedi200`](./fedi200) | fediversity | Testing machine for Hans
|
||||
[`fedi201`](./fedi201) | fediversity | FediPanel
|
||||
[`vm02116`](./vm02116) | procolix | Forgejo
|
||||
[`vm02187`](./vm02187) | procolix | Wiki
|
||||
|
||||
This table excludes all machines with names starting with `test`.
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
set -euC
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
{
|
||||
cat <<\EOF
|
||||
<!-- This file is auto-generated by `machines.md.sh` from the machines'
|
||||
configuration. -->
|
||||
|
||||
# Machines
|
||||
|
||||
Currently, this repository keeps track of the following VMs:
|
||||
|
||||
Machine | Proxmox | Description
|
||||
--------|---------|-------------
|
||||
EOF
|
||||
|
||||
vmOptions=$(
|
||||
cd ..
|
||||
nix eval \
|
||||
--impure --raw --expr "
|
||||
builtins.toJSON (builtins.getFlake (builtins.toString ./.)).vmOptions
|
||||
" \
|
||||
--log-format raw --quiet
|
||||
)
|
||||
|
||||
## NOTE: `jq`'s `keys` is alphabetically sorted, just what we want here.
|
||||
for machine in $(echo "$vmOptions" | jq -r 'keys[]'); do
|
||||
if [ "${machine#test}" = "$machine" ]; then
|
||||
proxmox=$(echo "$vmOptions" | jq -r ".$machine.proxmox")
|
||||
description=$(echo "$vmOptions" | jq -r ".$machine.description" | head -n 1)
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
printf '[`%s`](./%s) | %s | %s\n' "$machine" "$machine" "$proxmox" "$description"
|
||||
fi
|
||||
done
|
||||
|
||||
cat <<\EOF
|
||||
|
||||
This table excludes all machines with names starting with `test`.
|
||||
EOF
|
||||
} >| machines.md
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
locals {
|
||||
system = "x86_64-linux"
|
||||
vm_domain = "abundos.eu"
|
||||
# dependency paths pre-calculated from npins
|
||||
pins = jsondecode(file("${path.root}/.npins.json"))
|
||||
pins = jsondecode(file("${path.module}/.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"
|
||||
nix_path = "${join(":", [for name, dir in local.pins : "${name}=${dir}"])}:flake=${local.pins["nixpkgs"]}:flake"
|
||||
}
|
||||
|
||||
# hash of our code directory, used to trigger re-deploy
|
||||
|
|
@ -15,13 +16,6 @@ data "external" "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,
|
||||
|
|
@ -33,15 +27,15 @@ resource "terraform_data" "nixos" {
|
|||
# - `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,
|
||||
var.hostname,
|
||||
var.config_nix,
|
||||
var.config_tf,
|
||||
]
|
||||
|
||||
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.
|
||||
# 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
|
||||
|
|
@ -61,28 +55,14 @@ resource "terraform_data" "nixos" {
|
|||
'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
|
||||
}
|
||||
}), "\"", "\\\"")}";
|
||||
configuration =
|
||||
${var.config_nix} //
|
||||
# template parameters passed in from TF thru json
|
||||
builtins.fromJSON "${replace(jsonencode(var.config_tf), "\"", "\\\"")}" //
|
||||
{
|
||||
# nix path for debugging
|
||||
nix.nixPath = [ "${local.nix_path}" ];
|
||||
};
|
||||
};
|
||||
in
|
||||
# info we want to get back out
|
||||
|
|
@ -102,7 +82,7 @@ resource "terraform_data" "nixos" {
|
|||
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
|
||||
host="root@${var.hostname}.${local.vm_domain}" # FIXME: #24
|
||||
buildArgs=(
|
||||
--option extra-binary-caches https://cache.nixos.org/
|
||||
--option substituters $substituters
|
||||
13
infra/module/variables.tf
Normal file
13
infra/module/variables.tf
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
variable "hostname" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "config_nix" {
|
||||
type = string
|
||||
default = "{}"
|
||||
}
|
||||
|
||||
variable "config_tf" {
|
||||
type = map(any)
|
||||
default = {}
|
||||
}
|
||||
74
infra/operator/main.tf
Normal file
74
infra/operator/main.tf
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
locals {
|
||||
# user-facing applications
|
||||
application_configs = {
|
||||
# FIXME: wrap applications at the interface to grab them in one go?
|
||||
mastodon = {
|
||||
cfg = var.mastodon
|
||||
hostname = "test06"
|
||||
}
|
||||
pixelfed = {
|
||||
cfg = var.pixelfed
|
||||
hostname = "test04"
|
||||
}
|
||||
peertube = {
|
||||
cfg = var.peertube
|
||||
hostname = "test05"
|
||||
}
|
||||
}
|
||||
# services shared between applications
|
||||
peripherals = { for name, inst in {
|
||||
garage = "test01"
|
||||
} : name => {
|
||||
hostname = inst
|
||||
cfg = {
|
||||
# enable if any user applications are enabled
|
||||
enable = anytrue([for _, app in local.application_configs: app.cfg.enable])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module "nixos" {
|
||||
source = "../infra/deploy"
|
||||
|
||||
hostname = each.value.hostname
|
||||
config_nix = each.value.config_nix
|
||||
config_tf = each.value.config_nix
|
||||
|
||||
for_each = {for name, inst in merge(
|
||||
local.peripherals,
|
||||
local.application_configs,
|
||||
) : name => merge(inst, {
|
||||
config_nix = {
|
||||
terraform = {
|
||||
domain = local.vm_domain
|
||||
hostname = inst.hostname
|
||||
initialUser = var.initialUser
|
||||
}
|
||||
}
|
||||
config_nix = <<-EOF
|
||||
{
|
||||
# note interpolations here TF ones
|
||||
imports = [
|
||||
# shared NixOS config
|
||||
${path.root}/shared.nix
|
||||
# FIXME: separate template options by service
|
||||
${path.root}/options.nix
|
||||
# for service `mastodon` import `mastodon.nix`
|
||||
${path.root}/${name}.nix
|
||||
# FIXME: get VM details from TF
|
||||
${path.root}/../infra/test-machines/${inst.hostname}
|
||||
];
|
||||
# nix path for debugging
|
||||
nix.nixPath = [ "${local.nix_path}" ];
|
||||
## FIXME: switch root authentication to users with password-less sudo, see #24
|
||||
users.users.root.openssh.authorizedKeys.keys = let
|
||||
keys = import ../keys;
|
||||
in attrValues keys.contributors ++ [
|
||||
# allow our panel vm access to the test machines
|
||||
keys.panel
|
||||
];
|
||||
}
|
||||
EOF
|
||||
}) if inst.cfg.enable}
|
||||
}
|
||||
|
|
@ -6,11 +6,11 @@ let
|
|||
cores = 2;
|
||||
};
|
||||
};
|
||||
tf = pkgs.callPackage ./../launch/tf.nix {
|
||||
tf = pkgs.callPackage ./tf.nix {
|
||||
inherit lib pkgs;
|
||||
dir = "infra/";
|
||||
};
|
||||
tfEnv = pkgs.callPackage ./../launch/tf-env.nix { };
|
||||
tfEnv = pkgs.callPackage ./tf-env.nix { };
|
||||
in
|
||||
lib.mapAttrs (name: test: pkgs.testers.runNixOSTest (test // { inherit name; })) {
|
||||
tf-validate = {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ pkgs.stdenv.mkDerivation {
|
|||
runHook preBuild
|
||||
pushd ${path}
|
||||
# calculated pins
|
||||
echo '${lib.strings.toJSON sources}' > .npins.json
|
||||
echo '${lib.strings.toJSON sources}' > ../infra/deploy.npins.json
|
||||
# generate TF lock for nix's TF providers
|
||||
tofu init -input=false
|
||||
popd
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
variable "domain" {
|
||||
type = string
|
||||
default = "abundos.eu"
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
# service deployment
|
||||
|
||||
deploys [NixOS](https://nixos.org/) templates using [OpenTofu](https://opentofu.org/).
|
||||
|
||||
## 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.
|
||||
|
||||
## implementing
|
||||
|
||||
proper documentation TODO.
|
||||
until then, a reference implementation may be found in [`panel/`](https://git.fediversity.eu/Fediversity/Fediversity/src/branch/main/panel).
|
||||
159
launch/main.tf
159
launch/main.tf
|
|
@ -1,159 +0,0 @@
|
|||
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"
|
||||
# user-facing applications
|
||||
application_configs = {
|
||||
# FIXME: wrap applications at the interface to grab them in one go?
|
||||
mastodon = {
|
||||
cfg = var.mastodon
|
||||
hostname = "test06"
|
||||
}
|
||||
pixelfed = {
|
||||
cfg = var.pixelfed
|
||||
hostname = "test04"
|
||||
}
|
||||
peertube = {
|
||||
cfg = var.peertube
|
||||
hostname = "test05"
|
||||
}
|
||||
}
|
||||
# services shared between applications
|
||||
peripherals = { for name, inst in {
|
||||
garage = "test01"
|
||||
} : name => {
|
||||
hostname = inst
|
||||
cfg = {
|
||||
# enable if any user applications are enabled
|
||||
enable = anytrue([for _, app in local.application_configs: app.cfg.enable])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# hash of our code directory, used in dev to trigger re-deploy
|
||||
# FIXME settle for pwd when in /nix/store?
|
||||
# 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 = {for name, inst in merge(
|
||||
local.peripherals,
|
||||
local.application_configs,
|
||||
) : name => inst if inst.cfg.enable}
|
||||
|
||||
# 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,
|
||||
var.initialUser,
|
||||
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}/shared.nix
|
||||
# FIXME: separate template options by service
|
||||
${path.root}/options.nix
|
||||
# for service `mastodon` import `mastodon.nix`
|
||||
${path.root}/${each.key}.nix
|
||||
# FIXME: get VM details from TF
|
||||
${path.root}/../infra/test-machines/${each.value.hostname}
|
||||
];
|
||||
# nix path for debugging
|
||||
nix.nixPath = [ "${local.nix_path}" ];
|
||||
## FIXME: switch root authentication to users with password-less sudo, see #24
|
||||
users.users.root.openssh.authorizedKeys.keys = let
|
||||
keys = import ../keys;
|
||||
in attrValues keys.contributors ++ [
|
||||
# allow our panel vm access to the test machines
|
||||
keys.panel
|
||||
];
|
||||
} //
|
||||
# template parameters passed in from TF thru json
|
||||
builtins.fromJSON "${replace(jsonencode({
|
||||
terraform = {
|
||||
domain = var.domain
|
||||
hostname = each.value.hostname
|
||||
initialUser = var.initialUser
|
||||
}
|
||||
}), "\"", "\\\"")}";
|
||||
};
|
||||
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')"
|
||||
# FIXME: de-hardcode domain
|
||||
host="root@${each.value.hostname}.abundos.eu" # 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
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
{ lib, pkgs }:
|
||||
let
|
||||
defaults = {
|
||||
virtualisation = {
|
||||
memorySize = 2048;
|
||||
cores = 2;
|
||||
};
|
||||
};
|
||||
tf = pkgs.callPackage ./tf.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 = {
|
||||
inherit defaults;
|
||||
nodes.server = {
|
||||
environment.systemPackages = [
|
||||
tf
|
||||
tfEnv
|
||||
];
|
||||
};
|
||||
testScript = ''
|
||||
server.wait_for_unit("multi-user.target")
|
||||
server.succeed("${lib.getExe tf} -chdir='${tfEnv}/launch' validate")
|
||||
'';
|
||||
};
|
||||
}
|
||||
4
machines/README.md
Normal file
4
machines/README.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Machines
|
||||
|
||||
This directory contains the definition of [the VMs](machines.md) that host our
|
||||
infrastructure.
|
||||
|
|
@ -68,6 +68,19 @@
|
|||
"url": "https://github.com/cachix/git-hooks.nix/archive/dcf5072734cb576d2b0c59b2ac44f5050b5eac82.tar.gz",
|
||||
"hash": "1jmdxmx29xghjiaks6f5amnxld8w3kmxb2zv8lk2yzpgp6kr60qg"
|
||||
},
|
||||
"gitignore": {
|
||||
"type": "Git",
|
||||
"repository": {
|
||||
"type": "GitHub",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix"
|
||||
},
|
||||
"branch": "master",
|
||||
"submodules": false,
|
||||
"revision": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"url": "https://github.com/hercules-ci/gitignore.nix/archive/637db329424fd7e46cf4185293b9cc8c88c95394.tar.gz",
|
||||
"hash": "02wxkdpbhlm3yk5mhkhsp3kwakc16xpmsf2baw57nz1dg459qv8w"
|
||||
},
|
||||
"htmx": {
|
||||
"type": "GitRelease",
|
||||
"repository": {
|
||||
|
|
|
|||
60
proxmox/README.md
Normal file
60
proxmox/README.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# Infra
|
||||
|
||||
## 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 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`
|
||||
above 100. For instance, `fedi117`.
|
||||
|
||||
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.
|
||||
|
||||
2. Add a file for each of those VM's public keys, eg.
|
||||
```
|
||||
touch keys/systems/fedi117.pub
|
||||
```
|
||||
Those files need to exist during provisioning, but their content matters only
|
||||
when updating the machines' configuration.
|
||||
|
||||
FIXME: Remove this step by making the provisioning script not fail with the
|
||||
public key does not exist yet.
|
||||
|
||||
3. Run the provisioning script:
|
||||
```
|
||||
sh infra/proxmox-provision.sh fedi117
|
||||
```
|
||||
The script can take several ids at the same time. It requires some
|
||||
authentication options and provides several more. See `--help`.
|
||||
|
||||
4. (Optional) Add a DNS entry for the machine; for instance `fedi117.abundos.eu
|
||||
A 95.215.187.117`.
|
||||
|
||||
5. Grab the public host keys for the machines in question, and add it to the
|
||||
repository. For instance:
|
||||
```
|
||||
ssh fedi117.abundos.eu 'sudo cat /etc/ssh/ssh_host_ed25519_key.pub' > keys/systems/fedi117.pub
|
||||
```
|
||||
|
||||
FIXME: Make the provisioning script do that for us.
|
||||
|
||||
7. Regenerate the list of machines:
|
||||
```
|
||||
sh infra/machines.md.sh
|
||||
```
|
||||
Commit it with the machine's configuration, public key, etc.
|
||||
|
||||
8. At this point, the machine contains a very basic configuration that contains
|
||||
just enough for it to boot and be reachable. Go on to the next section to
|
||||
update the machine and put an actual configuration.
|
||||
|
||||
FIXME: Figure out why the full configuration isn't on the machine at this
|
||||
point and fix it.
|
||||
|
||||
## Removing an existing VM
|
||||
|
||||
See `infra/proxmox-remove.sh --help`.
|
||||
23
proxmox/default.nix
Normal file
23
proxmox/default.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
system ? builtins.currentSystem,
|
||||
sources ? import ../npins,
|
||||
pkgs ? import sources.nixpkgs { inherit system; },
|
||||
}:
|
||||
{
|
||||
# shell for testing TF directly
|
||||
shell = pkgs.mkShellNoCC {
|
||||
packages = [
|
||||
pkgs.openssh
|
||||
pkgs.httpie
|
||||
pkgs.jq
|
||||
];
|
||||
};
|
||||
|
||||
# re-export inputs so they can be overridden granularly
|
||||
# (they can't be accessed from the outside any other way)
|
||||
inherit
|
||||
sources
|
||||
system
|
||||
pkgs
|
||||
;
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@ let
|
|||
|
||||
installer =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
|
|
@ -228,8 +228,7 @@ build_iso () {
|
|||
|
||||
nix build \
|
||||
--impure --expr "
|
||||
let flake = builtins.getFlake (builtins.toString ./.); in
|
||||
flake.lib.makeInstallerIso {
|
||||
import ./makeInstallerIso.nix {
|
||||
nixosConfiguration = flake.nixosConfigurations.$vm_name;
|
||||
nixpkgs = flake.inputs.nixpkgs;
|
||||
$nix_host_keys
|
||||
|
|
@ -4,26 +4,16 @@
|
|||
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
|
||||
'';
|
||||
inherit (sources) agenix;
|
||||
in
|
||||
{
|
||||
# shell for testing TF directly
|
||||
shell = pkgs.mkShellNoCC {
|
||||
packages = [
|
||||
(import ./tf.nix { inherit lib pkgs; })
|
||||
pkgs.jaq
|
||||
setup
|
||||
(pkgs.callPackage "${agenix}/pkgs/agenix.nix" { })
|
||||
];
|
||||
};
|
||||
|
||||
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
|
||||
1
secrets/shell.nix
Normal file
1
secrets/shell.nix
Normal file
|
|
@ -0,0 +1 @@
|
|||
(import ./. { }).shell
|
||||
15
services/default.nix
Normal file
15
services/default.nix
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
system ? builtins.currentSystem,
|
||||
sources ? import ../npins,
|
||||
pkgs ? import sources.nixpkgs {
|
||||
inherit system;
|
||||
},
|
||||
}:
|
||||
let
|
||||
inherit (pkgs) lib;
|
||||
in
|
||||
lib.mapAttrs (name: test: pkgs.testers.runNixOSTest (test // { inherit name; })) {
|
||||
mastodon = import ./tests/mastodon.nix { inherit pkgs; };
|
||||
pixelfed-garage = import ./tests/pixelfed-garage.nix { inherit pkgs; };
|
||||
peertube = import ./tests/peertube.nix { inherit pkgs; };
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
{ self, ... }:
|
||||
|
||||
{
|
||||
flake.nixosModules.fediversity = import ./fediversity;
|
||||
|
||||
perSystem =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
checks = {
|
||||
mastodon = import ./tests/mastodon.nix { inherit self pkgs; };
|
||||
pixelfed-garage = import ./tests/pixelfed-garage.nix { inherit self pkgs; };
|
||||
peertube = import ./tests/peertube.nix { inherit self pkgs; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
## NOTE: This test will fail for Mastodon < 4.3 because of
|
||||
## https://github.com/mastodon/mastodon/issues/31145
|
||||
|
||||
{ pkgs, self }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
|
|
@ -50,8 +50,8 @@ pkgs.nixosTest {
|
|||
{ config, ... }:
|
||||
{
|
||||
virtualisation.memorySize = lib.mkVMOverride 4096;
|
||||
imports = with self.nixosModules; [
|
||||
fediversity
|
||||
imports = [
|
||||
../fediversity
|
||||
../vm/garage-vm.nix
|
||||
../vm/mastodon-vm.nix
|
||||
../vm/interactive-vm.nix
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
## This file is a basic test of Peertube functionalities.
|
||||
|
||||
{ pkgs, self }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
|
|
@ -168,8 +168,8 @@ pkgs.nixosTest {
|
|||
server =
|
||||
{ config, ... }:
|
||||
{
|
||||
imports = with self.nixosModules; [
|
||||
fediversity
|
||||
imports = [
|
||||
../fediversity
|
||||
../vm/garage-vm.nix
|
||||
../vm/peertube-vm.nix
|
||||
../vm/interactive-vm.nix
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{ pkgs, self }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
|
|
@ -143,8 +143,8 @@ pkgs.nixosTest {
|
|||
memorySize = lib.mkVMOverride 8192;
|
||||
cores = 8;
|
||||
};
|
||||
imports = with self.nixosModules; [
|
||||
fediversity
|
||||
imports = [
|
||||
../fediversity
|
||||
../vm/garage-vm.nix
|
||||
../vm/pixelfed-vm.nix
|
||||
];
|
||||
|
|
|
|||
1
shell.nix
Normal file
1
shell.nix
Normal file
|
|
@ -0,0 +1 @@
|
|||
(import ./. { }).shell
|
||||
Loading…
Add table
Reference in a new issue