diff --git a/machines/domains.json b/machines/domains.json index f25ca02..95d98ee 100644 --- a/machines/domains.json +++ b/machines/domains.json @@ -8,6 +8,7 @@ "adguard-meemee.rzegocki.dev": "10.100.20.2", "deedee.rzegocki.dev": "10.100.20.1", "home.rzegocki.dev": "10.100.20.2", + "home-code.rzegocki.dev": "10.100.20.2", "meemee.rzegocki.dev": "10.100.20.2", "wg.rzegocki.dev": "10.100.20.2", "zigbee2mqtt-bottomfloor.rzegocki.dev": "10.100.20.2", diff --git a/modules/system/apps/docker/default.nix b/modules/system/apps/docker/default.nix index 2baf07b..8958fec 100644 --- a/modules/system/apps/docker/default.nix +++ b/modules/system/apps/docker/default.nix @@ -117,7 +117,7 @@ in volumes = [ "/var/run/docker.sock:/var/run/docker.sock:ro" ]; # in rootless mode, socket lives under /run//.... }; opts = { - disableReadOnly = true; + readOnlyRootFilesystem = false; }; } ); diff --git a/modules/system/containers/flaresolverr/default.nix b/modules/system/containers/flaresolverr/default.nix index 4eae34c..6d61bd1 100644 --- a/modules/system/containers/flaresolverr/default.nix +++ b/modules/system/containers/flaresolverr/default.nix @@ -23,7 +23,7 @@ in opts = { # for proxying requestes to solve CF captcha allowPublic = true; - disableReadOnly = true; + readOnlyRootFilesystem = false; }; }; }; diff --git a/modules/system/containers/gluetun/default.nix b/modules/system/containers/gluetun/default.nix index 5eecf57..00c4031 100644 --- a/modules/system/containers/gluetun/default.nix +++ b/modules/system/containers/gluetun/default.nix @@ -80,7 +80,7 @@ in }; opts = { allowPublic = true; - disableReadOnly = true; + readOnlyRootFilesystem = false; }; }; diff --git a/modules/system/containers/home-assistant/default.nix b/modules/system/containers/home-assistant/default.nix index 4cf1b7a..15c906a 100644 --- a/modules/system/containers/home-assistant/default.nix +++ b/modules/system/containers/home-assistant/default.nix @@ -30,33 +30,74 @@ in sops.secrets."${cfg.envFileSopsSecret}" = { }; - virtualisation.oci-containers.containers.home-assistant = svc.mkContainer { - cfg = { - image = "ghcr.io/onedr0p/home-assistant:2024.12.3@sha256:09bcc0786ef5a57af1e0fff16bebfd6bd0b969d2a07e06127e12b41ab740a3b4"; - user = "65000:65000"; - environmentFiles = [ config.sops.secrets."${cfg.envFileSopsSecret}".path ]; - volumes = [ "${cfg.dataDir}/config:/config" ]; - extraOptions = [ - "--mount" - "type=tmpfs,destination=/config/logs,tmpfs-mode=1777" - "--mount" - "type=tmpfs,destination=/config/tts,tmpfs-mode=1777" - "--mount" - "type=tmpfs,destination=/tmp,tmpfs-mode=1777" - ]; + virtualisation.oci-containers.containers = { + code-server = svc.mkContainer { + cfg = { + image = "ghcr.io/coder/code-server:4.95.3@sha256:6d74583d68179cbb6ddadc2518b450d2ac3eaec2d342474fe1941e03371cd2cf"; + user = "65000:65000"; + cmd = [ + "--auth" + "none" + "--user-data-dir" + "/config/.vscode" + "--extensions-dir" + "/config/.vscode" + "--port" + "12321" + "/config" + ]; + volumes = [ "${cfg.dataDir}/config:/config" ]; + extraOptions = [ + "--mount" + "type=tmpfs,destination=/home/coder,tmpfs-mode=1777" + ]; + }; + opts = { + # download extensions + allowPublic = true; + readOnlyRootFilesystem = false; + allowPrivilegeEscalation = true; + }; }; - opts = { - # for various APIs - allowPublic = true; + home-assistant = svc.mkContainer { + cfg = { + image = "ghcr.io/onedr0p/home-assistant:2024.12.3@sha256:09bcc0786ef5a57af1e0fff16bebfd6bd0b969d2a07e06127e12b41ab740a3b4"; + user = "65000:65000"; + environmentFiles = [ config.sops.secrets."${cfg.envFileSopsSecret}".path ]; + environment = { + HOME_ASSISTANT__HACS_INSTALL = "true"; + }; + volumes = [ "${cfg.dataDir}/config:/config" ]; + extraOptions = [ + "--mount" + "type=tmpfs,destination=/config/logs,tmpfs-mode=1777" + "--mount" + "type=tmpfs,destination=/config/tts,tmpfs-mode=1777" + "--mount" + "type=tmpfs,destination=/tmp,tmpfs-mode=1777" + ]; + }; + opts = { + # for various APIs + allowPublic = true; + }; }; }; services = { - nginx.virtualHosts.home-assistant = svc.mkNginxVHost { - host = "home"; - proxyPass = "http://home-assistant.docker:8123"; - useAuthelia = false; - customCSP = "disable"; + nginx.virtualHosts = { + code-server = svc.mkNginxVHost { + host = "home-code"; + proxyPass = "http://code-server.docker:12321"; + useAuthelia = false; + customCSP = "disable"; + }; + home-assistant = svc.mkNginxVHost { + host = "home"; + proxyPass = "http://home-assistant.docker:8123"; + useAuthelia = false; + customCSP = "disable"; + }; }; restic.backups = lib.mkIf cfg.backup ( svc.mkRestic { @@ -78,9 +119,16 @@ in { directories = [ cfg.dataDir ]; }; mySystemApps.homepage = { - services.Apps.home-assistant = svc.mkHomepage "home-assistant" // { - href = "https://home.${config.mySystem.rootDomain}"; - description = "Home automation."; + services.Apps = { + code-server = svc.mkHomepage "hass-code-server" // { + icon = "coder.svg"; + href = "https://home-code.${config.mySystem.rootDomain}"; + description = "Home automation configuration editor."; + }; + home-assistant = svc.mkHomepage "home-assistant" // { + href = "https://home.${config.mySystem.rootDomain}"; + description = "Home automation."; + }; }; }; }; diff --git a/modules/system/containers/homepage/default.nix b/modules/system/containers/homepage/default.nix index f05ad5b..d4861be 100644 --- a/modules/system/containers/homepage/default.nix +++ b/modules/system/containers/homepage/default.nix @@ -120,7 +120,7 @@ in }; opts = { allowPublic = true; - disableReadOnly = true; + readOnlyRootFilesystem = false; }; }; diff --git a/modules/system/containers/mail-archive/dovecot.nix b/modules/system/containers/mail-archive/dovecot.nix index cf5828a..096e478 100644 --- a/modules/system/containers/mail-archive/dovecot.nix +++ b/modules/system/containers/mail-archive/dovecot.nix @@ -35,7 +35,7 @@ in ]; }; opts = { - disableReadOnly = true; + readOnlyRootFilesystem = false; }; }; diff --git a/modules/system/containers/piped/backend.nix b/modules/system/containers/piped/backend.nix index c1cd75d..1c2ac7a 100644 --- a/modules/system/containers/piped/backend.nix +++ b/modules/system/containers/piped/backend.nix @@ -44,7 +44,7 @@ in opts = { # proxying to youtube allowPublic = true; - disableReadOnly = true; + readOnlyRootFilesystem = false; }; }; diff --git a/modules/system/containers/piped/frontend.nix b/modules/system/containers/piped/frontend.nix index 49a5c91..e933991 100644 --- a/modules/system/containers/piped/frontend.nix +++ b/modules/system/containers/piped/frontend.nix @@ -25,7 +25,7 @@ in ]; }; opts = { - disableReadOnly = true; + readOnlyRootFilesystem = false; }; }; diff --git a/modules/system/containers/wg-easy/default.nix b/modules/system/containers/wg-easy/default.nix index 7910052..59a3ec4 100644 --- a/modules/system/containers/wg-easy/default.nix +++ b/modules/system/containers/wg-easy/default.nix @@ -75,7 +75,7 @@ in opts = { # to allow connections from outside allowPublic = true; - disableReadOnly = true; + readOnlyRootFilesystem = false; }; }; diff --git a/modules/system/lib.nix b/modules/system/lib.nix index 2dfe2b3..c13ebdd 100644 --- a/modules/system/lib.nix +++ b/modules/system/lib.nix @@ -134,7 +134,8 @@ let args = { allowPublic = false; - disableReadOnly = false; + readOnlyRootFilesystem = true; + allowPrivilegeEscalation = false; routeThroughVPN = false; } // opts; in @@ -147,11 +148,11 @@ // { dependsOn = (lib.optionals args.routeThroughVPN [ "gluetun" ]) ++ (cfg.dependsOn or [ ]); extraOptions = - (lib.optionals (!args.disableReadOnly) [ "--read-only" ]) + (lib.optionals args.readOnlyRootFilesystem [ "--read-only" ]) ++ [ "--cap-drop=all" - "--security-opt=no-new-privileges" ] + ++ (lib.optionals (!args.allowPrivilegeEscalation) [ "--security-opt=no-new-privileges" ]) ++ (cfg.extraOptions or [ ]) ++ lib.optionals (!args.routeThroughVPN) [ # /etc/hosts mapping conflicts with container network mode