diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..02cc451 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,10 @@ +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 78e4127..ca6e418 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1756787288, - "narHash": "sha256-rw/PHa1cqiePdBxhF66V7R+WAP8WekQ0mCDG4CFqT8Y=", + "lastModified": 1759381078, + "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d0fc30899600b9b3466ddb260fd83deb486c32f1", + "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", "type": "github" }, "original": { @@ -37,9 +37,30 @@ "inputs": { "flake-utils": "flake-utils", "nixpkgs": "nixpkgs", + "sops-nix": "sops-nix", "utils": "utils" } }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1759188042, + "narHash": "sha256-f9QC2KKiNReZDG2yyKAtDZh0rSK2Xp1wkPzKbHeQVRU=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "9fcfabe085281dd793589bdc770a2e577a3caa5d", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + }, "systems": { "locked": { "lastModified": 1681028828, diff --git a/flake.nix b/flake.nix index 7701f3a..446f4ce 100644 --- a/flake.nix +++ b/flake.nix @@ -5,6 +5,10 @@ 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"; @@ -13,11 +17,11 @@ outputs = inputs@{ self, nixpkgs, - flake-utils, utils, + flake-utils, sops-nix, utils, ... }: let - system = "x86_64-linux"; + system = utils.lib.system.x86_64-linux; in utils.lib.mkFlake { inherit self inputs; @@ -28,6 +32,8 @@ modules = [ ./modules ./users + + sops-nix.nixosModules.sops ]; }; diff --git a/hosts/Development/default.nix b/hosts/Development/default.nix index b2237b7..608a31c 100644 --- a/hosts/Development/default.nix +++ b/hosts/Development/default.nix @@ -7,6 +7,11 @@ bind9.enable = true; traefik.enable = true; plex.enable = true; + coder = { + enable = true; + accessUrl = "https://code.depeuter.dev"; + wildcardAccessUrl = "*.code.depeuter.dev"; + }; }; virtualisation.guest.enable = true; }; diff --git a/modules/apps/bind9/db.depeuter.dev b/modules/apps/bind9/db.depeuter.dev index 72f3825..d3b6b42 100644 --- a/modules/apps/bind9/db.depeuter.dev +++ b/modules/apps/bind9/db.depeuter.dev @@ -1,6 +1,6 @@ $TTL 604800 @ IN SOA ns1 admin ( - 15 ; Serial + 18 ; Serial 604800 ; Refresh 86400 ; Retry 2419200 ; Expire @@ -40,6 +40,9 @@ sonarr IN A 192.168.0.33 ; Development VM plex IN A 192.168.0.91 +code IN A 192.168.0.91 +*.code IN A 192.168.0.91 + ; Catchalls *.production IN A 192.168.0.31 *.development IN A 192.168.0.91 diff --git a/modules/apps/coder/default.nix b/modules/apps/coder/default.nix new file mode 100644 index 0000000..18751c8 --- /dev/null +++ b/modules/apps/coder/default.nix @@ -0,0 +1,148 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.homelab.apps.coder; + + postgresUser = "coder"; + postgresPassword = "ChangeMe"; + postgresDb = "coder"; + + networkName = "coder"; + proxyNet = config.homelab.apps.traefik.sharedNetworkName; + + coderVersion = "v2.25.3"; + coderDbVersion = "17.6"; +in { + options.homelab.apps.coder = { + enable = lib.mkEnableOption "Coder (Docker)"; + port = lib.mkOption { + type = lib.types.port; + default = 7080; + description = "Port to expose Coder on."; + }; + accessUrl = lib.mkOption { + type = lib.types.str; + description = "The URL to access Coder at."; + }; + wildcardAccessUrl = lib.mkOption { + type = lib.types.str; + description = "A wildcard URL to access Coder at (e.g. for workspaces)."; + }; + + db.port = lib.mkOption { + type = lib.types.either lib.types.bool lib.types.port; + default = false; + description = "Port to expose the database on. Set to false to not expose."; + }; + }; + + config = lib.mkIf cfg.enable { + homelab.virtualisation.containers.enable = true; + + systemd.services."docker-${networkName}-create-network" = { + description = "Create Docker network for ${networkName}"; + requiredBy = [ + "docker-coder.service" + "docker-coderDb.service" + ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + if ! ${pkgs.docker}/bin/docker network ls | grep -q ${networkName}; then + ${pkgs.docker}/bin/docker network create ${networkName} + fi + ''; + }; + + virtualisation.oci-containers.containers = { + coder = let + coderPort = 7080; + in { + hostname = "coder"; + image = "ghcr.io/coder/coder:${coderVersion}"; + autoStart = true; + dependsOn = [ + "coderDb" + ]; + extraOptions = [ + "--group-add" "131" # Add docker group to access the socket + + # Modify DNS + "--dns=192.168.0.91" + ]; + ports = [ + "${toString cfg.port}:${toString coderPort}/tcp" + ]; + networks = [ + networkName + proxyNet + ]; + volumes = [ + "/var/run/docker.sock:/var/run/docker.sock" + ]; + labels = { + "traefik.enable" = "true"; + "traefik.docker.network" = proxyNet; + "traefik.http.routers.coder.rule" = "HostRegexp(`.+\.code\.depeuter\.dev`) || Host(`code.depeuter.dev`)"; + "traefik.http.services.coder.loadbalancer.server.port" = toString coderPort; + }; + environment = { + CODER_PG_CONNECTION_URL = "postgresql://${postgresUser}:${postgresPassword}@coder-db/${postgresDb}?sslmode=disable"; + + # Required if you are not using the tunnel + CODER_ACCESS_URL = cfg.accessUrl; + CODER_WILDCARD_ACCESS_URL = cfg.wildcardAccessUrl; + CODER_DISABLE_PATH_APPS = "false"; # TODO Enable me! + + CODER_HTTP_ADDRESS = "0.0.0.0:${toString coderPort}"; + CODER_TLS_ENABLE = "false"; + + # TODO Enable me! + #CODER_REDIRECT_TO_ACCESS_URL = "true"; + + # Disable telemetry + CODER_TELEMETRY_ENABLED = "false"; + }; + }; + + coderDb = { + hostname = "coder-db"; + image = "postgres:${coderDbVersion}"; + autoStart = true; + extraOptions = [ + ''--health-cmd="pg_isready -U ${postgresUser} -d ${postgresDb}"'' + "--health-interval=5s" + "--health-timeout=5s" + "--health-retries=5" + ]; + ports = lib.mkIf cfg.db.port [ + "${toString cfg.db.port}:5432/tcp" + ]; + networks = [ + networkName + ]; + volumes = [ + "coder_data:/var/lib/postgresql/data" + ]; + environment = { + POSTGRES_USER = postgresUser; + POSTGRES_PASSWORD = postgresPassword; + POSTGRES_DB = postgresDb; + }; + }; + + traefik.cmd = [ + "--entrypoints.websecure.http.tls.domains[2].main=code.depeuter.dev" + "--entrypoints.websecure.http.tls.domains[2].sans=*.code.depeuter.dev" + ]; + }; + + virtualisation.docker.daemon.settings = { + dns = [ + "192.168.0.91" + ]; + }; + }; +} diff --git a/modules/apps/default.nix b/modules/apps/default.nix index 7c8b8f8..9974f68 100644 --- a/modules/apps/default.nix +++ b/modules/apps/default.nix @@ -4,6 +4,7 @@ ./bind9 ./calibre ./changedetection + ./coder ./freshrss ./gitea ./jellyfin diff --git a/modules/apps/vaultwarden/default.nix b/modules/apps/vaultwarden/default.nix index 4510299..4b1016e 100644 --- a/modules/apps/vaultwarden/default.nix +++ b/modules/apps/vaultwarden/default.nix @@ -8,7 +8,7 @@ in { options.homelab.apps.vaultwarden = { enable = lib.mkEnableOption "Vaultwarden"; port = lib.mkOption { - type = lib.types.int; + type = lib.types.port; default = 10102; description = "Vaultwarden WebUI port"; }; diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml new file mode 100644 index 0000000..e17dab1 --- /dev/null +++ b/secrets/secrets.yaml @@ -0,0 +1,19 @@ +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 552909b..4038266 100644 --- a/users/admin/default.nix +++ b/users/admin/default.nix @@ -18,8 +18,8 @@ in { ]; initialPassword = "ChangeMe"; openssh.authorizedKeys.keys = [ - # TODO ChangeMe - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPrG+ldRBdCeHEXrsy/qHXIJYg8xQXVuiUR0DxhFjYNg" + # HomeLab > NixOS > admin > ssh + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGWIOOEqTy8cWKpENVbzD4p7bsQgQb/Dgpzk8i0dZ00T" ]; packages = with pkgs; [ curl