feat: z2m!
This commit is contained in:
parent
f923a0e25a
commit
3c067ad506
8 changed files with 338 additions and 208 deletions
|
@ -14,7 +14,6 @@
|
|||
|
||||
|
||||
|
||||
|
||||
};
|
||||
mySystem.system.systemd.pushover-alerts.enable = false;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
redlib.enable = true;
|
||||
|
||||
mosquitto.enable = true;
|
||||
zigbee2mqtt.enable = true;
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -70,12 +70,6 @@ in
|
|||
};
|
||||
environmentFiles = [ config.sops.secrets."services/${app}/env".path ];
|
||||
ports = [ (builtins.toString port) ]; # expose port
|
||||
labels = lib.myLib.mkTraefikLabels {
|
||||
name = app;
|
||||
domain = config.networking.domain;
|
||||
|
||||
inherit port;
|
||||
};
|
||||
};
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
|
||||
|
|
|
@ -16,5 +16,6 @@
|
|||
./powerdns
|
||||
./adguardhome
|
||||
./mosquitto
|
||||
./zigbee2mqtt
|
||||
];
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ in
|
|||
|
||||
sops.secrets."services/mosquitto/mq/hashedPassword" = {
|
||||
sopsFile = ./secrets.sops.yaml;
|
||||
owner = config.users.users.mosquitto.name;
|
||||
owner = "mosquitto";
|
||||
group = "mosquitto";
|
||||
restartUnits = [ "${app}.service" ];
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
services:
|
||||
mosquitto:
|
||||
mq:
|
||||
hashedPassword: ENC[AES256_GCM,data:l6QVTtfZJhsMfKoN/pIuKevjq6avIroUMSJQpj/53Lhuw/Okw2E9o1QBECBYvNUoU/367rCR82TBmPF5jguunWLI15bxnKxBvcPda33SlYwPGuiXDaALfk0WAPs11mpwvpgNNiVPOD5gDCW7YSNG8w==,iv:VF9Cm8Yp7SZY/CH5V6aLTGWb0CA4N50Kl7RPJJ/aKBc=,tag:dq9HwYCakSSel3cv/t3BjQ==,type:str]
|
||||
hashedPassword: ENC[AES256_GCM,data:FI2KLDYBW+HCXbOfmdyRYEwI8IeEX2iNWAiyGyn6FE2kkP1K1GETLbissBds+6DAPgbBULhxh8PZ9nkOCtR9QGKLkImxgMU1o8Zmwc6UxfkmFWvEDyt0/3g5gEVoO2rsLx4GMp4qO6Wbz0QCxJWJwQ==,iv:Pt9g/c3A1aChcgxQMSa76f1/c7uq8ctf9CDTFKNSvcs=,tag:zSS9heWyjvwFwKoEmYo+GA==,type:str]
|
||||
plainPassword.yaml: ENC[AES256_GCM,data:z+/SQE+PfsIoDekjf5D6f6nkxsfiNmcym4YSVdIl,iv:heh5N8HazUUP251llJLVGdka+65Ofjm4by1kug5uKYI=,tag:NS5K47rZRLH6OzyQopB3+A==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
|
@ -11,68 +12,68 @@ sops:
|
|||
- recipient: age1lj5vmr02qkudvv2xedfj5tq8x93gllgpr6tzylwdlt7lud4tfv5qfqsd5u
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFVlVjV3BBQjJHT1ZOVm9n
|
||||
RGhhOGcxanhNWEIxTTBUMU9DcEd3Tjc1c25VCjZVOXhVajVhVzR4WWlEbTQ5amFD
|
||||
WWN4bXJueVBrSHBocU93MDB5ZDdjT0EKLS0tIFhXY2xNZnVLYnIyYmxTSXU3Q3g4
|
||||
dElVV3ZsNFZZM083Tm10dVJJeDlkTWMK3/QJ1Gni+zj7J7gc0x3xL35rfBr6UNVa
|
||||
4ii+q0pHpMBTMb0S1nGbazi3wb1I5KxnINzS6mFSWXkMFU63l3b2YA==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjNmJPbGFaRXkrYnh6RHR4
|
||||
dHBWNWs0RDB1UnFycXdoWmFFYkNGcHh4YUZjCm9LYnZIU1dvNzVTNHp0NjBEMTE2
|
||||
MHpOdVh5aVR3c2o5V21LU1ZDWnpXdFEKLS0tIDB4emRQRGVVYzFYQ2JsakVIeFhn
|
||||
QlFEYjBSVjVKUFVEV3gwK2NZaW1XSGMKHBPiLSd7Ixs68xMcpOJzw2Vu4GbKAglY
|
||||
1yAcQgIRvFxCV/uz4BwAFvyCtYYsUD4GhEAFp/wwq6W1hTEAseV0RA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age17edew3aahg3t5nte5g0a505sn96vnj8g8gqse8q06ccrrn2n3uysyshu2c
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPejZ3NVMrZnRtMkNQV3dp
|
||||
ejJraDFpcG5mNEs5WE5YMGJKTEx5OGs4ZkJNCk05NDA4NTVxTFQ4UU5Mck9hYlZS
|
||||
Skx0L0xDVkxqU0ZROTBBTjQzaHdNSUkKLS0tIHpRQWtub3Bmc29aSjdBeHhKK1pq
|
||||
L0dLRm4wRTZsS0thc3VUSit5cDgxL2MKXGdQz7a9oEoqxNnGCQODcpb4W1RUKcli
|
||||
josRkGYVeOfRY0+1BKwk5XIbAKMohz+YbTKUKkWDYEXiffSjd7Ae2Q==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGRGE0OWZaR0ZhY2piMkxY
|
||||
cG1HRFIrWjJFeG8vbzhPWW51cWVvN2FXV2hvCjhLNmVwRkRWQm54N3FPczFudGVB
|
||||
N096dmFaUktqMDBIRWxlTnVaa2VOcVkKLS0tIEFZSmYweDRqVlpOdUhESXFjbnR0
|
||||
RXpBU2t0bFlJQW1RSXZ0dzZFT3RXT0UKraC9wurjhf+SiKPewE5L3auOI59kaj/h
|
||||
7nUUnWUQfkebO5wxtmbbmenXK//oY1tRbC/Dp2JPUTQo2wwrXMF/JQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1u4tht685sqg6dkmjyer96r93pl425u6353md6fphpd84jh3jwcusvm7mgk
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtNWhPRkt3M1NJajBlOCty
|
||||
RlEwQ1ZCQXhNQnIxbzVwcHpJUE11U2ZvcmxnClYyZ3dqSC91K2I2TmhSMEVIUWJy
|
||||
N1dMbjdsNjVUdVM3Uk9BeElRaUhzRXcKLS0tIGxhS1pTUEt3aU9nckNHMnQ2Q0xw
|
||||
WjdCRTRMdzVMekk1YXZBejdxdWF4UEkK7SPmOHbup24/IhITZzOnl7YSSYXl/ShW
|
||||
gOqyzkXxe079LHOadm/nqn+XVgnYdTeGf4budabp1TxUaMPsxgjG8g==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEVjdTRkdDMElXV0pLL3Fv
|
||||
MFpxaStjaHNPSmY1RnFUbUhVS09hUEZYYVFVCk4yUEsxV2FvYm5ybVdGS0pmVW5m
|
||||
b1FYb3RxYXFhVVhjNms1bjBtVEYyMm8KLS0tIDk2Uy9xT3VZdGdSY1Rjc3l5OGE4
|
||||
ZzJvWTdDRlFNMmliUGZZbnRCc0UwRHcKdJllfqPlYBNf/nWkT5E1Is1moIFvN6lc
|
||||
XVGQ9tzH1tpZC9PwmC1nL08fmuzwI5k9zqL2D+eG+vH7yjBLRFzxVg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1cp6vegrmqfkuj8nmt2u3z0sur7n0f7e9x9zmdv4zygp8j2pnucpsdkgagc
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkcFpSOE16bVlKalc4eEJn
|
||||
cVdwdWJwV3grR0dUUkZ2V1kvVyt5UVNmQVNrCnJLakF1aWhKaGYyYnR3Zlh0dUxI
|
||||
WStFbmVjWEM3QkU0NmlodjY0OXJLOWsKLS0tIFRPOC96M3IxcXdsaDB5RnJJb1dZ
|
||||
a3hpczhWUDVQM3JiVU5ja3ZDMVRGb3MKowyjuHf0SO6zJ4+dnnuxWUn17uTDh0Iy
|
||||
4x0cAKbwuSLlna3miG0Vxvfy/EehDuiZFW3c3EM7ITdayodM4lQNwQ==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzOUJOTFJFSHp1QTdKVmZk
|
||||
UVZhVEpqQzVTOTZHOXBYbDJUVjBpL2ErV2tJCm1jOUVmVE8wc3ZLSDZJRVkxQkNU
|
||||
eEw2RVNpVzJFcTlPbnF1Q2g0RVo5OUEKLS0tIFpvcU11RGVNR0dNQWc1aGJFd1lm
|
||||
Ym1kellUNjRsTTdQZTViZnBkRllqbWsKWFwR8WeIxJunlgzT3GpYkIdFRLJZlhm4
|
||||
Vr4N5CMnNXJYWRiNJDrHDKvVw6EeUUhyJ+7aJ9UAfR0YfX47yIlW5A==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1ekt5xz7u2xgdzgsrffhd9x22n80cn4thxd8zxjy2ey5vq3ca7gnqz25g5r
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXMy9XTFEvMExXQUJqbnlL
|
||||
YTdLd0c4bnVkOENtVGlocnRVQmhocHRiTlNnCm5Cc08yK3lLTkU0ZkNzQUViOC9q
|
||||
a1JGRFlaVnJyMVRod2NKWHJ6VVlSMzQKLS0tIFI4Z01hKzN5Y1VZKzIwb1VvVnZz
|
||||
bXFlZ1hCV3ZGOXJBMDY3M1RzOVZzbWMKlCRZZ+cKYyxd5VusNklUqJkVGp4/A7/U
|
||||
TBmsn2lHgLi+mnoCN6YLNcLz0gxG27VFMAQSaDECMW6HP0Yy2soAKA==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnWUpaOUVnRS9Va211UXl0
|
||||
dUFmOVlmR2d1REVNRXJKMFV1OTVsSDZGRldvCk5CcGpWZHFBYmtsbVRjWW1QejNJ
|
||||
Y0FPSVJ1UlhhcVhRaTVXMERyRURIRjAKLS0tIDloZ2J0anNqSEZmUXg4eDFyTVZ0
|
||||
WXAvTmRpUjRKMnJlZmV0SEEwZndtNkEK99oVyOIlfKP6zHnuS1LKGORuOLfX3vAU
|
||||
Gw7IHXRUSpZhElOSK0jc9F2O6IEGYpfu5PYC4m8uojhRXsG6W/XTXA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1jpeh4s553taxkyxhzlshzqjfrtvmmp5lw0hmpgn3mdnmgzku332qe082dl
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZSnZKNjRGamJGZ2gxbnBR
|
||||
S2t5TkpTcll6QVpmclhrWEtGODQrUkVyVVRjCmgwcWpBTWZhMFc4NC9MVDV4UVox
|
||||
WVY1WjMxajVsNG9YRTJOYktrSTVZRUkKLS0tIE01dkZXRTFmM3lWN0RqLzJWQVF0
|
||||
aSt3SUE2N3BJeFJUVnR6K2UzUDl0a28K2WcNLOYihCBoL5KMTQWvtbgqtTosA3Y6
|
||||
s+2XzBnz/RonDVe2Wh+trkwfKfiwyEvhcyBHQIjU6g4eWovVDMq7Vw==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArUVZScTVpWjZvUzlFeDVQ
|
||||
RjRreTBPTEF3bXZ1Sk5sWmgzUURxcU5talFzClFRSjFFUEtQMis4dkNLRFFaaHlq
|
||||
QXdhQWxEMXdHSGgzSXlqZm4xbEFVaGMKLS0tIG9OOHUwZWI3SXJ2SWZvdS9EVzV5
|
||||
aVpWNmk5b1owbjJHSWtnOHRJWmhEbGMKT4VdLG/8qX+KWO6vQ2TsrT1+w4XgDani
|
||||
KOAS/DimV22EjmHljs9ByWdqkVw0KIBfp2oXo9m0Jqn0H1M2yEMozg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1j2r8mypw44uvqhfs53424h6fu2rkr5m7asl7rl3zn3xzva9m3dcqpa97gw
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkaEVuZWRaeExoaStDQW14
|
||||
SFdwM1VxTFQ4dGdNRUdQOUF1djVnOUQ5M3hFCmc4NWxtTDNRcjlmVGxLSW45c0lm
|
||||
ZzRURjZmTTFibk43Q0RiZkk1NmdOL2sKLS0tIDZ0L3U2M2JlamJwTVUwRFVHR1FM
|
||||
aUsvNG95K0lxdUFjRUpXdHhDZjIyV0EKEYU4IkFdNXqWHD6+ukmcOkiB7UW5Fn1w
|
||||
M009nesLsOp1j1sVEStgPzPJLnw/j2OZQgkiMSzeLE1CrGLaOLdpCw==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWNzZiS1pVTXMxQW9UUldr
|
||||
dFNHUDhxV1lnOFNaK2J6SEY3WUtId0FLSTNjCkJhUm1sVnlJMFk5Wm9lNGdMYnZv
|
||||
eVR6MGNVYjBSNENqU1BJWituMnJJeFUKLS0tIEk0ZUVETHRmSmJjT2NDMGNrajlZ
|
||||
NUMxdEhvQnRES2hwck5jeEw3bnprZ00KUnkLNK+hmCihLwPiWt3NHjASuQwgBOlf
|
||||
AsW8BkUjjQY/ABR3X6sNSI8uXQt+8BHP14U4cO8jwggcyE2W1Pq03A==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2024-04-25T03:13:36Z"
|
||||
mac: ENC[AES256_GCM,data:YC1lPTCSUZPgZte0WHGbqh1k3vAfcvVNyxR7+daPH5xwrXyZa/jTIY5U/UuD+nVCr2YFB89QKGko6c76sqoDxhMRf/FDZt0YSa+RaOJO0LNinRBokV2sm0oYxeWoKEUB1B5cuXVfBqqsgw6qQqvIuysXGk0A8vjXUT/btZSd2/A=,iv:Gu3X3xxZ5dmb2Y6Ve/7xznmS0/x5uU9iIDRiOE/DR9Y=,tag:1l7GtZTxBFLvV4JzRVt4Ow==,type:str]
|
||||
lastmodified: "2024-04-25T05:21:30Z"
|
||||
mac: ENC[AES256_GCM,data:aN2YsPhDMl8vvLgi98iRCl5f7llJ8VTt7y1vh7liBAwG6hW1vZeetqSxvWiVDugozjsbK6n44AUDjhnfwo8EXp8iWQmJDXuS1PoEph4C18oo4Eu8n9ZpLQFGSKRMYXuetwrzOkn42tMYadYbwLPIandKqaTGUD4FcoqZtGxaH3c=,iv:Wfb1r8JNO74KjBWTIGwW2bXTVv3AIpj5KW9FXYrDm7c=,tag:FEnXv1S0J3XaxZ6TQz0bhQ==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.8.1
|
||||
|
|
|
@ -7,7 +7,88 @@
|
|||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.services.traefik;
|
||||
routersFile = builtins.toFile "routers.yaml" (builtins.toJSON cfg.routers);
|
||||
|
||||
# core dynamic options to define middleware
|
||||
# sso etc
|
||||
dynamicOptions = [{
|
||||
|
||||
http.middlewares = {
|
||||
# Whitelist local network and VPN addresses
|
||||
local-ip-only.ipWhiteList.sourceRange = [
|
||||
"127.0.0.1/32" # localhost
|
||||
"192.168.0.0/16" # RFC1918
|
||||
"10.0.0.0/8" # RFC1918
|
||||
"172.16.0.0/12" # RFC1918 (docker network)
|
||||
];
|
||||
|
||||
# authelia = {
|
||||
# # Forward requests w/ middlewares=authelia@file to authelia.
|
||||
# forwardAuth = {
|
||||
# # address = cfg.autheliaUrl;
|
||||
# address = "http://localhost:9092/api/verify?rd=https://auth.dhupar.xyz:444/";
|
||||
# trustForwardHeader = true;
|
||||
# authResponseHeaders = [
|
||||
# "Remote-User"
|
||||
# "Remote-Name"
|
||||
# "Remote-Email"
|
||||
# "Remote-Groups"
|
||||
# ];
|
||||
# };
|
||||
# };
|
||||
# authelia-basic = {
|
||||
# # Forward requests w/ middlewares=authelia-basic@file to authelia.
|
||||
# forwardAuth = {
|
||||
# address = "http://localhost:9092/api/verify?auth=basic";
|
||||
# trustForwardHeader = true;
|
||||
# authResponseHeaders = [
|
||||
# "Remote-User"
|
||||
# "Remote-Name"
|
||||
# "Remote-Email"
|
||||
# "Remote-Groups"
|
||||
# ];
|
||||
# };
|
||||
# };
|
||||
# https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview/#forwardauth-with-static-upstreams-configuration
|
||||
# auth-headers = {
|
||||
# browserXssFilter = true;
|
||||
# contentTypeNosniff = true;
|
||||
# forceSTSHeader = true;
|
||||
# frameDeny = true;
|
||||
# sslHost = domain;
|
||||
# sslRedirect = true;
|
||||
# stsIncludeSubdomains = true;
|
||||
# stsPreload = true;
|
||||
# stsSeconds = 315360000;
|
||||
# };
|
||||
};
|
||||
|
||||
tls.options.default = {
|
||||
minVersion = "VersionTLS13";
|
||||
sniStrict = true;
|
||||
};
|
||||
|
||||
# Set up wildcard domain certificates for both *.hostname.domain and *.local.domain
|
||||
http.routers = {
|
||||
traefik = {
|
||||
entrypoints = "websecure";
|
||||
rule = "Host(`traefik-${config.networking.hostName}.${config.mySystem.domain}`)";
|
||||
tls.certresolver = "letsencrypt";
|
||||
tls.domains = [{
|
||||
main = "${config.mySystem.domain}";
|
||||
sans = "*.${config.mySystem.domain}";
|
||||
}];
|
||||
middlewares = "local-ip-only@file";
|
||||
service = "api@internal";
|
||||
};
|
||||
};
|
||||
}];
|
||||
|
||||
# Combine the above 'core 'options with the (dynamicOptions)
|
||||
# list of ingress routers for each serfie defined in various
|
||||
# modules (cfg.routers)
|
||||
# this folds the list and iterates each element to add them together
|
||||
dynamicOptionsAttrset = lib.foldl' (acc: elem: lib.recursiveUpdate acc elem) { } (dynamicOptions ++ cfg.routers);
|
||||
routersFile = builtins.toFile "routers.yaml" (builtins.toJSON dynamicOptionsAttrset);
|
||||
|
||||
in
|
||||
{
|
||||
|
@ -21,185 +102,124 @@ in
|
|||
};
|
||||
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = mkIf cfg.enable
|
||||
{
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
# put the dynamic configs in a file
|
||||
# i put this in a file instead of piping directly into
|
||||
# the traefik module, so that if i update the file
|
||||
# with a new router nix doesnt restart traefik, it just updates
|
||||
# the etc file and traefik picks up the changes.
|
||||
environment.etc."traefik/config.yaml".source = routersFile;
|
||||
|
||||
sops.secrets."system/services/traefik/apiTokenFile".sopsFile = ./secrets.sops.yaml;
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
|
||||
# Restart when secret changes
|
||||
sops.secrets."system/services/traefik/apiTokenFile".restartUnits = [ "traefik.service" ];
|
||||
sops.secrets."system/services/traefik/apiTokenFile".sopsFile = ./secrets.sops.yaml;
|
||||
|
||||
systemd.services.traefik = {
|
||||
serviceConfig.EnvironmentFile = [
|
||||
config.sops.secrets."system/services/traefik/apiTokenFile".path
|
||||
];
|
||||
};
|
||||
# Restart when secret changes
|
||||
sops.secrets."system/services/traefik/apiTokenFile".restartUnits = [ "traefik.service" ];
|
||||
|
||||
# add user to group to view files/storage
|
||||
users.users.truxnell.extraGroups = [ "traefik" ];
|
||||
systemd.services.traefik = {
|
||||
serviceConfig.EnvironmentFile = [
|
||||
config.sops.secrets."system/services/traefik/apiTokenFile".path
|
||||
];
|
||||
};
|
||||
|
||||
services.traefik = {
|
||||
# TODO refactor into subfiles
|
||||
enable = true;
|
||||
group = "podman"; # podman backend, required to access socket
|
||||
# add user to group to view files/storage
|
||||
users.users.truxnell.extraGroups = [ "traefik" ];
|
||||
|
||||
dataDir = "${config.mySystem.persistentFolder}/traefik";
|
||||
# Required so traefik is permitted to watch docker events
|
||||
# group = "docker";
|
||||
services.traefik = {
|
||||
# TODO refactor into subfiles
|
||||
enable = true;
|
||||
group = "podman"; # podman backend, required to access socket
|
||||
|
||||
staticConfigOptions = {
|
||||
dataDir = "${config.mySystem.persistentFolder}/traefik";
|
||||
# Required so traefik is permitted to watch docker events
|
||||
# group = "docker";
|
||||
|
||||
global = {
|
||||
checkNewVersion = false;
|
||||
sendAnonymousUsage = false;
|
||||
};
|
||||
staticConfigOptions = {
|
||||
|
||||
api.dashboard = true;
|
||||
log.level = "DEBUG";
|
||||
|
||||
# Allow backend services to have self-signed certs
|
||||
serversTransport.insecureSkipVerify = true;
|
||||
|
||||
providers = {
|
||||
docker = {
|
||||
endpoint = "unix:///var/run/podman/podman.sock";
|
||||
exposedByDefault = false;
|
||||
defaultRule = "Host(`{{ normalize .Name }}.${config.mySystem.domain}`)";
|
||||
# network = "proxy";
|
||||
};
|
||||
file = {
|
||||
filename = routersFile;
|
||||
watch = true;
|
||||
global = {
|
||||
checkNewVersion = false;
|
||||
sendAnonymousUsage = false;
|
||||
};
|
||||
|
||||
};
|
||||
api.dashboard = true;
|
||||
log.level = "DEBUG";
|
||||
|
||||
# Listen on port 80 and redirect to port 443
|
||||
entryPoints.web = {
|
||||
address = ":80";
|
||||
http.redirections.entrypoint.to = "websecure";
|
||||
};
|
||||
# Allow backend services to have self-signed certs
|
||||
serversTransport.insecureSkipVerify = true;
|
||||
|
||||
# Run everything SSL
|
||||
entryPoints.websecure = {
|
||||
address = ":443";
|
||||
http = {
|
||||
tls = {
|
||||
certresolver = "letsencrypt";
|
||||
domains.main = "${config.mySystem.domain}";
|
||||
domains.sans = "*.${config.mySystem.domain}";
|
||||
providers = {
|
||||
docker = {
|
||||
endpoint = "unix:///var/run/podman/podman.sock";
|
||||
exposedByDefault = false;
|
||||
defaultRule = "Host(`{{ normalize .Name }}.${config.mySystem.domain}`)";
|
||||
# network = "proxy";
|
||||
};
|
||||
file = {
|
||||
filename = "/etc/traefik/config.yaml";
|
||||
watch = true;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
# Listen on port 80 and redirect to port 443
|
||||
entryPoints.web = {
|
||||
address = ":80";
|
||||
http.redirections.entrypoint.to = "websecure";
|
||||
};
|
||||
|
||||
# Run everything SSL
|
||||
entryPoints.websecure = {
|
||||
address = ":443";
|
||||
http = {
|
||||
tls = {
|
||||
certresolver = "letsencrypt";
|
||||
domains.main = "${config.mySystem.domain}";
|
||||
domains.sans = "*.${config.mySystem.domain}";
|
||||
};
|
||||
};
|
||||
http3 = { };
|
||||
};
|
||||
|
||||
certificatesResolvers.letsencrypt.acme = {
|
||||
dnsChallenge.provider = "cloudflare";
|
||||
dnsChallenge.resolvers = [ "1.1.1.1:53" ];
|
||||
keyType = "EC256";
|
||||
storage = "${config.services.traefik.dataDir}/acme.json";
|
||||
};
|
||||
# };
|
||||
};
|
||||
# Dynamic configuration
|
||||
# refer the etc file defined above with the build
|
||||
# dynamic options
|
||||
dynamicConfigFile = "/etc/traefik/config.yaml";
|
||||
};
|
||||
|
||||
mySystem.services.homepage.infrastructure = [
|
||||
{
|
||||
"Traefik ${config.networking.hostName}" = {
|
||||
icon = "traefik.png";
|
||||
href = "https://traefik-${config.networking.hostName}.${config.mySystem.domain}/dashboard/";
|
||||
|
||||
description = "Reverse Proxy";
|
||||
widget = {
|
||||
type = "traefik";
|
||||
url = "https://traefik-${config.networking.hostName}.${config.mySystem.domain}";
|
||||
};
|
||||
};
|
||||
http3 = { };
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
certificatesResolvers.letsencrypt.acme = {
|
||||
dnsChallenge.provider = "cloudflare";
|
||||
dnsChallenge.resolvers = [ "1.1.1.1:53" ];
|
||||
keyType = "EC256";
|
||||
storage = "${config.services.traefik.dataDir}/acme.json";
|
||||
};
|
||||
# };
|
||||
};
|
||||
# Dynamic configuration
|
||||
dynamicConfigOptions = {
|
||||
mySystem.services.gatus.monitors = [{
|
||||
|
||||
http.middlewares = {
|
||||
# Whitelist local network and VPN addresses
|
||||
local-ip-only.ipWhiteList.sourceRange = [
|
||||
"127.0.0.1/32" # localhost
|
||||
"192.168.0.0/16" # RFC1918
|
||||
"10.0.0.0/8" # RFC1918
|
||||
"172.16.0.0/12" # RFC1918 (docker network)
|
||||
];
|
||||
name = "Traefik ${config.networking.hostName}";
|
||||
group = "infrastructure";
|
||||
url = "https://traefik-${config.networking.hostName}.${config.mySystem.domain}";
|
||||
interval = "1m";
|
||||
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];
|
||||
}];
|
||||
|
||||
# authelia = {
|
||||
# # Forward requests w/ middlewares=authelia@file to authelia.
|
||||
# forwardAuth = {
|
||||
# # address = cfg.autheliaUrl;
|
||||
# address = "http://localhost:9092/api/verify?rd=https://auth.dhupar.xyz:444/";
|
||||
# trustForwardHeader = true;
|
||||
# authResponseHeaders = [
|
||||
# "Remote-User"
|
||||
# "Remote-Name"
|
||||
# "Remote-Email"
|
||||
# "Remote-Groups"
|
||||
# ];
|
||||
# };
|
||||
# };
|
||||
# authelia-basic = {
|
||||
# # Forward requests w/ middlewares=authelia-basic@file to authelia.
|
||||
# forwardAuth = {
|
||||
# address = "http://localhost:9092/api/verify?auth=basic";
|
||||
# trustForwardHeader = true;
|
||||
# authResponseHeaders = [
|
||||
# "Remote-User"
|
||||
# "Remote-Name"
|
||||
# "Remote-Email"
|
||||
# "Remote-Groups"
|
||||
# ];
|
||||
# };
|
||||
# };
|
||||
# https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview/#forwardauth-with-static-upstreams-configuration
|
||||
# auth-headers = {
|
||||
# browserXssFilter = true;
|
||||
# contentTypeNosniff = true;
|
||||
# forceSTSHeader = true;
|
||||
# frameDeny = true;
|
||||
# sslHost = domain;
|
||||
# sslRedirect = true;
|
||||
# stsIncludeSubdomains = true;
|
||||
# stsPreload = true;
|
||||
# stsSeconds = 315360000;
|
||||
# };
|
||||
};
|
||||
|
||||
tls.options.default = {
|
||||
minVersion = "VersionTLS13";
|
||||
sniStrict = true;
|
||||
};
|
||||
|
||||
# Set up wildcard domain certificates for both *.hostname.domain and *.local.domain
|
||||
http.routers = {
|
||||
traefik = {
|
||||
entrypoints = "websecure";
|
||||
rule = "Host(`traefik-${config.networking.hostName}.${config.mySystem.domain}`)";
|
||||
tls.certresolver = "letsencrypt";
|
||||
tls.domains = [{
|
||||
main = "${config.mySystem.domain}";
|
||||
sans = "*.${config.mySystem.domain}";
|
||||
}];
|
||||
middlewares = "local-ip-only@file";
|
||||
service = "api@internal";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mySystem.services.homepage.infrastructure = [
|
||||
{
|
||||
"Traefik ${config.networking.hostName}" = {
|
||||
icon = "traefik.png";
|
||||
href = "https://traefik-${config.networking.hostName}.${config.mySystem.domain}/dashboard/";
|
||||
|
||||
description = "Reverse Proxy";
|
||||
widget = {
|
||||
type = "traefik";
|
||||
url = "https://traefik-${config.networking.hostName}.${config.mySystem.domain}";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
mySystem.services.gatus.monitors = [{
|
||||
|
||||
name = "Traefik ${config.networking.hostName}";
|
||||
group = "infrastructure";
|
||||
url = "https://traefik-${config.networking.hostName}.${config.mySystem.domain}";
|
||||
interval = "1m";
|
||||
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];
|
||||
}];
|
||||
|
||||
};
|
||||
}
|
||||
|
|
113
nixos/modules/nixos/services/zigbee2mqtt/default.nix
Normal file
113
nixos/modules/nixos/services/zigbee2mqtt/default.nix
Normal file
|
@ -0,0 +1,113 @@
|
|||
{ lib
|
||||
, config
|
||||
, pkgs
|
||||
, ...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.services.zigbee2mqtt;
|
||||
persistentFolder = "${config.mySystem.persistentFolder}/nixos/services/${app}/";
|
||||
app = "zigbee2mqtt";
|
||||
user = app;
|
||||
group = app;
|
||||
|
||||
in
|
||||
{
|
||||
options.mySystem.services.zigbee2mqtt = {
|
||||
enable = mkEnableOption "zigbee2mqtt";
|
||||
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
|
||||
};
|
||||
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
# ensure folder exist and has correct owner/group
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${persistentFolder} 0750 ${user} ${group} -" #The - disables automatic cleanup, so the file wont be removed after a period
|
||||
];
|
||||
|
||||
sops.secrets."services/mosquitto/mq/plainPassword.yaml" = {
|
||||
sopsFile = ../mosquitto/secrets.sops.yaml;
|
||||
owner = config.users.users.zigbee2mqtt.name;
|
||||
group = config.users.users.zigbee2mqtt.group;
|
||||
restartUnits = [ "${app}.service" ];
|
||||
};
|
||||
|
||||
services.zigbee2mqtt = {
|
||||
enable = true;
|
||||
dataDir = persistentFolder;
|
||||
settings = {
|
||||
advanced.log_level = "warn";
|
||||
homeassistant = true;
|
||||
permit_join = false;
|
||||
include_device_information = true;
|
||||
frontend =
|
||||
{
|
||||
port = 8080;
|
||||
url = "https://${app}.${config.networking.domain}";
|
||||
};
|
||||
client_id = "z2m";
|
||||
serial = {
|
||||
port = "tcp://10.8.30.110:6638";
|
||||
};
|
||||
mqtt = {
|
||||
server = "mqtt://mqtt.trux.dev:1883";
|
||||
user = "mq";
|
||||
password = "!${config.sops.secrets."services/mosquitto/mq/plainPassword.yaml".path} password";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
users.users.truxnell.extraGroups = [ app ];
|
||||
|
||||
mySystem.services.traefik.routers = [{
|
||||
http.routers.${app} = {
|
||||
rule = "Host(`${app}.${config.mySystem.domain}`)";
|
||||
entrypoints = "websecure";
|
||||
middlewares = "local-ip-only@file";
|
||||
service = "${app}";
|
||||
};
|
||||
http.services.${app} = {
|
||||
loadBalancer = {
|
||||
servers = [{
|
||||
url = "http://localhost:8080";
|
||||
}];
|
||||
};
|
||||
};
|
||||
|
||||
}];
|
||||
|
||||
|
||||
mySystem.services.homepage.media = mkIf cfg.addToHomepage [
|
||||
{
|
||||
${app} = {
|
||||
icon = "${app}.svg";
|
||||
href = "https://${app}.${config.mySystem.domain}";
|
||||
description = "Zigbee bridge to MQTT";
|
||||
container = "${app}";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
mySystem.services.gatus.monitors = [{
|
||||
|
||||
name = app;
|
||||
group = "services";
|
||||
url = "https://${app}.${config.mySystem.domain}";
|
||||
interval = "1m";
|
||||
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];
|
||||
}];
|
||||
|
||||
services.restic.backups = config.lib.mySystem.mkRestic
|
||||
{
|
||||
inherit app;
|
||||
user = builtins.toString user;
|
||||
paths = [ persistentFolder ];
|
||||
appFolder = app;
|
||||
inherit persistentFolder;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
}
|
Reference in a new issue