diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 485dee6..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.idea diff --git a/.sops.yaml b/.sops.yaml deleted file mode 100644 index 02cc451..0000000 --- a/.sops.yaml +++ /dev/null @@ -1,10 +0,0 @@ -keys: - - &tdpeuter_Tibo-NixFatDesk age1fva6s64s884z0q2w7de024sp69ucvqu0pg9shrhhqsn3ewlpjfpsh6md7y - - &tdpeuter_Tibo-NixTop age1qzutny0mqpcccqw6myyfntu6wcskruu9ghzvt6r4te7afkqwnguq05ex37 - -creation_rules: - - path_regex: secrets/[^/]+\.(yaml|json|env|ini)$ - key_groups: - - age: - - *tdpeuter_Tibo-NixFatDesk - - *tdpeuter_Tibo-NixTop diff --git a/flake.lock b/flake.lock index 67df8c4..e3284fd 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1760524057, - "narHash": "sha256-EVAqOteLBFmd7pKkb0+FIUyzTF61VKi7YmvP1tw4nEw=", + "lastModified": 1735291276, + "narHash": "sha256-NYVcA06+blsLG6wpAbSPTCyLvxD/92Hy4vlY9WxFI1M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "544961dfcce86422ba200ed9a0b00dd4b1486ec5", + "rev": "634fd46801442d760e09493a794c4f15db2d0cbb", "type": "github" }, "original": { @@ -37,30 +37,9 @@ "inputs": { "flake-utils": "flake-utils", "nixpkgs": "nixpkgs", - "sops-nix": "sops-nix", "utils": "utils" } }, - "sops-nix": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1760393368, - "narHash": "sha256-8mN3kqyqa2PKY0wwZ2UmMEYMcxvNTwLaOrrDsw6Qi4E=", - "owner": "Mic92", - "repo": "sops-nix", - "rev": "ab8d56e85b8be14cff9d93735951e30c3e86a437", - "type": "github" - }, - "original": { - "owner": "Mic92", - "repo": "sops-nix", - "type": "github" - } - }, "systems": { "locked": { "lastModified": 1681028828, @@ -83,11 +62,11 @@ ] }, "locked": { - "lastModified": 1738591040, - "narHash": "sha256-4WNeriUToshQ/L5J+dTSWC5OJIwT39SEP7V7oylndi8=", + "lastModified": 1722363685, + "narHash": "sha256-XCf2PIAT6lH7BwytgioPmVf/wkzXjSKScC4KzcZgb64=", "owner": "gytis-ivaskevicius", "repo": "flake-utils-plus", - "rev": "afcb15b845e74ac5e998358709b2b5fe42a948d1", + "rev": "6b10f51ff73a66bb29f3bc8151a59d217713f496", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 446f4ce..44d63c2 100644 --- a/flake.nix +++ b/flake.nix @@ -5,10 +5,6 @@ nixpkgs.url = "nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; - sops-nix = { - url = "github:Mic92/sops-nix"; - inputs.nixpkgs.follows = "nixpkgs"; - }; utils = { url = "github:gytis-ivaskevicius/flake-utils-plus"; inputs.flake-utils.follows = "flake-utils"; @@ -17,11 +13,11 @@ outputs = inputs@{ self, nixpkgs, - flake-utils, sops-nix, utils, + flake-utils, utils, ... }: let - system = utils.lib.system.x86_64-linux; + system = "x86_64-linux"; in utils.lib.mkFlake { inherit self inputs; @@ -32,30 +28,22 @@ modules = [ ./modules ./users - - sops-nix.nixosModules.sops ]; }; hosts = { - # Physical hosts - Niko.modules = [ ./hosts/Niko ]; + Niko.modules = [ ./hosts/Niko ]; - # Virtual machines - - # Single-service Ingress.modules = [ ./hosts/Ingress ]; Gitea.modules = [ ./hosts/Gitea ]; Vaultwarden.modules = [ ./hosts/Vaultwarden ]; - # Production multi-service Binnenpost.modules = [ ./hosts/Binnenpost ]; Production.modules = [ ./hosts/Production ]; ProductionGPU.modules = [ ./hosts/ProductionGPU ]; ProductionArr.modules = [ ./hosts/ProductionArr ]; ACE.modules = [ ./hosts/ACE ]; - # Others Template.modules = [ ./hosts/Template ]; Development.modules = [ ./hosts/Development ]; Testing.modules = [ ./hosts/Testing ]; diff --git a/hosts/Binnenpost/default.nix b/hosts/Binnenpost/default.nix index 561fbe1..d78e2da 100644 --- a/hosts/Binnenpost/default.nix +++ b/hosts/Binnenpost/default.nix @@ -16,7 +16,6 @@ apps = { speedtest.enable = true; technitiumDNS.enable = true; - traefik.enable = true; }; virtualisation.guest.enable = true; }; @@ -77,14 +76,6 @@ }; }; - virtualisation.oci-containers.containers.traefik.labels = { - "traefik.http.routers.roxanne.rule" = "Host(`roxanne.depeuter.dev`)"; - "traefik.http.services.roxanne.loadbalancer.server.url" = "https://192.168.0.13:8006"; - - "traefik.http.routers.hugo.rule" = "Host(`hugo.depeuter.dev`)"; - "traefik.http.services.hugo.loadbalancer.server.url" = "https://192.168.0.11:444"; - }; - system.stateVersion = "24.05"; }; } diff --git a/hosts/Development/default.nix b/hosts/Development/default.nix index 77f6758..b2237b7 100644 --- a/hosts/Development/default.nix +++ b/hosts/Development/default.nix @@ -5,13 +5,8 @@ homelab = { apps = { bind9.enable = true; - homepage = { - enable = true; - exposePort = true; - }; traefik.enable = true; plex.enable = true; - solidtime.enable = true; }; virtualisation.guest.enable = true; }; diff --git a/hosts/Gitea/default.nix b/hosts/Gitea/default.nix index c6c9b43..5b2492f 100644 --- a/hosts/Gitea/default.nix +++ b/hosts/Gitea/default.nix @@ -5,13 +5,6 @@ homelab = { apps.gitea.enable = true; virtualisation.guest.enable = true; - - users.admin = { - enable = true; - authorizedKeys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFrp6aM62Bf7bj1YM5AlAWuNrANU3N5e8+LtbbpmZPKS" - ]; - }; }; networking = { diff --git a/hosts/Ingress/default.nix b/hosts/Ingress/default.nix index c0a3ac9..63e3ced 100644 --- a/hosts/Ingress/default.nix +++ b/hosts/Ingress/default.nix @@ -59,7 +59,6 @@ prefixLength = 24; }; "cloud.depeuter.dev" = { }; "git.depeuter.dev" = { }; - "home.depeuter.dev" = { }; "jelly.depeuter.dev" = { }; "vault.depeuter.dev" = { }; }; @@ -68,12 +67,7 @@ prefixLength = 24; # List services that you want to enable. services = { # Enable Nginx as a reverse proxy - nginx = let - nextcloud = { - host = "192.168.0.23"; - officePort = 8080; - }; - in { + nginx = { enable = true; # Use recommended settings @@ -85,7 +79,7 @@ prefixLength = 24; # Only allow PFS-enabled ciphers with AES256 sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL"; - upstreams.docservice.servers."${nextcloud.host}:${toString nextcloud.officePort}" = {}; + upstreams.docservice.servers."192.168.0.14:8080" = {}; appendHttpConfig = '' map $http_x_forwarded_proto $the_scheme { @@ -117,14 +111,14 @@ prefixLength = 24; forceSSL = true; locations = { "/" = { - proxyPass = "http://${nextcloud.host}"; + proxyPass = "http://192.168.0.14"; extraConfig = '' add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; fastcgi_request_buffering off; ''; }; "/office/" = { - proxyPass = "http://${nextcloud.host}:${toString nextcloud.officePort}/"; + proxyPass = "http://192.168.0.14:8080/"; priority = 500; recommendedProxySettings = false; extraConfig = '' @@ -142,32 +136,16 @@ prefixLength = 24; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ''; }; + "calendar.depeuter.dev".locations."/".return = "301 https://cloud.depeuter.dev/apps/calendar"; + "tasks.depeuter.dev".locations."/".return = "301 https://cloud.depeuter.dev/apps/tasks"; + "notes.depeuter.dev".locations."/".return = "301 https://cloud.depeuter.dev/apps/notes"; - "home.depeuter.dev" = { - enableACME = true; - forceSSL = true; - locations."/" = { - proxyPass = "http://192.168.0.21:8123"; - extraConfig = '' - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; - ''; - }; - }; - - "jelly.depeuter.dev" = let - jellyfin = { - host = "192.168.0.94"; - port = 8096; - }; - in { + "jelly.depeuter.dev" = { enableACME = true; forceSSL = true; locations = { "/" = { - proxyPass = "http://${jellyfin.host}:${toString jellyfin.port}"; + proxyPass = "http://192.168.0.94:8096"; extraConfig = '' # Proxy main Jellyfin traffic proxy_set_header Host $host; @@ -182,7 +160,7 @@ prefixLength = 24; ''; }; "/socket" = { - proxyPass = "http://${jellyfin.host}:${toString jellyfin.port}"; + proxyPass = "http://192.168.0.91:8096"; extraConfig = '' # Proxy Jellyfin Websockets traffic proxy_http_version 1.1; @@ -198,7 +176,7 @@ prefixLength = 24; }; }; extraConfig = '' - client_max_body_size 512M; + client_max_body_size 20M; # Security / XSS Mitigation Headers # NOTE: X-Frame-Options may cause issues with the webOS app @@ -228,7 +206,7 @@ prefixLength = 24; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - client_max_body_size 10G; + client_max_body_size 512M; keepalive_timeout 600s; proxy_buffers 4 256k; # Number and size of buffers for reading response proxy_buffer_size 256k; # Buffer for the first part of the response @@ -242,18 +220,10 @@ prefixLength = 24; enableACME = true; forceSSL = true; locations = { - "/" = { - proxyPass = "http://192.168.0.22:10102"; - proxyWebsockets = true; - }; + "/".proxyPass = "http://192.168.0.22:10102"; "~ ^/admin".return = 403; }; }; - "rss.depeuter.dev" = { - enableACME = true; - forceSSL = true; - locations."/".proxyPass = "http://192.168.92:${toString config.homelab.apps.freshrss.port}"; - }; }; }; }; diff --git a/hosts/Niko/default.nix b/hosts/Niko/default.nix index 910f325..57dbc27 100644 --- a/hosts/Niko/default.nix +++ b/hosts/Niko/default.nix @@ -7,10 +7,7 @@ ]; homelab = { - apps = { - technitiumDNS.enable = true; - traefik.enable = true; - }; + apps.technitiumDNS.enable = true; users.deploy.enable = true; }; @@ -37,11 +34,12 @@ hardware = { enableRedistributableFirmware = true; enableAllFirmware = true; - graphics.enable = true; + pulseaudio.enable = true; + opengl.enable = true; }; # Select internationalisation properties. - i18n.defaultLocale = "en_GB.UTF-8"; + i18n.defaultLocale = "en_GB.utf8"; networking = { hostName = "Niko"; @@ -81,8 +79,6 @@ user = config.users.users.jellyfin-mpv-shim.name; }; - pulseaudio.enable = true; - tailscale = { enable = true; useRoutingFeatures = "server"; @@ -98,6 +94,8 @@ # resolved.enable = true; }; + sound.enable = true; + # Define a user account. Don't forget to set a password with 'passwd'. users.users.jellyfin-mpv-shim = { description = "Jellyfin MPV Shim User"; @@ -116,4 +114,67 @@ systemd.services."cage-tty1".serviceConfig.Restart = "always"; system.stateVersion = "24.05"; + + virtualisation = { + # Enable Android emulator + # waydroid.enable = true; + + docker = { + enable = true; + autoPrune.enable = true; + }; + + oci-containers = { + backend = "docker"; + containers = { + reverse-proxy = { + hostname = "traefik"; + image = "traefik:v3.0"; + cmd = [ + "--api.insecure=true" + # Add Docker provider + "--providers.docker=true" + "--providers.docker.exposedByDefault=false" + # Add web entrypoint + "--entrypoints.web.address=:80/tcp" + "--entrypoints.web.http.redirections.entrypoint.to=websecure" + "--entrypoints.web.http.redirections.entrypoint.scheme=https" + # Add websecure entrypoint + "--entrypoints.websecure.address=:443/tcp" + "--entrypoints.websecure.http.tls=true" + "--entrypoints.websecure.http.tls.certResolver=letsencrypt" + "--entrypoints.websecure.http.tls.domains[0].main=depeuter.dev" + "--entrypoints.websecure.http.tls.domains[0].sans=*.depeuter.dev" + "--entrypoints.websecure.http.tls.domains[1].sans=*.niko.depeuter.dev" + # Certificates + "--certificatesresolvers.letsencrypt.acme.dnschallenge=true" + "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare" + "--certificatesresolvers.letsencrypt.acme.email=tibo.depeuter@telenet.be" + "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" + ]; + ports = [ + "80:80/tcp" + "443:443/tcp" + # "8080:8080/tcp" # The Web UI (enabled by --api.insecure=true) + ]; + environment = { + # TODO Hide this! + "CLOUDFLARE_DNS_API_TOKEN" = "6Vz64Op_a6Ls1ljGeBxFoOVfQ-yB-svRbf6OyPv2"; + }; + environmentFiles = [ + ]; + volumes = [ + "/var/run/docker.sock:/var/run/docker.sock:ro" # So that Traefik can listen to the Docker events + "letsencrypt:/letsencrypt" + ]; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.traefik.rule" = "Host(`traefik.niko.depeuter.dev`)"; + "traefik.http.services.traefik.loadbalancer.server.port" = "8080"; + }; + autoStart = true; + }; + }; + }; + }; } diff --git a/hosts/ProductionGPU/default.nix b/hosts/ProductionGPU/default.nix index fa9ca8c..75e48e7 100644 --- a/hosts/ProductionGPU/default.nix +++ b/hosts/ProductionGPU/default.nix @@ -17,7 +17,7 @@ defaultGateway = { address = "192.168.0.1"; - interface = "ens18"; + interface = "enp6s18"; }; # Open ports in the firewall. @@ -25,7 +25,7 @@ enable = true; }; - interfaces.ens18 = { + interfaces.enp6s18 = { ipv4.addresses = [ { address = "192.168.0.94"; @@ -40,7 +40,7 @@ ]; }; - system.stateVersion = "24.11"; + system.stateVersion = "unstable"; ### Nvidia GPU support ### @@ -64,7 +64,7 @@ }; hardware = { - graphics = { + opengl = { enable = true; # driSupport = true; # driSupport32Bit = true; diff --git a/hosts/Testing/default.nix b/hosts/Testing/default.nix index cc353f6..2da6563 100644 --- a/hosts/Testing/default.nix +++ b/hosts/Testing/default.nix @@ -3,10 +3,7 @@ { config = { homelab = { - apps = { - freshrss.enable = true; - traefik.enable = true; - }; + apps.freshrss.enable = true; virtualisation.guest.enable = true; }; diff --git a/hosts/Vaultwarden/default.nix b/hosts/Vaultwarden/default.nix index 5ded575..d8115bc 100644 --- a/hosts/Vaultwarden/default.nix +++ b/hosts/Vaultwarden/default.nix @@ -9,13 +9,6 @@ name = "Hugo's Vault"; }; virtualisation.guest.enable = true; - - users.admin = { - enable = true; - authorizedKeys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJnihoyozOCnm6T9OzL2xoMeMZckBYR2w43us68ABA93" - ]; - }; }; networking = { diff --git a/modules/apps/arr/default.nix b/modules/apps/arr/default.nix index 7b530c3..e2c0df5 100644 --- a/modules/apps/arr/default.nix +++ b/modules/apps/arr/default.nix @@ -12,16 +12,7 @@ let PGID = toString config.users.groups.media.gid; UMASK = "002"; in { - options.homelab.apps.arr = let - mkAppOption = appName: { - enable = lib.mkEnableOption "${appName} using Docker"; - exposePorts = lib.mkOption { - type = lib.types.bool; - description = "Expose ${appName} port"; - default = cfg.exposePorts; - }; - }; - in { + options.homelab.apps.arr = { enable = lib.mkEnableOption "Arr Stack using Docker"; exposePorts = lib.mkOption { type = lib.types.bool; @@ -30,11 +21,46 @@ in { default = ! config.homelab.apps.traefik.enable; }; - bazarr = mkAppOption "Bazarr"; - prowlarr = mkAppOption "Prowlarr"; - qbittorrent = mkAppOption "qBittorrent"; - radarr = mkAppOption "Radarr"; - sonarr = mkAppOption "Sonarr"; + bazarr = { + enable = lib.mkEnableOption "Bazarr using Docker"; + exposePorts = lib.mkOption { + type = lib.types.bool; + description = "Expose Bazarr port"; + default = cfg.exposePorts; + }; + }; + prowlarr = { + enable = lib.mkEnableOption "Prowlarr using Docker"; + exposePorts = lib.mkOption { + type = lib.types.bool; + description = "Expose Prowlarr port"; + default = cfg.exposePorts; + }; + }; + qbittorrent = { + enable = lib.mkEnableOption "qBittorrent using Docker"; + exposePorts = lib.mkOption { + type = lib.types.bool; + description = "Expose qBittorrent port"; + default = cfg.exposePorts; + }; + }; + radarr = { + enable = lib.mkEnableOption "Radarr using Docker"; + exposePorts = lib.mkOption { + type = lib.types.bool; + description = "Expose Radarr port"; + default = cfg.exposePorts; + }; + }; + sonarr = { + enable = lib.mkEnableOption "Sonarr using Docker"; + exposePorts = lib.mkOption { + type = lib.types.bool; + description = "Expose Sonarr port"; + default = cfg.exposePorts; + }; + }; }; config = { @@ -61,9 +87,9 @@ in { virtualisation.containers.enable = lib.mkIf inUse true; }; - fileSystems = let - mkFileSystem = device: { - inherit device; + fileSystems = lib.mkIf inUse { + "/srv/bazarr-backup" = lib.mkIf cfg.bazarr.enable { + device = "192.168.0.11:/mnt/BIG/BACKUP/BAZARR"; fsType = "nfs"; options = [ "rw" @@ -76,14 +102,75 @@ in { ]; }; - hugoBackup = "192.168.0.11:/mnt/BIG/BACKUP"; - in lib.mkIf inUse { - "/srv/bazarr-backup" = lib.mkIf cfg.bazarr.enable (mkFileSystem "${hugoBackup}/BAZARR"); - "/srv/prowlarr-backup" = lib.mkIf cfg.bazarr.enable (mkFileSystem "${hugoBackup}/PROWLARR"); - "/srv/qbittorrent" = lib.mkIf cfg.qbittorrent.enable (mkFileSystem "192.168.0.11:/mnt/SMALL/CONFIG/QBITTORRENT"); - "/srv/radarr-backup" = lib.mkIf cfg.radarr.enable (mkFileSystem "${hugoBackup}/RADARR"); - "/srv/sonarr-backup" = lib.mkIf cfg.sonarr.enable (mkFileSystem "${hugoBackup}/SONARR"); - "/srv/torrent" = mkFileSystem "192.168.0.11:/mnt/SMALL/MEDIA/TORRENT"; + "/srv/prowlarr-backup" = lib.mkIf cfg.prowlarr.enable { + device = "192.168.0.11:/mnt/BIG/BACKUP/PROWLARR"; + fsType = "nfs"; + options = [ + "rw" + "auto" + "nfsvers=4.2" + "rsize=1048576" "wsize=1048576" + "hard" + "timeo=600" "retrans=2" + "_netdev" "nosuid" "tcp" + ]; + }; + + "/srv/qbittorrent" = lib.mkIf cfg.qbittorrent.enable { + device = "192.168.0.11:/mnt/SMALL/CONFIG/QBITTORRENT"; + fsType = "nfs"; + options = [ + "rw" + "auto" + "nfsvers=4.2" + "rsize=1048576" "wsize=1048576" + "hard" + "timeo=600" "retrans=2" + "_netdev" "nosuid" "tcp" + ]; + }; + + "/srv/radarr-backup" = lib.mkIf cfg.radarr.enable { + device = "192.168.0.11:/mnt/BIG/BACKUP/RADARR"; + fsType = "nfs"; + options = [ + "rw" + "auto" + "nfsvers=4.2" + "rsize=1048576" "wsize=1048576" + "hard" + "timeo=600" "retrans=2" + "_netdev" "nosuid" "tcp" + ]; + }; + + "/srv/sonarr-backup" = lib.mkIf cfg.sonarr.enable { + device = "192.168.0.11:/mnt/BIG/BACKUP/SONARR"; + fsType = "nfs"; + options = [ + "rw" + "auto" + "nfsvers=4.2" + "rsize=1048576" "wsize=1048576" + "hard" + "timeo=600" "retrans=2" + "_netdev" "nosuid" "tcp" + ]; + }; + + "/srv/torrent" = { + device = "192.168.0.11:/mnt/SMALL/MEDIA/TORRENT"; + fsType = "nfs"; + options = [ + "rw" + "auto" + "nfsvers=4.2" + "rsize=1048576" "wsize=1048576" + "hard" + "timeo=600" "retrans=2" + "_netdev" "nosuid" "tcp" + ]; + }; }; # Make sure the Docker network exists. @@ -108,24 +195,45 @@ in { }; # Create a user for each app. - users.users = let - mkUser = uid: { - uid = lib.mkForce uid; + users.users = { + bazarr = lib.mkIf cfg.bazarr.enable { + uid = lib.mkForce 3003; isSystemUser = true; group = config.users.groups.media.name; home = "/var/empty"; shell = null; }; - in { - bazarr = lib.mkIf cfg.bazarr.enable (mkUser 3003); - prowlarr = lib.mkIf cfg.prowlarr.enable (mkUser 3004); - qbittorrent = lib.mkIf cfg.qbittorrent.enable (mkUser 3005) // { + prowlarr = lib.mkIf cfg.prowlarr.enable { + uid = lib.mkForce 3004; + isSystemUser = true; + group = config.users.groups.media.name; + home = "/var/empty"; + shell = null; + }; + qbittorrent = lib.mkIf cfg.qbittorrent.enable { + uid = lib.mkForce 3005; + isSystemUser = true; + group = config.users.groups.media.name; extraGroups = [ config.users.groups.apps.name ]; + home = "/var/empty"; + shell = null; + }; + radarr = lib.mkIf cfg.radarr.enable { + uid = lib.mkForce 3006; + isSystemUser = true; + group = config.users.groups.media.name; + home = "/var/empty"; + shell = null; + }; + sonarr = lib.mkIf cfg.sonarr.enable { + uid = lib.mkForce 3007; + isSystemUser = true; + group = config.users.groups.media.name; + home = "/var/empty"; + shell = null; }; - radarr = lib.mkIf cfg.radarr.enable (mkUser 3006); - sonarr = lib.mkIf cfg.sonarr.enable (mkUser 3007); }; virtualisation.oci-containers.containers = let diff --git a/modules/apps/default.nix b/modules/apps/default.nix index 385f915..7c8b8f8 100644 --- a/modules/apps/default.nix +++ b/modules/apps/default.nix @@ -6,10 +6,8 @@ ./changedetection ./freshrss ./gitea - ./homepage ./jellyfin ./plex - ./solidtime ./speedtest ./technitium-dns ./traefik diff --git a/modules/apps/freshrss/default.nix b/modules/apps/freshrss/default.nix index 4f4456f..f2ea7ba 100644 --- a/modules/apps/freshrss/default.nix +++ b/modules/apps/freshrss/default.nix @@ -27,7 +27,7 @@ in { "rw" "auto" "nfsvers=4.2" - "async" "soft" "timeo=600" + "sync" "hard" "timeo=600" "retrans=2" "_netdev" "nosuid" @@ -53,41 +53,24 @@ in { virtualisation.oci-containers.containers.freshrss = { hostname = "freshrss"; - image = "freshrss/freshrss:1.25.0"; + image = "freshrss/freshrss:1.24.0"; autoStart = true; user = "0:33"; ports = [ - "${toString port}:80/tcp" + "${toString port}:${toString port}/tcp" ]; extraOptions = [ "--network=${networkName}" ]; environment = { TZ = config.time.timeZone; - CRON_MIN = "3,18,33,48"; # Alternatively, configure cron inside container. - SERVER_DNS = "rss.depeuter.dev"; - TRUSTED_PROXY = "172.16.0.1/12 192.168.0.1/16"; + CRON_TIME = "3,18,33,48"; # Alternatively, configure cron inside container. + LISTEN = "0.0.0.0:${toString port}"; }; volumes = [ "/srv/freshrss/www/freshrss/data:/var/www/FreshRSS/data" "/srv/freshrss/www/freshrss/extensions:/var/www/FreshRSS/extensions" ]; - labels = { - "traefik.enable" = "true"; - - "traefik.http.middlewares.freshrssM1.compress" = "true"; - "traefik.http.middlewares.freshrssM2.headers.browserXssFilter" = "true"; - "traefik.http.middlewares.freshrssM2.headers.forceSTSHeader" = "true"; - "traefik.http.middlewares.freshrssM2.headers.frameDeny" = "true"; - "traefik.http.middlewares.freshrssM2.headers.referrerPolicy" = "no-referrer-when-downgrade"; - "traefik.http.middlewares.freshrssM2.headers.stsSeconds" = "31536000"; - "traefik.http.routers.freshrss.entryPoints" = "websecure"; - "traefik.http.routers.freshrss.tls" = "true"; - - "traefik.http.services.freshrss.loadbalancer.server.port" = "80"; - "traefik.http.routers.freshrss.middlewares" = "freshrssM1,freshrssM2"; - "traefik.http.routers.freshrss.rule" = "Host(`rss.depeuter.dev`)"; - }; }; }; } diff --git a/modules/apps/gitea/default.nix b/modules/apps/gitea/default.nix index 0361bd5..02f60cd 100644 --- a/modules/apps/gitea/default.nix +++ b/modules/apps/gitea/default.nix @@ -124,7 +124,7 @@ in { gitea = { hostname = "gitea"; - image = "codeberg.org/forgejo/forgejo:11.0.1-rootless"; + image = "codeberg.org/forgejo/forgejo:8.0.3-rootless"; autoStart = true; user = "${toString UID}:${toString GID}"; ports = [ @@ -576,7 +576,7 @@ in { #FORGEJO__picture__AVATAR_RENDERED_SIZE_FACTOR = "2"; # Maximum allowed file size for uploaded avatars. # This is to limit the amount of RAM used when resizing the image. - FORGEJO__picture__AVATAR_MAX_FILE_SIZE = "1048576"; + #FORGEJO__picture__AVATAR_MAX_FILE_SIZE = "1048576"; # If the uploaded file is not larger than this byte size, the image will be used as is, without resizing/converting. #FORGEJO__picture__AVATAR_MAX_ORIGIN_SIZE = "262144"; # Chinese users can choose "duoshuo" diff --git a/modules/apps/homepage/default.nix b/modules/apps/homepage/default.nix deleted file mode 100644 index b34f32f..0000000 --- a/modules/apps/homepage/default.nix +++ /dev/null @@ -1,79 +0,0 @@ -{ config, lib, ... }: - -let - cfg = config.homelab.apps.homepage; - - PUID = toString config.users.users.homepage.uid; - PGID = toString config.users.groups.apps.gid; - - homepage-config = "/srv/homepage-config"; - - proxyNet = config.homelab.apps.traefik.sharedNetworkName; -in { - options.homelab.apps.homepage = { - enable = lib.mkEnableOption "homepage"; - port = lib.mkOption { - type = lib.types.int; - default = 3000; - description = "homepage WebUI port"; - }; - exposePort = lib.mkEnableOption "expose homepage port"; - }; - - config = lib.mkIf cfg.enable { - homelab = { - users.apps.enable = true; - virtualisation.containers.enable = true; - }; - - users.users.homepage = { - uid = lib.mkForce 3018; - isSystemUser = true; - group = config.users.groups.apps.name; - home = "/var/empty"; - shell = null; - }; - - fileSystems."${homepage-config}" = { - device = "192.168.0.11:/mnt/SMALL/CONFIG/HOMEPAGE"; - fsType = "nfs"; - options = [ - "rw" - "auto" - "nfsvers=4.2" - "async" "soft" "timeo=100" "retry=50" "actimeo=1800" "lookupcache=all" - "nosuid" "tcp" - ]; - }; - - virtualisation.oci-containers.containers.homepage = let - host = "homepage.${config.networking.domain}"; - in { - hostname = "homepage"; - image = "ghcr.io/gethomepage/homepage:v1.10.1"; - autoStart = true; - user = "${toString PUID}:${toString PGID}"; - ports = lib.mkIf cfg.exposePort [ - "${toString cfg.port}:3000/tcp" - ]; - networks = [ - proxyNet - ]; - volumes = [ - "${homepage-config}:/app/config" - # "/var/run/docker.sock:/var/run/docker.sock:ro" # For docker integrations - ]; - labels = { - "traefik.enable" = "true"; - "traefik.docker.network" = proxyNet; - "traefik.http.routers.homepage.rule" = "Host(`${host}`)"; - "traefik.http.services.homepage.loadbalancer.server.port" = toString cfg.port; - }; - environment = { - inherit PUID PGID; - - HOMEPAGE_ALLOWED_HOSTS = "${host},192.168.0.91:3000"; - }; - }; - }; -} diff --git a/modules/apps/solidtime/default.nix b/modules/apps/solidtime/default.nix index 725d32d..9174df4 100644 --- a/modules/apps/solidtime/default.nix +++ b/modules/apps/solidtime/default.nix @@ -5,8 +5,10 @@ let networkName = "solidtime"; internalNetworkName = "solidtime-internal"; - proxyNet = config.homelab.apps.traefiik.sharedNetworkName; + version = "0.8.0"; + + port = 8000; user = "1000:1000"; # dbExternalPort = ...; @@ -16,16 +18,6 @@ let inherit (config.virtualisation.oci-containers) containers; - solidtimeImageName = "solidtime/solidtime"; - version = "0.10.0"; - solidtimeImage = "${solidtimeImageName}:${version}"; - solidtimeImageFile = pkgs.dockerTools.pullImage { - imageName = solidtimeImageName; - finalImageTag = version; - imageDigest = "sha256:817d3a366ecc39f0473d7154372afa82dd4e6e50c66d70be45804892c8421cbb"; - sha256 = "sha256-h5aCKaquUF/EVsOHaLOHrn1HAoXZYPhAbJ+e4cmjSA8="; - }; - volumes = [ "solidtime-storage:/var/www/html/storage" "solidtime-logs:/var/www/html/storage/logs" @@ -38,7 +30,7 @@ let VITE_APP_NAME = laravelEnv.APP_NAME; APP_ENV = "production"; APP_DEBUG = "false"; - APP_URL = "http://localhost:${toString cfg.port}"; + APP_URL = "http://localhost:${toString port}"; APP_FORCE_HTTPS = "false"; APP_ENABLE_REGISTRATION = "false"; TRUSTED_PROXIES = "0.0.0.0/0,2000:0:0:0:0:0:0:0/3"; @@ -78,15 +70,7 @@ let }; in { - options.homelab.apps.solidtime = { - enable = lib.mkEnableOption "Solidtime time tracker using Docker"; - port = lib.mkOption { - type = lib.types.int; - default = 8000; - description = "Solidtime WebUI port"; - }; - exposePort = lib.mkEnableOption "Expose Soldtime port"; - }; + options.homelab.apps.solidtime.enable = lib.mkEnableOption "Solidtime time tracker using Docker"; config = lib.mkIf cfg.enable { homelab.virtualisation.containers.enable = true; @@ -132,57 +116,53 @@ in { virtualisation.oci-containers.containers = { solidtime = { hostname = "solidtime"; - image = solidtimeImage; - imageFile = solidtimeImageFile; - inherit user; + image = "solidtime/solidtime:${version}"; autoStart = true; + inherit user; + ports = [ + # Open ports if you don't use Traefik + "${toString port}:8000" + ]; + extraOptions = [ + "--network=${networkName}" + "--network=${internalNetworkName}" + + # Healthecks + # test: [ "CMD-SHELL", "curl --fail http://localhost:8000/health-check/up || exit 1" ] + ''--health-cmd=curl --fail http://localhost:8000/health-check/up || exit 1'' + ]; + inherit volumes; dependsOn = [ "solidtimeDb" ]; - ports = [ - # Open ports if you don't use Traefik - "${toString cfg.port}:8000" - ]; - networks = [ - networkName - internalNetworkName - ]; - extraOptions = [ - # Healthecks - # test: [ "CMD", "curl", "--fail", "http://localhost:8000/health-check/up" ] - ''--health-cmd=curl --fail http://localhost:8000/health-check/up'' - ]; - inherit volumes; - labels = { - "traefik.enable" = "true"; - "traefik.http.routers.solidtime.rule" = "Host(`time.${config.networking.hostName}.depeuter.dev`)"; - "traefik.http.services.solidtime.loadbalancer.server.port" = toString cfg.port; - }; environmentFiles = [ "/home/admin/.solidtime.env" ]; environment = laravelEnv // { CONTAINER_MODE = "http"; }; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.solidtime.rule" = "Host(`time.${config.networking.hostName}.depeuter.dev`)"; + "traefik.http.services.solidtime.loadbalancer.server.port" = toString port; + }; }; solidtimeScheduler = { hostname = "scheduler"; - image = solidtimeImage; - imageFile = solidtimeImageFile; + image = "solidtime/solidtime:${version}"; inherit user; autoStart = true; + extraOptions = [ + "--network=${internalNetworkName}" + + # Healthchecks + # test: [ "CMD-SHELL", "supervisorctl status scheduler:scheduler_00" ] + ''--health-cmd="supervisorctl status scheduler:scheduler_00"'' + ]; + inherit volumes; dependsOn = [ "solidtimeDb" ]; - networks = [ - internalNetworkName - ]; - extraOptions = [ - # Healthchecks - # test: [ "CMD", "healthcheck" ] - ''--health-cmd="healthcheck"'' - ]; - inherit volumes; environmentFiles = [ "/home/admin/.solidtime.env" ]; @@ -192,17 +172,15 @@ in { }; solidtimeQueue = { hostname = "queue"; - image = solidtimeImage; - imageFile = solidtimeImageFile; + image = "solidtime/solidtime:${version}"; inherit user; autoStart = true; - networks = [ - internalNetworkName - ]; extraOptions = [ + "--network=${internalNetworkName}" + # Healthchecks - # test: [ "CMD", "healthcheck" ] - ''--health-cmd="healthcheck"'' + # test: [ "CMD-SHELL", "supervisorctl status worker:worker_00" ] + ''--health-cmd="supervisorctl status worker:worker_00"'' ]; inherit volumes; dependsOn = [ @@ -216,25 +194,16 @@ in { WORKER_COMMAND = "php /var/www/html/artisan queue:work"; }; }; - solidtimeDb = let - imageName = "postgres"; - finalImageTag = "15"; - in { + solidtimeDb = { hostname = "database"; - image = "${imageName}:${finalImageTag}"; - imageFile = pkgs.dockerTools.pullImage { - inherit imageName finalImageTag; - imageDigest = "sha256:98fe06b500b5eb29e45bf8c073eb0ca399790ce17b1d586448edc4203627d342"; - sha256 = "sha256-AZ4VkOlROX+nR/MjDjsA4xdHzmtKjiBAtsp2Q6IdOvg="; - }; + image = "postgres:15"; autoStart = true; ports = [ # "${toString dbExternalPort}:${toString dbInternalPort}" ]; - networks = [ - internalNetworkName - ]; extraOptions = [ + "--network=${internalNetworkName}" + # Healthchecks # test: - CMD - pg_isready - '-q' - '-d' - '${DB_DATABASE}' - '-U' - '${DB_USERNAME}' retries: 3 timeout: 5s ''--health-cmd="pg_isready -q -d ${laravelEnv.DB_DATABASE} -U ${laravelEnv.DB_USERNAME}"'' @@ -251,22 +220,13 @@ in { POSTGRES_PASSWORD = laravelEnv.DB_PASSWORD; }; }; - solidtimeGotenberg = let - imageName = "gotenberg/gotenberg"; - finalImageTag = "8.26.0"; - in { + solidtimeGotenberg = { hostname = "gotenberg"; - image = "${imageName}:${finalImageTag}"; - imageFile = pkgs.dockerTools.pullImage { - inherit imageName finalImageTag; - imageDigest = "sha256:328551506b3dec3ff6381dd47e5cd72a44def97506908269e201a8fbfa1c12c0"; - sha256 = "sha256-1zz4xDAgXxHUnkCVIfjHTgXb82EFEx+5am6Cu9+eZj4="; - }; + image = "gotenberg/gotenberg:8"; autoStart = true; - networks = [ - internalNetworkName - ]; extraOptions = [ + "--network=${internalNetworkName}" + # Healthchecks # test: [ "CMD", "curl", "--silent", "--fail", "http://localhost:3000/health" ] ''--health-cmd="curl --silent --fail http://localhost:${toString gotenbergPort}/health"'' diff --git a/modules/default.nix b/modules/default.nix index 1a000c3..5d901bc 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -1,7 +1,6 @@ { imports = [ ./apps - ./fileSystems ./services ./virtualisation diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml deleted file mode 100644 index e17dab1..0000000 --- a/secrets/secrets.yaml +++ /dev/null @@ -1,19 +0,0 @@ -users: - admin: - authorized_keys: - NixOS: ENC[AES256_GCM,data:sj2hkUkWp628KuXp+AnncLdawHpxb9fH1ZHnIisP0x9Tght9+/X2sWHpuMSeqi2i/R8B+Wgte66QkuwAOB0j+oB9N+66EhehmWZlK5hD/22p,iv:z18U+LvAQgPDfBBewE3lJmWZd0NGCPwJIe/h3tupuZc=,tag:ZJar3spO66JbDXygdTHh2w==,type:str] -sops: - age: - - recipient: age1qzutny0mqpcccqw6myyfntu6wcskruu9ghzvt6r4te7afkqwnguq05ex37 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjUSt2REk2Mmd0bk9ubjJk - dXFiY2JNR1dyZW9qTUdzaWZhY3c3amVwQzA0CkZHNVpZVjhsWXhVQVNaR0xONzhh - Y0lQaWNaNmpYYVdrRnZIZUhvUFUzcWMKLS0tIDAvSmF0VmpxcnZEQStXUjNCUE5Z - RnA2Lzk2WHFxOEh6dHN0aGhVSVpLTW8KA7IOvGDMBtgo4pe0Sw3Lol243xCDAJ4i - PhcJFiUObVRFZN7ISlULnOlTO3pT9jWvvmC5rDZWId3PQ8qjPvnOUg== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-10-04T17:33:22Z" - mac: ENC[AES256_GCM,data:I7I7uDFEWfw9+4KROtjHMVhaxYrVK5QmLfFZShSajF0A2Zxu9lg+fDGiMHk40JC5zD31P70QS/ipye1mBGQbCbLEA7uBUhNzZ7G1g58cIXF6vSGmt0fovm0MVSxEJ44r05fx6uT4OJu5BYVxYSlG84gTj9rCFXxxcBJMrh+6yaI=,iv:c1vudsp9bg0Pc2ddRyvWn6Tf0LhqNuEjxG9D4PpHqxs=,tag:K/1PSHhrTdsNPcPmRv/2Ew==,type:str] - unencrypted_suffix: _unencrypted - version: 3.10.2 diff --git a/users/admin/default.nix b/users/admin/default.nix index dc01c81..552909b 100644 --- a/users/admin/default.nix +++ b/users/admin/default.nix @@ -3,30 +3,24 @@ let cfg = config.homelab.users.admin; in { - options.homelab.users.admin = { - enable = lib.mkEnableOption "user System Administrator"; - authorizedKeys = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ - # HomeLab > NixOS > admin > ssh - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGWIOOEqTy8cWKpENVbzD4p7bsQgQb/Dgpzk8i0dZ00T" - ]; - }; - }; + options.homelab.users.admin.enable = lib.mkEnableOption "user System Administrator"; config = lib.mkIf cfg.enable { nix.settings.trusted-users = [ - config.users.users.gh0st.name + config.users.users.admin.name ]; - users.users.gh0st = { + users.users.admin = { description = "System Administrator"; isNormalUser = true; extraGroups = [ config.users.groups.wheel.name # Enable 'sudo' for the user. ]; initialPassword = "ChangeMe"; - openssh.authorizedKeys.keys = cfg.authorizedKeys; + openssh.authorizedKeys.keys = [ + # TODO ChangeMe + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPrG+ldRBdCeHEXrsy/qHXIJYg8xQXVuiUR0DxhFjYNg" + ]; packages = with pkgs; [ curl git diff --git a/users/backup/default.nix b/users/backup/default.nix index acae033..8181d02 100644 --- a/users/backup/default.nix +++ b/users/backup/default.nix @@ -13,8 +13,13 @@ in { "docker" # Allow access to the docker socket. ]; openssh.authorizedKeys.keys = [ + # TODO ChangeMe + + # Tibo-NixFat + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPrG+ldRBdCeHEXrsy/qHXIJYg8xQXVuiUR0DxhFjYNg" + # Hugo - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICms6vjhE9kOlqV5GBPGInwUHAfCSVHLI2Gtzee0VXPh" + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDAxR813vqq5zbu1NHrIybu5Imlu3k0rDCGxHiuGEhPoVV9c5FpnKNGLCi3ctm15ZcVBX4HcponYsKRBsCzM2pI4uXjxhHkLzbss5LttFuSzv5v/QHfLW1bvyJEMBEPxguGqAydAeWrBFdI9uHBEXeb325uKxMKBZHYvvpyAQ115c1wKy1bL8BfR0LTkhsFqexRvI86q59AVrAU/KFf6RXO0T9QA6H/vyWLlIPc7Ta+tSWwQ68bMmS5Pwn8q58tOAOAd6Lpt4TqUDJSppPjLEPKyKC6ShwMdEjwmwpEG0hxfsvaU8XERyQbSbEE9sLHRA2LoEdtMx3J8nzX3AwYUNspsqIv6NQZksnVqJ8OfL45ngUFcSJ6kBsUvCZfzEUGUTJ6Js0v84NOIXxNG/ZfPsk6ArXm3dvj2TYeK8llO6wpJnMMyztmmiODWoj9tepZSij44IgVM5wdWYIK/RZoYTsCQbmvJFfB8jhyJnf/7F19Vo5+LwhmCOsQh/KEK0F1DVc= admin@Hugo" ]; }; };