Compare commits
95 Commits
0a89116be6
...
f6907766f0
Author | SHA1 | Date | |
---|---|---|---|
|
f6907766f0 | ||
|
31dc159727 | ||
|
504f3590d3 | ||
|
e6ddfcd153 | ||
|
09b6afc1ac | ||
|
39fbc03827 | ||
|
5c1abae02c | ||
|
aabbff3ad4 | ||
|
241973d56a | ||
|
0da5018e8c | ||
|
184f039e40 | ||
|
0e513e1c69 | ||
|
6fafab2e5c | ||
|
2af3952cf5 | ||
|
c2d96e936e | ||
|
7217af2233 | ||
|
44af2887a5 | ||
|
9e8e7169d3 | ||
|
317803eb5a | ||
|
46cb8d1c7e | ||
|
60c447024d | ||
|
2afe7dc76c | ||
|
c3a2c54b13 | ||
|
388a11a76e | ||
|
d2b361e82b | ||
|
7053b64156 | ||
|
9277af4088 | ||
|
e8afefea50 | ||
|
4fa79d642f | ||
|
db884c9e86 | ||
|
cbd6725b2a | ||
|
51517d8914 | ||
|
3ba686f159 | ||
|
0d8776d8e7 | ||
|
f6b1d1d71c | ||
|
431e7fac05 | ||
|
a0331deac3 | ||
|
52a5a7e7d2 | ||
|
353f5822bf | ||
|
4369735976 | ||
|
9c71d75363 | ||
|
3508ebc879 | ||
|
c1baa0eb65 | ||
|
a022b2d0ce | ||
|
1a54c00cc2 | ||
|
301629243e | ||
|
48b86055a0 | ||
|
70c39b782b | ||
|
9b945b0a84 | ||
|
c7e579ec95 | ||
|
738b0e9577 | ||
|
a5232f522b | ||
|
2c350070a3 | ||
|
b1065f61d9 | ||
|
89aa2e7f20 | ||
|
985d325885 | ||
|
894bc74667 | ||
|
2d4bdd0cfd | ||
|
309872f4f2 | ||
|
9f0a119c8e | ||
|
d3e8f402a9 | ||
|
87511fc1b8 | ||
|
88990545ed | ||
|
08ae792712 | ||
|
8c72ff433c | ||
|
3c44bbc034 | ||
|
a44533a0e0 | ||
|
35035111e7 | ||
|
296609fdfb | ||
|
5601a2cab0 | ||
|
6bf0fc0967 | ||
|
9a0b8d3917 | ||
|
8808298c29 | ||
|
c2b89b7fc5 | ||
|
eec1a9c66a | ||
|
d40f064925 | ||
|
ddc4d884b7 | ||
|
955b9f4cfb | ||
|
bd95960c84 | ||
|
ab817ede3e | ||
|
95c5be3098 | ||
|
b2091de9c9 | ||
|
970b75b064 | ||
|
2f3470cf50 | ||
|
df91ea0fb9 | ||
|
e6c5b780df | ||
|
f3dfa9543e | ||
|
6a21b5b40a | ||
|
aba86e6d02 | ||
|
abbb655383 | ||
|
a7b03d9b9a | ||
|
a467cbe6dc | ||
|
63a6642f8c | ||
|
c47c8a42ee | ||
|
dd151c9f1a |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
result
|
||||
result/
|
||||
|
||||
.aider*
|
||||
.env
|
||||
|
435
flake.lock
generated
435
flake.lock
generated
@ -8,11 +8,11 @@
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1736955230,
|
||||
"narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=",
|
||||
"lastModified": 1747575206,
|
||||
"narHash": "sha256-NwmAFuDUO/PFcgaGGr4j3ozG9Pe5hZ/ogitWhY+D81k=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c",
|
||||
"rev": "4835b1dc898959d8547a871ef484930675cb47f1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -21,37 +21,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"cachix": {
|
||||
"inputs": {
|
||||
"devenv": [
|
||||
"teslamate-flake",
|
||||
"devenv"
|
||||
],
|
||||
"flake-compat": [
|
||||
"teslamate-flake",
|
||||
"devenv"
|
||||
],
|
||||
"git-hooks": [
|
||||
"teslamate-flake",
|
||||
"devenv"
|
||||
],
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1728672398,
|
||||
"narHash": "sha256-KxuGSoVUFnQLB2ZcYODW7AVPAh9JqRlD5BrfsC/Q4qs=",
|
||||
"owner": "cachix",
|
||||
"repo": "cachix",
|
||||
"rev": "aac51f698309fd0f381149214b7eee213c66ef0a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"ref": "latest",
|
||||
"repo": "cachix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@ -60,11 +29,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1700795494,
|
||||
"narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=",
|
||||
"lastModified": 1744478979,
|
||||
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d",
|
||||
"rev": "43975d782b418ebf4969e9ccba82466728c2851b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -74,154 +43,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"devenv": {
|
||||
"inputs": {
|
||||
"cachix": "cachix",
|
||||
"flake-compat": "flake-compat",
|
||||
"git-hooks": "git-hooks",
|
||||
"nix": "nix",
|
||||
"nixpkgs": "nixpkgs_6"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1732298876,
|
||||
"narHash": "sha256-WXlcDNMaMJeI4JO4VfQM2ZZCBJBds7j7N04tS9UjiYU=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "741e23a22f3dc9e53075be3eaa795ea9ed6f5129",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"devenv-root": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"narHash": "sha256-d6xi4mKdjkX2JFicDIv5niSzpyI0m/Hnm8GGAIU04kY=",
|
||||
"type": "file",
|
||||
"url": "file:///dev/null"
|
||||
},
|
||||
"original": {
|
||||
"type": "file",
|
||||
"url": "file:///dev/null"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"teslamate-flake",
|
||||
"devenv",
|
||||
"nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1712014858,
|
||||
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_2": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"teslamate-flake",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730504689,
|
||||
"narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "506278e768c2a08bec68eb62932193e341f55c90",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"git-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"teslamate-flake",
|
||||
"devenv"
|
||||
],
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"teslamate-flake",
|
||||
"devenv",
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": [
|
||||
"teslamate-flake",
|
||||
"devenv"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730302582,
|
||||
"narHash": "sha256-W1MIJpADXQCgosJZT8qBYLRuZls2KSiKdpnTVdKBuvU=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "af8a16fe5c264f5e9e18bcee2859b40a656876cf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"teslamate-flake",
|
||||
"devenv",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@ -230,11 +51,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1703113217,
|
||||
"narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=",
|
||||
"lastModified": 1745494811,
|
||||
"narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1",
|
||||
"rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -250,40 +71,24 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743387206,
|
||||
"narHash": "sha256-24N3NAuZZbYqZ39NgToZgHUw6M7xHrtrAm18kv0+2Wo=",
|
||||
"lastModified": 1748665073,
|
||||
"narHash": "sha256-RMhjnPKWtCoIIHiuR9QKD7xfsKb3agxzMfJY8V9MOew=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "15c5f9d04fabd176f30286c8f52bbdb2c853a146",
|
||||
"rev": "282e1e029cb6ab4811114fc85110613d72771dea",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "release-24.11",
|
||||
"ref": "release-25.05",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"libgit2": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1697646580,
|
||||
"narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
|
||||
"owner": "libgit2",
|
||||
"repo": "libgit2",
|
||||
"rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "libgit2",
|
||||
"repo": "libgit2",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"local-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 0,
|
||||
"narHash": "sha256-uewgkTWbDOpOP+wEA3f03XEKsPHsJi0iDqBGQnxWQo0=",
|
||||
"narHash": "sha256-eCA4jXsPHiBkrf1sNOfQPYS2g9DoCsICVzk4ec0cEdo=",
|
||||
"path": "/home/giulio/dev/nixpkgs",
|
||||
"type": "path"
|
||||
},
|
||||
@ -292,82 +97,29 @@
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
"nix": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"teslamate-flake",
|
||||
"devenv"
|
||||
],
|
||||
"flake-parts": "flake-parts",
|
||||
"libgit2": "libgit2",
|
||||
"nixpkgs": "nixpkgs_5",
|
||||
"nixpkgs-23-11": [
|
||||
"teslamate-flake",
|
||||
"devenv"
|
||||
],
|
||||
"nixpkgs-regression": [
|
||||
"teslamate-flake",
|
||||
"devenv"
|
||||
],
|
||||
"pre-commit-hooks": [
|
||||
"teslamate-flake",
|
||||
"devenv"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727438425,
|
||||
"narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=",
|
||||
"owner": "domenkozar",
|
||||
"repo": "nix",
|
||||
"rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "domenkozar",
|
||||
"ref": "devenv-2.24",
|
||||
"repo": "nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-master": {
|
||||
"locked": {
|
||||
"lastModified": 1743784178,
|
||||
"narHash": "sha256-rxchbu1Zcthv7fV+KWiF79SjUaeMe3tiK5qYhg+u+pA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "d142f5ee8a1bc234868d9ea5bcc7c0db708651e1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "master",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1743689281,
|
||||
"narHash": "sha256-y7Hg5lwWhEOgflEHRfzSH96BOt26LaYfrYWzZ+VoVdg=",
|
||||
"lastModified": 1748929857,
|
||||
"narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2bfc080955153be0be56724be6fa5477b4eefabb",
|
||||
"rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1703013332,
|
||||
"narHash": "sha256-+tFNwMvlXLbJZXiMHqYq77z/RfmpfpiI3yjL6o/Zo9M=",
|
||||
"lastModified": 1745391562,
|
||||
"narHash": "sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "54aac082a4d9bb5bbc5c4e899603abfb76a3f6d6",
|
||||
"rev": "8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -377,19 +129,35 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"nixpkgs-master": {
|
||||
"locked": {
|
||||
"lastModified": 1744440957,
|
||||
"narHash": "sha256-FHlSkNqFmPxPJvy+6fNLaNeWnF1lZSgqVCl/eWaJRc4=",
|
||||
"lastModified": 1749040375,
|
||||
"narHash": "sha256-zwVvfxgrXcInI2E/dDg9v80OrvKUT7HtPECu53Khcq0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "26d499fc9f1d567283d5d56fcf367edd815dba1d",
|
||||
"rev": "57afa2783caf7d6713f63c8e29fba6c52a3a5300",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "master",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1748889542,
|
||||
"narHash": "sha256-Hb4iMhIbjX45GcrgOp3b8xnyli+ysRPqAgZ/LZgyT5k=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "10d7f8d34e5eb9c0f9a0485186c1ca691d2c5922",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "26d499fc9f1d567283d5d56fcf367edd815dba1d",
|
||||
"rev": "10d7f8d34e5eb9c0f9a0485186c1ca691d2c5922",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
@ -409,70 +177,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1730531603,
|
||||
"narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_5": {
|
||||
"locked": {
|
||||
"lastModified": 1717432640,
|
||||
"narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "release-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_6": {
|
||||
"locked": {
|
||||
"lastModified": 1716977621,
|
||||
"narHash": "sha256-Q1UQzYcMJH4RscmpTkjlgqQDX5yi1tZL0O345Ri6vXQ=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"rev": "4267e705586473d3e5c8d50299e71503f16a6fb6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"ref": "rolling",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_7": {
|
||||
"locked": {
|
||||
"lastModified": 1732014248,
|
||||
"narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "23e89b7da85c3640bbc2173fe04f4bd114342367",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nvidia-patch": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@ -481,11 +185,11 @@
|
||||
"utils": "utils"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743670877,
|
||||
"narHash": "sha256-OHuOhVCfx10VpWwl9T5Q+QB3To0N95flBR1rSwOiUHA=",
|
||||
"lastModified": 1748931931,
|
||||
"narHash": "sha256-0NUhiMITsYlXDjgcVbLayI0rgrEdf5NIbpW3oLueYUs=",
|
||||
"owner": "icewind1991",
|
||||
"repo": "nvidia-patch-nixos",
|
||||
"rev": "e80a4919e88a8cb496f649234fb3fc7e992ece10",
|
||||
"rev": "fa8f006a236349790c94801ac85e43f103b35baf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -517,12 +221,11 @@
|
||||
"agenix-flake": "agenix-flake",
|
||||
"home-manager": "home-manager_2",
|
||||
"local-unstable": "local-unstable",
|
||||
"nixos-master": "nixos-master",
|
||||
"nixos-unstable": "nixos-unstable",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"nixpkgs-master": "nixpkgs-master",
|
||||
"nvidia-patch": "nvidia-patch",
|
||||
"pepeflake": "pepeflake",
|
||||
"teslamate-flake": "teslamate-flake"
|
||||
"pepeflake": "pepeflake"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
@ -555,50 +258,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"teslamate-flake": {
|
||||
"inputs": {
|
||||
"devenv": "devenv",
|
||||
"devenv-root": "devenv-root",
|
||||
"flake-parts": "flake-parts_2",
|
||||
"nixpkgs": "nixpkgs_7",
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1732358620,
|
||||
"narHash": "sha256-diQRtJYfzGIVLxrdBad3XKWCtR97rj9Q1ZJ9MmvJGRk=",
|
||||
"owner": "teslamate-org",
|
||||
"repo": "teslamate",
|
||||
"rev": "0ec408c8e182fe64e9568b6f137cbfb528717e8e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "teslamate-org",
|
||||
"ref": "v1.32.0",
|
||||
"repo": "teslamate",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"teslamate-flake",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1732292307,
|
||||
"narHash": "sha256-5WSng844vXt8uytT5djmqBCkopyle6ciFgteuA9bJpw=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "705df92694af7093dfbb27109ce16d828a79155f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
|
19
flake.nix
19
flake.nix
@ -1,14 +1,13 @@
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/26d499fc9f1d567283d5d56fcf367edd815dba1d";
|
||||
nixos-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
nixos-master.url = "github:NixOS/nixpkgs/master";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/10d7f8d34e5eb9c0f9a0485186c1ca691d2c5922";
|
||||
nixos-unstable.url = "github:NixOS/nixpkgs/c2a03962b8e24e669fb37b7df10e7c79531ff1a4";
|
||||
nixpkgs-master.url = "github:NixOS/nixpkgs/master";
|
||||
local-unstable.url = "path:///home/giulio/dev/nixpkgs";
|
||||
pepeflake.url = "git+https://git.giugl.io/peperunas/pepeflake";
|
||||
teslamate-flake.url = "github:teslamate-org/teslamate/v1.32.0";
|
||||
agenix-flake.url = "github:ryantm/agenix";
|
||||
home-manager = {
|
||||
url = "github:nix-community/home-manager/release-24.11";
|
||||
url = "github:nix-community/home-manager/release-25.05";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
nvidia-patch = {
|
||||
@ -21,10 +20,9 @@
|
||||
{ self
|
||||
, nixpkgs
|
||||
, nixos-unstable
|
||||
, nixos-master
|
||||
, nixpkgs-master
|
||||
, local-unstable
|
||||
, home-manager
|
||||
, teslamate-flake
|
||||
, nvidia-patch
|
||||
, agenix-flake
|
||||
, pepeflake
|
||||
@ -62,16 +60,14 @@
|
||||
};
|
||||
|
||||
unstablePkgs = importNixpkgs { flake = nixos-unstable; };
|
||||
masterPkgs = importNixpkgs { flake = nixos-master; };
|
||||
masterPkgs = importNixpkgs { flake = nixpkgs-master; };
|
||||
localPkgs = importNixpkgs { flake = local-unstable; };
|
||||
teslamatePkgs = importNixpkgs { flake = teslamate-flake; };
|
||||
agenixPkgs = importNixpkgs { flake = agenix-flake; };
|
||||
pepePkgs = pepeflake.packages.${system} // pepeflake.legacyPackages.${system} or { };
|
||||
|
||||
additionalOverlays = [
|
||||
(final: prev: { inherit unstablePkgs; })
|
||||
(final: prev: { inherit localPkgs; })
|
||||
(final: prev: { inherit teslamatePkgs; })
|
||||
(final: prev: { inherit agenixPkgs; })
|
||||
(final: prev: { inherit masterPkgs; })
|
||||
(final: prev: { inherit pepePkgs; })
|
||||
@ -104,7 +100,7 @@
|
||||
});
|
||||
|
||||
|
||||
pkgsLinuxX64Cuda = wrapPkgsSystem { system = sysLinuxX64; };
|
||||
pkgsLinuxX64Cuda = wrapPkgsSystem { system = sysLinuxX64; cudaSupport = true; };
|
||||
utilsLinuxX64Cuda = wrapUtils { pkgs = pkgsLinuxX64Cuda; };
|
||||
|
||||
pkgsLinuxAarch = wrapPkgsSystem { system = sysLinuxAarch; };
|
||||
@ -122,7 +118,6 @@
|
||||
roles = [ ];
|
||||
}];
|
||||
imports = [
|
||||
teslamate-flake.nixosModules.default
|
||||
agenix-flake.nixosModules.default
|
||||
];
|
||||
};
|
||||
|
@ -17,6 +17,9 @@
|
||||
environmentFile = config.age.secrets.restic-environment.path;
|
||||
repository = "b2:architect:/";
|
||||
paths = [ "/var/lib" "/services" ];
|
||||
exclude = [
|
||||
"/var/lib/ollama"
|
||||
];
|
||||
pruneOpts = [
|
||||
"--keep-daily 45"
|
||||
"--keep-weekly 12"
|
||||
|
@ -1,25 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
domain = "htbaz.giugl.io";
|
||||
in
|
||||
{
|
||||
services.bazarr = {
|
||||
enable = true;
|
||||
group = "media";
|
||||
};
|
||||
|
||||
architect.vhost.${domain} = with config.architect.networks; {
|
||||
dnsInterfaces = [ "tailscale" ];
|
||||
locations."/" = {
|
||||
allowLan = true;
|
||||
port = 6767;
|
||||
|
||||
allow = [
|
||||
tailscale.net
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
users.groups.media.members = [ "bazarr" ];
|
||||
}
|
@ -1,12 +1,9 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
macbookPubkey = (import ../pubkeys.nix).macbook;
|
||||
pubkeys = [ macbookPubkey ];
|
||||
domain = "devs.giugl.io";
|
||||
|
||||
utilities = import ./utilities.nix { inherit lib config; };
|
||||
inherit (utilities) generateDeviceStrings;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
@ -15,46 +12,20 @@ in
|
||||
./hardware.nix
|
||||
./firewall.nix
|
||||
./nginx.nix
|
||||
./gitea.nix
|
||||
./sonarr.nix
|
||||
./radarr.nix
|
||||
./bazarr.nix
|
||||
./nzbget.nix
|
||||
./nextcloud.nix
|
||||
./minio.nix
|
||||
./matrix.nix
|
||||
./fail2ban.nix
|
||||
./dns.nix
|
||||
# ./minecraft.nix
|
||||
./prowlarr.nix
|
||||
./redlib.nix
|
||||
# ./invidious.nix
|
||||
./jellyfin.nix
|
||||
# ./docker.nix
|
||||
./tailscale.nix
|
||||
./headscale.nix
|
||||
./llm.nix
|
||||
# ./photoprism.nix
|
||||
./sunshine.nix
|
||||
./jellyseer.nix
|
||||
./postgres.nix
|
||||
./netdata.nix
|
||||
./homeassistant.nix
|
||||
./searx.nix
|
||||
];
|
||||
|
||||
age.identityPaths = [ "/root/.ssh/id_ed25519" ];
|
||||
|
||||
architect = {
|
||||
networks.lan = {
|
||||
interface = "enp6s0";
|
||||
net = "10.0.0.0/24";
|
||||
devices = {
|
||||
architect = { address = "10.0.0.250"; hostname = "architect.${domain}"; };
|
||||
router = { address = "10.0.0.1"; hostname = "router.${domain}"; };
|
||||
dvr = { address = "10.0.0.3"; hostname = "dvr.${domain}"; };
|
||||
};
|
||||
};
|
||||
|
||||
firewall = {
|
||||
openTCP = [ 22 ];
|
||||
@ -77,8 +48,8 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
kernelParams = with config.architect.networks.lan; [
|
||||
"ip=${devices.architect.address}::${devices.router.address}:255.255.255.0::${interface}:off"
|
||||
kernelParams = with config.pepe.core.network.interfaces.lan; [
|
||||
"ip=${devices.architect.address}::${devices.brigettine.address}:255.255.255.0::${interface}:off"
|
||||
];
|
||||
|
||||
kernel.sysctl = { "net.ipv4.ip_forward" = 1; };
|
||||
@ -96,42 +67,17 @@ in
|
||||
tmp.tmpfsSize = "50%";
|
||||
};
|
||||
|
||||
networking = with config.architect.networks.lan; {
|
||||
networking = with config.pepe.core.network.interfaces.lan; {
|
||||
hostName = "architect";
|
||||
hostId = "49350853";
|
||||
useDHCP = false;
|
||||
defaultGateway = devices.router.address;
|
||||
defaultGateway = devices.brigettine.address;
|
||||
interfaces = {
|
||||
${interface}.ipv4.addresses = [{
|
||||
address = devices.architect.address;
|
||||
prefixLength = 24;
|
||||
}];
|
||||
};
|
||||
extraHosts = (generateDeviceStrings config.architect.networks.lan.devices) + ''
|
||||
|
||||
# Blacklist
|
||||
0.0.0.0 metrics.plex.tv
|
||||
0.0.0.0 analytics.plex.tv
|
||||
0.0.0.0 cdn.luckyorange.com
|
||||
0.0.0.0 w1.luckyorange.com
|
||||
0.0.0.0 browser.sentry-cdn.com
|
||||
0.0.0.0 analytics.facebook.com
|
||||
0.0.0.0 ads.facebook.com
|
||||
0.0.0.0 extmaps-api.yandex.net
|
||||
0.0.0.0 logservice.hicloud.com
|
||||
0.0.0.0 logbak.hicloud.com
|
||||
0.0.0.0 logservice1.hicloud.com
|
||||
0.0.0.0 samsung-com.112.2o7.net
|
||||
0.0.0.0 supportmetrics.apple.com
|
||||
0.0.0.0 analytics.oneplus.cn
|
||||
0.0.0.0 click.oneplus.cn
|
||||
0.0.0.0 analytics-api.samsunghealthcn.com
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.opengl = {
|
||||
enable = true;
|
||||
extraPackages = with pkgs; [ vaapiVdpau ];
|
||||
};
|
||||
|
||||
services = {
|
||||
@ -153,5 +99,177 @@ in
|
||||
};
|
||||
smartd.enable = true;
|
||||
};
|
||||
|
||||
pepe = {
|
||||
core = {
|
||||
media = {
|
||||
enable = true;
|
||||
path = "/media";
|
||||
};
|
||||
|
||||
network.interfaces = {
|
||||
lan = {
|
||||
interface = "enp6s0";
|
||||
type = "lan";
|
||||
net = "10.0.0.0/24";
|
||||
devices = {
|
||||
architect = { address = "10.0.0.250"; hostname = "architect.${domain}"; isEndpoint = true; };
|
||||
brigettine = { address = "10.0.0.1"; hostname = "router.${domain}"; };
|
||||
dreamel10 = { address = "10.0.0.199"; hostname = "dreamel10.${domain}"; };
|
||||
reolinkcamera = { address = "10.0.0.200"; hostname = "reolinkcamera.${domain}"; };
|
||||
lgtv = { address = "10.0.0.202"; hostname = "lgtv.${domain}"; };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
services = {
|
||||
gitea = {
|
||||
enable = true;
|
||||
domain = "git.giugl.io";
|
||||
};
|
||||
|
||||
immich = {
|
||||
enable = true;
|
||||
domain = "photos.giugl.io";
|
||||
package = pkgs.unstablePkgs.immich;
|
||||
};
|
||||
|
||||
radarr = {
|
||||
enable = true;
|
||||
domain = "htrad.giugl.io";
|
||||
package = pkgs.unstablePkgs.radarr;
|
||||
};
|
||||
|
||||
sonarr = {
|
||||
enable = true;
|
||||
domain = "htson.giugl.io";
|
||||
package = pkgs.unstablePkgs.sonarr;
|
||||
};
|
||||
|
||||
bazarr = {
|
||||
enable = true;
|
||||
domain = "htbaz.giugl.io";
|
||||
package = pkgs.unstablePkgs.bazarr;
|
||||
};
|
||||
|
||||
nzbget = {
|
||||
enable = true;
|
||||
domain = "htnzb.giugl.io";
|
||||
package = pkgs.unstablePkgs.nzbget;
|
||||
};
|
||||
|
||||
jellyfin = {
|
||||
enable = true;
|
||||
domain = "media.giugl.io";
|
||||
package = pkgs.unstablePkgs.jellyfin;
|
||||
};
|
||||
|
||||
jellyseer = {
|
||||
enable = true;
|
||||
domain = "aumm-aumm.giugl.io";
|
||||
};
|
||||
|
||||
prowlarr = {
|
||||
enable = true;
|
||||
domain = "htpro.giugl.io";
|
||||
};
|
||||
|
||||
redlib = {
|
||||
enable = true;
|
||||
domain = "reddit.giugl.io";
|
||||
package = pkgs.unstablePkgs.redlib;
|
||||
settings = {
|
||||
REDLIB_ROBOTS_DISABLE_INDEXING = "on";
|
||||
REDLIB_DEFAULT_THEME = "dracula";
|
||||
REDLIB_DEFAULT_SHOW_NSFW = "on";
|
||||
REDLIB_DEFAULT_BLUR_NSFW = "off";
|
||||
REDLIB_DEFAULT_USE_HLS = "on";
|
||||
REDLIB_DEFAULT_HIDE_HLS_NOTIFICATION = "on";
|
||||
};
|
||||
};
|
||||
|
||||
llm = {
|
||||
enable = true;
|
||||
package = pkgs.unstablePkgs.ollama-cuda;
|
||||
backendDomain = "ollama.giugl.io";
|
||||
acceleration = "cuda";
|
||||
};
|
||||
|
||||
homeassistant = {
|
||||
enable = true;
|
||||
package = pkgs.unstablePkgs.home-assistant;
|
||||
domain = "home.giugl.io";
|
||||
extraComponents = [
|
||||
"otbr"
|
||||
"litterrobot"
|
||||
"apple_tv"
|
||||
"homekit"
|
||||
"homekit_controller"
|
||||
"spotify"
|
||||
"hue"
|
||||
"sonos"
|
||||
"tplink"
|
||||
"ollama"
|
||||
"wyoming"
|
||||
"whisper"
|
||||
"piper"
|
||||
"isal"
|
||||
"radarr"
|
||||
"sonarr"
|
||||
"mqtt"
|
||||
"mqtt_eventstream"
|
||||
"mqtt_json"
|
||||
"mqtt_room"
|
||||
"mqtt_statestream"
|
||||
"github"
|
||||
"webostv"
|
||||
"reolink"
|
||||
"onvif"
|
||||
"xiaomi_miio"
|
||||
"ring"
|
||||
];
|
||||
|
||||
extraPackages = python3Packages: with pkgs.unstablePkgs.python3Packages; [
|
||||
pyporscheconnectapi
|
||||
];
|
||||
|
||||
config = {
|
||||
http = {
|
||||
server_host = "127.0.0.1";
|
||||
server_port = 8123;
|
||||
use_x_forwarded_for = true;
|
||||
trusted_proxies = [ "127.0.0.1" ];
|
||||
};
|
||||
homeassistant = {
|
||||
name = "Brigettine Square";
|
||||
latitude = 52.1958;
|
||||
longitude = 0.180746;
|
||||
unit_system = "metric";
|
||||
};
|
||||
default_config = { };
|
||||
automation = "!include automations.yaml";
|
||||
frontend.themes = "!include_dir_merge_named themes";
|
||||
};
|
||||
};
|
||||
|
||||
headscale = {
|
||||
enable = true;
|
||||
domain = "vipienne.giugl.io";
|
||||
settings = with config.pepe.core.network.interfaces.tailscale; {
|
||||
server_url = "https://${domain}";
|
||||
prefixes.v4 = net;
|
||||
dns = {
|
||||
magic_dns = false;
|
||||
override_local_dns = true;
|
||||
global = [ devices.architect.address ];
|
||||
nameservers.global = [ devices.architect.address ];
|
||||
};
|
||||
log.level = "debug";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,70 +1,13 @@
|
||||
{ config, pkgs, ... }:
|
||||
{ ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
generateCoreDNSConfig = domains:
|
||||
let
|
||||
generateForDomain = domain: conf:
|
||||
concatMapStrings
|
||||
(iface:
|
||||
let
|
||||
architectIP = config.architect.networks.${iface}.devices.architect.address;
|
||||
interfaceNet = config.architect.networks.${iface}.net;
|
||||
in
|
||||
''
|
||||
${domain} {
|
||||
view ${iface} {
|
||||
expr incidr(client_ip(), '${interfaceNet}')
|
||||
}
|
||||
|
||||
template IN A ${domain} {
|
||||
answer "${domain}. 60 IN A ${architectIP}"
|
||||
}
|
||||
|
||||
template IN HTTPS ${domain} {
|
||||
answer "${domain}. 60 IN HTTPS 1 . ipv4hint=\"${architectIP}\""
|
||||
}
|
||||
|
||||
cache
|
||||
log
|
||||
}
|
||||
''
|
||||
)
|
||||
conf.dnsInterfaces;
|
||||
in
|
||||
concatStrings (mapAttrsToList generateForDomain domains);
|
||||
|
||||
# Combine vhosts and the single domain
|
||||
allDomains = config.architect.vhost // {
|
||||
"architect.devs.giugl.io" = { dnsInterfaces = [ "lan" "tailscale" ]; };
|
||||
};
|
||||
domain = "adguard.giugl.io";
|
||||
in
|
||||
{
|
||||
architect.vhost.${domain} = with config.architect.networks; {
|
||||
dnsInterfaces = [ "tailscale" "lan" ];
|
||||
locations."/" = {
|
||||
port = config.services.adguardhome.port;
|
||||
allowLan = true;
|
||||
|
||||
allow = [
|
||||
tailscale.net
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
coredns = {
|
||||
enable = true;
|
||||
config = ''
|
||||
${generateCoreDNSConfig allDomains}
|
||||
|
||||
. {
|
||||
cache
|
||||
forward . 45.90.28.77 45.90.30.77
|
||||
}
|
||||
'';
|
||||
pepe.core.dns = {
|
||||
enable = true;
|
||||
nextDNSId = "d65174";
|
||||
extraDomains = {
|
||||
"architect.devs.giugl.io" = {
|
||||
dnsInterfaces = [ "lan" "tailscale" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -7,8 +7,8 @@
|
||||
packageFirewall = pkgs.nftables;
|
||||
bantime-increment.enable = true;
|
||||
ignoreIP = [
|
||||
config.architect.networks.lan.net
|
||||
config.architect.networks.tailscale.net
|
||||
config.pepe.core.network.interfaces.tailscale.net
|
||||
config.pepe.core.network.interfaces.lan.net
|
||||
];
|
||||
};
|
||||
}
|
||||
|
@ -1,20 +1,18 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
openTCP = lib.concatMapStringsSep "," (x: toString x) config.architect.firewall.openTCP;
|
||||
openUDP = lib.concatMapStringsSep "," (x: toString x) config.architect.firewall.openUDP;
|
||||
openTCPVPN = lib.concatMapStringsSep "," (x: toString x) config.architect.firewall.openTCPVPN;
|
||||
openUDPVPN = lib.concatMapStringsSep "," (x: toString x) config.architect.firewall.openUDPVPN;
|
||||
firewallRules = config.pepe.core.firewall;
|
||||
openTCP = lib.concatMapStringsSep "," (x: toString x) firewallRules.openTCP;
|
||||
openUDP = lib.concatMapStringsSep "," (x: toString x) firewallRules.openUDP;
|
||||
ifaces = config.pepe.core.network.interfaces;
|
||||
|
||||
deviceAddress = interface: device:
|
||||
ifaces.${interface}.devices.${device}.address;
|
||||
|
||||
deviceAddress = interface: device:
|
||||
config.architect.networks.${interface}.devices.${device}.address;
|
||||
|
||||
gdevices = [
|
||||
(deviceAddress "tailscale" "architect")
|
||||
(deviceAddress "tailscale" "dodino")
|
||||
(deviceAddress "tailscale" "manduria")
|
||||
(deviceAddress "tailscale" "kmerr")
|
||||
(deviceAddress "tailscale" "chuck")
|
||||
];
|
||||
in
|
||||
{
|
||||
@ -25,7 +23,7 @@ in
|
||||
|
||||
nftables = {
|
||||
enable = true;
|
||||
ruleset = with config.architect.networks; ''
|
||||
ruleset = with config.pepe.core.network.interfaces; ''
|
||||
table ip raw {
|
||||
chain PREROUTING {
|
||||
type filter hook prerouting priority raw; policy accept;
|
||||
|
@ -1,34 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
domain = "git.giugl.io";
|
||||
in
|
||||
{
|
||||
architect = {
|
||||
firewall.openTCP = [ config.services.gitea.settings.server.SSH_PORT ];
|
||||
vhost.${domain} = {
|
||||
dnsInterfaces = [ "lan" "tailscale" ];
|
||||
locations."/" = {
|
||||
port = config.services.gitea.settings.server.HTTP_PORT;
|
||||
allowWAN = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
database.type = "sqlite3";
|
||||
appName = "Gitea";
|
||||
# https://github.com/NixOS/nixpkgs/issues/235442#issuecomment-1574329453
|
||||
lfs.enable = true;
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = domain;
|
||||
ROOT_URL = "https://${domain}";
|
||||
SSH_PORT = 22;
|
||||
HTTP_PORT = 3001;
|
||||
};
|
||||
openid.enable_openid_signin = true;
|
||||
};
|
||||
};
|
||||
}
|
@ -56,7 +56,7 @@
|
||||
options = [ "bind" ];
|
||||
};
|
||||
|
||||
"/media" = {
|
||||
"${config.pepe.core.media.path}" = lib.mkIf config.pepe.core.media.enable {
|
||||
device = "nvmedata/media";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
@ -1,49 +0,0 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
domain = "vipienne.giugl.io";
|
||||
headscalePkg = pkgs.headscale;
|
||||
in
|
||||
{
|
||||
environment.systemPackages = [ headscalePkg ];
|
||||
|
||||
architect = {
|
||||
firewall = {
|
||||
openUDP = [ config.services.tailscale.port ];
|
||||
};
|
||||
|
||||
vhost.${domain} = {
|
||||
dnsInterfaces = [ "lan" "tailscale" ];
|
||||
locations."/" = {
|
||||
port = config.services.headscale.port;
|
||||
allowWAN = true;
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.headscale = {
|
||||
enable = true;
|
||||
package = headscalePkg;
|
||||
port = 1194;
|
||||
|
||||
settings = {
|
||||
server_url = "https://${domain}";
|
||||
# log.level = "debug";
|
||||
dns = {
|
||||
magic_dns = false;
|
||||
# base_domain = domain;
|
||||
override_local_dns = true;
|
||||
global = [
|
||||
config.architect.networks.tailscale.devices.architect.address
|
||||
];
|
||||
nameservers.global = [
|
||||
config.architect.networks.tailscale.devices.architect.address
|
||||
];
|
||||
};
|
||||
logtail.enabled = false;
|
||||
prefixes.v4 = config.architect.networks.tailscale.net;
|
||||
noise.private_key_path = "/var/lib/headscale/noise_private.key";
|
||||
};
|
||||
};
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
domain = "home.giugl.io";
|
||||
piperPort = 10200;
|
||||
whisperPort = 10300;
|
||||
in
|
||||
{
|
||||
services.go2rtc = {
|
||||
enable = true;
|
||||
settings.api.listen = "127.0.0.1:1984";
|
||||
};
|
||||
|
||||
# services.wyoming = {
|
||||
# faster-whisper = {
|
||||
# servers."home" = {
|
||||
# enable = true;
|
||||
# uri = "tcp://127.0.0.1:${toString whisperPort}";
|
||||
# model = "large-v3";
|
||||
# device = "cuda";
|
||||
# language = "en";
|
||||
# };
|
||||
# };
|
||||
# piper = {
|
||||
# servers."home" = {
|
||||
# enable = true;
|
||||
# uri = "tcp://127.0.0.1:${toString piperPort}";
|
||||
# voice = "en-us-ryan-medium";
|
||||
# lengthScale = 0.63;
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
|
||||
services.home-assistant = {
|
||||
enable = true;
|
||||
package = pkgs.unstablePkgs.home-assistant;
|
||||
config = {
|
||||
http = {
|
||||
server_host = "127.0.0.1";
|
||||
server_port = 8123;
|
||||
use_x_forwarded_for = true;
|
||||
trusted_proxies = [ "127.0.0.1" ];
|
||||
};
|
||||
homeassistant = {
|
||||
name = "Brigettine Square";
|
||||
latitude = 52.1958;
|
||||
longitude = 0.180746;
|
||||
unit_system = "metric";
|
||||
};
|
||||
default_config = { };
|
||||
automation = "!include automations.yaml";
|
||||
frontend.themes = "!include_dir_merge_named themes";
|
||||
};
|
||||
|
||||
extraComponents = [
|
||||
"otbr"
|
||||
"litterrobot"
|
||||
"apple_tv"
|
||||
"homekit"
|
||||
"homekit_controller"
|
||||
"spotify"
|
||||
"hue"
|
||||
"sonos"
|
||||
"tplink"
|
||||
"ollama"
|
||||
"wyoming"
|
||||
"whisper"
|
||||
"piper"
|
||||
"isal"
|
||||
"radarr"
|
||||
"sonarr"
|
||||
"mqtt"
|
||||
"mqtt_eventstream"
|
||||
"mqtt_json"
|
||||
"mqtt_room"
|
||||
"mqtt_statestream"
|
||||
"github"
|
||||
"webostv"
|
||||
"reolink"
|
||||
"onvif"
|
||||
"xiaomi_miio"
|
||||
"ring"
|
||||
];
|
||||
|
||||
extraPackages = python3Packages: with pkgs.unstablePkgs.python3Packages; [
|
||||
pyporscheconnectapi
|
||||
];
|
||||
};
|
||||
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [
|
||||
{
|
||||
address = "127.0.0.1";
|
||||
acl = [ "pattern readwrite #" ];
|
||||
omitPasswordAuth = true;
|
||||
settings.allow_anonymous = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
architect.vhost.${domain} = with config.architect.networks; {
|
||||
dnsInterfaces = [ "tailscale" "lan" ];
|
||||
|
||||
locations."/" = {
|
||||
port = config.services.home-assistant.config.http.server_port;
|
||||
allowWAN = true;
|
||||
allowLan = true;
|
||||
proxyWebsockets = true;
|
||||
allow = [
|
||||
tailscale.net
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
domain = "media.giugl.io";
|
||||
port = 8096;
|
||||
allowLan = true;
|
||||
in
|
||||
{
|
||||
# needed since StateDirectory does not accept symlinks
|
||||
systemd.services.jellyfin.serviceConfig.StateDirectory = lib.mkForce "";
|
||||
|
||||
architect.vhost.${domain} = with config.architect.networks; {
|
||||
dnsInterfaces = [ "lan" "tailscale" ];
|
||||
locations = {
|
||||
"/" = {
|
||||
inherit port allowLan;
|
||||
|
||||
allow = [
|
||||
tailscale.net
|
||||
];
|
||||
};
|
||||
|
||||
"/socket" = {
|
||||
inherit port allowLan;
|
||||
|
||||
proxyWebsockets = true;
|
||||
allow = [
|
||||
tailscale.net
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.jellyfin = {
|
||||
enable = true;
|
||||
group = "media";
|
||||
package = pkgs.unstablePkgs.jellyfin;
|
||||
};
|
||||
|
||||
users.groups = {
|
||||
media.members = [ "jellyfin" ];
|
||||
video.members = [ "jellyfin" ];
|
||||
render.members = [ "jellyfin" ];
|
||||
};
|
||||
|
||||
fileSystems."/tmp/jellyfin" = {
|
||||
device = "none";
|
||||
fsType = "tmpfs";
|
||||
options = [ "defaults" "size=20G" "uid=jellyfin" ];
|
||||
};
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
domain = "aumm-aumm.giugl.io";
|
||||
in
|
||||
{
|
||||
services.jellyseerr = {
|
||||
enable = true;
|
||||
# package = pkgs.unstablePkgs.jellyseerr;
|
||||
};
|
||||
|
||||
architect.vhost.${domain} = {
|
||||
dnsInterfaces = [ "tailscale" "lan" ];
|
||||
locations."/" = {
|
||||
port = config.services.jellyseerr.port;
|
||||
allowLan = true;
|
||||
|
||||
allow = [
|
||||
config.architect.networks.tailscale.net
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
backendDomain = "ollama.giugl.io";
|
||||
frontendDomain = "llm.giugl.io";
|
||||
ollamaPkg = pkgs.unstablePkgs.ollama-cuda;
|
||||
uiPkg = pkgs.unstablePkgs.open-webui;
|
||||
tikaPkg = pkgs.unstablePkgs.tika;
|
||||
in
|
||||
{
|
||||
environment = {
|
||||
systemPackages = [ ollamaPkg ];
|
||||
};
|
||||
|
||||
services = {
|
||||
ollama = {
|
||||
enable = true;
|
||||
|
||||
package = ollamaPkg;
|
||||
acceleration = "cuda";
|
||||
environmentVariables = {
|
||||
OLLAMA_FLASH_ATTENTION = "1";
|
||||
OLLAMA_NUM_PARALLEL = "2";
|
||||
OLLAMA_KV_CACHE_TYPE = "q8_0";
|
||||
};
|
||||
};
|
||||
|
||||
open-webui = {
|
||||
enable = true;
|
||||
package = uiPkg;
|
||||
};
|
||||
|
||||
tika = {
|
||||
enable = true;
|
||||
package = tikaPkg;
|
||||
};
|
||||
};
|
||||
|
||||
architect.vhost.${backendDomain} = {
|
||||
dnsInterfaces = [ "tailscale" "lan" ];
|
||||
|
||||
locations."/" = {
|
||||
host = config.services.ollama.host;
|
||||
port = config.services.ollama.port;
|
||||
allowLan = true;
|
||||
allowWAN = true;
|
||||
recommendedProxySettings = false;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
proxy_read_timeout 600s;
|
||||
proxy_set_header Host localhost:${toString config.services.ollama.host};
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
architect.vhost.${frontendDomain} = {
|
||||
dnsInterfaces = [ "tailscale" "lan" ];
|
||||
|
||||
locations."/" = {
|
||||
host = config.services.open-webui.host;
|
||||
port = config.services.open-webui.port;
|
||||
allowLan = true;
|
||||
allowWAN = true;
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
domain = "s3.giugl.io";
|
||||
|
||||
utilities = import ./utilities.nix { inherit lib config; };
|
||||
inherit (utilities) architectInterfaceAddress;
|
||||
in
|
||||
{
|
||||
services = {
|
||||
minio = {
|
||||
enable = true;
|
||||
package = pkgs.minio_legacy_fs;
|
||||
};
|
||||
|
||||
nginx.virtualHosts.${domain} = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:9000";
|
||||
extraConfig = ''
|
||||
client_max_body_size 500M;
|
||||
allow ${config.architect.networks.lan.net};
|
||||
allow ${config.architect.networks.tailscale.net};
|
||||
deny all;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.extraHosts = ''
|
||||
${architectInterfaceAddress "lan"} ${domain}
|
||||
${architectInterfaceAddress "tailscale"} ${domain}
|
||||
'';
|
||||
}
|
@ -22,8 +22,6 @@ in
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
nodejs-18_x
|
||||
libtensorflow
|
||||
ffmpeg
|
||||
];
|
||||
|
||||
@ -60,7 +58,7 @@ in
|
||||
enable = true;
|
||||
hostName = domain;
|
||||
https = true;
|
||||
package = pkgs.nextcloud30;
|
||||
package = pkgs.nextcloud31;
|
||||
datadir = "/services/nextcloud";
|
||||
configureRedis = true;
|
||||
caching = {
|
||||
|
@ -1,148 +1,25 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
options.architect = {
|
||||
firewall = {
|
||||
openTCP = mkOption {
|
||||
type = types.listOf types.int;
|
||||
default = [ ];
|
||||
};
|
||||
openUDP = mkOption {
|
||||
type = types.listOf types.int;
|
||||
default = [ ];
|
||||
};
|
||||
firewall = lib.mkOption {
|
||||
internal = true;
|
||||
default = config.pepe.core.firewall;
|
||||
};
|
||||
|
||||
networks = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
interface = mkOption {
|
||||
type = types.str;
|
||||
description = "The network interface name.";
|
||||
};
|
||||
|
||||
net = mkOption {
|
||||
type = types.str;
|
||||
description = "The network address in CIDR format.";
|
||||
};
|
||||
|
||||
devices = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
description = "The IP address of the device.";
|
||||
};
|
||||
|
||||
hostname = mkOption {
|
||||
type = types.str;
|
||||
description = "The hostname of the device.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "An attribute set of devices with their configurations.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "An attribute set of networks with their configurations.";
|
||||
networks = lib.mkOption {
|
||||
internal = true;
|
||||
default = config.pepe.core.network.interfaces;
|
||||
};
|
||||
|
||||
vhost = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
dnsInterfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = "List of interfaces to add extra DNS hosts for this vhost.";
|
||||
};
|
||||
|
||||
locations = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
extraConfig = mkOption {
|
||||
type = types.str;
|
||||
description = "Extra configuration for the location.";
|
||||
default = "";
|
||||
};
|
||||
|
||||
allowLan = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
proxyWebsockets = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
description = "The host for the location.";
|
||||
default = "127.0.0.1";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
description = "The port number for the location.";
|
||||
};
|
||||
|
||||
allow = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = "IP address or CIDR block to allow.";
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
|
||||
recommendedProxySettings = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Force the use of recommended proxy configuration.";
|
||||
};
|
||||
|
||||
allowWAN = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "If set to false, deny all WAN traffic.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "An attribute set of location configurations.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "An attribute set of domain configurations.";
|
||||
vhost = lib.mkOption {
|
||||
internal = true;
|
||||
default = config.pepe.core.vhost.hosts;
|
||||
};
|
||||
};
|
||||
|
||||
# TODO: move to nginx
|
||||
config = {
|
||||
services.nginx.virtualHosts = mapAttrs
|
||||
(domain: conf: {
|
||||
forceSSL = true;
|
||||
useACMEHost= "giugl.io";
|
||||
locations = mapAttrs
|
||||
(path: location: {
|
||||
proxyPass = "http://${location.host}:${toString location.port}${location.path}";
|
||||
proxyWebsockets = location.proxyWebsockets;
|
||||
recommendedProxySettings = location.recommendedProxySettings;
|
||||
extraConfig = ''
|
||||
${concatMapStringsSep "\n" (allowCIDR: "allow ${allowCIDR};") location.allow}
|
||||
${optionalString location.allowLan ''allow ${config.architect.networks."lan".net};''}
|
||||
${optionalString (!location.allowWAN) "deny all;"}
|
||||
'' + location.extraConfig;
|
||||
})
|
||||
conf.locations;
|
||||
})
|
||||
config.architect.vhost;
|
||||
|
||||
config.architect.networks.docker = {
|
||||
interface = "docker0";
|
||||
net = "172.17.0.0/16";
|
||||
};
|
||||
}
|
||||
|
@ -3,6 +3,6 @@
|
||||
{
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
package = lib.mkForce pkgs.postgresql;
|
||||
package = lib.mkForce pkgs.postgresql_16;
|
||||
};
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
domain = "htpro.giugl.io";
|
||||
in
|
||||
{
|
||||
services.prowlarr = {
|
||||
enable = true;
|
||||
package = pkgs.unstablePkgs.prowlarr;
|
||||
};
|
||||
|
||||
architect.vhost.${domain} = with config.architect.networks; {
|
||||
dnsInterfaces = [ "tailscale" "lan" ];
|
||||
|
||||
locations."/" = {
|
||||
port = 9696;
|
||||
allowLan = true;
|
||||
proxyWebsockets=true;
|
||||
|
||||
allow = [
|
||||
tailscale.net
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
users.groups.media.members = [ "prowlarr" ];
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
domain = "htrad.giugl.io";
|
||||
in
|
||||
{
|
||||
services.radarr = {
|
||||
enable = true;
|
||||
package = pkgs.unstablePkgs.radarr;
|
||||
group = "media";
|
||||
};
|
||||
|
||||
architect.vhost.${domain} = with config.architect.networks; {
|
||||
dnsInterfaces = [ "tailscale" "lan" ];
|
||||
locations."/" = {
|
||||
port = 7878;
|
||||
allowLan = true;
|
||||
|
||||
allow = [
|
||||
tailscale.net
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
users.groups.media.members = [ "radarr" ];
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
domain = "htson.giugl.io";
|
||||
in
|
||||
{
|
||||
services.sonarr = {
|
||||
enable = true;
|
||||
group = "media";
|
||||
package = pkgs.unstablePkgs.sonarr;
|
||||
};
|
||||
|
||||
architect.vhost.${domain} = with config.architect.networks; {
|
||||
dnsInterfaces = [ "tailscale" "lan" ];
|
||||
|
||||
locations."/" = {
|
||||
port = 8989;
|
||||
allowLan = true;
|
||||
allow = [
|
||||
tailscale.net
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
users.groups.media.members = [ "sonarr" ];
|
||||
}
|
@ -38,22 +38,19 @@ let
|
||||
sunshinePkg = (pkgs.unstablePkgs.sunshine.override { cudaSupport = true; });
|
||||
in
|
||||
{
|
||||
pepe.core.graphics = {
|
||||
enable = true;
|
||||
nvidia = true;
|
||||
};
|
||||
|
||||
boot.kernelModules = [ "uinput" ];
|
||||
|
||||
environment.systemPackages = with pkgs.unstablePkgs; [ gamemode heroic ];
|
||||
|
||||
hardware = {
|
||||
pulseaudio.enable = false;
|
||||
|
||||
nvidia = {
|
||||
modesetting.enable = true;
|
||||
powerManagement.enable = false;
|
||||
powerManagement.finegrained = false;
|
||||
open = false;
|
||||
nvidiaSettings = true;
|
||||
package = config.boot.kernelPackages.nvidiaPackages.latest;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.NetworkManager-wait-online.enable = pkgs.lib.mkForce false;
|
||||
programs.steam = {
|
||||
enable = true;
|
||||
@ -159,7 +156,6 @@ in
|
||||
|
||||
xserver = {
|
||||
enable = true;
|
||||
videoDrivers = [ "nvidia" ];
|
||||
desktopManager.xfce.enable = true;
|
||||
|
||||
monitorSection = ''
|
||||
|
@ -7,24 +7,26 @@ let
|
||||
inherit (utilities) generateDeviceStrings;
|
||||
in
|
||||
{
|
||||
architect = {
|
||||
networks.tailscale = {
|
||||
pepe.core = {
|
||||
firewall.openUDP = [ 41641 ];
|
||||
|
||||
network.interfaces.tailscale = {
|
||||
interface = "ts0";
|
||||
net = "100.64.0.0/10";
|
||||
|
||||
type = "vpn";
|
||||
devices = {
|
||||
architect = { address = "100.64.0.1"; hostname = "architect.${domain}"; };
|
||||
architect = { address = "100.64.0.1"; hostname = "architect.${domain}"; isEndpoint = true; };
|
||||
kmerr = { address = "100.64.0.2"; hostname = "kmerr.${domain}"; };
|
||||
parallels = { address = "100.64.0.3"; hostname = "parallels.${domain}"; };
|
||||
chuck = { address = "100.64.0.4"; hostname = "chuck.${domain}"; };
|
||||
dodino = { address = "100.64.0.5"; hostname = "dodino.${domain}"; };
|
||||
work_laptop = { address = "100.64.0.4"; hostname = "work_laptop.${domain}"; };
|
||||
work_desktop = { address = "100.64.0.5"; hostname = "work_desktop.${domain}"; };
|
||||
manduria = { address = "100.64.0.6"; hostname = "manduria.${domain}"; };
|
||||
tommy = { address = "100.64.0.7"; hostname = "tommy.${domain}"; };
|
||||
ucsb-workstation = { address = "100.64.0.8"; hostname = "ucsb-workstation.${domain}"; };
|
||||
alfredo = { address = "100.64.0.9"; hostname = "alfredo.${domain}"; };
|
||||
appletv = { address = "100.64.0.13"; hostname = "appletv.${domain}"; };
|
||||
watkinshouse = { address = "100.64.0.14"; hostname = "watkinshouse.${domain}"; };
|
||||
afsun = { address = "100.64.0.15"; hostname = "afsun.${domain}"; };
|
||||
jacopo-desktop = { address = "100.64.0.21"; hostname = "jacopo-desktop.${domain}"; };
|
||||
jacopo-tv = { address = "100.64.0.22"; hostname = "jacopo-tv.${domain}"; };
|
||||
jacopo-phone = { address = "100.64.0.28"; hostname = "jacopo-phone.${domain}"; };
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -32,10 +34,10 @@ in
|
||||
services = {
|
||||
tailscale = {
|
||||
enable = true;
|
||||
interfaceName = config.architect.networks.tailscale.interface;
|
||||
interfaceName = config.pepe.core.network.interfaces.tailscale.interface;
|
||||
package = pkgs.unstablePkgs.tailscale;
|
||||
};
|
||||
};
|
||||
|
||||
networking.extraHosts = generateDeviceStrings config.architect.networks.tailscale.devices;
|
||||
networking.extraHosts = generateDeviceStrings config.pepe.core.network.interfaces.tailscale.devices;
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
ifaces = config.pepe.core.network.interfaces;
|
||||
in
|
||||
{
|
||||
# device.address device.hostname
|
||||
generateDeviceStrings = devices: lib.concatStringsSep "\n"
|
||||
(lib.mapAttrsToList (name: device: "${device.address} ${device.hostname}") devices);
|
||||
|
||||
|
||||
getDeviceAddress = interface: device:
|
||||
config.architect.networks.${interface}.devices.${device}.address;
|
||||
ifaces.${interface}.devices.${device}.address;
|
||||
|
||||
architectInterfaceAddress = interface:
|
||||
config.architect.networks.${interface}.devices.architect.address;
|
||||
ifaces.${interface}.devices.architect.address;
|
||||
}
|
||||
|
@ -31,13 +31,14 @@
|
||||
(mkSysRole "common")
|
||||
(mkSysRole "acme")
|
||||
(mkUser { name = "root"; roles = [ ]; })
|
||||
../modules
|
||||
];
|
||||
|
||||
home-manager = {
|
||||
useGlobalPkgs = true;
|
||||
};
|
||||
|
||||
system.stateVersion = "24.11";
|
||||
system.stateVersion = "25.05";
|
||||
}
|
||||
|
||||
home-manager.nixosModules.home-manager
|
||||
|
11
modules/core/default.nix
Normal file
11
modules/core/default.nix
Normal file
@ -0,0 +1,11 @@
|
||||
{...}: {
|
||||
imports = [
|
||||
./media.nix
|
||||
./graphics.nix
|
||||
./network.nix
|
||||
./vhost.nix
|
||||
./firewall.nix
|
||||
./dns.nix
|
||||
./docker.nix
|
||||
];
|
||||
}
|
169
modules/core/dns.nix
Normal file
169
modules/core/dns.nix
Normal file
@ -0,0 +1,169 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption types mkIf concatMapStrings concatStrings mapAttrsToList attrsets;
|
||||
cfg = config.pepe.core.dns;
|
||||
in
|
||||
{
|
||||
options.pepe.core.dns = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether to enable the DNS server.";
|
||||
};
|
||||
|
||||
nextDNSId = mkOption {
|
||||
type = types.str;
|
||||
default = "d65174";
|
||||
description = "NextDNS ID for DNS over TLS.";
|
||||
};
|
||||
|
||||
extraDomains = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
dnsInterfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = "List of interfaces to add DNS entries for this domain.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "Additional domains to add to DNS configuration.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.coredns = {
|
||||
enable = true;
|
||||
config =
|
||||
let
|
||||
# Function to generate domain-specific configurations
|
||||
generateDomainConfig = domain: conf: ifaceName:
|
||||
let
|
||||
iface = config.pepe.core.network.interfaces.${ifaceName};
|
||||
|
||||
ifaceEndpoint = lib.head (lib.attrNames (lib.filterAttrs (_: device: device.isEndpoint) iface.devices));
|
||||
serverIP = iface.devices.${ifaceEndpoint}.address;
|
||||
interfaceNet = iface.net;
|
||||
in
|
||||
''
|
||||
${domain} {
|
||||
view ${ifaceName} {
|
||||
expr incidr(client_ip(), '${interfaceNet}')
|
||||
}
|
||||
|
||||
template IN A ${domain} {
|
||||
answer "${domain}. 60 IN A ${serverIP}"
|
||||
}
|
||||
|
||||
template IN HTTPS ${domain} {
|
||||
answer "${domain}. 60 IN HTTPS 1 . ipv4hint=\"${serverIP}\""
|
||||
}
|
||||
|
||||
cache
|
||||
log
|
||||
}
|
||||
'';
|
||||
|
||||
# Function to generate device views for an interface
|
||||
generateDeviceViews = ifaceName:
|
||||
let
|
||||
iface = config.pepe.core.network.interfaces.${ifaceName};
|
||||
in
|
||||
concatMapStrings
|
||||
({ name, device }:
|
||||
let
|
||||
deviceIP = device.address;
|
||||
serverName = "${name}-${cfg.nextDNSId}.dns.nextdns.io";
|
||||
in
|
||||
''
|
||||
. {
|
||||
view ${name} {
|
||||
expr client_ip() == '${deviceIP}'
|
||||
}
|
||||
|
||||
forward . tls://45.90.28.77 tls://45.90.30.77 {
|
||||
tls_servername ${serverName}
|
||||
health_check 5s
|
||||
}
|
||||
}
|
||||
''
|
||||
)
|
||||
(attrsets.mapAttrsToList
|
||||
(name: device: { inherit name device; })
|
||||
iface.devices
|
||||
);
|
||||
|
||||
# Collect all interfaces used across all domains
|
||||
allInterfaces = lib.unique (lib.flatten
|
||||
(lib.mapAttrsToList
|
||||
(_: conf: conf.dnsInterfaces)
|
||||
(config.pepe.core.vhost.hosts // cfg.extraDomains)
|
||||
));
|
||||
|
||||
# Generate all device views once
|
||||
allDeviceViews = concatMapStrings generateDeviceViews allInterfaces;
|
||||
|
||||
# Function to generate configurations for all domains
|
||||
generateCoreDNSConfig = domains:
|
||||
let
|
||||
generateForDomain = domain: conf:
|
||||
concatMapStrings
|
||||
(ifaceName: generateDomainConfig domain conf ifaceName)
|
||||
conf.dnsInterfaces;
|
||||
in
|
||||
concatStrings (mapAttrsToList generateForDomain domains);
|
||||
|
||||
allDomains = config.pepe.core.vhost.hosts // cfg.extraDomains;
|
||||
in
|
||||
let
|
||||
# Function to generate DNS records for individual devices based on dnsResolvableName
|
||||
generateDeviceHostRecords =
|
||||
let
|
||||
generateRecordsForInterface = ifaceName: ifaceConfig:
|
||||
lib.concatStringsSep "\n" (lib.mapAttrsToList
|
||||
(deviceName: deviceConfig:
|
||||
if deviceConfig.hostname!= null then
|
||||
let
|
||||
deviceAddress = deviceConfig.address;
|
||||
deviceIface = ifaceConfig.net;
|
||||
deviceHost = deviceConfig.hostname;
|
||||
in
|
||||
''
|
||||
${deviceHost} {
|
||||
view ${ifaceName} {
|
||||
expr incidr(client_ip(), '${deviceIface}')
|
||||
}
|
||||
|
||||
template IN A ${deviceHost} {
|
||||
answer "${deviceHost}. 60 IN A ${deviceAddress}"
|
||||
}
|
||||
|
||||
cache
|
||||
log
|
||||
}
|
||||
''
|
||||
else ""
|
||||
)
|
||||
ifaceConfig.devices);
|
||||
in
|
||||
lib.concatStringsSep "\n" (lib.mapAttrsToList generateRecordsForInterface config.pepe.core.network.interfaces);
|
||||
in
|
||||
''
|
||||
${generateCoreDNSConfig allDomains}
|
||||
|
||||
${generateDeviceHostRecords}
|
||||
|
||||
${allDeviceViews}
|
||||
|
||||
. {
|
||||
forward . tls://45.90.28.77 tls://45.90.30.77 {
|
||||
tls_servername "lan-${cfg.nextDNSId}.dns.nextdns.io"
|
||||
health_check 5s
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
60
modules/core/docker.nix
Normal file
60
modules/core/docker.nix
Normal file
@ -0,0 +1,60 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.core.docker;
|
||||
in
|
||||
{
|
||||
options.pepe.core.docker = with lib; {
|
||||
enable = mkEnableOption "Enable Docker";
|
||||
nvidia = mkEnableOption "Enable NVIDIA Container Toolkit";
|
||||
dataRoot = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/docker";
|
||||
description = "Docker data root directory";
|
||||
};
|
||||
extraOptions = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = "Extra options for Docker daemon";
|
||||
};
|
||||
enableOnBoot = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Start Docker on boot";
|
||||
};
|
||||
iptables = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether Docker should manipulate iptables";
|
||||
};
|
||||
users = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "Users to add to the docker group";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
hardware.nvidia-container-toolkit.enable = cfg.nvidia;
|
||||
|
||||
virtualisation = {
|
||||
oci-containers.backend = "docker";
|
||||
|
||||
docker = {
|
||||
enable = true;
|
||||
extraOptions = cfg.extraOptions;
|
||||
enableOnBoot = cfg.enableOnBoot;
|
||||
daemon.settings = {
|
||||
iptables = cfg.iptables;
|
||||
data-root = cfg.dataRoot;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
users.users = lib.genAttrs cfg.users (user: {
|
||||
extraGroups = [ "docker" ];
|
||||
});
|
||||
};
|
||||
}
|
27
modules/core/firewall.nix
Normal file
27
modules/core/firewall.nix
Normal file
@ -0,0 +1,27 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
cfg = config.pepe.core.firewall;
|
||||
in
|
||||
{
|
||||
options.pepe.core.firewall = {
|
||||
openTCP = mkOption {
|
||||
type = types.listOf types.int;
|
||||
default = [ ];
|
||||
description = "TCP ports to open in the firewall";
|
||||
};
|
||||
openUDP = mkOption {
|
||||
type = types.listOf types.int;
|
||||
default = [ ];
|
||||
description = "UDP ports to open in the firewall";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = cfg.openTCP;
|
||||
allowedUDPPorts = cfg.openUDP;
|
||||
};
|
||||
};
|
||||
}
|
39
modules/core/graphics.nix
Normal file
39
modules/core/graphics.nix
Normal file
@ -0,0 +1,39 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.core.graphics;
|
||||
in
|
||||
{
|
||||
options.pepe.core.graphics = with lib; {
|
||||
enable = mkEnableOption "Enable graphics";
|
||||
nvidia = mkEnableOption "Enable nvidia graphics";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
hardware = {
|
||||
graphics = {
|
||||
enable = true;
|
||||
extraPackages = with pkgs; mkIf cfg.nvidia [ vaapiVdpau ];
|
||||
};
|
||||
|
||||
nvidia = mkIf cfg.nvidia {
|
||||
modesetting.enable = true;
|
||||
powerManagement.enable = false;
|
||||
powerManagement.finegrained = false;
|
||||
open = false;
|
||||
nvidiaSettings = true;
|
||||
package = config.boot.kernelPackages.nvidiaPackages.latest;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
xserver = {
|
||||
enable = true;
|
||||
videoDrivers = mkIf cfg.nvidia [ "nvidia" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
27
modules/core/media.nix
Normal file
27
modules/core/media.nix
Normal file
@ -0,0 +1,27 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.pepe.core.media;
|
||||
in
|
||||
{
|
||||
options.pepe.core.media = with lib; {
|
||||
enable = mkEnableOption "Enable media library";
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "media";
|
||||
};
|
||||
path = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
groupMembers = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.groups.${cfg.group}.members = [ cfg.group ] ++ cfg.groupMembers;
|
||||
};
|
||||
}
|
||||
|
126
modules/core/network.nix
Normal file
126
modules/core/network.nix
Normal file
@ -0,0 +1,126 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
cfg = config.pepe.core.network;
|
||||
in
|
||||
{
|
||||
options.pepe.core.network = {
|
||||
interfaces = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
interface = mkOption {
|
||||
type = types.str;
|
||||
description = "The network interface name.";
|
||||
};
|
||||
|
||||
type = mkOption {
|
||||
type = types.enum [ "lan" "wan" "vpn" ];
|
||||
description = "The type of interface (lan, wan, or vpn).";
|
||||
};
|
||||
|
||||
net = mkOption {
|
||||
type = types.str;
|
||||
description = "The network address in CIDR format.";
|
||||
};
|
||||
|
||||
devices = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
description = "The IP address of the device.";
|
||||
};
|
||||
|
||||
hostname = mkOption {
|
||||
type = types.str;
|
||||
description = "The hostname of the device.";
|
||||
};
|
||||
|
||||
isEndpoint = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether this device serves as a DNS endpoint for this interface.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "An attribute set of devices with their configurations.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "An attribute set of networks with their configurations.";
|
||||
};
|
||||
|
||||
interfacesByType = mkOption {
|
||||
type = types.attrsOf (types.listOf types.str);
|
||||
default = { };
|
||||
description = "Interfaces grouped by type (lan, wan, vpn) for easy access.";
|
||||
internal = true;
|
||||
};
|
||||
|
||||
dnsEndpoints = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
interface = mkOption {
|
||||
type = types.str;
|
||||
description = "The interface this DNS endpoint belongs to.";
|
||||
};
|
||||
|
||||
device = mkOption {
|
||||
type = types.str;
|
||||
description = "The device name that serves as the DNS endpoint.";
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
description = "The IP address of the DNS endpoint.";
|
||||
};
|
||||
|
||||
serverName = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = "DNS server name for TLS connections.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "DNS endpoints for each interface.";
|
||||
internal = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
# Create lists of interfaces by type for easy access elsewhere
|
||||
pepe.core.network.interfacesByType = {
|
||||
lan = lib.attrNames (lib.filterAttrs (_: iface: iface.type == "lan") cfg.interfaces);
|
||||
wan = lib.attrNames (lib.filterAttrs (_: iface: iface.type == "wan") cfg.interfaces);
|
||||
vpn = lib.attrNames (lib.filterAttrs (_: iface: iface.type == "vpn") cfg.interfaces);
|
||||
};
|
||||
|
||||
# Collect DNS endpoints from all interfaces
|
||||
pepe.core.network.dnsEndpoints =
|
||||
let
|
||||
collectEndpoints = ifaceName: iface:
|
||||
lib.mapAttrs'
|
||||
(deviceName: device:
|
||||
lib.nameValuePair
|
||||
"${ifaceName}-${deviceName}"
|
||||
{
|
||||
interface = ifaceName;
|
||||
device = deviceName;
|
||||
address = device.address;
|
||||
serverName = device.dnsServerName;
|
||||
}
|
||||
)
|
||||
(lib.filterAttrs (_: device: device.isDnsEndpoint) iface.devices);
|
||||
in
|
||||
lib.foldl
|
||||
(acc: ifaceName:
|
||||
acc // (collectEndpoints ifaceName cfg.interfaces.${ifaceName})
|
||||
)
|
||||
{ }
|
||||
(lib.attrNames cfg.interfaces);
|
||||
};
|
||||
}
|
131
modules/core/vhost.nix
Normal file
131
modules/core/vhost.nix
Normal file
@ -0,0 +1,131 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption types mapAttrs concatMapStringsSep optionalString mkIf;
|
||||
cfg = config.pepe.core.vhost;
|
||||
in
|
||||
{
|
||||
options.pepe.core.vhost = {
|
||||
hosts = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
locations = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
extraConfig = mkOption {
|
||||
type = types.str;
|
||||
description = "Extra configuration for the location.";
|
||||
default = "";
|
||||
};
|
||||
|
||||
proxyWebsockets = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
description = "The host for the location.";
|
||||
default = "127.0.0.1";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
description = "The port number for the location.";
|
||||
};
|
||||
|
||||
allow = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = "IP address or CIDR block to allow.";
|
||||
};
|
||||
|
||||
allowVPN = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "If set to true, allow VPN traffic.";
|
||||
};
|
||||
|
||||
allowLAN = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "If set to true, allow LAN traffic.";
|
||||
};
|
||||
|
||||
allowWAN = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "If set to true, allow WAN traffic. If false, deny all WAN traffic.";
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
|
||||
recommendedProxySettings = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Force the use of recommended proxy configuration.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "An attribute set of location configurations.";
|
||||
};
|
||||
|
||||
resolveLocally = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "If true, ensure the vhost is resolvable to 127.0.0.1 locally on this server.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "An attribute set of domain configurations.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
pepe.core.firewall.openTCP = [ 80 443 ];
|
||||
# Configure DNS entries for vhosts when DNS is enabled
|
||||
pepe.core.dns = mkIf config.pepe.core.dns.enable {
|
||||
extraDomains = mapAttrs
|
||||
(domain: conf: {
|
||||
dnsInterfaces =
|
||||
(lib.optionals (lib.any (loc: loc.allowLAN) (lib.attrValues conf.locations))
|
||||
config.pepe.core.network.interfacesByType.lan) ++
|
||||
(lib.optionals (lib.any (loc: loc.allowVPN) (lib.attrValues conf.locations))
|
||||
config.pepe.core.network.interfacesByType.vpn);
|
||||
})
|
||||
cfg.hosts;
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts = mapAttrs
|
||||
(domain: conf: {
|
||||
forceSSL = true;
|
||||
useACMEHost = "giugl.io";
|
||||
locations = mapAttrs
|
||||
(path: location: {
|
||||
proxyPass = "http://${location.host}:${toString location.port}${location.path}";
|
||||
proxyWebsockets = location.proxyWebsockets;
|
||||
recommendedProxySettings = location.recommendedProxySettings;
|
||||
extraConfig = ''
|
||||
${concatMapStringsSep "\n" (allowCIDR: "allow ${allowCIDR};") location.allow}
|
||||
${optionalString location.allowLAN (concatMapStringsSep "\n" (ifaceName: "allow ${config.pepe.core.network.interfaces.${ifaceName}.net};") config.pepe.core.network.interfacesByType.lan)}
|
||||
${optionalString location.allowVPN (concatMapStringsSep "\n" (ifaceName: "allow ${config.pepe.core.network.interfaces.${ifaceName}.net};") config.pepe.core.network.interfacesByType.vpn)}
|
||||
${optionalString (!location.allowWAN) "deny all;"}
|
||||
'' + location.extraConfig;
|
||||
})
|
||||
conf.locations;
|
||||
})
|
||||
cfg.hosts;
|
||||
|
||||
networking.extraHosts = lib.concatStringsSep "\n" (lib.flatten (lib.mapAttrsToList
|
||||
(domain: hostConf:
|
||||
lib.optionals hostConf.resolveLocally "127.0.0.1 ${domain}"
|
||||
)
|
||||
cfg.hosts
|
||||
));
|
||||
};
|
||||
}
|
7
modules/default.nix
Normal file
7
modules/default.nix
Normal file
@ -0,0 +1,7 @@
|
||||
{ ... }: {
|
||||
imports = [
|
||||
./services
|
||||
./core
|
||||
];
|
||||
}
|
||||
|
35
modules/services/bazarr/default.nix
Normal file
35
modules/services/bazarr/default.nix
Normal file
@ -0,0 +1,35 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.bazarr;
|
||||
in
|
||||
{
|
||||
options.pepe.services.bazarr = with lib; {
|
||||
enable = mkEnableOption "Enable bazarr";
|
||||
package = mkPackageOption pkgs "bazarr" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.bazarr = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
group = "media";
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
port = 6767;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
};
|
||||
};
|
||||
|
||||
pepe.core.media.groupMembers = mkIf config.pepe.core.media.enable [ "bazarr" ];
|
||||
};
|
||||
}
|
20
modules/services/default.nix
Normal file
20
modules/services/default.nix
Normal file
@ -0,0 +1,20 @@
|
||||
{ ... }: {
|
||||
imports = [
|
||||
./bazarr
|
||||
./gitea
|
||||
./homeassistant
|
||||
./immich
|
||||
./jellyfin
|
||||
./jellyseer
|
||||
./lidarr
|
||||
./llm
|
||||
./minio
|
||||
./navidrome
|
||||
./nzbget
|
||||
./prowlarr
|
||||
./radarr
|
||||
./redlib
|
||||
./sonarr
|
||||
./headscale
|
||||
];
|
||||
}
|
53
modules/services/gitea/default.nix
Normal file
53
modules/services/gitea/default.nix
Normal file
@ -0,0 +1,53 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.gitea;
|
||||
in
|
||||
{
|
||||
options.pepe.services.gitea = with lib; {
|
||||
enable = mkEnableOption "Enable gitea";
|
||||
package = mkPackageOption pkgs "gitea" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
pepe.core = {
|
||||
firewall.openTCP = [ config.services.gitea.settings.server.SSH_PORT ];
|
||||
vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
port = config.services.gitea.settings.server.HTTP_PORT;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
allowWAN = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
database.type = "sqlite3";
|
||||
appName = "Gitea";
|
||||
# https://github.com/NixOS/nixpkgs/issues/235442#issuecomment-1574329453
|
||||
lfs.enable = true;
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = cfg.domain;
|
||||
ROOT_URL = "https://${cfg.domain}";
|
||||
SSH_PORT = 22;
|
||||
HTTP_PORT = 3001;
|
||||
};
|
||||
service = {
|
||||
DISABLE_REGISTRATION = true;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
}
|
59
modules/services/headscale/default.nix
Normal file
59
modules/services/headscale/default.nix
Normal file
@ -0,0 +1,59 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.headscale;
|
||||
in
|
||||
{
|
||||
options.pepe.services.headscale = with lib; {
|
||||
enable = mkEnableOption "Enable Headscale";
|
||||
package = mkPackageOption pkgs "headscale" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
description = "Domain for the Headscale service.";
|
||||
};
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "Host for the Headscale service.";
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 1194;
|
||||
description = "Port for the Headscale service.";
|
||||
};
|
||||
settings = mkOption {
|
||||
type = types.attrsOf types.anything;
|
||||
default = { };
|
||||
description = "Arbitrary configuration settings for Headscale.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
services.headscale = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
port = cfg.port;
|
||||
settings = cfg.settings;
|
||||
};
|
||||
|
||||
pepe.core = {
|
||||
firewall.openUDP = [ cfg.port ];
|
||||
vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
host = cfg.host;
|
||||
port = cfg.port;
|
||||
allowWAN = true;
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
|
||||
proxy_buffering off;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
69
modules/services/homeassistant/default.nix
Normal file
69
modules/services/homeassistant/default.nix
Normal file
@ -0,0 +1,69 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.homeassistant;
|
||||
in
|
||||
{
|
||||
options.pepe.services.homeassistant = with lib; {
|
||||
enable = mkEnableOption "Enable Home Assistant";
|
||||
package = mkPackageOption pkgs "home-assistant" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
extraComponents = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "Additional components to enable in Home Assistant";
|
||||
};
|
||||
extraPackages = mkOption {
|
||||
type = types.functionTo (types.listOf types.package);
|
||||
default = _: [];
|
||||
description = "Additional Python packages for Home Assistant";
|
||||
};
|
||||
config = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
description = "Home Assistant configuration";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.home-assistant = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
extraComponents = cfg.extraComponents;
|
||||
extraPackages = cfg.extraPackages;
|
||||
config = cfg.config;
|
||||
};
|
||||
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [
|
||||
{
|
||||
address = "127.0.0.1";
|
||||
acl = [ "pattern readwrite #" ];
|
||||
omitPasswordAuth = true;
|
||||
settings.allow_anonymous = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.go2rtc = {
|
||||
enable = true;
|
||||
settings.api.listen = "127.0.0.1:1984";
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
port = config.services.home-assistant.config.http.server_port or 8123;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
allowWAN = true;
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
42
modules/services/immich/default.nix
Normal file
42
modules/services/immich/default.nix
Normal file
@ -0,0 +1,42 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.pepe.services.immich;
|
||||
in
|
||||
{
|
||||
options.pepe.services.immich = with lib; {
|
||||
enable = mkEnableOption "Enable immich";
|
||||
package = mkPackageOption pkgs "immich" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
immich = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
# accelerationDevices = null;
|
||||
};
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
host = "[::1]";
|
||||
port = config.services.immich.port;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
allowWAN = true;
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
# allow large file uploads
|
||||
client_max_body_size 50000M;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
users.users.immich.extraGroups = [ "video" "render" "media" "nextcloud" ];
|
||||
};
|
||||
}
|
63
modules/services/jellyfin/default.nix
Normal file
63
modules/services/jellyfin/default.nix
Normal file
@ -0,0 +1,63 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf mkForce;
|
||||
|
||||
cfg = config.pepe.services.jellyfin;
|
||||
in
|
||||
{
|
||||
options.pepe.services.jellyfin = with lib; {
|
||||
enable = mkEnableOption "Enable jellyfin";
|
||||
package = mkPackageOption pkgs "jellyfin" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
tmpfsSize = mkOption {
|
||||
type = types.str;
|
||||
default = "20G";
|
||||
description = "Size of the tmpfs mount for Jellyfin";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# needed since StateDirectory does not accept symlinks
|
||||
systemd.services.jellyfin.serviceConfig.StateDirectory = mkForce "";
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = {
|
||||
locations = {
|
||||
"/" = {
|
||||
port = 8096;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
};
|
||||
|
||||
"/socket" = {
|
||||
port = 8096;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.jellyfin = {
|
||||
enable = true;
|
||||
group = "media";
|
||||
package = cfg.package;
|
||||
};
|
||||
|
||||
users.groups = {
|
||||
video.members = [ "jellyfin" ];
|
||||
render.members = [ "jellyfin" ];
|
||||
};
|
||||
|
||||
pepe.core.media.groupMembers = mkIf config.pepe.core.media.enable [ "jellyfin" ];
|
||||
|
||||
fileSystems."/tmp/jellyfin" = {
|
||||
device = "none";
|
||||
fsType = "tmpfs";
|
||||
options = [ "defaults" "size=${cfg.tmpfsSize}" "uid=jellyfin" ];
|
||||
};
|
||||
};
|
||||
}
|
32
modules/services/jellyseer/default.nix
Normal file
32
modules/services/jellyseer/default.nix
Normal file
@ -0,0 +1,32 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.jellyseer;
|
||||
in
|
||||
{
|
||||
options.pepe.services.jellyseer = with lib; {
|
||||
enable = mkEnableOption "Enable jellyseer";
|
||||
package = mkPackageOption pkgs "jellyseerr" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.jellyseerr = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
port = config.services.jellyseerr.port;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
36
modules/services/lidarr/default.nix
Normal file
36
modules/services/lidarr/default.nix
Normal file
@ -0,0 +1,36 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.lidarr;
|
||||
in
|
||||
{
|
||||
options.pepe.services.lidarr = with lib; {
|
||||
enable = mkEnableOption "Enable lidarr";
|
||||
package = mkPackageOption pkgs "lidarr" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.lidarr = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
group = "media";
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = with config.pepe.core.network; {
|
||||
dnsInterfaces = [ interfaceTypes.lan interfaceTypes.vpn ];
|
||||
locations."/" = {
|
||||
port = 8686;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
};
|
||||
};
|
||||
|
||||
pepe.core.media.groupMembers = mkIf config.pepe.core.media.enable [ "lidarr" ];
|
||||
};
|
||||
}
|
110
modules/services/llm/default.nix
Normal file
110
modules/services/llm/default.nix
Normal file
@ -0,0 +1,110 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf mkEnableOption mkPackageOption mkOption types optionalAttrs mkMerge;
|
||||
|
||||
cfg = config.pepe.services.llm;
|
||||
in
|
||||
{
|
||||
options.pepe.services.llm = {
|
||||
enable = mkEnableOption "Enable LLM backend service (Ollama)";
|
||||
|
||||
package = mkPackageOption pkgs "ollama" { };
|
||||
|
||||
backendDomain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Domain for Ollama backend. If null, no vhost is created for the backend.";
|
||||
};
|
||||
|
||||
acceleration = mkOption {
|
||||
type = types.enum [ "none" "cuda" "rocm" ];
|
||||
default = "none";
|
||||
description = "Acceleration type for Ollama";
|
||||
};
|
||||
|
||||
environmentVariables = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {
|
||||
OLLAMA_FLASH_ATTENTION = "1";
|
||||
OLLAMA_NUM_PARALLEL = "2";
|
||||
OLLAMA_KV_CACHE_TYPE = "q8_0";
|
||||
};
|
||||
description = "Environment variables for Ollama";
|
||||
};
|
||||
|
||||
frontend = {
|
||||
enable = mkEnableOption "Enable LLM frontend service (Open WebUI)"; # Defaults to false
|
||||
uiPackage = mkPackageOption pkgs "open-webui" { };
|
||||
tikaPackage = mkPackageOption pkgs "tika" { }; # Tika for document processing with Open WebUI
|
||||
domain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Domain for Open WebUI frontend. If null, no vhost is created for the frontend.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
# Combined environment packages
|
||||
{
|
||||
environment.systemPackages =
|
||||
(if cfg.enable then [ cfg.package ] else [ ]) ++
|
||||
(if cfg.enable && cfg.frontend.enable then [ cfg.frontend.uiPackage cfg.frontend.tikaPackage ] else [ ]);
|
||||
}
|
||||
|
||||
# Backend Ollama Service Configuration
|
||||
(mkIf cfg.enable {
|
||||
services.ollama = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
acceleration = cfg.acceleration;
|
||||
environmentVariables = cfg.environmentVariables;
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts = optionalAttrs (cfg.backendDomain != null) {
|
||||
"${cfg.backendDomain}" = {
|
||||
locations."/" = {
|
||||
host = config.services.ollama.host;
|
||||
port = config.services.ollama.port;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
allowWAN = true;
|
||||
recommendedProxySettings = false;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
proxy_read_timeout 600s; # Ollama can take time to respond
|
||||
proxy_set_header Host localhost:${toString config.services.ollama.port};
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
# Frontend Open WebUI and Tika Service Configuration
|
||||
(mkIf (cfg.enable && cfg.frontend.enable) {
|
||||
services.open-webui = {
|
||||
enable = true;
|
||||
package = cfg.frontend.uiPackage;
|
||||
};
|
||||
|
||||
services.tika = {
|
||||
enable = true;
|
||||
package = cfg.frontend.tikaPackage;
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts = optionalAttrs (cfg.frontend.domain != null) {
|
||||
"${cfg.frontend.domain}" = {
|
||||
locations."/" = {
|
||||
host = config.services.open-webui.host;
|
||||
port = config.services.open-webui.port;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
allowWAN = true;
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
35
modules/services/minio/default.nix
Normal file
35
modules/services/minio/default.nix
Normal file
@ -0,0 +1,35 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.minio;
|
||||
in
|
||||
{
|
||||
options.pepe.services.minio = with lib; {
|
||||
enable = mkEnableOption "Enable MinIO S3-compatible object storage";
|
||||
package = mkPackageOption pkgs "minio" {};
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.minio = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
port = 9000;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
extraConfig = ''
|
||||
client_max_body_size 500M;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
84
modules/services/navidrome/default.nix
Normal file
84
modules/services/navidrome/default.nix
Normal file
@ -0,0 +1,84 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.navidrome;
|
||||
in
|
||||
{
|
||||
options.pepe.services.navidrome = with lib; {
|
||||
enable = mkEnableOption "Enable navidrome";
|
||||
package = mkPackageOption pkgs "navidrome" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
musicFolder = mkOption {
|
||||
type = types.str;
|
||||
default = "/media/Music";
|
||||
description = "Path to the music library";
|
||||
};
|
||||
beetsConfig = mkOption {
|
||||
type = types.str;
|
||||
default = "/media/beets.conf";
|
||||
description = "Path to the beets configuration file";
|
||||
};
|
||||
settings = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
description = "Additional settings for Navidrome";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.navidrome = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
settings = {
|
||||
MusicFolder = cfg.musicFolder;
|
||||
LastFM.enable = true;
|
||||
LastFM.ApiKey = "5cef5cb5f9d31326b97d0f929ca9cf20";
|
||||
LastFM.Secret = "d1296896126f4caae47407aecf080b25";
|
||||
Spotify.ID = "3900c029b4f34f3fb61d554dda64794d";
|
||||
Spotify.Secret = "d931ce5575a9401aa5ff8d37558cca0a";
|
||||
EnableGravatar = true;
|
||||
LogLevel = "WARN";
|
||||
} // cfg.settings;
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = with config.pepe.core.network; {
|
||||
dnsInterfaces = [ interfaceTypes.lan interfaceTypes.vpn ];
|
||||
locations."/" = {
|
||||
port = 4533;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
allowWAN = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
"beets-update" = {
|
||||
enable = true;
|
||||
before = [ "beets-import.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.beets}/bin/beet -c ${cfg.beetsConfig} update";
|
||||
};
|
||||
};
|
||||
|
||||
"beets-import" = {
|
||||
enable = true;
|
||||
path = [ pkgs.imagemagick ];
|
||||
requires = [ "beets-update.service" ];
|
||||
after = [ "beets-update.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.beets}/bin/beet -c ${cfg.beetsConfig} import --flat -q ${cfg.musicFolder}";
|
||||
};
|
||||
startAt = "weekly";
|
||||
};
|
||||
};
|
||||
|
||||
pepe.core.media.groupMembers = mkIf config.pepe.core.media.enable [ "navidrome" ];
|
||||
};
|
||||
}
|
35
modules/services/nzbget/default.nix
Normal file
35
modules/services/nzbget/default.nix
Normal file
@ -0,0 +1,35 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.nzbget;
|
||||
in
|
||||
{
|
||||
options.pepe.services.nzbget = with lib; {
|
||||
enable = mkEnableOption "Enable nzbget";
|
||||
package = mkPackageOption pkgs "nzbget" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.nzbget = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
group = "media";
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
port = 6789;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
};
|
||||
};
|
||||
|
||||
pepe.core.media.groupMembers = mkIf config.pepe.core.media.enable [ "nzbget" ];
|
||||
};
|
||||
}
|
35
modules/services/prowlarr/default.nix
Normal file
35
modules/services/prowlarr/default.nix
Normal file
@ -0,0 +1,35 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.prowlarr;
|
||||
in
|
||||
{
|
||||
options.pepe.services.prowlarr = with lib; {
|
||||
enable = mkEnableOption "Enable prowlarr";
|
||||
package = mkPackageOption pkgs "prowlarr" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.prowlarr = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
port = 9696;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
|
||||
pepe.core.media.groupMembers = mkIf config.pepe.core.media.enable [ "prowlarr" ];
|
||||
};
|
||||
}
|
34
modules/services/radarr/default.nix
Normal file
34
modules/services/radarr/default.nix
Normal file
@ -0,0 +1,34 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.radarr;
|
||||
in
|
||||
{
|
||||
options.pepe.services.radarr = with lib; {
|
||||
enable = mkEnableOption "Enable radarr";
|
||||
package = mkPackageOption pkgs "radarr" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.radarr = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
port = 7878;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
};
|
||||
};
|
||||
|
||||
pepe.core.media.groupMembers = mkIf config.pepe.core.media.enable [ config.services.radarr.group ];
|
||||
};
|
||||
}
|
48
modules/services/redlib/default.nix
Normal file
48
modules/services/redlib/default.nix
Normal file
@ -0,0 +1,48 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.redlib;
|
||||
in
|
||||
{
|
||||
options.pepe.services.redlib = with lib; {
|
||||
enable = mkEnableOption "Enable Redlib";
|
||||
package = mkPackageOption pkgs "redlib" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
settings = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {
|
||||
REDLIB_ROBOTS_DISABLE_INDEXING = "on";
|
||||
REDLIB_DEFAULT_THEME = "dracula";
|
||||
REDLIB_DEFAULT_SHOW_NSFW = "on";
|
||||
REDLIB_DEFAULT_BLUR_NSFW = "off";
|
||||
REDLIB_DEFAULT_USE_HLS = "on";
|
||||
REDLIB_DEFAULT_HIDE_HLS_NOTIFICATION = "on";
|
||||
};
|
||||
description = "Environment variables for Redlib configuration";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.redlib = {
|
||||
enable = true;
|
||||
port = 9090;
|
||||
package = cfg.package;
|
||||
};
|
||||
|
||||
systemd.services.redlib.environment = cfg.settings;
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
port = config.services.redlib.port;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
allowWAN = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
34
modules/services/sonarr/default.nix
Normal file
34
modules/services/sonarr/default.nix
Normal file
@ -0,0 +1,34 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.pepe.services.sonarr;
|
||||
in
|
||||
{
|
||||
options.pepe.services.sonarr = with lib; {
|
||||
enable = mkEnableOption "Enable sonarr";
|
||||
package = mkPackageOption pkgs "sonarr" { };
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.sonarr = {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
};
|
||||
|
||||
pepe.core.vhost.hosts.${cfg.domain} = {
|
||||
locations."/" = {
|
||||
port = 8989;
|
||||
allowLAN = true;
|
||||
allowVPN = true;
|
||||
};
|
||||
};
|
||||
|
||||
pepe.core.media.groupMembers = mkIf config.pepe.core.media.enable [ config.services.sonarr.group ];
|
||||
};
|
||||
}
|
@ -4,22 +4,22 @@ let
|
||||
giuglioDomain = "giugl.io";
|
||||
in
|
||||
{
|
||||
age.secrets.ovh = {
|
||||
file = ../secrets/ovh.age;
|
||||
age.secrets.cloudflare = {
|
||||
file = ../secrets/cloudflare.age;
|
||||
owner = "acme";
|
||||
};
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
certs.${giuglioDomain} =
|
||||
{
|
||||
dnsProvider = "ovh";
|
||||
environmentFile = config.age.secrets.ovh.path;
|
||||
dnsProvider = "cloudflare";
|
||||
environmentFile = config.age.secrets.cloudflare.path;
|
||||
extraDomainNames = [ "*.${giuglioDomain}" ];
|
||||
};
|
||||
defaults = {
|
||||
email = "letsencrypt@depasquale.giugl.io";
|
||||
dnsProvider = "ovh";
|
||||
environmentFile = config.age.secrets.ovh.path;
|
||||
dnsProvider = "cloudflare";
|
||||
environmentFile = config.age.secrets.cloudflare.path;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ in
|
||||
sessionVariables = {
|
||||
AICHAT_CONFIG_DIR = configDir;
|
||||
};
|
||||
packages = [ pkgs.unstablePkgs.aichat ];
|
||||
packages = [ pkgs.aichat ];
|
||||
|
||||
file.".config/aichat/config.yaml".text = lib.readFile ./aichat/config.yaml;
|
||||
file.".config/aichat/roles/commitmessage.md".text = lib.readFile ./aichat/roles/commitmessage.md;
|
||||
|
@ -15,9 +15,7 @@ let
|
||||
tree
|
||||
] ++ lib.optional (!pkgs.stdenv.isDarwin) pastebinit;
|
||||
|
||||
unstablePkgs = with pkgs.unstablePkgs; [
|
||||
aider-chat-full
|
||||
];
|
||||
unstablePkgs = with pkgs.unstablePkgs; [ aider-chat ];
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
@ -28,7 +26,7 @@ in
|
||||
|
||||
home = {
|
||||
packages = stablePkgs ++ unstablePkgs;
|
||||
|
||||
stateVersion = "24.11";
|
||||
|
||||
stateVersion = "25.05";
|
||||
};
|
||||
}
|
||||
|
28
secrets/cloudflare.age
Normal file
28
secrets/cloudflare.age
Normal file
@ -0,0 +1,28 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-rsa QXZdow
|
||||
pLJHkOUl7t8yhuq+vytj+LHENNT71NJH/gS4cEMNhEkzZjc8ScSrhVgLl/TMGImh
|
||||
cb6yfRIccymVLL8gdXitIAk1srZjuwiZrFK4Ril/x8RKfV50GrHDMf+8Os3QNE05
|
||||
VprnYCbyKj05+/fHSSUDnQmAAe7wvi4iA2Aa5E4DWE7t+QcMB5epPMBdJoWX6ELS
|
||||
cYI7nDu32AIkYCODht9B5SChbwHACLqqG8CV5N2TfRBi6v7R2FaLhbbRvdAIQWQc
|
||||
x2TGI1utRURtxgs/WhQ6Sco1QNrIEO89a/78OGxrIT/PMAukvx2J2WG6iH/2LgX0
|
||||
H39680n3/YTTmL4OMWW+hKlzv4tdBsbgjR0sKRI/OzDrn/s0ZzA1JACwUn2ndOS/
|
||||
0EcvW5VLLd2PHvwABm2Biw7mhilC4D6d9YZu/9uFbmPCzlXO3zmeeSnw630gDWxX
|
||||
CRTEQMNE7+cdQy8j/upDBQOBnSSgmBMriuklsgcPZGnTkxWM7b9NOAeXavTucXhD
|
||||
9PART4hQomlvGBzKM6Ien9kgeDG9OA9WkM+2rvLWQLDy3T9Qo37d/4qLg3sPNr4M
|
||||
NUUSKRQKnA7i126ZrX/mUxcp3kJkCAsMX4GF6VMVobXshCSHqKhEWKwHuyPWI4rn
|
||||
gHUqvSMKDujkA6v+9UaZESQt8jKl+N44MDUMdfYwPyE
|
||||
-> ssh-ed25519 7eGqHw WIUvcH8xsrI0AcutXKxwhbrZifrb8vntIWCGDUW3qiI
|
||||
3IuBdZRAGA/nfEuakP2/E+QA07jBJjBlNtotGLZlkZQ
|
||||
-> ssh-rsa tO3rGg
|
||||
DOBhMzioILjlrOAdycMzSwDxgww5p8QAlV/L7ECBrBFscoWageW4GOyZVjtE/7Ot
|
||||
beG59oP8ra4lczXfPSOtY2qz8pN59vqw3WqG3TPMvR8xZDslVXE8nubfkoUohsG8
|
||||
1ZibaP/ygQSYHUfnLzebYBhk1N4u6jeIcxJXgTLhWLlvkv9+AKAcoHhSWVbKMbz+
|
||||
i8WLECJHuOeR43hJxuxvkPTWsu6HUB+yXT1J+dPcIe9W20CqX+CN0pjwSUJu0T0A
|
||||
tZf2NfkYmFnho2IEdxdKnGRDE2lvQmZjf1oQn7GWFqywlVB3eCOR6K/s1Tb4I2W1
|
||||
wybLuEndQBnUsUDQVs34OeN/5L3Pw40zksFSSVe3Fu5XxmWl1WemGWp1/jB7j6u7
|
||||
7bnOlAMUzpqQ9yom0oxXYwEC9pUtqPwYGKeAV9o5U3vVXMDWtEXXMCe0oDjJY8js
|
||||
e5xSOuaMi9CcVkU+HyjrEgw0uS4ymDWVghT4IVl8zNWeare5ALMcR/290xffaQyg
|
||||
|
||||
--- DIW17nFtjI4Oo+Qoi0YzeLH8A6IVAQwhtELkXWWhtwo
|
||||
D*;ôCx<08>Auçdrß¾ö0ð£ú1Ldæoòr´&<26>JL4WíÌ!‚²=ê7:pÀØí*ûpVÙK³,0®rλâãu¼¡ã‹¶óWEâ{£q½7,Ôßÿk“¾²<C2BE>ºÎàäxÔ+^xDâº0g“K,ª(zØwáC˘þ è{d}-FÜ
|
||||
õ<EFBFBD>Ëþ¦TÌÍA„
|
@ -1,29 +0,0 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-rsa QXZdow
|
||||
aYgowxTfdGOqTYOZBbkg/dH7f+m6nvVF/8qZX0DE4hazln/QS9maWbkOwD7FLldm
|
||||
HRNV/YwZZEhbujHbDqgxnXk7Q11KOA72864B6mF2VZUruyo0cnACqo7OyzwApqv/
|
||||
+LPjGb9h/gCJpQ3a5Jdh202FfaNGAh358fZVDyd37XPSOykiIAAxgMlDyn+96OiM
|
||||
P2vsyduWXDsqzCqtiNQrKVjryI5CIGOTAcYTgQ35S3uXFD8Gu27KfagUwZp2hdyp
|
||||
3WmGl+ZTrPNdOwzLWGj/RXaeTslABn1Owmq1naASRvJpp97ToynRzkDA50rBqUyR
|
||||
vGVB9IJxSjkSm3BJ4UAI6rpoz/6t2jkfNNE1cPix4AYjPAMyU+uiUSaZ/UBkwlXw
|
||||
08rM1eGcBaErB1ExcDV5+jUCdJBfi6Q9vIG7Ty4wbN1PfztAhzEyzT0L1bTn1AKC
|
||||
4S9n5lqFa1CdraK9eh2A+o9CNlkta+Z24ctPTVqBYtImBTKHOTofhr0omQdFV6M2
|
||||
bhxsOoAAoNhwn/lWC2fAcgfPQrUOW524+eHyPjsvf4rNNv0bk5EP1J4vMrWr9rqJ
|
||||
v5GEQ77YVXYQthiyg74XYc3Eo8sbtE+ncDoOquzdT385POd870qi1ht+JMY6OEmj
|
||||
q8lxVau2SFTKPkkmZKmtoNrYdKp5+DsB3nOUKcIXofs
|
||||
-> ssh-ed25519 7eGqHw cCrhq1kfav4TYAUOpP4O6fQ958O37Uad2jX9SUrnxn4
|
||||
TSiMyrYsdblB5SFwZpw7HhmicWX1vNomhBP4HtlvHJo
|
||||
-> ssh-rsa tO3rGg
|
||||
J6oPMt6hiry6ks3hlAjUAY1AzEYU+7voto5XC+I6Fmyfabz9zaJ3TtbCPVF5BRNR
|
||||
DOYLiD24EbcVoqECn2A2MRK1xH4owBD5YaE3Il2NwSJHhC+ZhROaMTu5mHxbzK/u
|
||||
BF2MLRZ0Bwwq4szaHoFf12TFwNtIRZXS9m6l4jHdsxWj6x0iui18p3JLxij1cVwE
|
||||
03rSWz+9c8bpZ6LHuPJAhatBZHSZwkKwH8Dn8NOxCLmVNRM4PyvJsj9lRn7fMwRY
|
||||
64QI2z6bRAry6oINbVAAOsPlM0Ix+7hbFs/UstnENFqfcDvPzrrhALDhuDLIJpGu
|
||||
WgAaMStZGjydy0oqHJceuduxVreqTlfiki7yruRFqRBgjMopwOsw5i9UPWR6SZ+E
|
||||
cUCFeEynUMrmFSp5qvDX0WtkU2G/GRFEPaB+k+UN+JduIRb2RBCLt2uG0249TwO8
|
||||
T4sq098XTM8wARgOv6n51lHFCPpM3iSbP5KMCYH9FhsJV0Qu9Q7157McNZuVL9Ie
|
||||
|
||||
--- KYLAPCcTkg/tF2c2ni4UaBTV5AhUleg8GgJH0oRQSK0
|
||||
½;¬jŒ<6A>a羄ïÓÄ<C393>5`hÂŒø»æy;JúãÈå³C¢µ‡£ÏwX:eßøw³ù»ÜH
|
||||
L<EFBFBD>he’jCÓ2¨ì"#˵„=Î/Dzˆ1ÒÅÿ¼™^Nû$ÃéM·úqN…v1µØÁ–Ç”ç¸T¦ÌñÙ—Ç0FsÕ(WeõöË…¡˜Ý8|^‹iYFQæ3œ ¡Õ
|
||||
A¤1ïEÜÂÚM_=;•¸‚×jFÜVý[Ýät°¬{©
w×…Ê<E280A6>Ö)
|
@ -11,5 +11,5 @@ in
|
||||
"nextcloud-database.age".publicKeys = pubkeys;
|
||||
"restic-environment.age".publicKeys = pubkeys;
|
||||
"restic-passwords.age".publicKeys = pubkeys;
|
||||
"ovh.age".publicKeys = pubkeys;
|
||||
"cloudflare.age".publicKeys = pubkeys;
|
||||
}
|
||||
|
@ -1,14 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# this guy updates the hash of the last
|
||||
# successful build of nixpkgs on hydra
|
||||
# (so we don't have to rebuild EVERYTHING)
|
||||
RELEASE=24.11
|
||||
RELEASE=25.05
|
||||
|
||||
new=$(curl -sL "https://monitoring.nixos.org/prometheus/api/v1/query?query=channel_revision" | jq -r ".data.result[] | select(.metric.channel==\"nixos-${RELEASE}\") | .metric.revision")
|
||||
old=$(jq -r ".nodes.nixpkgs.locked.rev" flake.lock)
|
||||
update_channel() {
|
||||
local channel_name="$1" # Hydra channel name (e.g., nixos-24.11)
|
||||
local flake_input_name="$2" # Flake input name (e.g., nixpkgs)
|
||||
local new old
|
||||
|
||||
echo "Old hash: ${old}"
|
||||
echo "New hash: ${new}"
|
||||
# Get latest revision from Hydra
|
||||
new=$(curl -sL "https://monitoring.nixos.org/prometheus/api/v1/query?query=channel_revision" |
|
||||
jq -r ".data.result[] | select(.metric.channel==\"${channel_name}\") | .metric.revision")
|
||||
|
||||
sed -i s/"${old}"/"${new}"/ flake.nix
|
||||
# Get current revision from flake.lock using input name
|
||||
old=$(jq -r ".nodes as \$nodes |
|
||||
.nodes.root.inputs.[\"${flake_input_name}\"] as \$target_input |
|
||||
\$nodes | to_entries[] |
|
||||
select(.key == \$target_input) |
|
||||
.value.locked.rev" flake.lock)
|
||||
|
||||
if [ "${old}" == "${new}" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
replace_hash "${flake_input_name}" "${new}"
|
||||
|
||||
echo "${new}"
|
||||
}
|
||||
|
||||
replace_hash() {
|
||||
local name="$1" hash="$2"
|
||||
|
||||
sed -i "s|\(${name}\.url = \"github:NixOS/nixpkgs/\)[^\"]*|\1${hash}|" flake.nix
|
||||
# sed -i "s|${name}/${old}|${name}/${new}|" flake.nix
|
||||
}
|
||||
|
||||
update_stable() {
|
||||
echo "Checking NixOS ${RELEASE}..."
|
||||
|
||||
new_hash=$(update_channel "nixos-${RELEASE}" "nixpkgs")
|
||||
|
||||
if [ -z "$new_hash" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Updated stable to: ${new_hash}"
|
||||
}
|
||||
|
||||
update_unstable() {
|
||||
echo "Checking unstable..."
|
||||
|
||||
new_hash=$(update_channel "nixos-unstable" "nixos-unstable")
|
||||
|
||||
if [ -z "$new_hash" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Updated unstable to: ${new_hash}"
|
||||
}
|
||||
|
||||
update_stable
|
||||
update_unstable
|
||||
|
Loading…
x
Reference in New Issue
Block a user