diff --git a/home-server.nix b/home-server.nix index 707ded7..d49b1cc 100644 --- a/home-server.nix +++ b/home-server.nix @@ -29,6 +29,7 @@ in with builtins; { ./services/paperless.nix ./services/nextcloud.nix ./services/calibre-web.nix + ./services/focalboard.nix ]; age.secrets.cloudflare.file = ./secrets/cloudflare.age; @@ -89,6 +90,7 @@ in with builtins; { "news.felschr.com" "etebase.felschr.com" "paperless.felschr.com" + "boards.felschr.com" ]; extraConfig = with pkgs; '' usev6=cmdv6, cmdv6=${ diff --git a/secrets/focalboard/.env.age b/secrets/focalboard/.env.age new file mode 100644 index 0000000..035df86 Binary files /dev/null and b/secrets/focalboard/.env.age differ diff --git a/secrets/focalboard/db-password.age b/secrets/focalboard/db-password.age new file mode 100644 index 0000000..0db040f --- /dev/null +++ b/secrets/focalboard/db-password.age @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 OAZQhA dxA+WbNEn/S09SFxcocGPj2b1NhorC1/qmjpq5rtxh0 +qSMHnpKjYm/wFX2aspH8ciuZrDrY80GoUbb1+xnHwXg +-> ssh-ed25519 72ij7w tW82g/+efG37VE2f5QW0k/oy0pWzUg5ZXBG/8OaRSW8 +PCNKgRF41kD+LpzeHq+QONwiSw7pvfMhqa+3iljRw98 +-> TM0[wD[-grease ] )A`15 < D +hHJtcXJ+ +--- L78Bv0VeBpdNUDkDnp5Dm3RZlU1ywVo/IhXwL1d9Ol0 +©ÛJúĬHZºP¸U_äiÅ0,í‰^41ÝÄh™D’"ÿò öpÿð_˜µ0¬+ÅcëÍ|/Ð-CçÎÇÉÀÂjJ 8U¹ \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index eca37ef..cd35cf6 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -31,4 +31,6 @@ in { "home-server/hostKey.age".publicKeys = [ felschr home-server ]; "hass/secrets.age".publicKeys = [ felschr home-server ]; "esphome/password.age".publicKeys = [ felschr home-server ]; + "focalboard/.env.age".publicKeys = [ felschr home-server ]; + "focalboard/db-password.age".publicKeys = [ felschr home-server ]; } diff --git a/services/focalboard.nix b/services/focalboard.nix new file mode 100644 index 0000000..c01490c --- /dev/null +++ b/services/focalboard.nix @@ -0,0 +1,77 @@ +{ config, lib, pkgs, ... }: + +let + dataDir = "/var/lib/focalboard"; + ociBackend = config.virtualisation.oci-containers.backend; + containersHost = "localhost"; + port = 8003; + domain = "boards.felschr.com"; + dbHost = containersHost; + dbPort = toString config.services.postgresql.port; + dbUser = "focalboard"; + dbName = "focalboard"; + dbPasswordFile = config.age.secrets.focalboard-db-password.path; + + pgSuperUser = config.services.postgresql.superUser; +in { + age.secrets.focalboard-env.file = ../secrets/focalboard/.env.age; + age.secrets.focalboard-db-password.file = + ../secrets/focalboard/db-password.age; + + services.postgresql = { + enable = true; + enableTCPIP = true; + ensureDatabases = [ dbName ]; + ensureUsers = [{ + name = dbUser; + ensurePermissions."DATABASE ${dbName}" = "ALL PRIVILEGES"; + }]; + }; + + systemd.services.focalboard-init = { + enable = true; + description = "Set up paths & database access for Focalboard"; + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; + before = [ "${ociBackend}-focalboard.service" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + LoadCredential = [ "db_password:${dbPasswordFile}" ]; + }; + script = '' + mkdir -p ${dataDir} + echo "Set focalboard postgres user password" + db_password="$(<"$CREDENTIALS_DIRECTORY/db_password")" + ${pkgs.sudo}/bin/sudo -u ${pgSuperUser} ${pkgs.postgresql}/bin/psql postgres \ + -c "alter user ${dbUser} with password '$db_password'" + ''; + }; + + virtualisation.oci-containers.containers.focalboard = { + image = "mattermost/focalboard"; + ports = [ "${toString port}:${toString port}" ]; + volumes = [ "${dataDir}:/var/lib/focalboard" ]; + environment = { + FOCALBOARD_PORT = toString port; + FOCALBOARD_DBTYPE = "postgres"; + }; + # only secrets need to be included, e.g. FOCALBOARD_DBCONFIG + environmentFiles = [ config.age.secrets.focalboard-env.path ]; + extraOptions = [ "--network=host" ]; + }; + + systemd.services."${ociBackend}-focalboard" = { + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; + }; + + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://localhost:${toString port}"; + proxyWebsockets = true; + }; + }; +}