Compare commits
40 commits
52eb5d90d9
...
03795a46a7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03795a46a7 | ||
|
|
66d6857710 | ||
|
|
d0a8fb0c09 | ||
|
|
855cd7bd9b | ||
|
|
1e5cd75652 | ||
|
|
b2ac4a6ac1 | ||
|
|
590f42d5d9 | ||
|
|
ed10898adb | ||
|
|
c0c528ae29 | ||
|
|
c89b6e7ee9 | ||
|
|
1ba340e2a4 | ||
|
|
6ea0361692 | ||
|
|
3c186a9e56 | ||
|
|
c31063ca56 | ||
|
|
9a5716f2df | ||
|
|
e1530c606f | ||
|
|
53c592abd9 | ||
|
|
93e27dd3e5 | ||
|
|
dd2aa96e25 | ||
|
|
fd02a136ef | ||
|
|
e7cba90a45 | ||
|
|
e9fe620fa9 | ||
|
|
ef8607e38e | ||
|
|
5ef710f8f2 | ||
|
|
d435d8d487 | ||
|
|
9beef4e013 | ||
|
|
641feb1b84 | ||
|
|
8c358daf56 | ||
|
|
334c977988 | ||
|
|
29cff6eee8 | ||
|
|
f91ac73b72 | ||
|
|
5b2eb482df | ||
|
|
582822cd5b | ||
|
|
279e106427 | ||
|
|
a96f976be1 | ||
|
|
9041fe3d69 | ||
|
|
fe6650622f | ||
|
|
ca8c213e74 | ||
|
|
9e3fa025cd | ||
|
|
5bed1bbba1 |
10 changed files with 849 additions and 205 deletions
|
|
@ -1 +0,0 @@
|
|||
/nix/store/1w2s62i701n28sj08gn1445qr4v3vijp-pre-commit-config.json
|
||||
122
flake.lock
generated
122
flake.lock
generated
|
|
@ -15,11 +15,11 @@
|
|||
"uv2nix": "uv2nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772909021,
|
||||
"narHash": "sha256-hcstQ1Z9aQSJM3AVCLb0/OPTicbME9nhP01GiPrOjZM=",
|
||||
"lastModified": 1776085803,
|
||||
"narHash": "sha256-JvvWVbXJYSY8qOReMbAOD4lxcN2cjKV6lg/jLz8CEuY=",
|
||||
"owner": "nix-community",
|
||||
"repo": "authentik-nix",
|
||||
"rev": "7e4730351fb6df479c46a1bf7e23d46a0b0c5d46",
|
||||
"rev": "4370b561c8bafb59773ce3a518506bcf1161dbdb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -47,16 +47,16 @@
|
|||
"authentik-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1772567399,
|
||||
"narHash": "sha256-0Vpf1hj9C8r+rhrCgwoNazpQ+mwgjdjDhuoKCxYQFWw=",
|
||||
"lastModified": 1775573258,
|
||||
"narHash": "sha256-Xq7JGI/8ppIydIuWd9KRJKUrh7UpeniwvZ4NAtXbYJ4=",
|
||||
"owner": "goauthentik",
|
||||
"repo": "authentik",
|
||||
"rev": "0dccbd4193c45c581e9fb7cd89df0c1487510f1f",
|
||||
"rev": "5249546862986202b901c2afd860992ec48c6ef6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "goauthentik",
|
||||
"ref": "version/2026.2.1",
|
||||
"ref": "version/2026.2.2",
|
||||
"repo": "authentik",
|
||||
"type": "github"
|
||||
}
|
||||
|
|
@ -84,11 +84,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773025010,
|
||||
"narHash": "sha256-khlHllTsovXgT2GZ0WxT4+RvuMjNeR5OW0UYeEHPYQo=",
|
||||
"lastModified": 1776613567,
|
||||
"narHash": "sha256-gC9Cp5ibBmGD5awCA9z7xy6MW6iJufhazTYJOiGlCUI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "7b9f7f88ab3b339f8142dc246445abb3c370d3d3",
|
||||
"rev": "32f4236bfc141ae930b5ba2fb604f561fed5219d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -118,25 +118,9 @@
|
|||
"locked": {
|
||||
"lastModified": 1767039857,
|
||||
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
|
||||
"owner": "NixOS",
|
||||
"repo": "flake-compat",
|
||||
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_3": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1761588595,
|
||||
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
|
||||
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -186,9 +170,13 @@
|
|||
},
|
||||
"git-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_2",
|
||||
"flake-compat": [
|
||||
"mailserver",
|
||||
"flake-compat"
|
||||
],
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"mailserver",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
|
|
@ -206,54 +194,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"git-hooks_2": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"mailserver",
|
||||
"flake-compat"
|
||||
],
|
||||
"gitignore": "gitignore_2",
|
||||
"nixpkgs": [
|
||||
"mailserver",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1763319842,
|
||||
"narHash": "sha256-YG19IyrTdnVn0l3DvcUYm85u3PaqBt6tI6VvolcuHnA=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "7275fa67fbbb75891c16d9dee7d88e58aea2d761",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"git-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"mailserver",
|
||||
|
|
@ -278,16 +219,16 @@
|
|||
"mailserver": {
|
||||
"inputs": {
|
||||
"blobs": "blobs",
|
||||
"flake-compat": "flake-compat_3",
|
||||
"git-hooks": "git-hooks_2",
|
||||
"flake-compat": "flake-compat_2",
|
||||
"git-hooks": "git-hooks",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773313890,
|
||||
"narHash": "sha256-NXm/kOAk7HLziH1uWaUbNb9MhDS8yxFfQ8fMK5eN8/A=",
|
||||
"lastModified": 1773912645,
|
||||
"narHash": "sha256-QHzRqq6gh+t3F/QU9DkP7X63dDDcuIQmaDz12p7ANTg=",
|
||||
"ref": "nixos-25.11",
|
||||
"rev": "9cdd6869e513df8153db4b920c8f15d394e150f7",
|
||||
"revCount": 842,
|
||||
"rev": "25e6dbb8fca3b6e779c5a46fd03bd760b2165bb5",
|
||||
"revCount": 843,
|
||||
"type": "git",
|
||||
"url": "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver"
|
||||
},
|
||||
|
|
@ -356,11 +297,11 @@
|
|||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1764020296,
|
||||
"narHash": "sha256-6zddwDs2n+n01l+1TG6PlyokDdXzu/oBmEejcH5L5+A=",
|
||||
"lastModified": 1773831496,
|
||||
"narHash": "sha256-JW2/QPyCVzmouqEp1H9kNa8JXd7xEhlam9sy3TYfhDY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a320ce8e6e2cc6b4397eef214d202a50a4583829",
|
||||
"rev": "826430a188181a750ffa5948daff334039c5d741",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -372,11 +313,11 @@
|
|||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1773222311,
|
||||
"narHash": "sha256-BHoB/XpbqoZkVYZCfXJXfkR+GXFqwb/4zbWnOr2cRcU=",
|
||||
"lastModified": 1776734388,
|
||||
"narHash": "sha256-vl3dkhlE5gzsItuHoEMVe+DlonsK+0836LIRDnm6MXQ=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0590cd39f728e129122770c029970378a79d076a",
|
||||
"rev": "10e7ad5bbcb421fe07e3a4ad53a634b0cd57ffac",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -440,7 +381,6 @@
|
|||
"inputs": {
|
||||
"authentik": "authentik",
|
||||
"disko": "disko",
|
||||
"git-hooks": "git-hooks",
|
||||
"mailserver": "mailserver",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"sops": "sops"
|
||||
|
|
@ -453,11 +393,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773096132,
|
||||
"narHash": "sha256-M3zEnq9OElB7zqc+mjgPlByPm1O5t2fbUrH3t/Hm5Ag=",
|
||||
"lastModified": 1776771786,
|
||||
"narHash": "sha256-DRFGPfFV6hbrfO9a1PH1FkCi7qR5FgjSqsQGGvk1rdI=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "d1ff3b1034d5bab5d7d8086a7803c5a5968cd784",
|
||||
"rev": "bef289e2248991f7afeb95965c82fbcd8ff72598",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
18
flake.nix
18
flake.nix
|
|
@ -18,10 +18,6 @@
|
|||
url = "github:nix-community/disko";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
git-hooks = {
|
||||
url = "github:cachix/git-hooks.nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
|
|
@ -32,7 +28,6 @@
|
|||
mailserver,
|
||||
disko,
|
||||
sops,
|
||||
git-hooks,
|
||||
}:
|
||||
let
|
||||
sshkeys = [
|
||||
|
|
@ -47,12 +42,6 @@
|
|||
devShells.x86_64-linux.default =
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
||||
pre-commit-check = git-hooks.lib.x86_64-linux.run {
|
||||
src = ./.;
|
||||
hooks = {
|
||||
nixfmt-rfc-style.enable = true;
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.mkShell {
|
||||
# Import GPG keys from keys directory
|
||||
|
|
@ -64,15 +53,11 @@
|
|||
# Isolate sops GPG keys to .git/gnupg (optional)
|
||||
# sopsCreateGPGHome = true;
|
||||
|
||||
shellHook = ''
|
||||
${pre-commit-check.shellHook}
|
||||
'';
|
||||
|
||||
nativeBuildInputs = [
|
||||
sops.packages.x86_64-linux.sops-import-keys-hook
|
||||
];
|
||||
|
||||
buildInputs = pre-commit-check.enabledPackages ++ [
|
||||
buildInputs = [
|
||||
pkgs.sops
|
||||
];
|
||||
};
|
||||
|
|
@ -208,6 +193,7 @@
|
|||
[
|
||||
./hosts/${input}
|
||||
./default.nix
|
||||
./modules/monitoring.nix
|
||||
disko.nixosModules.disko
|
||||
authentik.nixosModules.default
|
||||
mailserver.nixosModules.mailserver
|
||||
|
|
|
|||
246
hosts/monitoring/default.nix
Normal file
246
hosts/monitoring/default.nix
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
"${modulesPath}/virtualisation/proxmox-lxc.nix"
|
||||
];
|
||||
|
||||
networking = {
|
||||
hostName = "monitoring";
|
||||
fqdn = "monitoring.adm.htw.stura-dresden.de";
|
||||
interfaces.eth0.ipv4.addresses = [
|
||||
{
|
||||
address = "141.56.51.20";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
defaultGateway = {
|
||||
address = "141.56.51.254";
|
||||
interface = "eth0";
|
||||
};
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [
|
||||
80
|
||||
443
|
||||
4317 # OTLP gRPC (Proxmox)
|
||||
4318 # OTLP HTTP (Proxmox)
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Loki - Log aggregation system
|
||||
services.loki = {
|
||||
enable = true;
|
||||
configuration = {
|
||||
auth_enabled = false;
|
||||
server = {
|
||||
http_listen_port = 3100;
|
||||
grpc_listen_port = 9096;
|
||||
};
|
||||
common = {
|
||||
path_prefix = "/var/lib/loki";
|
||||
storage.filesystem = {
|
||||
chunks_directory = "/var/lib/loki/chunks";
|
||||
rules_directory = "/var/lib/loki/rules";
|
||||
};
|
||||
replication_factor = 1;
|
||||
ring = {
|
||||
instance_addr = "127.0.0.1";
|
||||
kvstore.store = "inmemory";
|
||||
};
|
||||
};
|
||||
limits_config = {
|
||||
ingestion_rate_mb = 32;
|
||||
ingestion_burst_size_mb = 64;
|
||||
per_stream_rate_limit = "32MB";
|
||||
per_stream_rate_limit_burst = "64MB";
|
||||
max_query_series = 100000;
|
||||
retention_period = "672h"; # 28 days
|
||||
};
|
||||
compactor = {
|
||||
retention_enabled = true;
|
||||
working_directory = "/var/lib/loki/compactor";
|
||||
delete_request_store = "filesystem";
|
||||
};
|
||||
schema_config = {
|
||||
configs = [
|
||||
{
|
||||
from = "2024-01-01";
|
||||
store = "tsdb";
|
||||
object_store = "filesystem";
|
||||
schema = "v13";
|
||||
index = {
|
||||
prefix = "index_";
|
||||
period = "24h";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Mimir - Scalable metrics storage
|
||||
services.mimir = {
|
||||
enable = true;
|
||||
configuration = {
|
||||
multitenancy_enabled = false;
|
||||
memberlist = {
|
||||
bind_addr = [ "0.0.0.0" ];
|
||||
bind_port = 7946;
|
||||
advertise_addr = "141.56.51.20";
|
||||
join_members = [ "141.56.51.20:7946" ];
|
||||
};
|
||||
blocks_storage = {
|
||||
backend = "filesystem";
|
||||
filesystem = {
|
||||
dir = "/var/lib/mimir/data";
|
||||
};
|
||||
};
|
||||
compactor = {
|
||||
data_dir = "/var/lib/mimir/compactor";
|
||||
};
|
||||
distributor = {
|
||||
ring = {
|
||||
kvstore.store = "memberlist";
|
||||
};
|
||||
};
|
||||
ingester = {
|
||||
ring = {
|
||||
kvstore.store = "memberlist";
|
||||
replication_factor = 1;
|
||||
};
|
||||
};
|
||||
ruler_storage = {
|
||||
backend = "filesystem";
|
||||
filesystem = {
|
||||
dir = "/var/lib/mimir/rules";
|
||||
};
|
||||
};
|
||||
server = {
|
||||
http_listen_port = 9009;
|
||||
grpc_listen_port = 9095;
|
||||
};
|
||||
limits = {
|
||||
ingestion_rate = 100000;
|
||||
ingestion_burst_size = 200000;
|
||||
max_global_series_per_user = 0;
|
||||
compactor_blocks_retention_period = "672h"; # 28 days
|
||||
};
|
||||
store_gateway = {
|
||||
sharding_ring = {
|
||||
replication_factor = 1;
|
||||
kvstore.store = "memberlist";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Grafana - Visualization and dashboarding
|
||||
services.grafana = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server = {
|
||||
http_addr = "127.0.0.1";
|
||||
http_port = 3000;
|
||||
domain = "mon.adm.htw.stura-dresden.de";
|
||||
root_url = "https://mon.adm.htw.stura-dresden.de";
|
||||
};
|
||||
security = {
|
||||
admin_user = "admin";
|
||||
admin_password = "$__file{/var/lib/grafana/admin_password}";
|
||||
};
|
||||
};
|
||||
provision = {
|
||||
enable = true;
|
||||
datasources.settings.datasources = [
|
||||
{
|
||||
name = "Mimir";
|
||||
type = "prometheus";
|
||||
url = "http://localhost:9009/prometheus";
|
||||
isDefault = true;
|
||||
}
|
||||
{
|
||||
name = "Loki";
|
||||
type = "loki";
|
||||
url = "http://localhost:3100";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Nginx reverse proxy with ACME certificates
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
||||
virtualHosts."log.adm.htw.stura-dresden.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:3100";
|
||||
proxyWebsockets = true;
|
||||
recommendedProxySettings = true;
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."met.adm.htw.stura-dresden.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:9009";
|
||||
recommendedProxySettings = true;
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."mon.adm.htw.stura-dresden.de" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:3000";
|
||||
proxyWebsockets = true;
|
||||
recommendedProxySettings = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Vector - receive OpenTelemetry data from Proxmox and forward to Loki/Mimir
|
||||
services.vector.settings = {
|
||||
sources.proxmox_otlp = {
|
||||
type = "opentelemetry";
|
||||
grpc.address = "0.0.0.0:4317";
|
||||
http.address = "0.0.0.0:4318";
|
||||
};
|
||||
|
||||
transforms.proxmox_normalize_logs = {
|
||||
type = "remap";
|
||||
inputs = [ "proxmox_otlp.logs" ];
|
||||
source = ''
|
||||
.host = string(.resources."host.name") ?? "proxmox"
|
||||
.unit = string(.attributes."service.name") ?? "proxmox"
|
||||
'';
|
||||
};
|
||||
|
||||
transforms.proxmox_normalize_metrics = {
|
||||
type = "remap";
|
||||
inputs = [ "proxmox_otlp.metrics" ];
|
||||
source = ''
|
||||
.tags.host = string(.resources."host.name") ?? "proxmox"
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
stura.monitoring = {
|
||||
extraMetricInputs = [ "proxmox_normalize_metrics" ];
|
||||
extraLogInputs = [ "proxmox_normalize_logs" ];
|
||||
};
|
||||
|
||||
services.openssh.enable = true;
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
|
|
@ -87,6 +87,11 @@
|
|||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
|
||||
commonHttpConfig = ''
|
||||
real_ip_header proxy_protocol;
|
||||
set_real_ip_from 141.56.51.1/32;
|
||||
'';
|
||||
|
||||
logError = ''
|
||||
/dev/null emerg
|
||||
'';
|
||||
|
|
@ -94,9 +99,21 @@
|
|||
virtualHosts.${config.networking.fqdn} = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
extraConfig = ''
|
||||
access_log off;
|
||||
'';
|
||||
listen = [
|
||||
{
|
||||
port = 80;
|
||||
addr = "0.0.0.0";
|
||||
}
|
||||
{
|
||||
port = 443;
|
||||
addr = "0.0.0.0";
|
||||
ssl = true;
|
||||
proxyProtocol = true;
|
||||
}
|
||||
];
|
||||
# extraConfig = ''
|
||||
# access_log off;
|
||||
# '';
|
||||
};
|
||||
# virtualHosts."cloud.htw.stura-dresden.de" = {
|
||||
# forceSSL = true;
|
||||
|
|
|
|||
|
|
@ -20,25 +20,99 @@
|
|||
}
|
||||
];
|
||||
defaultGateway.address = "141.56.51.254";
|
||||
firewall = {
|
||||
allowedTCPPorts = [
|
||||
22
|
||||
53 # DNS
|
||||
80
|
||||
443
|
||||
1005
|
||||
2142
|
||||
];
|
||||
allowedUDPPorts = [
|
||||
53 # DNS
|
||||
123 # NTP
|
||||
];
|
||||
};
|
||||
firewall.enable = false;
|
||||
nftables = {
|
||||
enable = true;
|
||||
ruleset = ''
|
||||
table inet filter {
|
||||
set blacklist4 {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
# manage: nft add element inet filter blacklist4 { 1.2.3.0/24 }
|
||||
}
|
||||
|
||||
set blacklist6 {
|
||||
type ipv6_addr
|
||||
flags interval
|
||||
# manage: nft add element inet filter blacklist6 { 2001:db8::/32 }
|
||||
}
|
||||
|
||||
chain input {
|
||||
type filter hook input priority filter; policy drop;
|
||||
|
||||
iif "lo" accept
|
||||
ct state established,related accept
|
||||
|
||||
ip saddr 141.56.51.0/24 accept
|
||||
ip saddr @blacklist4 drop
|
||||
ip6 saddr @blacklist6 drop
|
||||
|
||||
# public ports
|
||||
tcp dport { 80, 443, 1005, 2142 } accept
|
||||
|
||||
# lan-only: dns and ntp
|
||||
ip saddr 141.56.51.0/24 tcp dport 53 accept
|
||||
ip saddr 141.56.51.0/24 udp dport { 53, 123 } accept
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority filter; policy drop;
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority filter; policy accept;
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# Phase 1: Kernel-Level TCP Tuning
|
||||
boot.kernel.sysctl = {
|
||||
# Connection tracking - prevents "table full" errors
|
||||
"net.netfilter.nf_conntrack_max" = 262144; # Conservative limit matching current kernel
|
||||
"net.netfilter.nf_conntrack_buckets" = 65536; # 4:1 ratio
|
||||
|
||||
# Reduce connection tracking timeouts (defaults are excessive)
|
||||
"net.netfilter.nf_conntrack_tcp_timeout_established" = 600; # 10 min (down from 5 days)
|
||||
"net.netfilter.nf_conntrack_tcp_timeout_time_wait" = 30; # 30s
|
||||
"net.netfilter.nf_conntrack_tcp_timeout_close_wait" = 15; # 15s
|
||||
"net.netfilter.nf_conntrack_tcp_timeout_fin_wait" = 30; # 30s
|
||||
|
||||
# TCP connection handling
|
||||
"net.core.somaxconn" = 65535; # Must be >= HAProxy maxconn
|
||||
"net.core.netdev_max_backlog" = 16384;
|
||||
"net.ipv4.tcp_max_syn_backlog" = 8192;
|
||||
|
||||
# TCP buffer auto-tuning (16MB max)
|
||||
"net.ipv4.tcp_rmem" = "4096 87380 16777216";
|
||||
"net.ipv4.tcp_wmem" = "4096 65536 16777216";
|
||||
"net.core.rmem_max" = 16777216;
|
||||
"net.core.wmem_max" = 16777216;
|
||||
|
||||
# TCP optimization
|
||||
"net.ipv4.tcp_fin_timeout" = 15;
|
||||
"net.ipv4.tcp_keepalive_time" = 300; # 5 min
|
||||
"net.ipv4.tcp_keepalive_probes" = 3;
|
||||
"net.ipv4.tcp_keepalive_intvl" = 15;
|
||||
|
||||
# TCP Fast Open
|
||||
"net.ipv4.tcp_fastopen" = 3;
|
||||
|
||||
# BBR congestion control for better throughput
|
||||
"net.ipv4.tcp_congestion_control" = "bbr";
|
||||
"net.core.default_qdisc" = "fq";
|
||||
|
||||
# Ephemeral port range
|
||||
"net.ipv4.ip_local_port_range" = "10000 65535";
|
||||
|
||||
# TIME_WAIT socket reuse
|
||||
"net.ipv4.tcp_tw_reuse" = 1;
|
||||
};
|
||||
|
||||
# Enable BBR kernel module
|
||||
boot.kernelModules = [ "tcp_bbr" ];
|
||||
|
||||
# wenn instanzen in die flake migriert sind könnte man das autogenerierien
|
||||
services =
|
||||
let
|
||||
|
|
@ -52,96 +126,112 @@
|
|||
domain = "docs.adm.htw.stura-dresden.de";
|
||||
httpPort = 8080;
|
||||
httpsPort = 8443;
|
||||
sendProxy = false;
|
||||
};
|
||||
plone = {
|
||||
dest = "141.56.51.3";
|
||||
domain = "stura.htw-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = true;
|
||||
};
|
||||
plone_alt = {
|
||||
dest = "141.56.51.3";
|
||||
domain = "www.stura.htw-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = true;
|
||||
};
|
||||
plone_neu = {
|
||||
dest = "141.56.51.3";
|
||||
domain = "www.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = true;
|
||||
};
|
||||
plone_neu2 = {
|
||||
dest = "141.56.51.3";
|
||||
domain = "htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = true;
|
||||
};
|
||||
tix = {
|
||||
dest = "141.56.51.220";
|
||||
domain = "tix.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = false;
|
||||
};
|
||||
post = {
|
||||
dest = "141.56.51.56";
|
||||
domain = "post.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = false;
|
||||
};
|
||||
vot = {
|
||||
dest = "141.56.51.57";
|
||||
domain = "vot.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = false;
|
||||
};
|
||||
mail = {
|
||||
dest = "141.56.51.14";
|
||||
domain = "mail.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = false;
|
||||
};
|
||||
lists = {
|
||||
dest = "141.56.51.14";
|
||||
domain = "lists.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = false;
|
||||
};
|
||||
dat = {
|
||||
dest = "141.56.51.17";
|
||||
domain = "dat.stu.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
};
|
||||
pro = {
|
||||
dest = "141.56.51.15";
|
||||
domain = "pro.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
};
|
||||
cloud = {
|
||||
dest = "141.56.51.16";
|
||||
domain = "cloud.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = false;
|
||||
};
|
||||
wiki = {
|
||||
dest = "141.56.51.13";
|
||||
domain = "wiki.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = true;
|
||||
};
|
||||
beach = {
|
||||
dest = "141.56.51.51";
|
||||
domain = "beach.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = false;
|
||||
};
|
||||
studicloud = {
|
||||
dest = "141.56.51.17";
|
||||
domain = "dat.stu.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = false;
|
||||
};
|
||||
bbb = {
|
||||
dest = "141.56.51.94";
|
||||
domain = "bbb.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = false;
|
||||
};
|
||||
bbb-test = {
|
||||
dest = "141.56.51.94";
|
||||
domain = "bbb.test.htw.stura-dresden.de";
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
sendProxy = false;
|
||||
};
|
||||
}
|
||||
# zusätzlich zu den oben definierten wird hier noch ein redirect für jeden nginx virtualhost in diese flake generiert
|
||||
|
|
@ -160,6 +250,15 @@
|
|||
prev
|
||||
// (builtins.foldl' (
|
||||
val: vhost:
|
||||
let
|
||||
proxyProtocol =
|
||||
if
|
||||
self.nixosConfigurations.${name}.config.services.nginx.virtualHosts.${vhost}.listen == [ ]
|
||||
then
|
||||
false
|
||||
else
|
||||
true;
|
||||
in
|
||||
val
|
||||
// {
|
||||
"${vhost}" = {
|
||||
|
|
@ -167,6 +266,7 @@
|
|||
domain = vhost;
|
||||
httpsPort = 443;
|
||||
httpPort = 80;
|
||||
sendProxy = proxyProtocol;
|
||||
};
|
||||
}
|
||||
) { } vhosts)
|
||||
|
|
@ -223,43 +323,43 @@
|
|||
"127.0.0.1"
|
||||
];
|
||||
listenOnIpv6 = [ ];
|
||||
zones = {
|
||||
"htw.stura-dresden.de" = {
|
||||
master = true;
|
||||
file = pkgs.writeText "htw.stura-dresden.de.zone" ''
|
||||
$TTL 3600
|
||||
@ IN SOA proxy.htw.stura-dresden.de. hostmaster.htw.stura-dresden.de. (
|
||||
2026031301 ; Serial (YYYYMMDDNN)
|
||||
3600 ; Refresh (1 hour)
|
||||
1800 ; Retry (30 minutes)
|
||||
604800 ; Expire (1 week)
|
||||
86400 ) ; Minimum TTL (1 day)
|
||||
|
||||
; Name servers
|
||||
@ IN NS proxy.htw.stura-dresden.de.
|
||||
|
||||
; Proxy host - main IPv4 gateway
|
||||
proxy IN A 141.56.51.1
|
||||
proxy IN AAAA 2a01:4f8:1c19:96f8::1
|
||||
|
||||
; Auto-generated CNAME records for all subdomains pointing to proxy
|
||||
${lib.foldlAttrs (
|
||||
prev: name: value:
|
||||
let
|
||||
zoneSuffix = ".htw.stura-dresden.de";
|
||||
# Check if this domain belongs to our zone
|
||||
isInZone = lib.hasSuffix zoneSuffix value.domain;
|
||||
# Extract subdomain by removing the zone suffix
|
||||
subdomain = lib.removeSuffix zoneSuffix value.domain;
|
||||
in
|
||||
if isInZone && subdomain != "" && subdomain != "htw.stura-dresden.de" then
|
||||
prev + "${subdomain}${" "}IN${" "}CNAME${" "}proxy.htw.stura-dresden.de.\n"
|
||||
else
|
||||
prev
|
||||
) "" forwards}
|
||||
'';
|
||||
};
|
||||
};
|
||||
# zones = {
|
||||
# "htw.stura-dresden.de" = {
|
||||
# master = true;
|
||||
# file = pkgs.writeText "htw.stura-dresden.de.zone" ''
|
||||
# $TTL 3600
|
||||
# @ IN SOA proxy.htw.stura-dresden.de. hostmaster.htw.stura-dresden.de. (
|
||||
# 2026031301 ; Serial (YYYYMMDDNN)
|
||||
# 3600 ; Refresh (1 hour)
|
||||
# 1800 ; Retry (30 minutes)
|
||||
# 604800 ; Expire (1 week)
|
||||
# 86400 ) ; Minimum TTL (1 day)
|
||||
#
|
||||
# ; Name servers
|
||||
# @ IN NS proxy.htw.stura-dresden.de.
|
||||
#
|
||||
# ; Proxy host - main IPv4 gateway
|
||||
# proxy IN A 141.56.51.1
|
||||
# proxy IN AAAA 2a01:4f8:1c19:96f8::1
|
||||
#
|
||||
# ; Auto-generated CNAME records for all subdomains pointing to proxy
|
||||
# ${lib.foldlAttrs (
|
||||
# prev: name: value:
|
||||
# let
|
||||
# zoneSuffix = ".htw.stura-dresden.de";
|
||||
# # Check if this domain belongs to our zone
|
||||
# isInZone = lib.hasSuffix zoneSuffix value.domain;
|
||||
# # Extract subdomain by removing the zone suffix
|
||||
# subdomain = lib.removeSuffix zoneSuffix value.domain;
|
||||
# in
|
||||
# if isInZone && subdomain != "" && subdomain != "htw.stura-dresden.de" then
|
||||
# prev + "${subdomain}${" "}IN${" "}CNAME${" "}proxy.htw.stura-dresden.de.\n"
|
||||
# else
|
||||
# prev
|
||||
# ) "" forwards}
|
||||
# '';
|
||||
# };
|
||||
# };
|
||||
};
|
||||
|
||||
# Chrony NTP server for the internal network
|
||||
|
|
@ -335,18 +435,35 @@
|
|||
global
|
||||
# schreibe globalen log ins journal ip -> app
|
||||
log /dev/log format raw local0
|
||||
maxconn 50000
|
||||
# man könnte metriken über einen socket file statt einen lokalen port machen für user permission control
|
||||
# stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
|
||||
tune.bufsize 32762
|
||||
maxconn 60000 # Safe limit below kernel conntrack (262144)
|
||||
|
||||
# Buffer optimizations (Phase 2)
|
||||
tune.bufsize 32768 # Power of 2 (was 32762)
|
||||
tune.maxrewrite 8192
|
||||
|
||||
# Connection handling
|
||||
tune.maxaccept 500 # Prevent accept starvation
|
||||
tune.maxpollevents 300
|
||||
|
||||
# TCP buffer sizes (64KB)
|
||||
tune.rcvbuf.client 65536
|
||||
tune.rcvbuf.server 65536
|
||||
tune.sndbuf.client 65536
|
||||
tune.sndbuf.server 65536
|
||||
|
||||
defaults
|
||||
log global
|
||||
mode tcp
|
||||
option tcplog
|
||||
timeout connect 5s
|
||||
timeout client 30s
|
||||
timeout server 30s
|
||||
|
||||
# Optimized timeouts (Phase 5)
|
||||
timeout connect 3s # Reduce from 5s
|
||||
timeout client 60s # Increase from 30s
|
||||
timeout server 60s # Increase from 30s
|
||||
timeout queue 5s # Prevent indefinite queueing
|
||||
|
||||
# Performance
|
||||
option splice-auto # Zero-copy kernel splicing
|
||||
|
||||
# stats seite zeigt backend connection status, wenn check gesetzt ist
|
||||
frontend stats
|
||||
|
|
@ -354,13 +471,21 @@
|
|||
mode http
|
||||
stats enable
|
||||
stats uri /stats
|
||||
stats refresh 10s
|
||||
stats refresh 5s # Reduce from 10s for real-time monitoring
|
||||
stats show-legends
|
||||
stats show-node
|
||||
stats show-modules
|
||||
stats admin if TRUE # Enable admin operations
|
||||
http-request use-service prometheus-exporter if { path /metrics }
|
||||
|
||||
frontend http-in
|
||||
bind *:80
|
||||
mode http
|
||||
tcp-request connection expect-proxy layer4 if { src 178.104.18.93 }
|
||||
maxconn 60000
|
||||
backlog 8192
|
||||
option dontlognull
|
||||
option http-keep-alive # Reuse connections for redirects
|
||||
|
||||
# hier wird eine regel pro domain aus der forwarder liste generiert
|
||||
${lib.foldlAttrs (
|
||||
|
|
@ -379,8 +504,8 @@
|
|||
prev: name: value:
|
||||
prev
|
||||
+ ''
|
||||
use_backend ${name}_80 if is_${name}
|
||||
http-request redirect scheme https code 301 if !is_acme is_${name}
|
||||
use_backend ${name}_80 if is_${name}
|
||||
''
|
||||
) "" forwards}
|
||||
|
||||
|
|
@ -401,10 +526,18 @@
|
|||
frontend sni_router
|
||||
bind *:443
|
||||
mode tcp
|
||||
# mehrere pakete puffern und connection beenden wenn es kein ssl handshake sieht
|
||||
tcp-request inspect-delay 1s
|
||||
tcp-request connection expect-proxy layer4 if { src 178.104.18.93 }
|
||||
|
||||
# Reduce inspection delay - SNI is in first packet (Phase 3)
|
||||
tcp-request inspect-delay 500ms # Was 1s
|
||||
tcp-request content accept if { req_ssl_hello_type 1 }
|
||||
|
||||
# Connection handling
|
||||
option clitcpka # Enable client TCP keep-alive
|
||||
maxconn 60000
|
||||
backlog 16384 # Increase from default 1024
|
||||
option dontlognull # Skip logging of monitoring probes
|
||||
|
||||
# tcp redirect der anwendung basierend auf ssl_sni handshake parameter
|
||||
${lib.foldlAttrs (
|
||||
prev: name: value:
|
||||
|
|
@ -435,13 +568,117 @@
|
|||
server ${name} ${value.dest}:${builtins.toString value.httpPort}
|
||||
backend ${name}_443
|
||||
mode tcp
|
||||
server ${name} ${value.dest}:${builtins.toString value.httpsPort} check
|
||||
option tcpka # Enable server TCP keep-alive (Phase 4)
|
||||
timeout server 60s # Increase from 30s for long-lived HTTPS
|
||||
timeout connect 3s # Reduce from 5s (local network)
|
||||
server ${name} ${value.dest}:${builtins.toString value.httpsPort} ${
|
||||
if value.sendProxy == true then "send-proxy-v2" else ""
|
||||
} check inter 3000 rise 2 fall 3 maxconn 5000
|
||||
|
||||
''
|
||||
) "" forwards}
|
||||
'';
|
||||
};
|
||||
vector.settings = {
|
||||
enrichment_tables.geoip_table = {
|
||||
type = "mmdb";
|
||||
path = "/var/lib/GeoIP/GeoLite2-City.mmdb";
|
||||
};
|
||||
sources.haproxy_metrics = {
|
||||
type = "prometheus_scrape";
|
||||
endpoints = [ "http://127.0.0.1:8404/metrics" ];
|
||||
scrape_interval_secs = 15;
|
||||
};
|
||||
transforms = {
|
||||
add_host_label_haproxy = {
|
||||
type = "remap";
|
||||
inputs = [ "haproxy_metrics" ];
|
||||
source = ''
|
||||
.tags.host = get_hostname!()
|
||||
'';
|
||||
};
|
||||
haproxy_logs_filter = {
|
||||
type = "filter";
|
||||
inputs = [ "journald_logs" ];
|
||||
condition = ''."_SYSTEMD_UNIT" == "haproxy.service"'';
|
||||
};
|
||||
haproxy_logs_parse = {
|
||||
type = "remap";
|
||||
inputs = [ "haproxy_logs_filter" ];
|
||||
source = ''
|
||||
.host = get_hostname!()
|
||||
.unit = "haproxy"
|
||||
# IPv4: "1.2.3.4:port" IPv6: "[2001:db8::1]:port"
|
||||
parsed, err = parse_regex(.message, r'^(?:\[(?P<ipv6>[0-9a-fA-F:]+)\]|(?P<ipv4>[\d.]+)):\d+')
|
||||
if err == null {
|
||||
if is_null(parsed.ipv6) {
|
||||
.client_ip = parsed.ipv4
|
||||
} else {
|
||||
.client_ip = parsed.ipv6
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
haproxy_geoip = {
|
||||
type = "remap";
|
||||
inputs = [ "haproxy_logs_parse" ];
|
||||
source = ''
|
||||
if exists(.client_ip) && !is_null(.client_ip) {
|
||||
.geoip = get_enrichment_table_record("geoip_table", {"ip": string!(.client_ip)}) ?? {}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
sinks.mimir.inputs = lib.mkForce [
|
||||
"add_host_label_metrics"
|
||||
"add_host_label_haproxy"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
stura.monitoring.extraLogInputs = [ "haproxy_geoip" ];
|
||||
|
||||
users.users.root.packages = [
|
||||
(pkgs.writeShellScriptBin "nft-blacklist" ''
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
echo "Usage: nft-blacklist <add|del> <ip-or-cidr>"
|
||||
echo " add - add entry to blacklist set"
|
||||
echo " del - remove entry from blacklist set"
|
||||
exit 1
|
||||
}
|
||||
|
||||
[[ $# -ne 2 ]] && usage
|
||||
|
||||
ACTION="$1"
|
||||
ADDR="$2"
|
||||
|
||||
if [[ "$ADDR" == *:* ]]; then
|
||||
SET="blacklist6"
|
||||
elif [[ "$ADDR" == *.* ]]; then
|
||||
SET="blacklist4"
|
||||
else
|
||||
echo "Error: cannot determine address family for '$ADDR'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$ACTION" in
|
||||
add)
|
||||
${pkgs.nftables}/bin/nft add element inet filter "$SET" "{ $ADDR }"
|
||||
echo "Added $ADDR to $SET"
|
||||
;;
|
||||
del)
|
||||
${pkgs.nftables}/bin/nft delete element inet filter "$SET" "{ $ADDR }"
|
||||
echo "Removed $ADDR from $SET"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
'')
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
];
|
||||
|
|
|
|||
|
|
@ -90,7 +90,9 @@
|
|||
services.redmine.settings.production.email_delivery = {
|
||||
delivery_method = ":smtp";
|
||||
smtp_settings = {
|
||||
address = "mail.${config.networking.domain}";
|
||||
# @tan 27-03-2026: muss an "alten" mailserver senden
|
||||
#address = "mail.${config.networking.domain}";
|
||||
address = "mail.stura.htw-dresden.de";
|
||||
port = 25;
|
||||
};
|
||||
#### Alternativ waere vielleicht auch das Versand von Mails durch das Programm sendmail (als lokale Installation) moeglich.
|
||||
|
|
@ -132,13 +134,29 @@
|
|||
|
||||
#### Der StuRa speichert nicht!
|
||||
services.nginx.logError = ''/dev/null emerg'';
|
||||
services.nginx.appendHttpConfig = ''
|
||||
access_log off;
|
||||
# services.nginx.appendHttpConfig = ''
|
||||
# access_log off;
|
||||
# '';
|
||||
services.nginx.commonHttpConfig = ''
|
||||
real_ip_header proxy_protocol;
|
||||
set_real_ip_from 141.56.51.1/32;
|
||||
'';
|
||||
|
||||
#### Anscheinend kann mit nix nur die Konfiguration fuer eine konkrete (manuelle) Konfiguration fuer den Dienst web server.
|
||||
services.nginx.virtualHosts."${config.networking.fqdn}" = {
|
||||
#### https://search.nixos.org/options?show=services.nginx.virtualHosts.<name>.default
|
||||
listen = [
|
||||
{
|
||||
port = 80;
|
||||
addr = "0.0.0.0";
|
||||
}
|
||||
{
|
||||
port = 443;
|
||||
addr = "0.0.0.0";
|
||||
ssl = true;
|
||||
proxyProtocol = true;
|
||||
}
|
||||
];
|
||||
default = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString config.services.redmine.port}";
|
||||
|
|
|
|||
|
|
@ -38,15 +38,44 @@
|
|||
"9.9.9.9"
|
||||
"1.1.1.1"
|
||||
];
|
||||
firewall = {
|
||||
allowedTCPPorts = [
|
||||
22
|
||||
80
|
||||
443
|
||||
];
|
||||
};
|
||||
firewall.enable = false;
|
||||
nftables = {
|
||||
enable = true;
|
||||
ruleset = ''
|
||||
table inet filter {
|
||||
set blacklist4 {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
# manage at runtime: nft add element inet filter blacklist4 { 1.2.3.0/24 }
|
||||
}
|
||||
|
||||
set blacklist6 {
|
||||
type ipv6_addr
|
||||
flags interval
|
||||
# manage at runtime: nft add element inet filter blacklist6 { 2001:db8::/32 }
|
||||
}
|
||||
|
||||
chain input {
|
||||
type filter hook input priority filter; policy drop;
|
||||
|
||||
iif "lo" accept
|
||||
ct state established,related accept
|
||||
|
||||
ip saddr @blacklist4 drop
|
||||
ip6 saddr @blacklist6 drop
|
||||
|
||||
tcp dport { 22, 80, 443 } accept
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority filter; policy drop;
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority filter; policy accept;
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -96,12 +125,50 @@
|
|||
server proxy 141.56.51.1:80
|
||||
backend http_443
|
||||
mode tcp
|
||||
server proxy 141.56.51.1:443
|
||||
server proxy 141.56.51.1:443 send-proxy-v2
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
users.users.root.packages = [
|
||||
(pkgs.writeShellScriptBin "nft-blacklist" ''
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
echo "Usage: nft-blacklist <add|del> <ip-or-cidr>"
|
||||
echo " add - add entry to blacklist set"
|
||||
echo " del - remove entry from blacklist set"
|
||||
exit 1
|
||||
}
|
||||
|
||||
[[ $# -ne 2 ]] && usage
|
||||
|
||||
ACTION="$1"
|
||||
ADDR="$2"
|
||||
|
||||
if [[ "$ADDR" == *:* ]]; then
|
||||
SET="blacklist6"
|
||||
elif [[ "$ADDR" == *.* ]]; then
|
||||
SET="blacklist4"
|
||||
else
|
||||
echo "Error: cannot determine address family for '$ADDR'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$ACTION" in
|
||||
add)
|
||||
${pkgs.nftables}/bin/nft add element inet filter "$SET" "{ $ADDR }"
|
||||
echo "Added $ADDR to $SET"
|
||||
;;
|
||||
del)
|
||||
${pkgs.nftables}/bin/nft delete element inet filter "$SET" "{ $ADDR }"
|
||||
echo "Removed $ADDR from $SET"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
'')
|
||||
];
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
|
|
|
|||
|
|
@ -99,6 +99,17 @@
|
|||
services.mediawiki.database.passwordFile = "/var/lib/mediawiki/mediawiki-dbpassword";
|
||||
|
||||
|
||||
services.httpd = {
|
||||
extraModules = [ "remoteip" ];
|
||||
|
||||
extraConfig = ''
|
||||
# Trust HAProxy's address (adjust to your HAProxy IP/subnet)
|
||||
RemoteIPProxyProtocol On
|
||||
# RemoteIPProxyProtocolExceptions 127.0.0.1 ::1
|
||||
|
||||
RemoteIPTrustedProxy 141.56.51.1/32
|
||||
'';
|
||||
};
|
||||
#### 2024-02-17 vater:
|
||||
#### trace: warning: The option `services.mediawiki.virtualHost' defined in `/etc/nixos/configuration.nix' has been renamed to `services.mediawiki.httpd.virtualHost'.
|
||||
# services.mediawiki.virtualHost.hostName = "wiki.stura.htw-dresden.de";
|
||||
|
|
@ -150,8 +161,8 @@
|
|||
Lockdown = pkgs.fetchzip {
|
||||
# url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_43-7ac8966.tar.gz";
|
||||
# url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_44-af1f4df.tar.gz";
|
||||
url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_45-a46dbea.tar.gz";
|
||||
sha256 = "sha256-zTTpbQiqudLILPSzmKGjKr6wZjh0YUttGmqwjPpAToc=";
|
||||
url = "https://extdist.wmflabs.org/dist/extensions/CategoryLockdown-REL1_45-a715472.tar.gz";
|
||||
sha256 = "sha256-1gl5m9xkmLrdjoR0M13gcQHLtZt4Bt0PUXDiDEqjpvk=";
|
||||
};
|
||||
|
||||
#### Hinzufuegen der Erweiterung ConfirmEdit fuer eine zusaetzliche Bestaetigung bei Bearbeitungen, etwa um Herausforderungen (aka CAPTCHA) zu stellen
|
||||
|
|
@ -168,8 +179,8 @@
|
|||
#### Hinzufuegen der Erweiterung ContributionScores fuer eine Statistik von Beitraegen nach Beitragenden
|
||||
#### https://www.mediawiki.org/wiki/Extension:ContributionScores
|
||||
ContributionScores = pkgs.fetchzip {
|
||||
url = "https://extdist.wmflabs.org/dist/extensions/ContributionScores-REL1_45-cd4c94b.tar.gz";
|
||||
sha256 = "sha256-8ClNtEQ66deKM1DsRYaaZ3KlRl4yCt6UhpXcozRQzQ8=";
|
||||
url = "https://extdist.wmflabs.org/dist/extensions/ContributionCredits-REL1_45-22c28de.tar.gz";
|
||||
sha256 = "sha256-9T67jCEYQyU7P9sN7tYbnevU5+FX6Y1nydXGEdzQS9k=";
|
||||
};
|
||||
|
||||
#### Hinzufuegen der Erweiterung Interwiki fuer das Verwenden von Verweisen als eine Art Namensraum, wie beispielweise auf Wikipedia oder selbst festgelegte Verweise
|
||||
|
|
@ -190,8 +201,8 @@
|
|||
#### https://www.mediawiki.org/wiki/Extension:UserMerge
|
||||
UserMerge = pkgs.fetchzip {
|
||||
# url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_43-ed4a689.tar.gz";
|
||||
url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-446566b.tar.gz";
|
||||
sha256 = "sha256-DTDKlzet3lThh/sRLucyb8b9lhK5FYZ+dMgwrThFFBM=";
|
||||
url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-433f6c2.tar.gz";
|
||||
sha256 = "sha256-JyY4pJNBKQ9bOKrilPWCheZ5ihWwPM6ZJ0qHsZ3coPk=";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
123
modules/monitoring.nix
Normal file
123
modules/monitoring.nix
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
{ pkgs, lib, config, ... }:
|
||||
let
|
||||
cfg = config.stura.monitoring;
|
||||
in {
|
||||
options.stura.monitoring = {
|
||||
extraLogFiles = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "Additional log file paths for vector to scrape and forward to Loki.";
|
||||
example = [ "/var/log/nginx/access.log" "/var/log/nginx/error.log" ];
|
||||
};
|
||||
|
||||
extraGroups = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "Supplementary groups added to the vector systemd service to allow reading protected log files.";
|
||||
example = [ "nginx" "postfix" ];
|
||||
};
|
||||
|
||||
extraMetricInputs = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "Additional vector component IDs to feed into the mimir sink alongside host_metrics.";
|
||||
example = [ "proxmox_normalize_metrics" ];
|
||||
};
|
||||
|
||||
extraLogInputs = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "Additional vector component IDs to feed into the loki sink alongside journald_logs.";
|
||||
example = [ "proxmox_normalize_logs" ];
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
networking.hosts = {
|
||||
# rewrite these host entries on each system, this does not go through proxy
|
||||
"141.56.51.20" = [
|
||||
"mon.adm.htw.stura-dresden.de"
|
||||
"log.adm.htw.stura-dresden.de"
|
||||
"met.adm.htw.stura-dresden.de"
|
||||
];
|
||||
};
|
||||
services.vector = {
|
||||
enable = true;
|
||||
settings = {
|
||||
sources = {
|
||||
host_metrics = {
|
||||
type = "host_metrics";
|
||||
collectors = [
|
||||
"cpu"
|
||||
"disk"
|
||||
"filesystem"
|
||||
"load"
|
||||
"host"
|
||||
"memory"
|
||||
"network"
|
||||
"process"
|
||||
];
|
||||
};
|
||||
|
||||
journald_logs = {
|
||||
type = "journald";
|
||||
include_units = []; # empty = collect all units
|
||||
};
|
||||
} // lib.optionalAttrs (cfg.extraLogFiles != [] || config.services.nginx.enable) {
|
||||
extra_log_files = {
|
||||
type = "file";
|
||||
include = lib.optional config.services.nginx.enable "/var/log/nginx/access.log"
|
||||
++ cfg.extraLogFiles;
|
||||
};
|
||||
};
|
||||
|
||||
transforms = {
|
||||
add_host_label_metrics = {
|
||||
type = "remap";
|
||||
inputs = [ "host_metrics" ];
|
||||
source = ''
|
||||
.tags.host = get_hostname!()
|
||||
del(.tags.command)
|
||||
'';
|
||||
};
|
||||
|
||||
add_host_label_logs = {
|
||||
type = "remap";
|
||||
inputs = [ "journald_logs" ] ++ lib.optional (cfg.extraLogFiles != [] || config.services.nginx.enable) "extra_log_files";
|
||||
source = ''
|
||||
.host = get_hostname!()
|
||||
.unit = string(."_SYSTEMD_UNIT") ?? "file"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
sinks = {
|
||||
mimir = {
|
||||
type = "prometheus_remote_write";
|
||||
inputs = [ "add_host_label_metrics" ] ++ cfg.extraMetricInputs;
|
||||
endpoint = "https://met.adm.htw.stura-dresden.de/api/v1/push";
|
||||
tls.verify_certificate = false;
|
||||
healthcheck.enabled = false;
|
||||
};
|
||||
|
||||
loki = {
|
||||
type = "loki";
|
||||
inputs = [ "add_host_label_logs" ] ++ cfg.extraLogInputs;
|
||||
endpoint = "https://log.adm.htw.stura-dresden.de";
|
||||
labels = {
|
||||
host = "{{ host }}";
|
||||
unit = "{{ unit }}";
|
||||
};
|
||||
tls.verify_certificate = false;
|
||||
encoding.codec = "json";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.vector.serviceConfig.SupplementaryGroups =
|
||||
[ "systemd-journal" ]
|
||||
++ lib.optional config.services.nginx.enable "nginx"
|
||||
++ cfg.extraGroups;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue