diff --git a/secrets/default.nix b/secrets/default.nix index 2e96df6..141308e 100644 --- a/secrets/default.nix +++ b/secrets/default.nix @@ -33,5 +33,13 @@ in { file = ./zitadel-key.age; owner = abstrServiceUser "zitadel"; }; + forgejo-mailpass = mkIf server { + file = ./forgejo-mailpass.age; + owner = abstrServiceUser "forgejo"; + }; + immich-oidc = mkIf server { + file = ./immich-oidc.age; + owner = abstrServiceUser "immich"; + }; }; } diff --git a/secrets/forgejo-mailpass.age b/secrets/forgejo-mailpass.age new file mode 100644 index 0000000..eed7f49 --- /dev/null +++ b/secrets/forgejo-mailpass.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-ed25519 GQzYWA j5yj1cq9FbYSW767zObF4RbJ7Jhx0818BryvWGWwnSw +LelnyL/SIat9BKl4hsz0n6rl8xPgchk+nQmfb1xkXkU +-> ssh-ed25519 MfR7VA sVGSrPd10dOdnDNROMGW1gLuczlVwMLpymgx6+cCJRE +8vf0ubRiRUWfc6Mgt0bNq99SgrY4pYJ0f4BHVRn+lYU +-> ssh-ed25519 +cvRTg VK4bHTmw+Oz7JLdP0zEbfKTjNUBtVxcbHX4zyZrQxx4 +1BjqL4TuNJO8VH9c2MT24ZlGz8ifniUZaK4AkK4VjM4 +-> ssh-ed25519 WCPLrA lD5KmpPXdvmTGMXMhye/ivnkbb0+XRCpUA4i6JBsK2w +0LKCxV8vSewkNOLJa+xEZp4w+qIRAVezv37g6hExpb0 +-> ssh-ed25519 7/ziYw Yq6qqosp/yOekCO7NBpNTJQVv8NciaSLiDFNuLaOjyA +8Joor9/H+ExdOQBavTMH13SI9MZgBKQQA2HPxKAF9uU +-> ssh-ed25519 VQy60Q /+R2djdRbYoWq1GzMFSj+gwXGf085axPJHOa0tIeFTs +dBVQQ7yucfpbmeR82Fp6MR1/IiQun3bqNVCm9qegL2g +--- fHjHEH5JtSZnKnJFC/KDQELHDwVsExA5aeuKN7DvL1M +AH? 'ahǒP>"/yRƄ!I= G4ٺ^iX}a: \ No newline at end of file diff --git a/secrets/immich-oidc.age b/secrets/immich-oidc.age new file mode 100644 index 0000000..11c301f --- /dev/null +++ b/secrets/immich-oidc.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-ed25519 GQzYWA MbczMCSPu7pJru1rmOsFuloCYLKlh7koC5drXcKlwiw +ZghUrcs7YT3ciwqOkrPDEzlZe3qN9ypBw3xRGYWNPaY +-> ssh-ed25519 MfR7VA KB6RE2QZ//Z6xoyQC502dJeg79rYXFJJdOwV+c6tOWo +e1zIz2nsV9JbBaadTnONrPLI5Ztyv9vf4Ewzd9uSHnU +-> ssh-ed25519 +cvRTg GntHLoUwpIrxm3FcVw+Bavaq6kLaZpVdTRLoMMVfpAY +abE1ZkhS39vylBg8bZ5K3vgnXr70Vbk1bLCKsCFlUvU +-> ssh-ed25519 WCPLrA +/GlB5CbM/1FwI5JE63DJVUChADjJfD3jJY3Y2KmXEU +pPqBhV49/wg/hWffFm2XFRGC9p1nQ57tj1YK7pPkQ3U +-> ssh-ed25519 7/ziYw lxlJVNMIqfoMPj6VGTt2V4PxFi+6WRMfOYcv1hpEMkM +kd8CI7RECJA5uPJu33D61OEnqWwZuNQ6VmYLqXew6gc +-> ssh-ed25519 VQy60Q YSgYVPPN7QutKhbv6/1vmoRnh14KXs0g2k9qxKuvQ2U +FL3fImxWoBeHrCLd+jp/a1oRd/Acgi6sV/g40dCRrTA +--- TipdjwDPkRxiV/R1FUYCm/tcD6M+XEaZhQjrzwMxiuA +E%ZDTs,5 jLOzﻸT _Hn*xQ7$Cv`Wqt%N6 5 \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 5f4df5c..df90563 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -20,4 +20,6 @@ in { "matrix-registration.age".publicKeys = keys; "mail-admin.age".publicKeys = keys; "zitadel-key.age".publicKeys = keys; + "forgejo-mailpass.age".publicKeys = keys; + "immich-oidc.age".publicKeys = keys; } diff --git a/system/server/forgejo.nix b/system/server/forgejo.nix index 17086b6..df2c29a 100644 --- a/system/server/forgejo.nix +++ b/system/server/forgejo.nix @@ -26,11 +26,32 @@ in { ROOT_URL = "https://${DOMAIN}/"; HTTP_PORT = 9004; }; - service.DISABLE_REGISTRATION = true; + service = { + ENABLE_INTERNAL_SIGNIN = false; + # DISABLE_REGISTRATION = true; + ALLOW_ONLY_EXTERNAL_REGISTRATION = true; + }; + oauth2_client = { + ENABLE_AUTO_REGISTRATION = true; + }; + "ui.meta" = { + AUTHOR = "JSW Git"; + DESCRIPTION = "Personal GIT-Forgejo instance."; + }; actions = { ENABLED = true; DEFAULT_ACTIONS_URL = "github"; }; + mailer = { + ENABLED = true; + SUBJECT_PREFIX = "JSWGit"; + PROTOCOL = "smtps"; + SMTP_ADDR = "mail.jsw.tf"; #FIXME: replace with config... to stalwart setting once using stalwart nixos module. + SMTP_PORT = 465; + FROM = "git@jsw.tf"; + USER = "git"; + PASSWD_URI = "file:${config.age.secrets.forgejo-mailpass.path}"; + }; }; }; }; diff --git a/system/server/immich.nix b/system/server/immich.nix index 216b8d2..3554292 100644 --- a/system/server/immich.nix +++ b/system/server/immich.nix @@ -1,61 +1,102 @@ { config, lib, + pkgs, ... }: let + inherit (lib) mkIf mkForce mkDefault; + cfg = config.niksos.server; + oidcSubstitute = "*@#OPENIDCLIENTSECRET#@*"; + config-dir = "/run/immich-conf"; + url = "photos.jsw.tf"; + httpsUrl = "https://" + url; in { - services.immich = { - enable = cfg; + config = + mkIf cfg + { + users.users.${config.services.immich.user}.extraGroups = ["video" "render"]; + services.caddy.virtualHosts.${url}.extraConfig = '' + reverse_proxy localhost:9002 + ''; - port = 9002; - machine-learning.enable = false; + services.immich = mkIf cfg { + enable = true; - settings = { - server.externalDomain = "https://photos.jsw.tf"; - ffmpeg = { - crf = 23; - threads = 0; - preset = "ultrafast"; - targetVideoCodec = "h264"; - acceptedVideoCodecs = [ - "h264" + port = 9002; + machine-learning.enable = false; + + accelerationDevices = mkDefault null; + + #NOTE: immich doesn't support variables in their config file, so we have to subsitute ourselfs.. + environment.IMMICH_CONFIG_FILE = mkForce "${config-dir}/immich.json"; + settings = { + server.externalDomain = httpsUrl; + oauth = { + enabled = true; + autoLaunch = true; + autoRegister = true; + buttonText = "Login with JSWAuth"; + clientId = "329735769805619570"; + clientSecret = oidcSubstitute; + issuerUrl = "https://${config.services.zitadel.settings.ExternalDomain}/.well-known/openid-configuration"; + mobileRedirectUri = "${httpsUrl}/api/oauth/mobile-redirect"; + mobileOverrideEnabled = true; + }; + passwordLogin.enabled = false; + ffmpeg = { + crf = 23; + threads = 0; + preset = "ultrafast"; + targetVideoCodec = "h264"; + acceptedVideoCodecs = [ + "h264" + ]; + targetAudioCodec = "aac"; + acceptedAudioCodecs = [ + "aac" + "mp3" + "libopus" + "pcm_s16le" + ]; + acceptedContainers = [ + "mov" + "ogg" + "webm" + ]; + targetResolution = "720"; + maxBitrate = "0"; + bframes = -1; + refs = 0; + gopSize = 0; + temporalAQ = false; + cqMode = "auto"; + twoPass = false; + preferredHwDevice = lib.mkDefault "auto"; + transcode = "all"; + tonemap = "hable"; + accel = lib.mkDefault "vaapi"; + accelDecode = true; + }; + }; + }; + + systemd = { + services.immich-server = { + preStart = let + refConfig = (pkgs.formats.json {}).generate "immich.json" config.services.immich.settings; + newConfig = "${config-dir}/immich.json"; + replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret"; + in '' + umask 077 + cp -f '${refConfig}' '${newConfig}' + chmod u+w '${newConfig}' + ${replaceSecretBin} '${oidcSubstitute}' '${config.age.secrets.immich-oidc.path}' '${newConfig}' + ''; + }; + tmpfiles.rules = [ + "d ${config-dir} 0700 immich immich" ]; - targetAudioCodec = "aac"; - acceptedAudioCodecs = [ - "aac" - "mp3" - "libopus" - "pcm_s16le" - ]; - acceptedContainers = [ - "mov" - "ogg" - "webm" - ]; - targetResolution = "720"; - maxBitrate = "0"; - bframes = -1; - refs = 0; - gopSize = 0; - temporalAQ = false; - cqMode = "auto"; - twoPass = false; - preferredHwDevice = lib.mkDefault "auto"; - transcode = "all"; - tonemap = "hable"; - accel = lib.mkDefault "vaapi"; - accelDecode = true; }; }; - - accelerationDevices = lib.mkDefault null; - }; - users.users.immich = lib.mkIf cfg {extraGroups = ["video" "render"];}; #NOTE: was first groups = lib.mkIf.. but then users.immich gets set even when server is disabled. - - services.caddy.virtualHosts."photos.jsw.tf" = { - extraConfig = '' - reverse_proxy localhost:9002 - ''; - }; } diff --git a/system/server/seafile.nix b/system/server/seafile.nix index ac18412..914d683 100644 --- a/system/server/seafile.nix +++ b/system/server/seafile.nix @@ -3,25 +3,52 @@ inputs, pkgs, ... -}: { +}: let + url = "files.jsw.tf"; + httpsUrl = "https://" + url; + authUrl = config.services.zitadel.settings.ExternalDomain; + httpsAuthUrl = "https://" + authUrl; + oidcSubstitute = "*@#OPENIDCLIENTSECRET#@*"; + config-dir = "/run/immich-conf"; +in { services.seafile = { enable = config.niksos.server; seahubPackage = inputs.nixpkgs-stable.legacyPackages.${pkgs.system}.seahub; - adminEmail = "jurnwubben@gmail.com"; + adminEmail = "jsw@jsw.tf"; initialAdminPassword = "ChangeMeTheFuckNow!"; gc.enable = true; - ccnetSettings.General.SERVICE_URL = "https://files.jsw.tf"; + ccnetSettings.General.SERVICE_URL = httpsUrl; seahubExtraConf = '' - ALLOWED_HOSTS = ['.files.jsw.tf'] + ALLOWED_HOSTS = ['.${url}'] CSRF_COOKIE_SECURE = True CSRF_COOKIE_SAMESITE = 'Strict' - CSRF_TRUSTED_ORIGINS = ['https://files.jsw.tf', 'https://www.files.jsw.tf'] + CSRF_TRUSTED_ORIGINS = ['${httpsUrl}'] SITE_NAME = "JSW Cloud" SITE_TITLE = "JSW Cloud" + + ENABLE_OAUTH = True + OAUTH_CREATE_UNKNOWN_USER = True + OAUTH_ACTIVATE_USER_AFTER_CREATION = True + OAUTH_ENABLE_INSECURE_TRANSPORT = False + OAUTH_CLIENT_ID = "329743411726844274" + OAUTH_CLIENT_SECRET = "${oidcSubstitute}" + OAUTH_REDIRECT_URL = '${httpsUrl}/oauth/callback/' + OAUTH_PROVIDER_DOMAIN = '${authUrl}' + OAUTH_PROVIDER = 'JSW Auth' + OAUTH_AUTHORIZATION_URL = '${httpsAuthUrl}/oauth/v2/authorize' + OAUTH_TOKEN_URL = '${httpsAuthUrl}/oauth/v2/token' + OAUTH_USER_INFO_URL = '${httpsAuthUrl}/oidc/v1/userinfo' + OAUTH_SCOPE = ["user",] + OAUTH_ATTRIBUTE_MAP = { + "id": (True, "email"), + "name": (False, "name"), + "email": (False, "contact_email"), + "uid": (True, "uid"), + } ''; seafileSettings = { quota.default = 30; @@ -35,8 +62,7 @@ }; }; - services.caddy.virtualHosts."files.jsw.tf" = { - # serverAliases = ["www.share.jsw.tf"]; + services.caddy.virtualHosts.${url} = { extraConfig = '' handle_path /seafhttp/* { reverse_proxy * unix//run/seafile/server.sock