nixos-test-pixelfed-wip #22

Merged
taeer merged 11 commits from nixos-test-pixelfed-wip into main 2024-09-20 17:47:21 +02:00
9 changed files with 68 additions and 29 deletions
Showing only changes of commit 9d1f20fc1c - Show all commits

View file

@ -1,6 +1,7 @@
{ lib, ... }: { lib, config, ... }:
let let
inherit (builtins) toString;
inherit (lib) mkOption; inherit (lib) mkOption;
inherit (lib.types) types; inherit (lib.types) types;
@ -19,9 +20,38 @@ in {
default = false; default = false;
}; };
garage = mkOption {
type = types.anything;
};
domain = mkOption {
type = types.string;
};
mastodon.enable = mkOption { type = types.bool; default = false; }; mastodon.enable = mkOption { type = types.bool; default = false; };
pixelfed.enable = mkOption { type = types.bool; default = false; }; pixelfed.enable = mkOption { type = types.bool; default = false; };
peertube.enable = mkOption { type = types.bool; default = false; }; peertube.enable = mkOption { type = types.bool; default = false; };
}; };
}; };
config.fediversity = {
garage = {
api = rec {
domain = "s3.garage.${config.fediversity.domain}";
port = 3900;
url = "http://${domain}:${toString port}";
};
rpc = rec {
port = 3901;
};
web = rec {
rootDomain = "web.garage.${config.fediversity.domain}";
port = 3902;
rootDomainAndPort = "${rootDomain}:${toString port}";
urlFor = bucket: "http://${bucket}.${rootDomainAndPort}";
};
};
};
} }

View file

@ -11,6 +11,7 @@ in
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
inherit (builtins) toString;
inherit (lib) types mkOption mkEnableOption optionalString concatStringsSep; inherit (lib) types mkOption mkEnableOption optionalString concatStringsSep;
inherit (lib.strings) escapeShellArg; inherit (lib.strings) escapeShellArg;
cfg = config.services.garage; cfg = config.services.garage;
@ -41,7 +42,7 @@ let
${optionalString corsRules.enable '' ${optionalString corsRules.enable ''
garage bucket allow --read --write --owner ${bucketArg} --key tmp garage bucket allow --read --write --owner ${bucketArg} --key tmp
# TODO: endpoin-url should not be hard-coded # TODO: endpoin-url should not be hard-coded
aws --region ${cfg.settings.s3_api.s3_region} --endpoint-url http://s3.garage.localhost:3900 s3api put-bucket-cors --bucket ${bucketArg} --cors-configuration ${corsRulesJSON} aws --region ${cfg.settings.s3_api.s3_region} --endpoint-url ${config.fediversity.garage.api.url} s3api put-bucket-cors --bucket ${bucketArg} --cors-configuration ${corsRulesJSON}
garage bucket deny --read --write --owner ${bucketArg} --key tmp garage bucket deny --read --write --owner ${bucketArg} --key tmp
''} ''}
''; '';
@ -135,19 +136,22 @@ in
virtualisation.forwardPorts = [ virtualisation.forwardPorts = [
{ {
from = "host"; from = "host";
host.port = 3901; host.port = config.fediversity.garage.rpc.port;
guest.port = 3901; guest.port = config.fediversity.garage.rpc.port;
} }
{ {
from = "host"; from = "host";
host.port = 3902; host.port = config.fediversity.garage.web.port;
guest.port = 3902; guest.port = config.fediversity.garage.web.port;
} }
]; ];
environment.systemPackages = [ pkgs.minio-client pkgs.awscli ]; environment.systemPackages = [ pkgs.minio-client pkgs.awscli ];
networking.firewall.allowedTCPPorts = [ 3901 3902 ]; networking.firewall.allowedTCPPorts = [
config.fediversity.garage.rpc.port
config.fediversity.garage.web.port
];
services.garage = { services.garage = {
enable = true; enable = true;
package = pkgs.garage_0_9; package = pkgs.garage_0_9;
@ -156,15 +160,15 @@ in
# TODO: use a secret file # TODO: use a secret file
rpc_secret = "d576c4478cc7d0d94cfc127138cbb82018b0155c037d1c827dfb6c36be5f6625"; rpc_secret = "d576c4478cc7d0d94cfc127138cbb82018b0155c037d1c827dfb6c36be5f6625";
# TODO: why does this have to be set? is there not a sensible default? # TODO: why does this have to be set? is there not a sensible default?
rpc_bind_addr = "[::]:3901"; rpc_bind_addr = "[::]:${toString config.fediversity.garage.rpc.port}";
rpc_public_addr = "[::1]:3901"; rpc_public_addr = "[::1]:${toString config.fediversity.garage.rpc.port}";
s3_api.api_bind_addr = "[::]:3900"; s3_api.api_bind_addr = "[::]:${toString config.fediversity.garage.api.port}";
s3_web.bind_addr = "[::]:3902"; s3_web.bind_addr = "[::]:${toString config.fediversity.garage.web.port}";
s3_web.root_domain = ".web.garage.localhost"; s3_web.root_domain = ".${config.fediversity.garage.web.rootDomain}";
index = "index.html"; index = "index.html";
s3_api.s3_region = "garage"; s3_api.s3_region = "garage";
s3_api.root_domain = ".s3.garage.localhost"; s3_api.root_domain = ".${config.fediversity.garage.api.domain}";
}; };
}; };
systemd.services.ensure-garage = { systemd.services.ensure-garage = {
@ -177,9 +181,9 @@ in
script = '' script = ''
set -xeuo pipefail set -xeuo pipefail
# Give garage time to start up by waiting until somethings speaks HTTP # Give Garage time to start up by waiting until somethings speaks HTTP
# behind localhost:3900. # behind Garage's API URL.
until ${pkgs.curl}/bin/curl -sio /dev/null http://localhost:3900/; do sleep 1; done until ${pkgs.curl}/bin/curl -sio /dev/null ${config.fediversity.garage.api.url}; do sleep 1; done
# XXX: this is very sensitive to being a single instance # XXX: this is very sensitive to being a single instance
# (doing the bare minimum to get garage up and running) # (doing the bare minimum to get garage up and running)

View file

@ -38,7 +38,7 @@ lib.mkIf (config.fediversity.enable && config.fediversity.mastodon.enable) {
extraConfig = rec { extraConfig = rec {
S3_ENABLED = "true"; S3_ENABLED = "true";
# TODO: this shouldn't be hard-coded, it should come from the garage configuration # TODO: this shouldn't be hard-coded, it should come from the garage configuration
S3_ENDPOINT = "http://s3.garage.localhost:3900"; S3_ENDPOINT = config.fediversity.garage.api.url;
S3_REGION = "garage"; S3_REGION = "garage";
S3_BUCKET = "mastodon"; S3_BUCKET = "mastodon";
# use <S3_BUCKET>.<S3_ENDPOINT> # use <S3_BUCKET>.<S3_ENDPOINT>
@ -46,7 +46,7 @@ lib.mkIf (config.fediversity.enable && config.fediversity.mastodon.enable) {
AWS_ACCESS_KEY_ID = snakeoil_key.id; AWS_ACCESS_KEY_ID = snakeoil_key.id;
AWS_SECRET_ACCESS_KEY = snakeoil_key.secret; AWS_SECRET_ACCESS_KEY = snakeoil_key.secret;
S3_PROTOCOL = "http"; S3_PROTOCOL = "http";
S3_HOSTNAME = "web.garage.localhost:3902"; S3_HOSTNAME = config.fediversity.garage.web.rootDomainAndPort;
# by default it tries to use "<S3_HOSTNAME>/<S3_BUCKET>" # by default it tries to use "<S3_HOSTNAME>/<S3_BUCKET>"
S3_ALIAS_HOST = "${S3_BUCKET}.${S3_HOSTNAME}"; S3_ALIAS_HOST = "${S3_BUCKET}.${S3_HOSTNAME}";
# SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/ # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/

View file

@ -56,27 +56,27 @@ lib.mkIf (config.fediversity.enable && config.fediversity.peertube.enable) {
settings = { settings = {
object_storage = { object_storage = {
enabled = true; enabled = true;
endpoint = "http://s3.garage.localhost:3900"; endpoint = config.fediversity.garage.api.url;
region = "garage"; region = "garage";
# not supported by garage # not supported by garage
# SEE: https://garagehq.deuxfleurs.fr/documentation/connect/apps/#peertube # SEE: https://garagehq.deuxfleurs.fr/documentation/connect/apps/#peertube
proxy.proxyify_private_files = false; proxy.proxyify_private_files = false;
web_videos = { web_videos = rec {
bucket_name = "peertube-videos"; bucket_name = "peertube-videos";
prefix = ""; prefix = "";
base_url = "http://peertube-videos.web.garage.localhost:3902"; base_url = config.fediversity.garage.web.urlFor bucket_name;
}; };
videos = { videos = rec {
bucket_name = "peertube-videos"; bucket_name = "peertube-videos";
prefix = ""; prefix = "";
base_url = "http://peertube-videos.web.garage.localhost:3902"; base_url = config.fediversity.garage.web.urlFor bucket_name;
}; };
streaming_playlists = { streaming_playlists = rec {
bucket_name = "peertube-playlists"; bucket_name = "peertube-playlists";
prefix = ""; prefix = "";
base_url = "http://peertube-playlists.web.garage.localhost:3902"; base_url = config.fediversity.garage.web.urlFor bucket_name;
}; };
}; };
}; };

View file

@ -37,7 +37,6 @@ lib.mkIf (config.fediversity.enable && config.fediversity.pixelfed.enable) {
services.pixelfed.enable = true; services.pixelfed.enable = true;
# TODO: factor these out so we're only defining e.g. s3.garage.localhost and port 3900 in one place
services.pixelfed.settings = { services.pixelfed.settings = {
# DANGEROUSLY_SET_FILESYSTEM_DRIVER = "s3"; # DANGEROUSLY_SET_FILESYSTEM_DRIVER = "s3";
FILESYSTEM_CLOUD = "s3"; FILESYSTEM_CLOUD = "s3";
@ -45,9 +44,9 @@ lib.mkIf (config.fediversity.enable && config.fediversity.pixelfed.enable) {
AWS_ACCESS_KEY_ID = snakeoil_key.id; AWS_ACCESS_KEY_ID = snakeoil_key.id;
AWS_SECRET_ACCESS_KEY = snakeoil_key.secret; AWS_SECRET_ACCESS_KEY = snakeoil_key.secret;
AWS_DEFAULT_REGION = "garage"; AWS_DEFAULT_REGION = "garage";
AWS_URL = "http://pixelfed.web.garage.localhost:3902/"; AWS_URL = config.fediversity.garage.web.urlFor "pixelfed";
AWS_BUCKET = "pixelfed"; AWS_BUCKET = "pixelfed";
AWS_ENDPOINT = "http://s3.garage.localhost:3900"; AWS_ENDPOINT = config.fediversity.garage.api.url;
AWS_USE_PATH_STYLE_ENDPOINT = false; AWS_USE_PATH_STYLE_ENDPOINT = false;
}; };

View file

@ -95,6 +95,7 @@ pkgs.nixosTest {
server.succeed("toot post --media $POST_MEDIA") server.succeed("toot post --media $POST_MEDIA")
with subtest("access garage"): with subtest("access garage"):
## REVIEW: could we grab `config.fediversity.garage.api.url` here in some way?
server.succeed("mc alias set garage http://s3.garage.localhost:3900 --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY") server.succeed("mc alias set garage http://s3.garage.localhost:3900 --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY")
Review

Yes! In typical nix dynamically-typed fashion, testScript can also be a function! And we can have

testScript = { nodes, ... }: ''
...
   ${nodes.server.fediversity.garage.api.url}
...
'';
Yes! In typical nix dynamically-typed fashion, `testScript` can also be a function! And we can have ``` testScript = { nodes, ... }: '' ... ${nodes.server.fediversity.garage.api.url} ... ''; ```
server.succeed("mc ls garage/mastodon") server.succeed("mc ls garage/mastodon")
@ -121,6 +122,7 @@ pkgs.nixosTest {
raise Exception("mastodon did not send a content security policy header") raise Exception("mastodon did not send a content security policy header")
csp = csp_match.group(1) csp = csp_match.group(1)
# the img-src content security policy should include the garage server # the img-src content security policy should include the garage server
## REVIEW: could we grab `config.fediversity.garage.web.url` here in some way?
garage_csp = re.match(".*; img-src[^;]*web\.garage\.localhost:3902.*", csp) garage_csp = re.match(".*; img-src[^;]*web\.garage\.localhost:3902.*", csp)
if garage_csp is None: if garage_csp is None:
raise Exception("Mastodon's content security policy does not include garage server. image will not be displayed properly on mastodon.") raise Exception("Mastodon's content security policy does not include garage server. image will not be displayed properly on mastodon.")

View file

@ -186,6 +186,7 @@ pkgs.nixosTest {
raise Exception("cannot detect the uploaded image on pixelfed page.") raise Exception("cannot detect the uploaded image on pixelfed page.")
with subtest("access garage"): with subtest("access garage"):
## REVIEW: could we grab `config.fediversity.garage.api.url` here in some way?
server.succeed("mc alias set garage http://s3.garage.localhost:3900 --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY") server.succeed("mc alias set garage http://s3.garage.localhost:3900 --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY")
server.succeed("mc ls garage/pixelfed") server.succeed("mc ls garage/pixelfed")
@ -202,6 +203,7 @@ pkgs.nixosTest {
with subtest("Check that image comes from garage"): with subtest("Check that image comes from garage"):
src = server.succeed("su - selenium -c 'selenium-script-get-src ${email} ${password}'") src = server.succeed("su - selenium -c 'selenium-script-get-src ${email} ${password}'")
## REVIEW: could we grab `config.fediversity.garage.web.url` here in some way?
if not src.startswith("http://pixelfed.web.garage.localhost:3902/"): if not src.startswith("http://pixelfed.web.garage.localhost:3902/"):
raise Exception("image does not come from garage") raise Exception("image does not come from garage")
''; '';

View file

@ -9,6 +9,7 @@
{ {
fediversity = { fediversity = {
enable = true; enable = true;
domain = "localhost";
mastodon.enable = true; mastodon.enable = true;
}; };

View file

@ -7,6 +7,7 @@
fediversity = { fediversity = {
enable = true; enable = true;
domain = "localhost";
pixelfed.enable = true; pixelfed.enable = true;
}; };
@ -24,7 +25,7 @@
# I feel like this should have an `enable` option and be configured via `services.nginx` rather than mirroring those options in services.pixelfed.nginx # I feel like this should have an `enable` option and be configured via `services.nginx` rather than mirroring those options in services.pixelfed.nginx
# TODO: If that indeed makes sense, upstream it. # TODO: If that indeed makes sense, upstream it.
nginx = { nginx = {
# locations."/public/".proxyPass = "http://pixelfed.web.garage.localhost:3902/public/"; # locations."/public/".proxyPass = "${config.fediversity.garage.web.urlFor "pixelfed"}/public/";
}; };
}; };
virtualisation.memorySize = 2048; virtualisation.memorySize = 2048;