diff --git a/services/README.md b/services/README.md index 6ef0b93..7d1b7c0 100644 --- a/services/README.md +++ b/services/README.md @@ -40,7 +40,7 @@ NOTE: it sometimes takes a while for the services to start up, and in the meanti ``` - Creating other accounts has to be enabled via the admin interface. `Administration > Configuration > Basic > Enable Signup` or just add an account directly from `Administration > Create user`. But functionality can also be tested from the root account. -- Pixelfed: +- Pixelfed: through the reverse proxy at - Account creation via the web interface won't work until we figure out email - For now, they can be created on the VM command line ```bash diff --git a/services/fediversity/garage.nix b/services/fediversity/garage.nix index 16b5702..f43fe11 100644 --- a/services/fediversity/garage.nix +++ b/services/fediversity/garage.nix @@ -216,6 +216,10 @@ in proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Disable buffering to a temporary file. proxy_max_temp_file_size 0; + + ## NOTE: This page suggests many more options for the object storage + ## proxy. We should take a look. + ## https://docs.joinmastodon.org/admin/optional/object-storage-proxy/ ''; }; }; diff --git a/services/fediversity/mastodon.nix b/services/fediversity/mastodon.nix index 8cd7454..2ed4b3e 100644 --- a/services/fediversity/mastodon.nix +++ b/services/fediversity/mastodon.nix @@ -46,9 +46,7 @@ lib.mkIf (config.fediversity.enable && config.fediversity.mastodon.enable) { AWS_ACCESS_KEY_ID = snakeoil_key.id; AWS_SECRET_ACCESS_KEY = snakeoil_key.secret; S3_PROTOCOL = "http"; - S3_HOSTNAME = config.fediversity.internal.garage.web.rootDomain; - # by default it tries to use "/" - S3_ALIAS_HOST = "${S3_BUCKET}.${S3_HOSTNAME}"; + S3_ALIAS_HOST = "${S3_BUCKET}.${config.fediversity.internal.garage.web.rootDomain}"; # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/ # TODO: can we set up ACLs with garage? S3_PERMISSION = ""; @@ -78,9 +76,6 @@ lib.mkIf (config.fediversity.enable && config.fediversity.mastodon.enable) { fromAddress = "noreply@${config.fediversity.internal.mastodon.domain}"; createLocally = false; }; - - # TODO: this is hardware-dependent. let's figure it out when we have hardware - # streamingProcesses = 1; }; security.acme = { diff --git a/services/flake-part.nix b/services/flake-part.nix index 01c941a..5563878 100644 --- a/services/flake-part.nix +++ b/services/flake-part.nix @@ -7,7 +7,7 @@ { pkgs, ... }: { checks = { - mastodon-garage = import ./tests/mastodon-garage.nix { inherit self pkgs; }; + mastodon = import ./tests/mastodon.nix { inherit self pkgs; }; pixelfed-garage = import ./tests/pixelfed-garage.nix { inherit self pkgs; }; }; }; diff --git a/services/tests/mastodon-garage.nix b/services/tests/mastodon.nix similarity index 74% rename from services/tests/mastodon-garage.nix rename to services/tests/mastodon.nix index b0a9d62..7bd36e1 100644 --- a/services/tests/mastodon-garage.nix +++ b/services/tests/mastodon.nix @@ -1,10 +1,19 @@ +## This file is a basic test of Mastodon functionalities. +## +## NOTE: This test will fail for Mastodon < 4.3 because of +## https://github.com/mastodon/mastodon/issues/31145 + { pkgs, self }: + let lib = pkgs.lib; ## FIXME: this binding was not used, but maybe we want a side-effect or something? # rebuildableTest = import ./rebuildableTest.nix pkgs; + testImage = pkgs.copyPathToStore ./green.png; + testImageColour = "#00FF00"; + seleniumScript = pkgs.writers.writePython3Bin "selenium-script" { libraries = with pkgs.python3Packages; [ selenium ]; } @@ -14,8 +23,6 @@ let from selenium.webdriver.firefox.options import Options from selenium.webdriver.support.ui import WebDriverWait - print(1) - options = Options() options.add_argument("--headless") # devtools don't show up in headless screenshots @@ -23,7 +30,7 @@ let service = webdriver.FirefoxService(executable_path="${lib.getExe pkgs.geckodriver}") # noqa: E501 driver = webdriver.Firefox(options=options, service=service) - driver.get("http://mastodon.localhost:55001/public/local") + driver.get("http://mastodon.localhost/public/local") # wait until the statuses load WebDriverWait(driver, 90).until( @@ -34,6 +41,7 @@ let driver.close() ''; in + pkgs.nixosTest { name = "test-mastodon-garage"; @@ -46,6 +54,7 @@ pkgs.nixosTest { fediversity ../vm/garage-vm.nix ../vm/mastodon-vm.nix + ../vm/interactive-vm.nix ]; # TODO: pair down environment.systemPackages = with pkgs; [ @@ -57,9 +66,9 @@ pkgs.nixosTest { seleniumScript helix imagemagick + expect ]; environment.variables = { - POST_MEDIA = ./green.png; AWS_ACCESS_KEY_ID = config.services.garage.ensureKeys.mastodon.id; AWS_SECRET_ACCESS_KEY = config.services.garage.ensureKeys.mastodon.secret; }; @@ -87,64 +96,67 @@ pkgs.nixosTest { if password_match is None: raise Exception(f"account creation did not generate a password.\n{account_creation_output}") password = password_match.group(1) - - with subtest("TTY Login"): - server.wait_until_tty_matches("1", "login: ") - server.send_chars("root\n"); + # print(f"Test user (test@test.com)'s password is: {password}") with subtest("Log in with toot"): - # toot doesn't provide a way to just specify our login details as arguments, so we have to pretend we're typing them in at the prompt - server.send_chars("toot login_cli --instance http://mastodon.localhost:55001 --email test@test.com\n") - server.wait_until_tty_matches("1", "Password: ") - server.send_chars(password + "\n") - server.wait_until_tty_matches("1", "Successfully logged in.") + # toot doesn't provide a way to just specify our login details as + # arguments, so we have to pretend we're typing them in at the prompt; + # we use 'expect' for this purpose. + server.succeed(f""" + expect -c ' + spawn toot login_cli --instance http://mastodon.localhost:55001 --email test@test.com + expect "Password: " + send "{password}\\n" + interact + ' >&2 + """) - with subtest("post text"): + with subtest("Post a text"): server.succeed("echo 'hello mastodon' | toot post") - with subtest("post image"): - server.succeed("toot post --media $POST_MEDIA") + with subtest("Post an image"): + server.succeed("toot post --media ${testImage}") - with subtest("access garage"): + with subtest("Access garage"): server.succeed("mc alias set garage ${nodes.server.fediversity.internal.garage.api.url} --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY") server.succeed("mc ls garage/mastodon") - with subtest("access image in garage"): + with subtest("Access image in garage"): image = server.succeed("mc find garage --regex original") image = image.rstrip() if image == "": raise Exception("image posted to mastodon did not get stored in garage") server.succeed(f"mc cat {image} >/garage-image.webp") garage_image_hash = server.succeed("identify -quiet -format '%#' /garage-image.webp") - image_hash = server.succeed("identify -quiet -format '%#' $POST_MEDIA") + image_hash = server.succeed("identify -quiet -format '%#' ${testImage}") if garage_image_hash != image_hash: raise Exception("image stored in garage did not match image uploaded") - with subtest("Content security policy allows garage images"): + with subtest("Content-Security-Policy allows garage content"): headers = server.succeed("xh -h http://mastodon.localhost:55001/public/local") csp_match = None # I can't figure out re.MULTILINE for header in headers.split("\n"): - csp_match = re.match('^Content-Security-Policy: (.*)$', header) + csp_match = re.match('^Content-Security-Policy: (.*)$', header) if csp_match is not None: break if csp_match is None: raise Exception("mastodon did not send a content security policy header") csp = csp_match.group(1) - # the img-src content security policy should include the garage server + # the connect-src content security policy should include the garage server ## TODO: use `nodes.server.fediversity.internal.garage.api.url` same as above, but beware of escaping the regex. Be careful with port 80 though. garage_csp = re.match(".*; img-src[^;]*web\.garage\.localhost.*", csp) 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.") - # this could in theory give a false positive if mastodon changes it's colorscheme to include pure green. - with subtest("image displays"): + # this could in theory give a false positive if mastodon changes it's colorscheme to include ${testImageColour}. + with subtest("Image displays"): server.succeed("selenium-script") server.copy_from_vm("/mastodon-screenshot.png", "") displayed_colors = server.succeed("convert /mastodon-screenshot.png -define histogram:unique-colors=true -format %c histogram:info:") - # check that the green image displayed somewhere - green_check = re.match(".*#00FF00.*", displayed_colors, re.S) - if green_check is None: + # check that the image displayed somewhere + image_check = re.match(".*${testImageColour}.*", displayed_colors, re.S) + if image_check is None: raise Exception("cannot detect the uploaded image on mastodon page.") ''; } diff --git a/services/tests/pixelfed-garage.nix b/services/tests/pixelfed-garage.nix index 849a45c..56c5d11 100644 --- a/services/tests/pixelfed-garage.nix +++ b/services/tests/pixelfed-garage.nix @@ -186,7 +186,7 @@ pkgs.nixosTest { server.succeed("pixelfed-manage user:create --name=test --username=test --email=${email} --password=${password} --confirm_email=1") # NOTE: This could in theory give a false positive if pixelfed changes it's - # colorscheme to include pure green. (see same problem in pixelfed-garage.nix). + # colorscheme to include pure green. (see same problem in mastodon-garage.nix). # TODO: For instance: post a red image and check that the green pixel IS NOT # there, then post a green image and check that the green pixel IS there. diff --git a/services/vm/interactive-vm.nix b/services/vm/interactive-vm.nix index 449864a..738f580 100644 --- a/services/vm/interactive-vm.nix +++ b/services/vm/interactive-vm.nix @@ -32,29 +32,8 @@ extra-experimental-features = nix-command flakes ''; - # no graphics. see nixos-shell - virtualisation = { - graphics = false; - qemu.consoles = [ - "tty0" - "hvc0" - ]; - qemu.options = [ - "-serial null" - "-device virtio-serial" - "-chardev stdio,mux=on,id=char0,signal=off" - "-mon chardev=char0,mode=readline" - "-device virtconsole,chardev=char0,nr=0" - ]; - }; + virtualisation.memorySize = 2048; - # we can't forward port 80 or 443, so let's run nginx on a different port - networking.firewall.allowedTCPPorts = [ - 8443 - 8080 - ]; - services.nginx.defaultSSLListenPort = 8443; - services.nginx.defaultHTTPListenPort = 8080; virtualisation.forwardPorts = [ { from = "host"; @@ -64,12 +43,12 @@ { from = "host"; host.port = 8080; - guest.port = 8080; + guest.port = 80; } { from = "host"; host.port = 8443; - guest.port = 8443; + guest.port = 443; } ]; } diff --git a/services/vm/mastodon-vm.nix b/services/vm/mastodon-vm.nix index fdaf71e..5a9daf2 100644 --- a/services/vm/mastodon-vm.nix +++ b/services/vm/mastodon-vm.nix @@ -33,15 +33,6 @@ email = "none"; }; }; - - virtualisation.memorySize = 2048; - virtualisation.forwardPorts = [ - { - from = "host"; - host.port = 44443; - guest.port = 443; - } - ]; } #### run mastodon as development environment @@ -58,7 +49,6 @@ BIND = "0.0.0.0"; # for letter_opener (still doesn't work though) REMOTE_DEV = "true"; - LOCAL_DOMAIN = "${config.fediversity.internal.mastodon.domain}:8443"; }; }; diff --git a/services/vm/pixelfed-vm.nix b/services/vm/pixelfed-vm.nix index b5e820f..927d042 100644 --- a/services/vm/pixelfed-vm.nix +++ b/services/vm/pixelfed-vm.nix @@ -23,13 +23,4 @@ in enableACME = mkVMOverride false; }; }; - - virtualisation.memorySize = 2048; - virtualisation.forwardPorts = [ - { - from = "host"; - host.port = 8000; - guest.port = 80; - } - ]; }