Upgraded snowfall lib

This commit is contained in:
Alejandro Angulo 2023-10-04 20:36:21 -07:00
parent 7e87dbc55b
commit a1709f033f
Signed by: alejandro-angulo
GPG key ID: 75579581C74554B6
58 changed files with 22 additions and 19 deletions

View file

@ -0,0 +1,82 @@
{
options,
config,
lib,
pkgs,
format,
...
}:
with lib; let
cfg = config.aa.services.adguardhome;
in {
options.aa.services.adguardhome = with types; {
enable = mkEnableOption "adguardhome";
acmeCertName = mkOption {
type = str;
default = "";
description = ''
If set to a non-empty string, forces SSL with the supplied acme
certificate.
'';
};
};
config = mkIf cfg.enable {
services.adguardhome = {
enable = true;
mutableSettings = true;
settings = {
bind_host = "0.0.0.0";
bind_port = 3000;
};
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts."adguardhome.kilonull.com" =
{
locations."/" = {
proxyPass = "http://127.0.0.1:3000";
};
}
// lib.optionalAttrs (cfg.acmeCertName != "") {
forceSSL = true;
useACMEHost = cfg.acmeCertName;
};
};
networking.firewall = {
# TODO: Remove this here and leave it up to systems to decide to enable
# the firewall
enable = true;
allowedTCPPorts = [
# Plain DNS
53
# DHCP
68
# HTTP
80
# HTTPS
443
# DNS over TLS
853
# DNSCrypt
5443
];
allowedUDPPorts = [
# Plain DNS
53
# DHCP
67
68
# DNS over QUIC
784
853
8853
# DNSCrypt
5443
];
};
};
}

View file

@ -0,0 +1,74 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.services.grafana;
server_settings = config.services.grafana.settings.server;
in {
options.aa.services.grafana = with types; {
enable = mkEnableOption "grafana";
acmeCertName = mkOption {
type = str;
default = "";
description = ''
If set to a non-empty string, forces SSL with the supplied acme
certificate.
'';
};
};
config = mkIf cfg.enable {
services.grafana = {
enable = true;
settings.server = {
domain = "grafana.kilonull.com";
http_port = 2342;
http_addr = "0.0.0.0";
};
provision = {
enable = true;
datasources = {
# This assumes prometheus, loki, and grafana are all running on the
# same host.
settings.datasources = [
{
name = "Prometheus";
type = "prometheus";
access = "proxy";
url = "http://127.0.0.1:${toString config.services.prometheus.port}";
}
{
name = "Loki";
type = "loki";
access = "proxy";
url = "http://127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}";
}
];
};
};
};
services.nginx = {
enable = true;
virtualHosts ."${server_settings.domain}" =
{
locations."/" = {
proxyPass = "http://${server_settings.http_addr}:${toString server_settings.http_port}";
proxyWebsockets = true;
};
}
// lib.optionalAttrs (cfg.acmeCertName != "") {
forceSSL = true;
useACMEHost = cfg.acmeCertName;
};
};
networking.firewall = {
allowedTCPPorts = [80 443];
};
};
}

View file

@ -0,0 +1,102 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.services.loki;
loki = config.services.loki;
in {
options.aa.services.loki = with types; {
enable = mkEnableOption "loki";
};
config = mkIf cfg.enable {
services.loki = {
enable = true;
configuration = {
server.http_listen_port = 3030;
auth_enabled = false;
ingester = {
lifecycler = {
address = "127.0.0.1";
ring = {
kvstore = {
store = "inmemory";
};
replication_factor = 1;
};
};
# Any chunk not receiving new logs in this time will be flushed
chunk_idle_period = "1h";
# All chunks will be flushed when they hit this age
max_chunk_age = "1h";
# Loki will attempt to build chunks up to this size, flushing first
# if chunk_idle_period or max_chunk_age is reached first
chunk_target_size = 999999;
chunk_retain_period = "30s";
max_transfer_retries = 0;
};
schema_config = {
configs = [
{
from = "2022-06-06";
store = "boltdb-shipper";
object_store = "filesystem";
schema = "v11";
index = {
prefix = "index_";
period = "24h";
};
}
];
};
storage_config = {
boltdb_shipper = {
active_index_directory = "/var/lib/loki/boltdb-shipper-active";
cache_location = "/var/lib/loki/boltdb-shipper-cache";
cache_ttl = "24h";
shared_store = "filesystem";
};
filesystem = {
directory = "/var/lib/loki/chunks";
};
};
limits_config = {
reject_old_samples = true;
reject_old_samples_max_age = "168h";
};
chunk_store_config = {
max_look_back_period = "0s";
};
table_manager = {
retention_deletes_enabled = false;
retention_period = "0s";
};
compactor = {
working_directory = "/var/lib/loki";
shared_store = "filesystem";
compactor_ring = {
kvstore = {
store = "inmemory";
};
};
};
};
};
networking.firewall = {
allowedTCPPorts = [loki.configuration.server.http_listen_port];
};
};
}

View file

@ -0,0 +1,65 @@
{
options,
config,
lib,
pkgs,
format,
...
}:
with lib; let
cfg = config.aa.services.nextcloud;
in {
options.aa.services.nextcloud = with types; {
enable = mkEnableOption "nextcloud";
acmeCertName = mkOption {
type = str;
default = "";
description = ''
If set to a non-empty string, forces SSL with the supplied acme
certificate.
'';
};
};
config = mkIf cfg.enable {
age.secrets.nextcloud_admin = {
file = ../../../secrets/nextcloud_admin.age;
owner = "nextcloud";
group = "nextcloud";
};
services.nextcloud = {
enable = true;
package = pkgs.nextcloud27;
hostName = "nextcloud.kilonull.com";
https = true;
database.createLocally = true;
datadir = "/tank/nextcloud";
# Arbitrary large size
maxUploadSize = "16G";
configureRedis = true;
logType = "file";
poolSettings = {
pm = "dynamic";
"pm.max_children" = "64";
"pm.max_requests" = "500";
"pm.max_spare_servers" = "25";
"pm.min_spare_servers" = "10";
"pm.start_servers" = "15";
};
config = {
dbtype = "pgsql";
adminuser = "alejandro";
adminpassFile = config.age.secrets.nextcloud_admin.path;
};
};
# nextcloud module configures nginx, just need to specify SSL stuffs here
services.nginx.virtualHosts.${config.services.nextcloud.hostName} = mkIf (cfg.acmeCertName != "") {
forceSSL = true;
useACMEHost = cfg.acmeCertName;
};
networking.firewall.allowedTCPPorts = [80 443];
};
}

View file

@ -0,0 +1,70 @@
{
options,
config,
lib,
pkgs,
format,
...
}:
with lib; let
cfg = config.aa.services.nix-serve;
in {
options.aa.services.nix-serve = with types; {
enable = mkEnableOption "nix-serve";
domain_name = mkOption {
type = str;
description = "The domain to use.";
};
subdomain_name = mkOption {
type = str;
description = "The subdomain to use.";
};
acmeCertName = mkOption {
type = str;
default = "";
description = ''
If set to a non-empty string, forces SSL with the supplied acme
certificate.
'';
};
};
config = mkIf cfg.enable {
nix.settings = {
allowed-users = ["nix-serve"];
trusted-users = ["nix-serve"];
};
environment.systemPackages = [pkgs.nix-serve];
services = {
nix-serve = {
enable = true;
# TODO: Document this or automate the inital creation.
secretKeyFile = "/var/gospelCache";
};
nginx = {
enable = true;
virtualHosts."${cfg.subdomain_name}.${cfg.domain_name}" =
{
serverAliases = ["${cfg.subdomain_name}"];
locations."/".extraConfig = ''
proxy_pass http://localhost:${toString config.services.nix-serve.port};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
'';
}
// lib.optionalAttrs (cfg.acmeCertName != "") {
forceSSL = true;
useACMEHost = cfg.acmeCertName;
};
};
};
networking.firewall = {
allowedTCPPorts = [80 443];
};
};
}

View file

@ -0,0 +1,47 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.services.octoprint;
in {
options.aa.services.octoprint = with types; {
enable = mkEnableOption "octoprint";
acmeCertName = mkOption {
type = str;
default = "";
description = ''
If set to a non-empty string, foces SSL with the supplied acme
certificate.
'';
};
};
config = mkIf cfg.enable {
services.octoprint.enable = true;
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts."octoprint.kilonull.com" =
{
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.octoprint.port}";
proxyWebsockets = true;
extraConfig = ''
client_max_body_size 32m;
'';
};
}
// lib.optionalAttrs (cfg.acmeCertName != "") {
forceSSL = true;
useACMEHost = cfg.acmeCertName;
};
};
networking.firewall.allowedTCPPorts = [80 443];
};
}

View file

@ -0,0 +1,43 @@
{
options,
config,
lib,
pkgs,
format,
...
}:
with lib; let
cfg = config.aa.services.openssh;
user = config.users.users.${config.aa.user.name};
user-id = builtins.toString user.uid;
default-key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEmPdQcM0KCQ3YunF1gwN+B+i1Q8KrIfiUvNtgFQjTy2";
in {
options.aa.services.openssh = with types; {
enable = mkEnableOption "ssh";
authorizedKeys = mkOption {
type = listOf str;
default = [default-key];
description = "The public keys to authorize";
};
};
config = mkIf cfg.enable {
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
PermitRootLogin = mkDefault (
if format == "install-iso"
then "yes"
else "no"
);
};
};
aa.user.extraOptions = {
openssh.authorizedKeys.keys = cfg.authorizedKeys;
};
};
}

View file

@ -0,0 +1,23 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.apps.steam;
in {
options.aa.services.printing = with types; {
enable = mkEnableOption "printing";
};
config = mkIf cfg.enable {
# Setup printing over the network
services.printing.enable = true;
services.avahi = {
enable = true;
nssmdns = true;
};
};
}

View file

@ -0,0 +1,59 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.services.prometheus;
exporters = config.services.prometheus.exporters;
in {
options.aa.services.prometheus = with types; {
enable = mkEnableOption "prometheus";
enableServer = mkOption {
type = bool;
default = false;
description = "Whether or not to enable the prometheus server";
};
enableNodeExporter = mkOption {
type = bool;
default = true;
description = "Whether or not to enable the node exporter";
};
};
config = mkIf cfg.enable {
services.prometheus = {
enable = cfg.enableServer;
exporters = {
node = {
enable = cfg.enableNodeExporter;
enabledCollectors = ["systemd"];
port = 9002;
openFirewall = true;
};
};
scrapeConfigs = mkIf cfg.enableServer [
{
job_name = "node";
static_configs = [
{
# TODO: How to automatically generate this whenever an exporter
# is configured
targets = [
"node:${toString exporters.node.port}"
"gospel:${toString exporters.node.port}"
"pi4:${toString exporters.node.port}"
];
}
];
}
];
};
networking.firewall = mkIf cfg.enableServer {
allowedTCPPorts = [config.services.prometheus.port];
};
};
}

View file

@ -0,0 +1,58 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.services.promtail;
loki = config.services.loki;
in {
options.aa.services.promtail = with types; {
enable = mkEnableOption "promtail";
};
config = mkIf cfg.enable {
services.promtail = {
enable = true;
configuration = {
server = {
http_listen_port = 28183;
grpc_listen_port = 0;
};
positions = {
filename = "/tmp/positions.yaml";
};
clients = [
{
# TODO: Don't hardcode this?
url = "http://node:3030/loki/api/v1/push";
}
];
scrape_configs = [
{
job_name = "journal";
journal = {
max_age = "12h";
labels = {
job = "systemd-journal";
host = config.networking.hostName;
};
};
relabel_configs = [
{
source_labels = ["__journal__systemd_unit"];
target_label = "unit";
}
];
}
];
};
};
# networking.firewall = {
# allowedTCPPorts = [80 443];
# };
};
}

View file

@ -0,0 +1,90 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.services.syncoid;
in {
options.aa.services.syncoid = with types; {
enable = mkEnableOption "syncoid (ZFS snap replication)";
commands = mkOption {
type = attrs;
default = {};
description = "Commands to pass directly to syncoid, see `services.syncoid.commands`";
};
remoteTargetUser = mkOption {
type = str;
default = "";
description = "The user to use on the target machine.";
};
remoteTargetDatasets = mkOption {
type = listOf str;
default = [];
description = "Datasets to be used as a remote target (e.g. a NAS's backups dataset)";
};
remoteTargetPublicKeys = mkOption {
type = listOf str;
default = [];
description = "SSH public keys that the syncoid service's user should trust";
};
};
config = mkIf cfg.enable {
services.syncoid = {
enable = true;
localSourceAllow =
options.services.syncoid.localSourceAllow.default
++ [
"mount"
];
localTargetAllow =
options.services.syncoid.localTargetAllow.default
++ [
"destroy"
];
commands = mkAliasDefinitions options.aa.services.syncoid.commands;
};
environment.systemPackages = mkIf (cfg.remoteTargetUser != "") (with pkgs; [
lzop
mbuffer
]);
users = mkIf (cfg.remoteTargetUser != "") {
users."${cfg.remoteTargetUser}" = {
shell = pkgs.bashInteractive;
group = cfg.remoteTargetUser;
isSystemUser = true;
home = "/var/lib/${cfg.remoteTargetUser}";
createHome = true;
openssh.authorizedKeys.keys = cfg.remoteTargetPublicKeys;
};
groups."${cfg.remoteTargetUser}" = {};
};
systemd.services.setup-syncoid-remote = {
description = "Permission setup for syncoid remote targets";
documentation = ["https://github.com/jimsalterjrs/sanoid/wiki/Syncoid#running-without-root"];
wantedBy = ["multi-user.target"];
path = [pkgs.zfs];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = "yes";
};
script = ''
DATASETS=(${toString cfg.remoteTargetDatasets})
for dataset in "''${DATASETS[@]}"; do
zfs allow \
-u ${cfg.remoteTargetUser} \
compression,mountpoint,create,mount,receive,rollback,destroy \
"$dataset"
done
'';
};
};
}

View file

@ -0,0 +1,50 @@
{
options,
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.aa.services.tailscale;
in {
options.aa.services.tailscale = with types; {
enable = mkEnableOption "tailscale";
configureClientRouting = mkOption {
type = bool;
default = false;
description = mdDoc ''
Configures tailscale as a client.
See `options.services.tailscale.useRoutingFeatures` for more information.
'';
};
configureServerRouting = mkOption {
type = bool;
default = false;
description = mdDoc ''
Configures tailscale as a server.
See `options.services.tailscale.useRoutingFeatures` for more information.
'';
};
};
config = mkIf cfg.enable {
environment.systemPackages = [pkgs.tailscale];
networking.firewall.allowedUDPPorts = [config.services.tailscale.port];
services.tailscale = {
enable = true;
useRoutingFeatures = mkIf (cfg.configureClientRouting || cfg.configureServerRouting) (
if (cfg.configureClientRouting && cfg.configureServerRouting)
then "both"
else
(
if cfg.configureClientRouting
then "client"
else "server"
)
);
};
};
}