diff --git a/hosts/sobotka/default.nix b/hosts/sobotka/default.nix index ac9e2154..9b4c2966 100644 --- a/hosts/sobotka/default.nix +++ b/hosts/sobotka/default.nix @@ -3,11 +3,9 @@ config, pkgs, ... -}: -let +}: let ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups; -in -{ +in { users.users.cnst = { isNormalUser = true; shell = pkgs.fish; @@ -51,8 +49,7 @@ in ./server.nix ]; - boot.initrd.luks.devices."luks-47b35d4b-467a-4637-a5f9-45177da62897".device = - "/dev/disk/by-uuid/47b35d4b-467a-4637-a5f9-45177da62897"; + boot.initrd.luks.devices."luks-47b35d4b-467a-4637-a5f9-45177da62897".device = "/dev/disk/by-uuid/47b35d4b-467a-4637-a5f9-45177da62897"; networking = { hostName = "sobotka"; @@ -69,8 +66,8 @@ in ]; boot = { - supportedFilesystems = [ "zfs" ]; - zfs.extraPools = [ "data" ]; + supportedFilesystems = ["zfs"]; + zfs.extraPools = ["data"]; }; services.zfs = { @@ -78,6 +75,8 @@ in autoScrub.enable = true; }; + environment.etc."nextcloud-admin-pass".text = "DeHKor3x8^eqqnBXjqhQ&QBl*3!sOLg8agfzOILihju#^0!2AfJ9W*vn"; + environment.variables.NH_FLAKE = "/home/cnst/.nix-config"; # # https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion diff --git a/hosts/sobotka/server.nix b/hosts/sobotka/server.nix index 4b67c4af..94e1a708 100644 --- a/hosts/sobotka/server.nix +++ b/hosts/sobotka/server.nix @@ -3,6 +3,7 @@ enable = true; email = "adam@cnst.dev"; domain = "cnix.dev"; + domainPublic = "cnst.dev"; user = "share"; group = "share"; uid = 994; @@ -61,12 +62,12 @@ credentialsFile = config.age.secrets.vaultwardenCloudflared.path; }; }; - ocis = { + nextcloud = { enable = true; - url = "cloud.cnst.dev"; + adminpassFile = config.age.secrets.nextcloudAdminPass.path; cloudflared = { - tunnelId = "8871dad0-e6ff-424c-9a6b-222ef0f492df"; - credentialsFile = config.age.secrets.ocisCloudflared.path; + tunnelId = "35802b60-7012-4f70-a686-f493c8f2dec0"; + credentialsFile = config.age.secrets.nextcloudCloudflared.path; }; }; fail2ban = { diff --git a/modules/nixos/services/agenix/default.nix b/modules/nixos/services/agenix/default.nix index 81d34eb1..4bfcbd26 100644 --- a/modules/nixos/services/agenix/default.nix +++ b/modules/nixos/services/agenix/default.nix @@ -77,7 +77,7 @@ in { keycloakCloudflared.file = "${self}/secrets/keycloakCloudflared.age"; keycloakDbPasswordFile.file = "${self}/secrets/keycloakDbPasswordFile.age"; nextcloudAdminPass.file = "${self}/secrets/nextcloudAdminPass.age"; - ocisCloudflared.file = "${self}/secrets/ocisCloudflared.age"; + nextcloudCloudflared.file = "${self}/secrets/nextcloudCloudflared.age"; vaultwardenCloudflared.file = "${self}/secrets/vaultwardenCloudflared.age"; vaultwardenEnvironment.file = "${self}/secrets/vaultwardenEnvironment.age"; homepageEnvironment.file = "${self}/secrets/homepageEnvironment.age"; diff --git a/modules/server/caddy/default.nix b/modules/server/caddy/default.nix index 1d52a054..792f103c 100644 --- a/modules/server/caddy/default.nix +++ b/modules/server/caddy/default.nix @@ -39,6 +39,16 @@ in { group = config.services.caddy.group; environmentFile = getCloudflareCredentials config.networking.hostName; }; + certs.${config.server.domainPublic} = { + reloadServices = ["caddy.service"]; + domain = "${config.server.domainPublic}"; + extraDomainNames = ["*.${config.server.domainPublic}"]; + dnsProvider = "cloudflare"; + dnsResolver = "1.1.1.1:53"; + dnsPropagationCheck = true; + group = config.services.caddy.group; + environmentFile = getCloudflareCredentials config.networking.hostName; + }; }; services.caddy = { @@ -57,6 +67,17 @@ in { redir https://{host}{uri} ''; }; + + "http://${config.server.domainPublic}" = { + extraConfig = '' + redir https://{host}{uri} + ''; + }; + "http://*.${config.server.domainPublic}" = { + extraConfig = '' + redir https://{host}{uri} + ''; + }; }; }; }; diff --git a/modules/server/default.nix b/modules/server/default.nix index e0f39735..a0d49a9a 100644 --- a/modules/server/default.nix +++ b/modules/server/default.nix @@ -1,14 +1,16 @@ { lib, config, + pkgs, ... -}: -let +}: let + hardDrives = [ + "/dev/disk/by-label/data" + ]; inherit (lib) mkOption types; cfg = config.server; ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups; -in -{ +in { options.server = { enable = lib.mkEnableOption "The server services and configuration variables"; email = mkOption { @@ -25,6 +27,13 @@ in Domain name to be used to access the server services via Caddy reverse proxy ''; }; + domainPublic = mkOption { + default = ""; + type = types.str; + description = '' + Public domain name to be used to access the server services via Caddy reverse proxy + ''; + }; user = lib.mkOption { default = "share"; type = lib.types.str; @@ -93,5 +102,17 @@ in ]; }; }; + + systemd.services.hd-idle = { + description = "External HD spin down daemon"; + wantedBy = ["multi-user.target"]; + serviceConfig = { + Type = "simple"; + ExecStart = let + idleTime = toString 900; + hardDriveParameter = lib.strings.concatMapStringsSep " " (x: "-a ${x} -i ${idleTime}") hardDrives; + in "${pkgs.hd-idle}/bin/hd-idle -i 0 ${hardDriveParameter}"; + }; + }; }; } diff --git a/modules/server/nextcloud/default.nix b/modules/server/nextcloud/default.nix index 7d0eda91..90186ffa 100644 --- a/modules/server/nextcloud/default.nix +++ b/modules/server/nextcloud/default.nix @@ -4,7 +4,7 @@ lib, ... }: let - unit = "ocis"; + unit = "nextcloud"; cfg = config.server.${unit}; srv = config.server; in { @@ -12,24 +12,24 @@ in { enable = lib.mkEnableOption { description = "Enable ${unit}"; }; - adminUser = lib.mkOption { + adminpassFile = lib.mkOption { + type = lib.types.path; + }; + adminuser = lib.mkOption { type = lib.types.str; default = "cnst"; }; - adminPass = lib.mkOption { - type = lib.types.path; - }; configDir = lib.mkOption { type = lib.types.str; default = "/var/lib/${unit}"; }; url = lib.mkOption { type = lib.types.str; - default = "cloud.${srv.domain}"; + default = "cloud.${srv.domainPublic}"; }; homepage.name = lib.mkOption { type = lib.types.str; - default = "OCIS"; + default = "Nextcloud"; }; homepage.description = lib.mkOption { type = lib.types.str; @@ -37,118 +37,114 @@ in { }; homepage.icon = lib.mkOption { type = lib.types.str; - default = "owncloud.svg"; + default = "nextcloud.svg"; }; homepage.category = lib.mkOption { type = lib.types.str; default = "Services"; }; - cloudflared = { - credentialsFile = lib.mkOption { - type = lib.types.str; - example = lib.literalExpression '' - pkgs.writeText "cloudflare-credentials.json" ''' - {"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"} - ''' - ''; - }; - tunnelId = lib.mkOption { - type = lib.types.str; - example = "00000000-0000-0000-0000-000000000000"; - }; + cloudflared.credentialsFile = lib.mkOption { + type = lib.types.str; + example = lib.literalExpression '' + pkgs.writeText "cloudflare-credentials.json" ''' + {"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"} + ''' + ''; + }; + cloudflared.tunnelId = lib.mkOption { + type = lib.types.str; + example = "00000000-0000-0000-0000-000000000000"; }; }; config = lib.mkIf cfg.enable { - server = { - postgresql.databases = [ - { - database = "ocis"; - } - ]; - fail2ban = lib.mkIf config.server.fail2ban.enable { - jails = { - nextcloud = { - serviceName = "phpfm-nextcloud"; - failRegex = "^.*Login failed:.*(Remote IP: ).*$"; - }; + services.nginx.virtualHosts."nextcloud".listen = [ + { + addr = "127.0.0.1"; + port = 8083; + } + ]; + services.cloudflared = { + enable = true; + tunnels.${cfg.cloudflared.tunnelId} = { + credentialsFile = cfg.cloudflared.credentialsFile; + default = "http_status:404"; + ingress."${cfg.url}".service = "http://127.0.0.1:8083"; + }; + }; + + server.fail2ban = lib.mkIf config.server.fail2ban.enable { + jails = { + nextcloud = { + serviceName = "phpfpm-nextcloud"; + failRegex = "^.*Login failed:.*(Remote IP: ).*$"; }; }; }; - systemd.services.ocis.preStart = '' - ${lib.getExe pkgs.ocis} init || true - ''; - services = { - cloudflared = { - enable = true; - tunnels.${cfg.cloudflared.tunnelId} = { - credentialsFile = cfg.cloudflared.credentialsFile; - default = "http_status:404"; - ingress."${cfg.url}".service = "http://${config.services.ocis.address}:${toString config.services.ocis.port}"; - }; + + services.${unit} = { + enable = true; + package = pkgs.nextcloud31; + hostName = "nextcloud"; + configureRedis = true; + caching = { + redis = true; }; - ${unit} = { - enable = true; - url = "https://${cfg.url}"; - environment = let - cspFormat = pkgs.formats.yaml {}; - cspConfig = { - directives = { - child-src = ["'self'"]; - connect-src = [ - "'self'" - "blob:" - "https://${srv.keycloak.url}" - ]; - default-src = ["'none'"]; - font-src = ["'self'"]; - frame-ancestors = ["'none'"]; - frame-src = [ - "'self'" - "blob:" - "https://embed.diagrams.net" - ]; - img-src = [ - "'self'" - "data:" - "blob:" - ]; - manifest-src = ["'self'"]; - media-src = ["'self'"]; - object-src = [ - "'self'" - "blob:" - ]; - script-src = [ - "'self'" - "'unsafe-inline'" - ]; - style-src = [ - "'self'" - "'unsafe-inline'" - ]; - }; - }; - in { - PROXY_AUTOPROVISION_ACCOUNTS = "true"; - PROXY_ROLE_ASSIGNMENT_DRIVER = "oidc"; - OCIS_OIDC_ISSUER = "https://${srv.keycloak.url}/realms/ownCloud"; - PROXY_OIDC_REWRITE_WELLKNOWN = "true"; - WEB_OIDC_CLIENT_ID = "ocis"; - OCIS_LOG_LEVEL = "error"; - PROXY_TLS = "false"; - PROXY_USER_OIDC_CLAIM = "preferred_username"; - PROXY_USER_CS3_CLAIM = "username"; - OCIS_ADMIN_USER_ID = ""; - OCIS_INSECURE = "false"; - OCIS_EXCLUDE_RUN_SERVICES = "idp"; - GRAPH_ASSIGN_DEFAULT_USER_ROLE = "false"; - PROXY_CSP_CONFIG_FILE_LOCATION = toString (cspFormat.generate "csp.yaml" cspConfig); - GRAPH_USERNAME_MATCH = "none"; - PROXY_ROLE_ASSIGNMENT_ENABLED = "true"; - PROXY_ROLE_ASSIGNMENT_OIDC_CLAIM = "realm_access.roles"; - PROXY_ROLE_ASSIGNMENT_MAPPING = "ocisAdmin:admin,ocisUser:user"; - }; + occ = { + maintenance = "install"; }; + database.createLocally = true; + maxUploadSize = "50G"; + settings = { + trusted_proxies = ["127.0.0.1"]; + trusted_domains = ["cloud.${srv.domainPublic}" "192.168.88.14"]; + overwriteprotocol = "https"; + overwritehost = "cloud.${srv.domainPublic}"; + overwrite.cli.url = "https://cloud.${srv.domainPublic}"; + # mail_smtpmode = "sendmail"; + # mail_sendmailmode = "pipe"; + # user_oidc = { + # allow_multiple_user_backends = 0; + # }; + forwarded_for_headers = [ + "HTTP_CF_CONNECTING_IP" + ]; + enabledPreviewProviders = [ + "OC\\Preview\\BMP" + "OC\\Preview\\GIF" + "OC\\Preview\\JPEG" + "OC\\Preview\\Krita" + "OC\\Preview\\MarkDown" + "OC\\Preview\\MP3" + "OC\\Preview\\OpenDocument" + "OC\\Preview\\PNG" + "OC\\Preview\\TXT" + "OC\\Preview\\XBitmap" + "OC\\Preview\\HEIC" + ]; + }; + config = { + dbtype = "pgsql"; + dbuser = "nextcloud"; + dbhost = "/run/postgresql"; + dbname = "nextcloud"; + adminuser = "cnst"; + adminpassFile = cfg.adminpassFile; + }; + }; + services.caddy.virtualHosts."${srv.domainPublic}" = { + useACMEHost = srv.domainPublic; + extraConfig = '' + reverse_proxy http://127.0.0.1:8083 + ''; + }; + server.postgresql.databases = [ + { + database = "nextcloud"; + } + ]; + systemd.services."nextcloud-setup" = { + requires = ["postgresql.service"]; + after = ["postgresql.service"]; }; }; } diff --git a/secrets/nextcloudAdminPass.age b/secrets/nextcloudAdminPass.age index 841d7f0f..a273f5ab 100644 --- a/secrets/nextcloudAdminPass.age +++ b/secrets/nextcloudAdminPass.age @@ -1,11 +1,11 @@ age-encryption.org/v1 --> ssh-ed25519 t9iOEg PQ9P0XIzZ/u/gSgdOlfQXFVW1GemJxDaVCtqJkBYsBY -KOw543xyHFcTzkCyOAB40bbArhQW+cGPySfFB4ceMn4 --> ssh-ed25519 KUYMFA GdUikncmoMYip/ASuwLKXwv+Wa3qyfT/CBjQxaptIRY -vnHv5sJVDcce02IaKwPFefNzIzvlwgIKi1ZVo+2tq+0 --> ssh-ed25519 76RhUQ xLBZfVIBGSuEqGlV8ny+uDhDnHZrHv0b7PVOCyiFdRs -gK3tkiaZmHBTpwYImlftYgcyNc7k6kRl1dyOaEN/zls --> ssh-ed25519 Jf8sqw YFwHA8v2BZvppparLQ1ts75lBCuS1exwNbLt4vRLuQY -qV/PXIouLPAx0amjeeS8aQx3tqgG7VqHhSjqIu+kOF4 ---- SAbSjt7w+XOwUQI+1saRnttNRuC9NOUvQXWu/+MdLn0 -3U\'UUKUQgk"PRL'r*rAcOy{%AbLKM9' \ No newline at end of file +-> ssh-ed25519 t9iOEg 5z2kiVAol78mM42O1Jf9ndeBwElB0x4BectRt+R8GkM +gE89nfzfPZ7dcQDG57xdJAcrq565V+rbWDUEtNuBEwA +-> ssh-ed25519 KUYMFA 7aaMHpHzTC3U/7zol+LWE5IXrXm98ORcQpXkC3SNBBw +i4cyBlQrGmPiosCaCjv/7GUUikP2c/I8tA93Qz0o3cI +-> ssh-ed25519 76RhUQ 7Jppe6oBvuXqxoB4LNU+725b6ZeopHxgXq3WWDZlbhg +f+8GtX9dsCrnQ+kN0Swhq5LLNZrlzEVYJhwn+oN7yG8 +-> ssh-ed25519 Jf8sqw qBlvp6ZCHVkr37lfE+HrBNNEGcqQ8++GbMYBKhpr1Dk +9CoVJgvPZyIQOdTOFQWMotZaohFUmt953pivSVx6C9Q +--- ZSaeUcQ9T8TdcDXXNOWgTRAAG5+lRsl4sOFIOYgMISQ + Ua`'^neP=b>~ؑ RVng0ZEkmlw`ҝ /x~ \ No newline at end of file diff --git a/secrets/nextcloudCloudflared.age b/secrets/nextcloudCloudflared.age new file mode 100644 index 00000000..b6e0807e --- /dev/null +++ b/secrets/nextcloudCloudflared.age @@ -0,0 +1,11 @@ +age-encryption.org/v1 +-> ssh-ed25519 t9iOEg tCTVBy/ZypZ8DjzMhp6MsG0OUSmY/Z7nprs6OgMXiRs +GXMwQ7THAvuh9SpM12ck84R86Qvs+Db62ybohItDloE +-> ssh-ed25519 KUYMFA EwdbsocHYlzEJ2JLiI6oD6wkhaN+llPghPuO50oNLmY +NYQmMaeBM511yQeeEczVEW9Hx6y8/5NiQJ4PGtytBlw +-> ssh-ed25519 76RhUQ 3zs9rA1RoMUahExIGTBXV6i815jrK9UDrh6ZKi4gXQk +lWRnELDu+qd+MHBnYoSkBZblJoNcBXIeIW7phdZb7fg +-> ssh-ed25519 Jf8sqw zDqvIhlZ5TMP5l4Ymc0VUccb0EZHu6nzT0zAz0n/yiA +2C6PIEpv7dsDV7u87B991XRHIDcYRIfi60cvHK0Bkgo +--- TzhNfeAGrl1ggKFbSWgQw+R0xpKU+VOod/iEJlgLPOA +uGeR H=of|t'e L뉱lwfMG"}@\e *R7j%=?v%i\'0Qyj 8xyj&EBTɥ#HuE%5uLҐyĆ5K>t00 qV ŵ>_jUDJWꂿ>@w :CJEb,5U \ No newline at end of file diff --git a/secrets/ocisCloudflared.age b/secrets/ocisCloudflared.age deleted file mode 100644 index d4142a47..00000000 --- a/secrets/ocisCloudflared.age +++ /dev/null @@ -1,11 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 t9iOEg v2avJ6U6RgP+ZxIa1QzzqxB48cslbdB0TlDlcz4F0RE -JTyOfbyFWOh9Br07l2SZpDH/2xk5+Cnz3BEl+1DdQdA --> ssh-ed25519 KUYMFA pGewUt3eOluT+v/+Yuf8zsuQtZVRSbYQPVw6CkbrOUk -H3G8Gxug7dww1fkfpuErLCndsD0HHcEQkndIkkZaW4I --> ssh-ed25519 76RhUQ o0kqSfuXPVvPGk3snfUGdAZqJG1I5KOhbEK21XUcCXs -ZKFxlayTAQptEgfNdPawCB1EYSphO6CzgVOxP56n71U --> ssh-ed25519 Jf8sqw uor01IOxnc3p9iRi2019HjkZzs1ph9G+oiYIPKrXb3A -Q2uxuYsSmMc3N2g7IQ/87YHXNdcgF2MpIz8P53kPBSs ---- 3JvyOSSYzDA6OPnYq45RUKdgGE6EgzkP1kDyu1nRbww -`l0n˵ 8yiĕKnP&G2O `YwH+:(qpoA|͸dzg \Kh/+2hq1x6gǒ56Fz$Z28ߏUfOQ[8uaАuo-:&P  49Q?blif-OxxؼsjUSf[ \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 67418f79..fc967527 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -42,8 +42,8 @@ in { "vaultwardenCloudflared.age".publicKeys = core ++ sobotka; "keycloakDbPasswordFile.age".publicKeys = core ++ sobotka; "keycloakCloudflared.age".publicKeys = core ++ sobotka; - "ocisCloudflared.age".publicKeys = core ++ sobotka; - "ocisAdminPass.age".publicKeys = core ++ sobotka; + "nextcloudCloudflared.age".publicKeys = core ++ sobotka; + "nextcloudAdminPass.age".publicKeys = core ++ sobotka; "cloudflareDnsApiToken.age".publicKeys = core ++ sobotka; "cloudflareDnsCredentials.age".publicKeys = core ++ sobotka; "wgCredentials.age".publicKeys = core ++ sobotka;