feat: stuff i think. oh yeah home assistant and shit (#124)

* hax

* hax

* hack

* hax

* hax

* hax

* fix shit

---------

Co-authored-by: Truxnell <9149206+truxnell@users.noreply.github.com>
This commit is contained in:
Truxnell 2024-04-29 21:48:13 +10:00 committed by GitHub
parent 3fe476a3f5
commit 6cd4befc1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 790 additions and 103 deletions

View file

@ -96,6 +96,21 @@
"type": "github" "type": "github"
} }
}, },
"impermanence": {
"locked": {
"lastModified": 1708968331,
"narHash": "sha256-VUXLaPusCBvwM3zhGbRIJVeYluh2uWuqtj4WirQ1L9Y=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "a33ef102a02ce77d3e39c25197664b7a636f9c30",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "impermanence",
"type": "github"
}
},
"mk-naked-shell": { "mk-naked-shell": {
"flake": false, "flake": false,
"locked": { "locked": {
@ -383,6 +398,7 @@
"root": { "root": {
"inputs": { "inputs": {
"home-manager": "home-manager", "home-manager": "home-manager",
"impermanence": "impermanence",
"nix-index-database": "nix-index-database", "nix-index-database": "nix-index-database",
"nix-inspect": "nix-inspect", "nix-inspect": "nix-inspect",
"nix-vscode-extensions": "nix-vscode-extensions", "nix-vscode-extensions": "nix-vscode-extensions",

View file

@ -6,6 +6,10 @@
nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11"; nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11";
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
# impermanence
# https://github.com/nix-community/impermanence
impermanence.url = "github:nix-community/impermanence";
# nur # nur
nur.url = "github:nix-community/NUR"; nur.url = "github:nix-community/NUR";
@ -50,6 +54,7 @@
, sops-nix , sops-nix
, home-manager , home-manager
, nix-vscode-extensions , nix-vscode-extensions
, impermanence
, ... , ...
} @ inputs: } @ inputs:
@ -97,6 +102,7 @@
, baseModules ? [ , baseModules ? [
sops-nix.nixosModules.sops sops-nix.nixosModules.sops
home-manager.nixosModules.home-manager home-manager.nixosModules.home-manager
impermanence.nixosModules.impermanence
./nixos/profiles/global.nix # all machines get a global profile ./nixos/profiles/global.nix # all machines get a global profile
./nixos/modules/nixos # all machines get nixos modules ./nixos/modules/nixos # all machines get nixos modules
./nixos/hosts/${hostname} # load this host's config folder for machine-specific config ./nixos/hosts/${hostname} # load this host's config folder for machine-specific config

View file

@ -86,6 +86,7 @@
{ {
device = "rpool/safe/persist"; device = "rpool/safe/persist";
fsType = "zfs"; fsType = "zfs";
# neededForBoot = true; # for impermanence
}; };
swapDevices = swapDevices =

View file

@ -11,6 +11,7 @@
openssh.enable = true; openssh.enable = true;
podman.enable = true; podman.enable = true;
traefik.enable = true; traefik.enable = true;
postgresql.enable = true;

View file

@ -26,6 +26,9 @@
mosquitto.enable = true; mosquitto.enable = true;
zigbee2mqtt.enable = true; zigbee2mqtt.enable = true;
node-red.enable = true;
home-assistant.enable = true;
openvscode-server.enable = true;
}; };
@ -78,6 +81,7 @@
{ {
device = "rpool/safe/persist"; device = "rpool/safe/persist";
fsType = "zfs"; fsType = "zfs";
# neededForBoot = true; # for impermanence
}; };
fileSystems."/boot" = fileSystems."/boot" =

View file

@ -23,12 +23,15 @@ rec {
let let
user = existsOrDefault "user" options "568"; user = existsOrDefault "user" options "568";
group = existsOrDefault "group" options "568"; group = existsOrDefault "group" options "568";
envFiles = existsOrDefault "envFiles" options [ ];
addTraefikLabels = if (builtins.hasAttr "container" options) && (builtins.hasAttr "addTraefikLabels" options.container) then options.container.addTraefikLabels else false; addTraefikLabels = if (builtins.hasAttr "container" options) && (builtins.hasAttr "addTraefikLabels" options.container) then options.container.addTraefikLabels else true;
addToHomepage = lib.attrsets.attrByPath [ "homepage" "enable" ] true options;
homepageIcon = if (builtins.hasAttr "homepage" options) && (builtins.hasAttr "icon" options.homepage) then options.homepage.icon else "${options.app}.svg"; homepageIcon = if (builtins.hasAttr "homepage" options) && (builtins.hasAttr "icon" options.homepage) then options.homepage.icon else "${options.app}.svg";
subdomain = existsOrDefault "subdomainOverride" options options.app;
host = existsOrDefault "host" options "${subdomain}.${options.domain}";
host = existsOrDefault "host" options "${options.app}.${options.domain}"; enableBackups = (lib.attrsets.hasAttrByPath [ "persistence" "folder" ] options)
&& (lib.attrsets.attrByPath [ "persistence" "enable" ] true options);
# nix doesnt have an exhausive list of options for oci # nix doesnt have an exhausive list of options for oci
# so here i try to get a robust list of security options for containers # so here i try to get a robust list of security options for containers
# because everyone needs more tinfoild hat right? RIGHT? # because everyone needs more tinfoild hat right? RIGHT?
@ -44,19 +47,23 @@ rec {
in in
{ {
virtualisation.oci-containers.containers.${options.app} = { virtualisation.oci-containers.containers.${options.app} = mkIf options.container.enable {
image = "${options.image}"; image = "${options.container.image}";
user = "${user}:${group}"; user = "${user}:${group}";
environment = { environment = {
TZ = options.timeZone; TZ = options.timeZone;
} // options.container.env; } // options.container.env;
environmentFiles = [ ] ++ envFiles; environmentFiles = [ ]
volumes = [ ++ lib.attrsets.attrByPath [ "container" "envFiles" ] [ ] options;
"/etc/localtime:/etc/localtime:ro" volumes = [ "/etc/localtime:/etc/localtime:ro" ]
]; ++ lib.optionals (lib.attrsets.hasAttrByPath [ "container" "persistentFolderMount" ] options) [
"${options.persistence.folder}:${options.container.persistentFolderMount}:rw"
]
++ lib.attrsets.attrByPath [ "container" "volumes" ] [ ] options;
labels = mkIf addTraefikLabels (mkTraefikLabels { labels = mkIf addTraefikLabels (mkTraefikLabels {
name = options.app; name = subdomain;
port = options.port; port = options.port;
domain = options.domain; domain = options.domain;
url = host; url = host;
@ -65,7 +72,12 @@ rec {
extraOptions = containerExtraOptions; extraOptions = containerExtraOptions;
}; };
mySystem.services.homepage.${options.homepage.category} = mkIf options.addToHomepage [ systemd.tmpfiles.rules = [ ]
++ lib.optionals (lib.attrsets.hasAttrByPath [ "persistence" "folder" ] options) [ "d ${options.persistence.folder} 0755 ${user} ${group} -" ]
;
# built a entry for homepage
mySystem.services.homepage.${options.homepage.category} = mkIf addToHomepage [
{ {
${options.app} = { ${options.app} = {
icon = homepageIcon; icon = homepageIcon;
@ -75,6 +87,7 @@ rec {
}; };
} }
]; ];
} }
@ -107,5 +120,4 @@ rec {
} }
); );
} }

View file

@ -12,5 +12,7 @@
./factorio ./factorio
./whoogle ./whoogle
./redlib ./redlib
./home-assistant
./node-red
]; ];
} }

View file

@ -0,0 +1,67 @@
{ lib
, config
, pkgs
, ...
}:
with lib;
let
cfg = config.mySystem.services.home-assistant;
app = "Home-assistant";
user = "kah";
group = "kah";
appFolder = "home-assistant";
persistentFolder = "${config.mySystem.persistentFolder}/containers/${appFolder}";
in
{
options.mySystem.services.home-assistant.enable = mkEnableOption "home-assistant";
# running in a container vs nix module mainly
# as I know the container is solid. Bit iffy
# over the packaging of HA in nix & arguments
# from HA dev on nix packaging
config = mkIf cfg.enable
(lib.recursiveUpdate
{
sops.secrets."services/${app}/env" = {
sopsFile = ./secrets.sops.yaml;
owner = user;
group = group;
restartUnits = [ "podman-${app}.service" ];
};
}
(myLib.mkService
{
inherit app user group;
description = "Home Automation";
port = 8123;
timeZone = config.time.timeZone;
# subdomainOverride = "hass";
domain = config.networking.domain;
persistence = {
folder = persistentFolder;
backup = true;
};
homepage = {
icon = "home-assistant.svg";
category = "home";
};
container = {
enable = true;
image = "ghcr.io/onedr0p/home-assistant:2024.1.5@sha256:64bb3ffa532c3c52563f0e4a4de8d50c889f42a1b0826b35ee1ac728652fb107";
env = {
HASS_IP = "10.8.20.42";
};
envFiles = [ config.sops.secrets."services/${app}/env".path ];
persistentFolderMount = "/config";
addTraefikLabels = true;
caps = {
# readOnly = true;
noNewPrivileges = true;
# dropAll = true;
};
};
})
);
}

View file

@ -0,0 +1,89 @@
{ lib
, config
, pkgs
, ...
}:
with lib;
let
app = "home-assistant";
image = "ghcr.io/onedr0p/home-assistant:2024.1.5@sha256:64bb3ffa532c3c52563f0e4a4de8d50c889f42a1b0826b35ee1ac728652fb107";
user = "568"; #string
group = "568"; #string
port = 8123; #int
cfg = config.mySystem.services.${app};
appFolder = "containers/${app}";
persistentFolder = "${config.mySystem.persistentFolder}/${appFolder}";
in
{
options.mySystem.services.${app} =
{
enable = mkEnableOption "${app}";
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
};
config = mkIf cfg.enable {
# ensure folder exist and has correct owner/group
systemd.tmpfiles.rules = [
"d ${persistentFolder} 0755 ${user} ${group} -" #The - disables automatic cleanup, so the file wont be removed after a period
];
sops.secrets."services/${app}/env" = {
# configure secret for forwarding rules
sopsFile = ./secrets.sops.yaml;
owner = config.users.users.kah.name;
inherit (config.users.users.kah) group;
restartUnits = [ "podman-${app}.service" ];
};
virtualisation.oci-containers.containers.${app} = {
image = "${image}";
user = "${user}:${group}";
environment = {
HASS_IP = "10.8.20.42";
};
environmentFiles = [ config.sops.secrets."services/${app}/env".path ];
volumes = [
"${persistentFolder}:/config:rw"
"/etc/localtime:/etc/localtime:ro"
];
labels = lib.myLib.mkTraefikLabels {
name = app;
domain = config.networking.domain;
inherit port;
};
};
mySystem.services.homepage.media = mkIf cfg.addToHomepage [
{
Lidarr = {
icon = "${app}.svg";
href = "https://${app}.${config.mySystem.domain}";
description = "Home automation";
container = "${app}";
};
}
];
mySystem.services.gatus.monitors = [{
name = app;
group = "media";
url = "https://${app}.${config.mySystem.domain}";
interval = "1m";
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];
}];
services.restic.backups = config.lib.mySystem.mkRestic
{
inherit app;
user = builtins.toString user;
excludePaths = [ "Backups" ];
paths = [ appFolder ];
inherit appFolder;
};
};
}

View file

@ -0,0 +1,77 @@
services:
home-assistant:
env: ENC[AES256_GCM,data:SzSN0Gu1RhTL4VDyX5nOPFadNZ4s0grYnQKzZhHb3MwPkYtrinnFKARahZ0dkvnKjOjCxxP6uaYHF/9rBxyRRuxjoOk7Qj4xF9Rr9v5e/YSyJHhIOcX4KTaagLW55t7IK0dmHPX2eimWdUcTh1MKjWKgG6CtRGLYMN4fPTxzTjoLjtGiHD3tLhrDc+vMS4GYDWocBx3FXp8vICbKaLpVsUHT3JUWstQhnadtmCvywgrXid5UoJnWxtpQxR2vf7m7SYjcIRX1iA6/PHAhgZftsMt8Aw4tw8+gR5jJivmkBm3HE2iJwtDJnowvdVeAaLMdpdzDW45a7P++F5Cwr5yQLuKfkPeCkgiD1EzDKjQs4Rnq19+7ZDZT8WCA5wtzwP8+yzjLO0wZfJ4Bda0jd1tR+FeID3NSsU1il8S3bXLegLxmCLnYvzKRdxHrUUFu85xTfe8GYMtllUv8c10zAL9nRmRUPXh7JpXntKEidEy6w0F1iOWsR67yp1qOzlGOu7k0wMAS7QZ5/Op/nBjuugh+mOyABO5CpjnPqIXc19oerkNCHZJOmmHdT7wf3n90yn4j09XyIYDI6e7G+FXa/QwBqO5r0z+ulqHcpyhkklB425Zz5G2QUCBCz3mqJ/RhiWk+g4WwNEEecy31hNIaVl4zwwTlk/iFXdZ938NWp3jZp2zOzhGLlRcFbcuUzvqXqL1tFmIokIE/4AQll1zkmgUFFc/76ppTc4qylNy9z7NxM5/SJoONKW2jx4Tf2sEBIK/LICHgGu2VzBhCSOW+EyWr4vziRT9Kq4TVHLf56k+Sh2SKGFZg4FKkIVl7ZbiQyRp88Jqlna4sZwlA+4bcPMi8BMFj3yREv6t1uSaiUO+OtMpCrREuU9afp4OsQs1QyoED24Zh1TKkpZ7vJ6rYCT/j0EEEsSMEcV/dmIoyawGyM8KB5ZjZIR8LWaLffHARWBcholKANWv9a3kFp0qsqvqVxxNxH3GEqZlFz83igwWOeILeSdZ2BEVKZBP4tmQu8HvUEPHtucRUIbsPSMgRXHJPbmia4w7053OrmATEKNYKVXCspoA0gsPF9AqsH/I67NbpamJ0F1/sc+d0Zw8oJKHexes9WAa3S3bCVwdtPI2cIMNLTA4T7fA5d4yZ6joe+CnHZnprbd7LlQIoK/MEM8bftvGz3Jnk/3fqTOlW8yC4tknsnO44m3LJmQ2rDbWlswO3rQTP/SCpkHcXTgbT5A==,iv:q4C1fJqWWH5RIn42p7VWwonpMaOeahyp2jzb+1pNPr0=,tag:gDytkHSuISDbNqIbfvDnwQ==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1lj5vmr02qkudvv2xedfj5tq8x93gllgpr6tzylwdlt7lud4tfv5qfqsd5u
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNQzA1VlEzeVVwcDN6ZHpm
bDhYNlU4VWI5Z2FwUmVNZUJETUhKSkVCcm1vClI0ZmlyekRicUR4Z2lhMVdpUjE2
VXdrRDhuQWZ1K2Frb1dsWWFvdDBNQWsKLS0tIDgvcTBncUpYcHE4cXJzeUl6K2lY
VEJPencraktjeTFMeTJxWUowbUcyeFUKWRIPe0rrbHRpE4d4saqS9xMRzcy2huwg
kDXek89pTY+2kYcPiKIQ4FPdOO2abGkRZeNWUZ/Nc/MvUqBhtQoUQA==
-----END AGE ENCRYPTED FILE-----
- recipient: age17edew3aahg3t5nte5g0a505sn96vnj8g8gqse8q06ccrrn2n3uysyshu2c
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3ZnRncGo4VzFieTJIQXFn
VzFVQVhVSkVyeTFGaEtuYXBnQU5mZDhrS0FFCnZPanhkL2pCTzBEc1IrMGMwTDh6
eklPS0dOb0dJZEtEMU9YTHNQSURFNmcKLS0tIGRNTUU0MS9HMXdHQ0xXekNwNXMz
OUwrYnRXQkEvNXFRTkl2VVFoKy85NVkKvw3PHp1TwvCmXGKCv4mxvJQYhKommZg0
e0OAmzasx8ek7HDySvfTuYjQKVSCB46wtojuAMUkPScI/yqJLHJ4rQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1u4tht685sqg6dkmjyer96r93pl425u6353md6fphpd84jh3jwcusvm7mgk
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2N1I4QXczQUZqb1NGdXdk
VWRmTExoeDhXaVJPOWJYMW9IU2NseGxKY0ZzClhMRWJUSldDTzRvQkpBWldXVGVm
VXBmRFJDMkpaeXNDWE9lQ1Q5OWF6QUkKLS0tIGJ0VUd3OVZJVmRFMS9KdlFhSFdT
aU9rQU5mT3NNVjdvbUlaZ1hvbUErenMKyu1/RxivA+uaIjg+NbZUYSvMACyT5Jkq
Qu6Gq+hzh5++pi+dBn/OHqwn0hCszBYT5MBu3PueZoLAyqLwsuQ9eQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1cp6vegrmqfkuj8nmt2u3z0sur7n0f7e9x9zmdv4zygp8j2pnucpsdkgagc
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXZEp2SFVDcnMvNmxmUERQ
RG9FRnFuWmhCUnE2aktyWEFodExPWGo0OWxFCm5UbU91b1pVbkt3ZnIyNmlvbGxn
NFI4R2N2a1hJc2lhNEZiRzRCMFpWYUkKLS0tIHJkY1NnNjJwMmxTUDJRK2dIbzcv
TWMxL0FndGFqRlVyNFgxUjdIVVVRTUkKqtG3A2QgQtII1F3AhOBVggdtG8V8QezT
CTvO9LcCrb4cy2kC/7hC1HoUFVz3CJGlubS0QA9nfB4o3s5qdZ5XvA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ekt5xz7u2xgdzgsrffhd9x22n80cn4thxd8zxjy2ey5vq3ca7gnqz25g5r
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjUGdYb3BFWUJTekdzdHdo
N0JIblVRSldRTmFPMC9ReHJOVm04ditlSjJVCkpabGRldkVOTTA0RnF1cDZkZ2Ji
UlhuU1NWTFBOSnc2TUI5amNXWUJDNWcKLS0tIG45Q2ZlbzdiZFlvODgrN1JtaTQy
RG00dTI4RVNPL2lqbDVJTzMrODlsS0kKVj9SIj0j+dXB1yDAsshcumTTxx/IaGo9
FJ+Lhcb6w8C+e6MFLHFl45ifYcyRV7vqzzdPUzemjyJWm0FqbSeu+Q==
-----END AGE ENCRYPTED FILE-----
- recipient: age1jpeh4s553taxkyxhzlshzqjfrtvmmp5lw0hmpgn3mdnmgzku332qe082dl
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVU3FsMUxGTC9XUTJ4Tys1
YXgxamo2d3IyTDQyS1orb1ZNbGJaaklGZnlFCmlnUjk1cysySlNHNmpQdERVSTRa
cFhIV1N1bUs0enJzMVkxYVBnNVdralkKLS0tIEFEak04NENELy9mNk4wVm4wWlVQ
TmsxQitKMkpNNzlQaTVVWnIzSHE3YUUK6d+F8J//NhP9/R8S9fm8JBI9N76bzD6o
tLuj1N6MG+R2xONW1C4Eu39K+I5ynNyMPFCo7ACKb1TF91i28V7wtQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1j2r8mypw44uvqhfs53424h6fu2rkr5m7asl7rl3zn3xzva9m3dcqpa97gw
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUVHFaR3BOaE1LSzFQSnB0
NnZsMnZud0xzcmV2S3JQUkpkaXlYTFFsa21BCjNYRFhJQ2VITGRRdzYycGFJVDFr
TFZ1ZFhjOW5MYThiUlloQW1Wa3lBMFEKLS0tIERrU3R1d2JWM2p6ZktxZ2JoamNq
WTJJdkNXTy8yYUNQS0RzRHZpQlZjV2sKmLACWwksFbii3K5E9sfTSJq2Z3HMaj/F
hsHcpeNPdKtQlWw7ILa6Dl0/0sVAXssRFamb6teEVchipF9KJVATLQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-04-29T08:40:40Z"
mac: ENC[AES256_GCM,data:4S2pnHbrARApO/hRWn0ZlgWNNgdzzd2T/fx3LJ8M8n1cE5Us5Tj0yFxJPoiT/1Y+n3aZ/9hKD7AyIXhhrXA9gXk2MLHI1XjYVYkAtlW7264SIt9ZCEuJk4KN7LJnlFvxjF18yjKMBmjl34FCDaD8C+Pv+L3L1wOw/CMHHJ3Ayik=,iv:zT/TS+EDnq9s8mZiGR3rE2EDXwtPV3XUWE3xN2sHPQ4=,tag:Kh+PD7Hg5veeZvTb7Ta8rQ==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.8.1

View file

@ -0,0 +1,92 @@
{ lib
, config
, pkgs
, ...
}:
with lib;
let
cfg = config.mySystem.services.node-red;
app = "node-red";
persistentFolder = "${config.mySystem.persistentFolder}/${appFolder}";
appFolder = "apps/${app}";
user = config.services.node-red.user;
group = config.services.node-red.group;
url = "code-${config.networking.hostName}.${config.networking.domain}";
in
{
options.mySystem.services.node-red =
{
enable = mkEnableOption "node-red";
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
};
config = mkIf cfg.enable {
# ensure folder exist and has correct owner/group
systemd.tmpfiles.rules = [
"d ${persistentFolder} 0755 ${user} ${group} -" #The - disables automatic cleanup, so the file wont be removed after a period
];
services.node-red = {
enable = true;
userDir = persistentFolder;
};
mySystem.services.traefik.routers = [{
http.routers.${app} = {
rule = "Host(`${app}.${config.mySystem.domain}`)";
entrypoints = "websecure";
middlewares = "local-ip-only@file";
service = "${app}";
};
http.services.${app} = {
loadBalancer = {
servers = [{
url = "http://localhost:1880";
}];
};
};
}];
mySystem.services.homepage.media = mkIf cfg.addToHomepage [
{
code-shodan = {
icon = "${app}.svg";
href = "https://${url}";
description = "Music management";
container = "${app}";
widget = {
type = "${app}";
url = "https://${url}";
key = "{{HOMEPAGE_VAR_LIDARR__API_KEY}}";
};
};
}
];
mySystem.services.gatus.monitors = [{
name = app;
group = "media";
url = "https://${url}";
interval = "1m";
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];
}];
services.restic.backups = config.lib.mySystem.mkRestic
{
inherit app;
user = builtins.toString user;
excludePaths = [ "Backups" ];
paths = [ appFolder ];
inherit appFolder;
};
};
}

View file

@ -17,16 +17,18 @@ in
{ {
app = "Redlib"; app = "Redlib";
description = "Reddit alternate frontend"; description = "Reddit alternate frontend";
image = "quay.io/redlib/redlib@sha256:7fa92bb9b5a281123ee86a0b77a443939c2ccdabba1c12595dcd671a84cd5a64";
port = 8080; port = 8080;
user = "nobody"; user = "nobody";
group = "nobody"; group = "nobody";
timeZone = config.time.timeZone; timeZone = config.time.timeZone;
domain = config.networking.domain; domain = config.networking.domain;
addToHomepage = true; homepage = {
homepage.icon = "libreddit.svg"; icon = "libreddit.svg";
homepage.category = "home"; category = "home";
};
container = { container = {
enable = true;
image = "quay.io/redlib/redlib@sha256:7fa92bb9b5a281123ee86a0b77a443939c2ccdabba1c12595dcd671a84cd5a64";
env = { env = {
REDLIB_DEFAULT_SHOW_NSFW = "on"; REDLIB_DEFAULT_SHOW_NSFW = "on";
REDLIB_DEFAULT_USE_HLS = "on"; REDLIB_DEFAULT_USE_HLS = "on";

View file

@ -71,7 +71,7 @@ in
mySystem.services.gatus.monitors = [{ mySystem.services.gatus.monitors = [{
name = app; name = app;
group = "media"; group = "services";
url = "https://${app}.${config.mySystem.domain}"; url = "https://${app}.${config.mySystem.domain}";
interval = "1m"; interval = "1m";
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ]; conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];

View file

@ -19,7 +19,7 @@ with lib;
]; ];
initialize = true; initialize = true;
backupPrepareCommand = '' backupPrepareCommand = ''
# remove stale locks - this avoids some annoyance # remove stale locks - this avoids some occasional annoyance
# #
${pkgs.restic}/bin/restic unlock --remove-all || true ${pkgs.restic}/bin/restic unlock --remove-all || true
''; '';

View file

@ -75,7 +75,6 @@ in
upstream_dns = [ upstream_dns = [
# split brain dns - forward to local powerdns # split brain dns - forward to local powerdns
"[/trux.dev/]127.0.0.1:5353" "[/trux.dev/]127.0.0.1:5353"
"[/natallan.com/]127.0.0.1:5353"
# resolve fqdn for local ip's # resolve fqdn for local ip's
"[/l.voltaicforge.com/]10.8.10.1" "[/l.voltaicforge.com/]10.8.10.1"
@ -111,47 +110,29 @@ in
theme = "auto"; theme = "auto";
}; };
filters =
filters = [ let
{ urls = [
# AdGuard Base filter, Social media filter, Spyware filter, Mobile ads filter, EasyList and EasyPrivacy { name = "AdGuard DNS filter"; url = "https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt"; }
enabled = true; { name = "AdAway Default Blocklist"; url = "https://adaway.org/hosts.txt"; }
id = 1; { name = "Big OSID"; url = "https://big.oisd.nl"; }
name = "AdGuard DNS filter"; { name = "1Hosts Lite"; url = "https://o0.pages.dev/Lite/adblock.txt"; }
url = "https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt"; { name = "hagezi multi pro"; url = "https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/pro.txt"; }
} { name = "osint"; url = "https://osint.digitalside.it/Threat-Intel/lists/latestdomains.txt"; }
{ { name = "phishing army"; url = "https://phishing.army/download/phishing_army_blocklist_extended.txt"; }
# AdAway default blocklist { name = "notrack malware"; url = "https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-malware.txt"; }
enabled = true; { name = "EasyPrivacy"; url = "https://v.firebog.net/hosts/Easyprivacy.txt"; }
id = 2;
name = "AdAway Default Blocklist";
url = "https://adaway.org/hosts.txt";
}
{
# Big OSID
enabled = true;
id = 3;
name = "Big OSID";
url = "https://big.oisd.nl";
}
{
# 1Hosts Lite
enabled = true;
id = 4;
name = "1Hosts Lite";
url = "https://o0.pages.dev/Lite/adblock.txt";
}
{
# HAGEZI Multi Pro
enabled = true;
id = 5;
name = "hagezi multi pro";
url = "https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/pro.txt";
}
]; ];
buildList = id: url: {
enabled = true;
id = id;
name = url.name;
url = url.url;
};
in
(lib.imap1 buildList urls);
}; };
}; };

View file

@ -0,0 +1,221 @@
{ lib
, config
, pkgs
, ...
}:
with lib;
let
cfg = config.mySystem.services.blocky;
in
{
options.mySystem.services.blocky.enable = mkEnableOption "blocky";
config = mkIf cfg.enable {
services.blocky = {
enable = true;
settings = {
# optional: use black and white lists to block queries (for example ads, trackers, adult pages etc.)
blocking = {
# definition of blacklist groups. Can be external link (http/https) or local file
blackLists = {
ads = [
"https://blocklistproject.github.io/Lists/ads.txt"
];
malicious = [
"https://blocklistproject.github.io/Lists/adguard/malware-ags.txt"
];
adult = [
"https://blocklistproject.github.io/Lists/adguard/porn-ags.txt"
];
void = [ ];
};
# definition of whitelist groups. Attention: if the same group has black and whitelists, whitelists will be used to disable particular blacklist entries. If a group has only whitelist entries -> this means only domains from this list are allowed, all other domains will be blocked
whiteLists.ads = [ ];
# definition: which groups should be applied for which client
clientGroupsBlock = {
# default will be used, if no special definition for a client name exists
default = [ "ads" "malicious" ];
# use client name (with wildcard support: * - sequence of any characters, [0-9] - range)
# or single ip address / client subnet as CIDR notation
# "foo*" = [ "ads" ];
"10.8.10.40/24" = [ "ads" "malicioous" "adult" ];
};
# which response will be sent, if query is blocked:
# zeroIp: 0.0.0.0 will be returned (default)
# nxDomain: return NXDOMAIN as return code
# comma separated list of destination IP addresses (for example: 192.100.100.15, 2001:0db8:85a3:08d3:1319:8a2e:0370:7344). Should contain ipv4 and ipv6 to cover all query types. Useful with running web server on this address to display the "blocked" page.
blockType = "zeroIp";
# optional: TTL for answers to blocked domains
# default: 6h
blockTTL = "6h";
loading = {
# optional: automatically list refresh period (in duration format). Default: 4h.
# Negative value -> deactivate automatically refresh.
# 0 value -> use default
refreshPeriod = "4h";
# optional: if failOnError, application startup will fail if at least one list can't be downloaded / opened. Default: blocking
strategy = "fast";
downloads = {
# optional: timeout for list download (each url). Default: 60s. Use large values for big lists or slow internet connections
timeout = "60s";
# optional: Number of download attempts.
attempts = 5;
# optional: Time between the download attempts. Default: 1s
cooldown = "1s";
};
};
};
# optional: use these DNS servers to resolve blacklist urls and upstream DNS servers. It is useful if no system DNS resolver is configured, and/or to encrypt the bootstrap queries.
bootstrapDns = [
{
upstream = "https://one.one.one.one/dns-query";
ips = [ "1.1.1.1" "1.0.0.1" ];
}
{
upstream = "https://dns.quad9.net/dns-query";
ips = [ "9.9.9.9" "149.112.112.112" ];
}
];
# optional: configuration for caching of DNS responses
caching = {
# duration how long a response must be cached (min value).
# If <=0, use response's TTL, if >0 use this value, if TTL is smaller
# Default: 0
minTime = "0m";
# duration how long a response must be cached (max value).
# If <0, do not cache responses
# If 0, use TTL
# If > 0, use this value, if TTL is greater
# Default: 0
maxTime = "0m";
# Max number of cache entries (responses) to be kept in cache (soft limit). Useful on systems with limited amount of RAM.
# Default (0): unlimited
maxItemsCount = 0;
# if true, will preload DNS results for often used queries (default: names queried more than 5 times in a 2-hour time window)
# this improves the response time for often used queries, but significantly increases external traffic
# default: false
prefetching = true;
# prefetch track time window (in duration format)
# default: 120
prefetchExpires = "2h";
# name queries threshold for prefetch
# default: 5
prefetchThreshold = 5;
# Max number of domains to be kept in cache for prefetching (soft limit). Useful on systems with limited amount of RAM.
# Default (0): unlimited
prefetchMaxItemsCount = 0;
# Time how long negative results (NXDOMAIN response or empty result) are cached. A value of -1 will disable caching for negative results.
# Default: 30m
cacheTimeNegative = "90m";
};
# optional: Determines how blocky will create outgoing connections. This impacts both upstreams, and lists.
# accepted: dual, v4, v6
# default: dual
connectIPVersion = "v4";
# optional: custom IP address(es) for domain name (with all sub-domains). Multiple addresses must be separated by a comma
# example: query "printer.local" or "my.printer.local" will return 192.168.178.3
customDNS = {
customTTL = "1h";
# optional: if true (default), return empty result for unmapped query types (for example TXT, MX or AAAA if only IPv4 address is defined).
# if false, queries with unmapped types will be forwarded to the upstream resolver
filterUnmappedTypes = false;
# optional: replace domain in the query with other domain before resolver lookup in the mapping
# mapping = [ ];
};
# conditional = {
# fallbackUpstream = false;
# mapping = {
# "trux.dev" = "127.0.0.1:5353";
# # resolve fqdn for local ip's
# "l.voltaicforge.com" = "10.8.10.1";
# # reverse dns setup
# "in-addr.arpa" = "10.8.10.1"; # reverse dns lookup to UDMP
# "ip6.arpa" = "10.8.10.1"; # reverse dns lookup to UDMP
# };
# };
# optional: drop all queries with following query types. Default: empty
filtering.queryTypes = [ "AAAA" ];
# optional: logging configuration
log = {
# optional: Log level (one from debug, info, warn, error). Default: info
level = "info";
# optional: Log format (text or json). Default: text
format = "text";
# optional: log timestamps. Default: true
timestamp = true;
# optional: obfuscate log output (replace all alphanumeric characters with *) for user sensitive data like request domains or responses to increase privacy. Default: false
privacy = false;
};
# optional: Minimal TLS version that the DoH and DoT server will use
minTlsServeVersion = "1.2";
# if https port > 0: path to cert and key file for SSL encryption. if not set, self-signed certificate will be generated
#certFile: server.crt
#keyFile: server.key
# optional: ports configuration
ports = {
# optional: DNS listener port(s) and bind ip address(es), default 53 (UDP and TCP). Example: 53, :53, "127.0.0.1:5353,[::1]:5353"
dns = 53;
# optional: Port(s) and bind ip address(es) for DoT (DNS-over-TLS) listener. Example: 853, 127.0.0.1:853
tls = 853;
# optional: Port(s) and optional bind ip address(es) to serve HTTPS used for prometheus metrics, pprof, REST API, DoH... If you wish to specify a specific IP, you can do so such as 192.168.0.1:443. Example: 443, :443, 127.0.0.1:443,[::1]:443
https = 8443;
# optional: Port(s) and optional bind ip address(es) to serve HTTP used for prometheus metrics, pprof, REST API, DoH... If you wish to specify a specific IP, you can do so such as 192.168.0.1:4000. Example: 4000, :4000, 127.0.0.1:4000,[::1]:4000
http = 4000;
};
# optional: configuration for prometheus metrics endpoint
prometheus = {
# enabled if true
enable = true;
# url path, optional (default '/metrics')
path = "/metrics";
};
# optional: If true, blocky will fail to start unless at least one upstream server per group is reachable. Default: false
startVerifyUpstream = true;
upstreams = {
groups = {
# these external DNS resolvers will be used. Blocky picks 2 random resolvers from the list for each query
# format for resolver: [net:]host:[port][/path]. net could be empty (default, shortcut for tcp+udp), tcp+udp, tcp, udp, tcp-tls or https (DoH). If port is empty, default port will be used (53 for udp and tcp, 853 for tcp-tls, 443 for https (Doh))
# this configuration is mandatory, please define at least one external DNS resolver
default = [
"https://dns10.quad9.net/dns-query"
"https://dns.cloudflare.com/dns-query"
"https://doh.mullvad.net/dns-query"
];
# optional: use client name (with wildcard support: * - sequence of any characters, [0-9] - range)
# or single ip address / client subnet as CIDR notation
"10.8.50.1/24" = [ "https://cloudflare-dns.com/dns-query" ];
};
# Blocky supports different upstream strategies (default parallel_best) that determine how and to which upstream DNS servers requests are forwarded.
strategy = "parallel_best";
# optional: timeout to query the upstream resolver. Default: 2s
timeout = "2s";
};
};
};
};
}

View file

@ -29,7 +29,7 @@ in
config.environment = mkIf cfg.enable { config.environment = mkIf cfg.enable {
systemPackages = with pkgs; systemPackages = with pkgs;
[ [
(mkIf config.virtualisation.podman.enable nur.repos.procyon.cockpit-podman) # only if server runs pods # (mkIf config.virtualisation.podman.enable nur.repos.procyon.cockpit-podman) # TODO replace only if server runs pods
# nur.repos.dukzcry.cockpit-machines # TODO enable with virtualisation on server # nur.repos.dukzcry.cockpit-machines # TODO enable with virtualisation on server
# nur.repos.dukzcry.libvirt-dbus # TODO enable with virtualisation on server # nur.repos.dukzcry.libvirt-dbus # TODO enable with virtualisation on server

View file

@ -17,5 +17,8 @@
./adguardhome ./adguardhome
./mosquitto ./mosquitto
./zigbee2mqtt ./zigbee2mqtt
./postgresql
./blocky
./openvscode-server
]; ];
} }

View file

@ -1,8 +1,8 @@
services: services:
mosquitto: mosquitto:
mq: mq:
hashedPassword: ENC[AES256_GCM,data:FI2KLDYBW+HCXbOfmdyRYEwI8IeEX2iNWAiyGyn6FE2kkP1K1GETLbissBds+6DAPgbBULhxh8PZ9nkOCtR9QGKLkImxgMU1o8Zmwc6UxfkmFWvEDyt0/3g5gEVoO2rsLx4GMp4qO6Wbz0QCxJWJwQ==,iv:Pt9g/c3A1aChcgxQMSa76f1/c7uq8ctf9CDTFKNSvcs=,tag:zSS9heWyjvwFwKoEmYo+GA==,type:str] hashedPassword: ENC[AES256_GCM,data:rQYF6iIShg6CourZ6OzxKuAaXvIjDNThFm0g2foz05579PIPda/rAq7AgpKsiE0D5sCWhdJMfTYh58f8jTPN6ogzP1vb4tLHwzAI/w9DrDpoOH7dzkqcCXfkY0gVKdnKxXnzxnEefysaC9ReAq9IBw==,iv:ZHa+ihzRyCmAbvo1oZbtoqszKwyzoDTcdc5Ye6D7CMw=,tag:eQMR2NQzyYCkhEzX7dhaDQ==,type:str]
plainPassword.yaml: ENC[AES256_GCM,data:z+/SQE+PfsIoDekjf5D6f6nkxsfiNmcym4YSVdIl,iv:heh5N8HazUUP251llJLVGdka+65Ofjm4by1kug5uKYI=,tag:NS5K47rZRLH6OzyQopB3+A==,type:str] plainPassword.yaml: ENC[AES256_GCM,data:lbEC1tPTJiuNE0SluO4kYgQgCvOAXlJBZeTpBvRy,iv:N2HAZs/+6faMa/Ujo70ETHTPz/imi5pfqN9AZMFtR6g=,tag:sgFpjbnopM4KHgKGTw4nxw==,type:str]
sops: sops:
kms: [] kms: []
gcp_kms: [] gcp_kms: []
@ -12,68 +12,68 @@ sops:
- recipient: age1lj5vmr02qkudvv2xedfj5tq8x93gllgpr6tzylwdlt7lud4tfv5qfqsd5u - recipient: age1lj5vmr02qkudvv2xedfj5tq8x93gllgpr6tzylwdlt7lud4tfv5qfqsd5u
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjNmJPbGFaRXkrYnh6RHR4 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzd01kUitkWFYraHNRWVNa
dHBWNWs0RDB1UnFycXdoWmFFYkNGcHh4YUZjCm9LYnZIU1dvNzVTNHp0NjBEMTE2 S0pWSFJONWtMWkFIZlp5RkVFVktRQ2pNZmtFClBrQzIrT2JrWGNpaElaNytsSGRz
MHpOdVh5aVR3c2o5V21LU1ZDWnpXdFEKLS0tIDB4emRQRGVVYzFYQ2JsakVIeFhn Yk9OVXNnWmlraXgwb005R3BvTHlocWMKLS0tIGx1bUE5SnFBMnNIMG4zRTF4SE4v
QlFEYjBSVjVKUFVEV3gwK2NZaW1XSGMKHBPiLSd7Ixs68xMcpOJzw2Vu4GbKAglY T3IwT3c1bHZTMUN5K01iOHFiYTVHeE0KNOeRo78A13VYg0IrwmqBYYi+SSRurTc8
1yAcQgIRvFxCV/uz4BwAFvyCtYYsUD4GhEAFp/wwq6W1hTEAseV0RA== Xbdl2CFMR+i+2gL1dRx7clFX5bXvft0g3Ma2eMJaAg/lCUo5CDr/tw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age17edew3aahg3t5nte5g0a505sn96vnj8g8gqse8q06ccrrn2n3uysyshu2c - recipient: age17edew3aahg3t5nte5g0a505sn96vnj8g8gqse8q06ccrrn2n3uysyshu2c
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGRGE0OWZaR0ZhY2piMkxY YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBidStyMXBRNkt5dDh2cnZx
cG1HRFIrWjJFeG8vbzhPWW51cWVvN2FXV2hvCjhLNmVwRkRWQm54N3FPczFudGVB bXZqdm45WktRN3NUL3RyVHd1THhWVFF0V0F3CllHMXg2TGxKY0Vhdjc1MythMHJJ
N096dmFaUktqMDBIRWxlTnVaa2VOcVkKLS0tIEFZSmYweDRqVlpOdUhESXFjbnR0 N1NmeTBRYWxSeUNucWl5Z0hwTVQ0S3cKLS0tIDRFVGVDTURtSVp1QTFxazZPMnM5
RXpBU2t0bFlJQW1RSXZ0dzZFT3RXT0UKraC9wurjhf+SiKPewE5L3auOI59kaj/h THUzOFNDZ0dYNGtOY3dPOFA4aGxFSkEKJc6Q5goFoZ6qhVUlxUw1S/NzwPbL9kWs
7nUUnWUQfkebO5wxtmbbmenXK//oY1tRbC/Dp2JPUTQo2wwrXMF/JQ== 11jAiUxoUXySI3nCfg4TVNzxUPwn0ecnDH6Q/Q4Xa+ZU+zfCZI5UVw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1u4tht685sqg6dkmjyer96r93pl425u6353md6fphpd84jh3jwcusvm7mgk - recipient: age1u4tht685sqg6dkmjyer96r93pl425u6353md6fphpd84jh3jwcusvm7mgk
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEVjdTRkdDMElXV0pLL3Fv YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUZWJkWjkyS0g1MlBGeTRQ
MFpxaStjaHNPSmY1RnFUbUhVS09hUEZYYVFVCk4yUEsxV2FvYm5ybVdGS0pmVW5m ejJPMUV3cmdqUU83c2xtZHJyZEkvbFYyaTB3Ck5yZnFXTmpZeTYwU2txc1Q1NktZ
b1FYb3RxYXFhVVhjNms1bjBtVEYyMm8KLS0tIDk2Uy9xT3VZdGdSY1Rjc3l5OGE4 cVhDS0FwWDIwZG82Y3VGVmpUQXlXbzAKLS0tIFBwcjdSTU9Vblk5djdhWG93NHBN
ZzJvWTdDRlFNMmliUGZZbnRCc0UwRHcKdJllfqPlYBNf/nWkT5E1Is1moIFvN6lc NERNbWtmVXlxMThFdDNPdTBvcHR4cDgKXSZczDzQ0dhOTa3gQd0T/jvqnVt3fq/t
XVGQ9tzH1tpZC9PwmC1nL08fmuzwI5k9zqL2D+eG+vH7yjBLRFzxVg== sj2ZXRvfFBsRhhmvKXWODRzq2EFBBSTmsa0vXPrAIKKrXjHsYdyYsA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1cp6vegrmqfkuj8nmt2u3z0sur7n0f7e9x9zmdv4zygp8j2pnucpsdkgagc - recipient: age1cp6vegrmqfkuj8nmt2u3z0sur7n0f7e9x9zmdv4zygp8j2pnucpsdkgagc
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzOUJOTFJFSHp1QTdKVmZk YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZcm9sRFpTZE51SVd2YTJr
UVZhVEpqQzVTOTZHOXBYbDJUVjBpL2ErV2tJCm1jOUVmVE8wc3ZLSDZJRVkxQkNU amlzRjB2emszSmR5S2w0V09DUm8rbndtaVJrCmJOKzNjUC9PNjJsYXF5cGJXdTYx
eEw2RVNpVzJFcTlPbnF1Q2g0RVo5OUEKLS0tIFpvcU11RGVNR0dNQWc1aGJFd1lm bHZ0VjJrZUF0d2diOU9qVGQ3QUFqdW8KLS0tIExxUld4aWVpVWZ5SVphQkhnSDdS
Ym1kellUNjRsTTdQZTViZnBkRllqbWsKWFwR8WeIxJunlgzT3GpYkIdFRLJZlhm4 ZzZoRjJpN1FzM1pZQjNBaFNyS0RsODgKwMsYtYN+fepfQX8aS0scDdgloT6Qx+xq
Vr4N5CMnNXJYWRiNJDrHDKvVw6EeUUhyJ+7aJ9UAfR0YfX47yIlW5A== u3Gu3CF9uCifK0I/kr+4DzPpV/vJBR0Ash0NqSO69ljhYW2cc+NgnA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1ekt5xz7u2xgdzgsrffhd9x22n80cn4thxd8zxjy2ey5vq3ca7gnqz25g5r - recipient: age1ekt5xz7u2xgdzgsrffhd9x22n80cn4thxd8zxjy2ey5vq3ca7gnqz25g5r
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnWUpaOUVnRS9Va211UXl0 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1bi9EZDZKVVMrRGZaZ1lV
dUFmOVlmR2d1REVNRXJKMFV1OTVsSDZGRldvCk5CcGpWZHFBYmtsbVRjWW1QejNJ a0pRY254YzNMVWdRdGtMbnhGbU1nY2NQN1RnCm5rVHNoMFg2SEE5TElqeE9LRGNP
Y0FPSVJ1UlhhcVhRaTVXMERyRURIRjAKLS0tIDloZ2J0anNqSEZmUXg4eDFyTVZ0 Ykk0c2RrZWRZT2xBeHhrRVI2dlJKVDgKLS0tIGlZY2tUTkVWOWluU0RReC81bS9N
WXAvTmRpUjRKMnJlZmV0SEEwZndtNkEK99oVyOIlfKP6zHnuS1LKGORuOLfX3vAU aFpyZS8zQ3YzNkMwV2lNYmFXNEt5TWMKSivmE6kEm9lEfEdJmn9gorprZGz59blJ
Gw7IHXRUSpZhElOSK0jc9F2O6IEGYpfu5PYC4m8uojhRXsG6W/XTXA== xQaFGuqYQBiVj1SQA/NCcVqBnoFBwC+WuCkGIuezzsQGEFp4FxmSwQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1jpeh4s553taxkyxhzlshzqjfrtvmmp5lw0hmpgn3mdnmgzku332qe082dl - recipient: age1jpeh4s553taxkyxhzlshzqjfrtvmmp5lw0hmpgn3mdnmgzku332qe082dl
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArUVZScTVpWjZvUzlFeDVQ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0Z0ZlZHg4QjJ2bzlFY3pt
RjRreTBPTEF3bXZ1Sk5sWmgzUURxcU5talFzClFRSjFFUEtQMis4dkNLRFFaaHlq VE1oZ2QySDFnejlvUDFpdlBhN1hMVnBDNkVnCkF1UnpsaHZBRTJKRFpBcFB2eDBU
QXdhQWxEMXdHSGgzSXlqZm4xbEFVaGMKLS0tIG9OOHUwZWI3SXJ2SWZvdS9EVzV5 ZU4xSGc3YXVJbkxvSG04MjBVb3I4bFUKLS0tIHFWTFVBbWRSazNMc053S1QvVDhJ
aVpWNmk5b1owbjJHSWtnOHRJWmhEbGMKT4VdLG/8qX+KWO6vQ2TsrT1+w4XgDani cmRidFd6TWV0RXFOd2FBWkZCaE9RZncKdm5y1iSNtp9G7TO0P37P+txz25kwYLuU
KOAS/DimV22EjmHljs9ByWdqkVw0KIBfp2oXo9m0Jqn0H1M2yEMozg== 0IOBAf5JzqmiVV3cOPumhnXxESo2AG8404U1FV/7BsyCtDLWy/Sm4Q==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1j2r8mypw44uvqhfs53424h6fu2rkr5m7asl7rl3zn3xzva9m3dcqpa97gw - recipient: age1j2r8mypw44uvqhfs53424h6fu2rkr5m7asl7rl3zn3xzva9m3dcqpa97gw
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWNzZiS1pVTXMxQW9UUldr YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEOUlsT2hiVlV4c2JtN2dJ
dFNHUDhxV1lnOFNaK2J6SEY3WUtId0FLSTNjCkJhUm1sVnlJMFk5Wm9lNGdMYnZv dC8yb3N0L0xxczAyVWpJdHhTNzNBZFhwK1ZNCkt6VWloUDJzNDVJajN5OHJzcXQy
eVR6MGNVYjBSNENqU1BJWituMnJJeFUKLS0tIEk0ZUVETHRmSmJjT2NDMGNrajlZ SEdCbVdMd0lTZmU2aTZhUGdVYWhDbkUKLS0tIGc2K3VFeWVUUjFwRGk4eXNCRFFV
NUMxdEhvQnRES2hwck5jeEw3bnprZ00KUnkLNK+hmCihLwPiWt3NHjASuQwgBOlf RlFqRytvRWFoY1hjRHg0SS9SZWloWFUKhdVdRHgnJ6n0UMLlhspqtBmvgO7TkZXb
AsW8BkUjjQY/ABR3X6sNSI8uXQt+8BHP14U4cO8jwggcyE2W1Pq03A== fNhTuhmCi5THYE/I1/8Q9dMHwBPIRVM+1N2ZLrobd5GuS4ZY4AUXFQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-04-25T05:21:30Z" lastmodified: "2024-04-29T06:34:35Z"
mac: ENC[AES256_GCM,data:aN2YsPhDMl8vvLgi98iRCl5f7llJ8VTt7y1vh7liBAwG6hW1vZeetqSxvWiVDugozjsbK6n44AUDjhnfwo8EXp8iWQmJDXuS1PoEph4C18oo4Eu8n9ZpLQFGSKRMYXuetwrzOkn42tMYadYbwLPIandKqaTGUD4FcoqZtGxaH3c=,iv:Wfb1r8JNO74KjBWTIGwW2bXTVv3AIpj5KW9FXYrDm7c=,tag:FEnXv1S0J3XaxZ6TQz0bhQ==,type:str] mac: ENC[AES256_GCM,data:yaPeSkjnA2rQhUVbJd7JIgwbQe2xFl/GFZb+nPZUSZ+SrTnJd90X4NWxnyREkv7kvYzrmMF0XqMhZFHkQf6iGXwRlN53Bz4DjsGrHKDoxjYznOY8U2/UNgghqmZRjhrMBJecxjBjXpxb6myoi6MlRB6T/BC01DGy91s/T8lpqtM=,iv:7Dd6PiMObDY6MJ6G/Xz9sC6//qImtW+ErPtc1kbf33A=,tag:hLc+AtDVLHW4wHHZOrYQ7Q==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.8.1 version: 3.8.1

View file

@ -0,0 +1,72 @@
{ lib
, config
, pkgs
, ...
}:
with lib;
let
cfg = config.mySystem.services.openvscode-server;
app = "openvscode-server";
url = "code-${config.networking.hostName}.${config.networking.domain}";
in
{
options.mySystem.services.openvscode-server =
{
enable = mkEnableOption "openvscode-server";
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
};
config = mkIf cfg.enable {
services.openvscode-server = {
enable = true;
telemetryLevel = "off";
package = pkgs.unstable.openvscode-server; # TODO move to stable in 24.05?
# serverDataDir
user = "truxnell";
host = "0.0.0.0";
extraPackages = with pkgs;[ fish tmux ];
withoutConnectionToken = true;
};
mySystem.services.traefik.routers = [{
http.routers.${app} = {
rule = "Host(`${url}`)";
entrypoints = "websecure";
middlewares = "local-ip-only@file";
service = "${app}";
};
http.services.${app} = {
loadBalancer = {
servers = [{
url = "http://localhost:${builtins.toString config.services.openvscode-server.port}";
}];
};
};
}];
mySystem.services.homepage.media = mkIf cfg.addToHomepage [
{
code-shodan = {
icon = "vscode.svg";
href = "https://${url}";
description = "Code editor";
container = "${app}";
};
}
];
mySystem.services.gatus.monitors = [{
name = app;
group = "services";
url = "https://${url}";
interval = "1m";
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];
}];
};
}

View file

@ -0,0 +1,30 @@
{ lib
, config
, pkgs
, ...
}:
with lib;
let
cfg = config.mySystem.services.postgresql;
in
{
options.mySystem.services.postgresql.enable = mkEnableOption "postgresql";
config = mkIf cfg.enable {
services.postgresql = {
enable = true;
authentication = ''
local homeassistant homeassistant ident map=ha
'';
identMap = ''
ha root homeassistant
'';
ensureDatabases = [ "homeassistant" ];
ensureUsers = [
{ name = "homeassistant"; ensureDBOwnership = true; }
];
};
};
}

View file

@ -105,6 +105,11 @@ in
config = mkIf cfg.enable config = mkIf cfg.enable
{ {
# ensure folder exist and has correct owner/group
systemd.tmpfiles.rules = [
"f ${config.services.traefik.dataDir}/acme.json 0600 traefik ${config.services.traefik.group} -" #The - disables automatic cleanup, so the file wont be removed after a period
];
# put the dynamic configs in a file # put the dynamic configs in a file
# i put this in a file instead of piping directly into # i put this in a file instead of piping directly into
# the traefik module, so that if i update the file # the traefik module, so that if i update the file

View file

@ -37,7 +37,7 @@ in
enable = true; enable = true;
dataDir = persistentFolder; dataDir = persistentFolder;
settings = { settings = {
advanced.log_level = "warn"; advanced.log_level = "debug";
homeassistant = true; homeassistant = true;
permit_join = false; permit_join = false;
include_device_information = true; include_device_information = true;
@ -79,7 +79,7 @@ in
}]; }];
mySystem.services.homepage.media = mkIf cfg.addToHomepage [ mySystem.services.homepage.infrastructure = mkIf cfg.addToHomepage [
{ {
${app} = { ${app} = {
icon = "${app}.svg"; icon = "${app}.svg";

View file

@ -34,7 +34,13 @@ with lib;
zfs rollback -r ${cfg.rootPoolName}@${cfg.rootBlankSnapshotName} zfs rollback -r ${cfg.rootPoolName}@${cfg.rootBlankSnapshotName}
''; '';
# environment.persistence."${cfg.persistPath}/nixos" = {
# hideMounts = true;
# directories =
# [
# "/var/log"
# ];
# };
# move ssh keys to persist folder # move ssh keys to persist folder
services.openssh.hostKeys = mkIf config.services.openssh.enable [ services.openssh.hostKeys = mkIf config.services.openssh.enable [