{ 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 = { 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" ]; 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/"; }; }; }; gitea = { enable = true; stateDir = "/tank/forgejo"; package = pkgs.forgejo; 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" "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.users = { 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; }; system.stateVersion = "23.05"; }