# Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page, on # https://search.nixos.org/options and in the NixOS manual (`nixos-help`). { config, lib, pkgs, ... }: { imports = [ # Include the results of the hardware scan. ./hardware/samsehu.nix ]; # Use the `systemd-boot` boot loader boot.loader.systemd-boot.enable = true; # Added following instructions of openzfs configuration # randomly generated with `head -c4 /dev/urandom | od -A none -t x4` networking.hostId = "3e52e44f"; boot.supportedFilesystems = [ "zfs" ]; boot.zfs.forceImportRoot = false; networking.hostName = "samsehu"; # Define your hostname. # Pick only one of the below networking options. networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. # Set your time zone. time.timeZone = "America/Denver"; # Select internationalisation properties. i18n.defaultLocale = "en_US.UTF-8"; # console = { # font = "Lat2-Terminus16"; # keyMap = "us"; # useXkbConfig = true; # use xkb.options in tty. # }; # Enable CUPS to print documents. services.printing.enable = true; # Enable sound. sound.enable = true; hardware.pulseaudio.enable = true; # Define a user account. Don't forget to set a password with ‘passwd’. users.users.geemili = { isNormalUser = true; extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. packages = with pkgs; [ ]; }; users.users.desttinghim = { isNormalUser = true; extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. packages = with pkgs; [ ]; }; # List packages installed in system profile. To search, run: # $ nix search wget environment.systemPackages = with pkgs; [ helix wget git juanfont-headscale.headscale # install to allow debugging/control of headscale using the CLI pkgs.glauth ]; environment.variables = { EDITOR = "hx"; VISUAL = "hx"; }; # List services that you want to enable: # Enable the OpenSSH daemon. services.openssh = { enable = true; settings.PasswordAuthentication = false; settings.KbdInteractiveAuthentication = false; settings.PermitRootLogin = "no"; }; services.cockpit = { enable = true; openFirewall = true; settings = { WebService = { Origins = "https://cockpit.samsehu.perli.casa wss://cockpit.samsehu.perli.casa"; ProtocolHeader = "X-Forwarded-Proto"; LoginTo = false; }; }; }; services.udisks2.enable = true; services.jellyfin.enable = true; services.aria2 = { enable = true; downloadDir = "/zroot/downloads/"; # extraArguments = "--rpc-listen-all"; # rpcListenPort = 6800; # 6800 is the default # rpcSecret = "aria2rpc"; }; services.kavita = { enable = true; tokenKeyFile = "/var/kavita-token-key"; # Uh, typo in the service definition ipAdresses = [ "127.0.0.1" "::1" ]; }; services.glauth = { enable = true; settings = { debug = false; ldap = { enabled = true; listen = "127.0.0.1:3893"; tls = false; }; ldaps.enabled = false; backends = [ { datastore = "config"; baseDN = "dc=twins,dc=pearson"; nameFormat = "uid"; groupFormat = "ou"; } # TODO: package glauth sqlite plugin # { # datastore = "plugin"; # plugin = "sqlite.so"; # pluginhandler = "NewSqliteHandler"; # database = "/run/glauth/glauth.db"; # } ]; api = { enabled = true; tls = false; listen = "127.0.0.1:5555"; }; users = [ { name = "forgejo_search"; mail = "forgejo_search@tsamsehu.perli.casa"; uidnumber = 993; primarygroup = 5503; passappsha256 = [ "8adb23d6e1bd7db026a5784ff84efcbd57e4d9aea0e0798b78740a3ee335282c" ]; capabilities = [ { action = "search"; object = "ou=forgejo_user,dc=twins,dc=pearson"; } ]; } { name = "jellyfin_search"; mail = "jellyfin_search@samsehu.perli.casa"; uidnumber = 994; primarygroup = 5503; passappsha256 = [ "21fa12ba3e63cd4cb96f4009720d385f4d52461ae3ab70fac8dedaa6b7917ce9" ]; capabilities = [ { action = "search"; object = "ou=jellyfin_user,dc=twins,dc=pearson"; } ]; } { name = "nextcloud_system_user"; mail = "nextcloud@samsehu.perli.casa"; uidnumber = 988; primarygroup = 5503; passappsha256 = [ "0f11783cdf378aa867a2b590e422f8d645fd3d7fab52fb73bac3c62a64d91651" ]; capabilities = [ { action = "search"; object = "ou=nextcloud_user,dc=twins,dc=pearson"; } ]; } { name = "dex"; mail = "dex@samsehu.perli.casa"; uidnumber = 988; primarygroup = 5503; passappsha256 = [ "ab473aa297a6f7c919f116a5bf3af6e11905843df0a526ffe005742335e1c9d3" ]; capabilities = [ { action = "search"; object = "ou=people,dc=samsehu,dc=perli,dc=casa"; } { action = "search"; object = "ou=groups,dc=samsehu,dc=perli,dc=casa"; } ]; } ]; groups = [ { name = "people"; gidnumber = 5501; } { name = "groups"; gidnumber = 5502; } { name = "apps"; gidnumber = 5503; } { name = "forgejo_user"; gidnumber = 5504; } { name = "jellyfin_user"; gidnumber = 5505; } { name = "nextcloud_user"; gidnumber = 5506; } ]; }; }; users.users.dex = { isSystemUser = true; group = "dex"; }; users.groups.dex = {}; services.dex = { enable = true; environmentFile = config.age.secrets.DEX_ENVIRONMENT_FILE.path; settings = { issuer = "https://dex.samsehu.perli.casa"; storage.type = "memory"; web.http = "127.0.0.1:5556"; # services that can get a token from our dex instance staticClients = [ { id = "forgejo"; secret = "forgejo-secret"; name = "Forgejo"; redirectURIs = [ "https://git.samsehu.perli.casa/user/oauth2/dex/callback" ]; } ]; # authentication sources connectors = [ { type = "ldap"; id = "glauth"; name = "glauth LDAP"; config = { host = "127.0.0.1:3893"; insecureNoSSL = true; insecureSkipVerify = true; startTLS = false; bindDN = "cn=dex,ou=apps,dc=samsehu,dc=perli,dc=casa"; bindPW = "$DEX_GLAUTH_BIND_DN_PASSWORD"; userSearch = { baseDN = "ou=people,dc=samsehu,dc=perli,dc=casa"; username = "cn"; idAttr = "uid"; emailAttr = "mail"; }; groupSearch = { baseDN = "ou=groups,dc=samsehu,dc=perli,dc=casa"; userMatchers = [ { userAttr = "cn"; groupAttr = "uniqueMember"; } ]; nameAttr = "ou"; }; }; } ]; }; }; services.blocky = { enable = true; settings = { ports.dns = 53; ports.http = 4000; upstreams = { # Picks 2 random resolvers and returns answer from fastest one. Read docs for more info. strategy = "parallel_best"; groups.default = [ # CloudFlare "https://one.one.one.one/dns-query" # OpenDNS "https://doh.opendns.com/dns-query" # Google "8.8.8.8" "8.8.4.4" "2001:4860:4860::8888" "2001:4860:4860::8844" # Comcast/Our ISP "75.75.75.75" "75.75.76.76" ]; }; bootstrapDns = { upstream = "https://one.one.one.one/dns-query"; ips = [ "1.1.1.1" "1.0.0.1" ]; }; blocking = { blackLists = { ads = ["https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"]; }; clientGroupsBlock = { default = [ "ads" ]; }; }; customDNS = { rewrite = { "cockpit.samsehu.perli.casa" = "samsehu.perli.casa"; "git.samsehu.perli.casa" = "samsehu.perli.casa"; "nextcloud.samsehu.perli.casa" = "samsehu.perli.casa"; }; mapping = { "samsehu.perli.casa" = "192.168.0.69"; }; }; }; }; services.forgejo = { enable = true; settings = { server.ROOT_URL = "https://git.samsehu.perli.casa/"; server.HTTP_ADDR = "127.0.0.1"; }; }; # lldap LDAP authentication server users.users.lldap = { # allocates the `uid` in the range 100-999, which indicates to software like login managers that it should not be displayed to the user. isSystemUser = true; group = "lldap"; }; users.groups.lldap = {}; services.lldap = { enable = true; settings = { ldap_base_dn = "dc=twins,dc=pearson"; # Sets the root administrator's user name ldap_user_dn = "admin"; http_host = "127.0.0.1"; }; environment = { LLDAP_LDAP_USER_PASS_FILE = config.age.secrets.LLDAP_DEFAULT_ADMIN_PASSWORD.path; }; }; # Dynamic DNS through duck dns users.users.dynamicdns = { # allocates the `uid` in the range 100-999, which indicates to software like login managers that it should not be displayed to the user. isSystemUser = true; group = "dynamicdns"; }; users.groups.dynamicdns = {}; systemd.services.dynamic-dns-updater = { serviceConfig.User = "dynamicdns"; path = [ pkgs.curl ]; script = "curl --silent --url-query domains=samsehuperli --url-query token@${config.age.secrets.samsehu_DUCK_DNS_TOKEN.path} https://www.duckdns.org/update"; startAt = "hourly"; }; systemd.timers.dynamic-dns-updater = { timerConfig.RandomizedDelaySec = "15m"; }; # Next cloud setup services.nginx.enable = false; services.nextcloud = { enable = true; home = "/zroot/nextcloud"; hostName = "nextcloud.samsehu.perli.casa"; config.adminpassFile = "/var/nextcloud-admin-pass"; config.trustedProxies = [ "100.64.0.3" ]; caching.apcu = true; # Auto update apps autoUpdateApps.enable = true; extraApps = { gpoddersync = pkgs.fetchNextcloudApp { appName = "Gpodder Sync"; appVersion = "3.8.2"; sha256 = "sha256-eeBvRZUDVIaym0ngfPD2d7aY3SI/7lPWkrYPnqSh5Kw="; license = "agpl3Plus"; url = "https://github.com/thrillfall/nextcloud-gpodder/releases/download/3.8.2/gpoddersync.tar.gz"; }; }; }; services.phpfpm.pools.nextcloud.settings = { "listen.owner" = config.services.caddy.user; "listen.group" = config.services.caddy.group; }; # Reverse proxy with Caddy services.caddy = { enable = true; globalConfig = '' # servers { # protocols h1 h2 # } email "fresh.car0178@geemili.xyz" ''; virtualHosts."lldap.samsehu.perli.casa".extraConfig = '' bind 100.64.0.3 reverse_proxy localhost:17170 ''; virtualHosts."headscale.samsehu.perli.casa".extraConfig = '' bind 100.64.0.3 192.168.0.69 reverse_proxy localhost:64639 ''; virtualHosts."cockpit.samsehu.perli.casa".extraConfig = '' bind 100.64.0.3 reverse_proxy localhost:9090 ''; virtualHosts."git.samsehu.perli.casa".extraConfig = '' bind 100.64.0.3 192.168.0.69 reverse_proxy localhost:3000 ''; virtualHosts."jellyfin.samsehu.perli.casa".extraConfig = '' bind 100.64.0.3 192.168.0.69 reverse_proxy localhost:8096 ''; virtualHosts."nextcloud.samsehu.perli.casa".extraConfig = '' bind 100.64.0.3 # https://docs.nextcloud.com/server/27/admin_manual/issues/general_troubleshooting.html#service-discovery redir /.well-known/carddav /remote.php/dav 301 redir /.well-known/caldav /remote.php/dav 301 root * ${config.services.nextcloud.package} php_fastcgi unix/${config.services.phpfpm.pools.nextcloud.socket} { root ${config.services.nextcloud.package} capture_stderr } file_server ''; virtualHosts."glauth.samsehu.perli.casa".extraConfig = '' bind 100.64.0.3 reverse_proxy localhost:5555 ''; virtualHosts."dex.samsehu.perli.casa".extraConfig = '' bind 100.64.0.3 reverse_proxy localhost:5556 ''; virtualHosts."kavita.samsehu.perli.casa".extraConfig = '' bind 100.64.0.3 192.168.0.69 reverse_proxy localhost:5000 ''; virtualHosts."aria.samsehu.perli.casa".extraConfig = '' bind 100.64.0.3 root * ${pkgs.ariang}/share/ariang file_server reverse_proxy /jsonrpc localhost:6800 redir / /#!/settings/rpc/set?protocol=https&host=aria.samsehu.perli.casa&port=80&secret=YXJpYTJycGMK ''; }; # Headscale for access to the network while away from home services.headscale = { enable = true; package = pkgs.juanfont-headscale.headscale; settings = { server_url = "https://headscale.samsehu.perli.casa"; listen_addr = "127.0.0.1:64639"; metrics_listen_addr = "127.0.0.1:64640"; tls_cert_path = null; tls_key_path = null; dns_config = { nameservers = [ "100.64.0.3" ]; magic_dns = true; base_domain = "ts.samsehu.perli.casa"; restricted_nameservers = { "samsehu.perli.casa" = [ "100.64.0.3" ]; }; extra_records = [ { name = "samsehu.perli.casa"; type = "A"; value = "100.64.0.3"; } { name = "cockpit.samsehu.perli.casa"; type = "A"; value = "100.64.0.3"; } { name = "git.samsehu.perli.casa"; type = "A"; value = "100.64.0.3"; } { name = "nextcloud.samsehu.perli.casa"; type = "A"; value = "100.64.0.3"; } { name = "glauth.samsehu.perli.casa"; type = "A"; value = "100.64.0.3"; } { name = "dex.samsehu.perli.casa"; type = "A"; value = "100.64.0.3"; } { name = "jellyfin.samsehu.perli.casa"; type = "A"; value = "100.64.0.3"; } { name = "kavita.samsehu.perli.casa"; type = "A"; value = "100.64.0.3"; } { name = "aria.samsehu.perli.casa"; type = "A"; value = "100.64.0.3"; } ]; }; acl_policy_path = pkgs.writeText "acl_policy.hujson" '' { "groups": { "group:servers": [ "samsehu", ], "group:admin": [ "geemili", "desttinghim", ], }, "acls": [ { "action": "accept", "src": ["group:admin"], "dst": ["*:*"], } ], "ssh": [ { "action": "accept", "src": ["group:admin"], "dst": ["group:servers"], "users": ["group:admin", "geemili", "desttinghim", "forgejo"], }, ], } ''; }; }; services.tailscale.enable = true; # Enable automatic upgrades system.autoUpgrade.enable = true; system.autoUpgrade.allowReboot = true; system.autoUpgrade.flake = "git+http://127.0.0.1:3000/Twins/server-configuration.git"; # Enable automatic garbage collection nix.gc = { automatic = true; dates = "weekly"; options = "--delete-older-than 30d"; }; nix.settings.trusted-users = [ "geemili" ]; # Open ports in the firewall. networking.firewall.enable = true; networking.firewall.allowedTCPPorts = [ # Blocky DNS 53 # Blocky API 4000 # Caddy HTTP and HTTPS 80 443 ]; networking.firewall.allowedUDPPorts = [ # Blocky DNS 53 # mDNS 5353 # Headscale UDP port for STUN protocol 3478 ]; # Use systemd-resolved and set networkmanager to allow mdns services.resolved = { enable = true; extraConfig = '' DNSStubListener=false ''; }; networking.networkmanager.connectionConfig."connection.mdns" = 2; # 2 == yes # Copy the NixOS configuration file and link it from the resulting system # (/run/current-system/configuration.nix). This is useful in case you # accidentally delete configuration.nix. # system.copySystemConfiguration = true; # This option defines the first version of NixOS you have installed on this particular machine, # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions. # # Most users should NEVER change this value after the initial install, for any reason, # even if you've upgraded your system to a new NixOS release. # # This value does NOT affect the Nixpkgs version your packages and OS are pulled from, # so changing it will NOT upgrade your system. # # This value being lower than the current NixOS release does NOT mean your system is # out of date, out of support, or vulnerable. # # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration, # and migrated your data accordingly. # # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . system.stateVersion = "23.11"; # Did you read the comment? }