diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/abs-podcast-autoplaylist.nix | 1 | ||||
| -rw-r--r-- | modules/borgcopy/.envrc | 4 | ||||
| -rw-r--r-- | modules/borgcopy/.gitignore | 2 | ||||
| -rw-r--r-- | modules/borgcopy/default.nix | 39 | ||||
| -rw-r--r-- | modules/borgcopy/poetry.lock | 180 | ||||
| -rw-r--r-- | modules/borgcopy/pyproject.toml | 33 | ||||
| -rw-r--r-- | modules/borgcopy/uv.lock | 146 | ||||
| -rw-r--r-- | modules/i18n.nix | 156 | ||||
| -rw-r--r-- | modules/impermanence-timezone.nix | 41 | ||||
| -rw-r--r-- | modules/impermanence.nix | 6 | ||||
| -rw-r--r-- | modules/niri-autoselect-portal.nix | 6 | ||||
| -rw-r--r-- | modules/nix-access-tokens/nix.conf | 15 | ||||
| -rw-r--r-- | modules/postsrsd.nix | 6 | ||||
| -rw-r--r-- | modules/prometheus.nix | 2048 | ||||
| -rw-r--r-- | modules/uucp.nix | 373 |
15 files changed, 2306 insertions, 750 deletions
diff --git a/modules/abs-podcast-autoplaylist.nix b/modules/abs-podcast-autoplaylist.nix index 2532cfc3..f526a434 100644 --- a/modules/abs-podcast-autoplaylist.nix +++ b/modules/abs-podcast-autoplaylist.nix | |||
| @@ -37,6 +37,7 @@ in { | |||
| 37 | PrivateDevices = true; | 37 | PrivateDevices = true; |
| 38 | Type = "oneshot"; | 38 | Type = "oneshot"; |
| 39 | ExecStart = "${lib.getExe pkgs.abs-podcast-autoplaylist} %I.toml"; | 39 | ExecStart = "${lib.getExe pkgs.abs-podcast-autoplaylist} %I.toml"; |
| 40 | TimeoutSec = "5min"; | ||
| 40 | }; | 41 | }; |
| 41 | }; | 42 | }; |
| 42 | } // lib.mapAttrs' (name: { configSecret, ... }: lib.nameValuePair "abs-podcast-autoplaylist@${utils.escapeSystemdPath name}" { | 43 | } // lib.mapAttrs' (name: { configSecret, ... }: lib.nameValuePair "abs-podcast-autoplaylist@${utils.escapeSystemdPath name}" { |
diff --git a/modules/borgcopy/.envrc b/modules/borgcopy/.envrc new file mode 100644 index 00000000..01e755c1 --- /dev/null +++ b/modules/borgcopy/.envrc | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | use flake | ||
| 2 | |||
| 3 | uv venv && uv sync | ||
| 4 | . .venv/bin/activate | ||
diff --git a/modules/borgcopy/.gitignore b/modules/borgcopy/.gitignore new file mode 100644 index 00000000..4ccfae70 --- /dev/null +++ b/modules/borgcopy/.gitignore | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | .venv | ||
| 2 | **/__pycache__ | ||
diff --git a/modules/borgcopy/default.nix b/modules/borgcopy/default.nix index 8e1afc27..af021777 100644 --- a/modules/borgcopy/default.nix +++ b/modules/borgcopy/default.nix | |||
| @@ -1,25 +1,32 @@ | |||
| 1 | { config, pkgs, lib, utils, flakeInputs, ... }: | 1 | { config, pkgs, lib, utils, flake, flakeInputs, ... }: |
| 2 | 2 | ||
| 3 | with lib; | 3 | with lib; |
| 4 | 4 | ||
| 5 | let | 5 | let |
| 6 | copyBorg = | 6 | copyBorg = let |
| 7 | with pkgs.poetry2nix; | 7 | workspace = flakeInputs.uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./.; }; |
| 8 | mkPoetryApplication { | 8 | pythonSet = flake.lib.pythonSet { |
| 9 | projectDir = cleanPythonSources { src = ./.; }; | 9 | inherit pkgs; |
| 10 | python = pkgs.python312; | ||
| 11 | overlay = workspace.mkPyprojectOverlay { | ||
| 12 | sourcePreference = "wheel"; | ||
| 13 | }; | ||
| 14 | }; | ||
| 15 | virtualEnv = pythonSet.mkVirtualEnv "copy_borg" workspace.deps.default; | ||
| 16 | in virtualEnv.overrideAttrs (oldAttrs: { | ||
| 17 | meta = (oldAttrs.meta or {}) // { | ||
| 18 | mainProgram = "copy_borg"; | ||
| 19 | }; | ||
| 10 | 20 | ||
| 11 | overrides = overrides.withDefaults (self: super: { | 21 | nativeBuildInputs = (oldAttrs.nativeBuildInputs or []) ++ [ pkgs.makeWrapper ]; |
| 12 | pyprctl = super.pyprctl.overridePythonAttrs (oldAttrs: { | ||
| 13 | buildInputs = (oldAttrs.buildInputs or []) ++ [super.setuptools]; | ||
| 14 | }); | ||
| 15 | inherit (pkgs.python3Packages) python-unshare; | ||
| 16 | }); | ||
| 17 | 22 | ||
| 18 | postInstall = '' | 23 | postInstall = '' |
| 19 | wrapProgram $out/bin/copy_borg \ | 24 | ${oldAttrs.postInstall or ""} |
| 20 | --prefix PATH : ${makeBinPath (with pkgs; [util-linux borgbackup])}:${config.security.wrapperDir} | 25 | |
| 21 | ''; | 26 | wrapProgram $out/bin/copy_borg \ |
| 22 | }; | 27 | --prefix PATH : ${makeBinPath (with pkgs; [util-linux borgbackup])}:${config.security.wrapperDir} |
| 28 | ''; | ||
| 29 | }); | ||
| 23 | 30 | ||
| 24 | copyService = name: opts: nameValuePair "copy-borg@${utils.escapeSystemdPath name}" { | 31 | copyService = name: opts: nameValuePair "copy-borg@${utils.escapeSystemdPath name}" { |
| 25 | restartIfChanged = false; | 32 | restartIfChanged = false; |
diff --git a/modules/borgcopy/poetry.lock b/modules/borgcopy/poetry.lock deleted file mode 100644 index 759ecfe9..00000000 --- a/modules/borgcopy/poetry.lock +++ /dev/null | |||
| @@ -1,180 +0,0 @@ | |||
| 1 | # This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. | ||
| 2 | |||
| 3 | [[package]] | ||
| 4 | name = "colorama" | ||
| 5 | version = "0.4.6" | ||
| 6 | description = "Cross-platform colored terminal text." | ||
| 7 | category = "main" | ||
| 8 | optional = false | ||
| 9 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" | ||
| 10 | files = [ | ||
| 11 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, | ||
| 12 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, | ||
| 13 | ] | ||
| 14 | |||
| 15 | [[package]] | ||
| 16 | name = "halo" | ||
| 17 | version = "0.0.31" | ||
| 18 | description = "Beautiful terminal spinners in Python" | ||
| 19 | category = "main" | ||
| 20 | optional = false | ||
| 21 | python-versions = ">=3.4" | ||
| 22 | files = [ | ||
| 23 | {file = "halo-0.0.31-py2-none-any.whl", hash = "sha256:5350488fb7d2aa7c31a1344120cee67a872901ce8858f60da7946cef96c208ab"}, | ||
| 24 | {file = "halo-0.0.31.tar.gz", hash = "sha256:7b67a3521ee91d53b7152d4ee3452811e1d2a6321975137762eb3d70063cc9d6"}, | ||
| 25 | ] | ||
| 26 | |||
| 27 | [package.dependencies] | ||
| 28 | colorama = ">=0.3.9" | ||
| 29 | log-symbols = ">=0.0.14" | ||
| 30 | six = ">=1.12.0" | ||
| 31 | spinners = ">=0.0.24" | ||
| 32 | termcolor = ">=1.1.0" | ||
| 33 | |||
| 34 | [package.extras] | ||
| 35 | ipython = ["IPython (==5.7.0)", "ipywidgets (==7.1.0)"] | ||
| 36 | |||
| 37 | [[package]] | ||
| 38 | name = "humanize" | ||
| 39 | version = "4.6.0" | ||
| 40 | description = "Python humanize utilities" | ||
| 41 | category = "main" | ||
| 42 | optional = false | ||
| 43 | python-versions = ">=3.7" | ||
| 44 | files = [ | ||
| 45 | {file = "humanize-4.6.0-py3-none-any.whl", hash = "sha256:401201aca462749773f02920139f302450cb548b70489b9b4b92be39fe3c3c50"}, | ||
| 46 | {file = "humanize-4.6.0.tar.gz", hash = "sha256:5f1f22bc65911eb1a6ffe7659bd6598e33dcfeeb904eb16ee1e705a09bf75916"}, | ||
| 47 | ] | ||
| 48 | |||
| 49 | [package.extras] | ||
| 50 | tests = ["freezegun", "pytest", "pytest-cov"] | ||
| 51 | |||
| 52 | [[package]] | ||
| 53 | name = "log-symbols" | ||
| 54 | version = "0.0.14" | ||
| 55 | description = "Colored symbols for various log levels for Python" | ||
| 56 | category = "main" | ||
| 57 | optional = false | ||
| 58 | python-versions = "*" | ||
| 59 | files = [ | ||
| 60 | {file = "log_symbols-0.0.14-py3-none-any.whl", hash = "sha256:4952106ff8b605ab7d5081dd2c7e6ca7374584eff7086f499c06edd1ce56dcca"}, | ||
| 61 | {file = "log_symbols-0.0.14.tar.gz", hash = "sha256:cf0bbc6fe1a8e53f0d174a716bc625c4f87043cc21eb55dd8a740cfe22680556"}, | ||
| 62 | ] | ||
| 63 | |||
| 64 | [package.dependencies] | ||
| 65 | colorama = ">=0.3.9" | ||
| 66 | |||
| 67 | [[package]] | ||
| 68 | name = "pyprctl" | ||
| 69 | version = "0.1.3" | ||
| 70 | description = "An interface to Linux's prctl() syscall written in pure Python using ctypes." | ||
| 71 | category = "main" | ||
| 72 | optional = false | ||
| 73 | python-versions = ">=3.6" | ||
| 74 | files = [ | ||
| 75 | {file = "pyprctl-0.1.3-py3-none-any.whl", hash = "sha256:6302e5114f078fb33e5799835d0a69e2fc180bb6b28ad073515fa40c5272f1dd"}, | ||
| 76 | {file = "pyprctl-0.1.3.tar.gz", hash = "sha256:1fb54d3ab030ec02e4afc38fb9662d6634c12834e91ae7959de56a9c09f69c26"}, | ||
| 77 | ] | ||
| 78 | |||
| 79 | [[package]] | ||
| 80 | name = "python-dateutil" | ||
| 81 | version = "2.8.2" | ||
| 82 | description = "Extensions to the standard Python datetime module" | ||
| 83 | category = "main" | ||
| 84 | optional = false | ||
| 85 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" | ||
| 86 | files = [ | ||
| 87 | {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, | ||
| 88 | {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, | ||
| 89 | ] | ||
| 90 | |||
| 91 | [package.dependencies] | ||
| 92 | six = ">=1.5" | ||
| 93 | |||
| 94 | [[package]] | ||
| 95 | name = "python-unshare" | ||
| 96 | version = "0.2" | ||
| 97 | description = "Python bindings for the Linux unshare() syscall" | ||
| 98 | category = "main" | ||
| 99 | optional = false | ||
| 100 | python-versions = "*" | ||
| 101 | files = [ | ||
| 102 | {file = "python-unshare-0.2.tar.gz", hash = "sha256:f79b7de441b6c27930b775085a6a4fd2f378b628737aaaebc2a6c519023fd47a"}, | ||
| 103 | ] | ||
| 104 | |||
| 105 | [[package]] | ||
| 106 | name = "six" | ||
| 107 | version = "1.16.0" | ||
| 108 | description = "Python 2 and 3 compatibility utilities" | ||
| 109 | category = "main" | ||
| 110 | optional = false | ||
| 111 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" | ||
| 112 | files = [ | ||
| 113 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, | ||
| 114 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, | ||
| 115 | ] | ||
| 116 | |||
| 117 | [[package]] | ||
| 118 | name = "spinners" | ||
| 119 | version = "0.0.24" | ||
| 120 | description = "Spinners for terminals" | ||
| 121 | category = "main" | ||
| 122 | optional = false | ||
| 123 | python-versions = "*" | ||
| 124 | files = [ | ||
| 125 | {file = "spinners-0.0.24-py3-none-any.whl", hash = "sha256:2fa30d0b72c9650ad12bbe031c9943b8d441e41b4f5602b0ec977a19f3290e98"}, | ||
| 126 | {file = "spinners-0.0.24.tar.gz", hash = "sha256:1eb6aeb4781d72ab42ed8a01dcf20f3002bf50740d7154d12fb8c9769bf9e27f"}, | ||
| 127 | ] | ||
| 128 | |||
| 129 | [[package]] | ||
| 130 | name = "termcolor" | ||
| 131 | version = "2.2.0" | ||
| 132 | description = "ANSI color formatting for output in terminal" | ||
| 133 | category = "main" | ||
| 134 | optional = false | ||
| 135 | python-versions = ">=3.7" | ||
| 136 | files = [ | ||
| 137 | {file = "termcolor-2.2.0-py3-none-any.whl", hash = "sha256:91ddd848e7251200eac969846cbae2dacd7d71c2871e92733289e7e3666f48e7"}, | ||
| 138 | {file = "termcolor-2.2.0.tar.gz", hash = "sha256:dfc8ac3f350788f23b2947b3e6cfa5a53b630b612e6cd8965a015a776020b99a"}, | ||
| 139 | ] | ||
| 140 | |||
| 141 | [package.extras] | ||
| 142 | tests = ["pytest", "pytest-cov"] | ||
| 143 | |||
| 144 | [[package]] | ||
| 145 | name = "tqdm" | ||
| 146 | version = "4.65.0" | ||
| 147 | description = "Fast, Extensible Progress Meter" | ||
| 148 | category = "main" | ||
| 149 | optional = false | ||
| 150 | python-versions = ">=3.7" | ||
| 151 | files = [ | ||
| 152 | {file = "tqdm-4.65.0-py3-none-any.whl", hash = "sha256:c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671"}, | ||
| 153 | {file = "tqdm-4.65.0.tar.gz", hash = "sha256:1871fb68a86b8fb3b59ca4cdd3dcccbc7e6d613eeed31f4c332531977b89beb5"}, | ||
| 154 | ] | ||
| 155 | |||
| 156 | [package.dependencies] | ||
| 157 | colorama = {version = "*", markers = "platform_system == \"Windows\""} | ||
| 158 | |||
| 159 | [package.extras] | ||
| 160 | dev = ["py-make (>=0.1.0)", "twine", "wheel"] | ||
| 161 | notebook = ["ipywidgets (>=6)"] | ||
| 162 | slack = ["slack-sdk"] | ||
| 163 | telegram = ["requests"] | ||
| 164 | |||
| 165 | [[package]] | ||
| 166 | name = "xdg" | ||
| 167 | version = "6.0.0" | ||
| 168 | description = "Variables defined by the XDG Base Directory Specification" | ||
| 169 | category = "main" | ||
| 170 | optional = false | ||
| 171 | python-versions = ">=3.7,<4.0" | ||
| 172 | files = [ | ||
| 173 | {file = "xdg-6.0.0-py3-none-any.whl", hash = "sha256:df3510755b4395157fc04fc3b02467c777f3b3ca383257397f09ab0d4c16f936"}, | ||
| 174 | {file = "xdg-6.0.0.tar.gz", hash = "sha256:24278094f2d45e846d1eb28a2ebb92d7b67fc0cab5249ee3ce88c95f649a1c92"}, | ||
| 175 | ] | ||
| 176 | |||
| 177 | [metadata] | ||
| 178 | lock-version = "2.0" | ||
| 179 | python-versions = ">=3.10.0,<3.12" | ||
| 180 | content-hash = "3c6b538852447a8f3ae34e1be122716d47e669a2b44f7c5d3d850e5d877353c7" | ||
diff --git a/modules/borgcopy/pyproject.toml b/modules/borgcopy/pyproject.toml index f3401ed2..d76d73c6 100644 --- a/modules/borgcopy/pyproject.toml +++ b/modules/borgcopy/pyproject.toml | |||
| @@ -1,22 +1,25 @@ | |||
| 1 | [tool.poetry] | 1 | [project] |
| 2 | name = "copy_borg" | 2 | name = "copy_borg" |
| 3 | version = "0.0.0" | 3 | version = "0.0.0" |
| 4 | authors = ["Gregor Kleen <gkleen@yggdrasil.li>"] | ||
| 5 | description = "" | 4 | description = "" |
| 5 | authors = [{ name = "Gregor Kleen", email = "gkleen@yggdrasil.li" }] | ||
| 6 | requires-python = "~=3.12" | ||
| 7 | dependencies = [ | ||
| 8 | "humanize>=4.6.0,<5", | ||
| 9 | "tqdm>=4.65.0,<5", | ||
| 10 | "python-dateutil>=2.8.2,<3", | ||
| 11 | "xdg>=6.0.0,<7", | ||
| 12 | "pyprctl>=0.1.3,<0.2", | ||
| 13 | "halo>=0.0.31,<0.0.32", | ||
| 14 | "unshare>=0.22", | ||
| 15 | ] | ||
| 6 | 16 | ||
| 7 | [tool.poetry.scripts] | 17 | [project.scripts] |
| 8 | copy_borg = "copy_borg.__main__:main" | 18 | copy_borg = "copy_borg.__main__:main" |
| 9 | 19 | ||
| 10 | [tool.poetry.dependencies] | ||
| 11 | python = ">=3.10.0,<3.12" | ||
| 12 | humanize = "^4.6.0" | ||
| 13 | tqdm = "^4.65.0" | ||
| 14 | python-dateutil = "^2.8.2" | ||
| 15 | xdg = "^6.0.0" | ||
| 16 | python-unshare = "^0.2" | ||
| 17 | pyprctl = "^0.1.3" | ||
| 18 | halo = "^0.0.31" | ||
| 19 | |||
| 20 | [build-system] | 20 | [build-system] |
| 21 | requires = ["poetry-core>=1.0.0"] | 21 | requires = ["hatchling"] |
| 22 | build-backend = "poetry.core.masonry.api" \ No newline at end of file | 22 | build-backend = "hatchling.build" |
| 23 | |||
| 24 | [tool.hatch.build.targets.wheel] | ||
| 25 | packages = ["copy_borg"] | ||
diff --git a/modules/borgcopy/uv.lock b/modules/borgcopy/uv.lock new file mode 100644 index 00000000..1a282598 --- /dev/null +++ b/modules/borgcopy/uv.lock | |||
| @@ -0,0 +1,146 @@ | |||
| 1 | version = 1 | ||
| 2 | revision = 2 | ||
| 3 | requires-python = ">=3.12, <4" | ||
| 4 | |||
| 5 | [[package]] | ||
| 6 | name = "colorama" | ||
| 7 | version = "0.4.6" | ||
| 8 | source = { registry = "https://pypi.org/simple" } | ||
| 9 | sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } | ||
| 10 | wheels = [ | ||
| 11 | { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, | ||
| 12 | ] | ||
| 13 | |||
| 14 | [[package]] | ||
| 15 | name = "copy-borg" | ||
| 16 | version = "0.0.0" | ||
| 17 | source = { editable = "." } | ||
| 18 | dependencies = [ | ||
| 19 | { name = "halo" }, | ||
| 20 | { name = "humanize" }, | ||
| 21 | { name = "pyprctl" }, | ||
| 22 | { name = "python-dateutil" }, | ||
| 23 | { name = "tqdm" }, | ||
| 24 | { name = "unshare" }, | ||
| 25 | { name = "xdg" }, | ||
| 26 | ] | ||
| 27 | |||
| 28 | [package.metadata] | ||
| 29 | requires-dist = [ | ||
| 30 | { name = "halo", specifier = ">=0.0.31,<0.0.32" }, | ||
| 31 | { name = "humanize", specifier = ">=4.6.0,<5" }, | ||
| 32 | { name = "pyprctl", specifier = ">=0.1.3,<0.2" }, | ||
| 33 | { name = "python-dateutil", specifier = ">=2.8.2,<3" }, | ||
| 34 | { name = "tqdm", specifier = ">=4.65.0,<5" }, | ||
| 35 | { name = "unshare", specifier = ">=0.22" }, | ||
| 36 | { name = "xdg", specifier = ">=6.0.0,<7" }, | ||
| 37 | ] | ||
| 38 | |||
| 39 | [[package]] | ||
| 40 | name = "halo" | ||
| 41 | version = "0.0.31" | ||
| 42 | source = { registry = "https://pypi.org/simple" } | ||
| 43 | dependencies = [ | ||
| 44 | { name = "colorama" }, | ||
| 45 | { name = "log-symbols" }, | ||
| 46 | { name = "six" }, | ||
| 47 | { name = "spinners" }, | ||
| 48 | { name = "termcolor" }, | ||
| 49 | ] | ||
| 50 | sdist = { url = "https://files.pythonhosted.org/packages/ee/48/d53580d30b1fabf25d0d1fcc3f5b26d08d2ac75a1890ff6d262f9f027436/halo-0.0.31.tar.gz", hash = "sha256:7b67a3521ee91d53b7152d4ee3452811e1d2a6321975137762eb3d70063cc9d6", size = 11666, upload-time = "2020-11-10T02:36:48.335Z" } | ||
| 51 | |||
| 52 | [[package]] | ||
| 53 | name = "humanize" | ||
| 54 | version = "4.12.3" | ||
| 55 | source = { registry = "https://pypi.org/simple" } | ||
| 56 | sdist = { url = "https://files.pythonhosted.org/packages/22/d1/bbc4d251187a43f69844f7fd8941426549bbe4723e8ff0a7441796b0789f/humanize-4.12.3.tar.gz", hash = "sha256:8430be3a615106fdfceb0b2c1b41c4c98c6b0fc5cc59663a5539b111dd325fb0", size = 80514, upload-time = "2025-04-30T11:51:07.98Z" } | ||
| 57 | wheels = [ | ||
| 58 | { url = "https://files.pythonhosted.org/packages/a0/1e/62a2ec3104394a2975a2629eec89276ede9dbe717092f6966fcf963e1bf0/humanize-4.12.3-py3-none-any.whl", hash = "sha256:2cbf6370af06568fa6d2da77c86edb7886f3160ecd19ee1ffef07979efc597f6", size = 128487, upload-time = "2025-04-30T11:51:06.468Z" }, | ||
| 59 | ] | ||
| 60 | |||
| 61 | [[package]] | ||
| 62 | name = "log-symbols" | ||
| 63 | version = "0.0.14" | ||
| 64 | source = { registry = "https://pypi.org/simple" } | ||
| 65 | dependencies = [ | ||
| 66 | { name = "colorama" }, | ||
| 67 | ] | ||
| 68 | sdist = { url = "https://files.pythonhosted.org/packages/45/87/e86645d758a4401c8c81914b6a88470634d1785c9ad09823fa4a1bd89250/log_symbols-0.0.14.tar.gz", hash = "sha256:cf0bbc6fe1a8e53f0d174a716bc625c4f87043cc21eb55dd8a740cfe22680556", size = 3211, upload-time = "2019-08-08T06:32:22.538Z" } | ||
| 69 | wheels = [ | ||
| 70 | { url = "https://files.pythonhosted.org/packages/28/5d/d710c38be68b0fb54e645048fe359c3904cc3cb64b2de9d40e1712bf110c/log_symbols-0.0.14-py3-none-any.whl", hash = "sha256:4952106ff8b605ab7d5081dd2c7e6ca7374584eff7086f499c06edd1ce56dcca", size = 3081, upload-time = "2019-08-08T06:32:20.604Z" }, | ||
| 71 | ] | ||
| 72 | |||
| 73 | [[package]] | ||
| 74 | name = "pyprctl" | ||
| 75 | version = "0.1.3" | ||
| 76 | source = { registry = "https://pypi.org/simple" } | ||
| 77 | sdist = { url = "https://files.pythonhosted.org/packages/c9/16/6ed71ebcad76c1cd5f22185bcc6b31c0ee62fc5e693b626febea8fedeba3/pyprctl-0.1.3.tar.gz", hash = "sha256:1fb54d3ab030ec02e4afc38fb9662d6634c12834e91ae7959de56a9c09f69c26", size = 18739, upload-time = "2021-10-26T23:52:03.87Z" } | ||
| 78 | wheels = [ | ||
| 79 | { url = "https://files.pythonhosted.org/packages/bf/5e/62765de39bbce8111fb1f4453a4a804913bf49179fa265fb713ed66c9d15/pyprctl-0.1.3-py3-none-any.whl", hash = "sha256:6302e5114f078fb33e5799835d0a69e2fc180bb6b28ad073515fa40c5272f1dd", size = 20016, upload-time = "2021-10-26T23:52:02.986Z" }, | ||
| 80 | ] | ||
| 81 | |||
| 82 | [[package]] | ||
| 83 | name = "python-dateutil" | ||
| 84 | version = "2.9.0.post0" | ||
| 85 | source = { registry = "https://pypi.org/simple" } | ||
| 86 | dependencies = [ | ||
| 87 | { name = "six" }, | ||
| 88 | ] | ||
| 89 | sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } | ||
| 90 | wheels = [ | ||
| 91 | { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, | ||
| 92 | ] | ||
| 93 | |||
| 94 | [[package]] | ||
| 95 | name = "six" | ||
| 96 | version = "1.17.0" | ||
| 97 | source = { registry = "https://pypi.org/simple" } | ||
| 98 | sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } | ||
| 99 | wheels = [ | ||
| 100 | { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, | ||
| 101 | ] | ||
| 102 | |||
| 103 | [[package]] | ||
| 104 | name = "spinners" | ||
| 105 | version = "0.0.24" | ||
| 106 | source = { registry = "https://pypi.org/simple" } | ||
| 107 | sdist = { url = "https://files.pythonhosted.org/packages/d3/91/bb331f0a43e04d950a710f402a0986a54147a35818df0e1658551c8d12e1/spinners-0.0.24.tar.gz", hash = "sha256:1eb6aeb4781d72ab42ed8a01dcf20f3002bf50740d7154d12fb8c9769bf9e27f", size = 5308, upload-time = "2020-02-19T21:42:32.326Z" } | ||
| 108 | wheels = [ | ||
| 109 | { url = "https://files.pythonhosted.org/packages/9f/8e/3310207a68118000ca27ac878b8386123628b335ecb3d4bec4743357f0d1/spinners-0.0.24-py3-none-any.whl", hash = "sha256:2fa30d0b72c9650ad12bbe031c9943b8d441e41b4f5602b0ec977a19f3290e98", size = 5499, upload-time = "2020-02-19T21:42:30.876Z" }, | ||
| 110 | ] | ||
| 111 | |||
| 112 | [[package]] | ||
| 113 | name = "termcolor" | ||
| 114 | version = "3.1.0" | ||
| 115 | source = { registry = "https://pypi.org/simple" } | ||
| 116 | sdist = { url = "https://files.pythonhosted.org/packages/ca/6c/3d75c196ac07ac8749600b60b03f4f6094d54e132c4d94ebac6ee0e0add0/termcolor-3.1.0.tar.gz", hash = "sha256:6a6dd7fbee581909eeec6a756cff1d7f7c376063b14e4a298dc4980309e55970", size = 14324, upload-time = "2025-04-30T11:37:53.791Z" } | ||
| 117 | wheels = [ | ||
| 118 | { url = "https://files.pythonhosted.org/packages/4f/bd/de8d508070629b6d84a30d01d57e4a65c69aa7f5abe7560b8fad3b50ea59/termcolor-3.1.0-py3-none-any.whl", hash = "sha256:591dd26b5c2ce03b9e43f391264626557873ce1d379019786f99b0c2bee140aa", size = 7684, upload-time = "2025-04-30T11:37:52.382Z" }, | ||
| 119 | ] | ||
| 120 | |||
| 121 | [[package]] | ||
| 122 | name = "tqdm" | ||
| 123 | version = "4.67.1" | ||
| 124 | source = { registry = "https://pypi.org/simple" } | ||
| 125 | dependencies = [ | ||
| 126 | { name = "colorama", marker = "sys_platform == 'win32'" }, | ||
| 127 | ] | ||
| 128 | sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } | ||
| 129 | wheels = [ | ||
| 130 | { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, | ||
| 131 | ] | ||
| 132 | |||
| 133 | [[package]] | ||
| 134 | name = "unshare" | ||
| 135 | version = "0.22" | ||
| 136 | source = { registry = "https://pypi.org/simple" } | ||
| 137 | sdist = { url = "https://files.pythonhosted.org/packages/15/85/2ba218129c95b894efe87506489b525f859c40f6e21cb0521ff3cec754f4/unshare-0.22.tar.gz", hash = "sha256:d521d72cca6e876f22cbd5ff5eb51f1beef75e8f9c53b599b55fa05fba1dd3a6", size = 2041, upload-time = "2019-10-17T12:58:31.498Z" } | ||
| 138 | |||
| 139 | [[package]] | ||
| 140 | name = "xdg" | ||
| 141 | version = "6.0.0" | ||
| 142 | source = { registry = "https://pypi.org/simple" } | ||
| 143 | sdist = { url = "https://files.pythonhosted.org/packages/2a/b9/0e6e6f19fb75cf5e1758f4f33c1256738f718966700cffc0fde2f966218b/xdg-6.0.0.tar.gz", hash = "sha256:24278094f2d45e846d1eb28a2ebb92d7b67fc0cab5249ee3ce88c95f649a1c92", size = 3453, upload-time = "2023-02-27T19:27:44.309Z" } | ||
| 144 | wheels = [ | ||
| 145 | { url = "https://files.pythonhosted.org/packages/dd/54/3516c1cf349060fc3578686d271eba242f10ec00b4530c2985af9faac49b/xdg-6.0.0-py3-none-any.whl", hash = "sha256:df3510755b4395157fc04fc3b02467c777f3b3ca383257397f09ab0d4c16f936", size = 3855, upload-time = "2023-02-27T19:27:42.151Z" }, | ||
| 146 | ] | ||
diff --git a/modules/i18n.nix b/modules/i18n.nix deleted file mode 100644 index f84e8b64..00000000 --- a/modules/i18n.nix +++ /dev/null | |||
| @@ -1,156 +0,0 @@ | |||
| 1 | { | ||
| 2 | config, | ||
| 3 | lib, | ||
| 4 | pkgs, | ||
| 5 | ... | ||
| 6 | }: | ||
| 7 | let | ||
| 8 | aggregatedLocales = | ||
| 9 | (builtins.map | ||
| 10 | (l: (lib.replaceStrings [ "utf8" "utf-8" "UTF8" ] [ "UTF-8" "UTF-8" "UTF-8" ] l) + "/UTF-8") | ||
| 11 | ( | ||
| 12 | [ config.i18n.defaultLocale ] | ||
| 13 | ++ (lib.optionals (builtins.isList config.i18n.extraLocales) config.i18n.extraLocales) | ||
| 14 | ++ (lib.attrValues (lib.filterAttrs (n: _v: lib.hasPrefix "LC_" n) config.i18n.extraLocaleSettings)) | ||
| 15 | ) | ||
| 16 | ) | ||
| 17 | ++ (lib.optional (builtins.isString config.i18n.extraLocales) config.i18n.extraLocales); | ||
| 18 | in | ||
| 19 | { | ||
| 20 | disabledModules = [ "config/i18n.nix" ]; | ||
| 21 | |||
| 22 | ###### interface | ||
| 23 | |||
| 24 | options = { | ||
| 25 | |||
| 26 | i18n = { | ||
| 27 | glibcLocales = lib.mkOption { | ||
| 28 | type = lib.types.path; | ||
| 29 | default = pkgs.glibcLocales.override { | ||
| 30 | allLocales = lib.any (x: x == "all") config.i18n.supportedLocales; | ||
| 31 | locales = config.i18n.supportedLocales; | ||
| 32 | }; | ||
| 33 | defaultText = lib.literalExpression '' | ||
| 34 | pkgs.glibcLocales.override { | ||
| 35 | allLocales = lib.any (x: x == "all") config.i18n.supportedLocales; | ||
| 36 | locales = config.i18n.supportedLocales; | ||
| 37 | } | ||
| 38 | ''; | ||
| 39 | example = lib.literalExpression "pkgs.glibcLocales"; | ||
| 40 | description = '' | ||
| 41 | Customized pkg.glibcLocales package. | ||
| 42 | |||
| 43 | Changing this option can disable handling of i18n.defaultLocale | ||
| 44 | and supportedLocale. | ||
| 45 | ''; | ||
| 46 | }; | ||
| 47 | |||
| 48 | defaultLocale = lib.mkOption { | ||
| 49 | type = lib.types.str; | ||
| 50 | default = "en_US.UTF-8"; | ||
| 51 | example = "nl_NL.UTF-8"; | ||
| 52 | description = '' | ||
| 53 | The default locale. It determines the language for program | ||
| 54 | messages, the format for dates and times, sort order, and so on. | ||
| 55 | It also determines the character set, such as UTF-8. | ||
| 56 | ''; | ||
| 57 | }; | ||
| 58 | |||
| 59 | extraLocales = lib.mkOption { | ||
| 60 | type = lib.types.either (lib.types.listOf lib.types.str) (lib.types.enum [ "all" ]); | ||
| 61 | default = [ ]; | ||
| 62 | example = [ "nl_NL.UTF-8" ]; | ||
| 63 | description = '' | ||
| 64 | Additional locales that the system should support, besides the ones | ||
| 65 | configured with {option}`i18n.defaultLocale` and | ||
| 66 | {option}`i18n.extraLocaleSettings`. | ||
| 67 | Set this to `"all"` to install all available locales. | ||
| 68 | ''; | ||
| 69 | }; | ||
| 70 | |||
| 71 | extraLocaleSettings = lib.mkOption { | ||
| 72 | type = lib.types.attrsOf lib.types.str; | ||
| 73 | default = { }; | ||
| 74 | example = { | ||
| 75 | LC_MESSAGES = "en_US.UTF-8"; | ||
| 76 | LC_TIME = "de_DE.UTF-8"; | ||
| 77 | }; | ||
| 78 | description = '' | ||
| 79 | A set of additional system-wide locale settings other than | ||
| 80 | `LANG` which can be configured with | ||
| 81 | {option}`i18n.defaultLocale`. | ||
| 82 | ''; | ||
| 83 | }; | ||
| 84 | |||
| 85 | supportedLocales = lib.mkOption { | ||
| 86 | type = lib.types.listOf lib.types.str; | ||
| 87 | visible = false; | ||
| 88 | default = lib.unique ( | ||
| 89 | [ | ||
| 90 | "C.UTF-8/UTF-8" | ||
| 91 | "en_US.UTF-8/UTF-8" | ||
| 92 | ] | ||
| 93 | ++ aggregatedLocales | ||
| 94 | ); | ||
| 95 | example = [ | ||
| 96 | "en_US.UTF-8/UTF-8" | ||
| 97 | "nl_NL.UTF-8/UTF-8" | ||
| 98 | "nl_NL/ISO-8859-1" | ||
| 99 | ]; | ||
| 100 | description = '' | ||
| 101 | List of locales that the system should support. The value | ||
| 102 | `"all"` means that all locales supported by | ||
| 103 | Glibc will be installed. A full list of supported locales | ||
| 104 | can be found at <https://sourceware.org/git/?p=glibc.git;a=blob;f=localedata/SUPPORTED>. | ||
| 105 | ''; | ||
| 106 | }; | ||
| 107 | |||
| 108 | }; | ||
| 109 | |||
| 110 | }; | ||
| 111 | |||
| 112 | ###### implementation | ||
| 113 | |||
| 114 | config = { | ||
| 115 | warnings = | ||
| 116 | lib.optional | ||
| 117 | ( | ||
| 118 | !( | ||
| 119 | (lib.subtractLists config.i18n.supportedLocales aggregatedLocales) == [ ] | ||
| 120 | || lib.any (x: x == "all") config.i18n.supportedLocales | ||
| 121 | ) | ||
| 122 | ) | ||
| 123 | '' | ||
| 124 | `i18n.supportedLocales` is deprecated in favor of `i18n.extraLocales`, | ||
| 125 | and it seems you are using `i18n.supportedLocales` and forgot to | ||
| 126 | include some locales specified in `i18n.defaultLocale`, | ||
| 127 | `i18n.extraLocales` or `i18n.extraLocaleSettings`. | ||
| 128 | |||
| 129 | If you're trying to install additional locales not specified in | ||
| 130 | `i18n.defaultLocale` or `i18n.extraLocaleSettings`, consider adding | ||
| 131 | only those locales to `i18n.extraLocales`. | ||
| 132 | ''; | ||
| 133 | |||
| 134 | environment.systemPackages = | ||
| 135 | # We increase the priority a little, so that plain glibc in systemPackages can't win. | ||
| 136 | lib.optional (config.i18n.supportedLocales != [ ]) (lib.setPrio (-1) config.i18n.glibcLocales); | ||
| 137 | |||
| 138 | environment.sessionVariables = { | ||
| 139 | LANG = config.i18n.defaultLocale; | ||
| 140 | LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; | ||
| 141 | } // config.i18n.extraLocaleSettings; | ||
| 142 | |||
| 143 | systemd.globalEnvironment = lib.mkIf (config.i18n.supportedLocales != [ ]) { | ||
| 144 | LOCALE_ARCHIVE = "${config.i18n.glibcLocales}/lib/locale/locale-archive"; | ||
| 145 | }; | ||
| 146 | |||
| 147 | # ‘/etc/locale.conf’ is used by systemd. | ||
| 148 | environment.etc."locale.conf".source = pkgs.writeText "locale.conf" '' | ||
| 149 | LANG=${config.i18n.defaultLocale} | ||
| 150 | ${lib.concatStringsSep "\n" ( | ||
| 151 | lib.mapAttrsToList (n: v: "${n}=${v}") config.i18n.extraLocaleSettings | ||
| 152 | )} | ||
| 153 | ''; | ||
| 154 | |||
| 155 | }; | ||
| 156 | } | ||
diff --git a/modules/impermanence-timezone.nix b/modules/impermanence-timezone.nix new file mode 100644 index 00000000..a1edbfa5 --- /dev/null +++ b/modules/impermanence-timezone.nix | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | { config, lib, utils, pkgs, ... }: | ||
| 2 | |||
| 3 | { | ||
| 4 | options = { | ||
| 5 | environment.persistence = lib.mkOption { | ||
| 6 | type = lib.types.attrsOf (lib.types.submodule { | ||
| 7 | options = { | ||
| 8 | timezone = lib.mkEnableOption "storing system timezone"; | ||
| 9 | }; | ||
| 10 | }); | ||
| 11 | }; | ||
| 12 | }; | ||
| 13 | |||
| 14 | config = { | ||
| 15 | systemd = lib.mkMerge (lib.mapAttrsToList (name: cfg: lib.mkIf cfg.timezone { | ||
| 16 | services = { | ||
| 17 | "timezone@${utils.escapeSystemdPath name}" = { | ||
| 18 | wantedBy = [ "multi-user.target" ]; | ||
| 19 | serviceConfig = { | ||
| 20 | Type = "oneshot"; | ||
| 21 | RemainAfterExit = true; | ||
| 22 | ExecStart = "${pkgs.coreutils}/bin/cp -vP ${utils.escapeSystemdExecArg "${name}/etc/localtime"} /etc/localtime"; | ||
| 23 | ExecStop = "${pkgs.coreutils}/bin/cp -vP /etc/localtime ${utils.escapeSystemdExecArg "${name}/etc/localtime"}"; | ||
| 24 | }; | ||
| 25 | }; | ||
| 26 | "etc-localtime@${utils.escapeSystemdPath name}" = { | ||
| 27 | serviceConfig = { | ||
| 28 | Type = "oneshot"; | ||
| 29 | ExecStart = "${pkgs.coreutils}/bin/cp -vP /etc/localtime ${utils.escapeSystemdExecArg "${name}/etc/localtime"}"; | ||
| 30 | }; | ||
| 31 | }; | ||
| 32 | }; | ||
| 33 | paths."etc-localtime@${utils.escapeSystemdPath name}" = { | ||
| 34 | wantedBy = [ "timezone@${utils.escapeSystemdPath name}.service" ]; | ||
| 35 | after = [ "timezone@${utils.escapeSystemdPath name}.service" ]; | ||
| 36 | |||
| 37 | pathConfig.PathChanged = "/etc/localtime"; | ||
| 38 | }; | ||
| 39 | }) config.environment.persistence); | ||
| 40 | }; | ||
| 41 | } | ||
diff --git a/modules/impermanence.nix b/modules/impermanence.nix new file mode 100644 index 00000000..621576a3 --- /dev/null +++ b/modules/impermanence.nix | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | { flakeInputs, ... }: | ||
| 2 | { | ||
| 3 | imports = [ | ||
| 4 | flakeInputs.impermanence.nixosModules.impermanence | ||
| 5 | ]; | ||
| 6 | } | ||
diff --git a/modules/niri-autoselect-portal.nix b/modules/niri-autoselect-portal.nix new file mode 100644 index 00000000..df21aaae --- /dev/null +++ b/modules/niri-autoselect-portal.nix | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | { flakeInputs, ... }: | ||
| 2 | { | ||
| 3 | imports = [ | ||
| 4 | flakeInputs.niri-autoselect-portal.nixosModules.default | ||
| 5 | ]; | ||
| 6 | } | ||
diff --git a/modules/nix-access-tokens/nix.conf b/modules/nix-access-tokens/nix.conf index f0b394ef..80d5641c 100644 --- a/modules/nix-access-tokens/nix.conf +++ b/modules/nix-access-tokens/nix.conf | |||
| @@ -1,10 +1,6 @@ | |||
| 1 | { | 1 | { |
| 2 | "data": "ENC[AES256_GCM,data:/cdBpvCAFpgm0YWhy1WYlA09KlU6PzVfBYVLBD0boqGqvP+8wuyDzj5KWbcKsdGhoiklODiKR0ODXNU+fA35y862PFXvSb4xVyfbdKRndYdIA4W6vyobtoC9h7B1yR9pkq9L+1tqlU30Dgy2Gndg9rWHlIo+1lO/1A==,iv:B1Px2+cxCaopHZThkEG5saOib+PNvurPIS6aeAv2uPo=,tag:K3JqRaX3/iIqD3c//YdqSQ==,type:str]", | 2 | "data": "ENC[AES256_GCM,data:g5O8yjSfa+MbwDKa6NAfC2akwYQvLlGH9VAkBY4Sdjgi0IvzVocVSZwrHEkTbE4FyCdub9NVjhmoRiiZe8pW6R5sKHJxNko7yWvCUcUE/50bm/1icd97ZDLmIS5VcNprIukDN5DRswUjm9F+mxkERaZQypkpCE7DCQ==,iv:29HBGJTTtrugnF0lgPLgoDn1zr25aU2wE9IFrORBl8c=,tag:2vL4Uoa5zpgo510GGFEepA==,type:str]", |
| 3 | "sops": { | 3 | "sops": { |
| 4 | "kms": null, | ||
| 5 | "gcp_kms": null, | ||
| 6 | "azure_kv": null, | ||
| 7 | "hc_vault": null, | ||
| 8 | "age": [ | 4 | "age": [ |
| 9 | { | 5 | { |
| 10 | "recipient": "age1rmmhetcmllq0ahl5qznlr0eya2zdxwl9h6y5wnl97d2wtyx5t99sm2u866", | 6 | "recipient": "age1rmmhetcmllq0ahl5qznlr0eya2zdxwl9h6y5wnl97d2wtyx5t99sm2u866", |
| @@ -23,10 +19,9 @@ | |||
| 23 | "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2ejRHcGttNUxYZnFzTU5J\nMTFvY3daQ1VMM2xxYTgvLzZwT1owazVNenhzCktaWFF6K2s5UjI2b20rSHFNSS9E\nMVlJSmZhQm15eUs3U0hGTGpSRndmSDgKLS0tIDVrcjl4eDhwak1pRithbnRWWEZy\nVE9EOEpKdEJoRTFrTXpQVDc1cmsrU1kK/goTdUmpZPeMRbY1QzLXAa6Qpg4YYYYo\n3v3GK1bzdey8szfgIr1dHTtQEzqE2WX1swzZizDXj/RiUWx01Ky3GA==\n-----END AGE ENCRYPTED FILE-----\n" | 19 | "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2ejRHcGttNUxYZnFzTU5J\nMTFvY3daQ1VMM2xxYTgvLzZwT1owazVNenhzCktaWFF6K2s5UjI2b20rSHFNSS9E\nMVlJSmZhQm15eUs3U0hGTGpSRndmSDgKLS0tIDVrcjl4eDhwak1pRithbnRWWEZy\nVE9EOEpKdEJoRTFrTXpQVDc1cmsrU1kK/goTdUmpZPeMRbY1QzLXAa6Qpg4YYYYo\n3v3GK1bzdey8szfgIr1dHTtQEzqE2WX1swzZizDXj/RiUWx01Ky3GA==\n-----END AGE ENCRYPTED FILE-----\n" |
| 24 | } | 20 | } |
| 25 | ], | 21 | ], |
| 26 | "lastmodified": "2025-01-25T19:58:58Z", | 22 | "lastmodified": "2026-01-07T09:18:20Z", |
| 27 | "mac": "ENC[AES256_GCM,data:Oza4XgnTX3vly89nGluLbEytk1dUYAiOhIYewQyDLLLSSlUIpXmWhV+X0HUQ9AX5kUrEhNbVzRdvUG/9YwoWjTJfvd7tw41IYeTqgykMNXJUfGssoutXfeij9YR+t5aJaRhlTkIWcBhUjXSUNyJCl6Z3XmzWstTPZXEU9VmAvuE=,iv:LqVwIiit+WqI5NWSboexWsmPzg7e63nWJYsNFEK1Uog=,tag:ClR6oI62WXEfIYYAY6vL0A==,type:str]", | 23 | "mac": "ENC[AES256_GCM,data:9vEWlIE1gkm60HU6fMxJN8EkKqJm5H2mVk2P2VL7xLtVraP3wz0hJxDnIpfoAaVkbunjtR100FKjohXFIWTUeOsZgo093PSbmfgFi4Od04jNZmljE1oy7rMtV0eGFAtopPz2TsDScMa0Roqv2i6r1Pi2L3C3uQPR9/Jf4ORteD8=,iv:j/qjKBWz9dNWkvC5c69t4WrzO5TlqG4jgSmV+OP7Les=,tag:XtWavd8A4qqXlq1i7VoapQ==,type:str]", |
| 28 | "pgp": null, | ||
| 29 | "unencrypted_suffix": "_unencrypted", | 24 | "unencrypted_suffix": "_unencrypted", |
| 30 | "version": "3.9.3" | 25 | "version": "3.11.0" |
| 31 | } | 26 | } |
| 32 | } \ No newline at end of file | 27 | } |
diff --git a/modules/postsrsd.nix b/modules/postsrsd.nix index 205e669d..bc941e3e 100644 --- a/modules/postsrsd.nix +++ b/modules/postsrsd.nix | |||
| @@ -101,6 +101,12 @@ in | |||
| 101 | type = lib.types.lines; | 101 | type = lib.types.lines; |
| 102 | default = ""; | 102 | default = ""; |
| 103 | }; | 103 | }; |
| 104 | |||
| 105 | configurePostfix = lib.mkOption { | ||
| 106 | type = lib.types.bool; | ||
| 107 | default = false; | ||
| 108 | description = "noop"; | ||
| 109 | }; | ||
| 104 | }; | 110 | }; |
| 105 | }; | 111 | }; |
| 106 | 112 | ||
diff --git a/modules/prometheus.nix b/modules/prometheus.nix new file mode 100644 index 00000000..cda3a8cf --- /dev/null +++ b/modules/prometheus.nix | |||
| @@ -0,0 +1,2048 @@ | |||
| 1 | { | ||
| 2 | config, | ||
| 3 | pkgs, | ||
| 4 | lib, | ||
| 5 | ... | ||
| 6 | }: | ||
| 7 | |||
| 8 | with lib; | ||
| 9 | |||
| 10 | let | ||
| 11 | yaml = pkgs.formats.yaml { }; | ||
| 12 | cfg = config.services.prometheus; | ||
| 13 | checkConfigEnabled = | ||
| 14 | (lib.isBool cfg.checkConfig && cfg.checkConfig) || cfg.checkConfig == "syntax-only"; | ||
| 15 | |||
| 16 | workingDir = "/var/lib/" + cfg.stateDir; | ||
| 17 | |||
| 18 | triggerReload = pkgs.writeShellScriptBin "trigger-reload-prometheus" '' | ||
| 19 | PATH="${makeBinPath (with pkgs; [ systemd ])}" | ||
| 20 | if systemctl -q is-active prometheus.service; then | ||
| 21 | systemctl reload prometheus.service | ||
| 22 | fi | ||
| 23 | ''; | ||
| 24 | |||
| 25 | reload = pkgs.writeShellScriptBin "reload-prometheus" '' | ||
| 26 | PATH="${ | ||
| 27 | makeBinPath ( | ||
| 28 | with pkgs; | ||
| 29 | [ | ||
| 30 | systemd | ||
| 31 | coreutils | ||
| 32 | gnugrep | ||
| 33 | ] | ||
| 34 | ) | ||
| 35 | }" | ||
| 36 | cursor=$(journalctl --show-cursor -n0 | grep -oP "cursor: \K.*") | ||
| 37 | kill -HUP $MAINPID | ||
| 38 | journalctl -u prometheus.service --after-cursor="$cursor" -f \ | ||
| 39 | | grep -m 1 "Completed loading of configuration file" > /dev/null | ||
| 40 | ''; | ||
| 41 | |||
| 42 | # a wrapper that verifies that the configuration is valid | ||
| 43 | promtoolCheck = | ||
| 44 | what: name: file: | ||
| 45 | if checkConfigEnabled then | ||
| 46 | pkgs.runCommand "${name}-${replaceStrings [ " " ] [ "" ] what}-checked" | ||
| 47 | { | ||
| 48 | preferLocalBuild = true; | ||
| 49 | nativeBuildInputs = [ cfg.package.cli ]; | ||
| 50 | } | ||
| 51 | '' | ||
| 52 | ln -s ${file} $out | ||
| 53 | promtool ${what} $out | ||
| 54 | '' | ||
| 55 | else | ||
| 56 | file; | ||
| 57 | |||
| 58 | generatedPrometheusYml = yaml.generate "prometheus.yml" promConfig; | ||
| 59 | |||
| 60 | # This becomes the main config file for Prometheus | ||
| 61 | promConfig = lib.recursiveUpdate { | ||
| 62 | global = filterValidPrometheus cfg.globalConfig; | ||
| 63 | scrape_configs = filterValidPrometheus cfg.scrapeConfigs; | ||
| 64 | remote_write = filterValidPrometheus cfg.remoteWrite; | ||
| 65 | remote_read = filterValidPrometheus cfg.remoteRead; | ||
| 66 | rule_files = optionals (!(cfg.enableAgentMode)) ( | ||
| 67 | map (promtoolCheck "check rules" "rules") ( | ||
| 68 | cfg.ruleFiles | ||
| 69 | ++ optionals (builtins.length cfg.rules > 0) [ | ||
| 70 | (pkgs.writeText "prometheus.rules" (concatStringsSep "\n" cfg.rules)) | ||
| 71 | ] | ||
| 72 | ) | ||
| 73 | ); | ||
| 74 | alerting = { | ||
| 75 | inherit (cfg) alertmanagers; | ||
| 76 | }; | ||
| 77 | } cfg.extraConfig; | ||
| 78 | |||
| 79 | prometheusYml = | ||
| 80 | let | ||
| 81 | yml = | ||
| 82 | if cfg.configText != null then | ||
| 83 | pkgs.writeText "prometheus.yml" cfg.configText | ||
| 84 | else | ||
| 85 | generatedPrometheusYml; | ||
| 86 | in | ||
| 87 | promtoolCheck "check config ${ | ||
| 88 | lib.optionalString (cfg.checkConfig == "syntax-only") "--syntax-only" | ||
| 89 | }" "prometheus.yml" yml; | ||
| 90 | |||
| 91 | cmdlineArgs = | ||
| 92 | cfg.extraFlags | ||
| 93 | ++ [ | ||
| 94 | "--config.file=${if cfg.enableReload then "/etc/prometheus/prometheus.yaml" else prometheusYml}" | ||
| 95 | "--web.listen-address=${cfg.listenAddress}:${toString cfg.port}" | ||
| 96 | ] | ||
| 97 | ++ ( | ||
| 98 | if (cfg.enableAgentMode) then | ||
| 99 | [ | ||
| 100 | "--agent" | ||
| 101 | ] | ||
| 102 | else | ||
| 103 | [ | ||
| 104 | "--alertmanager.notification-queue-capacity=${toString cfg.alertmanagerNotificationQueueCapacity}" | ||
| 105 | "--storage.tsdb.path=${workingDir}/data/" | ||
| 106 | ] | ||
| 107 | ) | ||
| 108 | ++ optional (cfg.webExternalUrl != null) "--web.external-url=${cfg.webExternalUrl}" | ||
| 109 | ++ optional (cfg.retentionTime != null) "--storage.tsdb.retention.time=${cfg.retentionTime}" | ||
| 110 | ++ optional (cfg.webConfigFile != null) "--web.config.file=${cfg.webConfigFile}"; | ||
| 111 | |||
| 112 | filterValidPrometheus = filterAttrsListRecursive (n: v: !(n == "_module" || v == null)); | ||
| 113 | filterAttrsListRecursive = | ||
| 114 | pred: x: | ||
| 115 | if isAttrs x then | ||
| 116 | listToAttrs ( | ||
| 117 | concatMap ( | ||
| 118 | name: | ||
| 119 | let | ||
| 120 | v = x.${name}; | ||
| 121 | in | ||
| 122 | if pred name v then | ||
| 123 | [ | ||
| 124 | (nameValuePair name (filterAttrsListRecursive pred v)) | ||
| 125 | ] | ||
| 126 | else | ||
| 127 | [ ] | ||
| 128 | ) (attrNames x) | ||
| 129 | ) | ||
| 130 | else if isList x then | ||
| 131 | map (filterAttrsListRecursive pred) x | ||
| 132 | else | ||
| 133 | x; | ||
| 134 | |||
| 135 | # | ||
| 136 | # Config types: helper functions | ||
| 137 | # | ||
| 138 | |||
| 139 | mkDefOpt = | ||
| 140 | type: defaultStr: description: | ||
| 141 | mkOpt type ( | ||
| 142 | description | ||
| 143 | + '' | ||
| 144 | |||
| 145 | Defaults to ````${defaultStr}```` in prometheus | ||
| 146 | when set to `null`. | ||
| 147 | '' | ||
| 148 | ); | ||
| 149 | |||
| 150 | mkOpt = | ||
| 151 | type: description: | ||
| 152 | mkOption { | ||
| 153 | type = types.nullOr type; | ||
| 154 | default = null; | ||
| 155 | description = description; | ||
| 156 | }; | ||
| 157 | |||
| 158 | mkSdConfigModule = | ||
| 159 | extraOptions: | ||
| 160 | types.submodule { | ||
| 161 | options = { | ||
| 162 | basic_auth = mkOpt promTypes.basic_auth '' | ||
| 163 | Optional HTTP basic authentication information. | ||
| 164 | ''; | ||
| 165 | |||
| 166 | authorization = | ||
| 167 | mkOpt | ||
| 168 | (types.submodule { | ||
| 169 | options = { | ||
| 170 | type = mkDefOpt types.str "Bearer" '' | ||
| 171 | Sets the authentication type. | ||
| 172 | ''; | ||
| 173 | |||
| 174 | credentials = mkOpt types.str '' | ||
| 175 | Sets the credentials. It is mutually exclusive with `credentials_file`. | ||
| 176 | ''; | ||
| 177 | |||
| 178 | credentials_file = mkOpt types.str '' | ||
| 179 | Sets the credentials to the credentials read from the configured file. | ||
| 180 | It is mutually exclusive with `credentials`. | ||
| 181 | ''; | ||
| 182 | }; | ||
| 183 | }) | ||
| 184 | '' | ||
| 185 | Optional `Authorization` header configuration. | ||
| 186 | ''; | ||
| 187 | |||
| 188 | oauth2 = mkOpt promtypes.oauth2 '' | ||
| 189 | Optional OAuth 2.0 configuration. | ||
| 190 | Cannot be used at the same time as basic_auth or authorization. | ||
| 191 | ''; | ||
| 192 | |||
| 193 | proxy_url = mkOpt types.str '' | ||
| 194 | Optional proxy URL. | ||
| 195 | ''; | ||
| 196 | |||
| 197 | follow_redirects = mkDefOpt types.bool "true" '' | ||
| 198 | Configure whether HTTP requests follow HTTP 3xx redirects. | ||
| 199 | ''; | ||
| 200 | |||
| 201 | tls_config = mkOpt promTypes.tls_config '' | ||
| 202 | TLS configuration. | ||
| 203 | ''; | ||
| 204 | } | ||
| 205 | // extraOptions; | ||
| 206 | }; | ||
| 207 | |||
| 208 | # | ||
| 209 | # Config types: general | ||
| 210 | # | ||
| 211 | |||
| 212 | promTypes.globalConfig = types.submodule { | ||
| 213 | options = { | ||
| 214 | scrape_interval = mkDefOpt types.str "1m" '' | ||
| 215 | How frequently to scrape targets by default. | ||
| 216 | ''; | ||
| 217 | |||
| 218 | scrape_timeout = mkDefOpt types.str "10s" '' | ||
| 219 | How long until a scrape request times out. | ||
| 220 | ''; | ||
| 221 | |||
| 222 | evaluation_interval = mkDefOpt types.str "1m" '' | ||
| 223 | How frequently to evaluate rules by default. | ||
| 224 | ''; | ||
| 225 | |||
| 226 | external_labels = mkOpt (types.attrsOf types.str) '' | ||
| 227 | The labels to add to any time series or alerts when | ||
| 228 | communicating with external systems (federation, remote | ||
| 229 | storage, Alertmanager). | ||
| 230 | ''; | ||
| 231 | |||
| 232 | query_log_file = mkOpt types.str '' | ||
| 233 | Path to the file prometheus should write its query log to. | ||
| 234 | ''; | ||
| 235 | }; | ||
| 236 | }; | ||
| 237 | |||
| 238 | promTypes.basic_auth = types.submodule { | ||
| 239 | options = { | ||
| 240 | username = mkOption { | ||
| 241 | type = types.str; | ||
| 242 | description = '' | ||
| 243 | HTTP username | ||
| 244 | ''; | ||
| 245 | }; | ||
| 246 | password = mkOpt types.str "HTTP password"; | ||
| 247 | password_file = mkOpt types.str "HTTP password file"; | ||
| 248 | }; | ||
| 249 | }; | ||
| 250 | |||
| 251 | promTypes.sigv4 = types.submodule { | ||
| 252 | options = { | ||
| 253 | region = mkOpt types.str '' | ||
| 254 | The AWS region. | ||
| 255 | ''; | ||
| 256 | access_key = mkOpt types.str '' | ||
| 257 | The Access Key ID. | ||
| 258 | ''; | ||
| 259 | secret_key = mkOpt types.str '' | ||
| 260 | The Secret Access Key. | ||
| 261 | ''; | ||
| 262 | profile = mkOpt types.str '' | ||
| 263 | The named AWS profile used to authenticate. | ||
| 264 | ''; | ||
| 265 | role_arn = mkOpt types.str '' | ||
| 266 | The AWS role ARN. | ||
| 267 | ''; | ||
| 268 | }; | ||
| 269 | }; | ||
| 270 | |||
| 271 | promTypes.tls_config = types.submodule { | ||
| 272 | options = { | ||
| 273 | ca_file = mkOpt types.str '' | ||
| 274 | CA certificate to validate API server certificate with. | ||
| 275 | ''; | ||
| 276 | |||
| 277 | cert_file = mkOpt types.str '' | ||
| 278 | Certificate file for client cert authentication to the server. | ||
| 279 | ''; | ||
| 280 | |||
| 281 | key_file = mkOpt types.str '' | ||
| 282 | Key file for client cert authentication to the server. | ||
| 283 | ''; | ||
| 284 | |||
| 285 | server_name = mkOpt types.str '' | ||
| 286 | ServerName extension to indicate the name of the server. | ||
| 287 | http://tools.ietf.org/html/rfc4366#section-3.1 | ||
| 288 | ''; | ||
| 289 | |||
| 290 | insecure_skip_verify = mkOpt types.bool '' | ||
| 291 | Disable validation of the server certificate. | ||
| 292 | ''; | ||
| 293 | }; | ||
| 294 | }; | ||
| 295 | |||
| 296 | promtypes.oauth2 = types.submodule { | ||
| 297 | options = { | ||
| 298 | client_id = mkOpt types.str '' | ||
| 299 | OAuth client ID. | ||
| 300 | ''; | ||
| 301 | |||
| 302 | client_secret = mkOpt types.str '' | ||
| 303 | OAuth client secret. | ||
| 304 | ''; | ||
| 305 | |||
| 306 | client_secret_file = mkOpt types.str '' | ||
| 307 | Read the client secret from a file. It is mutually exclusive with `client_secret`. | ||
| 308 | ''; | ||
| 309 | |||
| 310 | scopes = mkOpt (types.listOf types.str) '' | ||
| 311 | Scopes for the token request. | ||
| 312 | ''; | ||
| 313 | |||
| 314 | token_url = mkOpt types.str '' | ||
| 315 | The URL to fetch the token from. | ||
| 316 | ''; | ||
| 317 | |||
| 318 | endpoint_params = mkOpt (types.attrsOf types.str) '' | ||
| 319 | Optional parameters to append to the token URL. | ||
| 320 | ''; | ||
| 321 | }; | ||
| 322 | }; | ||
| 323 | |||
| 324 | # https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config | ||
| 325 | promTypes.scrape_config = types.submodule { | ||
| 326 | options = { | ||
| 327 | authorization = mkOption { | ||
| 328 | type = types.nullOr types.attrs; | ||
| 329 | default = null; | ||
| 330 | description = '' | ||
| 331 | Sets the `Authorization` header on every scrape request with the configured credentials. | ||
| 332 | ''; | ||
| 333 | }; | ||
| 334 | job_name = mkOption { | ||
| 335 | type = types.str; | ||
| 336 | description = '' | ||
| 337 | The job name assigned to scraped metrics by default. | ||
| 338 | ''; | ||
| 339 | }; | ||
| 340 | scrape_interval = mkOpt types.str '' | ||
| 341 | How frequently to scrape targets from this job. Defaults to the | ||
| 342 | globally configured default. | ||
| 343 | ''; | ||
| 344 | |||
| 345 | scrape_timeout = mkOpt types.str '' | ||
| 346 | Per-target timeout when scraping this job. Defaults to the | ||
| 347 | globally configured default. | ||
| 348 | ''; | ||
| 349 | |||
| 350 | scrape_protocols = mkOpt (types.listOf types.str) '' | ||
| 351 | The protocols to negotiate during a scrape with the client. | ||
| 352 | ''; | ||
| 353 | |||
| 354 | fallback_scrape_protocol = mkOpt types.str '' | ||
| 355 | Fallback protocol to use if a scrape returns blank, unparseable, or otherwise | ||
| 356 | invalid Content-Type. | ||
| 357 | ''; | ||
| 358 | |||
| 359 | metrics_path = mkDefOpt types.str "/metrics" '' | ||
| 360 | The HTTP resource path on which to fetch metrics from targets. | ||
| 361 | ''; | ||
| 362 | |||
| 363 | honor_labels = mkDefOpt types.bool "false" '' | ||
| 364 | Controls how Prometheus handles conflicts between labels | ||
| 365 | that are already present in scraped data and labels that | ||
| 366 | Prometheus would attach server-side ("job" and "instance" | ||
| 367 | labels, manually configured target labels, and labels | ||
| 368 | generated by service discovery implementations). | ||
| 369 | |||
| 370 | If honor_labels is set to "true", label conflicts are | ||
| 371 | resolved by keeping label values from the scraped data and | ||
| 372 | ignoring the conflicting server-side labels. | ||
| 373 | |||
| 374 | If honor_labels is set to "false", label conflicts are | ||
| 375 | resolved by renaming conflicting labels in the scraped data | ||
| 376 | to "exported_\<original-label\>" (for example | ||
| 377 | "exported_instance", "exported_job") and then attaching | ||
| 378 | server-side labels. This is useful for use cases such as | ||
| 379 | federation, where all labels specified in the target should | ||
| 380 | be preserved. | ||
| 381 | ''; | ||
| 382 | |||
| 383 | honor_timestamps = mkDefOpt types.bool "true" '' | ||
| 384 | honor_timestamps controls whether Prometheus respects the timestamps present | ||
| 385 | in scraped data. | ||
| 386 | |||
| 387 | If honor_timestamps is set to `true`, the timestamps of the metrics exposed | ||
| 388 | by the target will be used. | ||
| 389 | |||
| 390 | If honor_timestamps is set to `false`, the timestamps of the metrics exposed | ||
| 391 | by the target will be ignored. | ||
| 392 | ''; | ||
| 393 | |||
| 394 | scheme = | ||
| 395 | mkDefOpt | ||
| 396 | (types.enum [ | ||
| 397 | "http" | ||
| 398 | "https" | ||
| 399 | ]) | ||
| 400 | "http" | ||
| 401 | '' | ||
| 402 | The URL scheme with which to fetch metrics from targets. | ||
| 403 | ''; | ||
| 404 | |||
| 405 | params = mkOpt (types.attrsOf (types.listOf types.str)) '' | ||
| 406 | Optional HTTP URL parameters. | ||
| 407 | ''; | ||
| 408 | |||
| 409 | basic_auth = mkOpt promTypes.basic_auth '' | ||
| 410 | Sets the `Authorization` header on every scrape request with the | ||
| 411 | configured username and password. | ||
| 412 | password and password_file are mutually exclusive. | ||
| 413 | ''; | ||
| 414 | |||
| 415 | bearer_token = mkOpt types.str '' | ||
| 416 | Sets the `Authorization` header on every scrape request with | ||
| 417 | the configured bearer token. It is mutually exclusive with | ||
| 418 | {option}`bearer_token_file`. | ||
| 419 | ''; | ||
| 420 | |||
| 421 | bearer_token_file = mkOpt types.str '' | ||
| 422 | Sets the `Authorization` header on every scrape request with | ||
| 423 | the bearer token read from the configured file. It is mutually | ||
| 424 | exclusive with {option}`bearer_token`. | ||
| 425 | ''; | ||
| 426 | |||
| 427 | tls_config = mkOpt promTypes.tls_config '' | ||
| 428 | Configures the scrape request's TLS settings. | ||
| 429 | ''; | ||
| 430 | |||
| 431 | proxy_url = mkOpt types.str '' | ||
| 432 | Optional proxy URL. | ||
| 433 | ''; | ||
| 434 | |||
| 435 | azure_sd_configs = mkOpt (types.listOf promTypes.azure_sd_config) '' | ||
| 436 | List of Azure service discovery configurations. | ||
| 437 | ''; | ||
| 438 | |||
| 439 | consul_sd_configs = mkOpt (types.listOf promTypes.consul_sd_config) '' | ||
| 440 | List of Consul service discovery configurations. | ||
| 441 | ''; | ||
| 442 | |||
| 443 | digitalocean_sd_configs = mkOpt (types.listOf promTypes.digitalocean_sd_config) '' | ||
| 444 | List of DigitalOcean service discovery configurations. | ||
| 445 | ''; | ||
| 446 | |||
| 447 | docker_sd_configs = mkOpt (types.listOf promTypes.docker_sd_config) '' | ||
| 448 | List of Docker service discovery configurations. | ||
| 449 | ''; | ||
| 450 | |||
| 451 | dockerswarm_sd_configs = mkOpt (types.listOf promTypes.dockerswarm_sd_config) '' | ||
| 452 | List of Docker Swarm service discovery configurations. | ||
| 453 | ''; | ||
| 454 | |||
| 455 | dns_sd_configs = mkOpt (types.listOf promTypes.dns_sd_config) '' | ||
| 456 | List of DNS service discovery configurations. | ||
| 457 | ''; | ||
| 458 | |||
| 459 | ec2_sd_configs = mkOpt (types.listOf promTypes.ec2_sd_config) '' | ||
| 460 | List of EC2 service discovery configurations. | ||
| 461 | ''; | ||
| 462 | |||
| 463 | eureka_sd_configs = mkOpt (types.listOf promTypes.eureka_sd_config) '' | ||
| 464 | List of Eureka service discovery configurations. | ||
| 465 | ''; | ||
| 466 | |||
| 467 | file_sd_configs = mkOpt (types.listOf promTypes.file_sd_config) '' | ||
| 468 | List of file service discovery configurations. | ||
| 469 | ''; | ||
| 470 | |||
| 471 | gce_sd_configs = mkOpt (types.listOf promTypes.gce_sd_config) '' | ||
| 472 | List of Google Compute Engine service discovery configurations. | ||
| 473 | |||
| 474 | See [the relevant Prometheus configuration docs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config) | ||
| 475 | for more detail. | ||
| 476 | ''; | ||
| 477 | |||
| 478 | hetzner_sd_configs = mkOpt (types.listOf promTypes.hetzner_sd_config) '' | ||
| 479 | List of Hetzner service discovery configurations. | ||
| 480 | ''; | ||
| 481 | |||
| 482 | http_sd_configs = mkOpt (types.listOf promTypes.http_sd_config) '' | ||
| 483 | List of HTTP service discovery configurations. | ||
| 484 | ''; | ||
| 485 | |||
| 486 | kubernetes_sd_configs = mkOpt (types.listOf promTypes.kubernetes_sd_config) '' | ||
| 487 | List of Kubernetes service discovery configurations. | ||
| 488 | ''; | ||
| 489 | |||
| 490 | kuma_sd_configs = mkOpt (types.listOf promTypes.kuma_sd_config) '' | ||
| 491 | List of Kuma service discovery configurations. | ||
| 492 | ''; | ||
| 493 | |||
| 494 | lightsail_sd_configs = mkOpt (types.listOf promTypes.lightsail_sd_config) '' | ||
| 495 | List of Lightsail service discovery configurations. | ||
| 496 | ''; | ||
| 497 | |||
| 498 | linode_sd_configs = mkOpt (types.listOf promTypes.linode_sd_config) '' | ||
| 499 | List of Linode service discovery configurations. | ||
| 500 | ''; | ||
| 501 | |||
| 502 | marathon_sd_configs = mkOpt (types.listOf promTypes.marathon_sd_config) '' | ||
| 503 | List of Marathon service discovery configurations. | ||
| 504 | ''; | ||
| 505 | |||
| 506 | nerve_sd_configs = mkOpt (types.listOf promTypes.nerve_sd_config) '' | ||
| 507 | List of AirBnB's Nerve service discovery configurations. | ||
| 508 | ''; | ||
| 509 | |||
| 510 | openstack_sd_configs = mkOpt (types.listOf promTypes.openstack_sd_config) '' | ||
| 511 | List of OpenStack service discovery configurations. | ||
| 512 | ''; | ||
| 513 | |||
| 514 | puppetdb_sd_configs = mkOpt (types.listOf promTypes.puppetdb_sd_config) '' | ||
| 515 | List of PuppetDB service discovery configurations. | ||
| 516 | ''; | ||
| 517 | |||
| 518 | scaleway_sd_configs = mkOpt (types.listOf promTypes.scaleway_sd_config) '' | ||
| 519 | List of Scaleway service discovery configurations. | ||
| 520 | ''; | ||
| 521 | |||
| 522 | serverset_sd_configs = mkOpt (types.listOf promTypes.serverset_sd_config) '' | ||
| 523 | List of Zookeeper Serverset service discovery configurations. | ||
| 524 | ''; | ||
| 525 | |||
| 526 | triton_sd_configs = mkOpt (types.listOf promTypes.triton_sd_config) '' | ||
| 527 | List of Triton Serverset service discovery configurations. | ||
| 528 | ''; | ||
| 529 | |||
| 530 | uyuni_sd_configs = mkOpt (types.listOf promTypes.uyuni_sd_config) '' | ||
| 531 | List of Uyuni Serverset service discovery configurations. | ||
| 532 | ''; | ||
| 533 | |||
| 534 | static_configs = mkOpt (types.listOf promTypes.static_config) '' | ||
| 535 | List of labeled target groups for this job. | ||
| 536 | ''; | ||
| 537 | |||
| 538 | relabel_configs = mkOpt (types.listOf promTypes.relabel_config) '' | ||
| 539 | List of relabel configurations. | ||
| 540 | ''; | ||
| 541 | |||
| 542 | metric_relabel_configs = mkOpt (types.listOf promTypes.relabel_config) '' | ||
| 543 | List of metric relabel configurations. | ||
| 544 | ''; | ||
| 545 | |||
| 546 | body_size_limit = mkDefOpt types.str "0" '' | ||
| 547 | An uncompressed response body larger than this many bytes will cause the | ||
| 548 | scrape to fail. 0 means no limit. Example: 100MB. | ||
| 549 | This is an experimental feature, this behaviour could | ||
| 550 | change or be removed in the future. | ||
| 551 | ''; | ||
| 552 | |||
| 553 | sample_limit = mkDefOpt types.int "0" '' | ||
| 554 | Per-scrape limit on number of scraped samples that will be accepted. | ||
| 555 | If more than this number of samples are present after metric relabelling | ||
| 556 | the entire scrape will be treated as failed. 0 means no limit. | ||
| 557 | ''; | ||
| 558 | |||
| 559 | label_limit = mkDefOpt types.int "0" '' | ||
| 560 | Per-scrape limit on number of labels that will be accepted for a sample. If | ||
| 561 | more than this number of labels are present post metric-relabeling, the | ||
| 562 | entire scrape will be treated as failed. 0 means no limit. | ||
| 563 | ''; | ||
| 564 | |||
| 565 | label_name_length_limit = mkDefOpt types.int "0" '' | ||
| 566 | Per-scrape limit on length of labels name that will be accepted for a sample. | ||
| 567 | If a label name is longer than this number post metric-relabeling, the entire | ||
| 568 | scrape will be treated as failed. 0 means no limit. | ||
| 569 | ''; | ||
| 570 | |||
| 571 | label_value_length_limit = mkDefOpt types.int "0" '' | ||
| 572 | Per-scrape limit on length of labels value that will be accepted for a sample. | ||
| 573 | If a label value is longer than this number post metric-relabeling, the | ||
| 574 | entire scrape will be treated as failed. 0 means no limit. | ||
| 575 | ''; | ||
| 576 | |||
| 577 | target_limit = mkDefOpt types.int "0" '' | ||
| 578 | Per-scrape config limit on number of unique targets that will be | ||
| 579 | accepted. If more than this number of targets are present after target | ||
| 580 | relabeling, Prometheus will mark the targets as failed without scraping them. | ||
| 581 | 0 means no limit. This is an experimental feature, this behaviour could | ||
| 582 | change in the future. | ||
| 583 | ''; | ||
| 584 | }; | ||
| 585 | }; | ||
| 586 | |||
| 587 | # | ||
| 588 | # Config types: service discovery | ||
| 589 | # | ||
| 590 | |||
| 591 | # For this one, the docs actually define all types needed to use mkSdConfigModule, but a bunch | ||
| 592 | # of them are marked with 'currently not support by Azure' so we don't bother adding them in | ||
| 593 | # here. | ||
| 594 | promTypes.azure_sd_config = types.submodule { | ||
| 595 | options = { | ||
| 596 | environment = mkDefOpt types.str "AzurePublicCloud" '' | ||
| 597 | The Azure environment. | ||
| 598 | ''; | ||
| 599 | |||
| 600 | authentication_method = | ||
| 601 | mkDefOpt | ||
| 602 | (types.enum [ | ||
| 603 | "OAuth" | ||
| 604 | "ManagedIdentity" | ||
| 605 | ]) | ||
| 606 | "OAuth" | ||
| 607 | '' | ||
| 608 | The authentication method, either OAuth or ManagedIdentity. | ||
| 609 | See <https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview> | ||
| 610 | ''; | ||
| 611 | |||
| 612 | subscription_id = mkOption { | ||
| 613 | type = types.str; | ||
| 614 | description = '' | ||
| 615 | The subscription ID. | ||
| 616 | ''; | ||
| 617 | }; | ||
| 618 | |||
| 619 | tenant_id = mkOpt types.str '' | ||
| 620 | Optional tenant ID. Only required with authentication_method OAuth. | ||
| 621 | ''; | ||
| 622 | |||
| 623 | client_id = mkOpt types.str '' | ||
| 624 | Optional client ID. Only required with authentication_method OAuth. | ||
| 625 | ''; | ||
| 626 | |||
| 627 | client_secret = mkOpt types.str '' | ||
| 628 | Optional client secret. Only required with authentication_method OAuth. | ||
| 629 | ''; | ||
| 630 | |||
| 631 | refresh_interval = mkDefOpt types.str "300s" '' | ||
| 632 | Refresh interval to re-read the instance list. | ||
| 633 | ''; | ||
| 634 | |||
| 635 | port = mkDefOpt types.port "80" '' | ||
| 636 | The port to scrape metrics from. If using the public IP | ||
| 637 | address, this must instead be specified in the relabeling | ||
| 638 | rule. | ||
| 639 | ''; | ||
| 640 | |||
| 641 | proxy_url = mkOpt types.str '' | ||
| 642 | Optional proxy URL. | ||
| 643 | ''; | ||
| 644 | |||
| 645 | follow_redirects = mkDefOpt types.bool "true" '' | ||
| 646 | Configure whether HTTP requests follow HTTP 3xx redirects. | ||
| 647 | ''; | ||
| 648 | |||
| 649 | tls_config = mkOpt promTypes.tls_config '' | ||
| 650 | TLS configuration. | ||
| 651 | ''; | ||
| 652 | }; | ||
| 653 | }; | ||
| 654 | |||
| 655 | promTypes.consul_sd_config = mkSdConfigModule { | ||
| 656 | server = mkDefOpt types.str "localhost:8500" '' | ||
| 657 | Consul server to query. | ||
| 658 | ''; | ||
| 659 | |||
| 660 | token = mkOpt types.str "Consul token"; | ||
| 661 | |||
| 662 | datacenter = mkOpt types.str "Consul datacenter"; | ||
| 663 | |||
| 664 | scheme = mkDefOpt types.str "http" "Consul scheme"; | ||
| 665 | |||
| 666 | username = mkOpt types.str "Consul username"; | ||
| 667 | |||
| 668 | password = mkOpt types.str "Consul password"; | ||
| 669 | |||
| 670 | tls_config = mkOpt promTypes.tls_config '' | ||
| 671 | Configures the Consul request's TLS settings. | ||
| 672 | ''; | ||
| 673 | |||
| 674 | services = mkOpt (types.listOf types.str) '' | ||
| 675 | A list of services for which targets are retrieved. | ||
| 676 | ''; | ||
| 677 | |||
| 678 | tags = mkOpt (types.listOf types.str) '' | ||
| 679 | An optional list of tags used to filter nodes for a given | ||
| 680 | service. Services must contain all tags in the list. | ||
| 681 | ''; | ||
| 682 | |||
| 683 | node_meta = mkOpt (types.attrsOf types.str) '' | ||
| 684 | Node metadata used to filter nodes for a given service. | ||
| 685 | ''; | ||
| 686 | |||
| 687 | tag_separator = mkDefOpt types.str "," '' | ||
| 688 | The string by which Consul tags are joined into the tag label. | ||
| 689 | ''; | ||
| 690 | |||
| 691 | allow_stale = mkOpt types.bool '' | ||
| 692 | Allow stale Consul results | ||
| 693 | (see <https://www.consul.io/api/index.html#consistency-modes>). | ||
| 694 | |||
| 695 | Will reduce load on Consul. | ||
| 696 | ''; | ||
| 697 | |||
| 698 | refresh_interval = mkDefOpt types.str "30s" '' | ||
| 699 | The time after which the provided names are refreshed. | ||
| 700 | |||
| 701 | On large setup it might be a good idea to increase this value | ||
| 702 | because the catalog will change all the time. | ||
| 703 | ''; | ||
| 704 | }; | ||
| 705 | |||
| 706 | promTypes.digitalocean_sd_config = mkSdConfigModule { | ||
| 707 | port = mkDefOpt types.port "80" '' | ||
| 708 | The port to scrape metrics from. | ||
| 709 | ''; | ||
| 710 | |||
| 711 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 712 | The time after which the droplets are refreshed. | ||
| 713 | ''; | ||
| 714 | }; | ||
| 715 | |||
| 716 | mkDockerSdConfigModule = | ||
| 717 | extraOptions: | ||
| 718 | mkSdConfigModule ( | ||
| 719 | { | ||
| 720 | host = mkOption { | ||
| 721 | type = types.str; | ||
| 722 | description = '' | ||
| 723 | Address of the Docker daemon. | ||
| 724 | ''; | ||
| 725 | }; | ||
| 726 | |||
| 727 | port = mkDefOpt types.port "80" '' | ||
| 728 | The port to scrape metrics from, when `role` is nodes, and for discovered | ||
| 729 | tasks and services that don't have published ports. | ||
| 730 | ''; | ||
| 731 | |||
| 732 | filters = | ||
| 733 | mkOpt | ||
| 734 | (types.listOf ( | ||
| 735 | types.submodule { | ||
| 736 | options = { | ||
| 737 | name = mkOption { | ||
| 738 | type = types.str; | ||
| 739 | description = '' | ||
| 740 | Name of the filter. The available filters are listed in the upstream documentation: | ||
| 741 | Services: <https://docs.docker.com/engine/api/v1.40/#operation/ServiceList> | ||
| 742 | Tasks: <https://docs.docker.com/engine/api/v1.40/#operation/TaskList> | ||
| 743 | Nodes: <https://docs.docker.com/engine/api/v1.40/#operation/NodeList> | ||
| 744 | ''; | ||
| 745 | }; | ||
| 746 | values = mkOption { | ||
| 747 | type = types.str; | ||
| 748 | description = '' | ||
| 749 | Value for the filter. | ||
| 750 | ''; | ||
| 751 | }; | ||
| 752 | }; | ||
| 753 | } | ||
| 754 | )) | ||
| 755 | '' | ||
| 756 | Optional filters to limit the discovery process to a subset of available resources. | ||
| 757 | ''; | ||
| 758 | |||
| 759 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 760 | The time after which the containers are refreshed. | ||
| 761 | ''; | ||
| 762 | } | ||
| 763 | // extraOptions | ||
| 764 | ); | ||
| 765 | |||
| 766 | promTypes.docker_sd_config = mkDockerSdConfigModule { | ||
| 767 | host_networking_host = mkDefOpt types.str "localhost" '' | ||
| 768 | The host to use if the container is in host networking mode. | ||
| 769 | ''; | ||
| 770 | }; | ||
| 771 | |||
| 772 | promTypes.dockerswarm_sd_config = mkDockerSdConfigModule { | ||
| 773 | role = mkOption { | ||
| 774 | type = types.enum [ | ||
| 775 | "services" | ||
| 776 | "tasks" | ||
| 777 | "nodes" | ||
| 778 | ]; | ||
| 779 | description = '' | ||
| 780 | Role of the targets to retrieve. Must be `services`, `tasks`, or `nodes`. | ||
| 781 | ''; | ||
| 782 | }; | ||
| 783 | }; | ||
| 784 | |||
| 785 | promTypes.dns_sd_config = types.submodule { | ||
| 786 | options = { | ||
| 787 | names = mkOption { | ||
| 788 | type = types.listOf types.str; | ||
| 789 | description = '' | ||
| 790 | A list of DNS SRV record names to be queried. | ||
| 791 | ''; | ||
| 792 | }; | ||
| 793 | |||
| 794 | type = | ||
| 795 | mkDefOpt | ||
| 796 | (types.enum [ | ||
| 797 | "SRV" | ||
| 798 | "A" | ||
| 799 | "AAAA" | ||
| 800 | "MX" | ||
| 801 | "NS" | ||
| 802 | ]) | ||
| 803 | "SRV" | ||
| 804 | '' | ||
| 805 | The type of DNS query to perform. | ||
| 806 | ''; | ||
| 807 | |||
| 808 | port = mkOpt types.port '' | ||
| 809 | The port number used if the query type is not SRV. | ||
| 810 | ''; | ||
| 811 | |||
| 812 | refresh_interval = mkDefOpt types.str "30s" '' | ||
| 813 | The time after which the provided names are refreshed. | ||
| 814 | ''; | ||
| 815 | }; | ||
| 816 | }; | ||
| 817 | |||
| 818 | promTypes.ec2_sd_config = types.submodule { | ||
| 819 | options = { | ||
| 820 | region = mkOption { | ||
| 821 | type = types.str; | ||
| 822 | description = '' | ||
| 823 | The AWS Region. If blank, the region from the instance metadata is used. | ||
| 824 | ''; | ||
| 825 | }; | ||
| 826 | endpoint = mkOpt types.str '' | ||
| 827 | Custom endpoint to be used. | ||
| 828 | ''; | ||
| 829 | |||
| 830 | access_key = mkOpt types.str '' | ||
| 831 | The AWS API key id. If blank, the environment variable | ||
| 832 | `AWS_ACCESS_KEY_ID` is used. | ||
| 833 | ''; | ||
| 834 | |||
| 835 | secret_key = mkOpt types.str '' | ||
| 836 | The AWS API key secret. If blank, the environment variable | ||
| 837 | `AWS_SECRET_ACCESS_KEY` is used. | ||
| 838 | ''; | ||
| 839 | |||
| 840 | profile = mkOpt types.str '' | ||
| 841 | Named AWS profile used to connect to the API. | ||
| 842 | ''; | ||
| 843 | |||
| 844 | role_arn = mkOpt types.str '' | ||
| 845 | AWS Role ARN, an alternative to using AWS API keys. | ||
| 846 | ''; | ||
| 847 | |||
| 848 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 849 | Refresh interval to re-read the instance list. | ||
| 850 | ''; | ||
| 851 | |||
| 852 | port = mkDefOpt types.port "80" '' | ||
| 853 | The port to scrape metrics from. If using the public IP | ||
| 854 | address, this must instead be specified in the relabeling | ||
| 855 | rule. | ||
| 856 | ''; | ||
| 857 | |||
| 858 | filters = | ||
| 859 | mkOpt | ||
| 860 | (types.listOf ( | ||
| 861 | types.submodule { | ||
| 862 | options = { | ||
| 863 | name = mkOption { | ||
| 864 | type = types.str; | ||
| 865 | description = '' | ||
| 866 | See [this list](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html) | ||
| 867 | for the available filters. | ||
| 868 | ''; | ||
| 869 | }; | ||
| 870 | |||
| 871 | values = mkOption { | ||
| 872 | type = types.listOf types.str; | ||
| 873 | default = [ ]; | ||
| 874 | description = '' | ||
| 875 | Value of the filter. | ||
| 876 | ''; | ||
| 877 | }; | ||
| 878 | }; | ||
| 879 | } | ||
| 880 | )) | ||
| 881 | '' | ||
| 882 | Filters can be used optionally to filter the instance list by other criteria. | ||
| 883 | ''; | ||
| 884 | }; | ||
| 885 | }; | ||
| 886 | |||
| 887 | promTypes.eureka_sd_config = mkSdConfigModule { | ||
| 888 | server = mkOption { | ||
| 889 | type = types.str; | ||
| 890 | description = '' | ||
| 891 | The URL to connect to the Eureka server. | ||
| 892 | ''; | ||
| 893 | }; | ||
| 894 | }; | ||
| 895 | |||
| 896 | promTypes.file_sd_config = types.submodule { | ||
| 897 | options = { | ||
| 898 | files = mkOption { | ||
| 899 | type = types.listOf types.str; | ||
| 900 | description = '' | ||
| 901 | Patterns for files from which target groups are extracted. Refer | ||
| 902 | to the Prometheus documentation for permitted filename patterns | ||
| 903 | and formats. | ||
| 904 | ''; | ||
| 905 | }; | ||
| 906 | |||
| 907 | refresh_interval = mkDefOpt types.str "5m" '' | ||
| 908 | Refresh interval to re-read the files. | ||
| 909 | ''; | ||
| 910 | }; | ||
| 911 | }; | ||
| 912 | |||
| 913 | promTypes.gce_sd_config = types.submodule { | ||
| 914 | options = { | ||
| 915 | # Use `mkOption` instead of `mkOpt` for project and zone because they are | ||
| 916 | # required configuration values for `gce_sd_config`. | ||
| 917 | project = mkOption { | ||
| 918 | type = types.str; | ||
| 919 | description = '' | ||
| 920 | The GCP Project. | ||
| 921 | ''; | ||
| 922 | }; | ||
| 923 | |||
| 924 | zone = mkOption { | ||
| 925 | type = types.str; | ||
| 926 | description = '' | ||
| 927 | The zone of the scrape targets. If you need multiple zones use multiple | ||
| 928 | gce_sd_configs. | ||
| 929 | ''; | ||
| 930 | }; | ||
| 931 | |||
| 932 | filter = mkOpt types.str '' | ||
| 933 | Filter can be used optionally to filter the instance list by other | ||
| 934 | criteria Syntax of this filter string is described here in the filter | ||
| 935 | query parameter section: <https://cloud.google.com/compute/docs/reference/latest/instances/list>. | ||
| 936 | ''; | ||
| 937 | |||
| 938 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 939 | Refresh interval to re-read the cloud instance list. | ||
| 940 | ''; | ||
| 941 | |||
| 942 | port = mkDefOpt types.port "80" '' | ||
| 943 | The port to scrape metrics from. If using the public IP address, this | ||
| 944 | must instead be specified in the relabeling rule. | ||
| 945 | ''; | ||
| 946 | |||
| 947 | tag_separator = mkDefOpt types.str "," '' | ||
| 948 | The tag separator used to separate concatenated GCE instance network tags. | ||
| 949 | |||
| 950 | See the GCP documentation on network tags for more information: | ||
| 951 | <https://cloud.google.com/vpc/docs/add-remove-network-tags> | ||
| 952 | ''; | ||
| 953 | }; | ||
| 954 | }; | ||
| 955 | |||
| 956 | promTypes.hetzner_sd_config = mkSdConfigModule { | ||
| 957 | role = mkOption { | ||
| 958 | type = types.enum [ | ||
| 959 | "robot" | ||
| 960 | "hcloud" | ||
| 961 | ]; | ||
| 962 | description = '' | ||
| 963 | The Hetzner role of entities that should be discovered. | ||
| 964 | One of `robot` or `hcloud`. | ||
| 965 | ''; | ||
| 966 | }; | ||
| 967 | |||
| 968 | port = mkDefOpt types.port "80" '' | ||
| 969 | The port to scrape metrics from. | ||
| 970 | ''; | ||
| 971 | |||
| 972 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 973 | The time after which the servers are refreshed. | ||
| 974 | ''; | ||
| 975 | }; | ||
| 976 | |||
| 977 | promTypes.http_sd_config = types.submodule { | ||
| 978 | options = { | ||
| 979 | url = mkOption { | ||
| 980 | type = types.str; | ||
| 981 | description = '' | ||
| 982 | URL from which the targets are fetched. | ||
| 983 | ''; | ||
| 984 | }; | ||
| 985 | |||
| 986 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 987 | Refresh interval to re-query the endpoint. | ||
| 988 | ''; | ||
| 989 | |||
| 990 | basic_auth = mkOpt promTypes.basic_auth '' | ||
| 991 | Authentication information used to authenticate to the API server. | ||
| 992 | password and password_file are mutually exclusive. | ||
| 993 | ''; | ||
| 994 | |||
| 995 | proxy_url = mkOpt types.str '' | ||
| 996 | Optional proxy URL. | ||
| 997 | ''; | ||
| 998 | |||
| 999 | follow_redirects = mkDefOpt types.bool "true" '' | ||
| 1000 | Configure whether HTTP requests follow HTTP 3xx redirects. | ||
| 1001 | ''; | ||
| 1002 | |||
| 1003 | tls_config = mkOpt promTypes.tls_config '' | ||
| 1004 | Configures the scrape request's TLS settings. | ||
| 1005 | ''; | ||
| 1006 | }; | ||
| 1007 | }; | ||
| 1008 | |||
| 1009 | promTypes.kubernetes_sd_config = mkSdConfigModule { | ||
| 1010 | api_server = mkOpt types.str '' | ||
| 1011 | The API server addresses. If left empty, Prometheus is assumed to run inside | ||
| 1012 | of the cluster and will discover API servers automatically and use the pod's | ||
| 1013 | CA certificate and bearer token file at /var/run/secrets/kubernetes.io/serviceaccount/. | ||
| 1014 | ''; | ||
| 1015 | |||
| 1016 | role = mkOption { | ||
| 1017 | type = types.enum [ | ||
| 1018 | "endpoints" | ||
| 1019 | "service" | ||
| 1020 | "pod" | ||
| 1021 | "node" | ||
| 1022 | "ingress" | ||
| 1023 | ]; | ||
| 1024 | description = '' | ||
| 1025 | The Kubernetes role of entities that should be discovered. | ||
| 1026 | One of endpoints, service, pod, node, or ingress. | ||
| 1027 | ''; | ||
| 1028 | }; | ||
| 1029 | |||
| 1030 | kubeconfig_file = mkOpt types.str '' | ||
| 1031 | Optional path to a kubeconfig file. | ||
| 1032 | Note that api_server and kube_config are mutually exclusive. | ||
| 1033 | ''; | ||
| 1034 | |||
| 1035 | namespaces = | ||
| 1036 | mkOpt | ||
| 1037 | (types.submodule { | ||
| 1038 | options = { | ||
| 1039 | names = mkOpt (types.listOf types.str) '' | ||
| 1040 | Namespace name. | ||
| 1041 | ''; | ||
| 1042 | }; | ||
| 1043 | }) | ||
| 1044 | '' | ||
| 1045 | Optional namespace discovery. If omitted, all namespaces are used. | ||
| 1046 | ''; | ||
| 1047 | |||
| 1048 | selectors = | ||
| 1049 | mkOpt | ||
| 1050 | (types.listOf ( | ||
| 1051 | types.submodule { | ||
| 1052 | options = { | ||
| 1053 | role = mkOption { | ||
| 1054 | type = types.str; | ||
| 1055 | description = '' | ||
| 1056 | Selector role | ||
| 1057 | ''; | ||
| 1058 | }; | ||
| 1059 | |||
| 1060 | label = mkOpt types.str '' | ||
| 1061 | Selector label | ||
| 1062 | ''; | ||
| 1063 | |||
| 1064 | field = mkOpt types.str '' | ||
| 1065 | Selector field | ||
| 1066 | ''; | ||
| 1067 | }; | ||
| 1068 | } | ||
| 1069 | )) | ||
| 1070 | '' | ||
| 1071 | Optional label and field selectors to limit the discovery process to a subset of available resources. | ||
| 1072 | See <https://kubernetes.io/docs/concepts/overview/working-with-objects/field-selectors/> | ||
| 1073 | and <https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/> to learn more about the possible | ||
| 1074 | filters that can be used. Endpoints role supports pod, service and endpoints selectors, other roles | ||
| 1075 | only support selectors matching the role itself (e.g. node role can only contain node selectors). | ||
| 1076 | |||
| 1077 | Note: When making decision about using field/label selector make sure that this | ||
| 1078 | is the best approach - it will prevent Prometheus from reusing single list/watch | ||
| 1079 | for all scrape configs. This might result in a bigger load on the Kubernetes API, | ||
| 1080 | because per each selector combination there will be additional LIST/WATCH. On the other hand, | ||
| 1081 | if you just want to monitor small subset of pods in large cluster it's recommended to use selectors. | ||
| 1082 | Decision, if selectors should be used or not depends on the particular situation. | ||
| 1083 | ''; | ||
| 1084 | }; | ||
| 1085 | |||
| 1086 | promTypes.kuma_sd_config = mkSdConfigModule { | ||
| 1087 | server = mkOption { | ||
| 1088 | type = types.str; | ||
| 1089 | description = '' | ||
| 1090 | Address of the Kuma Control Plane's MADS xDS server. | ||
| 1091 | ''; | ||
| 1092 | }; | ||
| 1093 | |||
| 1094 | refresh_interval = mkDefOpt types.str "30s" '' | ||
| 1095 | The time to wait between polling update requests. | ||
| 1096 | ''; | ||
| 1097 | |||
| 1098 | fetch_timeout = mkDefOpt types.str "2m" '' | ||
| 1099 | The time after which the monitoring assignments are refreshed. | ||
| 1100 | ''; | ||
| 1101 | }; | ||
| 1102 | |||
| 1103 | promTypes.lightsail_sd_config = types.submodule { | ||
| 1104 | options = { | ||
| 1105 | region = mkOpt types.str '' | ||
| 1106 | The AWS region. If blank, the region from the instance metadata is used. | ||
| 1107 | ''; | ||
| 1108 | |||
| 1109 | endpoint = mkOpt types.str '' | ||
| 1110 | Custom endpoint to be used. | ||
| 1111 | ''; | ||
| 1112 | |||
| 1113 | access_key = mkOpt types.str '' | ||
| 1114 | The AWS API keys. If blank, the environment variable `AWS_ACCESS_KEY_ID` is used. | ||
| 1115 | ''; | ||
| 1116 | |||
| 1117 | secret_key = mkOpt types.str '' | ||
| 1118 | The AWS API keys. If blank, the environment variable `AWS_SECRET_ACCESS_KEY` is used. | ||
| 1119 | ''; | ||
| 1120 | |||
| 1121 | profile = mkOpt types.str '' | ||
| 1122 | Named AWS profile used to connect to the API. | ||
| 1123 | ''; | ||
| 1124 | |||
| 1125 | role_arn = mkOpt types.str '' | ||
| 1126 | AWS Role ARN, an alternative to using AWS API keys. | ||
| 1127 | ''; | ||
| 1128 | |||
| 1129 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 1130 | Refresh interval to re-read the instance list. | ||
| 1131 | ''; | ||
| 1132 | |||
| 1133 | port = mkDefOpt types.port "80" '' | ||
| 1134 | The port to scrape metrics from. If using the public IP address, this must | ||
| 1135 | instead be specified in the relabeling rule. | ||
| 1136 | ''; | ||
| 1137 | }; | ||
| 1138 | }; | ||
| 1139 | |||
| 1140 | promTypes.linode_sd_config = mkSdConfigModule { | ||
| 1141 | port = mkDefOpt types.port "80" '' | ||
| 1142 | The port to scrape metrics from. | ||
| 1143 | ''; | ||
| 1144 | |||
| 1145 | tag_separator = mkDefOpt types.str "," '' | ||
| 1146 | The string by which Linode Instance tags are joined into the tag label. | ||
| 1147 | ''; | ||
| 1148 | |||
| 1149 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 1150 | The time after which the linode instances are refreshed. | ||
| 1151 | ''; | ||
| 1152 | }; | ||
| 1153 | |||
| 1154 | promTypes.marathon_sd_config = mkSdConfigModule { | ||
| 1155 | servers = mkOption { | ||
| 1156 | type = types.listOf types.str; | ||
| 1157 | description = '' | ||
| 1158 | List of URLs to be used to contact Marathon servers. You need to provide at least one server URL. | ||
| 1159 | ''; | ||
| 1160 | }; | ||
| 1161 | |||
| 1162 | refresh_interval = mkDefOpt types.str "30s" '' | ||
| 1163 | Polling interval. | ||
| 1164 | ''; | ||
| 1165 | |||
| 1166 | auth_token = mkOpt types.str '' | ||
| 1167 | Optional authentication information for token-based authentication: | ||
| 1168 | <https://docs.mesosphere.com/1.11/security/ent/iam-api/#passing-an-authentication-token> | ||
| 1169 | It is mutually exclusive with `auth_token_file` and other authentication mechanisms. | ||
| 1170 | ''; | ||
| 1171 | |||
| 1172 | auth_token_file = mkOpt types.str '' | ||
| 1173 | Optional authentication information for token-based authentication: | ||
| 1174 | <https://docs.mesosphere.com/1.11/security/ent/iam-api/#passing-an-authentication-token> | ||
| 1175 | It is mutually exclusive with `auth_token` and other authentication mechanisms. | ||
| 1176 | ''; | ||
| 1177 | }; | ||
| 1178 | |||
| 1179 | promTypes.nerve_sd_config = types.submodule { | ||
| 1180 | options = { | ||
| 1181 | servers = mkOption { | ||
| 1182 | type = types.listOf types.str; | ||
| 1183 | description = '' | ||
| 1184 | The Zookeeper servers. | ||
| 1185 | ''; | ||
| 1186 | }; | ||
| 1187 | |||
| 1188 | paths = mkOption { | ||
| 1189 | type = types.listOf types.str; | ||
| 1190 | description = '' | ||
| 1191 | Paths can point to a single service, or the root of a tree of services. | ||
| 1192 | ''; | ||
| 1193 | }; | ||
| 1194 | |||
| 1195 | timeout = mkDefOpt types.str "10s" '' | ||
| 1196 | Timeout value. | ||
| 1197 | ''; | ||
| 1198 | }; | ||
| 1199 | }; | ||
| 1200 | |||
| 1201 | promTypes.openstack_sd_config = types.submodule { | ||
| 1202 | options = | ||
| 1203 | let | ||
| 1204 | userDescription = '' | ||
| 1205 | username is required if using Identity V2 API. Consult with your provider's | ||
| 1206 | control panel to discover your account's username. In Identity V3, either | ||
| 1207 | userid or a combination of username and domain_id or domain_name are needed. | ||
| 1208 | ''; | ||
| 1209 | |||
| 1210 | domainDescription = '' | ||
| 1211 | At most one of domain_id and domain_name must be provided if using username | ||
| 1212 | with Identity V3. Otherwise, either are optional. | ||
| 1213 | ''; | ||
| 1214 | |||
| 1215 | projectDescription = '' | ||
| 1216 | The project_id and project_name fields are optional for the Identity V2 API. | ||
| 1217 | Some providers allow you to specify a project_name instead of the project_id. | ||
| 1218 | Some require both. Your provider's authentication policies will determine | ||
| 1219 | how these fields influence authentication. | ||
| 1220 | ''; | ||
| 1221 | |||
| 1222 | applicationDescription = '' | ||
| 1223 | The application_credential_id or application_credential_name fields are | ||
| 1224 | required if using an application credential to authenticate. Some providers | ||
| 1225 | allow you to create an application credential to authenticate rather than a | ||
| 1226 | password. | ||
| 1227 | ''; | ||
| 1228 | in | ||
| 1229 | { | ||
| 1230 | role = mkOption { | ||
| 1231 | type = types.str; | ||
| 1232 | description = '' | ||
| 1233 | The OpenStack role of entities that should be discovered. | ||
| 1234 | ''; | ||
| 1235 | }; | ||
| 1236 | |||
| 1237 | region = mkOption { | ||
| 1238 | type = types.str; | ||
| 1239 | description = '' | ||
| 1240 | The OpenStack Region. | ||
| 1241 | ''; | ||
| 1242 | }; | ||
| 1243 | |||
| 1244 | identity_endpoint = mkOpt types.str '' | ||
| 1245 | identity_endpoint specifies the HTTP endpoint that is required to work with | ||
| 1246 | the Identity API of the appropriate version. While it's ultimately needed by | ||
| 1247 | all of the identity services, it will often be populated by a provider-level | ||
| 1248 | function. | ||
| 1249 | ''; | ||
| 1250 | |||
| 1251 | username = mkOpt types.str userDescription; | ||
| 1252 | userid = mkOpt types.str userDescription; | ||
| 1253 | |||
| 1254 | password = mkOpt types.str '' | ||
| 1255 | password for the Identity V2 and V3 APIs. Consult with your provider's | ||
| 1256 | control panel to discover your account's preferred method of authentication. | ||
| 1257 | ''; | ||
| 1258 | |||
| 1259 | domain_name = mkOpt types.str domainDescription; | ||
| 1260 | domain_id = mkOpt types.str domainDescription; | ||
| 1261 | |||
| 1262 | project_name = mkOpt types.str projectDescription; | ||
| 1263 | project_id = mkOpt types.str projectDescription; | ||
| 1264 | |||
| 1265 | application_credential_name = mkOpt types.str applicationDescription; | ||
| 1266 | application_credential_id = mkOpt types.str applicationDescription; | ||
| 1267 | |||
| 1268 | application_credential_secret = mkOpt types.str '' | ||
| 1269 | The application_credential_secret field is required if using an application | ||
| 1270 | credential to authenticate. | ||
| 1271 | ''; | ||
| 1272 | |||
| 1273 | all_tenants = mkDefOpt types.bool "false" '' | ||
| 1274 | Whether the service discovery should list all instances for all projects. | ||
| 1275 | It is only relevant for the 'instance' role and usually requires admin permissions. | ||
| 1276 | ''; | ||
| 1277 | |||
| 1278 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 1279 | Refresh interval to re-read the instance list. | ||
| 1280 | ''; | ||
| 1281 | |||
| 1282 | port = mkDefOpt types.port "80" '' | ||
| 1283 | The port to scrape metrics from. If using the public IP address, this must | ||
| 1284 | instead be specified in the relabeling rule. | ||
| 1285 | ''; | ||
| 1286 | |||
| 1287 | availability = | ||
| 1288 | mkDefOpt | ||
| 1289 | (types.enum [ | ||
| 1290 | "public" | ||
| 1291 | "admin" | ||
| 1292 | "internal" | ||
| 1293 | ]) | ||
| 1294 | "public" | ||
| 1295 | '' | ||
| 1296 | The availability of the endpoint to connect to. Must be one of public, admin or internal. | ||
| 1297 | ''; | ||
| 1298 | |||
| 1299 | tls_config = mkOpt promTypes.tls_config '' | ||
| 1300 | TLS configuration. | ||
| 1301 | ''; | ||
| 1302 | }; | ||
| 1303 | }; | ||
| 1304 | |||
| 1305 | promTypes.puppetdb_sd_config = mkSdConfigModule { | ||
| 1306 | url = mkOption { | ||
| 1307 | type = types.str; | ||
| 1308 | description = '' | ||
| 1309 | The URL of the PuppetDB root query endpoint. | ||
| 1310 | ''; | ||
| 1311 | }; | ||
| 1312 | |||
| 1313 | query = mkOption { | ||
| 1314 | type = types.str; | ||
| 1315 | description = '' | ||
| 1316 | Puppet Query Language (PQL) query. Only resources are supported. | ||
| 1317 | <https://puppet.com/docs/puppetdb/latest/api/query/v4/pql.html> | ||
| 1318 | ''; | ||
| 1319 | }; | ||
| 1320 | |||
| 1321 | include_parameters = mkDefOpt types.bool "false" '' | ||
| 1322 | Whether to include the parameters as meta labels. | ||
| 1323 | Due to the differences between parameter types and Prometheus labels, | ||
| 1324 | some parameters might not be rendered. The format of the parameters might | ||
| 1325 | also change in future releases. | ||
| 1326 | |||
| 1327 | Note: Enabling this exposes parameters in the Prometheus UI and API. Make sure | ||
| 1328 | that you don't have secrets exposed as parameters if you enable this. | ||
| 1329 | ''; | ||
| 1330 | |||
| 1331 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 1332 | Refresh interval to re-read the resources list. | ||
| 1333 | ''; | ||
| 1334 | |||
| 1335 | port = mkDefOpt types.port "80" '' | ||
| 1336 | The port to scrape metrics from. | ||
| 1337 | ''; | ||
| 1338 | }; | ||
| 1339 | |||
| 1340 | promTypes.scaleway_sd_config = types.submodule { | ||
| 1341 | options = { | ||
| 1342 | access_key = mkOption { | ||
| 1343 | type = types.str; | ||
| 1344 | description = '' | ||
| 1345 | Access key to use. <https://console.scaleway.com/project/credentials> | ||
| 1346 | ''; | ||
| 1347 | }; | ||
| 1348 | |||
| 1349 | secret_key = mkOpt types.str '' | ||
| 1350 | Secret key to use when listing targets. <https://console.scaleway.com/project/credentials> | ||
| 1351 | It is mutually exclusive with `secret_key_file`. | ||
| 1352 | ''; | ||
| 1353 | |||
| 1354 | secret_key_file = mkOpt types.str '' | ||
| 1355 | Sets the secret key with the credentials read from the configured file. | ||
| 1356 | It is mutually exclusive with `secret_key`. | ||
| 1357 | ''; | ||
| 1358 | |||
| 1359 | project_id = mkOption { | ||
| 1360 | type = types.str; | ||
| 1361 | description = '' | ||
| 1362 | Project ID of the targets. | ||
| 1363 | ''; | ||
| 1364 | }; | ||
| 1365 | |||
| 1366 | role = mkOption { | ||
| 1367 | type = types.enum [ | ||
| 1368 | "instance" | ||
| 1369 | "baremetal" | ||
| 1370 | ]; | ||
| 1371 | description = '' | ||
| 1372 | Role of the targets to retrieve. Must be `instance` or `baremetal`. | ||
| 1373 | ''; | ||
| 1374 | }; | ||
| 1375 | |||
| 1376 | port = mkDefOpt types.port "80" '' | ||
| 1377 | The port to scrape metrics from. | ||
| 1378 | ''; | ||
| 1379 | |||
| 1380 | api_url = mkDefOpt types.str "https://api.scaleway.com" '' | ||
| 1381 | API URL to use when doing the server listing requests. | ||
| 1382 | ''; | ||
| 1383 | |||
| 1384 | zone = mkDefOpt types.str "fr-par-1" '' | ||
| 1385 | Zone is the availability zone of your targets (e.g. fr-par-1). | ||
| 1386 | ''; | ||
| 1387 | |||
| 1388 | name_filter = mkOpt types.str '' | ||
| 1389 | Specify a name filter (works as a LIKE) to apply on the server listing request. | ||
| 1390 | ''; | ||
| 1391 | |||
| 1392 | tags_filter = mkOpt (types.listOf types.str) '' | ||
| 1393 | Specify a tag filter (a server needs to have all defined tags to be listed) to apply on the server listing request. | ||
| 1394 | ''; | ||
| 1395 | |||
| 1396 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 1397 | Refresh interval to re-read the managed targets list. | ||
| 1398 | ''; | ||
| 1399 | |||
| 1400 | proxy_url = mkOpt types.str '' | ||
| 1401 | Optional proxy URL. | ||
| 1402 | ''; | ||
| 1403 | |||
| 1404 | follow_redirects = mkDefOpt types.bool "true" '' | ||
| 1405 | Configure whether HTTP requests follow HTTP 3xx redirects. | ||
| 1406 | ''; | ||
| 1407 | |||
| 1408 | tls_config = mkOpt promTypes.tls_config '' | ||
| 1409 | TLS configuration. | ||
| 1410 | ''; | ||
| 1411 | }; | ||
| 1412 | }; | ||
| 1413 | |||
| 1414 | # These are exactly the same. | ||
| 1415 | promTypes.serverset_sd_config = promTypes.nerve_sd_config; | ||
| 1416 | |||
| 1417 | promTypes.triton_sd_config = types.submodule { | ||
| 1418 | options = { | ||
| 1419 | account = mkOption { | ||
| 1420 | type = types.str; | ||
| 1421 | description = '' | ||
| 1422 | The account to use for discovering new targets. | ||
| 1423 | ''; | ||
| 1424 | }; | ||
| 1425 | |||
| 1426 | role = | ||
| 1427 | mkDefOpt | ||
| 1428 | (types.enum [ | ||
| 1429 | "container" | ||
| 1430 | "cn" | ||
| 1431 | ]) | ||
| 1432 | "container" | ||
| 1433 | '' | ||
| 1434 | The type of targets to discover, can be set to: | ||
| 1435 | - "container" to discover virtual machines (SmartOS zones, lx/KVM/bhyve branded zones) running on Triton | ||
| 1436 | - "cn" to discover compute nodes (servers/global zones) making up the Triton infrastructure | ||
| 1437 | ''; | ||
| 1438 | |||
| 1439 | dns_suffix = mkOption { | ||
| 1440 | type = types.str; | ||
| 1441 | description = '' | ||
| 1442 | The DNS suffix which should be applied to target. | ||
| 1443 | ''; | ||
| 1444 | }; | ||
| 1445 | |||
| 1446 | endpoint = mkOption { | ||
| 1447 | type = types.str; | ||
| 1448 | description = '' | ||
| 1449 | The Triton discovery endpoint (e.g. `cmon.us-east-3b.triton.zone`). This is | ||
| 1450 | often the same value as dns_suffix. | ||
| 1451 | ''; | ||
| 1452 | }; | ||
| 1453 | |||
| 1454 | groups = mkOpt (types.listOf types.str) '' | ||
| 1455 | A list of groups for which targets are retrieved, only supported when targeting the `container` role. | ||
| 1456 | If omitted all containers owned by the requesting account are scraped. | ||
| 1457 | ''; | ||
| 1458 | |||
| 1459 | port = mkDefOpt types.port "9163" '' | ||
| 1460 | The port to use for discovery and metric scraping. | ||
| 1461 | ''; | ||
| 1462 | |||
| 1463 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 1464 | The interval which should be used for refreshing targets. | ||
| 1465 | ''; | ||
| 1466 | |||
| 1467 | version = mkDefOpt types.int "1" '' | ||
| 1468 | The Triton discovery API version. | ||
| 1469 | ''; | ||
| 1470 | |||
| 1471 | tls_config = mkOpt promTypes.tls_config '' | ||
| 1472 | TLS configuration. | ||
| 1473 | ''; | ||
| 1474 | }; | ||
| 1475 | }; | ||
| 1476 | |||
| 1477 | promTypes.uyuni_sd_config = mkSdConfigModule { | ||
| 1478 | server = mkOption { | ||
| 1479 | type = types.str; | ||
| 1480 | description = '' | ||
| 1481 | The URL to connect to the Uyuni server. | ||
| 1482 | ''; | ||
| 1483 | }; | ||
| 1484 | |||
| 1485 | username = mkOption { | ||
| 1486 | type = types.str; | ||
| 1487 | description = '' | ||
| 1488 | Credentials are used to authenticate the requests to Uyuni API. | ||
| 1489 | ''; | ||
| 1490 | }; | ||
| 1491 | |||
| 1492 | password = mkOption { | ||
| 1493 | type = types.str; | ||
| 1494 | description = '' | ||
| 1495 | Credentials are used to authenticate the requests to Uyuni API. | ||
| 1496 | ''; | ||
| 1497 | }; | ||
| 1498 | |||
| 1499 | entitlement = mkDefOpt types.str "monitoring_entitled" '' | ||
| 1500 | The entitlement string to filter eligible systems. | ||
| 1501 | ''; | ||
| 1502 | |||
| 1503 | separator = mkDefOpt types.str "," '' | ||
| 1504 | The string by which Uyuni group names are joined into the groups label | ||
| 1505 | ''; | ||
| 1506 | |||
| 1507 | refresh_interval = mkDefOpt types.str "60s" '' | ||
| 1508 | Refresh interval to re-read the managed targets list. | ||
| 1509 | ''; | ||
| 1510 | }; | ||
| 1511 | |||
| 1512 | promTypes.static_config = types.submodule { | ||
| 1513 | options = { | ||
| 1514 | targets = mkOption { | ||
| 1515 | type = types.listOf types.str; | ||
| 1516 | description = '' | ||
| 1517 | The targets specified by the target group. | ||
| 1518 | ''; | ||
| 1519 | }; | ||
| 1520 | labels = mkOption { | ||
| 1521 | type = types.attrsOf types.str; | ||
| 1522 | default = { }; | ||
| 1523 | description = '' | ||
| 1524 | Labels assigned to all metrics scraped from the targets. | ||
| 1525 | ''; | ||
| 1526 | }; | ||
| 1527 | }; | ||
| 1528 | }; | ||
| 1529 | |||
| 1530 | # | ||
| 1531 | # Config types: relabling | ||
| 1532 | # | ||
| 1533 | |||
| 1534 | promTypes.relabel_config = types.submodule { | ||
| 1535 | options = { | ||
| 1536 | source_labels = mkOpt (types.listOf types.str) '' | ||
| 1537 | The source labels select values from existing labels. Their content | ||
| 1538 | is concatenated using the configured separator and matched against | ||
| 1539 | the configured regular expression. | ||
| 1540 | ''; | ||
| 1541 | |||
| 1542 | separator = mkDefOpt types.str ";" '' | ||
| 1543 | Separator placed between concatenated source label values. | ||
| 1544 | ''; | ||
| 1545 | |||
| 1546 | target_label = mkOpt types.str '' | ||
| 1547 | Label to which the resulting value is written in a replace action. | ||
| 1548 | It is mandatory for replace actions. | ||
| 1549 | ''; | ||
| 1550 | |||
| 1551 | regex = mkDefOpt types.str "(.*)" '' | ||
| 1552 | Regular expression against which the extracted value is matched. | ||
| 1553 | ''; | ||
| 1554 | |||
| 1555 | modulus = mkOpt types.int '' | ||
| 1556 | Modulus to take of the hash of the source label values. | ||
| 1557 | ''; | ||
| 1558 | |||
| 1559 | replacement = mkDefOpt types.str "$1" '' | ||
| 1560 | Replacement value against which a regex replace is performed if the | ||
| 1561 | regular expression matches. | ||
| 1562 | ''; | ||
| 1563 | |||
| 1564 | action = | ||
| 1565 | mkDefOpt | ||
| 1566 | (types.enum [ | ||
| 1567 | "replace" | ||
| 1568 | "lowercase" | ||
| 1569 | "uppercase" | ||
| 1570 | "keep" | ||
| 1571 | "drop" | ||
| 1572 | "hashmod" | ||
| 1573 | "labelmap" | ||
| 1574 | "labeldrop" | ||
| 1575 | "labelkeep" | ||
| 1576 | ]) | ||
| 1577 | "replace" | ||
| 1578 | '' | ||
| 1579 | Action to perform based on regex matching. | ||
| 1580 | ''; | ||
| 1581 | }; | ||
| 1582 | }; | ||
| 1583 | |||
| 1584 | # | ||
| 1585 | # Config types : remote read / write | ||
| 1586 | # | ||
| 1587 | |||
| 1588 | promTypes.remote_write = types.submodule { | ||
| 1589 | options = { | ||
| 1590 | url = mkOption { | ||
| 1591 | type = types.str; | ||
| 1592 | description = '' | ||
| 1593 | ServerName extension to indicate the name of the server. | ||
| 1594 | http://tools.ietf.org/html/rfc4366#section-3.1 | ||
| 1595 | ''; | ||
| 1596 | }; | ||
| 1597 | remote_timeout = mkOpt types.str '' | ||
| 1598 | Timeout for requests to the remote write endpoint. | ||
| 1599 | ''; | ||
| 1600 | headers = mkOpt (types.attrsOf types.str) '' | ||
| 1601 | Custom HTTP headers to be sent along with each remote write request. | ||
| 1602 | Be aware that headers that are set by Prometheus itself can't be overwritten. | ||
| 1603 | ''; | ||
| 1604 | write_relabel_configs = mkOpt (types.listOf promTypes.relabel_config) '' | ||
| 1605 | List of remote write relabel configurations. | ||
| 1606 | ''; | ||
| 1607 | name = mkOpt types.str '' | ||
| 1608 | Name of the remote write config, which if specified must be unique among remote write configs. | ||
| 1609 | The name will be used in metrics and logging in place of a generated value to help users distinguish between | ||
| 1610 | remote write configs. | ||
| 1611 | ''; | ||
| 1612 | basic_auth = mkOpt promTypes.basic_auth '' | ||
| 1613 | Sets the `Authorization` header on every remote write request with the | ||
| 1614 | configured username and password. | ||
| 1615 | password and password_file are mutually exclusive. | ||
| 1616 | ''; | ||
| 1617 | bearer_token = mkOpt types.str '' | ||
| 1618 | Sets the `Authorization` header on every remote write request with | ||
| 1619 | the configured bearer token. It is mutually exclusive with `bearer_token_file`. | ||
| 1620 | ''; | ||
| 1621 | bearer_token_file = mkOpt types.str '' | ||
| 1622 | Sets the `Authorization` header on every remote write request with the bearer token | ||
| 1623 | read from the configured file. It is mutually exclusive with `bearer_token`. | ||
| 1624 | ''; | ||
| 1625 | sigv4 = mkOpt promTypes.sigv4 '' | ||
| 1626 | Configures AWS Signature Version 4 settings. | ||
| 1627 | ''; | ||
| 1628 | tls_config = mkOpt promTypes.tls_config '' | ||
| 1629 | Configures the remote write request's TLS settings. | ||
| 1630 | ''; | ||
| 1631 | proxy_url = mkOpt types.str "Optional Proxy URL."; | ||
| 1632 | queue_config = | ||
| 1633 | mkOpt | ||
| 1634 | (types.submodule { | ||
| 1635 | options = { | ||
| 1636 | capacity = mkOpt types.int '' | ||
| 1637 | Number of samples to buffer per shard before we block reading of more | ||
| 1638 | samples from the WAL. It is recommended to have enough capacity in each | ||
| 1639 | shard to buffer several requests to keep throughput up while processing | ||
| 1640 | occasional slow remote requests. | ||
| 1641 | ''; | ||
| 1642 | max_shards = mkOpt types.int '' | ||
| 1643 | Maximum number of shards, i.e. amount of concurrency. | ||
| 1644 | ''; | ||
| 1645 | min_shards = mkOpt types.int '' | ||
| 1646 | Minimum number of shards, i.e. amount of concurrency. | ||
| 1647 | ''; | ||
| 1648 | max_samples_per_send = mkOpt types.int '' | ||
| 1649 | Maximum number of samples per send. | ||
| 1650 | ''; | ||
| 1651 | batch_send_deadline = mkOpt types.str '' | ||
| 1652 | Maximum time a sample will wait in buffer. | ||
| 1653 | ''; | ||
| 1654 | min_backoff = mkOpt types.str '' | ||
| 1655 | Initial retry delay. Gets doubled for every retry. | ||
| 1656 | ''; | ||
| 1657 | max_backoff = mkOpt types.str '' | ||
| 1658 | Maximum retry delay. | ||
| 1659 | ''; | ||
| 1660 | }; | ||
| 1661 | }) | ||
| 1662 | '' | ||
| 1663 | Configures the queue used to write to remote storage. | ||
| 1664 | ''; | ||
| 1665 | metadata_config = | ||
| 1666 | mkOpt | ||
| 1667 | (types.submodule { | ||
| 1668 | options = { | ||
| 1669 | send = mkOpt types.bool '' | ||
| 1670 | Whether metric metadata is sent to remote storage or not. | ||
| 1671 | ''; | ||
| 1672 | send_interval = mkOpt types.str '' | ||
| 1673 | How frequently metric metadata is sent to remote storage. | ||
| 1674 | ''; | ||
| 1675 | }; | ||
| 1676 | }) | ||
| 1677 | '' | ||
| 1678 | Configures the sending of series metadata to remote storage. | ||
| 1679 | Metadata configuration is subject to change at any point | ||
| 1680 | or be removed in future releases. | ||
| 1681 | ''; | ||
| 1682 | }; | ||
| 1683 | }; | ||
| 1684 | |||
| 1685 | promTypes.remote_read = types.submodule { | ||
| 1686 | options = { | ||
| 1687 | url = mkOption { | ||
| 1688 | type = types.str; | ||
| 1689 | description = '' | ||
| 1690 | ServerName extension to indicate the name of the server. | ||
| 1691 | http://tools.ietf.org/html/rfc4366#section-3.1 | ||
| 1692 | ''; | ||
| 1693 | }; | ||
| 1694 | name = mkOpt types.str '' | ||
| 1695 | Name of the remote read config, which if specified must be unique among remote read configs. | ||
| 1696 | The name will be used in metrics and logging in place of a generated value to help users distinguish between | ||
| 1697 | remote read configs. | ||
| 1698 | ''; | ||
| 1699 | required_matchers = mkOpt (types.attrsOf types.str) '' | ||
| 1700 | An optional list of equality matchers which have to be | ||
| 1701 | present in a selector to query the remote read endpoint. | ||
| 1702 | ''; | ||
| 1703 | remote_timeout = mkOpt types.str '' | ||
| 1704 | Timeout for requests to the remote read endpoint. | ||
| 1705 | ''; | ||
| 1706 | headers = mkOpt (types.attrsOf types.str) '' | ||
| 1707 | Custom HTTP headers to be sent along with each remote read request. | ||
| 1708 | Be aware that headers that are set by Prometheus itself can't be overwritten. | ||
| 1709 | ''; | ||
| 1710 | read_recent = mkOpt types.bool '' | ||
| 1711 | Whether reads should be made for queries for time ranges that | ||
| 1712 | the local storage should have complete data for. | ||
| 1713 | ''; | ||
| 1714 | basic_auth = mkOpt promTypes.basic_auth '' | ||
| 1715 | Sets the `Authorization` header on every remote read request with the | ||
| 1716 | configured username and password. | ||
| 1717 | password and password_file are mutually exclusive. | ||
| 1718 | ''; | ||
| 1719 | bearer_token = mkOpt types.str '' | ||
| 1720 | Sets the `Authorization` header on every remote read request with | ||
| 1721 | the configured bearer token. It is mutually exclusive with `bearer_token_file`. | ||
| 1722 | ''; | ||
| 1723 | bearer_token_file = mkOpt types.str '' | ||
| 1724 | Sets the `Authorization` header on every remote read request with the bearer token | ||
| 1725 | read from the configured file. It is mutually exclusive with `bearer_token`. | ||
| 1726 | ''; | ||
| 1727 | tls_config = mkOpt promTypes.tls_config '' | ||
| 1728 | Configures the remote read request's TLS settings. | ||
| 1729 | ''; | ||
| 1730 | proxy_url = mkOpt types.str "Optional Proxy URL."; | ||
| 1731 | }; | ||
| 1732 | }; | ||
| 1733 | |||
| 1734 | in | ||
| 1735 | { | ||
| 1736 | disabledModules = ["services/monitoring/prometheus/default.nix"]; | ||
| 1737 | |||
| 1738 | imports = [ | ||
| 1739 | (mkRenamedOptionModule [ "services" "prometheus2" ] [ "services" "prometheus" ]) | ||
| 1740 | (mkRemovedOptionModule [ "services" "prometheus" "environmentFile" ] | ||
| 1741 | "It has been removed since it was causing issues (https://github.com/NixOS/nixpkgs/issues/126083) and Prometheus now has native support for secret files, i.e. `basic_auth.password_file` and `authorization.credentials_file`." | ||
| 1742 | ) | ||
| 1743 | (mkRemovedOptionModule [ | ||
| 1744 | "services" | ||
| 1745 | "prometheus" | ||
| 1746 | "alertmanagerTimeout" | ||
| 1747 | ] "Deprecated upstream and no longer had any effect") | ||
| 1748 | ]; | ||
| 1749 | |||
| 1750 | options.services.prometheus = { | ||
| 1751 | |||
| 1752 | enable = mkEnableOption "Prometheus monitoring daemon"; | ||
| 1753 | |||
| 1754 | package = mkPackageOption pkgs "prometheus" { }; | ||
| 1755 | |||
| 1756 | port = mkOption { | ||
| 1757 | type = types.port; | ||
| 1758 | default = 9090; | ||
| 1759 | description = '' | ||
| 1760 | Port to listen on. | ||
| 1761 | ''; | ||
| 1762 | }; | ||
| 1763 | |||
| 1764 | listenAddress = mkOption { | ||
| 1765 | type = types.str; | ||
| 1766 | default = "0.0.0.0"; | ||
| 1767 | description = '' | ||
| 1768 | Address to listen on for the web interface, API, and telemetry. | ||
| 1769 | ''; | ||
| 1770 | }; | ||
| 1771 | |||
| 1772 | stateDir = mkOption { | ||
| 1773 | type = types.str; | ||
| 1774 | default = "prometheus2"; | ||
| 1775 | description = '' | ||
| 1776 | Directory below `/var/lib` to store Prometheus metrics data. | ||
| 1777 | This directory will be created automatically using systemd's StateDirectory mechanism. | ||
| 1778 | ''; | ||
| 1779 | }; | ||
| 1780 | |||
| 1781 | extraFlags = mkOption { | ||
| 1782 | type = types.listOf types.str; | ||
| 1783 | default = [ ]; | ||
| 1784 | description = '' | ||
| 1785 | Extra commandline options when launching Prometheus. | ||
| 1786 | ''; | ||
| 1787 | }; | ||
| 1788 | |||
| 1789 | enableReload = mkOption { | ||
| 1790 | default = false; | ||
| 1791 | type = types.bool; | ||
| 1792 | description = '' | ||
| 1793 | Reload prometheus when configuration file changes (instead of restart). | ||
| 1794 | |||
| 1795 | The following property holds: switching to a configuration | ||
| 1796 | (`switch-to-configuration`) that changes the prometheus | ||
| 1797 | configuration only finishes successfully when prometheus has finished | ||
| 1798 | loading the new configuration. | ||
| 1799 | ''; | ||
| 1800 | }; | ||
| 1801 | |||
| 1802 | enableAgentMode = mkEnableOption "agent mode"; | ||
| 1803 | |||
| 1804 | configText = mkOption { | ||
| 1805 | type = types.nullOr types.lines; | ||
| 1806 | default = null; | ||
| 1807 | description = '' | ||
| 1808 | If non-null, this option defines the text that is written to | ||
| 1809 | prometheus.yml. If null, the contents of prometheus.yml is generated | ||
| 1810 | from the structured config options. | ||
| 1811 | ''; | ||
| 1812 | }; | ||
| 1813 | |||
| 1814 | globalConfig = mkOption { | ||
| 1815 | type = promTypes.globalConfig; | ||
| 1816 | default = { }; | ||
| 1817 | description = '' | ||
| 1818 | Parameters that are valid in all configuration contexts. They | ||
| 1819 | also serve as defaults for other configuration sections | ||
| 1820 | ''; | ||
| 1821 | }; | ||
| 1822 | |||
| 1823 | remoteRead = mkOption { | ||
| 1824 | type = types.listOf promTypes.remote_read; | ||
| 1825 | default = [ ]; | ||
| 1826 | description = '' | ||
| 1827 | Parameters of the endpoints to query from. | ||
| 1828 | See [the official documentation](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_read) for more information. | ||
| 1829 | ''; | ||
| 1830 | }; | ||
| 1831 | |||
| 1832 | remoteWrite = mkOption { | ||
| 1833 | type = types.listOf promTypes.remote_write; | ||
| 1834 | default = [ ]; | ||
| 1835 | description = '' | ||
| 1836 | Parameters of the endpoints to send samples to. | ||
| 1837 | See [the official documentation](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write) for more information. | ||
| 1838 | ''; | ||
| 1839 | }; | ||
| 1840 | |||
| 1841 | rules = mkOption { | ||
| 1842 | type = types.listOf types.str; | ||
| 1843 | default = [ ]; | ||
| 1844 | description = '' | ||
| 1845 | Alerting and/or Recording rules to evaluate at runtime. | ||
| 1846 | ''; | ||
| 1847 | }; | ||
| 1848 | |||
| 1849 | ruleFiles = mkOption { | ||
| 1850 | type = types.listOf types.path; | ||
| 1851 | default = [ ]; | ||
| 1852 | description = '' | ||
| 1853 | Any additional rules files to include in this configuration. | ||
| 1854 | ''; | ||
| 1855 | }; | ||
| 1856 | |||
| 1857 | scrapeConfigs = mkOption { | ||
| 1858 | type = types.listOf promTypes.scrape_config; | ||
| 1859 | default = [ ]; | ||
| 1860 | description = '' | ||
| 1861 | A list of scrape configurations. | ||
| 1862 | ''; | ||
| 1863 | }; | ||
| 1864 | |||
| 1865 | alertmanagers = mkOption { | ||
| 1866 | type = types.listOf types.attrs; | ||
| 1867 | example = literalExpression '' | ||
| 1868 | [ { | ||
| 1869 | scheme = "https"; | ||
| 1870 | path_prefix = "/alertmanager"; | ||
| 1871 | static_configs = [ { | ||
| 1872 | targets = [ | ||
| 1873 | "prometheus.domain.tld" | ||
| 1874 | ]; | ||
| 1875 | } ]; | ||
| 1876 | } ] | ||
| 1877 | ''; | ||
| 1878 | default = [ ]; | ||
| 1879 | description = '' | ||
| 1880 | A list of alertmanagers to send alerts to. | ||
| 1881 | See [the official documentation](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alertmanager_config) for more information. | ||
| 1882 | ''; | ||
| 1883 | }; | ||
| 1884 | |||
| 1885 | alertmanagerNotificationQueueCapacity = mkOption { | ||
| 1886 | type = types.int; | ||
| 1887 | default = 10000; | ||
| 1888 | description = '' | ||
| 1889 | The capacity of the queue for pending alert manager notifications. | ||
| 1890 | ''; | ||
| 1891 | }; | ||
| 1892 | |||
| 1893 | webExternalUrl = mkOption { | ||
| 1894 | type = types.nullOr types.str; | ||
| 1895 | default = null; | ||
| 1896 | example = "https://example.com/"; | ||
| 1897 | description = '' | ||
| 1898 | The URL under which Prometheus is externally reachable (for example, | ||
| 1899 | if Prometheus is served via a reverse proxy). | ||
| 1900 | ''; | ||
| 1901 | }; | ||
| 1902 | |||
| 1903 | webConfigFile = mkOption { | ||
| 1904 | type = types.nullOr types.path; | ||
| 1905 | default = null; | ||
| 1906 | description = '' | ||
| 1907 | Specifies which file should be used as web.config.file and be passed on startup. | ||
| 1908 | See <https://prometheus.io/docs/prometheus/latest/configuration/https/> for valid options. | ||
| 1909 | ''; | ||
| 1910 | }; | ||
| 1911 | |||
| 1912 | checkConfig = mkOption { | ||
| 1913 | type = with types; either bool (enum [ "syntax-only" ]); | ||
| 1914 | default = true; | ||
| 1915 | example = "syntax-only"; | ||
| 1916 | description = '' | ||
| 1917 | Check configuration with `promtool check`. The call to `promtool` is | ||
| 1918 | subject to sandboxing by Nix. | ||
| 1919 | |||
| 1920 | If you use credentials stored in external files | ||
| 1921 | (`password_file`, `bearer_token_file`, etc), | ||
| 1922 | they will not be visible to `promtool` | ||
| 1923 | and it will report errors, despite a correct configuration. | ||
| 1924 | To resolve this, you may set this option to `"syntax-only"` | ||
| 1925 | in order to only syntax check the Prometheus configuration. | ||
| 1926 | ''; | ||
| 1927 | }; | ||
| 1928 | |||
| 1929 | retentionTime = mkOption { | ||
| 1930 | type = types.nullOr types.str; | ||
| 1931 | default = null; | ||
| 1932 | example = "15d"; | ||
| 1933 | description = '' | ||
| 1934 | How long to retain samples in storage. | ||
| 1935 | ''; | ||
| 1936 | }; | ||
| 1937 | |||
| 1938 | extraConfig = mkOption { | ||
| 1939 | type = yaml.type; | ||
| 1940 | default = {}; | ||
| 1941 | }; | ||
| 1942 | }; | ||
| 1943 | |||
| 1944 | config = mkIf cfg.enable { | ||
| 1945 | assertions = [ | ||
| 1946 | ( | ||
| 1947 | let | ||
| 1948 | # Match something with dots (an IPv4 address) or something ending in | ||
| 1949 | # a square bracket (an IPv6 addresses) followed by a port number. | ||
| 1950 | legacy = builtins.match "(.*\\..*|.*]):([[:digit:]]+)" cfg.listenAddress; | ||
| 1951 | in | ||
| 1952 | { | ||
| 1953 | assertion = legacy == null; | ||
| 1954 | message = '' | ||
| 1955 | Do not specify the port for Prometheus to listen on in the | ||
| 1956 | listenAddress option; use the port option instead: | ||
| 1957 | services.prometheus.listenAddress = ${builtins.elemAt legacy 0}; | ||
| 1958 | services.prometheus.port = ${builtins.elemAt legacy 1}; | ||
| 1959 | ''; | ||
| 1960 | } | ||
| 1961 | ) | ||
| 1962 | ]; | ||
| 1963 | |||
| 1964 | users.groups.prometheus.gid = config.ids.gids.prometheus; | ||
| 1965 | users.users.prometheus = { | ||
| 1966 | description = "Prometheus daemon user"; | ||
| 1967 | uid = config.ids.uids.prometheus; | ||
| 1968 | group = "prometheus"; | ||
| 1969 | }; | ||
| 1970 | environment.etc."prometheus/prometheus.yaml" = mkIf cfg.enableReload { | ||
| 1971 | source = prometheusYml; | ||
| 1972 | }; | ||
| 1973 | systemd.services.prometheus = { | ||
| 1974 | wantedBy = [ "multi-user.target" ]; | ||
| 1975 | after = [ "network.target" ]; | ||
| 1976 | serviceConfig = { | ||
| 1977 | ExecStart = | ||
| 1978 | "${lib.getExe cfg.package}" | ||
| 1979 | + optionalString (length cmdlineArgs != 0) (" \\\n " + concatStringsSep " \\\n " cmdlineArgs); | ||
| 1980 | ExecReload = mkIf cfg.enableReload "+${reload}/bin/reload-prometheus"; | ||
| 1981 | User = "prometheus"; | ||
| 1982 | Restart = "always"; | ||
| 1983 | RuntimeDirectory = "prometheus"; | ||
| 1984 | RuntimeDirectoryMode = "0700"; | ||
| 1985 | WorkingDirectory = workingDir; | ||
| 1986 | StateDirectory = cfg.stateDir; | ||
| 1987 | StateDirectoryMode = "0700"; | ||
| 1988 | # Hardening | ||
| 1989 | CapabilityBoundingSet = [ "" ]; | ||
| 1990 | DeviceAllow = [ "/dev/null rw" ]; | ||
| 1991 | DevicePolicy = "strict"; | ||
| 1992 | LockPersonality = true; | ||
| 1993 | MemoryDenyWriteExecute = true; | ||
| 1994 | NoNewPrivileges = true; | ||
| 1995 | PrivateDevices = true; | ||
| 1996 | PrivateTmp = true; | ||
| 1997 | PrivateUsers = true; | ||
| 1998 | ProtectClock = true; | ||
| 1999 | ProtectControlGroups = true; | ||
| 2000 | ProtectHome = true; | ||
| 2001 | ProtectHostname = true; | ||
| 2002 | ProtectKernelLogs = true; | ||
| 2003 | ProtectKernelModules = true; | ||
| 2004 | ProtectKernelTunables = true; | ||
| 2005 | ProtectProc = "invisible"; | ||
| 2006 | ProtectSystem = "full"; | ||
| 2007 | RemoveIPC = true; | ||
| 2008 | RestrictAddressFamilies = [ | ||
| 2009 | "AF_INET" | ||
| 2010 | "AF_INET6" | ||
| 2011 | "AF_UNIX" | ||
| 2012 | ]; | ||
| 2013 | RestrictNamespaces = true; | ||
| 2014 | RestrictRealtime = true; | ||
| 2015 | RestrictSUIDSGID = true; | ||
| 2016 | SystemCallArchitectures = "native"; | ||
| 2017 | SystemCallFilter = [ | ||
| 2018 | "@system-service" | ||
| 2019 | "~@privileged" | ||
| 2020 | ]; | ||
| 2021 | }; | ||
| 2022 | }; | ||
| 2023 | # prometheus-config-reload will activate after prometheus. However, what we | ||
| 2024 | # don't want is that on startup it immediately reloads prometheus because | ||
| 2025 | # prometheus itself might have just started. | ||
| 2026 | # | ||
| 2027 | # Instead we only want to reload prometheus when the config file has | ||
| 2028 | # changed. So on startup prometheus-config-reload will just output a | ||
| 2029 | # harmless message and then stay active (RemainAfterExit). | ||
| 2030 | # | ||
| 2031 | # Then, when the config file has changed, switch-to-configuration notices | ||
| 2032 | # that this service has changed (restartTriggers) and needs to be reloaded | ||
| 2033 | # (reloadIfChanged). The reload command then reloads prometheus. | ||
| 2034 | systemd.services.prometheus-config-reload = mkIf cfg.enableReload { | ||
| 2035 | wantedBy = [ "prometheus.service" ]; | ||
| 2036 | after = [ "prometheus.service" ]; | ||
| 2037 | reloadIfChanged = true; | ||
| 2038 | restartTriggers = [ prometheusYml ]; | ||
| 2039 | serviceConfig = { | ||
| 2040 | Type = "oneshot"; | ||
| 2041 | RemainAfterExit = true; | ||
| 2042 | TimeoutSec = 60; | ||
| 2043 | ExecStart = "${pkgs.logger}/bin/logger 'prometheus-config-reload will only reload prometheus when reloaded itself.'"; | ||
| 2044 | ExecReload = [ "${triggerReload}/bin/trigger-reload-prometheus" ]; | ||
| 2045 | }; | ||
| 2046 | }; | ||
| 2047 | }; | ||
| 2048 | } | ||
diff --git a/modules/uucp.nix b/modules/uucp.nix deleted file mode 100644 index 10f7297b..00000000 --- a/modules/uucp.nix +++ /dev/null | |||
| @@ -1,373 +0,0 @@ | |||
| 1 | { flake, config, lib, pkgs, ... }: | ||
| 2 | |||
| 3 | with lib; | ||
| 4 | |||
| 5 | let | ||
| 6 | portSpec = name: node: concatStringsSep "\n" (map (port: '' | ||
| 7 | port ${name}.${port} | ||
| 8 | type pipe | ||
| 9 | protocol ${node.protocols} | ||
| 10 | reliable true | ||
| 11 | command ${pkgs.openssh}/bin/ssh -x -o batchmode=yes ${name}.${port} | ||
| 12 | '') node.hostnames); | ||
| 13 | sysSpec = name: node: '' | ||
| 14 | system ${name} | ||
| 15 | time any | ||
| 16 | chat-seven-bit false | ||
| 17 | chat . "" | ||
| 18 | protocol ${node.protocols} | ||
| 19 | command-path ${concatStringsSep " " cfg.commandPath} | ||
| 20 | commands ${concatStringsSep " " node.commands} | ||
| 21 | ${concatStringsSep "\nalternate\n" (map (port: '' | ||
| 22 | port ${name}.${port} | ||
| 23 | '') node.hostnames)} | ||
| 24 | ''; | ||
| 25 | sshConfig = name: node: concatStringsSep "\n" (map (port: '' | ||
| 26 | Host ${name}.${port} | ||
| 27 | Hostname ${port} | ||
| 28 | IdentitiesOnly Yes | ||
| 29 | IdentityFile ${cfg.sshKeyDir}/${name} | ||
| 30 | '') node.hostnames); | ||
| 31 | sshKeyGen = name: node: '' | ||
| 32 | if [[ ! -e ${cfg.sshKeyDir}/${name} ]]; then | ||
| 33 | ${pkgs.openssh}/bin/ssh-keygen ${escapeShellArgs node.generateKey} -f ${cfg.sshKeyDir}/${name} | ||
| 34 | fi | ||
| 35 | ''; | ||
| 36 | restrictKey = key: '' | ||
| 37 | restrict,command="${chat}" ${key} | ||
| 38 | ''; | ||
| 39 | chat = pkgs.writeScript "chat" '' | ||
| 40 | #!${pkgs.stdenv.shell} | ||
| 41 | |||
| 42 | echo . | ||
| 43 | exec ${config.security.wrapperDir}/uucico | ||
| 44 | ''; | ||
| 45 | |||
| 46 | nodeCfg = { | ||
| 47 | options = { | ||
| 48 | commands = mkOption { | ||
| 49 | type = types.listOf types.str; | ||
| 50 | default = cfg.defaultCommands; | ||
| 51 | defaultText = literalExpression "config.services.uucp.defaultCommands"; | ||
| 52 | description = "Commands to allow for this remote"; | ||
| 53 | }; | ||
| 54 | |||
| 55 | protocols = mkOption { | ||
| 56 | type = types.separatedString ""; | ||
| 57 | default = cfg.defaultProtocols; | ||
| 58 | defaultText = literalExpression "config.services.uucp.defaultProtocols"; | ||
| 59 | description = "UUCP protocols to use for this remote"; | ||
| 60 | }; | ||
| 61 | |||
| 62 | publicKeys = mkOption { | ||
| 63 | type = types.listOf types.str; | ||
| 64 | default = []; | ||
| 65 | description = "SSH client public keys for this node"; | ||
| 66 | }; | ||
| 67 | |||
| 68 | generateKey = mkOption { | ||
| 69 | type = types.listOf types.str; | ||
| 70 | default = [ "-t" "ed25519" "-N" "" ]; | ||
| 71 | description = "Arguments to pass to `ssh-keygen` to generate a keypair for communication with this host"; | ||
| 72 | }; | ||
| 73 | |||
| 74 | hostnames = mkOption { | ||
| 75 | type = types.listOf types.str; | ||
| 76 | default = []; | ||
| 77 | description = "Hostnames to try in order when connecting"; | ||
| 78 | }; | ||
| 79 | }; | ||
| 80 | }; | ||
| 81 | |||
| 82 | cfg = config.services.uucp; | ||
| 83 | in { | ||
| 84 | options = { | ||
| 85 | services.uucp = { | ||
| 86 | enable = mkOption { | ||
| 87 | type = types.bool; | ||
| 88 | default = false; | ||
| 89 | description = '' | ||
| 90 | If enabled we set up an account accesible via uucp over ssh | ||
| 91 | ''; | ||
| 92 | }; | ||
| 93 | |||
| 94 | nodeName = mkOption { | ||
| 95 | type = types.str; | ||
| 96 | default = "nixos"; | ||
| 97 | description = "uucp node name"; | ||
| 98 | }; | ||
| 99 | |||
| 100 | sshUser = mkOption { | ||
| 101 | type = types.attrs; | ||
| 102 | default = {}; | ||
| 103 | description = "Overrides for the local uucp linux-user"; | ||
| 104 | }; | ||
| 105 | |||
| 106 | extraSSHConfig = mkOption { | ||
| 107 | type = types.str; | ||
| 108 | default = ""; | ||
| 109 | description = "Extra SSH config"; | ||
| 110 | }; | ||
| 111 | |||
| 112 | remoteNodes = mkOption { | ||
| 113 | type = types.attrsOf (types.submodule nodeCfg); | ||
| 114 | default = {}; | ||
| 115 | description = '' | ||
| 116 | Ports to set up | ||
| 117 | Names will probably need to be configured in sshConfig | ||
| 118 | ''; | ||
| 119 | }; | ||
| 120 | |||
| 121 | commandPath = mkOption { | ||
| 122 | type = types.listOf types.path; | ||
| 123 | default = [ "${pkgs.rmail}/bin" ]; | ||
| 124 | defaultText = literalExpression ''[ "''${pkgs.rmail}/bin" ]''; | ||
| 125 | description = '' | ||
| 126 | Command search path for all systems | ||
| 127 | ''; | ||
| 128 | }; | ||
| 129 | |||
| 130 | defaultCommands = mkOption { | ||
| 131 | type = types.listOf types.str; | ||
| 132 | default = ["rmail"]; | ||
| 133 | description = "Commands allowed for remotes without explicit override"; | ||
| 134 | }; | ||
| 135 | |||
| 136 | defaultProtocols = mkOption { | ||
| 137 | type = types.separatedString ""; | ||
| 138 | default = "te"; | ||
| 139 | description = "UUCP protocol to use within ssh unless overriden"; | ||
| 140 | }; | ||
| 141 | |||
| 142 | incomingProtocols = mkOption { | ||
| 143 | type = types.separatedString ""; | ||
| 144 | default = "te"; | ||
| 145 | description = "UUCP protocols to use when called"; | ||
| 146 | }; | ||
| 147 | |||
| 148 | homeDir = mkOption { | ||
| 149 | type = types.path; | ||
| 150 | default = "/var/uucp"; | ||
| 151 | description = "Home of the uucp user"; | ||
| 152 | }; | ||
| 153 | |||
| 154 | sshKeyDir = mkOption { | ||
| 155 | type = types.path; | ||
| 156 | default = "${cfg.homeDir}/.ssh/"; | ||
| 157 | defaultText = literalExpression ''''${config.services.uucp.homeDir}/.ssh/''; | ||
| 158 | description = "Directory to store ssh keypairs"; | ||
| 159 | }; | ||
| 160 | |||
| 161 | spoolDir = mkOption { | ||
| 162 | type = types.path; | ||
| 163 | default = "/var/spool/uucp"; | ||
| 164 | description = "Spool directory"; | ||
| 165 | }; | ||
| 166 | |||
| 167 | lockDir = mkOption { | ||
| 168 | type = types.path; | ||
| 169 | default = "/var/spool/uucp"; | ||
| 170 | description = "Lock directory"; | ||
| 171 | }; | ||
| 172 | |||
| 173 | pubDir = mkOption { | ||
| 174 | type = types.path; | ||
| 175 | default = "/var/spool/uucppublic"; | ||
| 176 | description = "Public directory"; | ||
| 177 | }; | ||
| 178 | |||
| 179 | logFile = mkOption { | ||
| 180 | type = types.path; | ||
| 181 | default = "/var/log/uucp"; | ||
| 182 | description = "Log file"; | ||
| 183 | }; | ||
| 184 | |||
| 185 | statFile = mkOption { | ||
| 186 | type = types.path; | ||
| 187 | default = "/var/log/uucp.stat"; | ||
| 188 | description = "Statistics file"; | ||
| 189 | }; | ||
| 190 | |||
| 191 | debugFile = mkOption { | ||
| 192 | type = types.path; | ||
| 193 | default = "/var/log/uucp.debug"; | ||
| 194 | description = "Debug file"; | ||
| 195 | }; | ||
| 196 | |||
| 197 | interval = mkOption { | ||
| 198 | type = types.nullOr types.str; | ||
| 199 | default = "1h"; | ||
| 200 | description = '' | ||
| 201 | Specification of when to run `uucico' in format used by systemd timers | ||
| 202 | The default is to do so every hour | ||
| 203 | ''; | ||
| 204 | }; | ||
| 205 | |||
| 206 | nmDispatch = mkOption { | ||
| 207 | type = types.bool; | ||
| 208 | default = config.networking.networkmanager.enable; | ||
| 209 | defaultText = literalExpression "config.networking.networkmanager.enable"; | ||
| 210 | description = '' | ||
| 211 | Install a network-manager dispatcher script to automatically | ||
| 212 | call all remotes when networking is available | ||
| 213 | ''; | ||
| 214 | }; | ||
| 215 | |||
| 216 | extraConfig = mkOption { | ||
| 217 | type = types.lines; | ||
| 218 | default = '' | ||
| 219 | run-uuxqt 1 | ||
| 220 | ''; | ||
| 221 | description = "Extra configuration to append verbatim to `/etc/uucp/config'"; | ||
| 222 | }; | ||
| 223 | |||
| 224 | extraSys = mkOption { | ||
| 225 | type = types.lines; | ||
| 226 | default = '' | ||
| 227 | protocol-parameter g packet-size 4096 | ||
| 228 | ''; | ||
| 229 | description = "Extra configuration to prepend verbatim to `/etc/uucp/sys`"; | ||
| 230 | }; | ||
| 231 | }; | ||
| 232 | }; | ||
| 233 | |||
| 234 | config = mkIf cfg.enable { | ||
| 235 | environment.etc."uucp/config" = { | ||
| 236 | text = '' | ||
| 237 | hostname ${cfg.nodeName} | ||
| 238 | |||
| 239 | spool ${cfg.spoolDir} | ||
| 240 | lockdir ${cfg.lockDir} | ||
| 241 | pubdir ${cfg.pubDir} | ||
| 242 | logfile ${cfg.logFile} | ||
| 243 | statfile ${cfg.statFile} | ||
| 244 | debugfile ${cfg.debugFile} | ||
| 245 | |||
| 246 | ${cfg.extraConfig} | ||
| 247 | ''; | ||
| 248 | }; | ||
| 249 | |||
| 250 | users.groups."uucp" = {}; | ||
| 251 | users.users."uucp" = { | ||
| 252 | name = "uucp"; | ||
| 253 | group = "uucp"; | ||
| 254 | isSystemUser = true; | ||
| 255 | isNormalUser = false; | ||
| 256 | createHome = true; | ||
| 257 | home = cfg.homeDir; | ||
| 258 | description = "User for uucp over ssh"; | ||
| 259 | useDefaultShell = true; | ||
| 260 | openssh.authorizedKeys.keys = map restrictKey (concatLists (mapAttrsToList (name: node: node.publicKeys) cfg.remoteNodes)); | ||
| 261 | } // cfg.sshUser; | ||
| 262 | |||
| 263 | system.activationScripts."uucp-sshconfig" = '' | ||
| 264 | mkdir -p ${config.users.users."uucp".home}/.ssh | ||
| 265 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${config.users.users."uucp".home}/.ssh | ||
| 266 | chmod 700 ${config.users.users."uucp".home}/.ssh | ||
| 267 | ln -fs ${builtins.toFile "ssh-config" '' | ||
| 268 | ${concatStringsSep "\n" (mapAttrsToList sshConfig cfg.remoteNodes)} | ||
| 269 | |||
| 270 | ${cfg.extraSSHConfig} | ||
| 271 | ''} ${config.users.users."uucp".home}/.ssh/config | ||
| 272 | |||
| 273 | mkdir -p ${cfg.sshKeyDir} | ||
| 274 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${cfg.sshKeyDir} | ||
| 275 | chmod 700 ${cfg.sshKeyDir} | ||
| 276 | |||
| 277 | ${concatStringsSep "\n" (mapAttrsToList sshKeyGen cfg.remoteNodes)} | ||
| 278 | ''; | ||
| 279 | |||
| 280 | system.activationScripts."uucp-logs" = '' | ||
| 281 | touch ${cfg.logFile} | ||
| 282 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${cfg.logFile} | ||
| 283 | chmod 644 ${cfg.logFile} | ||
| 284 | touch ${cfg.statFile} | ||
| 285 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${cfg.statFile} | ||
| 286 | chmod 644 ${cfg.statFile} | ||
| 287 | touch ${cfg.debugFile} | ||
| 288 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${cfg.debugFile} | ||
| 289 | chmod 644 ${cfg.debugFile} | ||
| 290 | ''; | ||
| 291 | |||
| 292 | environment.etc."uucp/port" = { | ||
| 293 | text = '' | ||
| 294 | port ssh | ||
| 295 | type stdin | ||
| 296 | protocol ${cfg.incomingProtocols} | ||
| 297 | '' + concatStringsSep "\n" (mapAttrsToList portSpec cfg.remoteNodes); | ||
| 298 | }; | ||
| 299 | environment.etc."uucp/sys" = { | ||
| 300 | text = cfg.extraSys + "\n" + concatStringsSep "\n" (mapAttrsToList sysSpec cfg.remoteNodes); | ||
| 301 | }; | ||
| 302 | |||
| 303 | security.wrappers = let | ||
| 304 | wrapper = p: { | ||
| 305 | name = p; | ||
| 306 | value = { | ||
| 307 | source = "${pkgs.uucp}/bin/${p}"; | ||
| 308 | owner = "root"; | ||
| 309 | group = "root"; | ||
| 310 | setuid = true; | ||
| 311 | setgid = false; | ||
| 312 | }; | ||
| 313 | }; | ||
| 314 | in listToAttrs (map wrapper ["uucico" "cu" "uucp" "uuname" "uustat" "uux" "uuxqt"]); | ||
| 315 | |||
| 316 | nixpkgs.overlays = [(self: super: { | ||
| 317 | rmail = super.writeShellScriptBin "rmail" '' | ||
| 318 | # Dummy UUCP rmail command for postfix/qmail systems | ||
| 319 | |||
| 320 | IFS=" " read junk from junk junk junk junk junk junk junk relay | ||
| 321 | |||
| 322 | case "$from" in | ||
| 323 | *[@!]*) ;; | ||
| 324 | *) from="$from@$relay";; | ||
| 325 | esac | ||
| 326 | |||
| 327 | exec ${config.security.wrapperDir}/sendmail -G -i -f "$from" -- "$@" | ||
| 328 | ''; | ||
| 329 | })]; | ||
| 330 | |||
| 331 | environment.systemPackages = with pkgs; [ | ||
| 332 | uucp | ||
| 333 | ]; | ||
| 334 | |||
| 335 | systemd.services."uucico@" = { | ||
| 336 | serviceConfig = { | ||
| 337 | User = "uucp"; | ||
| 338 | Type = "oneshot"; | ||
| 339 | ExecStart = "${config.security.wrapperDir}/uucico -D -S %i"; | ||
| 340 | }; | ||
| 341 | }; | ||
| 342 | |||
| 343 | systemd.timers."uucico@" = { | ||
| 344 | timerConfig.OnActiveSec = cfg.interval; | ||
| 345 | timerConfig.OnUnitActiveSec = cfg.interval; | ||
| 346 | }; | ||
| 347 | |||
| 348 | systemd.targets."multi-user" = { | ||
| 349 | wants = mapAttrsToList (name: node: "uucico@${name}.timer") cfg.remoteNodes; | ||
| 350 | }; | ||
| 351 | |||
| 352 | systemd.kill-user.enable = true; | ||
| 353 | systemd.targets."sleep" = { | ||
| 354 | after = [ "kill-user@uucp.service" ]; | ||
| 355 | wants = [ "kill-user@uucp.service" ]; | ||
| 356 | }; | ||
| 357 | |||
| 358 | networking.networkmanager.dispatcherScripts = optional cfg.nmDispatch { | ||
| 359 | type = "basic"; | ||
| 360 | source = pkgs.writeScript "callRemotes.sh" '' | ||
| 361 | #!${pkgs.stdenv.shell} | ||
| 362 | |||
| 363 | shopt -s extglob | ||
| 364 | |||
| 365 | case "''${2}" in | ||
| 366 | (?(vpn-)up) | ||
| 367 | ${concatStringsSep "\n " (mapAttrsToList (name: node: "${pkgs.systemd}/bin/systemctl start uucico@${name}.service") cfg.remoteNodes)} | ||
| 368 | ;; | ||
| 369 | esac | ||
| 370 | ''; | ||
| 371 | }; | ||
| 372 | }; | ||
| 373 | } | ||
