Files
nix-config/systems/x86_64-linux/jallen-nas/services.nix
2026-03-23 14:07:48 -05:00

187 lines
5.9 KiB
Nix
Executable File

{
lib,
pkgs,
...
}:
let
nasData = "/media/nas/main";
in
{
systemd.network.wait-online.enable = false;
# Force tailscaled to use nftables (Critical for clean nftables-only systems)
# This avoids the "iptables-compat" translation layer issues.
systemd.services.tailscaled.serviceConfig.Environment = [
"TS_DEBUG_FIREWALL_MODE=nftables"
];
networking.nftables.enable = true;
boot.initrd.systemd.network.wait-online.enable = false;
# Services configs
services = {
tailscale = {
enable = true;
openFirewall = true;
useRoutingFeatures = "server";
extraUpFlags = [
"--advertise-exit-node"
"--accept-dns=false"
"--advertise-routes=10.0.1.0/24"
"--hostname=jallen-nas"
];
extraSetFlags = [
"--advertise-exit-node"
"--hostname=jallen-nas"
"--webclient"
];
# authKeyFile = "/media/nas/main/nix-app-data/tailscale/auth";
};
postgresql = {
enable = true;
package = pkgs.postgresql_16;
enableTCPIP = true;
dataDir = "${nasData}/databases/postgresql";
ensureDatabases = [
"authentik"
"homeassistant"
"nextcloud"
"onlyoffice"
"synapse"
"sparkyfitness"
];
ensureUsers = [
{
name = "authentik";
ensureDBOwnership = true;
}
{
name = "homeassistant";
ensureDBOwnership = true;
}
{
name = "nextcloud";
ensureDBOwnership = true;
}
{
name = "onlyoffice";
ensureDBOwnership = true;
}
{
name = "synapse";
ensureDBOwnership = true;
}
{
name = "sparkyfitness";
ensureDBOwnership = true;
}
];
# pg_hba.conf — use lib.mkForce to replace the module defaults entirely.
#
# Connection matrix:
# postgres (admin) — Unix socket, peer (OS user postgres = DB user postgres)
# authentik — Unix socket, peer (OS user authentik = DB user authentik)
# nextcloud — Unix socket, peer (OS user nextcloud = DB user nextcloud)
# onlyoffice — Unix socket, peer (OS user onlyoffice = DB user onlyoffice) [disabled]
# synapse — Unix socket, peer via identMap (OS user matrix-synapse → DB user synapse)
# homeassistant — TCP from nuc-nixos (10.0.1.4), scram-sha-256
# sparkyfitness — TCP from Podman bridge (10.88.0.0/16), scram-sha-256
authentication = lib.mkForce ''
# TYPE DATABASE USER ADDRESS METHOD
# All local Unix socket connections use peer auth (with identMap for mismatched names)
local all all peer map=system
# homeassistant runs on nuc-nixos (10.0.1.4), not on this machine.
# trust is acceptable here: access is locked to a single known host IP on the LAN.
# TODO: set a password via ensureClauses and switch to scram-sha-256.
host homeassistant homeassistant 10.0.1.4/32 trust
# Podman container network sparkyfitness server connects via host LAN IP
host sparkyfitness sparkyfitness 10.88.0.0/16 scram-sha-256
'';
# identMap — maps OS usernames to PostgreSQL usernames for peer auth.
# The catch-all regex rule allows any OS user whose name matches their DB user
# directly (authentik, nextcloud, onlyoffice, postgres).
# Explicit entries cover mismatched names.
identMap = lib.mkForce ''
# MAPNAME OS-USERNAME DB-USERNAME
system matrix-synapse synapse
system /^(.*)$ \1
'';
# TODO: set sparkyfitness password declaratively via ensureUsers.*.ensureClauses.password
# once the SCRAM-SHA-256 hash is stored in SOPS (jallen-nas/sparky-fitness/db-password).
# The old initialScript has been removed — it only ran on first DB init and is now stale.
};
mysql = {
enable = true;
package = pkgs.mariadb; # explicit MariaDB package
dataDir = "${nasData}/databases/mariadb";
settings.mysqld = {
bind-address = "0.0.0.0";
port = 3306;
};
initialDatabases = [
{
name = "booklore";
}
];
ensureUsers = [
{
name = "booklore";
ensurePermissions = {
"database.*" = "ALL PRIVILEGES";
"*.*" = "SELECT, LOCK TABLES";
};
}
];
};
redis = {
servers = {
authentik = {
enable = true;
port = 6379;
};
ccache = {
enable = true;
port = 6363;
bind = "0.0.0.0";
openFirewall = true;
extraParams = [ "--protected-mode no" ];
};
manyfold = {
enable = true;
port = 6380;
};
onlyoffice = {
enable = true;
port = 6381;
};
};
};
};
# Pre-create extensions and grant superuser-owned objects that the sparkyfitness
# role cannot manage itself. Appended to postgresql-setup.service which already
# runs as the postgres superuser after the DB is confirmed ready.
#
# 1. pg_stat_statements requires superuser to CREATE EXTENSION.
# 2. The extension installs functions owned by the postgres superuser; the
# sparkyfitness role cannot GRANT EXECUTE on objects it doesn't own, so we
# pre-grant them here before the app's grantPermissions() runs.
systemd.services.postgresql-setup.script = lib.mkAfter ''
psql -d sparkyfitness -c "
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO sparkyfitness;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA pg_catalog TO sparkyfitness;
"
'';
}