my over complex system configurations dotfiles.isabelroses.com/
nixos nix flake dotfiles linux
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: add nginx.vhost and drop ssl tepmplate

isabel 2a3c097c 55f6ed34

+634 -663
-10
modules/flake/lib/template/default.nix
··· 1 1 let 2 - # this is a forced SSL template for Nginx 3 - # returns the attribute set with our desired settings 4 - ssl = domain: { 5 - quic = true; 6 - forceSSL = true; 7 - enableACME = false; 8 - useACMEHost = domain; 9 - }; 10 - 11 2 systemd = { 12 3 LockPersonality = true; 13 4 MemoryDenyWriteExecute = true; ··· 37 28 in 38 29 { 39 30 inherit 40 - ssl 41 31 systemd 42 32 xdg 43 33 ;
+63 -69
modules/nixos/services/selfhosted/akkoma/default.nix
··· 8 8 }: 9 9 let 10 10 inherit (lib.modules) mkIf; 11 - inherit (self.lib) template; 12 11 inherit (self.lib.services) mkServiceOption; 13 12 14 13 inherit ((pkgs.formats.elixirConf { }).lib) mkRaw mkMap; 15 14 16 15 rdomain = config.networking.domain; 17 16 cfg = config.garden.services.akkoma; 18 - web = config.services.akkoma.config.":pleroma"."Pleroma.Web.Endpoint"; 19 17 in 20 18 { 21 19 options.garden.services.akkoma = mkServiceOption "akkoma" { domain = "akko.${rdomain}"; }; 22 20 23 21 config = mkIf cfg.enable { 24 - services = { 25 - akkoma = { 26 - enable = true; 27 - extraPackages = builtins.attrValues { inherit (pkgs) ffmpeg exiftool imagemagick; }; 22 + services.akkoma = { 23 + enable = true; 24 + extraPackages = builtins.attrValues { inherit (pkgs) ffmpeg exiftool imagemagick; }; 28 25 29 - extraStatic = { 30 - "static/terms-of-service.html" = pkgs.writeText "terms-of-service.html" "Just be normal please"; 26 + extraStatic = { 27 + "static/terms-of-service.html" = pkgs.writeText "terms-of-service.html" "Just be normal please"; 31 28 32 - "favicon.png" = pkgs.fetchurl { 33 - url = "https://gravatar.com/avatar/c487c810e09878b4bd90df713a7c9523?size=512"; 34 - hash = "sha256-HNn7/n5R2mSApgsUKiTaYPvh614gCsJnUFoaUnLLXhM="; 35 - }; 36 - 37 - "emoji/blobs" = pkgs.blobs_gg; 38 - "emoji/awesome" = inputs'.tgirlpkgs.packages.emojis; 29 + "favicon.png" = pkgs.fetchurl { 30 + url = "https://gravatar.com/avatar/c487c810e09878b4bd90df713a7c9523?size=512"; 31 + hash = "sha256-HNn7/n5R2mSApgsUKiTaYPvh614gCsJnUFoaUnLLXhM="; 39 32 }; 40 33 41 - config = { 42 - ":pleroma"."Pleroma.Web.Endpoint".url.host = cfg.domain; 43 - ":pleroma"."Pleroma.Upload".base_url = "https://${cfg.domain}:443/media"; 34 + "emoji/blobs" = pkgs.blobs_gg; 35 + "emoji/awesome" = inputs'.tgirlpkgs.packages.emojis; 36 + }; 44 37 45 - ":pleroma".":instance" = { 46 - name = "not localhost"; 47 - description = "Isabel Roses' akkoma instance"; 48 - email = "isabel@isabelroses.com"; 49 - notify_email = "noreply@isabelroses.com"; 38 + config = { 39 + ":pleroma"."Pleroma.Web.Endpoint".url.host = cfg.domain; 40 + ":pleroma"."Pleroma.Upload".base_url = "https://${cfg.domain}:443/media"; 50 41 51 - languages = [ "en" ]; 42 + ":pleroma".":instance" = { 43 + name = "not localhost"; 44 + description = "Isabel Roses' akkoma instance"; 45 + email = "isabel@isabelroses.com"; 46 + notify_email = "noreply@isabelroses.com"; 52 47 53 - registrations_open = false; 54 - invites_enabled = true; 48 + languages = [ "en" ]; 55 49 56 - admin_privileges = [ 57 - "users_read" 58 - "users_manage_invites" 59 - "users_manage_activation_state" 60 - "users_manage_tags" 61 - "users_manage_credentials" 62 - "users_delete" 63 - "reports_manage_reports" 64 - "moderation_log_read" 65 - "statistics_read" 66 - ]; 50 + registrations_open = false; 51 + invites_enabled = true; 67 52 68 - federating = true; 53 + admin_privileges = [ 54 + "users_read" 55 + "users_manage_invites" 56 + "users_manage_activation_state" 57 + "users_manage_tags" 58 + "users_manage_credentials" 59 + "users_delete" 60 + "reports_manage_reports" 61 + "moderation_log_read" 62 + "statistics_read" 63 + ]; 69 64 70 - limit = 69420; 71 - remote_limit = 100000; 72 - max_pinned_statuses = 5; 73 - max_account_fields = 100; 65 + federating = true; 74 66 75 - upload_limit = 41943040; # 40Mb 67 + limit = 69420; 68 + remote_limit = 100000; 69 + max_pinned_statuses = 5; 70 + max_account_fields = 100; 76 71 77 - limit_to_local_content = mkRaw ":unauthenticated"; 78 - healthcheck = true; 79 - cleanup_attachments = true; 80 - allow_relay = true; 81 - safe_dm_mentions = true; 82 - external_user_synchronization = true; 83 - }; 72 + upload_limit = 41943040; # 40Mb 84 73 85 - # going to setup prometheus later 86 - ":prometheus"."Pleroma.Web.Endpoint.MetricsExporter" = { 87 - enabled = true; 88 - auth = false; 89 - format = mkRaw ":text"; 90 - path = "/api/pleroma/app_metrics"; 91 - }; 74 + limit_to_local_content = mkRaw ":unauthenticated"; 75 + healthcheck = true; 76 + cleanup_attachments = true; 77 + allow_relay = true; 78 + safe_dm_mentions = true; 79 + external_user_synchronization = true; 80 + }; 92 81 93 - ":pleroma".":mrf".policies = map mkRaw [ "Pleroma.Web.ActivityPub.MRF.SimplePolicy" ]; 82 + # going to setup prometheus later 83 + ":prometheus"."Pleroma.Web.Endpoint.MetricsExporter" = { 84 + enabled = true; 85 + auth = false; 86 + format = mkRaw ":text"; 87 + path = "/api/pleroma/app_metrics"; 88 + }; 94 89 95 - # we configure from nix 96 - ":pleroma".":configurable_from_database" = false; 90 + ":pleroma".":mrf".policies = map mkRaw [ "Pleroma.Web.ActivityPub.MRF.SimplePolicy" ]; 97 91 98 - ":pleroma"."Pleroma.Captcha".enabled = false; 92 + # we configure from nix 93 + ":pleroma".":configurable_from_database" = false; 99 94 100 - ":pleroma".":mrf_simple".blocklist = builtins.mapAttrs (_: mkMap) (import ./blocklist.nix); 101 - }; 95 + ":pleroma"."Pleroma.Captcha".enabled = false; 102 96 103 - nginx = { 104 - useACMEHost = rdomain; 105 - forceSSL = true; 106 - quic = true; 107 - }; 97 + ":pleroma".":mrf_simple".blocklist = builtins.mapAttrs (_: mkMap) (import ./blocklist.nix); 108 98 }; 109 99 110 - nginx.virtualHosts.${web.url.host} = template.ssl rdomain; 100 + nginx = { 101 + useACMEHost = rdomain; 102 + forceSSL = true; 103 + quic = true; 104 + }; 111 105 }; 112 106 }; 113 107 }
+33 -34
modules/nixos/services/selfhosted/attic.nix
··· 5 5 ... 6 6 }: 7 7 let 8 - inherit (self.lib) template; 9 8 inherit (lib.modules) mkIf; 10 9 inherit (self.lib.services) mkServiceOption; 11 10 inherit (self.lib.secrets) mkSecret; ··· 22 21 }; 23 22 24 23 config = mkIf config.garden.services.attic.enable { 24 + garden.services = { 25 + nginx.vhosts.${cfg.domain} = { 26 + locations."/" = { 27 + proxyPass = "http://${cfg.host}:${toString cfg.port}"; 28 + extraConfig = '' 29 + client_max_body_size 512m; 30 + ''; 31 + }; 32 + }; 33 + }; 34 + 25 35 age.secrets.attic-env = mkSecret { 26 36 file = "attic/env"; 27 37 owner = "atticd"; 28 38 }; 29 39 30 - services = { 31 - atticd = { 32 - enable = true; 33 - environmentFile = config.age.secrets.attic-env.path; 40 + services.atticd = { 41 + enable = true; 42 + environmentFile = config.age.secrets.attic-env.path; 34 43 35 - settings = { 36 - listen = "${cfg.host}:${toString cfg.port}"; 44 + settings = { 45 + listen = "${cfg.host}:${toString cfg.port}"; 37 46 38 - storage = { 39 - bucket = "meower"; 40 - type = "s3"; 41 - region = "auto"; 42 - endpoint = "https://604a41ff5d2574939efbb1c55bac090e.r2.cloudflarestorage.com"; 43 - }; 47 + storage = { 48 + bucket = "meower"; 49 + type = "s3"; 50 + region = "auto"; 51 + endpoint = "https://604a41ff5d2574939efbb1c55bac090e.r2.cloudflarestorage.com"; 52 + }; 44 53 45 - chunking = { 46 - nar-size-threshold = 65536; 47 - min-size = 16384; 48 - avg-size = 65536; 49 - max-size = 262144; 50 - }; 54 + chunking = { 55 + nar-size-threshold = 65536; 56 + min-size = 16384; 57 + avg-size = 65536; 58 + max-size = 262144; 59 + }; 51 60 52 - compression = { 53 - type = "zstd"; 54 - level = 12; 55 - }; 61 + compression = { 62 + type = "zstd"; 63 + level = 12; 64 + }; 56 65 57 - garbage-collection.interval = "8 hours"; 58 - }; 66 + garbage-collection.interval = "8 hours"; 59 67 }; 60 - 61 - nginx.virtualHosts.${cfg.domain} = { 62 - locations."/" = { 63 - proxyPass = "http://${cfg.host}:${toString cfg.port}"; 64 - extraConfig = '' 65 - client_max_body_size 512m; 66 - ''; 67 - }; 68 - } // template.ssl rdomain; 69 68 }; 70 69 }; 71 70 }
+9 -9
modules/nixos/services/selfhosted/atuin.nix
··· 5 5 ... 6 6 }: 7 7 let 8 - inherit (self.lib) template; 9 8 inherit (lib.modules) mkIf; 10 9 inherit (self.lib.services) mkServiceOption; 11 10 ··· 18 17 domain = "atuin.${rdomain}"; 19 18 }; 20 19 21 - config.services = mkIf cfg.enable { 22 - atuin = { 20 + config = mkIf cfg.enable { 21 + garden.services = { 22 + postgresql.enable = true; 23 + nginx.vhosts.${cfg.domain} = { 24 + locations."/".proxyPass = "http://${cfg.host}:${toString cfg.port}"; 25 + }; 26 + }; 27 + 28 + services.atuin = { 23 29 enable = true; 24 30 inherit (cfg) port host; 25 31 openRegistration = false; 26 32 maxHistoryLength = 1024 * 16; 27 33 }; 28 - 29 - nginx.virtualHosts.${cfg.domain} = { 30 - locations."/" = { 31 - proxyPass = "http://${cfg.host}:${toString cfg.port}"; 32 - }; 33 - } // template.ssl rdomain; 34 34 }; 35 35 }
+28 -29
modules/nixos/services/selfhosted/buildbot.nix
··· 7 7 ... 8 8 }: 9 9 let 10 - inherit (self.lib) template; 11 10 inherit (lib.modules) mkIf mkMerge; 12 11 inherit (self.lib.services) mkServiceOption; 13 12 inherit (self.lib.secrets) mkSecret; ··· 36 35 buildbot-gh-oauth = mkSecret { file = "buildbot/gh-oauth"; }; 37 36 }; 38 37 39 - services = { 40 - buildbot-nix = { 41 - master = { 42 - enable = true; 38 + garden.services = { 39 + nginx.vhosts.${cfg.domain} = { }; 40 + }; 43 41 44 - inherit (cfg) domain; 42 + services.buildbot-nix = { 43 + master = { 44 + enable = true; 45 45 46 - accessMode.public = { }; 47 - useHTTPS = true; 46 + inherit (cfg) domain; 48 47 49 - admins = [ "isabelroses" ]; 50 - workersFile = secrets.buildbot-workers.path; 48 + accessMode.public = { }; 49 + useHTTPS = true; 51 50 52 - pullBased.repositories.infra = { 53 - url = "https://github.com/isabelroses/dotfiles.git"; 54 - defaultBranch = "main"; 55 - }; 51 + admins = [ "isabelroses" ]; 52 + workersFile = secrets.buildbot-workers.path; 56 53 57 - authBackend = "github"; 58 - github = { 59 - enable = true; 60 - webhookSecretFile = secrets.buildbot-gh-webhook-secret.path; 61 - authType.app = { 62 - id = 1153859; 63 - secretKeyFile = secrets.buildbot-gh-private-key.path; 64 - }; 65 - oauthId = "Iv23liSeLy6J7IS9awg1"; 66 - oauthSecretFile = secrets.buildbot-gh-oauth.path; 67 - }; 54 + pullBased.repositories.infra = { 55 + url = "https://github.com/isabelroses/dotfiles.git"; 56 + defaultBranch = "main"; 68 57 }; 69 58 70 - worker = { 59 + authBackend = "github"; 60 + github = { 71 61 enable = true; 72 - # masterUrl = cfg.domain; 73 - workerPasswordFile = secrets.buildbot-worker.path; 62 + webhookSecretFile = secrets.buildbot-gh-webhook-secret.path; 63 + authType.app = { 64 + id = 1153859; 65 + secretKeyFile = secrets.buildbot-gh-private-key.path; 66 + }; 67 + oauthId = "Iv23liSeLy6J7IS9awg1"; 68 + oauthSecretFile = secrets.buildbot-gh-oauth.path; 74 69 }; 75 70 }; 76 71 77 - nginx.virtualHosts.${cfg.domain} = template.ssl rdomain; 72 + worker = { 73 + enable = true; 74 + # masterUrl = cfg.domain; 75 + workerPasswordFile = secrets.buildbot-worker.path; 76 + }; 78 77 }; 79 78 } 80 79
+14 -17
modules/nixos/services/selfhosted/forgejo.nix
··· 8 8 let 9 9 cfg = config.garden.services.forgejo; 10 10 rdomain = config.networking.domain; 11 - 12 - inherit (self.lib) template; 13 11 inherit (lib.modules) mkIf mkForce; 14 12 inherit (self.lib.services) mkServiceOption; 15 13 inherit (self.lib.secrets) mkSecret; ··· 36 34 }; 37 35 38 36 garden.services = { 39 - nginx.enable = true; 40 37 redis.enable = true; 41 38 postgresql.enable = true; 39 + 40 + nginx.vhosts.${cfg.domain} = { 41 + locations."/" = { 42 + recommendedProxySettings = true; 43 + proxyPass = 44 + "http://unix:" 45 + + ( 46 + if config.garden.services.anubis.enable then 47 + config.services.anubis.instances.forgejo.settings.BIND 48 + else 49 + config.services.forgejo.settings.server.HTTP_ADDR 50 + ); 51 + }; 52 + }; 42 53 }; 43 54 44 55 networking.firewall.allowedTCPPorts = [ ··· 177 188 ED25519_PRIVATE_KEY_HEX_FILE = config.age.secrets.anubis-forgejo.path; 178 189 }; 179 190 }; 180 - 181 - nginx.virtualHosts.${cfg.domain} = { 182 - locations."/" = { 183 - recommendedProxySettings = true; 184 - proxyPass = 185 - "http://unix:" 186 - + ( 187 - if config.garden.services.anubis.enable then 188 - config.services.anubis.instances.forgejo.settings.BIND 189 - else 190 - config.services.forgejo.settings.server.HTTP_ADDR 191 - ); 192 - }; 193 - } // template.ssl rdomain; 194 191 }; 195 192 }; 196 193 }
+100 -103
modules/nixos/services/selfhosted/grafana/default.nix
··· 5 5 ... 6 6 }: 7 7 let 8 - inherit (self.lib) template; 9 8 inherit (lib.modules) mkIf; 10 9 inherit (self.lib.services) mkServiceOption; 11 10 inherit (self.lib.secrets) mkSecret; ··· 40 39 41 40 garden.services = { 42 41 postgresql.enable = true; 42 + 43 + nginx.vhosts.${cfg.domain} = { 44 + locations."/" = { 45 + proxyPass = "http://${cfg.host}:${toString cfg.port}/"; 46 + proxyWebsockets = true; 47 + }; 48 + }; 43 49 }; 44 50 45 - services = { 46 - grafana = { 47 - enable = true; 48 - settings = { 49 - server = { 50 - root_url = "https://${cfg.domain}"; 51 - http_port = cfg.port; 52 - http_addr = cfg.host; 53 - inherit (cfg) domain; 54 - enforce_domain = true; 55 - }; 56 - 57 - database = { 58 - type = "postgres"; 59 - host = "/run/postgresql"; 60 - name = "grafana"; 61 - user = "grafana"; 62 - ssl_mode = "disable"; 63 - }; 51 + services.grafana = { 52 + enable = true; 53 + settings = { 54 + server = { 55 + root_url = "https://${cfg.domain}"; 56 + http_port = cfg.port; 57 + http_addr = cfg.host; 58 + inherit (cfg) domain; 59 + enforce_domain = true; 60 + }; 64 61 65 - smtp = 66 - let 67 - mailer = "grafana@${cfg.domain}"; 68 - in 69 - { 70 - enabled = true; 62 + database = { 63 + type = "postgres"; 64 + host = "/run/postgresql"; 65 + name = "grafana"; 66 + user = "grafana"; 67 + ssl_mode = "disable"; 68 + }; 71 69 72 - user = mailer; 73 - password = "$__file{" + config.age.secrets.mailserver-grafana-nohash.path + "}"; 70 + smtp = 71 + let 72 + mailer = "grafana@${cfg.domain}"; 73 + in 74 + { 75 + enabled = true; 74 76 75 - host = "${config.garden.services.mailserver.domain}:465"; 76 - from_address = mailer; 77 - startTLS_policy = "MandatoryStartTLS"; 78 - }; 77 + user = mailer; 78 + password = "$__file{" + config.age.secrets.mailserver-grafana-nohash.path + "}"; 79 79 80 - security = { 81 - cookie_secure = true; 80 + host = "${config.garden.services.mailserver.domain}:465"; 81 + from_address = mailer; 82 + startTLS_policy = "MandatoryStartTLS"; 82 83 }; 83 84 84 - analytics = { 85 - reporting_enabled = false; 86 - check_for_updates = false; 87 - }; 85 + security = { 86 + cookie_secure = true; 87 + }; 88 88 89 - auth.disable_login_form = false; 90 - "auth.anonymous".enabled = false; 91 - "auth.basic".enabled = false; 89 + analytics = { 90 + reporting_enabled = false; 91 + check_for_updates = false; 92 + }; 92 93 93 - "auth.generic_oauth" = 94 - let 95 - sso = "https://${config.garden.services.kanidm.domain}"; 96 - in 97 - { 98 - enabled = true; 99 - # auto_login = true; 100 - allow_signup = true; 101 - icon = "signin"; 102 - name = "Kanidm"; 103 - client_id = "grafana"; 104 - client_secret = "$__file{${config.age.secrets.grafana-oauth2.path}}"; 105 - use_pkce = true; 106 - scopes = "openid email profile"; 107 - login_attribute_path = "preferred_username"; 108 - auth_url = "${sso}/ui/oauth2"; 109 - token_url = "${sso}/oauth2/token"; 110 - api_url = "${sso}/oauth2/openid/grafana/userinfo"; 111 - }; 94 + auth.disable_login_form = false; 95 + "auth.anonymous".enabled = false; 96 + "auth.basic".enabled = false; 112 97 113 - users = { 114 - allow_signup = false; 98 + "auth.generic_oauth" = 99 + let 100 + sso = "https://${config.garden.services.kanidm.domain}"; 101 + in 102 + { 103 + enabled = true; 104 + # auto_login = true; 105 + allow_signup = true; 106 + icon = "signin"; 107 + name = "Kanidm"; 108 + client_id = "grafana"; 109 + client_secret = "$__file{${config.age.secrets.grafana-oauth2.path}}"; 110 + use_pkce = true; 111 + scopes = "openid email profile"; 112 + login_attribute_path = "preferred_username"; 113 + auth_url = "${sso}/ui/oauth2"; 114 + token_url = "${sso}/oauth2/token"; 115 + api_url = "${sso}/oauth2/openid/grafana/userinfo"; 115 116 }; 117 + 118 + users = { 119 + allow_signup = false; 116 120 }; 121 + }; 117 122 118 - provision = { 119 - enable = true; 120 - datasources.settings = { 121 - datasources = [ 122 - (mkIf srv.monitoring.prometheus.enable { 123 - name = "Prometheus"; 124 - type = "prometheus"; 125 - access = "proxy"; 126 - orgId = 1; 127 - uid = "PBFA97CFB590B2093"; 128 - url = "http://127.0.0.1:${toString config.services.prometheus.port}"; 129 - isDefault = true; 130 - version = 1; 131 - editable = true; 132 - jsonData = { 133 - graphiteVersion = "1.1"; 134 - tlsAuth = false; 135 - tlsAuthWithCACert = false; 136 - }; 137 - }) 123 + provision = { 124 + enable = true; 125 + datasources.settings = { 126 + datasources = [ 127 + (mkIf srv.monitoring.prometheus.enable { 128 + name = "Prometheus"; 129 + type = "prometheus"; 130 + access = "proxy"; 131 + orgId = 1; 132 + uid = "PBFA97CFB590B2093"; 133 + url = "http://127.0.0.1:${toString config.services.prometheus.port}"; 134 + isDefault = true; 135 + version = 1; 136 + editable = true; 137 + jsonData = { 138 + graphiteVersion = "1.1"; 139 + tlsAuth = false; 140 + tlsAuthWithCACert = false; 141 + }; 142 + }) 138 143 139 - (mkIf srv.monitoring.loki.enable { 140 - name = "Loki"; 141 - type = "loki"; 142 - access = "proxy"; 143 - url = "http://127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}"; 144 - }) 144 + (mkIf srv.monitoring.loki.enable { 145 + name = "Loki"; 146 + type = "loki"; 147 + access = "proxy"; 148 + url = "http://127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}"; 149 + }) 145 150 146 - (mkIf srv.database.postgresql.enable { 147 - name = "PostgreSQL"; 148 - type = "postgres"; 149 - access = "proxy"; 150 - url = "http://127.0.0.1:9103"; 151 - }) 152 - ]; 153 - }; 151 + (mkIf srv.database.postgresql.enable { 152 + name = "PostgreSQL"; 153 + type = "postgres"; 154 + access = "proxy"; 155 + url = "http://127.0.0.1:9103"; 156 + }) 157 + ]; 154 158 }; 155 159 }; 156 - 157 - nginx.virtualHosts.${cfg.domain} = { 158 - locations."/" = { 159 - proxyPass = "http://${cfg.host}:${toString cfg.port}/"; 160 - proxyWebsockets = true; 161 - }; 162 - } // template.ssl rdomain; 163 160 }; 164 161 }; 165 162 }
+37 -41
modules/nixos/services/selfhosted/headscale.nix
··· 6 6 ... 7 7 }: 8 8 let 9 - inherit (self.lib) template; 10 9 inherit (lib.modules) mkIf; 11 10 inherit (self.lib.services) mkServiceOption; 12 11 ··· 23 22 24 23 config = mkIf cfg.enable { 25 24 garden.services = { 26 - nginx.enable = true; 27 25 postgresql.enable = true; 26 + 27 + nginx.vhosts.${cfg.domain} = { 28 + locations."/" = { 29 + recommendedProxySettings = true; 30 + proxyPass = "http://${cfg.host}:${toString cfg.port}"; 31 + proxyWebsockets = true; 32 + }; 33 + 34 + locations."/web" = { 35 + root = "${inputs'.tgirlpkgs.packages.headscale-ui}/share"; 36 + }; 37 + }; 28 38 }; 29 39 30 40 garden.packages = { inherit (config.services.headscale) package; }; 31 41 networking.firewall.allowedUDPPorts = [ cfg.port ]; 32 42 33 - services = { 34 - headscale = { 35 - enable = true; 36 - address = cfg.host; 37 - inherit (cfg) port; 43 + services.headscale = { 44 + enable = true; 45 + address = cfg.host; 46 + inherit (cfg) port; 38 47 39 - settings = { 40 - server_url = cfg.domain; 48 + settings = { 49 + server_url = cfg.domain; 41 50 42 - dns_config = { 43 - override_local_dns = true; 44 - base_domain = rdomain; 45 - magic_dns = true; 46 - domains = [ cfg.domain ]; 47 - nameservers = [ "9.9.9.9" ]; 48 - }; 51 + dns_config = { 52 + override_local_dns = true; 53 + base_domain = rdomain; 54 + magic_dns = true; 55 + domains = [ cfg.domain ]; 56 + nameservers = [ "9.9.9.9" ]; 57 + }; 49 58 50 - log.level = "warn"; 59 + log.level = "warn"; 51 60 52 - ip_prefixes = [ 53 - "100.64.0.0/10" 54 - "fd7a:115c:a1e0::/48" 55 - ]; 61 + ip_prefixes = [ 62 + "100.64.0.0/10" 63 + "fd7a:115c:a1e0::/48" 64 + ]; 56 65 57 - db_type = "postgres"; 58 - db_host = "/run/postgresql"; 59 - db_name = "headscale"; 60 - db_user = "headscale"; 66 + db_type = "postgres"; 67 + db_host = "/run/postgresql"; 68 + db_name = "headscale"; 69 + db_user = "headscale"; 61 70 62 - # TODO: logtail 63 - logtail.enabled = false; 71 + # TODO: logtail 72 + logtail.enabled = false; 64 73 65 - disable_check_updates = true; 66 - }; 74 + disable_check_updates = true; 67 75 }; 68 - 69 - nginx.virtualHosts.${cfg.domain} = { 70 - locations."/" = { 71 - recommendedProxySettings = true; 72 - proxyPass = "http://localhost:${toString cfg.port}"; 73 - proxyWebsockets = true; 74 - }; 75 - 76 - locations."/web" = { 77 - root = "${inputs'.tgirlpkgs.packages.headscale-ui}/share"; 78 - }; 79 - } // template.ssl rdomain; 80 76 }; 81 77 }; 82 78 }
+87 -91
modules/nixos/services/selfhosted/kanidm.nix
··· 9 9 ... 10 10 }: 11 11 let 12 - inherit (self.lib) template; 13 12 inherit (lib.modules) mkIf; 14 13 inherit (self.lib.services) mkServiceOption; 15 14 inherit (self.lib.secrets) mkSecret; ··· 29 28 30 29 config = mkIf cfg.enable { 31 30 garden.services = { 32 - nginx.enable = true; 33 31 postgresql.enable = true; 32 + 33 + nginx.vhosts.${cfg.domain} = { 34 + locations."/".proxyPass = "https://${config.services.kanidm.serverSettings.bindaddress}"; 35 + }; 34 36 }; 35 37 36 38 age.secrets = { ··· 60 62 }; 61 63 }; 62 64 63 - services = { 64 - kanidm = { 65 - # we need to change the package so we have patches that allow us to provision secrets 66 - package = pkgs.kanidm.withSecretProvisioning; 65 + services.kanidm = { 66 + # we need to change the package so we have patches that allow us to provision secrets 67 + package = pkgs.kanidm.withSecretProvisioning; 67 68 68 - enableServer = true; 69 - serverSettings = { 70 - inherit (cfg) domain; 71 - origin = "https://${cfg.domain}"; 72 - bindaddress = "${cfg.host}:${toString cfg.port}"; 73 - ldapbindaddress = "${cfg.host}:3636"; 74 - trust_x_forward_for = true; 75 - tls_chain = "${certDir}/fullchain.pem"; 76 - tls_key = "${certDir}/key.pem"; 69 + enableServer = true; 70 + serverSettings = { 71 + inherit (cfg) domain; 72 + origin = "https://${cfg.domain}"; 73 + bindaddress = "${cfg.host}:${toString cfg.port}"; 74 + ldapbindaddress = "${cfg.host}:3636"; 75 + trust_x_forward_for = true; 76 + tls_chain = "${certDir}/fullchain.pem"; 77 + tls_key = "${certDir}/key.pem"; 77 78 78 - online_backup = { 79 - path = "/srv/storage/kanidm/backups"; 80 - schedule = "0 0 * * *"; 81 - }; 79 + online_backup = { 80 + path = "/srv/storage/kanidm/backups"; 81 + schedule = "0 0 * * *"; 82 82 }; 83 + }; 83 84 84 - provision = { 85 - enable = true; 85 + provision = { 86 + enable = true; 86 87 87 - adminPasswordFile = config.age.secrets.kanidm-admin-password.path; 88 - idmAdminPasswordFile = config.age.secrets.kanidm-idm-admin-password.path; 88 + adminPasswordFile = config.age.secrets.kanidm-admin-password.path; 89 + idmAdminPasswordFile = config.age.secrets.kanidm-idm-admin-password.path; 89 90 90 - persons = { 91 - isabel = { 92 - displayName = "isabel"; 93 - legalName = "isabel"; 94 - mailAddresses = [ "isabel@${rdomain}" ]; 95 - groups = [ 96 - "grafana.access" 97 - "grafana.admins" 98 - "forgejo.access" 99 - "forgejo.admins" 100 - ]; 101 - }; 91 + persons = { 92 + isabel = { 93 + displayName = "isabel"; 94 + legalName = "isabel"; 95 + mailAddresses = [ "isabel@${rdomain}" ]; 96 + groups = [ 97 + "grafana.access" 98 + "grafana.admins" 99 + "forgejo.access" 100 + "forgejo.admins" 101 + ]; 102 + }; 102 103 103 - robin = { 104 - displayName = "robin"; 105 - legalName = "robin"; 106 - mailAddresses = [ "robin@${rdomain}" ]; 107 - groups = [ 108 - "grafana.access" 109 - "forgejo.access" 110 - ]; 111 - }; 104 + robin = { 105 + displayName = "robin"; 106 + legalName = "robin"; 107 + mailAddresses = [ "robin@${rdomain}" ]; 108 + groups = [ 109 + "grafana.access" 110 + "forgejo.access" 111 + ]; 112 112 }; 113 + }; 113 114 114 - groups = { 115 - "grafana.access" = { }; 116 - "grafana.admins" = { }; 115 + groups = { 116 + "grafana.access" = { }; 117 + "grafana.admins" = { }; 117 118 118 - "forgejo.access" = { }; 119 - "forgejo.admins" = { }; 120 - }; 119 + "forgejo.access" = { }; 120 + "forgejo.admins" = { }; 121 + }; 121 122 122 - systems.oauth2 = { 123 - grafana = { 124 - displayName = "Grafana"; 125 - originUrl = "https://${cfg'.grafana.domain}/login/generic_oauth"; 126 - originLanding = "https://${cfg'.grafana.domain}/"; 127 - basicSecretFile = config.age.secrets.kanidm-oauth2-grafana.path; 128 - preferShortUsername = true; 129 - scopeMaps."grafana.access" = [ 130 - "openid" 131 - "email" 132 - "profile" 123 + systems.oauth2 = { 124 + grafana = { 125 + displayName = "Grafana"; 126 + originUrl = "https://${cfg'.grafana.domain}/login/generic_oauth"; 127 + originLanding = "https://${cfg'.grafana.domain}/"; 128 + basicSecretFile = config.age.secrets.kanidm-oauth2-grafana.path; 129 + preferShortUsername = true; 130 + scopeMaps."grafana.access" = [ 131 + "openid" 132 + "email" 133 + "profile" 134 + ]; 135 + claimMaps.groups = { 136 + joinType = "array"; 137 + valuesByGroup."grafana.admins" = [ 138 + "editor" 139 + "admin" 140 + "server_admin" 133 141 ]; 134 - claimMaps.groups = { 135 - joinType = "array"; 136 - valuesByGroup."grafana.admins" = [ 137 - "editor" 138 - "admin" 139 - "server_admin" 140 - ]; 141 - }; 142 142 }; 143 + }; 143 144 144 - forgejo = { 145 - displayName = "Forgejo"; 146 - originUrl = "https://${cfg'.forgejo.domain}/user/oauth2/Isabel%27s%20SSO/callback"; 147 - originLanding = "https://${cfg'.forgejo.domain}/"; 148 - basicSecretFile = config.age.secrets.kanidm-oauth2-forgejo.path; 149 - scopeMaps."forgejo.access" = [ 150 - "openid" 151 - "email" 152 - "profile" 153 - ]; 154 - # WARNING: PKCE is currently not supported by gitea/forgejo, 155 - # see https://github.com/go-gitea/gitea/issues/21376 156 - allowInsecureClientDisablePkce = true; 157 - preferShortUsername = true; 158 - claimMaps.groups = { 159 - joinType = "array"; 160 - valuesByGroup."forgejo.admins" = [ "admin" ]; 161 - }; 145 + forgejo = { 146 + displayName = "Forgejo"; 147 + originUrl = "https://${cfg'.forgejo.domain}/user/oauth2/Isabel%27s%20SSO/callback"; 148 + originLanding = "https://${cfg'.forgejo.domain}/"; 149 + basicSecretFile = config.age.secrets.kanidm-oauth2-forgejo.path; 150 + scopeMaps."forgejo.access" = [ 151 + "openid" 152 + "email" 153 + "profile" 154 + ]; 155 + # WARNING: PKCE is currently not supported by gitea/forgejo, 156 + # see https://github.com/go-gitea/gitea/issues/21376 157 + allowInsecureClientDisablePkce = true; 158 + preferShortUsername = true; 159 + claimMaps.groups = { 160 + joinType = "array"; 161 + valuesByGroup."forgejo.admins" = [ "admin" ]; 162 162 }; 163 163 }; 164 164 }; 165 165 }; 166 - 167 - nginx.virtualHosts.${cfg.domain} = { 168 - locations."/".proxyPass = "https://${config.services.kanidm.serverSettings.bindaddress}"; 169 - } // template.ssl rdomain; 170 166 }; 171 167 172 168 systemd.services.kanidm = {
+4 -6
modules/nixos/services/selfhosted/mailserver.nix
··· 7 7 ... 8 8 }: 9 9 let 10 - inherit (self.lib) template; 11 10 inherit (lib.modules) mkIf; 12 11 inherit (self.lib.services) mkServiceOption; 13 12 inherit (self.lib.secrets) mkSecret; ··· 22 21 23 22 config = mkIf cfg.enable { 24 23 garden.services = { 25 - nginx.enable = true; 26 24 redis.enable = true; 27 25 postgresql.enable = true; 26 + 27 + nginx.vhosts."webmail.${rdomain}" = { 28 + locations."/".extraConfig = lib.mkForce ""; 29 + }; 28 30 }; 29 31 30 32 age.secrets = { ··· 257 259 "listen.owner" = config.services.nginx.user; 258 260 "listen.group" = config.services.nginx.group; 259 261 }; 260 - 261 - nginx.virtualHosts."webmail.${rdomain}" = { 262 - locations."/".extraConfig = lib.mkForce ""; 263 - } // template.ssl rdomain; 264 262 }; 265 263 }; 266 264 }
+9 -12
modules/nixos/services/selfhosted/matrix.nix
··· 6 6 ... 7 7 }: 8 8 let 9 - inherit (self.lib) template; 10 9 inherit (lib.modules) mkIf; 11 10 inherit (self.lib.services) mkServiceOption; 12 11 inherit (self.lib.secrets) mkSecret; ··· 45 44 networking.firewall.allowedTCPPorts = [ cfg.port ]; 46 45 47 46 garden.services = { 48 - nginx.enable = true; 49 47 postgresql.enable = true; 48 + nginx.vhosts.${rdomain} = { 49 + locations = { 50 + "= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig; 51 + "= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig; 52 + "/_matrix".proxyPass = "http://[${bindAddress}]:${toString cfg.port}"; 53 + "/_synapse/client".proxyPass = "http://[${bindAddress}]:${toString cfg.port}"; 54 + }; 55 + serverAliases = [ "${cfg.domain}" ]; 56 + }; 50 57 }; 51 58 52 59 services = { ··· 57 64 LC_COLLATE = "C" 58 65 LC_CTYPE = "C"; 59 66 ''; 60 - 61 - nginx.virtualHosts.${rdomain} = { 62 - locations = { 63 - "= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig; 64 - "= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig; 65 - "/_matrix".proxyPass = "http://[${bindAddress}]:${toString cfg.port}"; 66 - "/_synapse/client".proxyPass = "http://[${bindAddress}]:${toString cfg.port}"; 67 - }; 68 - serverAliases = [ "${cfg.domain}" ]; 69 - } // template.ssl rdomain; 70 67 71 68 matrix-synapse = { 72 69 enable = true;
+43 -47
modules/nixos/services/selfhosted/nextcloud.nix
··· 8 8 let 9 9 rdomain = config.networking.domain; 10 10 11 - inherit (self.lib) template; 12 11 inherit (lib.modules) mkIf; 13 12 inherit (self.lib.services) mkServiceOption; 14 13 inherit (self.lib.secrets) mkSecret; ··· 26 25 }; 27 26 28 27 garden.services = { 29 - nginx.enable = true; 30 28 redis.enable = true; 31 29 postgresql.enable = true; 30 + 31 + nginx.vhosts.${cfg.domain} = { }; 32 32 }; 33 33 34 - services = { 35 - nextcloud = { 36 - enable = true; 37 - package = pkgs.nextcloud29; 34 + services.nextcloud = { 35 + enable = true; 36 + package = pkgs.nextcloud29; 38 37 39 - # webs stuff 40 - https = true; 41 - nginx.recommendedHttpHeaders = true; 42 - hostName = cfg.domain; 38 + # webs stuff 39 + https = true; 40 + nginx.recommendedHttpHeaders = true; 41 + hostName = cfg.domain; 43 42 44 - home = "/srv/storage/nextcloud"; 45 - maxUploadSize = "4G"; 46 - enableImagemagick = true; 43 + home = "/srv/storage/nextcloud"; 44 + maxUploadSize = "4G"; 45 + enableImagemagick = true; 47 46 48 - caching = { 49 - apcu = true; 50 - memcached = true; 51 - redis = true; 52 - }; 47 + caching = { 48 + apcu = true; 49 + memcached = true; 50 + redis = true; 51 + }; 53 52 54 - extraApps = { 55 - inherit (config.services.nextcloud.package.packages.apps) contacts calendar; 56 - }; 53 + extraApps = { 54 + inherit (config.services.nextcloud.package.packages.apps) contacts calendar; 55 + }; 57 56 58 - autoUpdateApps = { 59 - enable = true; 60 - startAt = "02:00"; 61 - }; 57 + autoUpdateApps = { 58 + enable = true; 59 + startAt = "02:00"; 60 + }; 62 61 63 - config = { 64 - adminuser = "isabel"; 65 - adminpassFile = config.age.secrets.nextcloud-passwd.path; 62 + config = { 63 + adminuser = "isabel"; 64 + adminpassFile = config.age.secrets.nextcloud-passwd.path; 66 65 67 - # database 68 - dbtype = "pgsql"; 69 - dbhost = "/run/postgresql"; 70 - dbname = "nextcloud"; 71 - }; 66 + # database 67 + dbtype = "pgsql"; 68 + dbhost = "/run/postgresql"; 69 + dbname = "nextcloud"; 70 + }; 72 71 73 - settings = { 74 - defaultPhoneRegion = "UK"; 72 + settings = { 73 + defaultPhoneRegion = "UK"; 75 74 76 - overwriteProtocol = "https"; 77 - extraTrustedDomains = [ "https://${toString cfg.domain}" ]; 78 - trustedProxies = [ "https://${toString cfg.domain}" ]; 75 + overwriteProtocol = "https"; 76 + extraTrustedDomains = [ "https://${toString cfg.domain}" ]; 77 + trustedProxies = [ "https://${toString cfg.domain}" ]; 79 78 80 - redis = { 81 - host = "/run/redis-nextcloud/redis.sock"; 82 - dbindex = 0; 83 - timeout = 1.5; 84 - }; 79 + redis = { 80 + host = "/run/redis-nextcloud/redis.sock"; 81 + dbindex = 0; 82 + timeout = 1.5; 85 83 }; 86 - 87 - # fix the opcache "buffer is almost full" error in admin overview 88 - phpOptions."opcache.interned_strings_buffer" = "16"; 89 84 }; 90 85 91 - nginx.virtualHosts.${cfg.domain} = template.ssl rdomain; 86 + # fix the opcache "buffer is almost full" error in admin overview 87 + phpOptions."opcache.interned_strings_buffer" = "16"; 92 88 }; 93 89 94 90 systemd.services = {
+28 -1
modules/nixos/services/selfhosted/nginx.nix
··· 6 6 ... 7 7 }: 8 8 let 9 + inherit (lib) types; 9 10 inherit (lib.modules) mkIf; 11 + inherit (lib.options) mkOption; 12 + inherit (lib.attrsets) mapAttrs; 10 13 inherit (self.lib.services) mkServiceOption; 11 14 inherit (self.lib.secrets) mkSecret; 12 15 13 16 cfg = config.garden.services.nginx; 14 17 in 15 18 { 16 - options.garden.services.nginx = mkServiceOption "nginx" { domain = "isabelroses.com"; }; 19 + options.garden.services.nginx = mkServiceOption "nginx" { 20 + domain = "isabelroses.com"; 21 + 22 + extraConfig = { 23 + vhosts = mkOption { 24 + type = types.attrsOf ( 25 + types.submodule { 26 + freeformType = types.attrsOf types.anything; 27 + } 28 + ); 29 + default = { }; 30 + }; 31 + }; 32 + }; 17 33 18 34 config = mkIf cfg.enable { 19 35 age.secrets.cloudflare-cert-api = mkSecret { ··· 59 75 60 76 sslCiphers = "EECDH+aRSA+AESGCM:EDH+aRSA:EECDH+aRSA:+AES256:+AES128:+SHA1:!CAMELLIA:!SEED:!3DES:!DES:!RC4:!eNULL"; 61 77 sslProtocols = "TLSv1.3 TLSv1.2"; 78 + 79 + virtualHosts = mapAttrs ( 80 + _: settings: 81 + { 82 + quic = true; 83 + forceSSL = true; 84 + enableACME = false; 85 + useACMEHost = cfg.domain; 86 + } 87 + // settings 88 + ) cfg.vhosts; 62 89 }; 63 90 }; 64 91 }
+16 -21
modules/nixos/services/selfhosted/photoprism.nix
··· 5 5 ... 6 6 }: 7 7 let 8 - inherit (self.lib) template; 9 8 inherit (lib.modules) mkIf; 10 9 inherit (self.lib.services) mkServiceOption; 11 10 ··· 21 20 22 21 config = mkIf cfg.enable { 23 22 garden.services = { 24 - nginx.enable = true; 25 23 mysql.enable = true; 24 + nginx.vhosts.${cfg.domain} = { }; 26 25 }; 27 26 28 - services = { 29 - photoprism = { 30 - enable = true; 31 - inherit (cfg) port; 32 - address = cfg.host; 27 + services.photoprism = { 28 + enable = true; 29 + inherit (cfg) port; 30 + address = cfg.host; 33 31 34 - originalsPath = "/var/lib/private/photoprism/originals"; 32 + originalsPath = "/var/lib/private/photoprism/originals"; 35 33 36 - settings = { 37 - PHOTOPRISM_ADMIN_USER = "admin"; 38 - PHOTOPRISM_ADMIN_PASSWORD = "L38*%puzpXX!j$7!"; 39 - PHOTOPRISM_DEFAULT_LOCALE = "en"; 40 - PHOTOPRISM_DATABASE_DRIVER = "mysql"; 41 - PHOTOPRISM_DATABASE_NAME = "photoprism"; 42 - PHOTOPRISM_DATABASE_SERVER = "/run/mysqld/mysqld.sock"; 43 - PHOTOPRISM_DATABASE_USER = "photoprism"; 44 - PHOTOPRISM_SITE_URL = "https://${cfg.domain}"; 45 - PHOTOPRISM_SITE_TITLE = "My PhotoPrism"; 46 - }; 34 + settings = { 35 + PHOTOPRISM_ADMIN_USER = "admin"; 36 + PHOTOPRISM_ADMIN_PASSWORD = "L38*%puzpXX!j$7!"; 37 + PHOTOPRISM_DEFAULT_LOCALE = "en"; 38 + PHOTOPRISM_DATABASE_DRIVER = "mysql"; 39 + PHOTOPRISM_DATABASE_NAME = "photoprism"; 40 + PHOTOPRISM_DATABASE_SERVER = "/run/mysqld/mysqld.sock"; 41 + PHOTOPRISM_DATABASE_USER = "photoprism"; 42 + PHOTOPRISM_SITE_URL = "https://${cfg.domain}"; 43 + PHOTOPRISM_SITE_TITLE = "My PhotoPrism"; 47 44 }; 48 - 49 - nginx.virtualHosts.${cfg.domain} = template.ssl rdomain; 50 45 }; 51 46 }; 52 47 }
+23 -25
modules/nixos/services/selfhosted/plausible.nix
··· 5 5 ... 6 6 }: 7 7 let 8 - inherit (self.lib) template; 9 8 inherit (lib.modules) mkIf; 10 9 inherit (self.lib.services) mkServiceOption; 11 10 inherit (self.lib.secrets) mkSecret; ··· 34 33 }; 35 34 }; 36 35 37 - garden.services.postgresql.enable = true; 36 + garden.services = { 37 + postgresql.enable = true; 38 + nginx.vhosts.${cfg.domain} = { 39 + locations."/".proxyPass = "http://${cfg.host}:${toString cfg.port}"; 40 + }; 41 + }; 38 42 39 - services = { 40 - plausible = { 41 - enable = true; 43 + services.plausible = { 44 + enable = true; 42 45 43 - server = { 44 - inherit (cfg) port; 45 - baseUrl = "https://${cfg.domain}"; 46 + server = { 47 + inherit (cfg) port; 48 + baseUrl = "https://${cfg.domain}"; 46 49 47 - disableRegistration = true; 48 - secretKeybaseFile = config.age.secrets.plausible-key.path; 49 - }; 50 - 51 - adminUser = { 52 - activate = true; 53 - name = "isabel"; 54 - email = "isabel@${cfg.domain}"; 55 - passwordFile = config.age.secrets.plausible-admin.path; 56 - }; 50 + disableRegistration = true; 51 + secretKeybaseFile = config.age.secrets.plausible-key.path; 52 + }; 57 53 58 - database.postgres = { 59 - dbname = "plausible"; 60 - socket = "/run/postgresql"; 61 - }; 54 + adminUser = { 55 + activate = true; 56 + name = "isabel"; 57 + email = "isabel@${cfg.domain}"; 58 + passwordFile = config.age.secrets.plausible-admin.path; 62 59 }; 63 60 64 - nginx.virtualHosts.${cfg.domain} = { 65 - locations."/".proxyPass = "http://${cfg.host}:${toString cfg.port}"; 66 - } // template.ssl rdomain; 61 + database.postgres = { 62 + dbname = "plausible"; 63 + socket = "/run/postgresql"; 64 + }; 67 65 }; 68 66 69 67 users = {
+9 -8
modules/nixos/services/selfhosted/uptime-kuma.nix
··· 5 5 ... 6 6 }: 7 7 let 8 - inherit (self.lib) template; 9 8 inherit (lib.modules) mkIf; 10 9 inherit (self.lib.services) mkServiceOption; 11 10 ··· 19 18 }; 20 19 21 20 config = mkIf cfg.enable { 21 + garden.services = { 22 + nginx.vhosts.${cfg.domain} = { 23 + locations."/" = { 24 + proxyPass = "http://${cfg.host}:${toString cfg.port}"; 25 + proxyWebsockets = true; 26 + }; 27 + }; 28 + }; 29 + 22 30 services.uptime-kuma = { 23 31 enable = true; 24 32 ··· 28 36 PORT = toString cfg.port; 29 37 }; 30 38 }; 31 - 32 - services.nginx.virtualHosts.${cfg.domain} = { 33 - locations."/" = { 34 - proxyPass = "http://${cfg.host}:${toString cfg.port}"; 35 - proxyWebsockets = true; 36 - }; 37 - } // template.ssl rdomain; 38 39 }; 39 40 }
+33 -34
modules/nixos/services/selfhosted/vaultwarden.nix
··· 5 5 ... 6 6 }: 7 7 let 8 - inherit (self.lib) template; 9 8 inherit (lib.modules) mkIf; 10 9 inherit (self.lib.services) mkServiceOption; 11 10 inherit (self.lib.secrets) mkSecret; ··· 20 19 }; 21 20 22 21 config = mkIf cfg.enable { 22 + garden.services = { 23 + nginx.vhosts.${cfg.domain} = { 24 + locations."/" = { 25 + proxyPass = "http://${cfg.host}:${toString cfg.port}"; 26 + extraConfig = "proxy_pass_header Authorization;"; 27 + }; 28 + }; 29 + }; 30 + 23 31 age.secrets.vaultwarden-env = mkSecret { 24 32 file = "vaultwarden-env"; 25 33 owner = "vaultwarden"; ··· 32 40 Group = "root"; 33 41 }; 34 42 35 - services = { 36 - vaultwarden = { 37 - enable = true; 38 - environmentFile = config.age.secrets.vaultwarden-env.path; 39 - backupDir = "/srv/storage/vaultwarden/backup"; 43 + services.vaultwarden = { 44 + enable = true; 45 + environmentFile = config.age.secrets.vaultwarden-env.path; 46 + backupDir = "/srv/storage/vaultwarden/backup"; 40 47 41 - config = { 42 - DOMAIN = "https://${cfg.domain}"; 43 - ROCKET_ADDRESS = cfg.host; 44 - ROCKET_PORT = cfg.port; 45 - extendedLogging = true; 46 - invitationsAllowed = true; 47 - useSyslog = true; 48 - logLevel = "warn"; 49 - showPasswordHint = false; 50 - SIGNUPS_ALLOWED = false; 51 - signupsAllowed = false; 52 - signupsDomainsWhitelist = "${rdomain}"; 53 - signupsVerify = true; 54 - smtpAuthMechanism = "Login"; 55 - smtpFrom = "vaultwarden@${rdomain}"; 56 - smtpFromName = "Isabelroses's Vaultwarden Service"; 57 - smtpHost = config.garden.services.mailserver.domain; 58 - smtpPort = 465; 59 - smtpSecurity = "force_tls"; 60 - dataDir = "/srv/storage/vaultwarden"; 61 - }; 48 + config = { 49 + DOMAIN = "https://${cfg.domain}"; 50 + ROCKET_ADDRESS = cfg.host; 51 + ROCKET_PORT = cfg.port; 52 + extendedLogging = true; 53 + invitationsAllowed = true; 54 + useSyslog = true; 55 + logLevel = "warn"; 56 + showPasswordHint = false; 57 + SIGNUPS_ALLOWED = false; 58 + signupsAllowed = false; 59 + signupsDomainsWhitelist = "${rdomain}"; 60 + signupsVerify = true; 61 + smtpAuthMechanism = "Login"; 62 + smtpFrom = "vaultwarden@${rdomain}"; 63 + smtpFromName = "Isabelroses's Vaultwarden Service"; 64 + smtpHost = config.garden.services.mailserver.domain; 65 + smtpPort = 465; 66 + smtpSecurity = "force_tls"; 67 + dataDir = "/srv/storage/vaultwarden"; 62 68 }; 63 - 64 - nginx.virtualHosts.${cfg.domain} = { 65 - locations."/" = { 66 - proxyPass = "http://${cfg.host}:${toString cfg.port}"; 67 - extraConfig = "proxy_pass_header Authorization;"; 68 - }; 69 - } // template.ssl rdomain; 70 69 }; 71 70 }; 72 71 }
+53 -56
modules/nixos/services/selfhosted/vikunja.nix
··· 5 5 ... 6 6 }: 7 7 let 8 - inherit (self.lib) template; 9 8 inherit (lib.modules) mkIf; 10 9 inherit (self.lib.services) mkServiceOption; 11 10 inherit (self.lib.secrets) mkSecret; ··· 27 26 }; 28 27 29 28 garden.services = { 30 - nginx.enable = true; 31 29 redis.enable = true; 32 30 postgresql.enable = true; 31 + 32 + nginx.vhosts.${cfg.domain} = { 33 + locations."/".proxyPass = "http://${cfg.host}:${toString cfg.port}"; 34 + }; 33 35 }; 34 36 35 - services = { 36 - vikunja = { 37 - enable = true; 37 + services.vikunja = { 38 + enable = true; 38 39 39 - inherit (cfg) port; 40 - frontendHostname = cfg.domain; 41 - frontendScheme = "https"; 40 + inherit (cfg) port; 41 + frontendHostname = cfg.domain; 42 + frontendScheme = "https"; 42 43 43 - environmentFiles = [ config.age.secrets.vikunja-env.path ]; 44 + environmentFiles = [ config.age.secrets.vikunja-env.path ]; 44 45 45 - database = { 46 - type = "postgres"; 47 - host = "/run/postgresql"; 48 - user = "vikunja"; 49 - database = "vikunja"; 50 - }; 46 + database = { 47 + type = "postgres"; 48 + host = "/run/postgresql"; 49 + user = "vikunja"; 50 + database = "vikunja"; 51 + }; 51 52 52 - settings = { 53 - service.enableregistration = false; 53 + settings = { 54 + service.enableregistration = false; 54 55 55 - defaultsettings = { 56 - avatar_provider = "gravatar"; 57 - week_start = 1; # monday 58 - }; 56 + defaultsettings = { 57 + avatar_provider = "gravatar"; 58 + week_start = 1; # monday 59 + }; 59 60 60 - mailer = { 61 - enabled = true; 62 - host = config.garden.services.mailserver.domain; 63 - port = 465; 64 - forcessl = true; 61 + mailer = { 62 + enabled = true; 63 + host = config.garden.services.mailserver.domain; 64 + port = 465; 65 + forcessl = true; 65 66 66 - authtype = "login"; 67 - fromemail = "noreply@${rdomain}"; 68 - username = "noreply@${rdomain}"; 69 - }; 67 + authtype = "login"; 68 + fromemail = "noreply@${rdomain}"; 69 + username = "noreply@${rdomain}"; 70 + }; 70 71 71 - openid = { 72 - enabled = true; 73 - redirecturl = "https://${cfg.domain}/auth/openid/"; 74 - providers = 75 - let 76 - sso = config.garden.services.kanidm.domain; 77 - in 78 - [ 79 - { 80 - name = "Isabel's SSO"; 81 - authurl = "https://${sso}/oauth2/openid/vikunja/"; 82 - logouturl = "https://${sso}/logout"; 83 - clientid = "vikunja"; 84 - } 85 - ]; 86 - }; 87 - 88 - # redis 89 - # redis = { 90 - # enabled = true; 91 - # host = "/run/redis-vikunja/redis.sock"; 92 - # db = 0; 93 - # }; 72 + openid = { 73 + enabled = true; 74 + redirecturl = "https://${cfg.domain}/auth/openid/"; 75 + providers = 76 + let 77 + sso = config.garden.services.kanidm.domain; 78 + in 79 + [ 80 + { 81 + name = "Isabel's SSO"; 82 + authurl = "https://${sso}/oauth2/openid/vikunja/"; 83 + logouturl = "https://${sso}/logout"; 84 + clientid = "vikunja"; 85 + } 86 + ]; 94 87 }; 88 + 89 + # redis 90 + # redis = { 91 + # enabled = true; 92 + # host = "/run/redis-vikunja/redis.sock"; 93 + # db = 0; 94 + # }; 95 95 }; 96 96 97 - nginx.virtualHosts.${cfg.domain} = { 98 - locations."/".proxyPass = "http://${cfg.host}:${toString cfg.port}"; 99 - } // template.ssl rdomain; 100 97 }; 101 98 102 99 users = {
+41 -45
modules/nixos/services/selfhosted/wakapi.nix
··· 5 5 ... 6 6 }: 7 7 let 8 - inherit (self.lib) template; 9 8 inherit (lib.modules) mkIf; 10 9 inherit (self.lib.services) mkServiceOption; 11 10 inherit (self.lib.secrets) mkSecret; ··· 35 34 }; 36 35 37 36 garden.services = { 38 - nginx.enable = true; 39 37 postgresql.enable = true; 38 + 39 + nginx.vhosts.${cfg.domain} = { 40 + locations."/".proxyPass = "http://${cfg.host}:${toString cfg.port}"; 41 + }; 40 42 }; 41 43 42 44 systemd.services.wakapi.serviceConfig = { ··· 50 52 CapabilityBoundingSet = "CAP_NET_BIND_SERVICE"; 51 53 }; 52 54 53 - services = { 54 - wakapi = { 55 - enable = true; 55 + services.wakapi = { 56 + enable = true; 56 57 57 - passwordSaltFile = config.age.secrets.wakapi.path; 58 - smtpPasswordFile = config.age.secrets.wakapi-mailer.path; 58 + passwordSaltFile = config.age.secrets.wakapi.path; 59 + smtpPasswordFile = config.age.secrets.wakapi-mailer.path; 59 60 60 - # setup out postgresql database 61 - database.createLocally = true; 61 + # setup out postgresql database 62 + database.createLocally = true; 62 63 63 - settings = { 64 - app.avatar_url_template = "https://www.gravatar.com/avatar/{email_hash}.png"; 64 + settings = { 65 + app.avatar_url_template = "https://www.gravatar.com/avatar/{email_hash}.png"; 65 66 66 - server = { 67 - inherit (cfg) port; 68 - public_url = "https://${cfg.domain}"; 69 - }; 67 + server = { 68 + inherit (cfg) port; 69 + public_url = "https://${cfg.domain}"; 70 + }; 70 71 71 - db = { 72 - dialect = "postgres"; 73 - host = "/run/postgresql"; 74 - port = 5432; # this needs to be set otherwise the service will fail 75 - name = "wakapi"; 76 - user = "wakapi"; 77 - }; 72 + db = { 73 + dialect = "postgres"; 74 + host = "/run/postgresql"; 75 + port = 5432; # this needs to be set otherwise the service will fail 76 + name = "wakapi"; 77 + user = "wakapi"; 78 + }; 78 79 79 - security = { 80 - allow_signup = false; 81 - disable_frontpage = true; 82 - }; 80 + security = { 81 + allow_signup = false; 82 + disable_frontpage = true; 83 + }; 83 84 84 - mail = 85 - let 86 - mailer = "noreply@${rdomain}"; 87 - in 88 - { 89 - enabled = true; 90 - sender = "<${mailer}>"; 91 - provider = "smtp"; 92 - smtp = { 93 - host = "mail.${rdomain}"; 94 - port = 465; 95 - username = mailer; 96 - tls = true; 97 - }; 85 + mail = 86 + let 87 + mailer = "noreply@${rdomain}"; 88 + in 89 + { 90 + enabled = true; 91 + sender = "<${mailer}>"; 92 + provider = "smtp"; 93 + smtp = { 94 + host = "mail.${rdomain}"; 95 + port = 465; 96 + username = mailer; 97 + tls = true; 98 98 }; 99 - }; 99 + }; 100 100 }; 101 - 102 - nginx.virtualHosts.${cfg.domain} = { 103 - locations."/".proxyPass = "http://${cfg.host}:${toString cfg.port}"; 104 - } // template.ssl rdomain; 105 101 }; 106 102 }; 107 103 }
+4 -5
modules/nixos/services/selfhosted/website.nix
··· 6 6 ... 7 7 }: 8 8 let 9 - inherit (self.lib) template; 10 9 inherit (lib.modules) mkIf; 11 10 inherit (self.lib.services) mkServiceOption; 12 11 ··· 19 18 }; 20 19 21 20 config = mkIf cfg.enable { 22 - services = { 23 - nginx.virtualHosts.${cfg.domain} = { 24 - root = inputs'.tgirlcloud.packages.isabelroses-website; 25 - } // template.ssl domain; 21 + garden.services = { 22 + nginx.vhosts.${cfg.domain} = { 23 + root = inputs'.tgirlpkgs.packages.isabelroses-website; 24 + }; 26 25 }; 27 26 }; 28 27 }