feat: postgres, calibre, radicale, z2m (#133)
* hax * hax * shell monitoring * hax radicale! * hacking * haxor * hax * hack * feat: refactor paths etc for impermance * fix: restic * hax * more hax * feat: migrate z2m * fix: websockets i guess * cleanup * hacks * hax * feat: miniflux + postgres * feat: add calibre * feat: calibre-web * Auto lint/format --------- Co-authored-by: Truxnell <9149206+truxnell@users.noreply.github.com> Co-authored-by: truxnell <truxnell@users.noreply.github.com>
This commit is contained in:
parent
5a39b54ae8
commit
49621dec0e
39 changed files with 1293 additions and 243 deletions
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
config = {
|
||||||
mySystem.purpose = "Network Attached Storage";
|
mySystem.purpose = "Network Attached Storage";
|
||||||
mySystem.system.impermanence.enable = true;
|
mySystem.system.impermanence.enable = true;
|
||||||
mySystem.services = {
|
mySystem.services = {
|
||||||
|
@ -43,7 +43,6 @@
|
||||||
mySystem.system.motd.networkInterfaces = [ "eno1" ];
|
mySystem.system.motd.networkInterfaces = [ "eno1" ];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
boot = {
|
boot = {
|
||||||
|
|
||||||
initrd.availableKernelModules = [ "xhci_pci" "ahci" "mpt3sas" "nvme" "usbhid" "usb_storage" "sd_mod" ];
|
initrd.availableKernelModules = [ "xhci_pci" "ahci" "mpt3sas" "nvme" "usbhid" "usb_storage" "sd_mod" ];
|
||||||
|
@ -95,6 +94,44 @@
|
||||||
swapDevices =
|
swapDevices =
|
||||||
[{ device = "/dev/disk/by-uuid/c2f716ef-9e8c-466b-bcb0-699397cb2dc0"; }];
|
[{ device = "/dev/disk/by-uuid/c2f716ef-9e8c-466b-bcb0-699397cb2dc0"; }];
|
||||||
|
|
||||||
|
# TODO does this live somewhere else?
|
||||||
|
# it is very machine-specific...
|
||||||
|
# add user with `sudo smbpasswd -a my_user`
|
||||||
|
services.samba = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
extraConfig = ''
|
||||||
|
workgroup = WORKGROUP
|
||||||
|
server string = daedalus
|
||||||
|
netbios name = daedalus
|
||||||
|
security = user
|
||||||
|
#use sendfile = yes
|
||||||
|
#max protocol = smb2
|
||||||
|
# note: localhost is the ipv6 localhost ::1
|
||||||
|
hosts allow = 10.8.10. 127.0.0.1 localhost
|
||||||
|
hosts deny = 0.0.0.0/0
|
||||||
|
guest account = nobody
|
||||||
|
map to guest = bad user
|
||||||
|
'';
|
||||||
|
shares = {
|
||||||
|
backup = {
|
||||||
|
path = "/tank/backup";
|
||||||
|
"read only" = "no";
|
||||||
|
};
|
||||||
|
documents = {
|
||||||
|
path = "/tank/documents";
|
||||||
|
"read only" = "no";
|
||||||
|
};
|
||||||
|
natflix = {
|
||||||
|
path = "/tank/natflix";
|
||||||
|
"read only" = "no";
|
||||||
|
};
|
||||||
|
# paperless = {
|
||||||
|
# path = "/tank/Apps/paperless/incoming";
|
||||||
|
# "read only" = "no";
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,13 @@
|
||||||
openssh.enable = true;
|
openssh.enable = true;
|
||||||
podman.enable = true;
|
podman.enable = true;
|
||||||
nginx.enable = true;
|
nginx.enable = true;
|
||||||
|
|
||||||
openvscode-server.enable = true;
|
openvscode-server.enable = true;
|
||||||
|
postgresql =
|
||||||
|
{ enable = true; backup = false; };
|
||||||
|
calibre-web = { enable = true; backup = false; dev = true; };
|
||||||
};
|
};
|
||||||
|
# mySystem.containers.calibre = { enable = true; backup = false; dev = true; };
|
||||||
|
|
||||||
mySystem.system.systemd.pushover-alerts.enable = false;
|
mySystem.system.systemd.pushover-alerts.enable = false;
|
||||||
|
|
||||||
mySystem.nfs.nas.enable = true;
|
mySystem.nfs.nas.enable = true;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
mySystem.services = {
|
mySystem.services = {
|
||||||
openssh.enable = true;
|
openssh.enable = true;
|
||||||
podman.enable = true;
|
podman.enable = true;
|
||||||
|
postgresql.enable = true;
|
||||||
|
|
||||||
nginx.enable = true;
|
nginx.enable = true;
|
||||||
|
|
||||||
|
@ -33,7 +34,14 @@
|
||||||
openvscode-server.enable = true;
|
openvscode-server.enable = true;
|
||||||
|
|
||||||
radicale.enable = true;
|
radicale.enable = true;
|
||||||
|
miniflux.enable = true;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
mySystem.containers = {
|
||||||
|
calibre.enable = true;
|
||||||
|
ecowitt2mqtt.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
mySystem.security.acme.enable = true;
|
mySystem.security.acme.enable = true;
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
};
|
};
|
||||||
|
|
157
nixos/modules/nixos/containers/calibre/default.nix
Normal file
157
nixos/modules/nixos/containers/calibre/default.nix
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
{ lib
|
||||||
|
, config
|
||||||
|
, pkgs
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.mySystem.${category}.${app};
|
||||||
|
app = "calibre";
|
||||||
|
category = "containers";
|
||||||
|
description = "eBook managment";
|
||||||
|
image = "ghcr.io/linuxserver/calibre:version-v7.10.0";
|
||||||
|
user = "0"; #string
|
||||||
|
group = "0"; #string
|
||||||
|
port = 8091; #int
|
||||||
|
appFolder = "/var/lib/${app}";
|
||||||
|
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||||
|
host = "${app}" + (if cfg.dev then "-dev" else "");
|
||||||
|
url = "${host}.${config.networking.domain}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.mySystem.${category}.${app} =
|
||||||
|
{
|
||||||
|
enable = mkEnableOption "${app}";
|
||||||
|
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
|
||||||
|
monitor = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable gatus monitoring";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
prometheus = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable prometheus scraping";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
addToDNS = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Add to DNS list";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
dev = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Development instance";
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
backup = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable backups";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
## Secrets
|
||||||
|
# sops.secrets."${category}/${app}/env" = {
|
||||||
|
# sopsFile = ./secrets.sops.yaml;
|
||||||
|
# owner = user;
|
||||||
|
# group = group;
|
||||||
|
# restartUnits = [ "${app}.service" ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
users.users.truxnell.extraGroups = [ group ];
|
||||||
|
|
||||||
|
|
||||||
|
# Folder perms - only for containers
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d ${appFolder}/ 0750 ${user} ${group} -"
|
||||||
|
];
|
||||||
|
|
||||||
|
## service
|
||||||
|
virtualisation.oci-containers.containers = config.lib.mySystem.mkContainer {
|
||||||
|
inherit app image user group;
|
||||||
|
|
||||||
|
env = {
|
||||||
|
PUID = "568";
|
||||||
|
PGID = "568";
|
||||||
|
};
|
||||||
|
volumes = [
|
||||||
|
"${appFolder}:/config:rw"
|
||||||
|
"${config.mySystem.nasFolder}/natflix/:/media:rw"
|
||||||
|
];
|
||||||
|
ports = [ "${builtins.toString port}:8080" ];
|
||||||
|
caps = {
|
||||||
|
noNewPrivileges = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# homepage integration
|
||||||
|
mySystem.services.homepage.infrastructure = mkIf cfg.addToHomepage [
|
||||||
|
{
|
||||||
|
${app} = {
|
||||||
|
icon = "${app}.svg";
|
||||||
|
href = "https://${url}";
|
||||||
|
inherit description;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
### gatus integration
|
||||||
|
mySystem.services.gatus.monitors = mkIf cfg.monitor [
|
||||||
|
{
|
||||||
|
name = app;
|
||||||
|
group = "${category}";
|
||||||
|
url = "https://${url}";
|
||||||
|
interval = "1m";
|
||||||
|
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
### Ingress
|
||||||
|
services.nginx.virtualHosts.${url} = {
|
||||||
|
forceSSL = true;
|
||||||
|
useACMEHost = config.networking.domain;
|
||||||
|
locations."^~ /" = {
|
||||||
|
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
### firewall config
|
||||||
|
|
||||||
|
# networking.firewall = mkIf cfg.openFirewall {
|
||||||
|
# allowedTCPPorts = [ port ];
|
||||||
|
# allowedUDPPorts = [ port ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
### backups
|
||||||
|
warnings = [
|
||||||
|
(mkIf (!cfg.backup && config.mySystem.purpose != "Development")
|
||||||
|
"WARNING: Backups for ${app} are disabled!")
|
||||||
|
];
|
||||||
|
|
||||||
|
services.restic.backups = mkIf cfg.backup (config.lib.mySystem.mkRestic
|
||||||
|
{
|
||||||
|
inherit app user;
|
||||||
|
paths = [ appFolder ];
|
||||||
|
inherit appFolder;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
# services.postgresqlBackup = {
|
||||||
|
# databases = [ app ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
./whoogle
|
./whoogle
|
||||||
./redlib
|
./redlib
|
||||||
./home-assistant
|
./home-assistant
|
||||||
# ./calibre
|
./calibre
|
||||||
|
./ecowitt2mqtt
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
158
nixos/modules/nixos/containers/ecowitt2mqtt/default.nix
Normal file
158
nixos/modules/nixos/containers/ecowitt2mqtt/default.nix
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
{ lib
|
||||||
|
, config
|
||||||
|
, pkgs
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.mySystem.${category}.${app};
|
||||||
|
app = "ecowitt2mqtt";
|
||||||
|
category = "containers";
|
||||||
|
description = "Weather station to MQTT";
|
||||||
|
image = "ghcr.io/bachya/ecowitt2mqtt:latest@sha256:3c6e9be9332e1b04db836ec721208c753a01faa236c7cf76f966f3ec4d64621d";
|
||||||
|
user = "nobody"; #string
|
||||||
|
group = "nobody"; #string
|
||||||
|
port = 8080; #int
|
||||||
|
# appFolder = "/var/lib/${app}";
|
||||||
|
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||||
|
host = "${app}" + (if cfg.dev then "-dev" else "");
|
||||||
|
url = "${host}.${config.networking.domain}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.mySystem.${category}.${app} =
|
||||||
|
{
|
||||||
|
enable = mkEnableOption "${app}";
|
||||||
|
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
|
||||||
|
monitor = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable gatus monitoring";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
prometheus = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable prometheus scraping";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
addToDNS = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Add to DNS list";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
dev = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Development instance";
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
backupLocal = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable local backups";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
backupRemote = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable remote backups";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
## Secrets
|
||||||
|
sops.secrets."${category}/${app}/env" = {
|
||||||
|
sopsFile = ./secrets.sops.yaml;
|
||||||
|
owner = user;
|
||||||
|
inherit group;
|
||||||
|
restartUnits = [ "podman-${app}.service" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.truxnell.extraGroups = [ group ];
|
||||||
|
|
||||||
|
|
||||||
|
# Folder perms - only for containers
|
||||||
|
# systemd.tmpfiles.rules = [
|
||||||
|
# "d ${persistentFolder}/ 0750 ${user} ${group} -"
|
||||||
|
# ];
|
||||||
|
|
||||||
|
## service
|
||||||
|
virtualisation.oci-containers.containers = config.lib.mySystem.mkContainer {
|
||||||
|
inherit app image user group;
|
||||||
|
env = {
|
||||||
|
ECOWITT2MQTT_MQTT_BROKER = "mqtt.trux.dev";
|
||||||
|
ECOWITT2MQTT_MQTT_PORT = "1883";
|
||||||
|
ECOWITT2MQTT_MQTT_TOPIC = "ecowitt2mqtt/pws";
|
||||||
|
ECOWITT2MQTT_PORT = "8080";
|
||||||
|
ECOWITT2MQTT_HASS_DISCOVERY = "true";
|
||||||
|
ECOWITT2MQTT_OUTPUT_UNIT_SYSTEM = "metric"; # Come on guys nobody want to use freedum units"
|
||||||
|
};
|
||||||
|
envFiles = [ config.sops.secrets."${category}/${app}/env".path ];
|
||||||
|
};
|
||||||
|
|
||||||
|
# homepage integration
|
||||||
|
# mySystem.services.homepage.infrastructure = mkIf cfg.addToHomepage [
|
||||||
|
# {
|
||||||
|
# ${app} = {
|
||||||
|
# icon = "${app}.svg";
|
||||||
|
# href = "https://${url}";
|
||||||
|
# description = description;
|
||||||
|
# };
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
|
||||||
|
### gatus integration
|
||||||
|
mySystem.services.gatus.monitors = mkIf cfg.monitor [
|
||||||
|
{
|
||||||
|
name = app;
|
||||||
|
group = "${category}";
|
||||||
|
url = "https://${url}/data/report"; # check the reporting URL for 405 'method not allowed's
|
||||||
|
interval = "1m";
|
||||||
|
conditions = [ "[CONNECTED] == true" "[STATUS] == 405" "[RESPONSE_TIME] < 50" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
### Ingress
|
||||||
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
|
# I dont need/want ssl for this one, weather station expets http
|
||||||
|
# useACMEHost = config.networking.domain;
|
||||||
|
# forceSSL = true;
|
||||||
|
locations."^~ /" = {
|
||||||
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
### firewall config
|
||||||
|
|
||||||
|
# networking.firewall = mkIf cfg.openFirewall {
|
||||||
|
# allowedTCPPorts = [ port ];
|
||||||
|
# allowedUDPPorts = [ port ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
### backups
|
||||||
|
# warnings = [
|
||||||
|
# (mkIf (!cfg.backupLocal && config.mySystem.purpose != "Development")
|
||||||
|
# "WARNING: Local backups for ${app} are disabled!")
|
||||||
|
# (mkIf (!cfg.backupRemote && config.mySystem.purpose != "Development")
|
||||||
|
# "WARNING: Remote backups for ${app} are disabled!")
|
||||||
|
# ];
|
||||||
|
|
||||||
|
# services.restic.backups = mkIf cfg.backups config.lib.mySystem.mkRestic
|
||||||
|
# {
|
||||||
|
# inherit app user;
|
||||||
|
# paths = [ appFolder ];
|
||||||
|
# inherit appFolder;
|
||||||
|
# local = cfg.backupLocal;
|
||||||
|
# remote = cfg.backupRemote;
|
||||||
|
# };
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
containers:
|
||||||
|
ecowitt2mqtt:
|
||||||
|
env: ENC[AES256_GCM,data:VP1/jz+SAK+ilGAlTt51bDS9QjzV+KXxN+c++/ZdYl4pFZrideghqCkGdknn83Jv4DcnIb30AtUdGR0QfTXY4AfFUUwJfgL8EcOe2+0=,iv:GSQ3/4q/cdOWZxYcGuFBzzyhDxf9wyRustiZgqB8PbI=,tag:/kLE6z5s5DDKGRxix7EnLw==,type:str]
|
||||||
|
sops:
|
||||||
|
kms: []
|
||||||
|
gcp_kms: []
|
||||||
|
azure_kv: []
|
||||||
|
hc_vault: []
|
||||||
|
age:
|
||||||
|
- recipient: age1lj5vmr02qkudvv2xedfj5tq8x93gllgpr6tzylwdlt7lud4tfv5qfqsd5u
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjRENkdkgycktRYnRLbHh3
|
||||||
|
MFNXSXZRU1Bnc0hpK1ZsOERQcG5Qd1BpRUJRCk00WkFKQWhZcmx4SFozd0JRN09r
|
||||||
|
bHpaODh5UGNOUFErbVdsK1VFYmdqT3cKLS0tIHdzQ2hxaVl1M1U2VDgrcHBOdlFz
|
||||||
|
eUhsRzJtNjQ1Mm9kdlI2OTRZVUpjY2sKDt5anrouamcYEaQDjiZEuZpdqe3uO1Ee
|
||||||
|
0BidTQuN9jfWOlIljftZ2CiedlCoYzXlnGkjIOMoD3uvRTpmRPKBdw==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age17edew3aahg3t5nte5g0a505sn96vnj8g8gqse8q06ccrrn2n3uysyshu2c
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxczQyV3JRNDVpZkZzSjVk
|
||||||
|
UWhzL28rZmtmSEI0N3pvWDlGUHhIQllySlM4CktXZlJCam1CUU9BNUpKTUgrRGJ4
|
||||||
|
NnE0c0x6WTRZMWsyVVBIVWw3Rmh6REUKLS0tIGJ4SllRa0p2c2p4UHkvMHBaUnhD
|
||||||
|
SU40RnZ4dXo1MXU2SjN2Q3ZHZXVjVUUKjeJxmnY397EK9MBe4uFpBQg0XE1p4y/0
|
||||||
|
cfck88D+LGvMrfBIsMcmMd2EmHsIzZt4SKMIr1ZQ+WdE+Mns6drHcQ==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1u4tht685sqg6dkmjyer96r93pl425u6353md6fphpd84jh3jwcusvm7mgk
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwWWxFcWhWOERzdVVmdE83
|
||||||
|
bmRyRXU1Z3RUU3MydWVJNlBUdlQ2NFVWSGxVCjRFY1BKOER6ejRIVWhLTVp4eSt4
|
||||||
|
c0Q5Rld1RFZKWEtGcThtUlJVMnpEcVEKLS0tIDhWMW45d1ZqZ25RY0NvVzQ0NTBK
|
||||||
|
RGttN1JNbXhmS2NnTFpOQlNKUC9vbm8KILk4bxt2b58+igJ4c4PrjgJY9AyGrvsO
|
||||||
|
zBfxhFvlGuYjR8W1r6VcH7+JsQhKZrw07gIU5ornHvE34oxgxdYXrA==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1cp6vegrmqfkuj8nmt2u3z0sur7n0f7e9x9zmdv4zygp8j2pnucpsdkgagc
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1b0x5QmJQbHA0STliVEM3
|
||||||
|
N0RZaFFud1VTbm4xUm5EMVFDMVRncGpDNWc0CndJYzVNMG8xZlo5dUlRb3BKVStF
|
||||||
|
OFdKYXdRL2ZwWlk1Uzd2WUthRTRzOEkKLS0tIFRVRnFpYWdTeGhNc1VpdCsrTFcv
|
||||||
|
bW5uVGNsQjFmUjNvQnYzc2pSMUliUjQKBzI9IGdKfEXNRVh3s7fon/6VS9ZUSpG/
|
||||||
|
hOHQ93wX0VAy6wO+iugDfM/1Zuc2V66+T4wYPfUtWapj009L31eufw==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1ekt5xz7u2xgdzgsrffhd9x22n80cn4thxd8zxjy2ey5vq3ca7gnqz25g5r
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBabEN5eXd2Q1A2R0ZsalYy
|
||||||
|
MW43TUdqaG80MmtzVit1QVdvcExQRjZYT1NjCnA5L2NxRks5UDZVYVVsRGJJZ3cz
|
||||||
|
bGhtVDFTVXFCTGtuUFRaNmtzVUdRZUEKLS0tIC9qYnRxZ2FqWllybnpMMU9NNDFx
|
||||||
|
VGNTdnhiMW9KcE9ST3RPUitaMVdsRVkKLaABu7ZJ1Nc4ROkrzoRiMe4vdLKMmzMW
|
||||||
|
O0ylhZRqqHx4nWGSBgx680zKm3WAx3o97nH3IFCaLlHuNGm46iOYkg==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1jpeh4s553taxkyxhzlshzqjfrtvmmp5lw0hmpgn3mdnmgzku332qe082dl
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDM2IvQU1IRnVVRVo0bmUx
|
||||||
|
QjMyZVRiN3pSUkNYUVYzSXVUSVBPTXdIWUZzCjZaOHo4bllaTklTb29XdVAySHJY
|
||||||
|
bmMwT3RxS0p5MjFHdXhIL0tIRERNTTAKLS0tIHBlQ2RJYTNDQm1oRGN3b2JIOXFi
|
||||||
|
YUdHa1RVVTRBbmJkdkdDa2JCbG40NlEKta9VW9hc2saA/nzWoER35S7Yl7M9CHQ7
|
||||||
|
YmZ4LIz8IqB6Sihk1pcmX2RAeMA8uMPfEMEBejwiuM57NjEFMgllbw==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1j2r8mypw44uvqhfs53424h6fu2rkr5m7asl7rl3zn3xzva9m3dcqpa97gw
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZSHYrejZ3RExjek1FR21Y
|
||||||
|
VlNvbmdnSjNrcHBkNFByNXpGTGkwMnVQMWlRCjg5U2l6NHVCakprVS9kUTFRa1lk
|
||||||
|
SXpEYU9WZHVlcGRSS1UyaDhkak5jMFEKLS0tIC8reGg4RWNDb1AzUkx5TGg1WVN1
|
||||||
|
ZzBpamhpVFRBZHZ0MTdJRTl5d2RqK3MKQuNJCLdNBa9DG8V4sRVQ6GKhWjcKK9eC
|
||||||
|
FcTxyUBPNDMVYlHR5DxONIfzT9ymlSReFUkwjXAgVTwhqLOgpTUGAw==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
lastmodified: "2024-05-03T09:52:12Z"
|
||||||
|
mac: ENC[AES256_GCM,data:Z4u5T4kJ+dRCE9qZENBstOMMrSSw503PRS5qwNmrx1kTbaNN5VPd/mrkxWM8pZudLxo3pBnCZSPYju1tpzQisRBcu/BwMAiBLx4xSJsEJhG//fWbv93XUGJ7i7nlW2Kl1V0QUrG1WSz5RXx1PE2oTEQCbRSGZyYo5FtHZsOhHEA=,iv:HidiueXjLNwBV1vY/7vNqWCDr+rfwN00NpfC9RuPZms=,tag:qkfNjPX6Ti2EnnWnqjtvNw==,type:str]
|
||||||
|
pgp: []
|
||||||
|
unencrypted_suffix: _unencrypted
|
||||||
|
version: 3.8.1
|
|
@ -69,7 +69,7 @@ in
|
||||||
RCON_PORT = "27019";
|
RCON_PORT = "27019";
|
||||||
};
|
};
|
||||||
environmentFiles = [ config.sops.secrets."services/${app}/env".path ];
|
environmentFiles = [ config.sops.secrets."services/${app}/env".path ];
|
||||||
ports = [ (builtins.toString port) ]; # expose port
|
ports = [ "${builtins.toString port}:${builtins.toString port}/UDP" ]; # expose port
|
||||||
};
|
};
|
||||||
networking.firewall = mkIf cfg.openFirewall {
|
networking.firewall = mkIf cfg.openFirewall {
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,7 +52,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
proxyWebsockets = true;
|
proxyWebsockets = true;
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
@ -61,7 +61,7 @@ in
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mySystem.services.homepage.media = mkIf cfg.addToHomepage [
|
mySystem.services.homepage.home = mkIf cfg.addToHomepage [
|
||||||
{
|
{
|
||||||
${app} = {
|
${app} = {
|
||||||
icon = "${app}.svg";
|
icon = "${app}.svg";
|
||||||
|
|
|
@ -300,7 +300,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ let
|
||||||
port = 8080; #int
|
port = 8080; #int
|
||||||
appFolder = "/var/lib/${app}";
|
appFolder = "/var/lib/${app}";
|
||||||
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||||
host = "${app}" + (if cfg.development then "-dev" else "");
|
host = "${app}" + (if cfg.dev then "-dev" else "");
|
||||||
url = "${host}.${config.networking.domain}";
|
url = "${host}.${config.networking.domain}";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
@ -41,7 +41,7 @@ in
|
||||||
description = "Add to DNS list";
|
description = "Add to DNS list";
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
development = mkOption
|
dev = mkOption
|
||||||
{
|
{
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
description = "Development instance";
|
description = "Development instance";
|
||||||
|
@ -83,11 +83,6 @@ in
|
||||||
## container
|
## container
|
||||||
virtualisation.oci-containers.containers = config.lib.mySystem.mkContainer {
|
virtualisation.oci-containers.containers = config.lib.mySystem.mkContainer {
|
||||||
inherit app image user group;
|
inherit app image user group;
|
||||||
env = {
|
|
||||||
test = "derp";
|
|
||||||
};
|
|
||||||
envFiles = [ ];
|
|
||||||
volumes = [ ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# homepage integration
|
# homepage integration
|
||||||
|
|
|
@ -43,7 +43,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ in
|
||||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
useACMEHost = config.networking.domain;
|
useACMEHost = config.networking.domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://${app}:${builtins.toString port}";
|
proxyPass = "http://${app}:${builtins.toString port}";
|
||||||
extraConfig = "resolver 10.88.0.1;";
|
extraConfig = "resolver 10.88.0.1;";
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,11 @@ with lib;
|
||||||
user = "${options.user}:${options.group}";
|
user = "${options.user}:${options.group}";
|
||||||
environment = {
|
environment = {
|
||||||
TZ = config.time.timeZone;
|
TZ = config.time.timeZone;
|
||||||
} // options.env;
|
} // lib.attrsets.attrByPath [ "env" ] { } options;
|
||||||
environmentFiles = lib.attrsets.attrByPath [ "envFiles" ] [ ] options;
|
environmentFiles = lib.attrsets.attrByPath [ "envFiles" ] [ ] options;
|
||||||
volumes = [ "/etc/localtime:/etc/localtime:ro" ]
|
volumes = [ "/etc/localtime:/etc/localtime:ro" ]
|
||||||
++ lib.attrsets.attrByPath [ "volumes" ] [ ] options;
|
++ lib.attrsets.attrByPath [ "volumes" ] [ ] options;
|
||||||
|
ports = lib.attrsets.attrByPath [ "ports" ] [ ] options;
|
||||||
extraOptions = containerExtraOptions;
|
extraOptions = containerExtraOptions;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
138
nixos/modules/nixos/services/calibre-web/default.nix
Normal file
138
nixos/modules/nixos/services/calibre-web/default.nix
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
{ lib
|
||||||
|
, config
|
||||||
|
, pkgs
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.mySystem.${category}.${app};
|
||||||
|
app = "calibre-web";
|
||||||
|
category = "services";
|
||||||
|
description = "Calibre web-server";
|
||||||
|
# image = "%{image}";
|
||||||
|
inherit (config.services.calibre-web) user;#string
|
||||||
|
inherit (config.services.calibre-web) group;#string
|
||||||
|
port = 8083; #int
|
||||||
|
appFolder = "/var/lib/${app}";
|
||||||
|
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||||
|
host = "${app}" + (if cfg.dev then "-dev" else "");
|
||||||
|
url = "${host}.${config.networking.domain}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.mySystem.${category}.${app} =
|
||||||
|
{
|
||||||
|
enable = mkEnableOption "${app}";
|
||||||
|
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
|
||||||
|
monitor = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable gatus monitoring";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
prometheus = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable prometheus scraping";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
addToDNS = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Add to DNS list";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
dev = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Development instance";
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
backup = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable backups";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
## Secrets
|
||||||
|
# sops.secrets."${category}/${app}/env" = {
|
||||||
|
# sopsFile = ./secrets.sops.yaml;
|
||||||
|
# owner = user;
|
||||||
|
# group = group;
|
||||||
|
# restartUnits = [ "${app}.service" ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
users.users.truxnell.extraGroups = [ group ];
|
||||||
|
|
||||||
|
|
||||||
|
# Folder perms - only for containers
|
||||||
|
# systemd.tmpfiles.rules = [
|
||||||
|
# "d ${persistentFolder}/ 0750 ${user} ${group} -"
|
||||||
|
# ];
|
||||||
|
|
||||||
|
## service
|
||||||
|
services.calibre-web = {
|
||||||
|
enable = true;
|
||||||
|
listen.port = port;
|
||||||
|
options = {
|
||||||
|
calibreLibrary = "${config.mySystem.nasFolder}/natflix/books/";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# homepage integration
|
||||||
|
mySystem.services.homepage.infrastructure = mkIf cfg.addToHomepage [
|
||||||
|
{
|
||||||
|
${app} = {
|
||||||
|
icon = "${app}.svg";
|
||||||
|
href = "https://${url}";
|
||||||
|
inherit description;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
### gatus integration
|
||||||
|
mySystem.services.gatus.monitors = mkIf cfg.monitor [
|
||||||
|
{
|
||||||
|
name = app;
|
||||||
|
group = "${category}";
|
||||||
|
url = "https://${url}";
|
||||||
|
interval = "1m";
|
||||||
|
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
### Ingress
|
||||||
|
services.nginx.virtualHosts.${url} = {
|
||||||
|
forceSSL = true;
|
||||||
|
useACMEHost = config.networking.domain;
|
||||||
|
locations."^~ /" = {
|
||||||
|
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
### firewall config
|
||||||
|
|
||||||
|
# networking.firewall = mkIf cfg.openFirewall {
|
||||||
|
# allowedTCPPorts = [ port ];
|
||||||
|
# allowedUDPPorts = [ port ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
### backups
|
||||||
|
warnings = [
|
||||||
|
(mkIf (!cfg.backup && config.mySystem.purpose != "Development")
|
||||||
|
"WARNING: Backups for ${app} are disabled!")
|
||||||
|
];
|
||||||
|
|
||||||
|
services.restic.backups = mkIf cfg.backup (config.lib.mySystem.mkRestic
|
||||||
|
{
|
||||||
|
inherit app user;
|
||||||
|
paths = [ appFolder ];
|
||||||
|
inherit appFolder;
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -25,5 +25,7 @@
|
||||||
./radicale
|
./radicale
|
||||||
./node-red
|
./node-red
|
||||||
./nginx
|
./nginx
|
||||||
|
./miniflux
|
||||||
|
./calibre-web
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ let
|
||||||
port = 2342; #int
|
port = 2342; #int
|
||||||
appFolder = "/var/lib/${app}";
|
appFolder = "/var/lib/${app}";
|
||||||
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||||
host = "${app}" + (if cfg.development then "-dev" else "");
|
host = "${app}" + (if cfg.dev then "-dev" else "");
|
||||||
url = "${host}.${config.networking.domain}";
|
url = "${host}.${config.networking.domain}";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
@ -40,7 +40,7 @@ in
|
||||||
description = "Add to DNS list";
|
description = "Add to DNS list";
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
development = mkOption
|
dev = mkOption
|
||||||
{
|
{
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
description = "Development instance";
|
description = "Development instance";
|
||||||
|
|
|
@ -12,13 +12,13 @@ let
|
||||||
image = "%{image}";
|
image = "%{image}";
|
||||||
user = "%{user kah}"; #string
|
user = "%{user kah}"; #string
|
||||||
group = "%{group kah}"; #string
|
group = "%{group kah}"; #string
|
||||||
port = %{ port }; #int
|
port = 1234; #int
|
||||||
appFolder = "/var/lib/${app}";
|
appFolder = "/var/lib/${app}";
|
||||||
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||||
host="${app}" ++ mkIf cfg.development "-dev";
|
host = "${app}" + (if cfg.dev then "-dev" else "");
|
||||||
url = "${host}.${config.networking.domain}";
|
url = "${host}.${config.networking.domain}";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.mySystem.${category}.${app} =
|
options.mySystem.${category}.${app} =
|
||||||
{
|
{
|
||||||
enable = mkEnableOption "${app}";
|
enable = mkEnableOption "${app}";
|
||||||
|
@ -41,26 +41,21 @@ let
|
||||||
description = "Add to DNS list";
|
description = "Add to DNS list";
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
development = mkOption
|
dev = mkOption
|
||||||
{
|
{
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
description = "Development instance";
|
description = "Development instance";
|
||||||
default = false;
|
default = false;
|
||||||
};
|
};
|
||||||
backupLocal = mkOption
|
backup = mkOption
|
||||||
{
|
{
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
description = "Enable local backups";
|
description = "Enable backups";
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
backupRemote = mkOption
|
|
||||||
{
|
|
||||||
type = lib.types.bool;
|
|
||||||
description = "Enable remote backups";
|
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
@ -92,7 +87,7 @@ let
|
||||||
${app} = {
|
${app} = {
|
||||||
icon = "${app}.svg";
|
icon = "${app}.svg";
|
||||||
href = "https://${url}";
|
href = "https://${url}";
|
||||||
description = description;
|
inherit description;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -110,8 +105,8 @@ let
|
||||||
|
|
||||||
### Ingress
|
### Ingress
|
||||||
services.nginx.virtualHosts.${url} = {
|
services.nginx.virtualHosts.${url} = {
|
||||||
useACMEHost = host;
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
|
useACMEHost = config.networking.domain;
|
||||||
locations."^~ /" = {
|
locations."^~ /" = {
|
||||||
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
||||||
};
|
};
|
||||||
|
@ -126,21 +121,23 @@ let
|
||||||
|
|
||||||
### backups
|
### backups
|
||||||
warnings = [
|
warnings = [
|
||||||
(mkIf (!cfg.backupLocal && config.mySystem.purpose != "Development")
|
(mkIf (!cfg.backup && config.mySystem.purpose != "Development")
|
||||||
"WARNING: Local backups for ${app} are disabled!")
|
"WARNING: Backups for ${app} are disabled!")
|
||||||
(mkIf (!cfg.backupRemote && config.mySystem.purpose != "Development")
|
|
||||||
"WARNING: Remote backups for ${app} are disabled!")
|
|
||||||
];
|
];
|
||||||
|
|
||||||
services.restic.backups = mkIf cfg.backups config.lib.mySystem.mkRestic
|
services.restic.backups = mkIf cfg.backup (config.lib.mySystem.mkRestic
|
||||||
{
|
{
|
||||||
inherit app user;
|
inherit app user;
|
||||||
paths = [ appFolder ];
|
paths = [ appFolder ];
|
||||||
inherit appFolder;
|
inherit appFolder;
|
||||||
local=cfg.backupLocal;
|
});
|
||||||
remote=cfg.backupRemote;
|
|
||||||
};
|
|
||||||
|
# services.postgresqlBackup = {
|
||||||
|
# databases = [ app ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
180
nixos/modules/nixos/services/miniflux/default.nix
Normal file
180
nixos/modules/nixos/services/miniflux/default.nix
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
{ lib
|
||||||
|
, config
|
||||||
|
, pkgs
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.mySystem.${category}.${app};
|
||||||
|
app = "miniflux";
|
||||||
|
category = "services";
|
||||||
|
description = "Minimalist feed reader";
|
||||||
|
# image = "%{image}";
|
||||||
|
user = app; #string
|
||||||
|
group = app; #string
|
||||||
|
port = 8072; #int
|
||||||
|
appFolder = "/var/lib/${app}";
|
||||||
|
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||||
|
host = "${app}" + (if cfg.dev then "-dev" else "");
|
||||||
|
url = "${host}.${config.networking.domain}";
|
||||||
|
databaseUrl = "user=miniflux host=/run/postgresql dbname=miniflux";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.mySystem.${category}.${app} =
|
||||||
|
{
|
||||||
|
enable = mkEnableOption "${app}";
|
||||||
|
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
|
||||||
|
monitor = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable gatus monitoring";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
prometheus = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable prometheus scraping";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
addToDNS = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Add to DNS list";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
dev = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Development instance";
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
backup = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable backups";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
## Secrets
|
||||||
|
sops.secrets."${category}/${app}/env" = {
|
||||||
|
sopsFile = ./secrets.sops.yaml;
|
||||||
|
owner = user;
|
||||||
|
inherit group;
|
||||||
|
restartUnits = [ "${app}.service" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.truxnell.extraGroups = [ group ];
|
||||||
|
users.users.miniflux = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "miniflux";
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.miniflux = { };
|
||||||
|
|
||||||
|
environment.persistence."${config.mySystem.system.impermanence.persistPath}" = lib.mkIf config.mySystem.system.impermanence.enable {
|
||||||
|
directories = [{ directory = appFolder; inherit user; inherit group; mode = "750"; }];
|
||||||
|
};
|
||||||
|
|
||||||
|
## service
|
||||||
|
services.miniflux = {
|
||||||
|
enable = true;
|
||||||
|
adminCredentialsFile = config.sops.secrets."${category}/${app}/env".path;
|
||||||
|
config = {
|
||||||
|
LISTEN_ADDR = "localhost:${builtins.toString port}";
|
||||||
|
DATABASE_URL = databaseUrl;
|
||||||
|
RUN_MIGRATIONS = "1";
|
||||||
|
CREATE_ADMIN = "1";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# automatically reset feed errors regular
|
||||||
|
# systemd.services.miniflux-reset-feed-errors = {
|
||||||
|
# description = "Miniflux reset feed errors";
|
||||||
|
# wantedBy = [ "multi-user.target" ];
|
||||||
|
# after = [ "network.target" "${app}.service" ];
|
||||||
|
# environment.DATABASE_URL = databaseUrl;
|
||||||
|
# startAt = "00/4:00"; # Every four hours.
|
||||||
|
# serviceConfig = {
|
||||||
|
# Type = "oneshot";
|
||||||
|
# DynamicUser = true;
|
||||||
|
# RuntimeDirectory = "miniflux"; # Creates /run/miniflux.
|
||||||
|
## EnvironmentFile = cfg.envFilePath;
|
||||||
|
# ExecStart = pkgs.writeShellScriptBin "miniflux-reset-feed-errors" ''
|
||||||
|
# ${cfg.package}/bin/miniflux -reset-feed-errors
|
||||||
|
# '';
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
# homepage integration
|
||||||
|
mySystem.services.homepage.infrastructure = mkIf cfg.addToHomepage [
|
||||||
|
{
|
||||||
|
${app} = {
|
||||||
|
icon = "${app}.svg";
|
||||||
|
href = "https://${url}";
|
||||||
|
inherit description;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
# ensure postgresql setup
|
||||||
|
|
||||||
|
services.postgresql = {
|
||||||
|
ensureDatabases = [ app ];
|
||||||
|
ensureUsers = [{
|
||||||
|
name = app;
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
|
||||||
|
### gatus integration
|
||||||
|
mySystem.services.gatus.monitors = mkIf cfg.monitor [
|
||||||
|
{
|
||||||
|
name = app;
|
||||||
|
group = "${category}";
|
||||||
|
url = "https://${url}";
|
||||||
|
interval = "1m";
|
||||||
|
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
### Ingress
|
||||||
|
services.nginx.virtualHosts.${url} = {
|
||||||
|
forceSSL = true;
|
||||||
|
useACMEHost = config.networking.domain;
|
||||||
|
locations."^~ /" = {
|
||||||
|
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
### firewall config
|
||||||
|
|
||||||
|
# networking.firewall = mkIf cfg.openFirewall {
|
||||||
|
# allowedTCPPorts = [ port ];
|
||||||
|
# allowedUDPPorts = [ port ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
### backups
|
||||||
|
warnings = [
|
||||||
|
(mkIf (!cfg.backup && config.mySystem.purpose != "Development")
|
||||||
|
"WARNING: Backups for ${app} are disabled!")
|
||||||
|
];
|
||||||
|
|
||||||
|
# services.restic.backups = mkIf cfg.backup (config.lib.mySystem.mkRestic
|
||||||
|
# {
|
||||||
|
# inherit app user;
|
||||||
|
# paths = [ appFolder ];
|
||||||
|
# inherit appFolder;
|
||||||
|
# });
|
||||||
|
|
||||||
|
services.postgresqlBackup = mkIf cfg.backup {
|
||||||
|
databases = [ app ];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
77
nixos/modules/nixos/services/miniflux/secrets.sops.yaml
Normal file
77
nixos/modules/nixos/services/miniflux/secrets.sops.yaml
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
services:
|
||||||
|
miniflux:
|
||||||
|
env: ENC[AES256_GCM,data:ZJeYF8xK2WhiIINfpnSQvqhKMywyI7sln/SMe7TN9RhPtO2bninS3+Fa50qWvEDlg3c=,iv:2B1LG2t3VbjSNLIIQrcvF9FtT+9ca+2+5Ox7hUsehFA=,tag:ydHlhoMqJkCVy+MYqblpUQ==,type:str]
|
||||||
|
sops:
|
||||||
|
kms: []
|
||||||
|
gcp_kms: []
|
||||||
|
azure_kv: []
|
||||||
|
hc_vault: []
|
||||||
|
age:
|
||||||
|
- recipient: age1lj5vmr02qkudvv2xedfj5tq8x93gllgpr6tzylwdlt7lud4tfv5qfqsd5u
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSNGIxTVpnYVJhaUNsOWtW
|
||||||
|
RUMrbzJkUWZvYkZPcUU5c2ZLNkFHeU9PSm44CnFHTFB4dlBzOVFUQldxNzlxRkNG
|
||||||
|
MkFncUQ3QlVpYmgrUHBkYk1nZm5hTEEKLS0tICtMeWx6bnAxMDBmWVhsakdNcUNP
|
||||||
|
MXdTTTJia2Jyb2hTMExtOEdJMkZJN2cKO8qhHDYVpSg3KhrGizcErDIg6ejYyBNE
|
||||||
|
V6w7jKHl5aaNLTaP4nBt7jMM3DQzc1pnFJBCPwj8uYQcG9Bd5+j7yw==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age17edew3aahg3t5nte5g0a505sn96vnj8g8gqse8q06ccrrn2n3uysyshu2c
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWR2JzQWFFQ29uL0FvZGNT
|
||||||
|
dU9pMklGaVRnWlRpZ3pKM3ZZTTVQQkxZUHhrCkxBTzMrR09zcW04WDlPRjZVbjNI
|
||||||
|
TVVxWVRaS2pKaGtmdVc4WUE5SEI2MXcKLS0tIE9ZcjQzM1prSm1yRXFVNWxZeWVv
|
||||||
|
a0x2cDhiUDlBZ2ZZVGZRbytBUEJqN2sK/+tVAbPLLBil/sHSBj0tKacvsEHGbXto
|
||||||
|
V1InpgnmZG3vmrFJM/i2ApjwpBC1diNzrd25A7jQZyriUw6CZdKZlw==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1u4tht685sqg6dkmjyer96r93pl425u6353md6fphpd84jh3jwcusvm7mgk
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJZEhscHdsWk5nek1BUEhJ
|
||||||
|
OWI1ekNZNEYvVXhrN0Y2U1FYRThZUlhsWVdNCnFERkNqTUkwY1FzRDRZS3ljWXpm
|
||||||
|
VFM1ejVjZVRkVnZyTlM5eldKMm15bkEKLS0tIHlvbXA0ZFU4R2FUSXlKU3A0S1lH
|
||||||
|
N0ExUFFxd3lFK3pvQzRJS1FzUy80ZE0KlCXPhxh5DHsL+QueUYpyfsr9/bjYoO+J
|
||||||
|
bNo45Dm0WruG+KUGYpk3+lK5ASAnSsEfL+q7NkyBVLT/ag+DSvL9IA==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1cp6vegrmqfkuj8nmt2u3z0sur7n0f7e9x9zmdv4zygp8j2pnucpsdkgagc
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1T2duOFNQQlRKMGhLZDA2
|
||||||
|
dG0zek9DelIveDZ3ZUNIWWx3M2hmZEdva2dFClRndEkzVXpRU1REbXY4ZEJhSElO
|
||||||
|
Z1RXdkZ3UGxrcjNXbExCYml4cEpCSjgKLS0tIGlObjkyT1JZV3VYYitqbk5NNkdC
|
||||||
|
dEI0azRtU0lCT25GSTRtaldNdzJzQVUKlkmuvYVDI9qkQpVhHMtJTOGSYXDQQoeo
|
||||||
|
/zUI1mrmplCoWhipSMmxg7pxEorK8VUxhX7iBg5360xRBbXWqhGh3w==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1ekt5xz7u2xgdzgsrffhd9x22n80cn4thxd8zxjy2ey5vq3ca7gnqz25g5r
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjQzc2OEQxOGp6Yk01eWE4
|
||||||
|
ZjVlYjhMMzQrdG5UdmdENEMrVVMvTnhURTJvCkZ5T2JmeXc3eTBKYy9EbGYzM0s5
|
||||||
|
cmlRc3dvYWMzeUtxMEt1QjBtVXVtSTQKLS0tIFJtQjIwbUxyWjl6MTlRUEluNlVu
|
||||||
|
RGlHc1Jobnl5bkxaSnhHWWlScjIxbWsKxSnmobPuqg4aQcEGw2LcaBtpAMb1mkUX
|
||||||
|
rj/UniXbYnZkIibIj/qaWpFuUbo1iCavl8cWzTrm/cjLSVjoIVYGAQ==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1jpeh4s553taxkyxhzlshzqjfrtvmmp5lw0hmpgn3mdnmgzku332qe082dl
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnYVVrL0RIdkV4bmpjN2ZN
|
||||||
|
SlZaRllGcU1KanY5ZnhZcFNMelRmSEQvSUI0CmFqRUNQMXRlcjNPOUg0UmUzdlVp
|
||||||
|
ZThjMFlnZ3pXdkJNZEZrbk1zUGJHOUUKLS0tIHFOdzhUT1VRdlFzZEplcU4zaHdR
|
||||||
|
R01xaEt1bkgvNElXUlY3WWx5RUF4Sm8KX9E/YojwOmaulW2j80jR3zGH0WmWzXZq
|
||||||
|
5TBWE0M4+cQPoEpA48deAV1y+oKQovFjSR08ytvZxFCK7RbKkz6h4g==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1j2r8mypw44uvqhfs53424h6fu2rkr5m7asl7rl3zn3xzva9m3dcqpa97gw
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyVk9ZMGFmK1FUeG53N2lZ
|
||||||
|
V25BdDMvT01TSjZ1MEx6NEVaU2dESnRRb0RFCklHZ05KYUNtVFV0QmFGTDJDejEv
|
||||||
|
VjNlU293MjQ5ZDhLYUVmRTg3c3FwWTgKLS0tIEx0dDdZY3czekl1b1FaQWp0d092
|
||||||
|
V1JHaFgxUHNCWjNteWNpckVSNGdLQW8KAYTC47LvPauQiDjylAegfl5zAdJMtzZV
|
||||||
|
BP1aNMPDIidKKiK3wonpslnNkT83sHDpdDf+IpvnBuWL9oj36fY+yA==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
lastmodified: "2024-05-05T01:01:40Z"
|
||||||
|
mac: ENC[AES256_GCM,data:bazV7Inpog/BX/rPAQEbDqpZuOtCVQUzTXjPpnwHrAbWobYYV9QeBCOhRxXQj8jU37lsnN9vNxNeAtJMQbLQu1KVYt6qs9tFVm/kGNeaAQooXQqaUXCHnQoVNuJbZmKjkiWgpepWfkoKyP4NAuBUG8jT1DMYIp6QvuzjxRwyiI8=,iv:Nu38xj+oYkEruqZ/PvKQ6/7aHYzOxQ6gv1jPU39fEOg=,tag:+doKpf6O7iUyBnIZaV2PMQ==,type:str]
|
||||||
|
pgp: []
|
||||||
|
unencrypted_suffix: _unencrypted
|
||||||
|
version: 3.8.1
|
|
@ -8,7 +8,17 @@ let
|
||||||
cfg = config.mySystem.nfs.nas;
|
cfg = config.mySystem.nfs.nas;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.mySystem.nfs.nas.enable = mkEnableOption "Mount NAS";
|
options.mySystem.nfs.nas = {
|
||||||
|
enable = mkEnableOption "Mount NAS";
|
||||||
|
lazy = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable lazymount";
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
config = mkIf cfg.enable
|
config = mkIf cfg.enable
|
||||||
{
|
{
|
||||||
|
@ -17,7 +27,7 @@ in
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [ nfs-utils ];
|
environment.systemPackages = with pkgs; [ nfs-utils ];
|
||||||
|
|
||||||
systemd.mounts = [{
|
systemd.mounts = lib.mkIf cfg.lazy [{
|
||||||
type = "nfs";
|
type = "nfs";
|
||||||
mountConfig = {
|
mountConfig = {
|
||||||
Options = "noatime";
|
Options = "noatime";
|
||||||
|
@ -26,7 +36,7 @@ in
|
||||||
where = "/mnt/nas";
|
where = "/mnt/nas";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
systemd.automounts = [{
|
systemd.automounts = lib.mkIf cfg.lazy [{
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
automountConfig = {
|
automountConfig = {
|
||||||
TimeoutIdleSec = "600";
|
TimeoutIdleSec = "600";
|
||||||
|
@ -34,5 +44,10 @@ in
|
||||||
where = "/mnt/nas";
|
where = "/mnt/nas";
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
fileSystems."${config.mySystem.nasFolder}" = lib.mkIf (!cfg.lazy) {
|
||||||
|
device = "daedalus.${config.mySystem.internalDomain}:/tank";
|
||||||
|
fsType = "nfs";
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ in
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://127.0.0.1:${builtins.toString config.services.node-red.port}";
|
proxyPass = "http://127.0.0.1:${builtins.toString config.services.node-red.port}";
|
||||||
|
proxyWebsockets = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ in
|
||||||
directories = [{ directory = appFolder; inherit user; inherit group; mode = "750"; }];
|
directories = [{ directory = appFolder; inherit user; inherit group; mode = "750"; }];
|
||||||
};
|
};
|
||||||
|
|
||||||
mySystem.services.homepage.media = mkIf cfg.addToHomepage [
|
mySystem.services.homepage.home = mkIf cfg.addToHomepage [
|
||||||
{
|
{
|
||||||
${app} = {
|
${app} = {
|
||||||
icon = "${app}.svg";
|
icon = "${app}.svg";
|
||||||
|
|
|
@ -38,9 +38,9 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
mySystem.services.homepage.media = mkIf cfg.addToHomepage [
|
mySystem.services.homepage.infrastructure = mkIf cfg.addToHomepage [
|
||||||
{
|
{
|
||||||
code-shodan = {
|
"code-${config.networking.hostName}" = {
|
||||||
icon = "vscode.svg";
|
icon = "vscode.svg";
|
||||||
href = "https://${url}";
|
href = "https://${url}";
|
||||||
|
|
||||||
|
|
|
@ -5,26 +5,84 @@
|
||||||
}:
|
}:
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.mySystem.services.postgresql;
|
cfg = config.mySystem.${category}.${app};
|
||||||
|
app = "postgresql";
|
||||||
|
category = "services";
|
||||||
|
description = "Postgres RDMS";
|
||||||
|
# user = "%{user kah}"; #string
|
||||||
|
# group = "%{group kah}"; #string
|
||||||
|
# port = 1234; #int
|
||||||
|
appFolder = "/var/lib/${app}";
|
||||||
|
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||||
|
# host = "${app}" + (if cfg.dev then "-dev" else "");
|
||||||
|
# url = "${host}.${config.networking.domain}";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.mySystem.services.postgresql.enable = mkEnableOption "postgresql";
|
options.mySystem.${category}.${app} =
|
||||||
|
{
|
||||||
|
enable = mkEnableOption "${app}";
|
||||||
|
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
|
||||||
|
prometheus = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable prometheus scraping";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
backup = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable backups";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
## Secrets
|
||||||
|
# sops.secrets."${category}/${app}/env" = {
|
||||||
|
# sopsFile = ./secrets.sops.yaml;
|
||||||
|
# owner = user;
|
||||||
|
# group = group;
|
||||||
|
# restartUnits = [ "${app}.service" ];
|
||||||
|
# };
|
||||||
|
|
||||||
services.postgresql = {
|
services.postgresql = {
|
||||||
enable = true;
|
enable = true;
|
||||||
authentication = ''
|
|
||||||
local homeassistant homeassistant ident map=ha
|
|
||||||
'';
|
|
||||||
identMap = ''
|
identMap = ''
|
||||||
ha root homeassistant
|
# ArbitraryMapName systemUser DBUser
|
||||||
|
superuser_map root postgres
|
||||||
|
superuser_map postgres postgres
|
||||||
|
# Let other names login as themselves
|
||||||
|
superuser_map /^(.*)$ \1
|
||||||
'';
|
'';
|
||||||
ensureDatabases = [ "homeassistant" ];
|
authentication = ''
|
||||||
ensureUsers = [
|
#type database DBuser auth-method optional_ident_map
|
||||||
{ name = "homeassistant"; ensureDBOwnership = true; }
|
local sameuser all peer map=superuser_map
|
||||||
];
|
'';
|
||||||
|
settings = {
|
||||||
|
max_connections = 200;
|
||||||
|
random_page_cost = 1.1;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# enable backups
|
||||||
|
services.postgresqlBackup = mkIf cfg.backup {
|
||||||
|
enable = lib.mkForce true;
|
||||||
|
location = "${config.mySystem.nasFolder}/backup/nixos/postgresql";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### firewall config
|
||||||
|
|
||||||
|
# networking.firewall = mkIf cfg.openFirewall {
|
||||||
|
# allowedTCPPorts = [ port ];
|
||||||
|
# allowedUDPPorts = [ port ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ let
|
||||||
port = 9001; #int
|
port = 9001; #int
|
||||||
appFolder = "/var/lib/${app}";
|
appFolder = "/var/lib/${app}";
|
||||||
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||||
host = "${app}" + (if cfg.development then "-dev" else "");
|
host = "${app}" + (if cfg.dev then "-dev" else "");
|
||||||
url = "${host}.${config.networking.domain}";
|
url = "${host}.${config.networking.domain}";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ in
|
||||||
description = "Add to DNS list";
|
description = "Add to DNS list";
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
development = mkOption
|
dev = mkOption
|
||||||
{
|
{
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
description = "Development instance";
|
description = "Development instance";
|
||||||
|
|
|
@ -15,7 +15,7 @@ let
|
||||||
port = 5232; #int
|
port = 5232; #int
|
||||||
appFolder = "/var/lib/${app}";
|
appFolder = "/var/lib/${app}";
|
||||||
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||||
host = "${app}" + (if cfg.development then "-dev" else "");
|
host = "${app}" + (if cfg.dev then "-dev" else "");
|
||||||
url = "${host}.${config.networking.domain}";
|
url = "${host}.${config.networking.domain}";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
@ -41,7 +41,7 @@ in
|
||||||
description = "Add to DNS list";
|
description = "Add to DNS list";
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
development = mkOption
|
dev = mkOption
|
||||||
{
|
{
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
description = "Development instance";
|
description = "Development instance";
|
||||||
|
|
143
nixos/modules/nixos/services/rss-bridge/default.nix
Normal file
143
nixos/modules/nixos/services/rss-bridge/default.nix
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
{ lib
|
||||||
|
, config
|
||||||
|
, pkgs
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.mySystem.${category}.${app};
|
||||||
|
app = "rss-bridge";
|
||||||
|
category = "services";
|
||||||
|
description = "rss feed for sites without";
|
||||||
|
# image = "%{image}";
|
||||||
|
inherit (services.rss-bridge) user;#string
|
||||||
|
inherit (services.rss-bridge) group;#string
|
||||||
|
port = 1234; #int
|
||||||
|
appFolder = "/var/lib/${app}";
|
||||||
|
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||||
|
host = "${app}" + (if cfg.dev then "-dev" else "");
|
||||||
|
url = "${host}.${config.networking.domain}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.mySystem.${category}.${app} =
|
||||||
|
{
|
||||||
|
enable = mkEnableOption "${app}";
|
||||||
|
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
|
||||||
|
monitor = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable gatus monitoring";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
prometheus = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable prometheus scraping";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
addToDNS = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Add to DNS list";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
dev = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Development instance";
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
backup = mkOption
|
||||||
|
{
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable backups";
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
## Secrets
|
||||||
|
# sops.secrets."${category}/${app}/env" = {
|
||||||
|
# sopsFile = ./secrets.sops.yaml;
|
||||||
|
# owner = user;
|
||||||
|
# group = group;
|
||||||
|
# restartUnits = [ "${app}.service" ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
users.users.truxnell.extraGroups = [ group ];
|
||||||
|
|
||||||
|
|
||||||
|
# Folder perms - only for containers
|
||||||
|
# systemd.tmpfiles.rules = [
|
||||||
|
# "d ${persistentFolder}/ 0750 ${user} ${group} -"
|
||||||
|
# ];
|
||||||
|
|
||||||
|
## service
|
||||||
|
# services.test= {
|
||||||
|
# enable = true;
|
||||||
|
# };
|
||||||
|
|
||||||
|
# homepage integration
|
||||||
|
mySystem.services.homepage.infrastructure = mkIf cfg.addToHomepage [
|
||||||
|
{
|
||||||
|
${app} = {
|
||||||
|
icon = "${app}.svg";
|
||||||
|
href = "https://${url}";
|
||||||
|
inherit description;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
### gatus integration
|
||||||
|
mySystem.services.gatus.monitors = mkIf cfg.monitor [
|
||||||
|
{
|
||||||
|
name = app;
|
||||||
|
group = "${category}";
|
||||||
|
url = "https://${url}";
|
||||||
|
interval = "1m";
|
||||||
|
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
### Ingress
|
||||||
|
services.nginx.virtualHosts.${url} = {
|
||||||
|
forceSSL = true;
|
||||||
|
useACMEHost = config.networking.domain;
|
||||||
|
locations."^~ /" = {
|
||||||
|
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
### firewall config
|
||||||
|
|
||||||
|
# networking.firewall = mkIf cfg.openFirewall {
|
||||||
|
# allowedTCPPorts = [ port ];
|
||||||
|
# allowedUDPPorts = [ port ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
### backups
|
||||||
|
warnings = [
|
||||||
|
(mkIf (!cfg.backup && config.mySystem.purpose != "Development")
|
||||||
|
"WARNING: Backups for ${app} are disabled!")
|
||||||
|
];
|
||||||
|
|
||||||
|
services.restic.backups = config.lib.mySystem.mkRestic
|
||||||
|
{
|
||||||
|
inherit app user;
|
||||||
|
paths = [ appFolder ];
|
||||||
|
inherit appFolder;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
# services.postgresqlBackup = {
|
||||||
|
# databases = [ app ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -16,7 +16,10 @@ with config;
|
||||||
# TODO decide if i drop to bash on pis?
|
# TODO decide if i drop to bash on pis?
|
||||||
shell.fish.enable = true;
|
shell.fish.enable = true;
|
||||||
|
|
||||||
nfs.nas.enable = true;
|
nfs.nas = {
|
||||||
|
enable = true;
|
||||||
|
lazy = true;
|
||||||
|
};
|
||||||
system.resticBackup.local.enable = false;
|
system.resticBackup.local.enable = false;
|
||||||
system.resticBackup.remote.enable = false;
|
system.resticBackup.remote.enable = false;
|
||||||
|
|
||||||
|
|
Reference in a new issue