diff --git a/profiles/homebox/default.nix b/profiles/homebox/default.nix index 268878c..4f69d59 100644 --- a/profiles/homebox/default.nix +++ b/profiles/homebox/default.nix @@ -86,6 +86,8 @@ searxng.enable = true; home-assistant.enable = true; n8n.enable = true; + + nextcloud.enable = true; }; containers = { diff --git a/system/virtualization/docker/docker-mailserver/default.nix b/system/virtualization/docker/docker-mailserver/default.nix new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/system/virtualization/docker/docker-mailserver/default.nix @@ -0,0 +1 @@ +{} diff --git a/system/virtualization/docker/home-assistant/default.nix b/system/virtualization/docker/home-assistant/default.nix index 43ea77c..5ed3982 100644 --- a/system/virtualization/docker/home-assistant/default.nix +++ b/system/virtualization/docker/home-assistant/default.nix @@ -1,7 +1,5 @@ { config, lib, ... }: let - hostPort = 9003; - subdomain = "hass"; name = "home-assistant"; @@ -14,12 +12,6 @@ in { }; config = lib.mkIf (config.sysconfig.docker.home-assistant.enable && config.sysconfig.docker.enable) { - - networking.firewall.interfaces = { - "ve-traefik" = { - allowedTCPPorts = [ hostPort ]; - }; - }; environment.etc."home-assistant/configuration.yaml".source = ./configuration.yaml; @@ -51,7 +43,6 @@ in { }; ports = [ - "${builtins.toString hostPort}:8123" ]; volumes = [ diff --git a/system/virtualization/docker/jellyfin/default.nix b/system/virtualization/docker/jellyfin/default.nix index 0967ef4..133e54f 100644 --- a/system/virtualization/docker/jellyfin/default.nix +++ b/system/virtualization/docker/jellyfin/default.nix @@ -1 +1,114 @@ -{} +{ config, lib, pkgs, ... }: let + + subdomain = "watch"; + + name = "jellyfin"; + +in { + + options.sysconfig.docker.jellyfin.enable = with lib; mkOption { + type = with types; bool; + default = false; + }; + + config = lib.mkIf (config.sysconfig.docker.jellyfin.enable && config.sysconfig.docker.enable) { + + networking.firewall.allowedUDPPorts = [ 7359 ]; + + virtualisation.oci-containers.containers.jellyfin = { + image = "jellyfin/jellyfin:10.11.6"; + + # unstable, waiting for 26.05 + #pull = "newer"; + + hostname = "${subdomain}.esotericbytes.com"; + + networks = [ + "docker-main" + ]; + + ports = [ + "7359:7359/udp" + ]; + + volumes = [ + "vol_jellyfin-config:/config" + "vol_jellyfin-cache:/cache" + ]; + + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.${name}.entrypoints" = "localsecure"; + "traefik.http.routers.${name}.rule" = "Host(`${subdomain}.esotericbytes.com`)"; + "traefik.http.routers.${name}.service" = "${name}"; + "traefik.http.routers.${name}.tls.certResolver" = "cloudflare"; + + "traefik.http.services.${name}.loadbalancer.server.port" = "8096"; + }; + + extraOptions = lib.mkIf config.sysconfig.docker.nvidia [ + "--device=nvidia.com/gpu=all" + ]; + + environment = { + JELLYFIN_PublishedServerUrl = "https://${subdomain}.esotericbytes.com"; + }; + }; + + systemd.services."docker-jellyfin" = { + serviceConfig = { + Restart = lib.mkOverride 90 "always"; + RestartMaxDelaySec = lib.mkOverride 90 "1m"; + RestartSec = lib.mkOverride 90 "100ms"; + RestartSteps = lib.mkOverride 90 9; + }; + after = [ + "docker-network-setup.service" + "docker-volume-jellyfin-config.service" + "docker-volume-jellyfin-cache.service" + ]; + requires = [ + "docker-network-setup.service" + "docker-volume-jellyfin-config.service" + "docker-volume-jellyfin-cache.service" + ]; + partOf = [ + "docker-compose-jellyfin-root.target" + ]; + wantedBy = [ + "docker-compose-jellyfin-root.target" + ]; + }; + + systemd.services."docker-volume-jellyfin-config" = { + path = [ pkgs.docker ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + docker volume inspect vol_jellyfin-config || docker volume create vol_jellyfin-config --driver=local + ''; + partOf = [ "docker-compose-jellyfin-root.target" ]; + wantedBy = [ "docker-compose-jellyfin-root.target" ]; + }; + + systemd.services."docker-volume-jellyfin-cache" = { + path = [ pkgs.docker ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + docker volume inspect vol_jellyfin-cache || docker volume create vol_jellyfin-cache --driver=local + ''; + partOf = [ "docker-compose-jellyfin-root.target" ]; + wantedBy = [ "docker-compose-jellyfin-root.target" ]; + }; + + systemd.targets."docker-compose-jellyfin-root" = { + wantedBy = [ "multi-user.target" ]; + }; + + }; +} diff --git a/system/virtualization/docker/kiwix/default.nix b/system/virtualization/docker/kiwix/default.nix new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/system/virtualization/docker/kiwix/default.nix @@ -0,0 +1 @@ +{} diff --git a/system/virtualization/docker/n8n/default.nix b/system/virtualization/docker/n8n/default.nix index 91cb72d..d978424 100644 --- a/system/virtualization/docker/n8n/default.nix +++ b/system/virtualization/docker/n8n/default.nix @@ -46,7 +46,6 @@ in { }; ports = [ - "${builtins.toString hostPort}:5678" ]; volumes = [ diff --git a/system/virtualization/docker/nextcloud/default.nix b/system/virtualization/docker/nextcloud/default.nix index 0967ef4..b890aef 100644 --- a/system/virtualization/docker/nextcloud/default.nix +++ b/system/virtualization/docker/nextcloud/default.nix @@ -1 +1,94 @@ -{} +{ config, lib, pkgs, ... }: let + + subdomain = "cloud"; + + name = "nextcloud"; + +in { + + options.sysconfig.docker.nextcloud.enable = with lib; mkOption { + type = with types; bool; + default = false; + }; + + config = lib.mkIf (config.sysconfig.docker.nextcloud.enable && config.sysconfig.docker.enable) { + + virtualisation.oci-containers.containers.nextcloud = { + image = "ghcr.io/nextcloud-releases/all-in-one:v12.5.0"; + + # unstable, waiting for 26.05 + #pull = "newer"; + + hostname = "${subdomain}.esotericbytes.com"; + + networks = [ + "docker-main" + ]; + + ports = [ + "3479:3479/tcp" + "3479:3479/udp" + ]; + + volumes = [ + "vol_nextcloud:/mnt/docker-aio-config" + "/run/docker.sock:/var/run/docker.sock:ro" + ]; + + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.${name}.entrypoints" = "localsecure"; + "traefik.http.routers.${name}.rule" = "Host(`${subdomain}.esotericbytes.com`)"; + "traefik.http.routers.${name}.service" = "${name}"; + "traefik.http.routers.${name}.tls.certResolver" = "cloudflare"; + + "traefik.http.services.${name}.loadbalancer.server.port" = "80"; + }; + + environment = { + TALK_PORT = "3479"; + }; + }; + + systemd.services."docker-nextcloud" = { + serviceConfig = { + Restart = lib.mkOverride 90 "always"; + RestartMaxDelaySec = lib.mkOverride 90 "1m"; + RestartSec = lib.mkOverride 90 "100ms"; + RestartSteps = lib.mkOverride 90 9; + }; + after = [ + "docker-network-setup.service" + "docker-volume-nextcloud.service" + ]; + requires = [ + "docker-network-setup.service" + "docker-volume-nextcloud.service" + ]; + partOf = [ + "docker-compose-nextcloud-root.target" + ]; + wantedBy = [ + "docker-compose-nextcloud-root.target" + ]; + }; + + systemd.services."docker-volume-nextcloud" = { + path = [ pkgs.docker ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + docker volume inspect vol_nextcloud || docker volume create vol_nextcloud --driver=local + ''; + partOf = [ "docker-compose-nextcloud-root.target" ]; + wantedBy = [ "docker-compose-nextcloud-root.target" ]; + }; + + systemd.targets."docker-compose-nextcloud-root" = { + wantedBy = [ "multi-user.target" ]; + }; + + }; +} diff --git a/system/virtualization/docker/openwebui/default.nix b/system/virtualization/docker/openwebui/default.nix index 79d6f83..4a1579a 100644 --- a/system/virtualization/docker/openwebui/default.nix +++ b/system/virtualization/docker/openwebui/default.nix @@ -1,7 +1,5 @@ { config, lib, pkgs, ... }: let - hostPort = 9007; - subdomain = "ai"; name = "openwebui"; diff --git a/system/virtualization/docker/passbolt/default.nix b/system/virtualization/docker/passbolt/default.nix new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/system/virtualization/docker/passbolt/default.nix @@ -0,0 +1 @@ +{} diff --git a/system/virtualization/docker/passbolt/docker-compose.nix b/system/virtualization/docker/passbolt/docker-compose.nix new file mode 100644 index 0000000..e6e6fec --- /dev/null +++ b/system/virtualization/docker/passbolt/docker-compose.nix @@ -0,0 +1,167 @@ +# Auto-generated by compose2nix. + +{ pkgs, lib, ... }: + +{ + # Runtime + virtualisation.docker = { + enable = true; + autoPrune.enable = true; + }; + virtualisation.oci-containers.backend = "docker"; + + # Containers + virtualisation.oci-containers.containers."passbolt-db" = { + image = "mariadb:10.11"; + environment = { + "MYSQL_DATABASE" = "passbolt"; + "MYSQL_PASSWORD" = "P4ssb0lt"; + "MYSQL_RANDOM_ROOT_PASSWORD" = "true"; + "MYSQL_USER" = "passbolt"; + }; + volumes = [ + "passbolt_database_volume:/var/lib/mysql:rw" + ]; + log-driver = "journald"; + extraOptions = [ + "--network-alias=db" + "--network=passbolt_default" + ]; + }; + systemd.services."docker-passbolt-db" = { + serviceConfig = { + Restart = lib.mkOverride 90 "always"; + RestartMaxDelaySec = lib.mkOverride 90 "1m"; + RestartSec = lib.mkOverride 90 "100ms"; + RestartSteps = lib.mkOverride 90 9; + }; + after = [ + "docker-network-passbolt_default.service" + "docker-volume-passbolt_database_volume.service" + ]; + requires = [ + "docker-network-passbolt_default.service" + "docker-volume-passbolt_database_volume.service" + ]; + partOf = [ + "docker-compose-passbolt-root.target" + ]; + wantedBy = [ + "docker-compose-passbolt-root.target" + ]; + }; + virtualisation.oci-containers.containers."passbolt-passbolt" = { + image = "passbolt/passbolt:latest-ce"; + environment = { + "APP_FULL_BASE_URL" = "https://passbolt.local"; + "DATASOURCES_DEFAULT_DATABASE" = "passbolt"; + "DATASOURCES_DEFAULT_HOST" = "db"; + "DATASOURCES_DEFAULT_PASSWORD" = "P4ssb0lt"; + "DATASOURCES_DEFAULT_USERNAME" = "passbolt"; + }; + volumes = [ + "passbolt_gpg_volume:/etc/passbolt/gpg:rw" + "passbolt_jwt_volume:/etc/passbolt/jwt:rw" + ]; + ports = [ + "80:80/tcp" + "443:443/tcp" + ]; + cmd = [ "/usr/bin/wait-for.sh" "-t" "0" "db:3306" "--" "/docker-entrypoint.sh" ]; + dependsOn = [ + "passbolt-db" + ]; + log-driver = "journald"; + extraOptions = [ + "--network-alias=passbolt" + "--network=passbolt_default" + ]; + }; + systemd.services."docker-passbolt-passbolt" = { + serviceConfig = { + Restart = lib.mkOverride 90 "always"; + RestartMaxDelaySec = lib.mkOverride 90 "1m"; + RestartSec = lib.mkOverride 90 "100ms"; + RestartSteps = lib.mkOverride 90 9; + }; + after = [ + "docker-network-passbolt_default.service" + "docker-volume-passbolt_gpg_volume.service" + "docker-volume-passbolt_jwt_volume.service" + ]; + requires = [ + "docker-network-passbolt_default.service" + "docker-volume-passbolt_gpg_volume.service" + "docker-volume-passbolt_jwt_volume.service" + ]; + partOf = [ + "docker-compose-passbolt-root.target" + ]; + wantedBy = [ + "docker-compose-passbolt-root.target" + ]; + }; + + # Networks + systemd.services."docker-network-passbolt_default" = { + path = [ pkgs.docker ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStop = "docker network rm -f passbolt_default"; + }; + script = '' + docker network inspect passbolt_default || docker network create passbolt_default + ''; + partOf = [ "docker-compose-passbolt-root.target" ]; + wantedBy = [ "docker-compose-passbolt-root.target" ]; + }; + + # Volumes + systemd.services."docker-volume-passbolt_database_volume" = { + path = [ pkgs.docker ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + docker volume inspect passbolt_database_volume || docker volume create passbolt_database_volume + ''; + partOf = [ "docker-compose-passbolt-root.target" ]; + wantedBy = [ "docker-compose-passbolt-root.target" ]; + }; + systemd.services."docker-volume-passbolt_gpg_volume" = { + path = [ pkgs.docker ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + docker volume inspect passbolt_gpg_volume || docker volume create passbolt_gpg_volume + ''; + partOf = [ "docker-compose-passbolt-root.target" ]; + wantedBy = [ "docker-compose-passbolt-root.target" ]; + }; + systemd.services."docker-volume-passbolt_jwt_volume" = { + path = [ pkgs.docker ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + docker volume inspect passbolt_jwt_volume || docker volume create passbolt_jwt_volume + ''; + partOf = [ "docker-compose-passbolt-root.target" ]; + wantedBy = [ "docker-compose-passbolt-root.target" ]; + }; + + # Root service + # When started, this will automatically create all resources and start + # the containers. When stopped, this will teardown all resources. + systemd.targets."docker-compose-passbolt-root" = { + unitConfig = { + Description = "Root target generated by compose2nix."; + }; + wantedBy = [ "multi-user.target" ]; + }; +} diff --git a/system/virtualization/docker/rustdesk/docker-compose.nix b/system/virtualization/docker/rustdesk/docker-compose.nix new file mode 100644 index 0000000..1c3ba02 --- /dev/null +++ b/system/virtualization/docker/rustdesk/docker-compose.nix @@ -0,0 +1,77 @@ +# Auto-generated by compose2nix. + +{ pkgs, lib, ... }: + +{ + # Runtime + virtualisation.docker = { + enable = true; + autoPrune.enable = true; + }; + virtualisation.oci-containers.backend = "docker"; + + # Containers + virtualisation.oci-containers.containers."hbbr" = { + image = "rustdesk/rustdesk-server:latest"; + volumes = [ + "/home/nathan/Projects/Olympus/system/virtualization/docker/rustdesk/data:/root:rw" + ]; + cmd = [ "hbbr" ]; + log-driver = "journald"; + extraOptions = [ + "--network=host" + ]; + }; + systemd.services."docker-hbbr" = { + serviceConfig = { + Restart = lib.mkOverride 90 "always"; + RestartMaxDelaySec = lib.mkOverride 90 "1m"; + RestartSec = lib.mkOverride 90 "100ms"; + RestartSteps = lib.mkOverride 90 9; + }; + partOf = [ + "docker-compose-rustdesk-root.target" + ]; + wantedBy = [ + "docker-compose-rustdesk-root.target" + ]; + }; + virtualisation.oci-containers.containers."hbbs" = { + image = "rustdesk/rustdesk-server:latest"; + volumes = [ + "/home/nathan/Projects/Olympus/system/virtualization/docker/rustdesk/data:/root:rw" + ]; + cmd = [ "hbbs" ]; + dependsOn = [ + "hbbr" + ]; + log-driver = "journald"; + extraOptions = [ + "--network=host" + ]; + }; + systemd.services."docker-hbbs" = { + serviceConfig = { + Restart = lib.mkOverride 90 "always"; + RestartMaxDelaySec = lib.mkOverride 90 "1m"; + RestartSec = lib.mkOverride 90 "100ms"; + RestartSteps = lib.mkOverride 90 9; + }; + partOf = [ + "docker-compose-rustdesk-root.target" + ]; + wantedBy = [ + "docker-compose-rustdesk-root.target" + ]; + }; + + # Root service + # When started, this will automatically create all resources and start + # the containers. When stopped, this will teardown all resources. + systemd.targets."docker-compose-rustdesk-root" = { + unitConfig = { + Description = "Root target generated by compose2nix."; + }; + wantedBy = [ "multi-user.target" ]; + }; +} diff --git a/system/virtualization/docker/searxng/default.nix b/system/virtualization/docker/searxng/default.nix index 760bd85..9ba7b10 100644 --- a/system/virtualization/docker/searxng/default.nix +++ b/system/virtualization/docker/searxng/default.nix @@ -1,7 +1,5 @@ { config, lib, ... }: let - hostPort = 9002; - subdomain = "searxng"; name = "searxng"; @@ -14,13 +12,7 @@ in { }; config = lib.mkIf (config.sysconfig.docker.searxng.enable && config.sysconfig.docker.enable) { - - networking.firewall.interfaces = { - "ve-traefik" = { - allowedTCPPorts = [ hostPort ]; - }; - }; - + environment.etc."searxng/settings.yml".source = ./settings.yml; virtualisation.oci-containers.containers.searxng = { @@ -47,7 +39,6 @@ in { }; ports = [ - "${builtins.toString hostPort}:8080" ]; volumes = [