Compare commits

...

5 commits

Author SHA1 Message Date
a0fb9920ba
moar extraDependencies 2025-07-03 15:04:13 +02:00
c2a45d5c14
[wip] handling env file (still fails)
rm unused dep nix-templating

fix imports
2025-07-03 15:04:13 +02:00
10cca18706
use templating fork 2025-07-03 15:03:14 +02:00
895e525728
add tests, fix some things
upgrade memory to resolve oom
2025-07-03 15:03:14 +02:00
554336f9ba
move from dev to operator
revert

add qemu import
2025-07-03 15:02:22 +02:00
15 changed files with 178 additions and 86 deletions

View file

@ -14,6 +14,7 @@ let
"mastodon"
"peertube"
"pixelfed"
"attic"
];
pathToRoot = /. + (builtins.unsafeDiscardStringContext self);
pathFromRoot = ./.;

View file

@ -25,6 +25,8 @@ in
peertube.inputDerivation
gixy
gixy.inputDerivation
shellcheck
shellcheck.inputDerivation
];
system.extraDependenciesFromModule = {
@ -48,6 +50,11 @@ in
s3AccessKeyFile = dummyFile;
s3SecretKeyFile = dummyFile;
};
attic = {
enable = true;
s3AccessKeyFile = dummyFile;
s3SecretKeyFile = dummyFile;
};
temp.cores = 1;
temp.initialUser = {
username = "dummy";
@ -72,6 +79,7 @@ in
nodes.mastodon.virtualisation.memorySize = 4 * 1024;
nodes.pixelfed.virtualisation.memorySize = 4 * 1024;
nodes.peertube.virtualisation.memorySize = 5 * 1024;
nodes.attic.virtualisation.memorySize = 2 * 1024;
## FIXME: The test of presence of the services are very simple: we only
## check that there is a systemd service of the expected name on the
@ -86,6 +94,7 @@ in
mastodon.fail("systemctl status mastodon-web.service")
peertube.fail("systemctl status peertube.service")
pixelfed.fail("systemctl status phpfpm-pixelfed.service")
attic.fail("systemctl status atticd.service")
with subtest("Run deployment with no services enabled"):
deployer.succeed("nixops4 apply check-deployment-cli-nothing --show-trace --no-interactive 1>&2")
@ -95,6 +104,7 @@ in
mastodon.fail("systemctl status mastodon-web.service")
peertube.fail("systemctl status peertube.service")
pixelfed.fail("systemctl status phpfpm-pixelfed.service")
attic.fail("systemctl status atticd.service")
with subtest("Run deployment with Mastodon and Pixelfed enabled"):
deployer.succeed("nixops4 apply check-deployment-cli-mastodon-pixelfed --show-trace --no-interactive 1>&2")
@ -104,6 +114,7 @@ in
mastodon.succeed("systemctl status mastodon-web.service")
peertube.fail("systemctl status peertube.service")
pixelfed.succeed("systemctl status phpfpm-pixelfed.service")
attic.fail("systemctl status atticd.service")
with subtest("Run deployment with only Peertube enabled"):
deployer.succeed("nixops4 apply check-deployment-cli-peertube --show-trace --no-interactive 1>&2")
@ -113,5 +124,6 @@ in
mastodon.fail("systemctl status mastodon-web.service")
peertube.succeed("systemctl status peertube.service")
pixelfed.fail("systemctl status phpfpm-pixelfed.service")
attic.fail("systemctl status atticd.service")
'';
}

View file

@ -40,7 +40,7 @@ in
## default. These values have been trimmed down to the gigabyte.
## Memory use is expected to be dominated by the NixOS evaluation,
## which happens on the deployer.
memorySize = 4 * 1024;
memorySize = 5 * 1024;
diskSize = 4 * 1024;
cores = 2;
};
@ -60,7 +60,9 @@ in
"${inputs.nixops4-nixos}"
"${inputs.nixpkgs}"
"${sources.nixpkgs}"
"${sources.flake-inputs}"
"${sources.vars}"
pkgs.stdenv
pkgs.stdenvNoCC

View file

@ -17,6 +17,7 @@ let
"mastodon"
"peertube"
"pixelfed"
"attic"
];
pathToRoot = /. + (builtins.unsafeDiscardStringContext self);
pathFromRoot = ./.;

View file

@ -33,6 +33,7 @@ let
enableMastodon,
enablePeertube,
enablePixelfed,
enableAttic,
}:
hostPkgs.writers.writePython3Bin "interact-with-panel"
{
@ -94,6 +95,7 @@ let
checkbox_set(driver.find_element(By.XPATH, "//input[@name = 'mastodon.enable']"), ${toPythonBool enableMastodon})
checkbox_set(driver.find_element(By.XPATH, "//input[@name = 'peertube.enable']"), ${toPythonBool enablePeertube})
checkbox_set(driver.find_element(By.XPATH, "//input[@name = 'pixelfed.enable']"), ${toPythonBool enablePixelfed})
checkbox_set(driver.find_element(By.XPATH, "//input[@name = 'attic.enable']"), ${toPythonBool enableAttic})
print("Start deployment...")
driver.find_element(By.XPATH, "//button[@id = 'deploy-button']").click()
@ -194,6 +196,11 @@ in
s3AccessKeyFile = dummyFile;
s3SecretKeyFile = dummyFile;
};
attic = {
enable = true;
s3AccessKeyFile = dummyFile;
s3SecretKeyFile = dummyFile;
};
temp.cores = 1;
temp.initialUser = {
username = "dummy";
@ -239,6 +246,7 @@ in
nodes.mastodon.virtualisation.memorySize = 4 * 1024;
nodes.pixelfed.virtualisation.memorySize = 4 * 1024;
nodes.peertube.virtualisation.memorySize = 5 * 1024;
nodes.attic.virtualisation.memorySize = 4 * 1024;
## FIXME: The test of presence of the services are very simple: we only
## check that there is a systemd service of the expected name on the
@ -311,6 +319,7 @@ in
mastodon.fail("systemctl status mastodon-web.service")
peertube.fail("systemctl status peertube.service")
pixelfed.fail("systemctl status phpfpm-pixelfed.service")
attic.fail("systemctl status atticd.service")
with subtest("Run deployment with no services enabled"):
client.succeed("${
@ -319,6 +328,7 @@ in
enableMastodon = false;
enablePeertube = false;
enablePixelfed = false;
enableAttic = false;
}
}/bin/interact-with-panel >&2")
@ -327,6 +337,7 @@ in
mastodon.fail("systemctl status mastodon-web.service")
peertube.fail("systemctl status peertube.service")
pixelfed.fail("systemctl status phpfpm-pixelfed.service")
attic.fail("systemctl status atticd.service")
with subtest("Run deployment with Mastodon and Pixelfed enabled"):
client.succeed("${
@ -335,6 +346,7 @@ in
enableMastodon = true;
enablePeertube = false;
enablePixelfed = true;
enableAttic = false;
}
}/bin/interact-with-panel >&2")
@ -343,6 +355,7 @@ in
mastodon.succeed("systemctl status mastodon-web.service")
peertube.fail("systemctl status peertube.service")
pixelfed.succeed("systemctl status phpfpm-pixelfed.service")
attic.fail("systemctl status atticd.service")
with subtest("Run deployment with only Peertube enabled"):
client.succeed("${
@ -351,6 +364,7 @@ in
enableMastodon = false;
enablePeertube = true;
enablePixelfed = false;
enableAttic = false;
}
}/bin/interact-with-panel >&2")
@ -359,5 +373,6 @@ in
mastodon.fail("systemctl status mastodon-web.service")
peertube.succeed("systemctl status peertube.service")
pixelfed.fail("systemctl status phpfpm-pixelfed.service")
attic.fail("systemctl status atticd.service")
'';
}

View file

@ -3,6 +3,7 @@
"mastodon": { "enable": false },
"peertube": { "enable": false },
"pixelfed": { "enable": false },
"attic": { "enable": false },
"initialUser": {
"displayName": "Testy McTestface",
"username": "test",

View file

@ -24,6 +24,7 @@
mastodonConfigurationResource,
peertubeConfigurationResource,
pixelfedConfigurationResource,
atticConfigurationResource,
}:
## From the hosting provider's perspective, the function is meant to be
@ -55,6 +56,7 @@ let
mastodon = nonNull panelConfigNullable.mastodon { enable = false; };
peertube = nonNull panelConfigNullable.peertube { enable = false; };
pixelfed = nonNull panelConfigNullable.pixelfed { enable = false; };
attic = nonNull panelConfigNullable.attic { enable = false; };
};
in
@ -107,6 +109,13 @@ in
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b";
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987";
};
atticS3KeyConfig =
{ pkgs, ... }:
{
# REVIEW: how were these generated above? how do i add one?
s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKaaaaaaaaaaaaaaaaaaaaaaaa";
s3SecretKeyFile = pkgs.writeText "s3SecretKey" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
};
makeConfigurationResource = resourceModule: config: {
type = providers.local.exec;
@ -140,13 +149,14 @@ in
{
garage-configuration = makeConfigurationResource garageConfigurationResource (
{ pkgs, ... }:
mkIf (cfg.mastodon.enable || cfg.peertube.enable || cfg.pixelfed.enable) {
mkIf (cfg.mastodon.enable || cfg.peertube.enable || cfg.pixelfed.enable || cfg.attic.enable) {
fediversity = {
inherit (cfg) domain;
garage.enable = true;
pixelfed = pixelfedS3KeyConfig { inherit pkgs; };
mastodon = mastodonS3KeyConfig { inherit pkgs; };
peertube = peertubeS3KeyConfig { inherit pkgs; };
attic = atticS3KeyConfig { inherit pkgs; };
};
}
);
@ -213,6 +223,25 @@ in
};
}
);
attic-configuration = makeConfigurationResource atticConfigurationResource (
{ pkgs, ... }:
mkIf cfg.attic.enable {
fediversity = {
inherit (cfg) domain;
temp.initialUser = {
inherit (cfg.initialUser) username email displayName;
# FIXME: disgusting, but nvm, this is going to be replaced by
# proper central authentication at some point
passwordFile = pkgs.writeText "password" cfg.initialUser.password;
};
attic = atticS3KeyConfig { inherit pkgs; } // {
enable = true;
};
};
}
);
};
};
}

View file

@ -71,6 +71,19 @@ in
});
default = null;
};
attic = mkOption {
description = ''
Configuration for the Attic service
'';
type =
with types;
nullOr (submodule {
options = {
enable = lib.mkEnableOption "Attic";
};
});
default = null;
};
initialUser = mkOption {
description = ''
Some services require an initial user to access them.

View file

@ -32,9 +32,11 @@ in
## options that really need to be injected from the resource. Everything else
## should go into the `./nixos` subdirectory.
nixos.module = {
imports = [
"${sources.agenix}/modules/age.nix"
"${sources.disko}/module.nix"
imports = with sources; [
"${agenix}/modules/age.nix"
"${disko}/module.nix"
"${vars}/options.nix"
"${vars}/backends/on-machine.nix"
./options.nix
./nixos
];

View file

@ -104,6 +104,10 @@ let
vmName = "test04";
isTestVm = true;
};
atticConfigurationResource = makeResourceModule {
vmName = "test12";
isTestVm = true;
};
};
nixops4ResourceNixosMockOptions = {

View file

@ -16,11 +16,4 @@
gateway = "2a00:51c0:13:1305::1";
};
};
nixos.module = {
imports = [
../../../infra/common/proxmox-qemu-vm.nix
../../../services/fediversity/attic
];
};
}

View file

@ -18,4 +18,11 @@
gateway = "2a00:51c0:13:1305::1";
};
};
nixos.module = {
imports = [
../../../infra/common/proxmox-qemu-vm.nix
../../../services/fediversity/attic
];
};
}

View file

@ -125,19 +125,6 @@
"url": "https://api.github.com/repos/bigskysoftware/htmx/tarball/v2.0.4",
"hash": "1c4zm3b7ym01ijydiss4amd14mv5fbgp1n71vqjk4alc35jlnqy2"
},
"nix-templating": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "lassulus",
"repo": "nix-templating"
},
"branch": "master",
"submodules": false,
"revision": "437fd19b727e963560980fc4026f79400c440e39",
"url": "https://github.com/lassulus/nix-templating/archive/437fd19b727e963560980fc4026f79400c440e39.tar.gz",
"hash": "000gdd9a4w6gh9lgklsb4dzchgd0fpdkxlhgvpmw0m6ssmrxivkb"
},
"nix-unit": {
"type": "Git",
"repository": {
@ -168,14 +155,14 @@
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "lassulus",
"owner": "kiaragrouwstra",
"repo": "vars"
},
"branch": "main",
"branch": "templates",
"submodules": false,
"revision": "856c18f0e7b95e262ac88ba9ddebf506a16fd4a5",
"url": "https://github.com/lassulus/vars/archive/856c18f0e7b95e262ac88ba9ddebf506a16fd4a5.tar.gz",
"hash": "095dmc67pf5idj4pgnibjbgfxpkm73px3sc6hylc9j0sqh3379q7"
"revision": "6ff942bf2b514edaa1022a92edb6552ac32a09d1",
"url": "https://github.com/kiaragrouwstra/vars/archive/6ff942bf2b514edaa1022a92edb6552ac32a09d1.tar.gz",
"hash": "1h1q3l1l1c1j4ak5lcj2yh85jwqww74ildiak2dkd4h1js9v6cvw"
}
},
"version": 5

View file

@ -7,14 +7,6 @@
let
inherit (lib) mkIf mkMerge;
sources = import ../../../npins;
inherit
(import "${sources.nix-templating}/lib.nix" {
inherit pkgs lib;
nix_templater = pkgs.callPackage "${sources.nix-templating}/pkgs/nix_templater" { };
})
fileContents
template
;
in
{
imports = with sources; [
@ -48,12 +40,7 @@ in
attic = {
inherit (config.fediversity.attic) s3AccessKeyFile s3SecretKeyFile;
ensureAccess = {
peertube-videos = {
read = true;
write = true;
owner = true;
};
peertube-playlists = {
attic = {
read = true;
write = true;
owner = true;
@ -89,11 +76,45 @@ in
8080
];
vars.settings.on-machine.enable = true;
vars.generators."templates" = rec {
dependencies = [ "attic" ];
runtimeInputs = [
pkgs.coreutils
pkgs.gnused
];
script = lib.concatStringsSep "\n" (
lib.mapAttrsToList (template: _: ''
cp "$templates/${template}" "$out/${template}"
echo "filling placeholders in template ${template}..."
${lib.concatStringsSep "\n" (
lib.mapAttrsToList (
parent:
{ placeholder, ... }:
''
sed -i "s/${placeholder}/$(cat "$in/attic/${parent}")/g" "$out/${template}"
echo "- substituted ${parent}"
''
) config.vars.generators."attic".files
)}
'') files
);
files."attic.env" = {
secret = true;
template = pkgs.writeText "attic.env" ''
ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64=${config.vars.generators.attic.files.token.placeholder}
AWS_ACCESS_KEY_ID=$(cat ${config.fediversity.attic.s3AccessKeyFile})
AWS_SECRET_ACCESS_KEY=$(cat ${config.fediversity.attic.s3SecretKeyFile})
'';
};
};
vars.generators.attic = {
runtimeInputs = [ pkgs.openssl ];
files.token.secret = true;
script = ''
genrsa -traditional 4096 | base64 -w0 > $out/token
genrsa -traditional 4096 | base64 -w0 > "$out"/token
'';
};
@ -102,17 +123,7 @@ in
# one `monolithic` and any number of `api-server` nodes
mode = "monolithic";
environmentFile = "${
template {
name = "attic.env";
outPath = "./attic.env";
text = ''
ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64=${fileContents config.vars.generators.attic.files.token.path}
AWS_ACCESS_KEY_ID=$(cat ${config.fediversity.peertube.s3AccessKeyFile})
AWS_SECRET_ACCESS_KEY=$(cat ${config.fediversity.peertube.s3SecretKeyFile})
'';
}
}/bin/attic.env";
environmentFile = config.vars.generators."templates".files."attic.env".path;
# https://github.com/zhaofengli/attic/blob/main/server/src/config-template.toml
settings = {
@ -255,41 +266,54 @@ in
#default-retention-period = "6 months";
};
jwt = {
# WARNING: Changing _anything_ in this section will break any existing
# tokens. If you need to regenerate them, ensure that you use the the
# correct secret and include the `iss` and `aud` claims.
# jwt = {
# WARNING: Changing _anything_ in this section will break any existing
# tokens. If you need to regenerate them, ensure that you use the the
# correct secret and include the `iss` and `aud` claims.
# JWT `iss` claim
#
# Set this to the JWT issuer that you want to validate.
# If this is set, all received JWTs will validate that the `iss` claim
# matches this value.
#token-bound-issuer = "some-issuer";
# JWT `iss` claim
#
# Set this to the JWT issuer that you want to validate.
# If this is set, all received JWTs will validate that the `iss` claim
# matches this value.
#token-bound-issuer = "some-issuer";
# JWT `aud` claim
#
# Set this to the JWT audience(s) that you want to validate.
# If this is set, all received JWTs will validate that the `aud` claim
# contains at least one of these values.
#token-bound-audiences = ["some-audience1", "some-audience2"];
};
# JWT `aud` claim
#
# Set this to the JWT audience(s) that you want to validate.
# If this is set, all received JWTs will validate that the `aud` claim
# contains at least one of these values.
#token-bound-audiences = ["some-audience1", "some-audience2"];
# };
# jwt.signing = {
# # JWT RS256 secret key
# #
# # Set this to the base64-encoded private half of an RSA PEM PKCS1 key.
# # TODO
# # You can also set it via the `ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64`
# # environment variable.
# token-rs256-secret-base64 = "%token_rs256_secret_base64%";
# You must configure JWT signing and verification inside your TOML configuration by setting one of the following options in the [jwt.signing] block:
# * token-rs256-pubkey-base64
# * token-rs256-secret-base64
# * token-hs256-secret-base64
# or by setting one of the following environment variables:
# * ATTIC_SERVER_TOKEN_RS256_PUBKEY_BASE64
# * ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64
# * ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64
# Options will be tried in that same order (configuration options first, then environment options if none of the configuration options were set, starting with the respective RSA pubkey option, the RSA secret option, and finally the HMAC secret option). The first option that is found will be used.
# If an RS256 pubkey (asymmetric RSA PEM PKCS1 public key) is provided, it will only be possible to verify received JWTs, and not sign new JWTs.
# If an RS256 secret (asymmetric RSA PEM PKCS1 private key) is provided, it will be used for both signing new JWTs and verifying received JWTs.
# If an HS256 secret (symmetric HMAC secret) is provided, it will be used for both signing new JWTs and verifying received JWTs.
# # JWT HS256 secret key
# #
# # Set this to the base64-encoded HMAC secret key.
# # You can also set it via the `ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64`
# # environment variable.
# #token-hs256-secret-base64 = "";
# JWT RS256 secret key
#
# Set this to the base64-encoded private half of an RSA PEM PKCS1 key.
# TODO
# You can also set it via the `ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64`
# environment variable.
# token-rs256-secret-base64 = "%token_rs256_secret_base64%";
# JWT HS256 secret key
#
# Set this to the base64-encoded HMAC secret key.
# You can also set it via the `ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64`
# environment variable.
#token-hs256-secret-base64 = "";
# };
};
};

View file

@ -13,6 +13,7 @@ in
./mastodon
./pixelfed
./peertube
./attic
];
options = {