forked from fediversity/fediversity
		
	separate vm.nix files for vm-specific configuration
This commit is contained in:
		
							parent
							
								
									366a67e112
								
							
						
					
					
						commit
						353c0a7ffa
					
				
					 12 changed files with 324 additions and 313 deletions
				
			
		
							
								
								
									
										67
									
								
								common.nix
									
										
									
									
									
								
							
							
						
						
									
										67
									
								
								common.nix
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,67 +0,0 @@
 | 
			
		|||
{ pkgs, ... }: {
 | 
			
		||||
  # customize nixos-rebuild build-vm to be a bit more convenient
 | 
			
		||||
  virtualisation.vmVariant = {
 | 
			
		||||
    # let us log in
 | 
			
		||||
    users.mutableUsers = false;
 | 
			
		||||
    users.users.root.hashedPassword = "";
 | 
			
		||||
    services.openssh = {
 | 
			
		||||
      enable = true;
 | 
			
		||||
      settings = {
 | 
			
		||||
        PermitRootLogin = "yes";
 | 
			
		||||
        PermitEmptyPasswords = "yes";
 | 
			
		||||
        UsePAM = "no";
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    # automatically log in
 | 
			
		||||
    services.getty.autologinUser = "root";
 | 
			
		||||
    services.getty.helpLine = ''
 | 
			
		||||
      Type `C-a c` to access the qemu console
 | 
			
		||||
      Type `C-a x` to quit
 | 
			
		||||
    '';
 | 
			
		||||
    # access to convenient things
 | 
			
		||||
    environment.systemPackages = with pkgs; [
 | 
			
		||||
      w3m
 | 
			
		||||
      python3
 | 
			
		||||
      xterm # for `resize`
 | 
			
		||||
    ];
 | 
			
		||||
    environment.loginShellInit = ''
 | 
			
		||||
      eval "$(resize)"
 | 
			
		||||
    '';
 | 
			
		||||
    nix.extraOptions = ''
 | 
			
		||||
      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"
 | 
			
		||||
      ];
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    # 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";
 | 
			
		||||
        host.port = 8080;
 | 
			
		||||
        guest.port = 8080;
 | 
			
		||||
      }
 | 
			
		||||
      {
 | 
			
		||||
        from = "host";
 | 
			
		||||
        host.port = 8443;
 | 
			
		||||
        guest.port = 8443;
 | 
			
		||||
      }
 | 
			
		||||
    ];
 | 
			
		||||
    
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								flake.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										16
									
								
								flake.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -2,18 +2,14 @@
 | 
			
		|||
  "nodes": {
 | 
			
		||||
    "nixpkgs": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1708475490,
 | 
			
		||||
        "narHash": "sha256-g1v0TsWBQPX97ziznfJdWhgMyMGtoBFs102xSYO4syU=",
 | 
			
		||||
        "owner": "nixos",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "0e74ca98a74bc7270d28838369593635a5db3260",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
        "lastModified": 1724846166,
 | 
			
		||||
        "narHash": "sha256-Um1Ahz09XHepSA1QQmdQk8nbsJEwHe54gP3naWp6D94=",
 | 
			
		||||
        "path": "/home/qolen/nixpkgs",
 | 
			
		||||
        "type": "path"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nixos",
 | 
			
		||||
        "ref": "nixos-unstable",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
        "path": "/home/qolen/nixpkgs",
 | 
			
		||||
        "type": "path"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "root": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										21
									
								
								flake.nix
									
										
									
									
									
								
							
							
						
						
									
										21
									
								
								flake.nix
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2,7 +2,8 @@
 | 
			
		|||
  description = "Testing mastodon configurations";
 | 
			
		||||
 | 
			
		||||
  inputs = {
 | 
			
		||||
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
 | 
			
		||||
    # nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
 | 
			
		||||
    nixpkgs.url = "path:/home/qolen/nixpkgs";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  outputs = { self, nixpkgs }: 
 | 
			
		||||
| 
						 | 
				
			
			@ -12,31 +13,41 @@
 | 
			
		|||
  in {
 | 
			
		||||
 | 
			
		||||
    nixosModules = {
 | 
			
		||||
      interactive-vm = import ./interactive-vm.nix;
 | 
			
		||||
      mastodon = import ./mastodon.nix;
 | 
			
		||||
      mastodon-vm = import ./mastodon-vm.nix;
 | 
			
		||||
      peertube = import ./peertube.nix;
 | 
			
		||||
      peertube-vm = import ./peertube-vm.nix;
 | 
			
		||||
      pixelfed = import ./pixelfed.nix;
 | 
			
		||||
      pixelfed-vm = import ./pixelfed-vm.nix;
 | 
			
		||||
      garage = import ./garage.nix;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    nixosConfigurations = {
 | 
			
		||||
      mastodon = nixpkgs.lib.nixosSystem {
 | 
			
		||||
        inherit system;
 | 
			
		||||
        modules = [ ./common.nix ./mastodon.nix ./garage.nix ];
 | 
			
		||||
        modules = with self.nixosModules; [ interactive-vm mastodon mastodon-vm garage ];
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      peertube = nixpkgs.lib.nixosSystem {
 | 
			
		||||
        inherit system;
 | 
			
		||||
        modules = [ ./common.nix ./peertube.nix ./garage.nix ];
 | 
			
		||||
        modules = with self.nixosModules; [ interactive-vm peertube peertube-vm garage ];
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      pixelfed = nixpkgs.lib.nixosSystem {
 | 
			
		||||
        inherit system;
 | 
			
		||||
        modules = [ ./common.nix ./pixelfed.nix ./garage.nix ];
 | 
			
		||||
        modules = with self.nixosModules; [ interactive-vm pixelfed pixelfed-vm garage ];
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      all = nixpkgs.lib.nixosSystem {
 | 
			
		||||
        inherit system;
 | 
			
		||||
        modules = [ ./common.nix ./mastodon.nix ./peertube.nix ./pixelfed.nix ./garage.nix ];
 | 
			
		||||
        modules = with self.nixosModules; [
 | 
			
		||||
          interactive-vm
 | 
			
		||||
          peertube peertube-vm
 | 
			
		||||
          pixelfed pixelfed-vm
 | 
			
		||||
          mastodon mastodon-vm
 | 
			
		||||
          garage
 | 
			
		||||
        ];
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										64
									
								
								interactive-vm.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								interactive-vm.nix
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
# customize nixos-rebuild build-vm to be a bit more convenient
 | 
			
		||||
{ pkgs, ... }: {
 | 
			
		||||
  # let us log in
 | 
			
		||||
  users.mutableUsers = false;
 | 
			
		||||
  users.users.root.hashedPassword = "";
 | 
			
		||||
  services.openssh = {
 | 
			
		||||
    enable = true;
 | 
			
		||||
    settings = {
 | 
			
		||||
      PermitRootLogin = "yes";
 | 
			
		||||
      PermitEmptyPasswords = "yes";
 | 
			
		||||
      UsePAM = false;
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  # automatically log in
 | 
			
		||||
  services.getty.autologinUser = "root";
 | 
			
		||||
  services.getty.helpLine = ''
 | 
			
		||||
    Type `C-a c` to access the qemu console
 | 
			
		||||
    Type `C-a x` to quit
 | 
			
		||||
  '';
 | 
			
		||||
  # access to convenient things
 | 
			
		||||
  environment.systemPackages = with pkgs; [
 | 
			
		||||
    w3m
 | 
			
		||||
    python3
 | 
			
		||||
    xterm # for `resize`
 | 
			
		||||
  ];
 | 
			
		||||
  environment.loginShellInit = ''
 | 
			
		||||
    eval "$(resize)"
 | 
			
		||||
  '';
 | 
			
		||||
  nix.extraOptions = ''
 | 
			
		||||
    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"
 | 
			
		||||
    ];
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  # 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";
 | 
			
		||||
      host.port = 8080;
 | 
			
		||||
      guest.port = 8080;
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
      from = "host";
 | 
			
		||||
      host.port = 8443;
 | 
			
		||||
      guest.port = 8443;
 | 
			
		||||
    }
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										118
									
								
								mastodon-vm.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								mastodon-vm.nix
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,118 @@
 | 
			
		|||
{ modulesPath, lib, config, ... }: {
 | 
			
		||||
 | 
			
		||||
  imports = [ (modulesPath + "/virtualisation/qemu-vm.nix") ];
 | 
			
		||||
 | 
			
		||||
  config = lib.mkMerge [
 | 
			
		||||
    {
 | 
			
		||||
      services.mastodon = {
 | 
			
		||||
        # redirects to localhost, but allows it to have a proper domain name
 | 
			
		||||
        localDomain = "mastodon.localhost";
 | 
			
		||||
 | 
			
		||||
        smtp = {
 | 
			
		||||
          fromAddress = "mastodon@mastodon.localhost";
 | 
			
		||||
          createLocally = false;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        extraConfig = {
 | 
			
		||||
          EMAIL_DOMAIN_ALLOWLIST = "example.com";
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        # from the documentation: recommended is the amount of your CPU cores
 | 
			
		||||
        # minus one. but it also must be a positive integer
 | 
			
		||||
        streamingProcesses = lib.max 1 (config.virtualisation.cores - 1);
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      security.acme = {
 | 
			
		||||
        defaults = {
 | 
			
		||||
          # invalid server; the systemd service will fail, and we won't get
 | 
			
		||||
          # properly signed certificates. but let's not spam the letsencrypt
 | 
			
		||||
          # servers (and we don't own this domain anyways)
 | 
			
		||||
          server = "https://127.0.0.1";
 | 
			
		||||
          email = "none";
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      virtualisation.memorySize = 2048;
 | 
			
		||||
      virtualisation.forwardPorts = [
 | 
			
		||||
        {
 | 
			
		||||
          from = "host";
 | 
			
		||||
          host.port = 44443;
 | 
			
		||||
          guest.port = 443;
 | 
			
		||||
        }
 | 
			
		||||
      ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #### run mastodon as development environment
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
      networking.firewall.allowedTCPPorts = [ 55001 ];
 | 
			
		||||
      services.mastodon = {
 | 
			
		||||
        # needed so we can directly access mastodon at port 55001
 | 
			
		||||
        # otherwise, mastodon has to be accessed *from* port 443, which we can't do via port forwarding
 | 
			
		||||
        enableUnixSocket = false;
 | 
			
		||||
        extraConfig = {
 | 
			
		||||
          RAILS_ENV = "development";
 | 
			
		||||
          # to be accessible from outside the VM
 | 
			
		||||
          BIND = "0.0.0.0";
 | 
			
		||||
          # for letter_opener (still doesn't work though)
 | 
			
		||||
          REMOTE_DEV = "true";
 | 
			
		||||
          LOCAL_DOMAIN = "mastodon.localhost:8443";
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      services.postgresql = {
 | 
			
		||||
        enable = true;
 | 
			
		||||
        ensureUsers = [
 | 
			
		||||
          {
 | 
			
		||||
            name = config.services.mastodon.database.user;
 | 
			
		||||
            ensureClauses.createdb = true;
 | 
			
		||||
            # ensurePermissions doesn't work anymore
 | 
			
		||||
            # ensurePermissions = {
 | 
			
		||||
            #   "mastodon_development.*" = "ALL PRIVILEGES";
 | 
			
		||||
            #   "mastodon_test.*" = "ALL PRIVILEGES";
 | 
			
		||||
            # }
 | 
			
		||||
          }
 | 
			
		||||
        ];
 | 
			
		||||
        # ensureDatabases = [ "mastodon_development_test" "mastodon_test" ];
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      # Currently, nixos seems to be able to create a single database per
 | 
			
		||||
      # postgres user. This works for the production version of mastodon, which
 | 
			
		||||
      # is what's packaged in nixpkgs. For development, we need two databases,
 | 
			
		||||
      # mastodon_development and mastodon_test. This used to be possible with
 | 
			
		||||
      # ensurePermissions, but that's broken and has been removed. Here I copy
 | 
			
		||||
      # the mastodon-init-db script from upstream nixpkgs, but add the single
 | 
			
		||||
      # line `rails db:setup`, which asks mastodon to create the postgres
 | 
			
		||||
      # databases for us.
 | 
			
		||||
      # FIXME: the commented out lines were breaking things, but presumably they're necessary for something.
 | 
			
		||||
      # TODO: see if we can fix the upstream ensurePermissions stuff. See commented out lines in services.postgresql above for what that config would look like.
 | 
			
		||||
      systemd.services.mastodon-init-db.script = lib.mkForce ''
 | 
			
		||||
        result="$(psql -t --csv -c \
 | 
			
		||||
            "select count(*) from pg_class c \
 | 
			
		||||
            join pg_namespace s on s.oid = c.relnamespace \
 | 
			
		||||
            where s.nspname not in ('pg_catalog', 'pg_toast', 'information_schema') \
 | 
			
		||||
            and s.nspname not like 'pg_temp%';")" || error_code=$?
 | 
			
		||||
        if [ "''${error_code:-0}" -ne 0 ]; then
 | 
			
		||||
          echo "Failure checking if database is seeded. psql gave exit code $error_code"
 | 
			
		||||
          exit "$error_code"
 | 
			
		||||
        fi
 | 
			
		||||
        if [ "$result" -eq 0 ]; then
 | 
			
		||||
          echo "Seeding database"
 | 
			
		||||
          rails db:setup
 | 
			
		||||
          # SAFETY_ASSURED=1 rails db:schema:load
 | 
			
		||||
          rails db:seed
 | 
			
		||||
        # else
 | 
			
		||||
          # echo "Migrating database (this might be a noop)"
 | 
			
		||||
          # rails db:migrate
 | 
			
		||||
        fi
 | 
			
		||||
      '';
 | 
			
		||||
      virtualisation.forwardPorts = [
 | 
			
		||||
        {
 | 
			
		||||
          from = "host";
 | 
			
		||||
          host.port = 55001;
 | 
			
		||||
          guest.port = 55001;
 | 
			
		||||
        }
 | 
			
		||||
      ];
 | 
			
		||||
    }
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										230
									
								
								mastodon.nix
									
										
									
									
									
								
							
							
						
						
									
										230
									
								
								mastodon.nix
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -4,188 +4,78 @@ let
 | 
			
		|||
    secret = "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34";
 | 
			
		||||
  };
 | 
			
		||||
in
 | 
			
		||||
{ config, lib, pkgs, ... }: lib.mkMerge [
 | 
			
		||||
  { # garage setup
 | 
			
		||||
    services.garage = {
 | 
			
		||||
      ensureBuckets = {
 | 
			
		||||
        mastodon = {
 | 
			
		||||
          website = true;
 | 
			
		||||
          corsRules = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            allowedHeaders = [ "*" ];
 | 
			
		||||
            allowedMethods = [ "GET" ];
 | 
			
		||||
            allowedOrigins = [ "*" ];
 | 
			
		||||
          };
 | 
			
		||||
{ config, lib, pkgs, ... }: {
 | 
			
		||||
 #### garage setup
 | 
			
		||||
  services.garage = {
 | 
			
		||||
    ensureBuckets = {
 | 
			
		||||
      mastodon = {
 | 
			
		||||
        website = true;
 | 
			
		||||
        corsRules = {
 | 
			
		||||
          enable = true;
 | 
			
		||||
          allowedHeaders = [ "*" ];
 | 
			
		||||
          allowedMethods = [ "GET" ];
 | 
			
		||||
          allowedOrigins = [ "*" ];
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
      ensureKeys = {
 | 
			
		||||
        mastodon = {
 | 
			
		||||
          inherit (snakeoil_key) id secret;
 | 
			
		||||
          ensureAccess = {
 | 
			
		||||
            mastodon = {
 | 
			
		||||
              read = true;
 | 
			
		||||
              write = true;
 | 
			
		||||
              owner = true;
 | 
			
		||||
            };
 | 
			
		||||
    };
 | 
			
		||||
    ensureKeys = {
 | 
			
		||||
      mastodon = {
 | 
			
		||||
        inherit (snakeoil_key) id secret;
 | 
			
		||||
        ensureAccess = {
 | 
			
		||||
          mastodon = {
 | 
			
		||||
            read = true;
 | 
			
		||||
            write = true;
 | 
			
		||||
            owner = true;
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
    services.mastodon = {
 | 
			
		||||
      extraConfig = rec {
 | 
			
		||||
        S3_ENABLED = "true";
 | 
			
		||||
        S3_ENDPOINT = "http://s3.garage.localhost:3900";
 | 
			
		||||
        S3_REGION = "garage";
 | 
			
		||||
        S3_BUCKET = "mastodon";
 | 
			
		||||
        # use <S3_BUCKET>.<S3_ENDPOINT>
 | 
			
		||||
        S3_OVERRIDE_PATH_STLE = "true";
 | 
			
		||||
        AWS_ACCESS_KEY_ID = snakeoil_key.id;
 | 
			
		||||
        AWS_SECRET_ACCESS_KEY = snakeoil_key.secret;
 | 
			
		||||
        S3_PROTOCOL = "http";
 | 
			
		||||
        S3_HOSTNAME = "web.garage.localhost:3902";
 | 
			
		||||
        # by default it tries to use "<S3_HOSTNAME>/<S3_BUCKET>"
 | 
			
		||||
        S3_ALIAS_HOST = "${S3_BUCKET}.${S3_HOSTNAME}";
 | 
			
		||||
        # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/
 | 
			
		||||
        # TODO: can we set up ACLs with garage?
 | 
			
		||||
        S3_PERMISSION = "";
 | 
			
		||||
      };
 | 
			
		||||
  };
 | 
			
		||||
  services.mastodon = {
 | 
			
		||||
    extraConfig = rec {
 | 
			
		||||
      S3_ENABLED = "true";
 | 
			
		||||
      # TODO: this shouldn't be hard-coded, it should come from the garage configuration
 | 
			
		||||
      S3_ENDPOINT = "http://s3.garage.localhost:3900";
 | 
			
		||||
      S3_REGION = "garage";
 | 
			
		||||
      S3_BUCKET = "mastodon";
 | 
			
		||||
      # use <S3_BUCKET>.<S3_ENDPOINT>
 | 
			
		||||
      S3_OVERRIDE_PATH_STLE = "true";
 | 
			
		||||
      AWS_ACCESS_KEY_ID = snakeoil_key.id;
 | 
			
		||||
      AWS_SECRET_ACCESS_KEY = snakeoil_key.secret;
 | 
			
		||||
      S3_PROTOCOL = "http";
 | 
			
		||||
      S3_HOSTNAME = "web.garage.localhost:3902";
 | 
			
		||||
      # by default it tries to use "<S3_HOSTNAME>/<S3_BUCKET>"
 | 
			
		||||
      S3_ALIAS_HOST = "${S3_BUCKET}.${S3_HOSTNAME}";
 | 
			
		||||
      # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/
 | 
			
		||||
      # TODO: can we set up ACLs with garage?
 | 
			
		||||
      S3_PERMISSION = "";
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
  # mastodon setup
 | 
			
		||||
  {
 | 
			
		||||
    # open up access to the mastodon web interface
 | 
			
		||||
    networking.firewall.allowedTCPPorts = [ 443 ];
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
    services.mastodon = {
 | 
			
		||||
      enable = true;
 | 
			
		||||
  #### mastodon setup
 | 
			
		||||
 | 
			
		||||
      # TODO: set up a domain name, and a DNS service so that this can run not in a vm
 | 
			
		||||
      # localDomain = "domain.social";
 | 
			
		||||
      configureNginx = true;
 | 
			
		||||
  # open up access to the mastodon web interface
 | 
			
		||||
  networking.firewall.allowedTCPPorts = [ 443 ];
 | 
			
		||||
 | 
			
		||||
      # TODO: configure a mailserver so this works
 | 
			
		||||
      # smtp.fromAddress = "mastodon@mastodon.localhost";
 | 
			
		||||
  services.mastodon = {
 | 
			
		||||
    enable = true;
 | 
			
		||||
 | 
			
		||||
      # TODO: this is hardware-dependent. let's figure it out when we have hardware
 | 
			
		||||
      # streamingProcesses = 1;
 | 
			
		||||
    };
 | 
			
		||||
    # TODO: set up a domain name, and a DNS service so that this can run not in a vm
 | 
			
		||||
    # localDomain = "domain.social";
 | 
			
		||||
    configureNginx = true;
 | 
			
		||||
 | 
			
		||||
    security.acme = {
 | 
			
		||||
      acceptTerms = true;
 | 
			
		||||
      preliminarySelfsigned = true;
 | 
			
		||||
      # TODO: configure a mailserver so we can set up acme
 | 
			
		||||
      # defaults.email = "test@example.com";
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
    # TODO: configure a mailserver so this works
 | 
			
		||||
    # smtp.fromAddress = "mastodon@domain.social";
 | 
			
		||||
 | 
			
		||||
  # VM setup
 | 
			
		||||
  {
 | 
			
		||||
    services.mastodon = {
 | 
			
		||||
      # redirects to localhost, but allows it to have a proper domain name
 | 
			
		||||
      localDomain = "mastodon.localhost";
 | 
			
		||||
    # TODO: this is hardware-dependent. let's figure it out when we have hardware
 | 
			
		||||
    # streamingProcesses = 1;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
      smtp = {
 | 
			
		||||
        fromAddress = "mastodon@mastodon.localhost";
 | 
			
		||||
        createLocally = false;
 | 
			
		||||
      };
 | 
			
		||||
  security.acme = {
 | 
			
		||||
    acceptTerms = true;
 | 
			
		||||
    preliminarySelfsigned = true;
 | 
			
		||||
    # TODO: configure a mailserver so we can set up acme
 | 
			
		||||
    # defaults.email = "test@example.com";
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
      extraConfig = {
 | 
			
		||||
        EMAIL_DOMAIN_ALLOWLIST = "example.com";
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      # from the documentation: recommended is the amount of your CPU cores minus one.
 | 
			
		||||
      # but it also must be a positive integer
 | 
			
		||||
      streamingProcesses = lib.max 1 (config.virtualisation.cores - 1);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    security.acme = {
 | 
			
		||||
      defaults = {
 | 
			
		||||
        # invalid server; the systemd service will fail, and we won't get properly signed certificates
 | 
			
		||||
        # but let's not spam the letsencrypt servers (and we don't own this domain anyways)
 | 
			
		||||
        server = "https://127.0.0.1";
 | 
			
		||||
        email = "none";
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    virtualisation.memorySize = 2048;
 | 
			
		||||
    virtualisation.forwardPorts = [
 | 
			
		||||
      {
 | 
			
		||||
        from = "host";
 | 
			
		||||
        host.port = 44443;
 | 
			
		||||
        guest.port = 443;
 | 
			
		||||
      }
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  # run mastodon as development environment
 | 
			
		||||
  {
 | 
			
		||||
    networking.firewall.allowedTCPPorts = [ 55001 ];
 | 
			
		||||
    services.mastodon = {
 | 
			
		||||
      # needed so we can directly access mastodon at port 55001
 | 
			
		||||
      # otherwise, mastodon has to be accessed *from* port 443, which we can't do via port forwarding
 | 
			
		||||
      enableUnixSocket = false;
 | 
			
		||||
      extraConfig = {
 | 
			
		||||
        RAILS_ENV = "development";
 | 
			
		||||
        # to be accessible from outside the VM
 | 
			
		||||
        BIND = "0.0.0.0";
 | 
			
		||||
        # for letter_opener (still doesn't work though)
 | 
			
		||||
        REMOTE_DEV = "true";
 | 
			
		||||
        LOCAL_DOMAIN = "mastodon.localhost:8443";
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    services.postgresql = {
 | 
			
		||||
      enable = true;
 | 
			
		||||
      ensureUsers = [
 | 
			
		||||
        {
 | 
			
		||||
          name = config.services.mastodon.database.user;
 | 
			
		||||
          ensureClauses.createdb = true;
 | 
			
		||||
          # ensurePermissions doesn't work anymore
 | 
			
		||||
          # ensurePermissions = {
 | 
			
		||||
          #   "mastodon_development.*" = "ALL PRIVILEGES";
 | 
			
		||||
          #   "mastodon_test.*" = "ALL PRIVILEGES";
 | 
			
		||||
          # }
 | 
			
		||||
        }
 | 
			
		||||
      ];
 | 
			
		||||
      # ensureDatabases = [ "mastodon_development_test" "mastodon_test" ];
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    # Currently, nixos seems to be able to create a single database per
 | 
			
		||||
    # postgres user. This works for the production version of mastodon, which
 | 
			
		||||
    # is what's packaged in nixpkgs. For development, we need two databases,
 | 
			
		||||
    # mastodon_development and mastodon_test. This used to be possible with
 | 
			
		||||
    # ensurePermissions, but that's broken and has been removed. Here I copy
 | 
			
		||||
    # the mastodon-init-db script from upstream nixpkgs, but add the single
 | 
			
		||||
    # line `rails db:setup`, which asks mastodon to create the postgres
 | 
			
		||||
    # databases for us.
 | 
			
		||||
    # FIXME: the commented out lines were breaking things, but presumably they're necessary for something.
 | 
			
		||||
    # TODO: see if we can fix the upstream ensurePermissions stuff. See above for what that config would look like.
 | 
			
		||||
    systemd.services.mastodon-init-db.script = lib.mkForce ''
 | 
			
		||||
      result="$(psql -t --csv -c \
 | 
			
		||||
          "select count(*) from pg_class c \
 | 
			
		||||
          join pg_namespace s on s.oid = c.relnamespace \
 | 
			
		||||
          where s.nspname not in ('pg_catalog', 'pg_toast', 'information_schema') \
 | 
			
		||||
          and s.nspname not like 'pg_temp%';")" || error_code=$?
 | 
			
		||||
      if [ "''${error_code:-0}" -ne 0 ]; then
 | 
			
		||||
        echo "Failure checking if database is seeded. psql gave exit code $error_code"
 | 
			
		||||
        exit "$error_code"
 | 
			
		||||
      fi
 | 
			
		||||
      if [ "$result" -eq 0 ]; then
 | 
			
		||||
        echo "Seeding database"
 | 
			
		||||
        rails db:setup
 | 
			
		||||
        # SAFETY_ASSURED=1 rails db:schema:load
 | 
			
		||||
        rails db:seed
 | 
			
		||||
      # else
 | 
			
		||||
        # echo "Migrating database (this might be a noop)"
 | 
			
		||||
        # rails db:migrate
 | 
			
		||||
      fi
 | 
			
		||||
    '';
 | 
			
		||||
    virtualisation.forwardPorts = [
 | 
			
		||||
      {
 | 
			
		||||
        from = "host";
 | 
			
		||||
        host.port = 55001;
 | 
			
		||||
        guest.port = 55001;
 | 
			
		||||
      }
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										30
									
								
								peertube-vm.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								peertube-vm.nix
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
{ pkgs, modulesPath, ... }: {
 | 
			
		||||
  imports = [ (modulesPath + "/virtualisation/qemu-vm.nix") ];
 | 
			
		||||
  services.peertube = {
 | 
			
		||||
    enable = true;
 | 
			
		||||
    # redirects to localhost, but allows it to have a proper domain name
 | 
			
		||||
    localDomain = "peertube.localhost";
 | 
			
		||||
    enableWebHttps = false;
 | 
			
		||||
    settings = {
 | 
			
		||||
      listen.hostname = "0.0.0.0";
 | 
			
		||||
      instance.name = "PeerTube Test VM";
 | 
			
		||||
    };
 | 
			
		||||
    # TODO: use agenix
 | 
			
		||||
    secrets.secretsFile = pkgs.writeText "secret" ''
 | 
			
		||||
      574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24
 | 
			
		||||
    '';
 | 
			
		||||
 | 
			
		||||
    # TODO: in most of nixpkgs, these are true by default. upstream that unless there's a good reason not to.
 | 
			
		||||
    redis.createLocally = true;
 | 
			
		||||
    database.createLocally = true;
 | 
			
		||||
    configureNginx = true;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  virtualisation.forwardPorts = [
 | 
			
		||||
    {
 | 
			
		||||
      from = "host";
 | 
			
		||||
      host.port = 9000;
 | 
			
		||||
      guest.port = 9000;
 | 
			
		||||
    }
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								peertube.nix
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								peertube.nix
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -83,34 +83,4 @@ in
 | 
			
		|||
    AWS_ACCESS_KEY_ID=${snakeoil_key.id}
 | 
			
		||||
    AWS_SECRET_ACCESS_KEY=${snakeoil_key.secret}
 | 
			
		||||
  '';
 | 
			
		||||
 | 
			
		||||
  virtualisation.vmVariant = { config, ... }: {
 | 
			
		||||
    services.peertube = {
 | 
			
		||||
      enable = true;
 | 
			
		||||
      # redirects to localhost, but allows it to have a proper domain name
 | 
			
		||||
      localDomain = "peertube.localhost";
 | 
			
		||||
      enableWebHttps = false;
 | 
			
		||||
      settings = {
 | 
			
		||||
        listen.hostname = "0.0.0.0";
 | 
			
		||||
        instance.name = "PeerTube Test VM";
 | 
			
		||||
      };
 | 
			
		||||
      # TODO: use agenix
 | 
			
		||||
      secrets.secretsFile = pkgs.writeText "secret" ''
 | 
			
		||||
        574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24
 | 
			
		||||
      '';
 | 
			
		||||
 | 
			
		||||
      # TODO: in most of nixpkgs, these are true by default. upstream that unless there's a good reason not to.
 | 
			
		||||
      redis.createLocally = true;
 | 
			
		||||
      database.createLocally = true;
 | 
			
		||||
      configureNginx = true;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    virtualisation.forwardPorts = [
 | 
			
		||||
      {
 | 
			
		||||
        from = "host";
 | 
			
		||||
        host.port = 9000;
 | 
			
		||||
        guest.port = 9000;
 | 
			
		||||
      }
 | 
			
		||||
    ];
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										27
									
								
								pixelfed-vm.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								pixelfed-vm.nix
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
{ pkgs, modulesPath, ... }: {
 | 
			
		||||
  imports = [ (modulesPath + "/virtualisation/qemu-vm.nix") ];
 | 
			
		||||
  networking.firewall.allowedTCPPorts = [ 80 ];
 | 
			
		||||
  services.pixelfed = {
 | 
			
		||||
    enable = true;
 | 
			
		||||
    domain = "pixelfed.localhost";
 | 
			
		||||
    # TODO: secrets management!
 | 
			
		||||
    secretFile = pkgs.writeText "secrets.env" ''
 | 
			
		||||
      APP_KEY=adKK9EcY8Hcj3PLU7rzG9rJ6KKTOtYfA
 | 
			
		||||
    '';
 | 
			
		||||
    settings = {
 | 
			
		||||
      OPEN_REGISTRATION = true;
 | 
			
		||||
      FORCE_HTTPS_URLS = false;
 | 
			
		||||
    };
 | 
			
		||||
    # 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.
 | 
			
		||||
    nginx = {};
 | 
			
		||||
  };
 | 
			
		||||
  virtualisation.memorySize = 2048;
 | 
			
		||||
  virtualisation.forwardPorts = [
 | 
			
		||||
    {
 | 
			
		||||
      from = "host";
 | 
			
		||||
      host.port = 8000;
 | 
			
		||||
      guest.port = 80;
 | 
			
		||||
    }
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								pixelfed.nix
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								pixelfed.nix
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -5,7 +5,6 @@ let
 | 
			
		|||
  };
 | 
			
		||||
in
 | 
			
		||||
{ config, lib, pkgs, ... }: {
 | 
			
		||||
 | 
			
		||||
  services.garage = {
 | 
			
		||||
    ensureBuckets = {
 | 
			
		||||
      pixelfed = {
 | 
			
		||||
| 
						 | 
				
			
			@ -45,31 +44,4 @@ in
 | 
			
		|||
    AWS_ENDPOINT = "http://s3.garage.localhost:3900";
 | 
			
		||||
    AWS_USE_PATH_STYLE_ENDPOINT = false;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  virtualisation.vmVariant = {
 | 
			
		||||
    networking.firewall.allowedTCPPorts = [ 80 ];
 | 
			
		||||
    services.pixelfed = {
 | 
			
		||||
      enable = true;
 | 
			
		||||
      domain = "pixelfed.localhost";
 | 
			
		||||
      # TODO: secrets management!
 | 
			
		||||
      secretFile = pkgs.writeText "secrets.env" ''
 | 
			
		||||
        APP_KEY=adKK9EcY8Hcj3PLU7rzG9rJ6KKTOtYfA
 | 
			
		||||
      '';
 | 
			
		||||
      settings = {
 | 
			
		||||
        OPEN_REGISTRATION = true;
 | 
			
		||||
        FORCE_HTTPS_URLS = false;
 | 
			
		||||
      };
 | 
			
		||||
      # I feel like this should have an `enable` option and be configured via `services.nginx` rather than mirroring those options here
 | 
			
		||||
      # TODO: If that indeed makes sense, upstream it.
 | 
			
		||||
      nginx = {};
 | 
			
		||||
    };
 | 
			
		||||
    virtualisation.memorySize = 2048;
 | 
			
		||||
    virtualisation.forwardPorts = [
 | 
			
		||||
      {
 | 
			
		||||
        from = "host";
 | 
			
		||||
        host.port = 8000;
 | 
			
		||||
        guest.port = 80;
 | 
			
		||||
      }
 | 
			
		||||
    ];
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,9 +37,9 @@ rebuildableTest {
 | 
			
		|||
  name = "test-mastodon-garage";
 | 
			
		||||
 | 
			
		||||
  nodes = {
 | 
			
		||||
    server = {config, ...}: {
 | 
			
		||||
    server = { config, ... }: {
 | 
			
		||||
      virtualisation.memorySize = lib.mkVMOverride 4096;
 | 
			
		||||
      imports = [ self.nixosModules.garage self.nixosModules.mastodon ];
 | 
			
		||||
      imports = with self.nixosModules; [ garage mastodon mastodon-vm ];
 | 
			
		||||
      # TODO: pair down
 | 
			
		||||
      environment.systemPackages = with pkgs; [
 | 
			
		||||
        python3
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ let
 | 
			
		|||
      settings = {
 | 
			
		||||
        PermitRootLogin = "yes";
 | 
			
		||||
        PermitEmptyPasswords = "yes";
 | 
			
		||||
        UsePAM = "no";
 | 
			
		||||
        UsePAM = false;
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue