{ flakeSelf, config, ... }: let hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; in { networking.nat = { enable = true; internalInterfaces = ["ve-+"]; externalInterface = "eno1"; }; age.secrets.mongodb-uri = { file = hostSecrets + "mongodb-uri.age"; }; containers.school = { autoStart = true; privateNetwork = true; ephemeral = true; hostAddress = "192.168.100.10"; localAddress = "192.168.100.11"; specialArgs = { showsApi = flakeSelf.inputs.shows-api; }; bindMounts = { secret = { mountPoint = "/mongodb.env"; isReadOnly = true; hostPath = config.age.secrets.mongodb-uri.path; }; }; config = { config, pkgs, lib, showsApi, ... }: { environment.systemPackages = [pkgs.htop]; users.users.shows = { name = "shows"; group = "shows"; isSystemUser = true; }; users.groups.shows = {}; systemd.services = let commonServiceConfig = { Type = "simple"; Restart = "on-failure"; RestartSec = 3; # Hardening CapabilityBoundingSet = ""; NoNewPrivileges = true; PrivateUsers = true; PrivateTmp = true; PrivateDevices = true; PrivateMounts = true; ProtectClock = true; ProtectControlGroups = true; ProtectHome = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; RestrictNamespaces = true; RestrictRealtime = true; RestrictSUIDSGID = true; }; in { shows-api = { description = "NestJS API to store info about shows on a MongoDB database"; after = ["network.target"]; wantedBy = ["multi-user.target"]; serviceConfig = commonServiceConfig // { ExecStart = lib.getExe showsApi.packages.x86_64-linux.default; StateDirectory = ["shows-api"]; RuntimeDirectory = ["shows-api"]; User = "shows"; Group = "shows"; EnvironmentFile = "/mongodb.env"; }; }; }; networking = { firewall.allowedTCPPorts = [3000]; # Use systemd-resolved inside the container # Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686 useHostResolvConf = lib.mkForce false; }; services.resolved.enable = true; system.stateVersion = "24.11"; }; }; services = { headscale.settings.dns.extra_records = [ { name = "shows.everest.tailscale"; type = "A"; value = "100.100.0.1"; } ]; caddy.virtualHosts.shows= { hostName = "shows.everest.tailscale"; extraConfig = '' import tailscale handle { respond "Ionic app goes here" } redir /admin /admin/ handle_path /admin/* { respond "Angular admin panel goes here" } redir /api /api/ handle_path /api/* { reverse_proxy ${config.containers.school.localAddress}:3000 } ''; }; }; }