diff --git a/hosts/vps1/akkoma/akkoma-static.nix b/hosts/vps1/akkoma/akkoma-static.nix new file mode 100644 index 0000000..8555a89 --- /dev/null +++ b/hosts/vps1/akkoma/akkoma-static.nix @@ -0,0 +1,30 @@ +{ pkgs, config, lib, ... }: +let + imperativeStaticPath = "/data/akkoma/static_i"; + declarativeStaticPath = "/data/akkoma/static_d"; + mergedStaticPath = "/data/akkoma/static"; + declarativeStaticFiles = let cfg = config.services.akkoma; in with lib; pkgs.runCommandLocal "declarative-akkoma-static" { } '' + ${concatStringsSep "\n" (mapAttrsToList (key: val: '' + mkdir -p $out/frontends/${escapeShellArg val.name}/ + ln -s ${escapeShellArg val.package} $out/frontends/${escapeShellArg val.name}/${escapeShellArg val.ref} + '') cfg.frontends)} + + ${optionalString (cfg.extraStatic != null) + (concatStringsSep "\n" (mapAttrsToList (key: val: '' + mkdir -p "$out/$(dirname ${escapeShellArg key})" + ln -s ${escapeShellArg val} $out/${escapeShellArg key} + '') cfg.extraStatic))} + ''; +in +{ + environment.systemPackages = with pkgs; [ mergerfs ]; + systemd.tmpfiles.rules = [ + "d ${imperativeStaticPath} 700 akkoma akkoma -" + "L+ ${declarativeStaticPath} - - - - ${toString declarativeStaticFiles}" + ]; + fileSystems."${mergedStaticPath}" = { + fsType = "fuse.mergerfs"; + device = "${imperativeStaticPath}:${declarativeStaticPath}"; + options = [ "cache.files=off" "dropcacheonclose=true" "category.create=epff" ]; + }; +} \ No newline at end of file diff --git a/hosts/vps1/akkoma/akkoma.nix b/hosts/vps1/akkoma/akkoma.nix new file mode 100644 index 0000000..ebbc4ec --- /dev/null +++ b/hosts/vps1/akkoma/akkoma.nix @@ -0,0 +1,53 @@ +{ pkgs, lib, config, ... }: +let + inherit ((pkgs.formats.elixirConf {}).lib) mkMap mkAtom mkRaw mkTuple; +in +{ + services.akkoma = { + enable = true; + initSecrets = false; + patches.configurableFromDatabase = true; + # frontends.mastodon = { + # package = ; + # name = "mastodon-fe"; + # ref = "stable"; + # }; + extraPackages = with pkgs; [ zip unzip exiftool ffmpeg_5-headless graphicsmagick-imagemagick-compat ]; + config = { + ":pleroma".":instance" = { + name = "My Akkoma instance"; + description = "Akkoma instance description"; + email = "user@localhost"; + registrations_open = false; + federating = false; + upload_dir = "/data/akkoma/uploads"; + static_dir = "/data/akkoma/static"; + }; + ":pleroma"."Pleroma.Web.Endpoint" = { + url.host = config.myAkkomaContainerOptions.domain; + http.ip = config.myAkkomaContainerOptions.localAddress; + http.port = config.myAkkomaContainerOptions.localPort; + }; + + ":pleroma"."Pleroma.Uploaders.Local".uploads = "/data/akkoma/uploads"; + + ":pleroma".":mrf".policies = map mkRaw [ + "Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy" + "Pleroma.Web.ActivityPub.MRF.TagPolicy" + "Pleroma.Web.ActivityPub.MRF.SimplePolicy" + ]; + ":pleroma".":mrf_simple".accept = [ + (mkTuple ["good.instance" "good!"]) + ]; + + + ":pleroma"."Pleroma.Web.Endpoint".secret_key_base = { _secret = "/run/secrets/akkotest-vps/key-base"; }; + ":pleroma"."Pleroma.Web.Endpoint".signing_salt = { _secret = "/run/secrets/akkotest-vps/signing-salt"; }; + ":pleroma"."Pleroma.Web.Endpoint".live_view.signing_salt = { _secret = "/run/secrets/akkotest-vps/liveview-salt"; }; + ":web_push_encryption".":vapid_details".private_key = { _secret = "/run/secrets/akkotest-vps/vapid-private"; }; + ":web_push_encryption".":vapid_details".public_key = { _secret = "/run/secrets/akkotest-vps/vapid-public"; }; + ":joken".":default_signer" = { _secret = "/run/secrets/akkotest-vps/jwt-signer"; }; + + }; + }; +} \ No newline at end of file diff --git a/hosts/vps1/akkoma/akkontainer.nix b/hosts/vps1/akkoma/akkontainer.nix new file mode 100644 index 0000000..4144cde --- /dev/null +++ b/hosts/vps1/akkoma/akkontainer.nix @@ -0,0 +1,45 @@ +{ lib, config, ... }: +let + cfg = config.myAkkomaContainerOptions; +in +with lib; +{ + options.myAkkomaContainerOptions = { + enable = mkEnableOption "akkoma container tweaks"; + hostAddress = mkOption { + type = types.str; + }; + localAddress = mkOption { + type = types.str; + }; + localPort = mkOption { + type = types.int; + }; + domain = mkOption { + type = types.str; + }; + isContainer = mkOption { + type = types.uniq types.bool; + default = false; + }; + containerName = mkOption { + type = types.uniq types.str; + }; + }; + + + config = mkIf (cfg.enable && (!cfg.isContainer)) { + containers.${cfg.containerName}.config = + { config, pkgs, ... }: + { + myAkkomaContainerOptions = with cfg; { + isContainer = true; + inherit hostAddress; + inherit localAddress; + inherit localPort; + inherit domain; + # inherit containerName; + }; + }; + }; +} \ No newline at end of file diff --git a/hosts/vps1/akkotest.nix b/hosts/vps1/akkotest.nix new file mode 100644 index 0000000..3b99e18 --- /dev/null +++ b/hosts/vps1/akkotest.nix @@ -0,0 +1,156 @@ +{ config, pkgs, lib, ... }: +let + rootDomain = "lgmrszd.xyz"; + hostAddress = "192.168.100.10"; + localAddress = "192.168.100.11"; + localPort = 4000; + domain = "akko429164.testdrive.${rootDomain}"; +in +{ + imports = [ + ./akkoma/akkontainer.nix + ]; + + + services.nginx.virtualHosts."${domain}" = { + serverName = "${domain}"; + forceSSL = true; + useACMEHost = "${rootDomain}"; + locations."/" = { + proxyPass = "http://${localAddress}:${toString localPort}"; + proxyWebsockets = true; + recommendedProxySettings = true; + }; + }; + + sops.secrets = + let + sopsFile = ../../secrets/akkotest-vps.yaml; + format = "yaml"; + sopsPrefix = "akkotest-vps"; + mkSopsSecret = secretList: builtins.listToAttrs(map + (name: { + name = "${sopsPrefix}/${name}"; + value = { + inherit sopsFile; + inherit format; + }; + }) + secretList); + in mkSopsSecret [ + "vapid-private" + "vapid-public" + "liveview-salt" + "signing-salt" + "jwt-signer" + "key-base" + ]; + + myAkkomaContainerOptions = { + enable = true; + # hostAddress = "192.168.100.10"; + # localAddress = "192.168.100.11"; + # localPort = 4000; + # domain = "akkotest.local"; + inherit hostAddress; + inherit localAddress; + inherit localPort; + inherit domain; + containerName = "akkotest"; + }; + + users = { + users."akkoma" = { + description = "Fake Akkoma user to set up files permissions"; + group = "akkoma"; + isSystemUser = true; + uid = 1234; + }; + groups."akkoma" = { gid = 1234; }; + }; + + containers.akkotest = + let + outerConfig = config; + hostDataPrefix = "/data/akkotest"; + containerDataPrefix = "/data/akkotest"; + in + { + ephemeral = true; + privateNetwork = true; + inherit hostAddress; + inherit localAddress; + allowedDevices = [ + { + modifier = "rwm"; + node = "/dev/fuse"; + } + ]; + bindMounts."/dev/fuse" = {}; + bindMounts.static = { + hostPath = "/data/akkotest/static_i"; + mountPoint = "/data/akkoma/static_i"; + isReadOnly = false; + }; + bindMounts.db = { + hostPath = "/data/akkotest/postgresql"; + mountPoint = "/data/postgresql"; + isReadOnly = false; + }; + bindMounts.uploads = { + hostPath = "/data/akkotest/uploads"; + mountPoint = "/data/akkoma/uploads"; + isReadOnly = false; + }; + # bindMounts.secrets = { + # hostPath = "/data/secrets_akkotest"; + # mountPoint = "/var/akkosecrets"; + # isReadOnly = true; + # }; + bindMounts."/run/secrets/akkotest-vps" = { + isReadOnly = true; + }; + + config = + { config, pkgs, ... }: + { + imports = [ + ./akkoma/akkontainer.nix + ./akkoma/akkoma.nix + ./akkoma/akkoma-static.nix + ../../modules/akkoma-patches.nix + ]; + users = { + users."akkoma" = { + description = "Akkoma user"; + group = "akkoma"; + isSystemUser = true; + uid = 1234; + }; + groups."akkoma" = { gid = 1234; }; + }; + # myAkkomaContainerOptions = outerConfig.myAkkomaContainerOptions.mkInnerConfig; + # myAkkomaContainerOptions = { + # inherit hostAddress; + # inherit localAddress; + # inherit localPort; + # inherit domain; + # isContainer = true; + # }; + environment.systemPackages = with pkgs; [ zip unzip ]; + systemd.tmpfiles.rules = [ + "d /data/postgresql 700 postgres postgres -" + # "d /data/uploads 700 akkoma akkoma -" + # "d /var/akkosecrets 500 akkoma akkoma -" + ]; + services.postgresql = { + enable = true; + package = pkgs.postgresql_15; + dataDir = "/data/postgresql"; + }; + networking.firewall.allowedTCPPorts = [ + localPort + ]; + }; + }; +} \ No newline at end of file diff --git a/hosts/vps1/configuration.nix b/hosts/vps1/configuration.nix index dd2a0dc..571b585 100644 --- a/hosts/vps1/configuration.nix +++ b/hosts/vps1/configuration.nix @@ -3,14 +3,15 @@ let rootDomain = "lgmrszd.xyz"; gtnhDomain = "gtnh.${rootDomain}"; discDomain = "discourse.testdrive.${rootDomain}"; - akkoDomain = "akko.testdrive.${rootDomain}"; - iceDomain = "ice.testdrive.${rootDomain}"; + akkoDomain = "akko429164.testdrive.${rootDomain}"; + iceDomain = "ice758549.testdrive.${rootDomain}"; in { imports = [ ./hardware-configuration.nix + ./akkotest.nix + (fetchTarball { url = "https://github.com/cariandrum22/nixos-vscode-server/tarball/support-for-new-dir-structure-of-vscode-server"; sha256 = "1sp4h0nb7dh7mcm8vdflihv76yz8azf5zifkcbxhq7xz48c8k5pd"; }) - ]; @@ -55,39 +56,6 @@ in }; - containers.akkotest = let secretpath = "${config.sops.secrets.example_key.path}"; in { - ephemeral = true; - privateNetwork = true; - hostAddress = "192.168.100.10"; - localAddress = "192.168.100.11"; - bindMounts."${secretpath}".isReadOnly = true; - specialArgs = {inherit secretpath;}; - - config = - { config, pkgs, secretpath, ... }: - { - users = { - users."akkoma" = { - description = "Akkoma user"; - group = "akkoma"; - isSystemUser = true; - uid = 1234; - }; - groups."akkoma" = { gid = 1234; }; - }; - }; - }; - - users = { - users."akkoma" = { - description = "Fake Akkoma user to set up secrets permissions"; - group = "akkoma"; - isSystemUser = true; - uid = 1234; - }; - groups."akkoma" = { gid = 1234; }; - }; - sops = { defaultSopsFile = ../../secrets/secrets.yaml; defaultSopsFormat = "yaml"; @@ -128,11 +96,11 @@ in useACMEHost = "${rootDomain}"; root = "/var/www/todo"; }; - virtualHosts.${akkoDomain} = { - forceSSL = true; - useACMEHost = "${rootDomain}"; - root = "/var/www/todo"; - }; + # virtualHosts.${akkoDomain} = { + # forceSSL = true; + # useACMEHost = "${rootDomain}"; + # root = "/var/www/todo"; + # }; virtualHosts.${iceDomain} = { forceSSL = true; useACMEHost = "${rootDomain}"; @@ -149,6 +117,7 @@ in environmentFile = config.sops.secrets.porkbun.path; extraDomainNames = [ "*.${rootDomain}" + "*.testdrive.${rootDomain}" # gtnhDomain # akkoDomain # iceDomain diff --git a/secrets/akkotest-vps.yaml b/secrets/akkotest-vps.yaml new file mode 100644 index 0000000..2a804a1 --- /dev/null +++ b/secrets/akkotest-vps.yaml @@ -0,0 +1,48 @@ +akkotest-vps: + vapid-private: ENC[AES256_GCM,data:Qyck/0SyvgEFDGcTTYlGqBG5wDSZHaTfNWuMjeSL1C3HGa9Wj971NYGblA==,iv:bLuppFITnm1c7Mq8tXqukXlrSJoBkHcQ/LktwWTdl44=,tag:mLiZTrJMjh2jAmyzF/aafQ==,type:str] + vapid-public: ENC[AES256_GCM,data:5qyu5dx9zSzZGpyJ5jMZs5/Uf08bLY5wlvkdouEzW0TKUawG5as2srp/HkKP60WQgVdU5hWPJ6rN9IHWFmcYgE5QzLLW3DY9pGvRbCAWIDBsYf/gCU1v,iv:vfAnen/P1Ma0lOl2hEzvVCgiCZ8vgaIl+xv4dqFQbGw=,tag:INVm5LBLLgbF1zSy+05LoA==,type:str] + liveview-salt: ENC[AES256_GCM,data:Uyl0+wB99W0=,iv:IGndkDLzlbkM3mYnNXWNudZOIfUCmBUtxuI4rLOEJ54=,tag:MW9rzpLhch4dWnee7Q5AKw==,type:str] + signing-salt: ENC[AES256_GCM,data:ZfCHoqiaDag=,iv:WxQLjZ9bW+vBgUSKKayDKGVkS2iS044aUmByHXhoQ+Q=,tag:YENnPQYwyRAY17Fj46dV9g==,type:str] + jwt-signer: ENC[AES256_GCM,data:7g9d/ZGMBt7fpxgBV9vkogLBilq/+FN8lyiGL817i9cFRXXcsL9Bk3i82RS8CRiHBHpqxQGM+bOu2dtCFw4eDA==,iv:NO4rwcWuEOB3P6xr27+gd0qpSXa6WuFCINYwcuxZLdU=,tag:hsg6QxEL5VtNepZFx/8Pag==,type:str] + key-base: ENC[AES256_GCM,data:Aw/HP07GBbOs1KiI0WCP3cAs1WyyA5aL0UXCOsVrF/HquukRId2FzM8c2gu+F5UcPzGwuybmLm3cA79230WWJA==,iv:A3s5GMKYwHDEU8zTWePgyK4CQY/56N6r4sDOjYlj0hA=,tag:rZY8XI5xJWs3/JY7JlMLLQ==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1acgqxvyczgsamz53z3v0gmahzfxlg9tscwnrgcxrfndgxhsvn3vs4ss5tk + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzZDMyZlpzWnNkQWg5SkJr + Y1FyZlMwNWFTdi9ZdVZlZUVyN1JwNm1GVFhvCkoyM2JFK1JHeW0rbXB2elUrUmlG + Ym5tc0VYTmdrTmZ6NFNLZFVQd2xlZ1kKLS0tIG05QkdhUmJrUzBwdWtHZmhhV25y + akFsaU9Nb1NZQys3RklHUUpIOTEybTgK29g8D12Lx09RU6xviWRcnZw5TiFyALIM + PnInRDat+nwKO4v49ttTasoRbEvK1AVlRJ9kjj/RTyx+Rlq/2eaYVg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1xrzl49tvnatuu55xu5av6xcxyhrakd7mkzl5kz30kqqaxvh2m3sqax8jeu + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzY3NLL2RjeFpyTUVvWlBM + Uk16cXo3L3F2RzY5OHVhYWEyK1Jya3lQVkVFCnpuaTN2THI4YnZRUm5tbWxhNDdt + SkhxT2hwakVNaHdCMzdXSHlKQXA0YkUKLS0tIDR5K3h1RXlOVzdKdHVnWG4wdThI + d3JFdk10UGRqS0xFT2l6WFZpYVlGcE0KyrMH7z7ordSlvTAQ1wCaNtS66hS4e+Kn + /Q/bJVkie6+yufTencwEkG+j4f7LT6WV1lQ4I2YBx/WT6qk7H+EeNQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-02-18T10:43:53Z" + mac: ENC[AES256_GCM,data:FWfa41Njefc4R3t88RmdC1gra/nOejiAvhPy1C9S1ZW36HApVVh7hbKNyu1YpD7tjLliYfWETDLo1e6hDUDUGks78XfdgBzPc/hX9gmBXgZE3K82vV+KPYfttTUq6SCxusTqQKw22Szt4jFP48cRFEiMUdqelGikQxigoKZKhPU=,iv:UDsWQ1bX5M3vhXQ1xmgHOtUreXDIHATcdtD64nUrbnY=,tag:Zys4Aqng7MQQv85YtWGKFg==,type:str] + pgp: + - created_at: "2024-02-18T10:30:50Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DrTkQq20WUVESAQdAzfQDqcGhO2z3dLvouqjI2FHBzp0stP7HDRLdGhfqPh8w + uCiHVRq1c/6Tz8DaeAJpxoYseN8ytkkfU8SKpiwq+wIw/7mP6HFCWIC0BFjgOcOA + 1GgBCQIQuCwDRIsaZa81L8/raAwOnuPqfI9MBdBOyanC/BmkjBdwvy8TGEBOIYwg + 768duwdY/oI7cBFsV9ljbBbvZB+1ayZQsC7qyKdFa2PEGF5qV4+LuqzhQLzt9DJ8 + O6YvuHin17w70g== + =xA7J + -----END PGP MESSAGE----- + fp: D3067BE844D3FC49535A47B29396B8BA6FBB14DE + unencrypted_suffix: _unencrypted + version: 3.8.1