Compare commits

..

10 commits

66 changed files with 1061 additions and 882 deletions

View file

@ -1,24 +0,0 @@
name: deploy-infra
on:
workflow_dispatch: # allows manual triggering
push:
branches:
- main
jobs:
deploy:
runs-on: native
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up SSH key for age secrets and SSH
run: |
env
mkdir -p ~/.ssh
echo "${{ secrets.CD_SSH_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
- name: Deploy
run: nix-shell --run 'eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519 && SHELL=$(which bash) nixops4 apply -v default'

View file

@ -21,23 +21,17 @@ jobs:
- uses: actions/checkout@v4
- run: nix-shell --run 'nix-unit ./deployment/data-model-test.nix'
check-mastodon:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.test-mastodon-service -L
check-peertube:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix build .#checks.x86_64-linux.test-peertube-service -L
- run: nix-build services -A tests.peertube
check-panel:
runs-on: native
steps:
- uses: actions/checkout@v4
- run: nix-build -A tests.panel
- run: nix-build panel -A tests
check-deployment-basic:
runs-on: native

View file

@ -15,9 +15,8 @@ jobs:
- name: Update pins
run: nix-shell --run "npins update"
- name: Create PR
uses: https://github.com/KiaraGrouwstra/gitea-create-pull-request@f9f80aa5134bc5c03c38f5aaa95053492885b397
uses: peter-evans/create-pull-request@v7
with:
remote-instance-api-version: v1
token: "${{ secrets.DEPLOY_KEY }}"
branch: npins-update
commit-message: "npins: update sources"

View file

@ -12,7 +12,6 @@ let
inherit (pkgs) lib;
inherit (import sources.flake-inputs) import-flake;
inherit ((import-flake { src = ./.; }).inputs) nixops4;
panel = import ./panel { inherit sources system; };
pre-commit-check =
(import "${git-hooks}/nix" {
inherit nixpkgs system;
@ -72,7 +71,6 @@ in
tests = {
inherit pre-commit-check;
panel = panel.tests;
};
# re-export inputs so they can be overridden granularly

View file

@ -1,8 +0,0 @@
{
targetMachines = [
"hello"
"cowsay"
];
pathToRoot = ../../..;
pathFromRoot = ./.;
}

View file

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

View file

@ -1,36 +0,0 @@
{
inputs,
sources,
lib,
providers,
...
}:
let
inherit (import ./constants.nix) targetMachines pathToRoot pathFromRoot;
in
{
providers = {
inherit (inputs.nixops4.modules.nixops4Provider) local;
};
resources = lib.genAttrs targetMachines (nodeName: {
type = providers.local.exec;
imports = [
inputs.nixops4-nixos.modules.nixops4Resource.nixos
../common/targetResource.nix
];
_module.args = { inherit inputs sources; };
inherit nodeName pathToRoot pathFromRoot;
nixos.module =
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.${nodeName} ];
};
});
}

View file

@ -0,0 +1,57 @@
{
self,
inputs,
lib,
sources,
...
}:
let
inherit (lib) genAttrs;
targetMachines = [
"hello"
"cowsay"
];
pathToRoot = /. + (builtins.unsafeDiscardStringContext self);
pathFromRoot = ./.;
in
{
_class = "flake";
perSystem =
{ pkgs, ... }:
{
checks.deployment-basic = pkgs.testers.runNixOSTest {
imports = [
../common/nixosTest.nix
./nixosTest.nix
];
_module.args = { inherit inputs sources; };
inherit targetMachines pathToRoot pathFromRoot;
};
};
nixops4Deployments.check-deployment-basic =
{ providers, ... }:
{
providers = {
inherit (inputs.nixops4.modules.nixops4Provider) local;
};
resources = genAttrs targetMachines (nodeName: {
type = providers.local.exec;
imports = [
inputs.nixops4-nixos.modules.nixops4Resource.nixos
../common/targetResource.nix
];
_module.args = { inherit inputs sources; };
inherit nodeName pathToRoot pathFromRoot;
nixos.module =
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.${nodeName} ];
};
});
};
}

View file

@ -1,22 +0,0 @@
{
inputs = {
nixops4.follows = "nixops4-nixos/nixops4";
nixops4-nixos.url = "github:nixops4/nixops4-nixos";
};
outputs =
inputs:
import ./mkFlake.nix inputs (
{ inputs, sources, ... }:
{
imports = [
inputs.nixops4.modules.flake.default
];
nixops4Deployments.check-deployment-basic = {
imports = [ ./deployment/check/basic/deployment.nix ];
_module.args = { inherit inputs sources; };
};
}
);
}

View file

@ -1,15 +1,10 @@
{ inputs, lib, ... }:
{ inputs, ... }:
{
_class = "nixosTest";
name = "deployment-basic";
sourceFileset = lib.fileset.unions [
./constants.nix
./deployment.nix
];
nodes.deployer =
{ pkgs, ... }:
{

View file

@ -1,11 +0,0 @@
{
targetMachines = [
"garage"
"mastodon"
"peertube"
"pixelfed"
];
pathToRoot = ../../..;
pathFromRoot = ./.;
enableAcme = true;
}

View file

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

View file

@ -1,59 +0,0 @@
{
inputs,
sources,
lib,
}:
let
inherit (builtins) fromJSON readFile listToAttrs;
inherit (import ./constants.nix)
targetMachines
pathToRoot
pathFromRoot
enableAcme
;
makeTargetResource = nodeName: {
imports = [ ../common/targetResource.nix ];
_module.args = { inherit inputs sources; };
inherit
nodeName
pathToRoot
pathFromRoot
enableAcme
;
};
## The deployment function - what we are here to test!
##
## TODO: Modularise `deployment/default.nix` to get rid of the nested
## function calls.
makeTestDeployment =
args:
(import ../..)
{
inherit lib;
inherit (inputs) nixops4 nixops4-nixos;
fediversity = import ../../../services/fediversity;
}
(listToAttrs (
map (nodeName: {
name = "${nodeName}ConfigurationResource";
value = makeTargetResource nodeName;
}) targetMachines
))
(fromJSON (readFile ../../configuration.sample.json) // args);
in
{
check-deployment-cli-nothing = makeTestDeployment { };
check-deployment-cli-mastodon-pixelfed = makeTestDeployment {
mastodon.enable = true;
pixelfed.enable = true;
};
check-deployment-cli-peertube = makeTestDeployment {
peertube.enable = true;
};
}

View file

@ -0,0 +1,95 @@
{
self,
inputs,
lib,
sources,
...
}:
let
inherit (builtins) fromJSON readFile listToAttrs;
targetMachines = [
"garage"
"mastodon"
"peertube"
"pixelfed"
"attic"
];
pathToRoot = /. + (builtins.unsafeDiscardStringContext self);
pathFromRoot = ./.;
enableAcme = true;
in
{
_class = "flake";
perSystem =
{ pkgs, ... }:
{
checks.deployment-cli = pkgs.testers.runNixOSTest {
imports = [
../common/nixosTest.nix
./nixosTest.nix
];
_module.args = { inherit inputs sources; };
inherit
targetMachines
pathToRoot
pathFromRoot
enableAcme
;
};
};
nixops4Deployments =
let
makeTargetResource = nodeName: {
imports = [ ../common/targetResource.nix ];
_module.args = { inherit inputs sources; };
inherit
nodeName
pathToRoot
pathFromRoot
enableAcme
;
};
## The deployment function - what we are here to test!
##
## TODO: Modularise `deployment/default.nix` to get rid of the nested
## function calls.
makeTestDeployment =
args:
(import ../..)
{
inherit lib;
inherit (inputs) nixops4 nixops4-nixos;
fediversity = import ../../../services/fediversity;
}
(listToAttrs (
map (nodeName: {
name = "${nodeName}ConfigurationResource";
value = makeTargetResource nodeName;
}) targetMachines
))
(fromJSON (readFile ../../configuration.sample.json) // args);
in
{
check-deployment-cli-nothing = makeTestDeployment {
attic.enable = true;
};
check-deployment-cli-mastodon-pixelfed = makeTestDeployment {
mastodon.enable = true;
pixelfed.enable = true;
attic.enable = true;
};
check-deployment-cli-peertube = makeTestDeployment {
peertube.enable = true;
attic.enable = true;
};
};
}

View file

@ -1,26 +0,0 @@
{
inputs = {
nixops4.follows = "nixops4-nixos/nixops4";
nixops4-nixos.url = "github:nixops4/nixops4-nixos";
};
outputs =
inputs:
import ./mkFlake.nix inputs (
{
inputs,
sources,
lib,
...
}:
{
imports = [
inputs.nixops4.modules.flake.default
];
nixops4Deployments = import ./deployment/check/cli/deployments.nix {
inherit inputs sources lib;
};
}
);
}

View file

@ -1,9 +1,4 @@
{
inputs,
hostPkgs,
lib,
...
}:
{ inputs, hostPkgs, ... }:
let
## Some places need a dummy file that will in fact never be used. We create
@ -16,21 +11,6 @@ in
name = "deployment-cli";
sourceFileset = lib.fileset.unions [
./constants.nix
./deployments.nix
# REVIEW: I would like to be able to grab all of `/deployment` minus
# `/deployment/check`, but I can't because there is a bunch of other files
# in `/deployment`. Maybe we can think of a reorg making things more robust
# here? (comment also in panel test)
../../default.nix
../../options.nix
../../configuration.sample.json
../../../services/fediversity
];
nodes.deployer =
{ pkgs, ... }:
{
@ -45,6 +25,8 @@ in
peertube.inputDerivation
gixy
gixy.inputDerivation
pkgs.acl
pkgs.attr
];
system.extraDependenciesFromModule = {
@ -68,6 +50,11 @@ in
s3AccessKeyFile = dummyFile;
s3SecretKeyFile = dummyFile;
};
attic = {
enable = true;
s3AccessKeyFile = dummyFile;
s3SecretKeyFile = dummyFile;
};
temp.cores = 1;
temp.initialUser = {
username = "dummy";
@ -92,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
@ -106,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")
@ -115,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")
@ -124,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")
@ -133,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;
};
@ -54,16 +54,20 @@ in
system.extraDependencies =
[
inputs.flake-parts
inputs.flake-parts.inputs.nixpkgs-lib
inputs.nixops4
inputs.nixops4-nixos
inputs.nixpkgs
sources.flake-parts
sources.nixpkgs
sources.flake-inputs
sources.git-hooks
sources.vars
sources.nix-templating
pkgs.stdenv
pkgs.stdenvNoCC
pkgs.acl
pkgs.attr
]
++ (
let

View file

@ -13,7 +13,6 @@ let
toJSON
;
inherit (lib)
types
fileset
mkOption
genAttrs
@ -28,6 +27,14 @@ let
forConcat = xs: f: concatStringsSep "\n" (map f xs);
## The whole repository, with the flake at its root.
## FIXME: We could probably have fileset be the union of ./. with flake.nix
## and flake.lock - I doubt we need anything else.
src = fileset.toSource {
fileset = config.pathToRoot;
root = config.pathToRoot;
};
## We will need to override some inputs by the empty flake, so we make one.
emptyFlake = runCommandNoCC "empty-flake" { } ''
mkdir $out
@ -46,39 +53,9 @@ in
## FIXME: I wish I could just use `testScript` but with something like
## `mkOrder` to put this module's string before something else.
extraTestScript = mkOption { };
sourceFileset = mkOption {
## REVIEW: Upstream to nixpkgs?
type = types.mkOptionType {
name = "fileset";
description = "fileset";
descriptionClass = "noun";
check = (x: (builtins.tryEval (fileset.unions [ x ])).success);
merge = (_: defs: fileset.unions (map (x: x.value) defs));
};
description = ''
A fileset that will be copied to the deployer node in the current
working directory. This should contain all the files that are
necessary to run that particular test, such as the NixOS
modules necessary to evaluate a deployment.
'';
};
};
config = {
sourceFileset = fileset.unions [
# NOTE: not the flake itself; it will be overridden.
../../../mkFlake.nix
../../../flake.lock
../../../npins
./sharedOptions.nix
./targetNode.nix
./targetResource.nix
(config.pathToCwd + "/flake-under-test.nix")
];
acmeNodeIP = config.nodes.acme.networking.primaryIPAddress;
nodes =
@ -126,16 +103,8 @@ in
${n}.wait_for_unit("multi-user.target")
'')}
## A subset of the repository that is necessary for this test. It will be
## copied inside the test. The smaller this set, the faster our CI, because we
## won't need to re-run when things change outside of it.
with subtest("Unpacking"):
deployer.succeed("cp -r --no-preserve=mode ${
fileset.toSource {
root = ../../..;
fileset = config.sourceFileset;
}
}/* .")
deployer.succeed("cp -r --no-preserve=mode ${src}/* .")
with subtest("Configure the network"):
${forConcat config.targetMachines (
@ -165,16 +134,11 @@ in
## NOTE: This is super slow. It could probably be optimised in Nix, for
## instance by allowing to grab things directly from the host's store.
##
## NOTE: We use the repository as-is (cf `src` above), overriding only
## `flake.nix` by our `flake-under-test.nix`. We also override the flake
## lock file to use locally available inputs, as we cannot download them.
##
with subtest("Override the flake and its lock"):
deployer.succeed("cp ${config.pathFromRoot}/flake-under-test.nix flake.nix")
with subtest("Override the lock"):
deployer.succeed("""
nix flake lock --extra-experimental-features 'flakes nix-command' \
--offline -v \
--override-input flake-parts ${inputs.flake-parts} \
--override-input nixops4 ${inputs.nixops4.packages.${system}.flake-in-a-bottle} \
\
--override-input nixops4-nixos ${inputs.nixops4-nixos} \
@ -186,6 +150,9 @@ in
inputs.nixops4-nixos.inputs.nixops4.packages.${system}.flake-in-a-bottle
} \
--override-input nixops4-nixos/git-hooks-nix ${emptyFlake} \
\
--override-input nixpkgs ${inputs.nixpkgs} \
--override-input git-hooks ${inputs.git-hooks} \
;
""")

View file

@ -1,11 +0,0 @@
{
targetMachines = [
"garage"
"mastodon"
"peertube"
"pixelfed"
];
pathToRoot = ../../..;
pathFromRoot = ./.;
enableAcme = true;
}

View file

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

View file

@ -1,58 +0,0 @@
{
inputs,
sources,
lib,
}:
let
inherit (builtins) fromJSON listToAttrs;
inherit (import ./constants.nix)
targetMachines
pathToRoot
pathFromRoot
enableAcme
;
makeTargetResource = nodeName: {
imports = [ ../common/targetResource.nix ];
_module.args = { inherit inputs sources; };
inherit
nodeName
pathToRoot
pathFromRoot
enableAcme
;
};
## The deployment function - what we are here to test!
##
## TODO: Modularise `deployment/default.nix` to get rid of the nested
## function calls.
makeTestDeployment =
args:
(import ../..)
{
inherit lib;
inherit (inputs) nixops4 nixops4-nixos;
fediversity = import ../../../services/fediversity;
}
(listToAttrs (
map (nodeName: {
name = "${nodeName}ConfigurationResource";
value = makeTargetResource nodeName;
}) targetMachines
))
args;
in
makeTestDeployment (
fromJSON (
let
env = builtins.getEnv "DEPLOYMENT";
in
if env == "" then
throw "The DEPLOYMENT environment needs to be set. You do not want to use this deployment unless in the `deployment-panel` NixOS test."
else
env
)
)

View file

@ -0,0 +1,95 @@
{
self,
inputs,
lib,
sources,
...
}:
let
inherit (builtins)
fromJSON
listToAttrs
;
targetMachines = [
"garage"
"mastodon"
"peertube"
"pixelfed"
"attic"
];
pathToRoot = /. + (builtins.unsafeDiscardStringContext self);
pathFromRoot = ./.;
enableAcme = true;
in
{
_class = "flake";
perSystem =
{ pkgs, ... }:
{
checks.deployment-panel = pkgs.testers.runNixOSTest {
imports = [
../common/nixosTest.nix
./nixosTest.nix
];
_module.args = { inherit inputs sources; };
inherit
targetMachines
pathToRoot
pathFromRoot
enableAcme
;
};
};
nixops4Deployments =
let
makeTargetResource = nodeName: {
imports = [ ../common/targetResource.nix ];
_module.args = { inherit inputs sources; };
inherit
nodeName
pathToRoot
pathFromRoot
enableAcme
;
};
## The deployment function - what we are here to test!
##
## TODO: Modularise `deployment/default.nix` to get rid of the nested
## function calls.
makeTestDeployment =
args:
(import ../..)
{
inherit lib;
inherit (inputs) nixops4 nixops4-nixos;
fediversity = import ../../../services/fediversity;
}
(listToAttrs (
map (nodeName: {
name = "${nodeName}ConfigurationResource";
value = makeTargetResource nodeName;
}) targetMachines
))
args;
in
{
check-deployment-panel = makeTestDeployment (
fromJSON (
let
env = builtins.getEnv "DEPLOYMENT";
in
if env == "" then
throw "The DEPLOYMENT environment needs to be set. You do not want to use this deployment unless in the `deployment-panel` NixOS test."
else
env
)
);
};
}

View file

@ -1,26 +0,0 @@
{
inputs = {
nixops4.follows = "nixops4-nixos/nixops4";
nixops4-nixos.url = "github:nixops4/nixops4-nixos";
};
outputs =
inputs:
import ./mkFlake.nix inputs (
{
inputs,
sources,
lib,
...
}:
{
imports = [
inputs.nixops4.modules.flake.default
];
nixops4Deployments.check-deployment-panel = import ./deployment/check/panel/deployment.nix {
inherit inputs sources lib;
};
}
);
}

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()
@ -125,20 +127,6 @@ in
name = "deployment-panel";
sourceFileset = lib.fileset.unions [
./constants.nix
./deployment.nix
# REVIEW: I would like to be able to grab all of `/deployment` minus
# `/deployment/check`, but I can't because there is a bunch of other files
# in `/deployment`. Maybe we can think of a reorg making things more robust
# here? (comment also in CLI test)
../../default.nix
../../options.nix
../../../services/fediversity
];
## The panel's module sets `nixpkgs.overlays` which clashes with
## `pkgsReadOnly`. We disable it here.
node.pkgsReadOnly = false;
@ -208,6 +196,11 @@ in
s3AccessKeyFile = dummyFile;
s3SecretKeyFile = dummyFile;
};
attic = {
enable = true;
s3AccessKeyFile = dummyFile;
s3SecretKeyFile = dummyFile;
};
temp.cores = 1;
temp.initialUser = {
username = "dummy";
@ -253,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
@ -325,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("${
@ -333,6 +328,7 @@ in
enableMastodon = false;
enablePeertube = false;
enablePixelfed = false;
enableAttic = false;
}
}/bin/interact-with-panel >&2")
@ -341,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("${
@ -349,6 +346,7 @@ in
enableMastodon = true;
enablePeertube = false;
enablePixelfed = true;
enableAttic = false;
}
}/bin/interact-with-panel >&2")
@ -357,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("${
@ -365,6 +364,7 @@ in
enableMastodon = false;
enablePeertube = true;
enablePixelfed = false;
enableAttic = false;
}
}/bin/interact-with-panel >&2")
@ -373,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

@ -1,8 +1,9 @@
{
"domain": "fediversity.net",
"mastodon": { "enable": false },
"peertube": { "enable": false },
"pixelfed": { "enable": false },
"mastodon": { "enable": true },
"peertube": { "enable": true },
"pixelfed": { "enable": true },
"attic": { "enable": true },
"initialUser": {
"displayName": "Testy McTestface",
"username": "test",

View file

@ -1,13 +1,9 @@
let
inherit (import ../default.nix { }) pkgs inputs;
inherit (import ../default.nix { }) pkgs;
inherit (pkgs) lib;
inherit (lib) mkOption;
eval =
module:
(lib.evalModules {
specialArgs = {
inherit inputs;
};
modules = [
module
./data-model.nix
@ -20,51 +16,32 @@ in
test-eval = {
expr =
let
fediversity = eval (
{ config, ... }:
{
config = {
applications.hello =
{ ... }:
{
description = ''Command-line tool that will print "Hello, world!" on the terminal'';
example = eval {
runtime-environments.bar.nixos = {
module =
{ ... }:
{
options = {
enable = lib.mkEnableOption "Hello in the shell";
system.stateVersion = "25.05";
};
};
implementation =
cfg:
lib.optionalAttrs cfg.enable {
dummy.login-shell.packages.hello = pkgs.hello;
applications.foo = {
module =
{ pkgs, ... }:
{
environment.systemPackages = [
pkgs.hello
];
};
};
};
options = {
example-configuration = mkOption {
type = config.configuration;
readOnly = true;
default = {
enable = true;
applications.hello.enable = true;
};
};
};
}
);
in
{
inherit (fediversity)
example-configuration
;
has-runtime = lib.isAttrs example.runtime-environments.bar.nixos.module;
has-application = lib.isAttrs example.applications.foo.module;
};
expected = {
example-configuration = {
enable = true;
applications.hello.enable = true;
};
has-runtime = true;
has-application = true;
};
};
}

View file

@ -1,89 +1,45 @@
{
lib,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (lib.types)
attrsOf
attrTag
deferredModuleWith
submodule
optionType
functionTo
;
functionType = import ./function.nix;
application-resources = {
options.resources = mkOption {
# TODO: maybe transpose, and group the resources by type instead
type = attrsOf (
attrTag (lib.mapAttrs (_name: resource: mkOption { type = resource.request; }) config.resources)
);
};
};
inherit (lib) types mkOption;
in
with types;
{
_class = "nixops4Deployment";
options = {
runtime-environments = mkOption {
description = "Collection of runtime environments into which applications can be deployed";
type = attrsOf (attrTag {
nixos = mkOption {
description = "A single NixOS machine";
type = submodule {
options = {
module = mkOption {
description = "The NixOS module describing the base configuration for that machine";
type = deferredModule;
};
};
};
};
});
};
applications = mkOption {
description = "Collection of Fediversity applications";
type = attrsOf (
submodule (application: {
_class = "fediversity-application";
type = attrsOf (submoduleWith {
modules = [
{
options = {
description = mkOption {
description = "Description to be shown in the application overview";
type = types.str;
};
module = mkOption {
description = "Operator-facing configuration options for the application";
type = deferredModuleWith { staticModules = [ { _class = "fediversity-application-config"; } ]; };
};
implementation = mkOption {
description = "Mapping of application configuration to deployment resources, a description of what an application needs to run";
type = application.config.config-mapping.function-type;
};
resources = mkOption {
description = "Compute resources required by an application";
type = functionTo application.config.config-mapping.output-type;
readOnly = true;
default = input: (application.config.implementation input).output;
};
config-mapping = mkOption {
description = "Function type for the mapping from application configuration to required resources";
type = submodule functionType;
readOnly = true;
default = {
input-type = application.config.module;
output-type = application-resources;
description = "The NixOS module for that application, for configuring that application";
type = deferredModule;
};
};
};
})
);
};
configuration = mkOption {
description = "Configuration type declaring options to be set by operators";
type = optionType;
readOnly = true;
default = submodule {
options = {
enable = lib.mkEnableOption {
description = "your Fediversity configuration";
};
applications = lib.mapAttrs (
_name: application:
mkOption {
description = application.description;
type = submodule application.module;
default = { };
}
) config.applications;
};
};
];
});
};
};
}

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

@ -1,26 +1,9 @@
{ inputs, sources, ... }:
{
_class = "flake";
perSystem =
{ pkgs, ... }:
{
checks = {
deployment-basic = import ./check/basic {
inherit (pkgs.testers) runNixOSTest;
inherit inputs sources;
};
deployment-cli = import ./check/cli {
inherit (pkgs.testers) runNixOSTest;
inherit inputs sources;
};
deployment-panel = import ./check/panel {
inherit (pkgs.testers) runNixOSTest;
inherit inputs sources;
};
};
};
imports = [
./check/basic/flake-part.nix
./check/cli/flake-part.nix
./check/panel/flake-part.nix
];
}

View file

@ -1,37 +0,0 @@
/**
Modular function type
*/
{ config, lib, ... }:
let
inherit (lib) mkOption types;
inherit (types)
deferredModule
submodule
functionTo
optionType
;
in
{
options = {
input-type = mkOption {
type = deferredModule;
};
output-type = mkOption {
type = deferredModule;
};
function-type = mkOption {
type = optionType;
readOnly = true;
default = functionTo (submodule {
options = {
input = mkOption {
type = submodule config.input-type;
};
output = mkOption {
type = submodule config.output-type;
};
};
});
};
};
}

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.

121
flake.lock generated
View file

@ -59,6 +59,22 @@
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_3": {
"flake": false,
"locked": {
"lastModified": 1733328505,
@ -74,7 +90,7 @@
"type": "github"
}
},
"flake-compat_3": {
"flake-compat_4": {
"flake": false,
"locked": {
"lastModified": 1696426674,
@ -127,6 +143,24 @@
}
},
"flake-parts_3": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib_3"
},
"locked": {
"lastModified": 1738453229,
"narHash": "sha256-7H9XgNiGLKN1G1CgRh0vUL4AheZSYzPm+zmZ7vxbJdo=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "32ea77a06711b758da0ad9bd6a844c5740a87abd",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_4": {
"inputs": {
"nixpkgs-lib": [
"nixops4-nixos",
@ -167,12 +201,32 @@
"type": "github"
}
},
"git-hooks-nix": {
"git-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1742649964,
"narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"git-hooks-nix": {
"inputs": {
"flake-compat": "flake-compat_2",
"gitignore": "gitignore_2",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1737465171,
"narHash": "sha256-R10v2hoJRLq8jcL4syVFag7nIGE7m13qO48wRIukWNg=",
@ -227,6 +281,27 @@
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"gitignore_2": {
"inputs": {
"nixpkgs": [
"nixops4-nixos",
@ -266,8 +341,8 @@
},
"nix": {
"inputs": {
"flake-compat": "flake-compat_2",
"flake-parts": "flake-parts_3",
"flake-compat": "flake-compat_3",
"flake-parts": "flake-parts_4",
"git-hooks-nix": "git-hooks-nix_2",
"nixfmt": "nixfmt",
"nixpkgs": [
@ -341,10 +416,10 @@
},
"nixops4": {
"inputs": {
"flake-parts": "flake-parts_2",
"flake-parts": "flake-parts_3",
"nix": "nix",
"nix-cargo-integration": "nix-cargo-integration",
"nixpkgs": "nixpkgs_2",
"nixpkgs": "nixpkgs_3",
"nixpkgs-old": "nixpkgs-old"
},
"locked": {
@ -363,7 +438,7 @@
},
"nixops4-nixos": {
"inputs": {
"flake-parts": "flake-parts",
"flake-parts": "flake-parts_2",
"git-hooks-nix": "git-hooks-nix",
"nixops4": "nixops4",
"nixops4-nixos": [
@ -445,6 +520,18 @@
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
}
},
"nixpkgs-lib_3": {
"locked": {
"lastModified": 1738452942,
"narHash": "sha256-vJzFZGaCpnmo7I6i416HaBLpC+hvcURh/BQwROcGIp8=",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
}
},
"nixpkgs-old": {
"locked": {
"lastModified": 1735563628,
@ -478,6 +565,22 @@
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1730768919,
"narHash": "sha256-8AKquNnnSaJRXZxc5YmF/WfmxiHX6MMZZasRP6RRQkE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a04d33c0c3f1a59a2c1cb0c6e34cd24500e5a1dc",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1738410390,
"narHash": "sha256-xvTo0Aw0+veek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc=",
@ -518,7 +621,7 @@
},
"purescript-overlay": {
"inputs": {
"flake-compat": "flake-compat_3",
"flake-compat": "flake-compat_4",
"nixpkgs": [
"nixops4-nixos",
"nixops4",
@ -561,6 +664,8 @@
},
"root": {
"inputs": {
"flake-parts": "flake-parts",
"git-hooks": "git-hooks",
"nixops4": [
"nixops4-nixos",
"nixops4"

View file

@ -1,36 +1,67 @@
{
inputs = {
flake-parts.url = "github:hercules-ci/flake-parts";
git-hooks.url = "github:cachix/git-hooks.nix";
nixops4.follows = "nixops4-nixos/nixops4";
nixops4-nixos.url = "github:nixops4/nixops4-nixos";
};
outputs =
inputs:
import ./mkFlake.nix inputs (
{ inputs, sources, ... }:
inputs@{ self, flake-parts, ... }:
let
sources = import ./npins;
inherit (import sources.flake-inputs) import-flake;
inherit (sources) git-hooks;
# XXX(@fricklerhandwerk): this atrocity is required to splice in a foreign Nixpkgs via flake-parts
# XXX - this is just importing a flake
nixpkgs = import-flake { src = sources.nixpkgs; };
# XXX - this overrides the inputs attached to `self`
inputs' = self.inputs // {
nixpkgs = nixpkgs;
};
self' = self // {
inputs = inputs';
};
in
# XXX - finally we override the overall set of `inputs` -- we need both:
# `flake-parts obtains `nixpkgs` from `self.inputs` and not from `inputs`.
flake-parts.lib.mkFlake
{
inputs = inputs // {
inherit nixpkgs;
};
self = self';
specialArgs = {
inherit sources;
};
}
(
{ inputs, ... }:
{
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
imports = [
"${sources.git-hooks}/flake-module.nix"
"${git-hooks}/flake-module.nix"
inputs.nixops4.modules.flake.default
./deployment/flake-part.nix
./infra/flake-part.nix
./keys/flake-part.nix
./secrets/flake-part.nix
./services/tests/flake-part.nix
];
perSystem =
{
pkgs,
lib,
system,
...
}:
{
checks = {
panel = (import ./. { inherit sources system; }).tests.panel.basic;
};
formatter = pkgs.nixfmt-rfc-style;
pre-commit.settings.hooks =

View file

@ -1,13 +1,14 @@
# Infra
This directory contains the definition of [the VMs](../machines/machines.md) that host our
This directory contains the definition of [the VMs](machines.md) that host our
infrastructure.
## Provisioning VMs with an initial configuration
> NOTE[Niols]: This is still very manual and clunky. Two things will happen:
> 1. In the near future, I will improve the provisioning script to make this a bit less clunky.
> 2. In the far future, NixOps4 will be able to communicate with Proxmox directly and everything will become much cleaner.
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
everything will become much cleaner.
1. Choose names for your VMs. It is recommended to choose `fediXXX`, with `XXX`
above 100. For instance, `fedi117`.
@ -24,7 +25,8 @@ infrastructure.
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.
FIXME: Remove this step by making the provisioning script not fail with the
public key does not exist yet.
3. Run the provisioning script:
```
@ -42,7 +44,7 @@ infrastructure.
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.
FIXME: Make the provisioning script do that for us.
7. Regenerate the list of machines:
```
@ -54,7 +56,7 @@ infrastructure.
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
FIXME: Figure out why the full configuration isn't on the machine at this
point and fix it.
## Updating existing VM configurations

View file

@ -1,13 +1,7 @@
{
config,
...
}:
{
_class = "nixos";
users.users = {
root.openssh.authorizedKeys.keys = config.users.users.procolix.openssh.authorizedKeys.keys;
procolix = {
isNormalUser = true;
extraGroups = [ "wheel" ];

View file

@ -1,10 +1,9 @@
{ sources, ... }:
{ modulesPath, ... }:
{
_class = "nixos";
imports = [
"${sources.nixpkgs}/nixos/modules/profiles/qemu-guest.nix"
];
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
boot = {
initrd = {

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
];
@ -48,9 +50,9 @@ in
## the secret's file.
age.secrets = concatMapAttrs (
name: secret:
optionalAttrs (elem config.fediversityVm.hostPublicKey secret.publicKeys) {
optionalAttrs (elem config.fediversityVm.hostPublicKey secret.publicKeys) ({
${removeSuffix ".age" name}.file = secrets.rootPath + "/${name}";
}
})
) secrets.mapping;
## FIXME: Remove direct root authentication once the NixOps4 NixOS provider
@ -58,8 +60,6 @@ in
users.users.root.openssh.authorizedKeys.keys = attrValues keys.contributors ++ [
# allow our panel vm access to the test machines
keys.panel
# allow continuous deployment access
keys.cd
];
};

View file

@ -27,19 +27,12 @@ let
_module.args = {
inherit
inputs
sources
keys
secrets
;
};
nixos.module.imports = [
./common/proxmox-qemu-vm.nix
];
nixos.specialArgs = {
inherit sources;
};
imports =
[
./common/resource.nix
@ -47,6 +40,7 @@ let
++ (
if isTestVm then
[
./common/proxmox-qemu-vm.nix
../machines/operator/${vmName}
{
nixos.module.users.users.root.openssh.authorizedKeys.keys = [
@ -69,21 +63,6 @@ let
vmNames:
{ providers, ... }:
{
# XXX: this type merge is for adding `specialArgs` to resource modules
options.resources = mkOption {
type =
with lib.types;
lazyAttrsOf (submoduleWith {
class = "nixops4Resource";
modules = [ ];
# TODO(@fricklerhandwerk): we may want to pass through all of `specialArgs`
# once we're sure it's sane. leaving it here for better control during refactoring.
specialArgs = {
inherit sources;
};
});
};
config = {
providers.local = inputs.nixops4.modules.nixops4Provider.local;
resources = genAttrs vmNames (vmName: {
type = providers.local.exec;
@ -96,7 +75,6 @@ let
];
});
};
};
makeDeployment' = vmName: makeDeployment [ vmName ];
## Given an attrset of test configurations (key = test machine name, value =
@ -126,6 +104,10 @@ let
vmName = "test04";
isTestVm = true;
};
atticConfigurationResource = makeResourceModule {
vmName = "test12";
isTestVm = true;
};
};
nixops4ResourceNixosMockOptions = {

View file

@ -15,6 +15,7 @@ let
installer =
{
config,
pkgs,
lib,
...

View file

@ -1 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMlsYTtMx3hFO8B5B8iHaXL2JKj9izHeC+/AMhIWXBPs cd-age

View file

@ -35,5 +35,4 @@ in
contributors = collectKeys ./contributors;
systems = collectKeys ./systems;
panel = removeTrailingWhitespace (readFile ./panel-ssh-key.pub);
cd = removeTrailingWhitespace (readFile ./cd-ssh-key.pub);
}

View file

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

View file

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

View file

@ -48,7 +48,7 @@ in
};
## NOTE: This is a physical machine, so is not covered by disko
fileSystems."/" = lib.mkForce {
fileSystems."/" = {
device = "rpool/root";
fsType = "zfs";
};
@ -58,7 +58,7 @@ in
fsType = "zfs";
};
fileSystems."/boot" = lib.mkForce {
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/50B2-DD3F";
fsType = "vfat";
options = [

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

@ -1,54 +0,0 @@
## This file contains a tweak of flake-parts's `mkFlake` function to splice in
## sources taken from npins.
## NOTE: Much of the logic in this file feels like it should be not super
## specific to fediversity. Could it make sense to extract the core of this to
## another place it feels closer to in spirit, such as @fricklerhandwerk's
## flake-inputs (which this code already depends on anyway, and which already
## contained two distinct helpers for migrating away from flakes)? cf
## https://git.fediversity.eu/Fediversity/Fediversity/pulls/447#issuecomment-8671
inputs@{ self, ... }:
let
sources = import ./npins;
inherit (import sources.flake-inputs) import-flake;
# XXX(@fricklerhandwerk): this atrocity is required to splice in a foreign Nixpkgs via flake-parts
# XXX - this is just importing a flake
nixpkgs = import-flake { src = sources.nixpkgs; };
# XXX - this overrides the inputs attached to `self`
inputs' = self.inputs // {
nixpkgs = nixpkgs;
};
self' = self // {
inputs = inputs';
};
flake-parts-lib = import "${sources.flake-parts}/lib.nix" { inherit (nixpkgs) lib; };
in
flakeModule:
flake-parts-lib.mkFlake
{
# XXX - finally we override the overall set of `inputs` -- we need both:
# `flake-parts obtains `nixpkgs` from `self.inputs` and not from `inputs`.
inputs = inputs // {
inherit nixpkgs;
};
self = self';
specialArgs = {
inherit sources;
};
}
{
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
imports = [ flakeModule ];
}

View file

@ -125,6 +125,19 @@
"url": "https://api.github.com/repos/bigskysoftware/htmx/tarball/v2.0.4",
"hash": "1c4zm3b7ym01ijydiss4amd14mv5fbgp1n71vqjk4alc35jlnqy2"
},
"nix-templating": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "KiaraGrouwstra",
"repo": "nix-templating"
},
"branch": "lib-default-arg",
"submodules": false,
"revision": "e1ff247d508b4efd057a4d6bb13cf45b62c2512f",
"url": "https://github.com/KiaraGrouwstra/nix-templating/archive/e1ff247d508b4efd057a4d6bb13cf45b62c2512f.tar.gz",
"hash": "0g59h4r029jw8vlvn8da62fk9m737s80fg2qk57322iv9lkqlvp0"
},
"nix-unit": {
"type": "Git",
"repository": {
@ -150,6 +163,19 @@
"revision": "f33a4d26226c05d501b9d4d3e5e60a3a59991921",
"url": "https://github.com/nixos/nixpkgs/archive/f33a4d26226c05d501b9d4d3e5e60a3a59991921.tar.gz",
"hash": "1b6dm1sn0bdpcsmxna0zzspjaixa2dald08005fry5jrbjvwafdj"
},
"vars": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "kiaragrouwstra",
"repo": "vars"
},
"branch": "templates",
"submodules": false,
"revision": "6ff942bf2b514edaa1022a92edb6552ac32a09d1",
"url": "https://github.com/kiaragrouwstra/vars/archive/6ff942bf2b514edaa1022a92edb6552ac32a09d1.tar.gz",
"hash": "1h1q3l1l1c1j4ak5lcj2yh85jwqww74ildiak2dkd4h1js9v6cvw"
}
},
"version": 5

View file

@ -45,7 +45,7 @@ in
'';
};
module = ./nix/configuration.nix;
module = import ./nix/configuration.nix;
tests = pkgs.callPackage ./nix/tests.nix { };
# re-export inputs so they can be overridden granularly

View file

@ -202,8 +202,11 @@ in
};
};
# needed to place a config file with home-manager
users.users.${name}.isNormalUser = true;
users.users.${name} = {
# TODO[Niols]: change to system user or document why we specifically
# need a normal user.
isNormalUser = true;
};
users.groups.${name} = { };
systemd.services.${name} = {

View file

@ -1,19 +1,17 @@
age-encryption.org/v1
-> ssh-ed25519 Jpc21A bBCQmvfRUwJuIXbpVJ092XUBVszGrb6gILGbgV9j9BY
7DEGwhqdfqMs5cxXtlMkSTPjw4qhczBgW0dmoJ6dh6g
-> ssh-ed25519 BAs8QA oiVedFC6UklEFCJUybGr93+XrddyCtV4r4TnE4nhpWI
xasnkP4NCl9TuYSE1u0Xi0b/PiwcrfHCz2QMnpTjLcU
-> ssh-ed25519 ofQnlg LrMcWdaEUVyIgd/KznwJW/2sucIu5MuxDEcEJAmf8mA
p6pQoisuXre2J4r6ArV6C6lKO2J/aNdBFhqLPBoZ2wA
-> ssh-ed25519 COspvA q2OGeVofPKyGCpr4Mf9VoaRvZCWTRl8n2mvkQOdTnyQ
M+ffAGecJG/94k/Z5DdokltrZppS2IcxkZa8JKHwIMs
-> ssh-ed25519 2XrTgw Bsz/G4QderToPSfMKOR6s5yWb0xCGUlsjGJxJYQNBRc
JYrXZb8qj1Yi9u5bnI/WzuNxy7gyFLCTIUaGNmcOYnk
-> ssh-ed25519 awJeHA KKJMQSt0PvC6P+T/kxQv96tSBdLQLiY2f8q35IwGm28
p7Cf2HLlPl0qmsO6Hh5zwVgKkEs3A6fdSBndMKsacbk
-> ssh-ed25519 Fa25Dw 3m/qyannP4gjXxkUuO0LQRU8Z8HXOg4WReMDd7786y8
dNMyiBGeJDrBScE9TEyZZ7+MGMG6FLuoRTK82EVeX1w
-> ssh-ed25519 i+ecmQ oCs4Ep2K75yjmUOh1ox4F25tGq+O/mZ2/c2E8+IRlEc
0Wc9gDxhvHK5tEVM5kJ0mQXc3kp7tJ2JNHg54N0+tJ8
--- mXrqbcHxjjkS5MrQaCVm4hTsAUEENAWlIYtiYx6rtas
ž`€úì}öÙ7Ù>­iŒbàéëÕè/& ɪŠwŽ„ì7àí[ã±Hˆc“
-> ssh-ed25519 Jpc21A 9edPaA2tT4SeYNTPzF0E157daC2o+JH/WQQCT+vLbFg
C48EtLdhB75TTzfEZTw1DypicHiVlSmFzjfbqfO9N/8
-> ssh-ed25519 BAs8QA T+kXpZg1v0XRkub5DWir7vYwO7KaOJLZBNYxxXiBUCw
zBRwMTDpyI7twEwUGsmJYyYPw9btBx5Kakj1yT+XY8U
-> ssh-ed25519 ofQnlg 4UoEDY/tdKz8LrX1BkBU1/cn+vSaYLUl7xX9YmzANBY
8CACq1n3AJgD9IyPN23iRvThqsfQFF5+jmkKnhun24U
-> ssh-ed25519 COspvA HxcbkqHL+LpVmwb+Fo5JuUU+C+Pxzdxtb0yZHixwuzM
7FIhxdbjHJlgQQgjrHHUK5cecqs5aT7X3I8TWf8c2gc
-> ssh-ed25519 2XrTgw R6Ia8MVIZKPnNZ0rspZ34EqoY8fOLeB9H7vnvNBLg1g
55NUqz5Yygt6FKJ3bR5iHxQp8G7S2gyFwrJNX1Pb/2Y
-> ssh-ed25519 awJeHA hJdTuAScoewVMt7HWiisSkL0zSeClFzYzzKL84G893o
ou780VLrW1s4d6L+lEVu3kXaGn4dvtFPA31supwEL50
-> ssh-ed25519 Fa25Dw mJcqnXA3fQeoKrG7RJ7nVeLxPvrxqbj+lJdx6jQ9IR8
f5Q7mrQSSDsm1Z/uSAnvx66mgnRC3XaBLQrVL9f/Ijs
--- W/KmboXTLV12X6WtVQKHNe+ZHvS2q9EHUZwofSgJSE8
^kûÚ h©0ÔkÇ ¢¸_Ç·ûQÞm7\òÖ}÷Áë?½qø<ÿm

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -7,12 +7,11 @@ let
keys = import ../keys;
contributors = attrValues keys.contributors;
cd = [ keys.cd ];
in
concatMapAttrs
(name: systems: {
"${name}.age".publicKeys = contributors ++ systems ++ cd;
"${name}.age".publicKeys = contributors ++ systems;
})
(

View file

@ -1,19 +1,18 @@
age-encryption.org/v1
-> ssh-ed25519 Jpc21A NStZFZPTHMhVCnQ5Zkbl39vWztrxfsSXok24/e8H7QQ
JjHP6Cus76PGYYxpbnc2cSZ79zvdD8LISYDPbvXsnqU
-> ssh-ed25519 BAs8QA iocHfHjWlEUsbtibqEbYDceAqURr2vjxuYapqon9hyU
ljL+olZdhWtHeV3uh3pOu22+sY13wPn2vKQDduPSqVs
-> ssh-ed25519 ofQnlg 9YVfMKyoP3+xtzg/ok2I9yf3YdIYoBpUJa/3d2N/8lI
2yUalyj7O3c1YDA2xTb9QNYrFBDHwcyGBX3mydv0ifI
-> ssh-ed25519 COspvA cOSNsZXBbhQ/B49fq3KwcY6siVrTz48doTrta/0d/Hw
jcRtVxA/tVFM9btPAPI6zKk8BwAVlaQlvHC203MpmIQ
-> ssh-ed25519 2XrTgw d3EKtYkxjeJZ8kt3ofIklGmRwUCgTIB/WVVlvxggGRk
IhcrpWN9xFsKRw9iCfYMONPOU7TpTt4kTBNwMDtk7zo
-> ssh-ed25519 awJeHA Ei64e3+FJDM6S8NP+YfEWEg9t72qTXZ0IdZE8dYQPm4
ggRc86sXin06eXJkLbK8CdJFDa1237WMfSgwNd5ngmM
-> ssh-ed25519 dgBsjw 9etK6tNrFlWVAKTz5U0TitkiGYLKTad3QiRWVpLPrwM
xHLzFnRtcvpVZYZrxWz5q4uadhHrHVlfqjteOWfIccE
-> ssh-ed25519 i+ecmQ SDTnYBLMOaH173B/wqaOifE6a90gSesRqMHmX7/iZFk
kS9tuKnMXCXNUnoZ06DisOOyZHe/mZl4a0JRA+eynE8
--- C0R5WxDDCqQGxyvFoeNX838az0bjp55PGh//1NFG4LE
ŠÉY—±³<EFBFBD>„ÏKRÇËej±éŒ7xÑí Óì¾7jÏ-œJý«[ÀF?Ÿ=-wXMC~)èŃ<E280BA>Éõb«ëƒCÜ4ÌÖÞOwý~¿š8ñv—ÙÜžèX»ØÆƒí!5¦
-> ssh-ed25519 Jpc21A EuMYAiZX+4A12eu19mIY7u+WYF7NJ9qJosQSVlxR6n8
bK5CMXAmP23t1p9bgmqoVg4Qcu2qYKGc4t36v8e9eow
-> ssh-ed25519 BAs8QA IwRyitDNTzUPzQAUbDNEKjFiF8WPD/OyztOZQeoTEzw
OwiTWvk4NmUgExav0uH6HlThDNU5hsKXfR6KHsFOV3I
-> ssh-ed25519 ofQnlg 3TcMbLX1JsQL8+Gqy7IFZwykZr2BspvPCuZT1SHtnQQ
Ci5OeBj2aiC8ut9jIEUMt3qfYH+cJrnVud6AH54Ndn8
-> ssh-ed25519 COspvA 0t9f3Wu3ILv4QTJhwT619y+7XFrryCLbpIZC6aE+qQI
oPQP48F6oO/tkqLZDdjkGtIap7KHiAknbpTNL6/yLaU
-> ssh-ed25519 2XrTgw YOZsaYQH9vMH0QqSXGh8GyhRV4MbcBGPFfFaKpo3Ckk
kUShJbADA+6bpx2adxvzlI/0jSM5bIBfZfdSE/7Vm5Y
-> ssh-ed25519 awJeHA dF3m0hQWX9c0EezDr56Kt/F4d1Uim7NwvIX6zRws0Eo
pst243yrARODwrnyz8cJAzgDxdPOUsRbs7yPZePABFs
-> ssh-ed25519 dgBsjw PUYHcP/tgNnKyvlIoJRcNcW3zabVV1iHXIWfKqgW9xc
tXNjSuVH/g/oN5o75FPkFFpviF7SeFSN9kbqURvgMDE
--- wHgBAN9c6F6T5hFJGo8uH8zqDkQDwx3/jVNKUtQ3arE
«Ñ¢Á
ò@µú¡fÃ`m;ÕcæäU²€ùò£Íd…eSèyfv¿»¡€J?ø `œfj£Äa}lÃó ¿Úxç²BÇt2èfìôm08ÓoÝtRál9˜èx¤¢ŒÅžæ÷

Binary file not shown.

Binary file not shown.

View file

@ -21,11 +21,11 @@ For those that know it, we could say that the current module is an analogous of
## Content of this directory
- [fediversity](./fediversity) contains the definition of the services. Look in
- [fediversity][./fediversity] contains the definition of the services. Look in
particular at its `default.nix` that contains the definition of the options.
- [vm](./vm) contains options specific to making the service run in local QEMU
- [vm][./vm] contains options specific to making the service run in local QEMU
VMs. These modules will for instance override the defaults to disable SSL, and
they will add virtualisation options to forward ports, for instance.
- [tests](./tests) contain full NixOS tests of the services.
- [tests][./tests] contain full NixOS tests of the services.

13
services/default.nix Normal file
View file

@ -0,0 +1,13 @@
{
system ? builtins.currentSystem,
sources ? import ../npins,
pkgs ? import sources.nixpkgs { inherit system; },
...
}:
{
tests = {
mastodon = pkgs.nixosTest ./tests/mastodon.nix;
pixelfed-garage = pkgs.nixosTest ./tests/pixelfed-garage.nix;
peertube = pkgs.nixosTest ./tests/peertube.nix;
};
}

View file

@ -0,0 +1,322 @@
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkIf mkMerge;
sources = import ../../../npins;
in
{
imports = with sources; [
./options.nix
"${vars}/options.nix"
"${vars}/backends/on-machine.nix"
];
config = mkMerge [
(mkIf
(
config.fediversity.garage.enable
&& config.fediversity.attic.s3AccessKeyFile != null
&& config.fediversity.attic.s3SecretKeyFile != null
)
{
fediversity.garage = {
ensureBuckets = {
attic = {
website = true;
# TODO: these are too broad, after getting everything to work narrow it down to the domain we actually want
corsRules = {
enable = true;
allowedHeaders = [ "*" ];
allowedMethods = [ "GET" ];
allowedOrigins = [ "*" ];
};
};
};
ensureKeys = {
attic = {
inherit (config.fediversity.attic) s3AccessKeyFile s3SecretKeyFile;
ensureAccess = {
attic = {
read = true;
write = true;
owner = true;
};
};
};
};
};
}
)
(mkIf config.fediversity.attic.enable {
services.postgresql = {
enable = true;
authentication = lib.mkForce ''
local all all trust
'';
ensureDatabases = [
"atticd"
];
ensureUsers = [
{
name = "atticd";
ensureDBOwnership = true;
}
];
};
# open up access to the mastodon web interface. 80 is necessary if only for ACME
networking.firewall.allowedTCPPorts = [
80
443
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
'';
};
services.atticd = {
enable = true;
# one `monolithic` and any number of `api-server` nodes
mode = "monolithic";
environmentFile = config.vars.generators."templates".files."attic.env".path;
# https://github.com/zhaofengli/attic/blob/main/server/src/config-template.toml
settings = {
# Socket address to listen on
# listen = "[::]:8080";
listen = "0.0.0.0:8080";
# listen = "127.0.0.1:8080";
# Allowed `Host` headers
#
# This _must_ be configured for production use. If unconfigured or the
# list is empty, all `Host` headers are allowed.
allowed-hosts = [ ];
# The canonical API endpoint of this server
#
# This is the endpoint exposed to clients in `cache-config` responses.
#
# This _must_ be configured for production use. If not configured, the
# API endpoint is synthesized from the client's `Host` header which may
# be insecure.
#
# The API endpoint _must_ end with a slash (e.g., `https://domain.tld/attic/`
# not `https://domain.tld/attic`).
api-endpoint = "https://${config.fediversity.attic.domain}/";
# Whether to soft-delete caches
#
# If this is enabled, caches are soft-deleted instead of actually
# removed from the database. Note that soft-deleted caches cannot
# have their names reused as long as the original database records
# are there.
#soft-delete-caches = false;
# Whether to require fully uploading a NAR if it exists in the global cache.
#
# If set to false, simply knowing the NAR hash is enough for
# an uploader to gain access to an existing NAR in the global
# cache.
#require-proof-of-possession = true;
# Database connection
database = {
# Connection URL
#
# For production use it's recommended to use PostgreSQL.
# url = "postgresql:///atticd:password@127.0.0.1:5432/atticd";
url = "postgresql:///atticd?host=/run/postgresql";
# Whether to enable sending on periodic heartbeat queries
#
# If enabled, a heartbeat query will be sent every minute
#heartbeat = false;
};
# File storage configuration
storage = {
# Storage type
#
# Can be "local" or "s3".
type = "s3";
# ## Local storage
# The directory to store all files under
# path = "%storage_path%";
# ## S3 Storage (set type to "s3" and uncomment below)
# The AWS region
region = "garage";
# The name of the bucket
bucket = "attic";
# Custom S3 endpoint
#
# Set this if you are using an S3-compatible object storage (e.g., Minio).
endpoint = config.fediversity.garage.api.url;
# Credentials
#
# If unset, the credentials are read from the `AWS_ACCESS_KEY_ID` and
# `AWS_SECRET_ACCESS_KEY` environment variables.
# storage.credentials = {
# access_key_id = "";
# secret_access_key = "";
# };
};
# Data chunking
#
# Warning: If you change any of the values here, it will be
# difficult to reuse existing chunks for newly-uploaded NARs
# since the cutpoints will be different. As a result, the
# deduplication ratio will suffer for a while after the change.
chunking = {
# The minimum NAR size to trigger chunking
#
# If 0, chunking is disabled entirely for newly-uploaded NARs.
# If 1, all NARs are chunked.
nar-size-threshold = 65536; # chunk files that are 64 KiB or larger
# The preferred minimum size of a chunk, in bytes
min-size = 16384; # 16 KiB
# The preferred average size of a chunk, in bytes
avg-size = 65536; # 64 KiB
# The preferred maximum size of a chunk, in bytes
max-size = 262144; # 256 KiB
};
# Compression
compression = {
# Compression type
#
# Can be "none", "brotli", "zstd", or "xz"
type = "zstd";
# Compression level
#level = 8;
};
# Garbage collection
garbage-collection = {
# The frequency to run garbage collection at
#
# By default it's 12 hours. You can use natural language
# to specify the interval, like "1 day".
#
# If zero, automatic garbage collection is disabled, but
# it can still be run manually with `atticd --mode garbage-collector-once`.
interval = "12 hours";
# Default retention period
#
# Zero (default) means time-based garbage-collection is
# disabled by default. You can enable it on a per-cache basis.
#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 `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.signing = {
# 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 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

@ -0,0 +1,14 @@
{ config, lib, ... }:
{
options.fediversity.attic =
(import ../sharedOptions.nix {
inherit config lib;
serviceName = "attic";
serviceDocName = "Attic Nix Cache server";
})
//
{
};
}

View file

@ -13,6 +13,7 @@ in
./mastodon
./pixelfed
./peertube
./attic
];
options = {
@ -49,7 +50,7 @@ in
displayName = mkOption {
type = types.str;
description = "Name of the initial user, for humans";
default = config.fediversity.temp.initialUser.username;
default = config.fediversity.temp.initialUser.name;
};
email = mkOption {
type = types.str;
@ -65,16 +66,4 @@ in
};
};
};
config = {
## FIXME: This should clearly go somewhere else; and we should have a
## `staging` vs. `production` setting somewhere.
security.acme = {
acceptTerms = true;
# use a priority more urgent than mkDefault for panel deployment to work,
# yet looser than default so this will not clash with the setting in tests.
defaults.email = lib.modules.mkOverride 200 "something@fediversity.net";
# defaults.server = "https://acme-staging-v02.api.letsencrypt.org/directory";
};
};
}

View file

@ -1,14 +0,0 @@
{ ... }:
{
_class = "flake";
perSystem =
{ pkgs, ... }:
{
checks = {
test-mastodon-service = pkgs.testers.runNixOSTest ./mastodon.nix;
test-pixelfed-garage-service = pkgs.testers.runNixOSTest ./pixelfed-garage.nix;
test-peertube-service = pkgs.testers.runNixOSTest ./peertube.nix;
};
};
}

View file

@ -6,7 +6,7 @@
{ pkgs, ... }:
let
inherit (pkgs) lib writeText;
lib = pkgs.lib;
## FIXME: this binding was not used, but maybe we want a side-effect or something?
# rebuildableTest = import ./rebuildableTest.nix pkgs;
@ -69,17 +69,9 @@ in
expect
];
environment.variables = {
AWS_ACCESS_KEY_ID = "$(cat ${config.fediversity.mastodon.s3AccessKeyFile})";
AWS_SECRET_ACCESS_KEY = "$(cat ${config.fediversity.mastodon.s3SecretKeyFile})";
AWS_ACCESS_KEY_ID = config.fediversity.garage.ensureKeys.mastodon.id;
AWS_SECRET_ACCESS_KEY = config.fediversity.garage.ensureKeys.mastodon.secret;
};
services.mastodon.extraEnvFiles = [
# generate as: cd ${pkgs.mastodon}; IGNORE_ALREADY_SET_SECRETS=true RAILS_ENV=development ${pkgs.mastodon}/bin/rails db:encryption:init
(writeText "rest" ''
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=naGoEzeyjUmwIlmgZZmGQDWJrlWud5eX
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=A0tE1VJ7S3cjaOQ58mNkhrVFY7o5NKDB
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=tGHhd5Os7hLxa8QTzWwjyVLrvsj5VsCw
'')
];
};
};

View file

@ -113,7 +113,6 @@ let
${seleniumQuit}'';
dummyFile = pkgs.writeText "dummy" "dummy";
in
{
name = "test-pixelfed-garage";
@ -162,8 +161,8 @@ in
];
environment.variables = {
POST_MEDIA = ./fediversity.png;
AWS_ACCESS_KEY_ID = "$(cat ${config.fediversity.pixelfed.s3AccessKeyFile})";
AWS_SECRET_ACCESS_KEY = "$(cat ${config.fediversity.pixelfed.s3SecretKeyFile})";
AWS_ACCESS_KEY_ID = config.fediversity.garage.ensureKeys.pixelfed.id;
AWS_SECRET_ACCESS_KEY = config.fediversity.garage.ensureKeys.pixelfed.secret;
## without this we get frivolous errors in the logs
MC_REGION = "garage";
};
@ -171,12 +170,6 @@ in
users.users.selenium = {
isNormalUser = true;
};
fediversity.temp.initialUser = {
username = "dummy";
displayName = "dummy";
email = "dummy";
passwordFile = dummyFile;
};
};
};