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
|
||||||
result/
|
result/
|
||||||
|
|
||||||
|
.aider*
|
||||||
|
.env
|
||||||
|
435
flake.lock
generated
435
flake.lock
generated
@ -8,11 +8,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1736955230,
|
"lastModified": 1747575206,
|
||||||
"narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=",
|
"narHash": "sha256-NwmAFuDUO/PFcgaGGr4j3ozG9Pe5hZ/ogitWhY+D81k=",
|
||||||
"owner": "ryantm",
|
"owner": "ryantm",
|
||||||
"repo": "agenix",
|
"repo": "agenix",
|
||||||
"rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c",
|
"rev": "4835b1dc898959d8547a871ef484930675cb47f1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -21,37 +21,6 @@
|
|||||||
"type": "github"
|
"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": {
|
"darwin": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
@ -60,11 +29,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1700795494,
|
"lastModified": 1744478979,
|
||||||
"narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=",
|
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
|
||||||
"owner": "lnl7",
|
"owner": "lnl7",
|
||||||
"repo": "nix-darwin",
|
"repo": "nix-darwin",
|
||||||
"rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d",
|
"rev": "43975d782b418ebf4969e9ccba82466728c2851b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -74,154 +43,6 @@
|
|||||||
"type": "github"
|
"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": {
|
"home-manager": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
@ -230,11 +51,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1703113217,
|
"lastModified": 1745494811,
|
||||||
"narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=",
|
"narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1",
|
"rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -250,40 +71,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1743387206,
|
"lastModified": 1748665073,
|
||||||
"narHash": "sha256-24N3NAuZZbYqZ39NgToZgHUw6M7xHrtrAm18kv0+2Wo=",
|
"narHash": "sha256-RMhjnPKWtCoIIHiuR9QKD7xfsKb3agxzMfJY8V9MOew=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "15c5f9d04fabd176f30286c8f52bbdb2c853a146",
|
"rev": "282e1e029cb6ab4811114fc85110613d72771dea",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"ref": "release-24.11",
|
"ref": "release-25.05",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"type": "github"
|
"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": {
|
"local-unstable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 0,
|
"lastModified": 0,
|
||||||
"narHash": "sha256-uewgkTWbDOpOP+wEA3f03XEKsPHsJi0iDqBGQnxWQo0=",
|
"narHash": "sha256-eCA4jXsPHiBkrf1sNOfQPYS2g9DoCsICVzk4ec0cEdo=",
|
||||||
"path": "/home/giulio/dev/nixpkgs",
|
"path": "/home/giulio/dev/nixpkgs",
|
||||||
"type": "path"
|
"type": "path"
|
||||||
},
|
},
|
||||||
@ -292,82 +97,29 @@
|
|||||||
"type": "path"
|
"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": {
|
"nixos-unstable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1743689281,
|
"lastModified": 1748929857,
|
||||||
"narHash": "sha256-y7Hg5lwWhEOgflEHRfzSH96BOt26LaYfrYWzZ+VoVdg=",
|
"narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "2bfc080955153be0be56724be6fa5477b4eefabb",
|
"rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
|
"rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1703013332,
|
"lastModified": 1745391562,
|
||||||
"narHash": "sha256-+tFNwMvlXLbJZXiMHqYq77z/RfmpfpiI3yjL6o/Zo9M=",
|
"narHash": "sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "54aac082a4d9bb5bbc5c4e899603abfb76a3f6d6",
|
"rev": "8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -377,19 +129,35 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs-master": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1744440957,
|
"lastModified": 1749040375,
|
||||||
"narHash": "sha256-FHlSkNqFmPxPJvy+6fNLaNeWnF1lZSgqVCl/eWaJRc4=",
|
"narHash": "sha256-zwVvfxgrXcInI2E/dDg9v80OrvKUT7HtPECu53Khcq0=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"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"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "26d499fc9f1d567283d5d56fcf367edd815dba1d",
|
"rev": "10d7f8d34e5eb9c0f9a0485186c1ca691d2c5922",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -409,70 +177,6 @@
|
|||||||
"type": "github"
|
"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": {
|
"nvidia-patch": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
@ -481,11 +185,11 @@
|
|||||||
"utils": "utils"
|
"utils": "utils"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1743670877,
|
"lastModified": 1748931931,
|
||||||
"narHash": "sha256-OHuOhVCfx10VpWwl9T5Q+QB3To0N95flBR1rSwOiUHA=",
|
"narHash": "sha256-0NUhiMITsYlXDjgcVbLayI0rgrEdf5NIbpW3oLueYUs=",
|
||||||
"owner": "icewind1991",
|
"owner": "icewind1991",
|
||||||
"repo": "nvidia-patch-nixos",
|
"repo": "nvidia-patch-nixos",
|
||||||
"rev": "e80a4919e88a8cb496f649234fb3fc7e992ece10",
|
"rev": "fa8f006a236349790c94801ac85e43f103b35baf",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -517,12 +221,11 @@
|
|||||||
"agenix-flake": "agenix-flake",
|
"agenix-flake": "agenix-flake",
|
||||||
"home-manager": "home-manager_2",
|
"home-manager": "home-manager_2",
|
||||||
"local-unstable": "local-unstable",
|
"local-unstable": "local-unstable",
|
||||||
"nixos-master": "nixos-master",
|
|
||||||
"nixos-unstable": "nixos-unstable",
|
"nixos-unstable": "nixos-unstable",
|
||||||
"nixpkgs": "nixpkgs_2",
|
"nixpkgs": "nixpkgs_2",
|
||||||
|
"nixpkgs-master": "nixpkgs-master",
|
||||||
"nvidia-patch": "nvidia-patch",
|
"nvidia-patch": "nvidia-patch",
|
||||||
"pepeflake": "pepeflake",
|
"pepeflake": "pepeflake"
|
||||||
"teslamate-flake": "teslamate-flake"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
@ -555,50 +258,6 @@
|
|||||||
"type": "github"
|
"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": {
|
"utils": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems_2"
|
"systems": "systems_2"
|
||||||
|
19
flake.nix
19
flake.nix
@ -1,14 +1,13 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/26d499fc9f1d567283d5d56fcf367edd815dba1d";
|
nixpkgs.url = "github:NixOS/nixpkgs/10d7f8d34e5eb9c0f9a0485186c1ca691d2c5922";
|
||||||
nixos-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
nixos-unstable.url = "github:NixOS/nixpkgs/c2a03962b8e24e669fb37b7df10e7c79531ff1a4";
|
||||||
nixos-master.url = "github:NixOS/nixpkgs/master";
|
nixpkgs-master.url = "github:NixOS/nixpkgs/master";
|
||||||
local-unstable.url = "path:///home/giulio/dev/nixpkgs";
|
local-unstable.url = "path:///home/giulio/dev/nixpkgs";
|
||||||
pepeflake.url = "git+https://git.giugl.io/peperunas/pepeflake";
|
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";
|
agenix-flake.url = "github:ryantm/agenix";
|
||||||
home-manager = {
|
home-manager = {
|
||||||
url = "github:nix-community/home-manager/release-24.11";
|
url = "github:nix-community/home-manager/release-25.05";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
nvidia-patch = {
|
nvidia-patch = {
|
||||||
@ -21,10 +20,9 @@
|
|||||||
{ self
|
{ self
|
||||||
, nixpkgs
|
, nixpkgs
|
||||||
, nixos-unstable
|
, nixos-unstable
|
||||||
, nixos-master
|
, nixpkgs-master
|
||||||
, local-unstable
|
, local-unstable
|
||||||
, home-manager
|
, home-manager
|
||||||
, teslamate-flake
|
|
||||||
, nvidia-patch
|
, nvidia-patch
|
||||||
, agenix-flake
|
, agenix-flake
|
||||||
, pepeflake
|
, pepeflake
|
||||||
@ -62,16 +60,14 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
unstablePkgs = importNixpkgs { flake = nixos-unstable; };
|
unstablePkgs = importNixpkgs { flake = nixos-unstable; };
|
||||||
masterPkgs = importNixpkgs { flake = nixos-master; };
|
masterPkgs = importNixpkgs { flake = nixpkgs-master; };
|
||||||
localPkgs = importNixpkgs { flake = local-unstable; };
|
localPkgs = importNixpkgs { flake = local-unstable; };
|
||||||
teslamatePkgs = importNixpkgs { flake = teslamate-flake; };
|
|
||||||
agenixPkgs = importNixpkgs { flake = agenix-flake; };
|
agenixPkgs = importNixpkgs { flake = agenix-flake; };
|
||||||
pepePkgs = pepeflake.packages.${system} // pepeflake.legacyPackages.${system} or { };
|
pepePkgs = pepeflake.packages.${system} // pepeflake.legacyPackages.${system} or { };
|
||||||
|
|
||||||
additionalOverlays = [
|
additionalOverlays = [
|
||||||
(final: prev: { inherit unstablePkgs; })
|
(final: prev: { inherit unstablePkgs; })
|
||||||
(final: prev: { inherit localPkgs; })
|
(final: prev: { inherit localPkgs; })
|
||||||
(final: prev: { inherit teslamatePkgs; })
|
|
||||||
(final: prev: { inherit agenixPkgs; })
|
(final: prev: { inherit agenixPkgs; })
|
||||||
(final: prev: { inherit masterPkgs; })
|
(final: prev: { inherit masterPkgs; })
|
||||||
(final: prev: { inherit pepePkgs; })
|
(final: prev: { inherit pepePkgs; })
|
||||||
@ -104,7 +100,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
pkgsLinuxX64Cuda = wrapPkgsSystem { system = sysLinuxX64; };
|
pkgsLinuxX64Cuda = wrapPkgsSystem { system = sysLinuxX64; cudaSupport = true; };
|
||||||
utilsLinuxX64Cuda = wrapUtils { pkgs = pkgsLinuxX64Cuda; };
|
utilsLinuxX64Cuda = wrapUtils { pkgs = pkgsLinuxX64Cuda; };
|
||||||
|
|
||||||
pkgsLinuxAarch = wrapPkgsSystem { system = sysLinuxAarch; };
|
pkgsLinuxAarch = wrapPkgsSystem { system = sysLinuxAarch; };
|
||||||
@ -122,7 +118,6 @@
|
|||||||
roles = [ ];
|
roles = [ ];
|
||||||
}];
|
}];
|
||||||
imports = [
|
imports = [
|
||||||
teslamate-flake.nixosModules.default
|
|
||||||
agenix-flake.nixosModules.default
|
agenix-flake.nixosModules.default
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
environmentFile = config.age.secrets.restic-environment.path;
|
environmentFile = config.age.secrets.restic-environment.path;
|
||||||
repository = "b2:architect:/";
|
repository = "b2:architect:/";
|
||||||
paths = [ "/var/lib" "/services" ];
|
paths = [ "/var/lib" "/services" ];
|
||||||
|
exclude = [
|
||||||
|
"/var/lib/ollama"
|
||||||
|
];
|
||||||
pruneOpts = [
|
pruneOpts = [
|
||||||
"--keep-daily 45"
|
"--keep-daily 45"
|
||||||
"--keep-weekly 12"
|
"--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
|
let
|
||||||
macbookPubkey = (import ../pubkeys.nix).macbook;
|
macbookPubkey = (import ../pubkeys.nix).macbook;
|
||||||
pubkeys = [ macbookPubkey ];
|
pubkeys = [ macbookPubkey ];
|
||||||
domain = "devs.giugl.io";
|
domain = "devs.giugl.io";
|
||||||
|
|
||||||
utilities = import ./utilities.nix { inherit lib config; };
|
|
||||||
inherit (utilities) generateDeviceStrings;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
@ -15,46 +12,20 @@ in
|
|||||||
./hardware.nix
|
./hardware.nix
|
||||||
./firewall.nix
|
./firewall.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./gitea.nix
|
|
||||||
./sonarr.nix
|
|
||||||
./radarr.nix
|
|
||||||
./bazarr.nix
|
|
||||||
./nzbget.nix
|
|
||||||
./nextcloud.nix
|
./nextcloud.nix
|
||||||
./minio.nix
|
|
||||||
./matrix.nix
|
./matrix.nix
|
||||||
./fail2ban.nix
|
./fail2ban.nix
|
||||||
./dns.nix
|
./dns.nix
|
||||||
# ./minecraft.nix
|
|
||||||
./prowlarr.nix
|
|
||||||
./redlib.nix
|
|
||||||
# ./invidious.nix
|
|
||||||
./jellyfin.nix
|
|
||||||
# ./docker.nix
|
|
||||||
./tailscale.nix
|
./tailscale.nix
|
||||||
./headscale.nix
|
|
||||||
./llm.nix
|
|
||||||
# ./photoprism.nix
|
|
||||||
./sunshine.nix
|
./sunshine.nix
|
||||||
./jellyseer.nix
|
|
||||||
./postgres.nix
|
./postgres.nix
|
||||||
./netdata.nix
|
./netdata.nix
|
||||||
./homeassistant.nix
|
|
||||||
./searx.nix
|
./searx.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
age.identityPaths = [ "/root/.ssh/id_ed25519" ];
|
age.identityPaths = [ "/root/.ssh/id_ed25519" ];
|
||||||
|
|
||||||
architect = {
|
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 = {
|
firewall = {
|
||||||
openTCP = [ 22 ];
|
openTCP = [ 22 ];
|
||||||
@ -77,8 +48,8 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
kernelParams = with config.architect.networks.lan; [
|
kernelParams = with config.pepe.core.network.interfaces.lan; [
|
||||||
"ip=${devices.architect.address}::${devices.router.address}:255.255.255.0::${interface}:off"
|
"ip=${devices.architect.address}::${devices.brigettine.address}:255.255.255.0::${interface}:off"
|
||||||
];
|
];
|
||||||
|
|
||||||
kernel.sysctl = { "net.ipv4.ip_forward" = 1; };
|
kernel.sysctl = { "net.ipv4.ip_forward" = 1; };
|
||||||
@ -96,42 +67,17 @@ in
|
|||||||
tmp.tmpfsSize = "50%";
|
tmp.tmpfsSize = "50%";
|
||||||
};
|
};
|
||||||
|
|
||||||
networking = with config.architect.networks.lan; {
|
networking = with config.pepe.core.network.interfaces.lan; {
|
||||||
hostName = "architect";
|
hostName = "architect";
|
||||||
hostId = "49350853";
|
hostId = "49350853";
|
||||||
useDHCP = false;
|
useDHCP = false;
|
||||||
defaultGateway = devices.router.address;
|
defaultGateway = devices.brigettine.address;
|
||||||
interfaces = {
|
interfaces = {
|
||||||
${interface}.ipv4.addresses = [{
|
${interface}.ipv4.addresses = [{
|
||||||
address = devices.architect.address;
|
address = devices.architect.address;
|
||||||
prefixLength = 24;
|
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 = {
|
services = {
|
||||||
@ -153,5 +99,177 @@ in
|
|||||||
};
|
};
|
||||||
smartd.enable = true;
|
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; {
|
pepe.core.dns = {
|
||||||
dnsInterfaces = [ "tailscale" "lan" ];
|
enable = true;
|
||||||
locations."/" = {
|
nextDNSId = "d65174";
|
||||||
port = config.services.adguardhome.port;
|
extraDomains = {
|
||||||
allowLan = true;
|
"architect.devs.giugl.io" = {
|
||||||
|
dnsInterfaces = [ "lan" "tailscale" ];
|
||||||
allow = [
|
};
|
||||||
tailscale.net
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
|
||||||
coredns = {
|
|
||||||
enable = true;
|
|
||||||
config = ''
|
|
||||||
${generateCoreDNSConfig allDomains}
|
|
||||||
|
|
||||||
. {
|
|
||||||
cache
|
|
||||||
forward . 45.90.28.77 45.90.30.77
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
packageFirewall = pkgs.nftables;
|
packageFirewall = pkgs.nftables;
|
||||||
bantime-increment.enable = true;
|
bantime-increment.enable = true;
|
||||||
ignoreIP = [
|
ignoreIP = [
|
||||||
config.architect.networks.lan.net
|
config.pepe.core.network.interfaces.tailscale.net
|
||||||
config.architect.networks.tailscale.net
|
config.pepe.core.network.interfaces.lan.net
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
openTCP = lib.concatMapStringsSep "," (x: toString x) config.architect.firewall.openTCP;
|
firewallRules = config.pepe.core.firewall;
|
||||||
openUDP = lib.concatMapStringsSep "," (x: toString x) config.architect.firewall.openUDP;
|
openTCP = lib.concatMapStringsSep "," (x: toString x) firewallRules.openTCP;
|
||||||
openTCPVPN = lib.concatMapStringsSep "," (x: toString x) config.architect.firewall.openTCPVPN;
|
openUDP = lib.concatMapStringsSep "," (x: toString x) firewallRules.openUDP;
|
||||||
openUDPVPN = lib.concatMapStringsSep "," (x: toString x) config.architect.firewall.openUDPVPN;
|
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 = [
|
gdevices = [
|
||||||
(deviceAddress "tailscale" "architect")
|
(deviceAddress "tailscale" "architect")
|
||||||
(deviceAddress "tailscale" "dodino")
|
|
||||||
(deviceAddress "tailscale" "manduria")
|
(deviceAddress "tailscale" "manduria")
|
||||||
(deviceAddress "tailscale" "kmerr")
|
(deviceAddress "tailscale" "kmerr")
|
||||||
(deviceAddress "tailscale" "chuck")
|
|
||||||
];
|
];
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@ -25,7 +23,7 @@ in
|
|||||||
|
|
||||||
nftables = {
|
nftables = {
|
||||||
enable = true;
|
enable = true;
|
||||||
ruleset = with config.architect.networks; ''
|
ruleset = with config.pepe.core.network.interfaces; ''
|
||||||
table ip raw {
|
table ip raw {
|
||||||
chain PREROUTING {
|
chain PREROUTING {
|
||||||
type filter hook prerouting priority raw; policy accept;
|
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" ];
|
options = [ "bind" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
"/media" = {
|
"${config.pepe.core.media.path}" = lib.mkIf config.pepe.core.media.enable {
|
||||||
device = "nvmedata/media";
|
device = "nvmedata/media";
|
||||||
fsType = "zfs";
|
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; [
|
environment.systemPackages = with pkgs; [
|
||||||
nodejs-18_x
|
|
||||||
libtensorflow
|
|
||||||
ffmpeg
|
ffmpeg
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -60,7 +58,7 @@ in
|
|||||||
enable = true;
|
enable = true;
|
||||||
hostName = domain;
|
hostName = domain;
|
||||||
https = true;
|
https = true;
|
||||||
package = pkgs.nextcloud30;
|
package = pkgs.nextcloud31;
|
||||||
datadir = "/services/nextcloud";
|
datadir = "/services/nextcloud";
|
||||||
configureRedis = true;
|
configureRedis = true;
|
||||||
caching = {
|
caching = {
|
||||||
|
@ -1,148 +1,25 @@
|
|||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
options.architect = {
|
options.architect = {
|
||||||
firewall = {
|
firewall = lib.mkOption {
|
||||||
openTCP = mkOption {
|
internal = true;
|
||||||
type = types.listOf types.int;
|
default = config.pepe.core.firewall;
|
||||||
default = [ ];
|
|
||||||
};
|
|
||||||
openUDP = mkOption {
|
|
||||||
type = types.listOf types.int;
|
|
||||||
default = [ ];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
networks = mkOption {
|
networks = lib.mkOption {
|
||||||
type = types.attrsOf (types.submodule {
|
internal = true;
|
||||||
options = {
|
default = config.pepe.core.network.interfaces;
|
||||||
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.";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
vhost = mkOption {
|
vhost = lib.mkOption {
|
||||||
type = types.attrsOf (types.submodule {
|
internal = true;
|
||||||
options = {
|
default = config.pepe.core.vhost.hosts;
|
||||||
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.";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# TODO: move to nginx
|
config.architect.networks.docker = {
|
||||||
config = {
|
interface = "docker0";
|
||||||
services.nginx.virtualHosts = mapAttrs
|
net = "172.17.0.0/16";
|
||||||
(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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
{
|
{
|
||||||
services.postgresql = {
|
services.postgresql = {
|
||||||
enable = true;
|
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; });
|
sunshinePkg = (pkgs.unstablePkgs.sunshine.override { cudaSupport = true; });
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
pepe.core.graphics = {
|
||||||
|
enable = true;
|
||||||
|
nvidia = true;
|
||||||
|
};
|
||||||
|
|
||||||
boot.kernelModules = [ "uinput" ];
|
boot.kernelModules = [ "uinput" ];
|
||||||
|
|
||||||
environment.systemPackages = with pkgs.unstablePkgs; [ gamemode heroic ];
|
environment.systemPackages = with pkgs.unstablePkgs; [ gamemode heroic ];
|
||||||
|
|
||||||
hardware = {
|
hardware = {
|
||||||
pulseaudio.enable = false;
|
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;
|
systemd.services.NetworkManager-wait-online.enable = pkgs.lib.mkForce false;
|
||||||
programs.steam = {
|
programs.steam = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@ -159,7 +156,6 @@ in
|
|||||||
|
|
||||||
xserver = {
|
xserver = {
|
||||||
enable = true;
|
enable = true;
|
||||||
videoDrivers = [ "nvidia" ];
|
|
||||||
desktopManager.xfce.enable = true;
|
desktopManager.xfce.enable = true;
|
||||||
|
|
||||||
monitorSection = ''
|
monitorSection = ''
|
||||||
|
@ -7,24 +7,26 @@ let
|
|||||||
inherit (utilities) generateDeviceStrings;
|
inherit (utilities) generateDeviceStrings;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
architect = {
|
pepe.core = {
|
||||||
networks.tailscale = {
|
firewall.openUDP = [ 41641 ];
|
||||||
|
|
||||||
|
network.interfaces.tailscale = {
|
||||||
interface = "ts0";
|
interface = "ts0";
|
||||||
net = "100.64.0.0/10";
|
net = "100.64.0.0/10";
|
||||||
|
type = "vpn";
|
||||||
devices = {
|
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}"; };
|
kmerr = { address = "100.64.0.2"; hostname = "kmerr.${domain}"; };
|
||||||
parallels = { address = "100.64.0.3"; hostname = "parallels.${domain}"; };
|
work_laptop = { address = "100.64.0.4"; hostname = "work_laptop.${domain}"; };
|
||||||
chuck = { address = "100.64.0.4"; hostname = "chuck.${domain}"; };
|
work_desktop = { address = "100.64.0.5"; hostname = "work_desktop.${domain}"; };
|
||||||
dodino = { address = "100.64.0.5"; hostname = "dodino.${domain}"; };
|
|
||||||
manduria = { address = "100.64.0.6"; hostname = "manduria.${domain}"; };
|
manduria = { address = "100.64.0.6"; hostname = "manduria.${domain}"; };
|
||||||
tommy = { address = "100.64.0.7"; hostname = "tommy.${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}"; };
|
alfredo = { address = "100.64.0.9"; hostname = "alfredo.${domain}"; };
|
||||||
appletv = { address = "100.64.0.13"; hostname = "appletv.${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}"; };
|
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 = {
|
services = {
|
||||||
tailscale = {
|
tailscale = {
|
||||||
enable = true;
|
enable = true;
|
||||||
interfaceName = config.architect.networks.tailscale.interface;
|
interfaceName = config.pepe.core.network.interfaces.tailscale.interface;
|
||||||
package = pkgs.unstablePkgs.tailscale;
|
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, ... }:
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
ifaces = config.pepe.core.network.interfaces;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
# device.address device.hostname
|
# device.address device.hostname
|
||||||
generateDeviceStrings = devices: lib.concatStringsSep "\n"
|
generateDeviceStrings = devices: lib.concatStringsSep "\n"
|
||||||
(lib.mapAttrsToList (name: device: "${device.address} ${device.hostname}") devices);
|
(lib.mapAttrsToList (name: device: "${device.address} ${device.hostname}") devices);
|
||||||
|
|
||||||
getDeviceAddress = interface: device:
|
getDeviceAddress = interface: device:
|
||||||
config.architect.networks.${interface}.devices.${device}.address;
|
ifaces.${interface}.devices.${device}.address;
|
||||||
|
|
||||||
architectInterfaceAddress = interface:
|
architectInterfaceAddress = interface:
|
||||||
config.architect.networks.${interface}.devices.architect.address;
|
ifaces.${interface}.devices.architect.address;
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,14 @@
|
|||||||
(mkSysRole "common")
|
(mkSysRole "common")
|
||||||
(mkSysRole "acme")
|
(mkSysRole "acme")
|
||||||
(mkUser { name = "root"; roles = [ ]; })
|
(mkUser { name = "root"; roles = [ ]; })
|
||||||
|
../modules
|
||||||
];
|
];
|
||||||
|
|
||||||
home-manager = {
|
home-manager = {
|
||||||
useGlobalPkgs = true;
|
useGlobalPkgs = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
system.stateVersion = "24.11";
|
system.stateVersion = "25.05";
|
||||||
}
|
}
|
||||||
|
|
||||||
home-manager.nixosModules.home-manager
|
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";
|
giuglioDomain = "giugl.io";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
age.secrets.ovh = {
|
age.secrets.cloudflare = {
|
||||||
file = ../secrets/ovh.age;
|
file = ../secrets/cloudflare.age;
|
||||||
owner = "acme";
|
owner = "acme";
|
||||||
};
|
};
|
||||||
security.acme = {
|
security.acme = {
|
||||||
acceptTerms = true;
|
acceptTerms = true;
|
||||||
certs.${giuglioDomain} =
|
certs.${giuglioDomain} =
|
||||||
{
|
{
|
||||||
dnsProvider = "ovh";
|
dnsProvider = "cloudflare";
|
||||||
environmentFile = config.age.secrets.ovh.path;
|
environmentFile = config.age.secrets.cloudflare.path;
|
||||||
extraDomainNames = [ "*.${giuglioDomain}" ];
|
extraDomainNames = [ "*.${giuglioDomain}" ];
|
||||||
};
|
};
|
||||||
defaults = {
|
defaults = {
|
||||||
email = "letsencrypt@depasquale.giugl.io";
|
email = "letsencrypt@depasquale.giugl.io";
|
||||||
dnsProvider = "ovh";
|
dnsProvider = "cloudflare";
|
||||||
environmentFile = config.age.secrets.ovh.path;
|
environmentFile = config.age.secrets.cloudflare.path;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ in
|
|||||||
sessionVariables = {
|
sessionVariables = {
|
||||||
AICHAT_CONFIG_DIR = configDir;
|
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/config.yaml".text = lib.readFile ./aichat/config.yaml;
|
||||||
file.".config/aichat/roles/commitmessage.md".text = lib.readFile ./aichat/roles/commitmessage.md;
|
file.".config/aichat/roles/commitmessage.md".text = lib.readFile ./aichat/roles/commitmessage.md;
|
||||||
|
@ -15,9 +15,7 @@ let
|
|||||||
tree
|
tree
|
||||||
] ++ lib.optional (!pkgs.stdenv.isDarwin) pastebinit;
|
] ++ lib.optional (!pkgs.stdenv.isDarwin) pastebinit;
|
||||||
|
|
||||||
unstablePkgs = with pkgs.unstablePkgs; [
|
unstablePkgs = with pkgs.unstablePkgs; [ aider-chat ];
|
||||||
aider-chat-full
|
|
||||||
];
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
@ -28,7 +26,7 @@ in
|
|||||||
|
|
||||||
home = {
|
home = {
|
||||||
packages = stablePkgs ++ unstablePkgs;
|
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;
|
"nextcloud-database.age".publicKeys = pubkeys;
|
||||||
"restic-environment.age".publicKeys = pubkeys;
|
"restic-environment.age".publicKeys = pubkeys;
|
||||||
"restic-passwords.age".publicKeys = pubkeys;
|
"restic-passwords.age".publicKeys = pubkeys;
|
||||||
"ovh.age".publicKeys = pubkeys;
|
"cloudflare.age".publicKeys = pubkeys;
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,62 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# this guy updates the hash of the last
|
RELEASE=25.05
|
||||||
# successful build of nixpkgs on hydra
|
|
||||||
# (so we don't have to rebuild EVERYTHING)
|
|
||||||
RELEASE=24.11
|
|
||||||
|
|
||||||
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")
|
update_channel() {
|
||||||
old=$(jq -r ".nodes.nixpkgs.locked.rev" flake.lock)
|
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}"
|
# Get latest revision from Hydra
|
||||||
echo "New hash: ${new}"
|
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