diff --git a/flake.nix b/flake.nix index f59094b..cef9d01 100644 --- a/flake.nix +++ b/flake.nix @@ -105,7 +105,8 @@ let # Global configuration for my systems - globals = rec { + globals = let baseName = "masu.rs"; + in rec { user = "noah"; fullName = "Noah Masur"; gitName = fullName; @@ -114,6 +115,14 @@ mail.imapHost = "imap.purelymail.com"; mail.smtpHost = "smtp.purelymail.com"; dotfilesRepo = "git@github.com:nmasur/dotfiles"; + gitServer = "git.${baseName}"; + metricsServer = "metrics.${baseName}"; + prometheusServer = "prom.${baseName}"; + secretsServer = "vault.${baseName}"; + streamServer = "stream.${baseName}"; + contentServer = "cloud.${baseName}"; + bookServer = "books.${baseName}"; + downloadServer = "download.${baseName}"; }; # Common overlays to always use diff --git a/hosts/flame/default.nix b/hosts/flame/default.nix index 4eaee89..99bc6eb 100644 --- a/hosts/flame/default.nix +++ b/hosts/flame/default.nix @@ -10,7 +10,7 @@ inputs.nixpkgs.lib.nixosSystem { system = "aarch64-linux"; specialArgs = { }; modules = [ - (removeAttrs globals [ "mail.server" ]) + globals inputs.home-manager.nixosModules.home-manager ../../modules/common ../../modules/nixos @@ -43,14 +43,16 @@ inputs.nixpkgs.lib.nixosSystem { "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+AbmjGEwITk5CK9y7+Rg27Fokgj9QEjgc9wST6MA3s"; # Programs and services - caddy.enable = true; cloudflare.enable = true; # Proxy traffic with Cloudflare dotfiles.enable = true; # Clone dotfiles - gaming.minecraft-server.enable = true; # Setup Minecraft server - giteaServer = "git.masu.rs"; - metricsServer = "metrics.masu.rs"; neovim.enable = true; - vaultwardenServer = "vault.masu.rs"; + + services.caddy.enable = true; + services.grafana.enable = true; + services.prometheus.enable = true; + services.gitea.enable = true; + services.vaultwarden.enable = true; + services.minecraft-server.enable = true; # Setup Minecraft server cloudflareTunnel = { enable = true; diff --git a/hosts/swan/default.nix b/hosts/swan/default.nix index 87ff2fd..ef52312 100644 --- a/hosts/swan/default.nix +++ b/hosts/swan/default.nix @@ -48,14 +48,16 @@ inputs.nixpkgs.lib.nixosSystem { theme = { colors = (import ../../colorscheme/gruvbox).dark; }; nixpkgs.overlays = overlays; neovim.enable = true; - caddy.enable = true; cloudflare.enable = true; dotfiles.enable = true; - streamServer = "stream.masu.rs"; - nextcloudServer = "cloud.masu.rs"; - bookServer = "books.masu.rs"; - arrServer = "download.masu.rs"; - samba.enable = true; + arrs.enable = true; + + services.caddy.enable = true; + services.jellyfin.enable = true; + services.nextcloud.enable = true; + services.calibre-web.enable = true; + services.prometheus.enable = true; + services.samba.enable = true; cloudflareTunnel = { enable = true; diff --git a/modules/common/applications/firefox.nix b/modules/common/applications/firefox.nix index 703a14e..c990741 100644 --- a/modules/common/applications/firefox.nix +++ b/modules/common/applications/firefox.nix @@ -33,7 +33,6 @@ vimium multi-account-containers facebook-container - temporary-containers (lib.mkIf config._1password.enable onepassword-password-manager) okta-browser-plugin sponsorblock diff --git a/modules/nixos/gaming/minecraft-server.nix b/modules/nixos/gaming/minecraft-server.nix index 34c6562..bcbf8f1 100644 --- a/modules/nixos/gaming/minecraft-server.nix +++ b/modules/nixos/gaming/minecraft-server.nix @@ -9,10 +9,7 @@ let in { - options.gaming.minecraft-server.enable = - lib.mkEnableOption "Minecraft Server."; - - config = lib.mkIf config.gaming.minecraft-server.enable { + config = lib.mkIf config.services.minecraft-server.enable { unfreePackages = [ "minecraft-server" ]; diff --git a/modules/nixos/services/arr.nix b/modules/nixos/services/arr.nix index 1a3361f..76ec0c4 100644 --- a/modules/nixos/services/arr.nix +++ b/modules/nixos/services/arr.nix @@ -1,14 +1,15 @@ { config, lib, ... }: { options = { - arrServer = lib.mkOption { + arrs.enable = lib.mkEnableOption "Arr services"; + downloadServer = lib.mkOption { type = lib.types.nullOr lib.types.str; - description = "Hostname for arr services"; + description = "Hostname for download services"; default = null; }; }; - config = lib.mkIf (config.arrServer != null) { + config = lib.mkIf config.arrs.enable { services = { bazarr = { diff --git a/modules/nixos/services/caddy.nix b/modules/nixos/services/caddy.nix index 702e20b..938b97e 100644 --- a/modules/nixos/services/caddy.nix +++ b/modules/nixos/services/caddy.nix @@ -1,7 +1,6 @@ { config, pkgs, lib, ... }: { options = { - caddy.enable = lib.mkEnableOption "Caddy reverse proxy."; caddy.tlsPolicies = lib.mkOption { type = lib.types.listOf lib.types.attrs; description = "Caddy JSON TLS policies"; @@ -19,35 +18,35 @@ }; }; - config = lib.mkIf (config.caddy.enable && config.caddy.routes != [ ]) { + config = + lib.mkIf (config.services.caddy.enable && config.caddy.routes != [ ]) { - services.caddy = { - enable = true; - adapter = "''"; # Required to enable JSON - configFile = pkgs.writeText "Caddyfile" (builtins.toJSON { - apps.http.servers.main = { - listen = [ ":443" ]; - routes = config.caddy.routes; - errors.routes = config.caddy.blocks; - # logs = { }; # Uncomment to collect access logs - }; - apps.tls.automation.policies = config.caddy.tlsPolicies; - logging.logs.main = { - encoder = { format = "console"; }; - writer = { - output = "file"; - filename = "${config.services.caddy.logDir}/caddy.log"; - roll = true; + services.caddy = { + adapter = "''"; # Required to enable JSON + configFile = pkgs.writeText "Caddyfile" (builtins.toJSON { + apps.http.servers.main = { + listen = [ ":443" ]; + routes = config.caddy.routes; + errors.routes = config.caddy.blocks; + # logs = { }; # Uncomment to collect access logs }; - level = "INFO"; - }; - }); + apps.tls.automation.policies = config.caddy.tlsPolicies; + logging.logs.main = { + encoder = { format = "console"; }; + writer = { + output = "file"; + filename = "${config.services.caddy.logDir}/caddy.log"; + roll = true; + }; + level = "INFO"; + }; + }); + + }; + + networking.firewall.allowedTCPPorts = [ 80 443 ]; + networking.firewall.allowedUDPPorts = [ 443 ]; }; - networking.firewall.allowedTCPPorts = [ 80 443 ]; - networking.firewall.allowedUDPPorts = [ 443 ]; - - }; - } diff --git a/modules/nixos/services/calibre.nix b/modules/nixos/services/calibre.nix index 75f44c4..6a7968f 100644 --- a/modules/nixos/services/calibre.nix +++ b/modules/nixos/services/calibre.nix @@ -19,10 +19,9 @@ in { }; }; - config = lib.mkIf (config.bookServer != null) { + config = lib.mkIf config.services.calibre-web.enable { services.calibre-web = { - enable = true; openFirewall = true; options = { reverseProxyAuth.enable = false; diff --git a/modules/nixos/services/default.nix b/modules/nixos/services/default.nix index 834f260..1ca9753 100644 --- a/modules/nixos/services/default.nix +++ b/modules/nixos/services/default.nix @@ -9,6 +9,7 @@ ./cloudflare.nix ./gitea.nix ./gnupg.nix + ./grafana.nix ./honeypot.nix ./jellyfin.nix ./keybase.nix diff --git a/modules/nixos/services/gitea.nix b/modules/nixos/services/gitea.nix index 81fbb80..d1f8ede 100644 --- a/modules/nixos/services/gitea.nix +++ b/modules/nixos/services/gitea.nix @@ -6,23 +6,22 @@ in { options = { - giteaServer = lib.mkOption { - description = "Hostname for Gitea."; + gitServer = lib.mkOption { + description = "Hostname for git server (Gitea)."; type = lib.types.nullOr lib.types.str; default = null; }; }; - config = lib.mkIf (config.giteaServer != null) { + config = lib.mkIf config.services.gitea.enable { services.gitea = { - enable = true; database.type = "sqlite3"; settings = { repository = { DEFAULT_PUSH_CREATE_PRIVATE = true; DISABLE_HTTP_GIT = false; - ACCESS_CONTROL_ALLOW_ORIGIN = config.giteaServer; + ACCESS_CONTROL_ALLOW_ORIGIN = config.gitServer; ENABLE_PUSH_CREATE_USER = true; ENABLE_PUSH_CREATE_ORG = true; DEFAULT_BRANCH = "main"; @@ -30,7 +29,7 @@ in { server = { HTTP_PORT = 3001; HTTP_ADDRESS = "127.0.0.1"; - ROOT_URL = "https://${config.giteaServer}/"; + ROOT_URL = "https://${config.gitServer}/"; SSH_PORT = 22; START_SSH_SERVER = false; # Use sshd instead DISABLE_SSH = false; @@ -47,7 +46,7 @@ in { networking.firewall.allowedTCPPorts = [ 122 ]; caddy.routes = [{ - match = [{ host = [ config.giteaServer ]; }]; + match = [{ host = [ config.gitServer ]; }]; handle = [{ handler = "reverse_proxy"; upstreams = [{ dial = "localhost:3001"; }]; diff --git a/modules/nixos/services/grafana.nix b/modules/nixos/services/grafana.nix new file mode 100644 index 0000000..bd2e735 --- /dev/null +++ b/modules/nixos/services/grafana.nix @@ -0,0 +1,24 @@ +{ config, lib, ... }: { + + options.metricsServer = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "Hostname of the metrics server."; + default = null; + }; + + config = lib.mkIf config.services.grafana.enable { + + # Required to fix error in latest nixpkgs + services.grafana.settings = { }; + + caddy.routes = [{ + match = [{ host = [ config.metricsServer ]; }]; + handle = [{ + handler = "reverse_proxy"; + upstreams = [{ dial = "localhost:3000"; }]; + }]; + }]; + + }; + +} diff --git a/modules/nixos/services/jellyfin.nix b/modules/nixos/services/jellyfin.nix index c8441f1..5dc9700 100644 --- a/modules/nixos/services/jellyfin.nix +++ b/modules/nixos/services/jellyfin.nix @@ -8,9 +8,8 @@ }; }; - config = lib.mkIf (config.streamServer != null) { + config = lib.mkIf config.services.jellyfin.enable { - services.jellyfin.enable = true; services.jellyfin.group = "media"; users.users.jellyfin = { isSystemUser = true; }; diff --git a/modules/nixos/services/nextcloud.nix b/modules/nixos/services/nextcloud.nix index 78d4bab..b33eb55 100644 --- a/modules/nixos/services/nextcloud.nix +++ b/modules/nixos/services/nextcloud.nix @@ -2,15 +2,15 @@ options = { - nextcloudServer = lib.mkOption { + contentServer = lib.mkOption { type = lib.types.nullOr lib.types.str; - description = "Hostname for Nextcloud"; + description = "Hostname for personal content system (Nextcloud)"; default = null; }; }; - config = lib.mkIf (config.nextcloudServer != null) { + config = lib.mkIf config.services.nextcloud.enable { services.nextcloud = { enable = true; @@ -21,7 +21,7 @@ maxUploadSize = "50G"; config = { adminpassFile = config.secrets.nextcloud.dest; - extraTrustedDomains = [ config.nextcloudServer ]; + extraTrustedDomains = [ config.contentServer ]; }; }; @@ -33,7 +33,7 @@ # Point Caddy to Nginx caddy.routes = [{ - match = [{ host = [ config.nextcloudServer ]; }]; + match = [{ host = [ config.contentServer ]; }]; handle = [{ handler = "reverse_proxy"; upstreams = [{ dial = "localhost:8080"; }]; diff --git a/modules/nixos/services/prometheus.nix b/modules/nixos/services/prometheus.nix index 914d824..afc21cc 100644 --- a/modules/nixos/services/prometheus.nix +++ b/modules/nixos/services/prometheus.nix @@ -1,32 +1,64 @@ -{ config, lib, ... }: { +{ config, pkgs, lib, ... }: { - options.metricsServer = lib.mkOption { + options.prometheusServer = lib.mkOption { type = lib.types.nullOr lib.types.str; - description = "Hostname of the Grafana server."; + description = "Hostname of the Prometheus server."; default = null; }; - config = lib.mkIf (config.metricsServer != null) { + # If hosting Grafana, host local Prometheus and listen for inbound jobs. + # If not hosting Grafana, send remote Prometheus writes to primary host - services.grafana.enable = true; - - # Required to fix error in latest nixpkgs - services.grafana.settings = { }; + config = lib.mkIf config.services.prometheus.enable { services.prometheus = { - enable = true; exporters.node.enable = true; scrapeConfigs = [{ job_name = "local"; static_configs = [{ targets = [ "127.0.0.1:9100" ]; }]; }]; + webExternalUrl = lib.mkIf config.services.grafana.enable + "https://${config.prometheusServer}"; + webConfigFile = + lib.mkIf config.services.grafana.enable (pkgs.formats.yaml { }).generate + "webconfig.yml" { + basic_auth_users = { + # Generate password: htpasswd -nBC 10 "" | tr -d ':\n' + # Encrypt and place in private/prometheus.age + "prometheus" = + "$2y$10$r7FWHLHTGPAY312PdhkPEuvb05aGn9Nk1IO7qtUUUjmaDl35l6sLa"; + }; + }; + remoteWrite = lib.mkIf (!config.services.grafana.enable) [{ + name = config.networking.hostName; + url = "https://${config.prometheusServer}"; + basic_auth = { + # Uses password hashed with bcrypt above + username = "prometheus"; + password_file = config.secrets.prometheus.dest; + }; + }]; }; - caddy.routes = [{ - match = [{ host = [ config.metricsServer ]; }]; + # Create credentials file for remote Prometheus push + secrets.prometheus = lib.mkIf (!config.services.grafana.enable) { + source = ../../../private/prometheus.age; + dest = "${config.secretsDirectory}/prometheus"; + owner = "prometheus"; + group = "prometheus"; + permissions = "0440"; + }; + systemd.services.prometheus-secret = + lib.mkIf (!config.services.grafana.enable) { + requiredBy = [ "prometheus.service" ]; + before = [ "prometheus.service" ]; + }; + + caddy.routes = lib.mkIf config.services.grafana.enable [{ + match = [{ host = [ config.prometheusServer ]; }]; handle = [{ handler = "reverse_proxy"; - upstreams = [{ dial = "localhost:3000"; }]; + upstreams = [{ dial = "localhost:9090"; }]; }]; }]; diff --git a/modules/nixos/services/samba.nix b/modules/nixos/services/samba.nix index 435fd79..ea4e972 100644 --- a/modules/nixos/services/samba.nix +++ b/modules/nixos/services/samba.nix @@ -1,11 +1,8 @@ { config, lib, ... }: { - options = { samba.enable = lib.mkEnableOption "Enable Samba sharing."; }; - config = { - services.samba = lib.mkIf (config.samba.enable) { - enable = true; + services.samba = lib.mkIf config.services.samba.enable { openFirewall = true; shares.data = { path = "/data"; diff --git a/modules/nixos/services/vaultwarden.nix b/modules/nixos/services/vaultwarden.nix index fe96684..15f92b0 100644 --- a/modules/nixos/services/vaultwarden.nix +++ b/modules/nixos/services/vaultwarden.nix @@ -6,19 +6,18 @@ in { options = { - vaultwardenServer = lib.mkOption { - description = "Hostname for Vaultwarden."; + secretsServer = lib.mkOption { + description = "Hostname for passwords and secrets (Vaultwarden)."; type = lib.types.nullOr lib.types.str; default = null; }; }; - config = lib.mkIf (config.vaultwardenServer != null) { + config = lib.mkIf config.services.vaultwarden.enable { services.vaultwarden = { - enable = true; config = { - DOMAIN = "https://${config.vaultwardenServer}"; + DOMAIN = "https://${config.secretsServer}"; SIGNUPS_ALLOWED = false; SIGNUPS_VERIFY = true; INVITATIONS_ALLOWED = true; @@ -47,7 +46,7 @@ in { networking.firewall.allowedTCPPorts = [ 3012 ]; caddy.routes = [{ - match = [{ host = [ config.vaultwardenServer ]; }]; + match = [{ host = [ config.secretsServer ]; }]; handle = [{ handler = "reverse_proxy"; upstreams = [{ dial = "localhost:8222"; }]; diff --git a/private/prometheus.age b/private/prometheus.age new file mode 100644 index 0000000..de8e937 --- /dev/null +++ b/private/prometheus.age @@ -0,0 +1,12 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBDRWNi +YlJubmg1Ly94cHgxbHV3dStaRkZDRXdNZzVjRCt0R2RNMFkxUEZNCnJxZnc1UHFB +MURselZuL1U5OHFQb0tPLytWelRzYXlvNngya3RQOXREUEkKLT4gc3NoLWVkMjU1 +MTkgWXlTVU1RIDRiR2ZEMUZsYTlGbXFoR0NyZXVXMEZmS3BONDNFQUo4VU1XNkZ0 +ZWFzMHcKM1crbDVsR2VmVTFNckxaa21MTW9UVWE3Z01qMi9VT0kwMm80V0tMSWM1 +bwotPiBzc2gtZWQyNTUxOSBuanZYNUEgd0tIampOVU5ZeWtxNWZpaGdFQTBlWlha +Z0lBQWp0dzhMRHU5UnVzWVlUSQpnUHlCZ0w5Z1hMYm1Dc1UxQ1lLRHlnaUhJQllW +RGMvTEhhc29VL2JXZnhNCi0tLSB6TThQbmV0eFJ0d2pZd1h0c2RuTGFzUHhyYWJp +b2RhVTNkSXczRGJpN1UwCt7I+OsqQdQbFXhYPV5/kqDAr/jVoJ9H5PSfdLkeVIrr +AqScUaOrdctUZEBIF8/FouJkSbIiU8muBNrBKx9CylI= +-----END AGE ENCRYPTED FILE-----