infra/nix/nas/configuration.nix

562 lines
15 KiB
Nix

{
config,
pkgs,
...
}: {
imports = [
# Include the results of the hardware scan.
./hardware.nix
];
age.secrets.action-token = {
file = ../../secrets/vancouver-action-runner.age;
owner = "gitea-runner";
};
age.secrets.restic-b2-credentials = {
file = ../../secrets/vancouver-restic-b2.age;
group = "users";
mode = "770";
};
age.secrets.restic-password = {
file = ../../secrets/vancouver-restic-password.age;
group = "users";
mode = "770";
};
age.secrets.healthcheck-ping = {
file = ../../secrets/healthchecks-ping.sh.age;
group = "users";
mode = "770";
};
age.secrets.cloudflare-dns = {
file = ../../secrets/cloudflare-dns.age;
owner = "acme";
};
nix = {
settings = {
auto-optimise-store = true;
experimental-features = ["nix-command" "flakes"];
};
};
boot = {
tmp.cleanOnBoot = true;
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
supportedFilesystems = ["zfs" "ntfs"];
kernelModules = ["coretemp" "kvm-amd" "it87"];
zfs.extraPools = ["tank"];
};
services = {
paperless = {
enable = true;
dataDir = "/tank/documents";
settings = {
PAPERLESS_OCR_USER_ARGS = {
invalidate_digital_signatures = true;
};
};
};
fwupd.enable = true;
promtail = {
enable = true;
configuration = {
server = {
http_listen_port = 3031;
grpc_listen_port = 0;
};
positions = {
filename = "/tmp/positions.yaml";
};
clients = [
{
url = "http://monitoring:3030/loki/api/v1/push";
}
];
scrape_configs = [
{
job_name = "journal";
journal = {
max_age = "12h";
labels = {
job = "systemd-journal";
host = "vancouver";
};
};
relabel_configs = [
{
source_labels = ["__journal__systemd_unit"];
target_label = "unit";
}
];
}
];
};
};
restic = {
backups = {
"gsimmer" = {
user = "gsimmer";
environmentFile = config.age.secrets.restic-b2-credentials.path;
repository = "s3:s3.us-west-000.backblazeb2.com/gsimmer-backup";
paths = [
"/tank/gsimmer/projects"
"/tank/gsimmer/org"
"/tank/gsimmer/Backup/Pictures"
"/tank/gsimmer/Photos"
"/tank/shared"
];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
RandomizedDelaySec = "6h";
};
pruneOpts = [
"--keep-daily 7"
"--keep-weekly 5"
"--keep-monthly 12"
"--keep-yearly 5"
];
passwordFile = config.age.secrets.restic-password.path;
backupPrepareCommand = ''
${pkgs.curl}/bin/curl -fsS -m 10 --retry 5 -o /dev/null $(${pkgs.coreutils}/bin/cat ${config.age.secrets.healthcheck-ping.path})/gsimmer-backup/start
'';
backupCleanupCommand = ''
output="$(journalctl --unit restic-backups-gsimmer.service --since=today --boot --no-pager | ${pkgs.coreutils}/bin/tail --bytes 100000)"
${pkgs.curl}/bin/curl -fsS -m 10 --retry 5 -o /dev/null "$(${pkgs.coreutils}/bin/cat ${config.age.secrets.healthcheck-ping.path})/gsimmer-backup/$?" --data-raw "$output"
'';
};
"becki" = {
user = "becki";
environmentFile = config.age.secrets.restic-b2-credentials.path;
repository = "s3:s3.us-west-000.backblazeb2.com/bsimmer-backup";
paths = [
"/tank/becki/VRChat\ Avatars"
"/tank/becki/Pictures"
];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
RandomizedDelaySec = "6h";
};
pruneOpts = [
"--keep-daily 7"
"--keep-weekly 5"
"--keep-monthly 12"
"--keep-yearly 5"
];
passwordFile = config.age.secrets.restic-password.path;
initialize = true;
backupPrepareCommand = ''
${pkgs.curl}/bin/curl -fsS -m 10 --retry 5 -o /dev/null $(${pkgs.coreutils}/bin/cat ${config.age.secrets.healthcheck-ping.path})/becki-backup/start
'';
backupCleanupCommand = ''
output="$(journalctl --unit restic-backups-becki.service --since=today --boot --no-pager | ${pkgs.coreutils}/bin/tail --bytes 100000)"
${pkgs.curl}/bin/curl -fsS -m 10 --retry 5 -o /dev/null "$(${pkgs.coreutils}/bin/cat ${config.age.secrets.healthcheck-ping.path})/becki-backup/$?" --data-raw "$output"
'';
};
"apps" = {
user = "root";
environmentFile = config.age.secrets.restic-b2-credentials.path;
repository = "s3:s3.us-west-000.backblazeb2.com/gsimmer-app-backup";
paths = [
"/tank/k3scluster"
"/tank/forgejo"
"/tank/documents"
];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
RandomizedDelaySec = "12h";
};
pruneOpts = [
"--keep-daily 7"
"--keep-weekly 5"
"--keep-monthly 12"
"--keep-yearly 5"
];
backupPrepareCommand = ''
${pkgs.curl}/bin/curl -fsS -m 10 --retry 5 -o /dev/null $(${pkgs.coreutils}/bin/cat ${config.age.secrets.healthcheck-ping.path})/apps-backup/start
'';
backupCleanupCommand = ''
output="$(journalctl --unit restic-backups-apps.service --since=today --boot --no-pager | ${pkgs.coreutils}/bin/tail --bytes 100000)"
${pkgs.curl}/bin/curl -fsS -m 10 --retry 5 -o /dev/null "$(${pkgs.coreutils}/bin/cat ${config.age.secrets.healthcheck-ping.path})/apps-backup/$?" --data-raw "$output"
'';
passwordFile = config.age.secrets.restic-password.path;
initialize = true;
};
};
};
syncthing = {
enable = true;
overrideDevices = false;
overrideFolders = false;
user = "gsimmer";
dataDir = "/tank/gsimmer";
guiAddress = "100.116.48.47:8384";
};
prometheus.exporters = {
blackbox = {
enable = true;
configFile = "/var/lib/blackbox/config.yml";
};
node = {
enable = true;
listenAddress = "100.116.48.47";
enabledCollectors = [
"systemd"
"zfs"
"processes"
];
};
};
pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
};
zfs.autoScrub.enable = true;
tailscale.enable = true;
openssh.enable = true;
xserver.videoDrivers = ["nvidia"];
nfs.server.enable = true;
samba-wsdd.enable = true;
samba = {
enable = true;
securityType = "user";
openFirewall = true;
extraConfig = ''
workgroup = WORKGROUP
server string = smbnix
netbios name = smbnix
security = user
#use sendfile = yes
#max protocol = smb2
# note: localhost is the ipv6 localhost ::1
hosts allow = 100. 192.168.50. 127.0.0.1 localhost
hosts deny = 0.0.0.0/0
guest account = nobody
map to guest = bad user
'';
shares = {
streamboxes = {
path = "/tank/streamboxes";
browseable = "yes";
"read only" = "no";
"guest ok" = "yes";
"create mask" = "0644";
"directory mask" = "0755";
};
media = {
path = "/tank/media";
browseable = "yes";
"read only" = "no";
"guest ok" = "yes";
"create mask" = "0644";
"directory mask" = "0755";
};
becki = {
path = "/tank/becki";
browseable = "yes";
"read only" = "no";
"guest ok" = "no";
"create mask" = "0644";
"directory mask" = "0755";
"admin users" = "becki";
};
shared = {
path = "/tank/shared";
browseable = "yes";
"read only" = "no";
"guest ok" = "no";
"create mask" = "0644";
"directory mask" = "0755";
};
gabriel = {
path = "/tank/gsimmer";
browseable = "yes";
"read only" = "no";
"guest ok" = "no";
"create mask" = "0644";
"directory mask" = "0755";
"admin users" = "gsimmer";
};
};
};
plex = {
enable = true;
openFirewall = true;
};
nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedBrotliSettings = true;
recommendedZstdSettings = true;
recommendedOptimisation = true;
recommendedTlsSettings = true;
virtualHosts."git.gmem.ca" = {
enableACME = true;
addSSL = true;
acmeRoot = null;
locations."/" = {
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 500M;
'';
proxyPass = "http://127.0.0.1:8973/";
};
};
virtualHosts."docs.gmem.ca" = {
enableACME = true;
addSSL = true;
acmeRoot = null;
locations."/" = {
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 500M;
'';
proxyPass = "http://127.0.0.1:${toString config.services.paperless.port}/";
};
};
};
forgejo = {
enable = true;
stateDir = "/tank/forgejo";
user = "git";
group = "git";
settings = {
DEFAULT = {
APP_NAME = "Arch's Git Forge";
};
server = {
ROOT_URL = "https://git.gmem.ca/";
HTTP_ADDR = "127.0.0.1";
HTTP_PORT = 8973;
};
service = {
DISABLE_REGISTRATION = true;
COOKIE_SECURE = true;
};
actions = {
ENABLED = true;
};
federation = {
ENABLED = true;
};
metrics = {
ENABLED = true;
};
"repository.signing" = {
SIGNING_KEY = "default";
INITIAL_COMMIT = "always";
WIKI = "always";
CRUD_ACTIONS = "always";
MERGES = "always";
};
indexer = {
REPO_INDEXER_ENABLED = true;
};
};
};
gitea-actions-runner = {
package = pkgs.forgejo-actions-runner;
instances = {
vancouver = {
name = "vancouver";
enable = true;
labels = [
"debian-latest:docker://node:18-bullseye"
"ubuntu-latest:docker://node:18-bullseye"
"docker:docker://gitea/act_runner:nightly-dind-rootless"
"nix:docker://nixos/nix"
];
url = "https://git.gmem.ca/";
tokenFile = config.age.secrets.action-token.path;
settings = {
cache.port = 4328;
container.network = "podman3";
};
};
};
};
sanoid = {
enable = true;
datasets = {
"tank/becki" = {
autoprune = true;
autosnap = true;
daily = 4;
monthly = 3;
yearly = 1;
};
"tank/gsimmer" = {
autoprune = true;
autosnap = true;
daily = 4;
monthly = 3;
yearly = 1;
};
"tank/shared" = {
autoprune = true;
autosnap = true;
daily = 2;
monthly = 2;
};
"tank/k3scluster" = {
autoprune = true;
autosnap = true;
daily = 2;
monthly = 2;
};
"tank/forgejo" = {
autoprune = true;
autosnap = true;
daily = 2;
monthly = 2;
};
};
};
};
networking = {
hostId = "e1e29bf4";
hostName = "vancouver";
domain = "gmem.ca";
firewall = {
trustedInterfaces = ["tailscale0"];
checkReversePath = "loose";
enable = true;
allowedTCPPorts = [22 80 443 9798 2049 4328];
allowedUDPPorts = [41641];
};
nftables.enable = true;
};
environment.systemPackages = with pkgs; [
vim
wget
git
htop
tailscale
home-manager
lm_sensors
screen
nix-output-monitor
cifs-utils
cloudflared
bat
gnupg
pinentry
];
time.timeZone = "Europe/London";
nixpkgs.config.allowUnfree = true;
hardware = {
opengl.enable = true;
nvidia.modesetting.enable = true;
pulseaudio.enable = false;
};
programs = {
zsh.enable = true;
fish.enable = true;
};
environment.shells = with pkgs; [zsh fish];
users = {
groups.git = {};
users = {
git = {
home = "/tank/forgejo";
useDefaultShell = true;
group = "git";
isSystemUser = true;
};
gsimmer = {
shell = pkgs.fish;
isNormalUser = true;
home = "/tank/gsimmer";
extraGroups = ["wheel" "libvirtd" "qemu-libvirtd"];
openssh.authorizedKeys.keys = let
authorizedKeys = pkgs.fetchurl {
url = "https://gmem.ca/ssh";
hash = "sha256-7PpFDgWVfp26c9PuW+2s3O8MBAODtHr4q7WU/l3BoG4=";
};
in
pkgs.lib.splitString "\n" (builtins.readFile
authorizedKeys);
};
becki = {
shell = pkgs.fish;
isNormalUser = true;
home = "/tank/becki";
};
root.openssh.authorizedKeys.keys = let
authorizedKeys = pkgs.fetchurl {
url = "https://gmem.ca/ssh";
hash = "sha256-7PpFDgWVfp26c9PuW+2s3O8MBAODtHr4q7WU/l3BoG4=";
};
in
pkgs.lib.splitString "\n" (builtins.readFile
authorizedKeys);
};
};
home-manager.users.gsimmer = {pkgs, ...}: {
programs.git = {
userName = "Gabriel Simmer";
userEmail = "git@gmem.ca";
};
programs.bash.enable = false;
home.stateVersion = "23.05";
};
virtualisation = {
docker = {
enable = true;
rootless = {
enable = true;
setSocketVariable = true;
};
};
};
virtualisation.oci-containers.containers = {
speedtest = {
image = "ghcr.io/miguelndecarvalho/speedtest-exporter";
ports = ["9798:9798"];
};
};
sound.enable = true;
security.rtkit.enable = true;
security.acme.acceptTerms = true;
security.acme.defaults.email = "acme@gmem.ca";
security.acme.certs."git.gmem.ca" = {
domain = "*.gmem.ca";
dnsProvider = "cloudflare";
credentialsFile = config.age.secrets.cloudflare-dns.path;
};
security.acme.certs."docs.gmem.ca" = {
domain = "*.gmem.ca";
dnsProvider = "cloudflare";
credentialsFile = config.age.secrets.cloudflare-dns.path;
};
system.stateVersion = "23.05";
}