From ab1889dd8d405c5b7a5fad9a45a0082644a79143 Mon Sep 17 00:00:00 2001 From: LuckShiba Date: Fri, 12 Dec 2025 02:04:46 -0300 Subject: [PATCH 1/6] teams/danklinux: init --- maintainers/team-list.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/maintainers/team-list.nix b/maintainers/team-list.nix index 6d09fe0932b7..be89875bead4 100644 --- a/maintainers/team-list.nix +++ b/maintainers/team-list.nix @@ -251,6 +251,15 @@ with lib.maintainers; shortName = "Cyberus Technology employees"; }; + danklinux = { + members = [ + luckshiba + marcusramberg + ]; + scope = "Maintain DankMaterialShell and related packages and modules from Dank Linux."; + shortName = "Dank Linux"; + }; + darwin = { github = "darwin-core"; enableFeatureFreezePing = true; From e60e3f9ded96318fdf6a1c079541b1013536e7f4 Mon Sep 17 00:00:00 2001 From: LuckShiba Date: Fri, 12 Dec 2025 02:24:25 -0300 Subject: [PATCH 2/6] teams/danklinux: inherit packages and modules --- nixos/modules/programs/dsearch.nix | 2 +- nixos/modules/programs/wayland/dms-shell.nix | 2 +- pkgs/by-name/dg/dgop/package.nix | 2 +- pkgs/by-name/dm/dms-shell/package.nix | 2 +- pkgs/by-name/ds/dsearch/package.nix | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nixos/modules/programs/dsearch.nix b/nixos/modules/programs/dsearch.nix index c6d7509c91dd..a719631312be 100644 --- a/nixos/modules/programs/dsearch.nix +++ b/nixos/modules/programs/dsearch.nix @@ -49,5 +49,5 @@ in systemd.user.services.dsearch.wantedBy = mkIf cfg.systemd.enable [ cfg.systemd.target ]; }; - meta.maintainers = with lib.maintainers; [ luckshiba ]; + meta.maintainers = lib.teams.danklinux.maintainers; } diff --git a/nixos/modules/programs/wayland/dms-shell.nix b/nixos/modules/programs/wayland/dms-shell.nix index a49330fddcf5..15a8c01d03e7 100644 --- a/nixos/modules/programs/wayland/dms-shell.nix +++ b/nixos/modules/programs/wayland/dms-shell.nix @@ -198,5 +198,5 @@ in hardware.graphics.enable = lib.mkDefault true; }; - meta.maintainers = with lib.maintainers; [ luckshiba ]; + meta.maintainers = lib.teams.danklinux.maintainers; } diff --git a/pkgs/by-name/dg/dgop/package.nix b/pkgs/by-name/dg/dgop/package.nix index 406d29a53772..f3552c6c04f9 100644 --- a/pkgs/by-name/dg/dgop/package.nix +++ b/pkgs/by-name/dg/dgop/package.nix @@ -45,7 +45,7 @@ buildGoModule (finalAttrs: { homepage = "https://github.com/AvengeMedia/dgop"; changelog = "https://github.com/AvengeMedia/dgop/releases/tag/v${finalAttrs.version}"; license = lib.licenses.mit; - maintainers = with lib.maintainers; [ luckshiba ]; + teams = [ lib.teams.danklinux ]; mainProgram = "dgop"; platforms = lib.platforms.unix; }; diff --git a/pkgs/by-name/dm/dms-shell/package.nix b/pkgs/by-name/dm/dms-shell/package.nix index deba3b5218bd..5d49076a30c1 100644 --- a/pkgs/by-name/dm/dms-shell/package.nix +++ b/pkgs/by-name/dm/dms-shell/package.nix @@ -67,7 +67,7 @@ buildGoModule (finalAttrs: { homepage = "https://danklinux.com"; changelog = "https://github.com/AvengeMedia/DankMaterialShell/releases/tag/v${finalAttrs.version}"; license = lib.licenses.mit; - maintainers = with lib.maintainers; [ luckshiba ]; + teams = [ lib.teams.danklinux ]; mainProgram = "dms"; platforms = lib.platforms.linux; }; diff --git a/pkgs/by-name/ds/dsearch/package.nix b/pkgs/by-name/ds/dsearch/package.nix index 18056b4016db..7030edcb7213 100644 --- a/pkgs/by-name/ds/dsearch/package.nix +++ b/pkgs/by-name/ds/dsearch/package.nix @@ -47,7 +47,7 @@ buildGoModule (finalAttrs: { homepage = "https://github.com/AvengeMedia/danksearch"; changelog = "https://github.com/AvengeMedia/danksearch/releases/tag/v${finalAttrs.version}"; license = lib.licenses.mit; - maintainers = with lib.maintainers; [ luckshiba ]; + teams = [ lib.teams.danklinux ]; mainProgram = "dsearch"; platforms = lib.platforms.unix; }; From f2d16d9418755e83c0c234a29df6656dffb4638b Mon Sep 17 00:00:00 2001 From: LuckShiba Date: Sat, 13 Dec 2025 18:53:43 -0300 Subject: [PATCH 3/6] dms-shell: 0.6.2 -> 1.0.2 --- pkgs/by-name/dm/dms-shell/package.nix | 128 ++++++++++++++++---------- 1 file changed, 78 insertions(+), 50 deletions(-) diff --git a/pkgs/by-name/dm/dms-shell/package.nix b/pkgs/by-name/dm/dms-shell/package.nix index 5d49076a30c1..d317b77c9637 100644 --- a/pkgs/by-name/dm/dms-shell/package.nix +++ b/pkgs/by-name/dm/dms-shell/package.nix @@ -7,68 +7,96 @@ procps, nix-update-script, bashNonInteractive, + fprintd, + kdePackages, + qt6, }: -buildGoModule (finalAttrs: { - pname = "dms-shell"; - version = "0.6.2"; +buildGoModule ( + finalAttrs: + let + qmlPkgs = with kdePackages; [ + kirigami.unwrapped + sonnet + qtmultimedia + ]; - src = fetchFromGitHub { - owner = "AvengeMedia"; - repo = "DankMaterialShell"; - tag = "v${finalAttrs.version}"; - hash = "sha256-dLbiTWsKoF0if/Wqet/+L90ILdAaBqp+REGOou8uH3k="; - }; + qmlImportPath = lib.concatStringsSep ":" (map (o: "${o}/${qt6.qtbase.qtQmlPrefix}") qmlPkgs); + qtPluginPath = lib.concatStringsSep ":" (map (o: "${o}/${qt6.qtbase.qtPluginPrefix}") qmlPkgs); + in + { + pname = "dms-shell"; + version = "1.0.2"; - sourceRoot = "${finalAttrs.src.name}/core"; + src = fetchFromGitHub { + owner = "AvengeMedia"; + repo = "DankMaterialShell"; + tag = "v${finalAttrs.version}"; + hash = "sha256-rWjWYu5rs3ZOJ4YJpvIscBZSYu74thJHc0VYyYKJTUc="; + }; - vendorHash = "sha256-nc4CvEPfJ6l16/zmhnXr1jqpi6BeSXd3g/51djbEfpQ="; + sourceRoot = "${finalAttrs.src.name}/core"; - ldflags = [ - "-w" - "-s" - "-X main.Version=${finalAttrs.version}" - ]; + vendorHash = "sha256-2PCqiW4frxME8IlmwWH5ktznhd/G1bah5Ae4dp0HPTQ="; - subPackages = [ "cmd/dms" ]; + ldflags = [ + "-s" + "-w" + "-X main.Version=${finalAttrs.version}" + ]; - nativeBuildInputs = [ - installShellFiles - makeWrapper - ]; + subPackages = [ "cmd/dms" ]; - postInstall = '' - mkdir -p $out/share/quickshell - cp -r ${finalAttrs.src}/quickshell $out/share/quickshell/dms + nativeBuildInputs = [ + installShellFiles + makeWrapper + ]; - wrapProgram $out/bin/dms --add-flags "-c $out/share/quickshell/dms" + postInstall = '' + mkdir -p $out/share/quickshell/dms + cp -r ${finalAttrs.src}/quickshell/. $out/share/quickshell/dms/ - install -Dm644 ${finalAttrs.src}/quickshell/assets/systemd/dms.service \ - $out/lib/systemd/user/dms.service - substituteInPlace $out/lib/systemd/user/dms.service \ - --replace-fail /usr/bin/dms $out/bin/dms \ - --replace-fail /usr/bin/pkill ${procps}/bin/pkill + install -D ${finalAttrs.src}/assets/dms-open.desktop \ + $out/share/applications/dms-open.desktop + install -D ${finalAttrs.src}/core/assets/danklogo.svg \ + $out/share/hicolor/scalable/apps/danklogo.svg - substituteInPlace $out/share/quickshell/dms/Modules/Greetd/assets/dms-greeter \ - --replace-fail /bin/bash ${bashNonInteractive}/bin/bash + wrapProgram $out/bin/dms \ + --add-flags "-c $out/share/quickshell/dms" \ + --prefix "NIXPKGS_QT6_QML_IMPORT_PATH" ":" "${qmlImportPath}" \ + --prefix "QT_PLUGIN_PATH" ":" "${qtPluginPath}" - installShellCompletion --cmd dms \ - --bash <($out/bin/dms completion bash) \ - --fish <($out/bin/dms completion fish) \ - --zsh <($out/bin/dms completion zsh) - ''; + install -Dm644 ${finalAttrs.src}/assets/systemd/dms.service \ + $out/lib/systemd/user/dms.service - passthru = { - updateScript = nix-update-script { }; - }; + substituteInPlace $out/lib/systemd/user/dms.service \ + --replace-fail /usr/bin/dms $out/bin/dms \ + --replace-fail /usr/bin/pkill ${procps}/bin/pkill - meta = { - description = "Desktop shell for wayland compositors built with Quickshell & GO"; - homepage = "https://danklinux.com"; - changelog = "https://github.com/AvengeMedia/DankMaterialShell/releases/tag/v${finalAttrs.version}"; - license = lib.licenses.mit; - teams = [ lib.teams.danklinux ]; - mainProgram = "dms"; - platforms = lib.platforms.linux; - }; -}) + substituteInPlace $out/share/quickshell/dms/Modules/Greetd/assets/dms-greeter \ + --replace-fail /bin/bash ${bashNonInteractive}/bin/bash + + substituteInPlace $out/share/quickshell/dms/assets/pam/fprint \ + --replace-fail pam_fprintd.so ${fprintd}/lib/security/pam_fprintd.so + + installShellCompletion --cmd dms \ + --bash <($out/bin/dms completion bash) \ + --fish <($out/bin/dms completion fish) \ + --zsh <($out/bin/dms completion zsh) + ''; + + passthru = { + updateScript = nix-update-script { }; + }; + + meta = { + description = "DankMaterialShell - Desktop shell for wayland compositors built with Quickshell & GO"; + homepage = "https://danklinux.com"; + changelog = "https://github.com/AvengeMedia/DankMaterialShell/releases/tag/v${finalAttrs.version}"; + license = lib.licenses.mit; + teams = [ lib.teams.danklinux ]; + mainProgram = "dms"; + platforms = lib.platforms.linux; + }; + } +) From e9b36b8ab908f1431012c93756d206262112987a Mon Sep 17 00:00:00 2001 From: LuckShiba Date: Sat, 13 Dec 2025 18:55:53 -0300 Subject: [PATCH 4/6] nixos/dms-shell: update to dms-shell 1.0.2 --- nixos/modules/programs/wayland/dms-shell.nix | 130 ++++++++++++------- 1 file changed, 80 insertions(+), 50 deletions(-) diff --git a/nixos/modules/programs/wayland/dms-shell.nix b/nixos/modules/programs/wayland/dms-shell.nix index 15a8c01d03e7..48d180dc50a0 100644 --- a/nixos/modules/programs/wayland/dms-shell.nix +++ b/nixos/modules/programs/wayland/dms-shell.nix @@ -14,10 +14,20 @@ let types optional optionals + mapAttrs + mapAttrs' + filterAttrs ; cfg = config.programs.dms-shell; + path = [ + "programs" + "dms-shell" + ]; + + builtInRemovedMsg = "This is now built-in in DMS and doesn't need additional dependencies."; + optionalPackages = optionals cfg.enableSystemMonitoring [ pkgs.dgop ] ++ optionals cfg.enableClipboard [ @@ -28,20 +38,33 @@ let pkgs.glib pkgs.networkmanager ] - ++ optional cfg.enableBrightnessControl pkgs.brightnessctl - ++ optional cfg.enableColorPicker pkgs.hyprpicker ++ optional cfg.enableDynamicTheming pkgs.matugen ++ optional cfg.enableAudioWavelength pkgs.cava - ++ optional cfg.enableCalendarEvents pkgs.khal - ++ optional cfg.enableSystemSound pkgs.kdePackages.qtmultimedia; + ++ optional cfg.enableCalendarEvents pkgs.khal; in { + imports = [ + (lib.mkRemovedOptionModule (path ++ [ "enableBrightnessControl" ]) builtInRemovedMsg) + (lib.mkRemovedOptionModule (path ++ [ "enableColorPicker" ]) builtInRemovedMsg) + (lib.mkRemovedOptionModule ( + path ++ [ "enableSystemSound" ] + ) "qtmultimedia is now included on dms-shell package.") + ]; + options.programs.dms-shell = { enable = mkEnableOption "DankMaterialShell, a complete desktop shell for Wayland compositors"; package = mkPackageOption pkgs "dms-shell" { }; systemd = { + enable = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable DankMaterialShell systemd startup service. + ''; + }; + target = mkOption { type = types.str; default = "graphical-session.target"; @@ -98,28 +121,6 @@ in ''; }; - enableBrightnessControl = mkOption { - type = types.bool; - default = true; - description = '' - Whether to install dependencies required for brightness and backlight control. - This enables screen brightness adjustment widgets. - - Requires: brightnessctl - ''; - }; - - enableColorPicker = mkOption { - type = types.bool; - default = true; - description = '' - Whether to install dependencies required for color picking functionality. - This enables on-screen color picker tools. - - Requires: hyprpicker - ''; - }; - enableDynamicTheming = mkOption { type = types.bool; default = true; @@ -153,48 +154,77 @@ in ''; }; - enableSystemSound = mkOption { - type = types.bool; - default = true; - description = '' - Whether to install dependencies required for system sound support. - This enables audio playback for system notifications and events. - - Requires: qtmultimedia - ''; - }; - quickshell = { package = mkPackageOption pkgs "quickshell" { }; }; + + plugins = mkOption { + type = types.attrsOf ( + types.submodule { + options = { + enable = mkOption { + type = types.bool; + default = true; + description = "Whether to enable this plugin"; + }; + src = mkOption { + type = types.either types.package types.path; + description = "Source of the plugin package or path"; + }; + }; + } + ); + default = { }; + description = "DMS Plugins to install and enable"; + example = lib.literalExpression '' + { + DockerManager = { + src = pkgs.fetchFromGitHub { + owner = "LuckShiba"; + repo = "DmsDockerManager"; + rev = "v1.2.0"; + sha256 = "sha256-VoJCaygWnKpv0s0pqTOmzZnPM922qPDMHk4EPcgVnaU="; + }; + }; + AnotherPlugin = { + enable = true; + src = pkgs.another-plugin; + }; + } + ''; + }; }; config = mkIf cfg.enable { - environment.etc."xdg/quickshell/dms".source = "${cfg.package}/share/quickshell/dms"; + systemd.packages = lib.mkIf cfg.systemd.enable [ cfg.package ]; - systemd.packages = [ cfg.package ]; - - systemd.user.services.dms = { + systemd.user.services.dms = lib.mkIf cfg.systemd.enable { wantedBy = [ cfg.systemd.target ]; - restartTriggers = optional cfg.systemd.restartIfChanged "${cfg.package}/share/quickshell/dms"; + restartIfChanged = cfg.systemd.restartIfChanged; path = lib.mkForce [ ]; }; environment.systemPackages = [ cfg.package cfg.quickshell.package - pkgs.ddcutil - pkgs.libsForQt5.qt5ct - pkgs.kdePackages.qt6ct ] ++ optionalPackages; - fonts.packages = with pkgs; [ - fira-code - inter - material-symbols - ]; + environment.etc = + mapAttrs' + (name: value: { + name = "xdg/quickshell/dms-plugins/${name}"; + inherit value; + }) + ( + mapAttrs (name: plugin: { + source = plugin.src; + }) (filterAttrs (n: v: v.enable) cfg.plugins) + ); + services.power-profiles-daemon.enable = lib.mkDefault true; + services.accounts-daemon.enable = lib.mkDefault true; + hardware.i2c.enable = lib.mkDefault true; hardware.graphics.enable = lib.mkDefault true; }; From 0de2873a44048f045695efb58ec198c74f7d1bf6 Mon Sep 17 00:00:00 2001 From: LuckShiba Date: Sat, 13 Dec 2025 18:56:06 -0300 Subject: [PATCH 5/6] nixos/dms-greeter: update to dms-shell 1.0.2 --- .../services/display-managers/dms-greeter.nix | 113 ++++++++++++------ 1 file changed, 75 insertions(+), 38 deletions(-) diff --git a/nixos/modules/services/display-managers/dms-greeter.nix b/nixos/modules/services/display-managers/dms-greeter.nix index 1355291516fa..246a02ea414f 100644 --- a/nixos/modules/services/display-managers/dms-greeter.nix +++ b/nixos/modules/services/display-managers/dms-greeter.nix @@ -13,16 +13,19 @@ let mkIf mkDefault mkPackageOption + mkRemovedOptionModule literalExpression getExe makeBinPath optionalString - concatMapStringsSep + escapeShellArgs ; cfg = config.services.displayManager.dms-greeter; cfgAutoLogin = config.services.displayManager.autoLogin; + cacheDir = "/var/lib/dms-greeter"; + greeterScript = pkgs.writeShellScriptBin "dms-greeter-start" '' export PATH=$PATH:${ makeBinPath [ @@ -30,18 +33,28 @@ let config.programs.${cfg.compositor.name}.package ] } - exec ${cfg.package}/share/quickshell/dms/Modules/Greetd/assets/dms-greeter \ - --command ${cfg.compositor.name} \ - -p ${cfg.package}/share/quickshell/dms \ - --cache-dir /var/lib/dms-greeter \ - ${ - optionalString ( - cfg.compositor.customConfig != "" - ) "-C ${pkgs.writeText "dms-greeter-compositor-config" cfg.compositor.customConfig}" - } \ - ${optionalString cfg.logs.save ">> ${cfg.logs.path} 2>&1"} + ${ + escapeShellArgs ( + [ + "sh" + "${cfg.package}/share/quickshell/dms/Modules/Greetd/assets/dms-greeter" + "--cache-dir" + cacheDir + "--command" + cfg.compositor.name + "-p" + "${cfg.package}/share/quickshell/dms" + ] + ++ lib.optionals (cfg.compositor.customConfig != "") [ + "-C" + "${pkgs.writeText "dmsgreeter-compositor-config" cfg.compositor.customConfig}" + ] + ) + } ${optionalString cfg.logs.save "> ${cfg.logs.path} 2>&1"} ''; + jq = getExe pkgs.jq; + configFilesFromHome = if cfg.configHome != null then [ @@ -180,7 +193,7 @@ in ]; services.greetd = { - enable = true; + enable = mkDefault true; settings = { default_session = { user = "dms-greeter"; @@ -200,7 +213,7 @@ in material-symbols ]; - systemd.tmpfiles.settings."10-dms-greeter"."/var/lib/dms-greeter".d = { + systemd.tmpfiles.settings."10-dms-greeter".${cacheDir}.d = { user = "dms-greeter"; group = "dms-greeter"; mode = "0750"; @@ -211,40 +224,64 @@ in allConfigFiles = cfg.configFiles ++ configFilesFromHome; in '' - set -euo pipefail - - cd /var/lib/dms-greeter || exit 1 - - ${concatMapStringsSep "\n" (f: '' - if [[ -f "${f}" ]]; then - cp "${f}" . || true - fi - '') allConfigFiles} - - # Handle session.json wallpaper path - if [[ -f session.json ]]; then - if wallpaper=$(${getExe pkgs.jq} -r '.wallpaperPath' session.json 2>/dev/null); then - if [[ -f "$wallpaper" ]]; then - cp "$wallpaper" wallpaper.jpg || true - mv session.json session.orig.json - ${getExe pkgs.jq} '.wallpaperPath = "/var/lib/dms-greeter/wallpaper.jpg"' \ - session.orig.json > session.json || true + cd ${cacheDir} + ${lib.concatStringsSep "\n" ( + lib.map (f: '' + if [ -f "${f}" ]; then + cp "${f}" . fi - fi + '') allConfigFiles + )} + + if [ -f session.json ]; then + copy_wallpaper() { + local path=$(${jq} -r ".$1 // empty" session.json) + if [ -f "$path" ]; then + cp "$path" "$2" + ${jq} ".$1 = \"${cacheDir}/$2\"" session.json > session.tmp + mv session.tmp session.json + fi + } + + copy_monitor_wallpapers() { + ${jq} -r ".$1 // {} | to_entries[] | .key + \":\" + .value" session.json 2>/dev/null | while IFS=: read monitor path; do + local dest="$2-$(echo "$monitor" | tr -c '[:alnum:]' '-')" + if [ -f "$path" ]; then + cp "$path" "$dest" + ${jq} --arg m "$monitor" --arg p "${cacheDir}/$dest" ".$1[\$m] = \$p" session.json > session.tmp + mv session.tmp session.json + fi + done + } + + copy_wallpaper "wallpaperPath" "wallpaper" + copy_wallpaper "wallpaperPathLight" "wallpaper-light" + copy_wallpaper "wallpaperPathDark" "wallpaper-dark" + copy_monitor_wallpapers "monitorWallpapers" "wallpaper-monitor" + copy_monitor_wallpapers "monitorWallpapersLight" "wallpaper-monitor-light" + copy_monitor_wallpapers "monitorWallpapersDark" "wallpaper-monitor-dark" fi - # Rename colors file if it exists - [[ -f dms-colors.json ]] && mv dms-colors.json colors.json || true + if [ -f settings.json ]; then + if cp "$(${jq} -r '.customThemeFile' settings.json)" custom-theme.json; then + mv settings.json settings.orig.json + ${jq} '.customThemeFile = "${cacheDir}/custom-theme.json"' settings.orig.json > settings.json + fi + fi - # Fix ownership of all files - chown -R "dms-greeter:dms-greeter" . || true + mv dms-colors.json colors.json || : + chown dms-greeter:dms-greeter * || : ''; + services.displayManager.dms-greeter.configFiles = lib.mkIf ( + cfg.configHome != null + ) configFilesFromHome; + users.groups.dms-greeter = { }; users.users.dms-greeter = { description = "DankMaterialShell greeter user"; isSystemUser = true; - home = "/var/lib/dms-greeter"; + home = cacheDir; homeMode = "0750"; createHome = true; group = "dms-greeter"; @@ -257,5 +294,5 @@ in services.libinput.enable = mkDefault true; }; - meta.maintainers = with lib.maintainers; [ luckshiba ]; + meta.maintainers = lib.teams.danklinux.maintainers; } From e25f99a9380fe9b084c1a1884d931ed929396d4a Mon Sep 17 00:00:00 2001 From: LuckShiba Date: Sat, 13 Dec 2025 21:43:24 -0300 Subject: [PATCH 6/6] nixos/release-notes: add entries for dms-shell, dms-greeter, and dsearch modules --- nixos/doc/manual/release-notes/rl-2605.section.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nixos/doc/manual/release-notes/rl-2605.section.md b/nixos/doc/manual/release-notes/rl-2605.section.md index d6aa01e7019c..cd40062aca34 100644 --- a/nixos/doc/manual/release-notes/rl-2605.section.md +++ b/nixos/doc/manual/release-notes/rl-2605.section.md @@ -20,6 +20,12 @@ - [LibreChat](https://www.librechat.ai/), open-source self-hostable ChatGPT clone with Agents and RAG APIs. Available as [services.librechat](#opt-services.librechat.enable). +- [DankMaterialShell](https://danklinux.com), a complete desktop shell for Wayland compositors built with Quickshell. Available as [programs.dms-shell](#opt-programs.dms-shell.enable). + +- [dms-greeter](https://danklinux.com), a modern display manager greeter for DankMaterialShell that works with greetd and supports multiple Wayland compositors. Available as [services.displayManager.dms-greeter](#opt-services.displayManager.dms-greeter.enable). + +- [dsearch](https://github.com/AvengeMedia/danksearch), a fast filesystem search service with fuzzy matching. Available as [programs.dsearch](#opt-programs.dsearch.enable). + - [udp-over-tcp](https://github.com/mullvad/udp-over-tcp), a tunnel for proxying UDP traffic over a TCP stream. Available as `services.udp-over-tcp`. - [Komodo Periphery](https://github.com/moghtech/komodo), a multi-server Docker and Git deployment agent by Komodo. Available as [services.komodo-periphery](#opt-services.komodo-periphery.enable).