diff options
Diffstat (limited to 'nixos/hosts/tente')
-rw-r--r-- | nixos/hosts/tente/default.nix | 77 | ||||
-rw-r--r-- | nixos/hosts/tente/exporters.nix | 55 | ||||
-rw-r--r-- | nixos/hosts/tente/git.nix | 15 | ||||
-rw-r--r-- | nixos/hosts/tente/gotify.nix | 21 | ||||
-rw-r--r-- | nixos/hosts/tente/grafana.nix | 74 | ||||
-rw-r--r-- | nixos/hosts/tente/matrix.nix | 41 | ||||
-rw-r--r-- | nixos/hosts/tente/metadata.toml | 1 | ||||
-rw-r--r-- | nixos/hosts/tente/monitoring.nix | 317 | ||||
-rw-r--r-- | nixos/hosts/tente/web-personal.nix | 2 |
9 files changed, 217 insertions, 386 deletions
diff --git a/nixos/hosts/tente/default.nix b/nixos/hosts/tente/default.nix index 8904ba7..b9ac389 100644 --- a/nixos/hosts/tente/default.nix +++ b/nixos/hosts/tente/default.nix @@ -1,4 +1,3 @@ -# channel="nixos-small" # Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page, on # https://search.nixos.org/options and in the NixOS manual (`nixos-help`). @@ -6,46 +5,72 @@ { config, lib, pkgs, ... }: let - domain = "push-f.com"; + baseDomain = "push-f.com"; acmeEmail = "martin@push-f.com"; - sources = import ../../npins; - helpers = import <top/helpers.nix> { inherit config; }; + sources = import <top/npins>; + helpers = import <top/helpers.nix> { inherit config lib pkgs; }; + pkgs-unstable = import sources.nixpkgs-unstable {}; in -{ +rec { + _module.args = { inherit pkgs-unstable; }; imports = [ ./hardware-configuration.nix <top/profiles/server> <top/shared/postgresql.nix> <top/shared/tailscale.nix> + <top/shared/monitoring.nix> ./web-personal.nix ./git.nix - ./gotify.nix ./headscale.nix ./matrix.nix - ./monitoring.nix + ./exporters.nix + ./grafana.nix + "${sources.my-lex-surf}/service.nix" "${sources.my-osm-proposals}/service.nix" "${sources.my-geopos-link}/service.nix" + "${sources.my-rust-features}/service.nix" "${sources.my-spec-pub}/service.nix" ]; - web-personal.domain = domain; + web-personal.domain = baseDomain; web-personal.matrixApiDomain = config.matrix.apiDomain; - git.webUiDomain = "git.${domain}"; - headscale.domain = "tailscale.${domain}"; - matrix.serverName = domain; - matrix.apiDomain = "matrix.${domain}"; + git.webUiDomain = "git.${baseDomain}"; + headscale.domain = "tailscale.${baseDomain}"; + matrix.serverName = baseDomain; + matrix.apiDomain = "matrix.${baseDomain}"; + + users.users.www-generator = { + isSystemUser = true; + group = "www-generator"; + }; + users.groups.www-generator = {}; + + services.lex-surf = + let + domain = "lex.surf"; + in + { + enable = true; + domain = domain; + enableACME = true; + fetchUser = "www-generator"; + nginx = { + forceSSL = true; + extraConfig = helpers.mkNginxConfig domain; + }; + }; services.osm_proposals = let - subdomain = "osm-proposals.${domain}"; + domain = "osm-proposals.${baseDomain}"; in { enable = true; - virtualHost = subdomain; + virtualHost = domain; nginx = { enableACME = true; forceSSL = true; - extraConfig = helpers.mkNginxConfig subdomain; + extraConfig = helpers.mkNginxConfig domain; }; }; @@ -63,6 +88,21 @@ in }; }; + services.rust-features = + let + domain = "rust-features.${baseDomain}"; + in + { + enable = true; + user = "www-generator"; + virtualHost = domain; + nginx = { + enableACME = true; + forceSSL = true; + extraConfig = helpers.mkNginxConfig domain; + }; + }; + services.spec-pub = let domain = "spec.pub"; @@ -77,12 +117,13 @@ in }; }; - monitoring.grafanaUiPort = 3000; + grafana.port = 3000; + grafana.matrixForwarderPort = 3002; + grafana.matrixServerUrl = "http://localhost:${toString matrix.port}"; monitoring.alloyUiPort = 3001; monitoring.lokiPort = 3030; - gotify.port = 4000; monitoring.prometheusNodeExporterPort = 9002; - monitoring.prometheusSqlExporterPort = 9003; + exporters.sqlExporterPort = 9003; headscale.port = 8080; matrix.port = 8008; diff --git a/nixos/hosts/tente/exporters.nix b/nixos/hosts/tente/exporters.nix new file mode 100644 index 0000000..1ed53e5 --- /dev/null +++ b/nixos/hosts/tente/exporters.nix @@ -0,0 +1,55 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.exporters; +in +{ + options.exporters = { + sqlExporterPort = lib.mkOption { + type = lib.types.int; + }; + }; + + imports = [ + <top/shared/prometheus-sql-exporter/service.nix> + ]; + + config = { + services.prometheus-sql-exporter = { + enable = true; + port = cfg.sqlExporterPort; + config = { + target = { + # This URL should be postgresql:///postgres?host=/run/postgresql + # but sql_exporter uses xo/dburl which isn't spec-compliant: https://github.com/xo/dburl/issues/46 + data_source_name = "postgresql:/run/postgresql:/postgres"; + collectors = ["db-sizes"]; + }; + collectors = [ + { + collector_name = "db-sizes"; + metrics = [ + { + metric_name = "pg_db_size_bytes"; + help = "disk space used by the database"; + type = "gauge"; + key_labels = ["database_name"]; + values = ["size"]; + query = "SELECT datname AS database_name, pg_database_size(datname) as size from pg_database"; + } + ]; + } + ]; + }; + }; + + monitoring.prometheusScrapeConfigs = [ + { + job_name = "sql"; + static_configs = [{ + targets = [ "localhost:${toString cfg.sqlExporterPort}" ]; + }]; + } + ]; + }; +} diff --git a/nixos/hosts/tente/git.nix b/nixos/hosts/tente/git.nix index ee10a43..49ecff0 100644 --- a/nixos/hosts/tente/git.nix +++ b/nixos/hosts/tente/git.nix @@ -2,7 +2,7 @@ let cfg = config.git; - helpers = import <top/helpers.nix> { inherit config; }; + helpers = import <top/helpers.nix> { inherit config lib pkgs; }; in { options.git = { @@ -47,6 +47,19 @@ in enable-git-config = 1; root-title = "push-f.com repositories"; root-desc = "My various repositories."; + readme = ":README.md"; + about-filter = + # about-formatting.sh from cgit uses python-markdown which doesn't + # follow CommonMark, so we're using the lowdown parser instead. + let + # The about-filter is invoked with stdin but also with the filename + # as argv[1] so we wrap lowdown in a script to ignore the argument. + formatScript = pkgs.writeScriptBin "about-format.sh" '' + #!/bin/sh + ${pkgs.lowdown}/bin/lowdown + ''; + in + "${formatScript}/bin/about-format.sh"; enable-index-owner = 0; source-filter = "${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py"; clone-prefix = "https://${cfg.webUiDomain}"; diff --git a/nixos/hosts/tente/gotify.nix b/nixos/hosts/tente/gotify.nix deleted file mode 100644 index ba0fd02..0000000 --- a/nixos/hosts/tente/gotify.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ config, lib, ... }: - -let - cfg = config.gotify; -in -{ - options.gotify = { - port = lib.mkOption { - type = lib.types.int; - }; - }; - - config = { - services.gotify = { - enable = true; - environment = { - GOTIFY_SERVER_PORT = cfg.port; - }; - }; - }; -} diff --git a/nixos/hosts/tente/grafana.nix b/nixos/hosts/tente/grafana.nix new file mode 100644 index 0000000..02d26c5 --- /dev/null +++ b/nixos/hosts/tente/grafana.nix @@ -0,0 +1,74 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.grafana; +in +{ + options.grafana = { + port = lib.mkOption { + type = lib.types.int; + }; + matrixForwarderPort = lib.mkOption { + type = lib.types.int; + }; + prometheusSqlExporterPort = lib.mkOption { + type = lib.types.int; + }; + matrixServerUrl = lib.mkOption { + type = lib.types.str; + }; + }; + + imports = [ + <top/shared/prometheus-sql-exporter/service.nix> + <top/shared/grafana-matrix-forwarder/service.nix> + ]; + + config = { + age.secrets.grafana-matrix-forwarder-env.file = <top/secrets/grafana-matrix-forwarder-env.age>; + + services.grafana = { + enable = true; + settings = { + server = { + http_addr = "0.0.0.0"; + http_port = cfg.port; + }; + }; + + provision = { + enable = true; + datasources.settings.datasources = [ + { + name = "Prometheus Tente"; + type = "prometheus"; + url = "http://${config.services.prometheus.listenAddress}:${toString config.services.prometheus.port}"; + } + { + name = "Loki Tente"; + type = "loki"; + access = "proxy"; + url = "http://127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}"; + } + { + name = "Prometheus Ev"; + type = "prometheus"; + url = "http://ev.tailnet:9090"; + } + { + name = "Loki Ev"; + type = "loki"; + access = "proxy"; + url = "http://ev.tailnet:3030"; + } + ]; + }; + }; + services.grafana-matrix-forwarder = { + enable = true; + port = cfg.matrixForwarderPort; + homeserver = cfg.matrixServerUrl; + environmentFile = config.age.secrets.grafana-matrix-forwarder-env.path; + }; + }; +} diff --git a/nixos/hosts/tente/matrix.nix b/nixos/hosts/tente/matrix.nix index cf0f09a..89782fc 100644 --- a/nixos/hosts/tente/matrix.nix +++ b/nixos/hosts/tente/matrix.nix @@ -1,8 +1,8 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, pkgs-unstable, ... }: let cfg = config.matrix; - helpers = import <top/helpers.nix> { inherit config; }; + helpers = import <top/helpers.nix> { inherit config lib pkgs; }; in { options.matrix = { @@ -19,32 +19,19 @@ in config = { services = { - matrix-synapse = { + matrix-conduit = { enable = true; + package = pkgs-unstable.matrix-conduit; settings = { - server_name = cfg.serverName; - listeners = [{ - # This listener matches the default of NixOS 24.11 (replicated here to make the port configurable). - bind_addresses = ["127.0.0.1"]; + global = { + server_name = cfg.serverName; port = cfg.port; - resources = [ - { - compress = true; - names = ["client"]; - } - { - compress = false; - names = ["federation"]; - } - ]; - tls = false; - type = "http"; - x_forwarded = true; - }]; + address = "127.0.0.1"; # this is the default of conduit but the nixos service defaults to ::1 + database_backend = "rocksdb"; + enable_lightning_bolt = false; + allow_registration = false; + }; }; - - # The default is INFO which can easily spam the systemd journal with 500k messages a day. - log.root.level = "WARNING"; }; nginx.virtualHosts.${cfg.apiDomain} = { @@ -54,14 +41,12 @@ in # TODO: add locations."/" with some message - # Forward all Matrix API calls to the synapse Matrix homeserver. A trailing slash + # Forward all Matrix API calls to the Conduit Matrix homeserver. A trailing slash # *must not* be used here. locations."/_matrix".proxyPass = "http://127.0.0.1:${toString cfg.port}"; - # Forward requests for e.g. SSO and password-resets. - locations."/_synapse/client".proxyPass = "http://127.0.0.1:${toString cfg.port}"; }; - # I don't really care about these nginx access logs. Synapse has its own + # I don't really care about these nginx access logs. Conduit has its own # log anyway and with the default log rotation (weekly and delaycompress=true) # the access logs from last week took up ~800MB. logrotate.settings.matrix-nginx-access-log = diff --git a/nixos/hosts/tente/metadata.toml b/nixos/hosts/tente/metadata.toml new file mode 100644 index 0000000..58f0301 --- /dev/null +++ b/nixos/hosts/tente/metadata.toml @@ -0,0 +1 @@ +channel = "nixos-small" diff --git a/nixos/hosts/tente/monitoring.nix b/nixos/hosts/tente/monitoring.nix deleted file mode 100644 index 7e92eed..0000000 --- a/nixos/hosts/tente/monitoring.nix +++ /dev/null @@ -1,317 +0,0 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.monitoring; -in -{ - options.monitoring = { - grafanaUiPort = lib.mkOption { - type = lib.types.int; - }; - lokiPort = lib.mkOption { - type = lib.types.int; - }; - alloyUiPort = lib.mkOption { - type = lib.types.int; - }; - prometheusNodeExporterPort = lib.mkOption { - type = lib.types.int; - }; - prometheusSqlExporterPort = lib.mkOption { - type = lib.types.int; - }; - }; - - imports = [ - <top/shared/prometheus-sql-exporter/service.nix> - ]; - - config = { - services.grafana = { - enable = true; - settings = { - server = { - http_addr = "0.0.0.0"; - http_port = cfg.grafanaUiPort; - }; - }; - - provision = { - enable = true; - datasources.settings.datasources = [ - { - name = "Prometheus"; - type = "prometheus"; - url = "http://${config.services.prometheus.listenAddress}:${toString config.services.prometheus.port}"; - } - { - name = "Loki"; - type = "loki"; - access = "proxy"; - url = "http://127.0.0.1:${toString cfg.lokiPort}"; - } - ]; - }; - }; - - services.prometheus = { - enable = true; - - scrapeConfigs = [ - { - job_name = "node"; - static_configs = [{ - targets = [ "localhost:${toString cfg.prometheusNodeExporterPort}" ]; - }]; - } - { - job_name = "sql"; - static_configs = [{ - targets = [ "localhost:${toString cfg.prometheusSqlExporterPort}" ]; - }]; - } - ]; - - exporters.node = { - enable = true; - enabledCollectors = [ "systemd" ]; - port = cfg.prometheusNodeExporterPort; - }; - }; - - services.prometheus-sql-exporter = { - enable = true; - port = cfg.prometheusSqlExporterPort; - config = { - target = { - # This URL should be postgresql:///postgres?host=/run/postgresql - # but sql_exporter uses xo/dburl which isn't spec-compliant: https://github.com/xo/dburl/issues/46 - data_source_name = "postgresql:/run/postgresql:/postgres"; - collectors = ["db-sizes"]; - }; - collectors = [ - { - collector_name = "db-sizes"; - metrics = [ - { - metric_name = "pg_db_size_bytes"; - help = "disk space used by the database"; - type = "gauge"; - key_labels = ["database_name"]; - values = ["size"]; - query = "SELECT datname AS database_name, pg_database_size(datname) as size from pg_database"; - } - ]; - } - ]; - }; - }; - - services.loki = { - enable = true; - configuration = { - server.http_listen_port = cfg.lokiPort; - auth_enabled = false; - - ingester = { - lifecycler = { - address = "127.0.0.1"; - ring = { - kvstore.store = "inmemory"; - replication_factor = 1; - }; - }; - }; - - schema_config = { - configs = [{ - store = "tsdb"; - object_store = "filesystem"; - schema = "v13"; - index = { - prefix = "index_"; - period = "24h"; - }; - }]; - }; - - storage_config = { - tsdb_shipper = { - active_index_directory = "/var/lib/loki/tsdb-active"; - cache_location = "/var/lib/loki/tsdb-cache"; - }; - }; - - compactor = { - working_directory = "/var/lib/loki"; - }; - - limits_config = { - allow_structured_metadata = true; - }; - }; - }; - - systemd.services.alloy = { - serviceConfig = { - SupplementaryGroups = [ - "systemd-journal" - "www-data" - ]; - }; - }; - - services.alloy = { - enable = true; - extraFlags = ["--server.http.listen-addr=0.0.0.0:${toString cfg.alloyUiPort}"]; - # TODO: submit PR to nixpkgs so that the alloy config can be specified as a JSON expression - configPath = pkgs.writeText "config.alloy" '' - loki.source.journal "journal" { - max_age = "12h0m0s" - relabel_rules = discovery.relabel.journal.rules - forward_to = [loki.process.journal.receiver] - labels = { - host = "tente", - job = "systemd-journal", - } - } - - loki.process "journal" { - forward_to = [loki.write.default.receiver] - - stage.match { - // Select messages from systemd services that have LogExtraFields=log_format=logfmt. - selector = "{__journal_log_format=\"logfmt\"}" - stage.logfmt { - mapping = { time = "", level = "" } - } - stage.timestamp { - source = "time" - format = "RFC3339" - } - stage.structured_metadata { - values = { level = "" } - } - } - } - - discovery.relabel "journal" { - targets = [] - - rule { - source_labels = ["__journal__systemd_unit"] - target_label = "unit" - } - } - - loki.source.file "nginx_access" { - targets = local.file_match.nginx_access.targets - forward_to = [loki.process.nginx_access.receiver] - } - - local.file_match "nginx_access" { - path_targets = [{ - __path__ = "/var/log/nginx/*.access.log", - }] - } - - loki.process "nginx_access" { - forward_to = [loki.write.default.receiver] - - stage.static_labels { - values = { - job = "nginx", - } - } - - // Extracting the log file name as vhost because it's more convenient - // to query for than the full filename. We could also use server_name - // but there could be wildcard server_names and Loki labels should have - // a low cardinality for performance reasons. - stage.regex { - source = "filename" - expression = "(?P<vhost>[^/]+)\\.access\\.log$" - } - - stage.labels { - values = { - vhost = "", - } - } - - stage.json { - expressions = { "msec" = "", path = "" } - } - - stage.timestamp { - source = "msec" - format = "Unix" - } - - // Setting level=info to prevent Loki's log level detection from wrongly - // detecting messages with paths containing "error" as errors. - // Creating the filetype entry via stage.template because there's no - // static_structured_metadata stage yet. (https://github.com/grafana/loki/issues/16703) - stage.template { - source = "level" - template = "info" - } - stage.structured_metadata { - values = { level = "" } - } - - stage.labels { - values = { - // Temporarily adding path as a label so that we can use it in the match selectors. - path = "", - } - } - - stage.match { - selector = "{path=~\"/\\\\.well-known/.*\"}" - // Creating the filetype entry via stage.template because there's no - // static_structured_metadata stage yet. (https://github.com/grafana/loki/issues/16703) - stage.template { - source = "filetype" - template = "well-known" - } - } - - stage.match { - selector = "{path=\"/robots.txt\"}" - stage.template { - source = "filetype" - template = "robots.txt" - } - } - - stage.match { - selector = "{path=~\".*\\\\.atom$\"}" - stage.template { - source = "filetype" - template = "feed" - } - } - - stage.structured_metadata { - values = { - filetype = "", - } - } - - // Dropping path again because it has a too high cardinality for a label. - stage.label_drop { - values = [ "path" ] - } - } - - loki.write "default" { - endpoint { - url = "http://127.0.0.1:${toString cfg.lokiPort}/loki/api/v1/push" - } - external_labels = {} - } - ''; - }; - }; -} diff --git a/nixos/hosts/tente/web-personal.nix b/nixos/hosts/tente/web-personal.nix index 109a87d..d706b9d 100644 --- a/nixos/hosts/tente/web-personal.nix +++ b/nixos/hosts/tente/web-personal.nix @@ -2,7 +2,7 @@ let cfg = config.web-personal; - helpers = import <top/helpers.nix> { inherit config; }; + helpers = import <top/helpers.nix> { inherit config lib pkgs; }; in { options.web-personal = { |