Unverified Commit b4cc3330 authored by Vladimír Čunát's avatar Vladimír Čunát
Browse files

Merge branch 'master' into staging-next

parents 0a1690dd fcf38c9b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@

- [stalwart-mail](https://stalw.art), an all-in-one email server (SMTP, IMAP, JMAP). Available as [services.stalwart-mail](#opt-services.stalwart-mail.enable).

- [Jool](https://nicmx.github.io/Jool/en/index.html), an Open Source implementation of IPv4/IPv6 translation on Linux. Available as [networking.jool.enable](#opt-networking.jool.enable).
- [Jool](https://nicmx.github.io/Jool/en/index.html), a kernelspace NAT64 and SIIT implementation, providing translation between IPv4 and IPv6. Available as [networking.jool.enable](#opt-networking.jool.enable).

- [Apache Guacamole](https://guacamole.apache.org/), a cross-platform, clientless remote desktop gateway. Available as [services.guacamole-server](#opt-services.guacamole-server.enable) and [services.guacamole-client](#opt-services.guacamole-client.enable) services.

+1 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ in

    i18n.inputMethod.uim = {
      toolbar = mkOption {
        type    = types.enum [ "gtk" "gtk3" "gtk-systray" "gtk3-systray" "qt4" ];
        type    = types.enum [ "gtk" "gtk3" "gtk-systray" "gtk3-systray" "qt5" ];
        default = "gtk";
        example = "gtk-systray";
        description = lib.mdDoc ''
+53 −46
Original line number Diff line number Diff line
@@ -11,27 +11,18 @@
  settingsFileUnsubstituted = settingsFormat.generate "mautrix-whatsapp-config-unsubstituted.json" cfg.settings;
  settingsFormat = pkgs.formats.json {};
  appservicePort = 29318;
in {
  imports = [];
  options.services.mautrix-whatsapp = {
    enable = lib.mkEnableOption "mautrix-whatsapp, a puppeting/relaybot bridge between Matrix and WhatsApp.";

    settings = lib.mkOption {
      type = settingsFormat.type;
      default = {
  mkDefaults = lib.mapAttrsRecursive (n: v: lib.mkDefault v);
  defaultConfig = {
    homeserver.address = "http://localhost:8448";
    appservice = {
          address = "http://localhost:${toString appservicePort}";
      hostname = "[::]";
      port = appservicePort;
          database = {
            type = "sqlite3";
            uri = "${dataDir}/mautrix-whatsapp.db";
          };
      database.type = "sqlite3";
      database.uri = "${dataDir}/mautrix-whatsapp.db";
      id = "whatsapp";
          bot = {
            username = "whatsappbot";
            displayname = "WhatsApp Bridge Bot";
          };
      bot.username = "whatsappbot";
      bot.displayname = "WhatsApp Bridge Bot";
      as_token = "";
      hs_token = "";
    };
@@ -46,18 +37,21 @@ in {
    };
    logging = {
      min_level = "info";
          writers = [
            {
      writers = lib.singleton {
        type = "stdout";
        format = "pretty-colored";
            }
            {
              type = "file";
              format = "json";
            }
          ];
        time_format = " ";
      };
    };
  };

in {
  options.services.mautrix-whatsapp = {
    enable = lib.mkEnableOption (lib.mdDoc "mautrix-whatsapp, a puppeting/relaybot bridge between Matrix and WhatsApp.");

    settings = lib.mkOption {
      type = settingsFormat.type;
      default = defaultConfig;
      description = lib.mdDoc ''
        {file}`config.yaml` configuration as a Nix attribute set.
        Configuration options should match those described in
@@ -117,10 +111,22 @@ in {
  };

  config = lib.mkIf cfg.enable {
    services.mautrix-whatsapp.settings = {
      homeserver.domain = lib.mkDefault config.services.matrix-synapse.settings.server_name;

    users.users.mautrix-whatsapp = {
      isSystemUser = true;
      group = "mautrix-whatsapp";
      home = dataDir;
      description = "Mautrix-WhatsApp bridge user";
    };

    users.groups.mautrix-whatsapp = {};

    services.mautrix-whatsapp.settings = lib.mkMerge (map mkDefaults [
      defaultConfig
      # Note: this is defined here to avoid the docs depending on `config`
      { homeserver.domain = config.services.matrix-synapse.settings.server_name; }
    ]);

    systemd.services.mautrix-whatsapp = {
      description = "Mautrix-WhatsApp Service - A WhatsApp bridge for Matrix";

@@ -158,10 +164,11 @@ in {
      '';

      serviceConfig = {
        DynamicUser = true;
        User = "mautrix-whatsapp";
        Group = "mautrix-whatsapp";
        EnvironmentFile = cfg.environmentFile;
        StateDirectory = baseNameOf dataDir;
        WorkingDirectory = "${dataDir}";
        WorkingDirectory = dataDir;
        ExecStart = ''
          ${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp \
          --config='${settingsFile}' \
+186 −127
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ let
    TemporaryFileSystem = [ "/" ];
    BindReadOnlyPaths = [
      builtins.storeDir
      "/run/current-system/kernel-modules"
      "/run/booted-system/kernel-modules"
    ];

    # Give capabilities to load the module and configure it
@@ -31,26 +31,96 @@ let

  configFormat = pkgs.formats.json {};

  mkDefaultAttrs = lib.mapAttrs (n: v: lib.mkDefault v);
  # Generate the config file of instance `name`
  nat64Conf = name:
    configFormat.generate "jool-nat64-${name}.conf"
      (cfg.nat64.${name} // { instance = name; });
  siitConf = name:
    configFormat.generate "jool-siit-${name}.conf"
      (cfg.siit.${name} // { instance = name; });

  # NAT64 config type
  nat64Options = lib.types.submodule {
    # The format is plain JSON
    freeformType = configFormat.type;
    # Some options with a default value
    options.framework = lib.mkOption {
      type = lib.types.enum [ "netfilter" "iptables" ];
      default = "netfilter";
      description = lib.mdDoc ''
        The framework to use for attaching Jool's translation to the exist
        kernel packet processing rules. See the
        [documentation](https://nicmx.github.io/Jool/en/intro-jool.html#design)
        for the differences between the two options.
      '';
    };
    options.global.pool6 = lib.mkOption {
      type = lib.types.strMatching "[[:xdigit:]:]+/[[:digit:]]+"
        // { description = "Network prefix in CIDR notation"; };
      default = "64:ff9b::/96";
      description = lib.mdDoc ''
        The prefix used for embedding IPv4 into IPv6 addresses.
        Defaults to the well-known NAT64 prefix, defined by
        [RFC 6052](https://datatracker.ietf.org/doc/html/rfc6052).
      '';
    };
  };

  # SIIT config type
  siitOptions = lib.types.submodule {
    # The format is, again, plain JSON
    freeformType = configFormat.type;
    # Some options with a default value
    options = { inherit (nat64Options.getSubOptions []) framework; };
  };

  makeNat64Unit = name: opts: {
    "jool-nat64-${name}" = {
      description = "Jool, NAT64 setup of instance ${name}";
      documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
      after = [ "network.target" ];
      wantedBy = [ "multi-user.target" ];
      serviceConfig = {
        Type = "oneshot";
        RemainAfterExit = true;
        ExecStartPre = "${pkgs.kmod}/bin/modprobe jool";
        ExecStart    = "${jool-cli}/bin/jool file handle ${nat64Conf name}";
        ExecStop     = "${jool-cli}/bin/jool -f ${nat64Conf name} instance remove";
      } // hardening;
    };
  };

  defaultNat64 = {
    instance = "default";
    framework = "netfilter";
    global.pool6 = "64:ff9b::/96";
  makeSiitUnit = name: opts: {
    "jool-siit-${name}" = {
      description = "Jool, SIIT setup of instance ${name}";
      documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
      after = [ "network.target" ];
      wantedBy = [ "multi-user.target" ];
      serviceConfig = {
        Type = "oneshot";
        RemainAfterExit = true;
        ExecStartPre = "${pkgs.kmod}/bin/modprobe jool_siit";
        ExecStart    = "${jool-cli}/bin/jool_siit file handle ${siitConf name}";
        ExecStop     = "${jool-cli}/bin/jool_siit -f ${siitConf name} instance remove";
      } // hardening;
    };
  defaultSiit = {
    instance = "default";
    framework = "netfilter";
  };

  nat64Conf = configFormat.generate "jool-nat64.conf" cfg.nat64.config;
  siitConf  = configFormat.generate "jool-siit.conf" cfg.siit.config;
  checkNat64 = name: _: ''
    printf 'Validating Jool configuration for NAT64 instance "${name}"... '
    jool file check ${nat64Conf name}
    printf 'Ok.\n'; touch "$out"
  '';

  checkSiit = name: _: ''
    printf 'Validating Jool configuration for SIIT instance "${name}"... '
    jool_siit file check ${siitConf name}
    printf 'Ok.\n'; touch "$out"
  '';

in

{
  ###### interface

  options = {
    networking.jool.enable = lib.mkOption {
      type = lib.types.bool;
@@ -64,15 +134,18 @@ in
        NAT64, analogous to the IPv4 NAPT. Refer to the upstream
        [documentation](https://nicmx.github.io/Jool/en/intro-xlat.html) for
        the supported modes of translation and how to configure them.

        Enabling this option will install the Jool kernel module and the
        command line tools for controlling it.
      '';
    };

    networking.jool.nat64.enable = lib.mkEnableOption (lib.mdDoc "a NAT64 instance of Jool.");
    networking.jool.nat64.config = lib.mkOption {
      type = configFormat.type;
      default = defaultNat64;
    networking.jool.nat64 = lib.mkOption {
      type = lib.types.attrsOf nat64Options;
      default = { };
      example = lib.literalExpression ''
        {
          default = {
            # custom NAT64 prefix
            global.pool6 = "2001:db8:64::/96";

@@ -96,7 +169,7 @@ in
            ];

            pool4 = [
            # Ports for dynamic translation
              # Port ranges for dynamic translation
              { protocol =  "TCP";  prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
              { protocol =  "UDP";  prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
              { protocol = "ICMP";  prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
@@ -105,116 +178,102 @@ in
              { protocol =  "TCP";  prefix = "192.0.2.16/32"; "port range" = "22"; }
              { protocol =  "UDP";  prefix = "192.0.2.16/32"; "port range" = "53"; }
            ];
          };
        }
      '';
      description = lib.mdDoc ''
        The configuration of a stateful NAT64 instance of Jool managed through
        NixOS. See https://nicmx.github.io/Jool/en/config-atomic.html for the
        available options.
        Definitions of NAT64 instances of Jool.
        See the
        [documentation](https://nicmx.github.io/Jool/en/config-atomic.html) for
        the available options. Also check out the
        [tutorial](https://nicmx.github.io/Jool/en/run-nat64.html) for an
        introduction to NAT64 and how to troubleshoot the setup.

        The attribute name defines the name of the instance, with the main one
        being `default`: this can be accessed from the command line without
        specifying the name with `-i`.

        ::: {.note}
        Existing or more instances created manually will not interfere with the
        NixOS instance, provided the respective `pool4` addresses and port
        ranges are not overlapping.
        Instances created imperatively from the command line will not interfere
        with the NixOS instances, provided the respective `pool4` addresses and
        port ranges are not overlapping.
        :::

        ::: {.warning}
        Changes to the NixOS instance performed via `jool instance nixos-nat64`
        are applied correctly but will be lost after restarting
        `jool-nat64.service`.
        Changes to an instance performed via `jool -i <name>` are applied
        correctly but will be lost after restarting the respective
        `jool-nat64-<name>.service`.
        :::
      '';
    };

    networking.jool.siit.enable = lib.mkEnableOption (lib.mdDoc "a SIIT instance of Jool.");
    networking.jool.siit.config = lib.mkOption {
      type = configFormat.type;
      default = defaultSiit;
    networking.jool.siit = lib.mkOption {
      type = lib.types.attrsOf siitOptions;
      default = { };
      example = lib.literalExpression ''
        {
          default = {
            # Maps any IPv4 address x.y.z.t to 2001:db8::x.y.z.t and v.v.
          pool6 = "2001:db8::/96";
            global.pool6 = "2001:db8::/96";

            # Explicit address mappings
            eamt = [
              # 2001:db8:1:: ←→ 192.0.2.0
            { "ipv6 prefix": "2001:db8:1::/128", "ipv4 prefix": "192.0.2.0" }
              { "ipv6 prefix" = "2001:db8:1::/128"; "ipv4 prefix" = "192.0.2.0"; }
              # 2001:db8:1::x ←→ 198.51.100.x
            { "ipv6 prefix": "2001:db8:2::/120", "ipv4 prefix": "198.51.100.0/24" }
          ]
              { "ipv6 prefix" = "2001:db8:2::/120"; "ipv4 prefix" = "198.51.100.0/24"; }
            ];
          };
        }
      '';
      description = lib.mdDoc ''
        The configuration of a SIIT instance of Jool managed through
        NixOS. See https://nicmx.github.io/Jool/en/config-atomic.html for the
        available options.
        Definitions of SIIT instances of Jool.
        See the
        [documentation](https://nicmx.github.io/Jool/en/config-atomic.html) for
        the available options. Also check out the
        [tutorial](https://nicmx.github.io/Jool/en/run-vanilla.html) for an
        introduction to SIIT and how to troubleshoot the setup.

        The attribute name defines the name of the instance, with the main one
        being `default`: this can be accessed from the command line without
        specifying the name with `-i`.

        ::: {.note}
        Existing or more instances created manually will not interfere with the
        NixOS instance, provided the respective `EAMT` address mappings are not
        overlapping.
        Instances created imperatively from the command line will not interfere
        with the NixOS instances, provided the respective EAMT addresses and
        port ranges are not overlapping.
        :::

        ::: {.warning}
        Changes to the NixOS instance performed via `jool instance nixos-siit`
        are applied correctly but will be lost after restarting
        `jool-siit.service`.
        Changes to an instance performed via `jool -i <name>` are applied
        correctly but will be lost after restarting the respective
        `jool-siit-<name>.service`.
        :::
      '';
    };

  };

  ###### implementation

  config = lib.mkIf cfg.enable {
    environment.systemPackages = [ jool-cli ];
    # Install kernel module and cli tools
    boot.extraModulePackages = [ jool ];
    environment.systemPackages = [ jool-cli ];

    systemd.services.jool-nat64 = lib.mkIf cfg.nat64.enable {
      description = "Jool, NAT64 setup";
      documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
      after = [ "network.target" ];
      wantedBy = [ "multi-user.target" ];
      reloadIfChanged = true;
      serviceConfig = {
        Type = "oneshot";
        RemainAfterExit = true;
        ExecStartPre = "${pkgs.kmod}/bin/modprobe jool";
        ExecStart    = "${jool-cli}/bin/jool file handle ${nat64Conf}";
        ExecStop     = "${jool-cli}/bin/jool -f ${nat64Conf} instance remove";
      } // hardening;
    };

    systemd.services.jool-siit = lib.mkIf cfg.siit.enable {
      description = "Jool, SIIT setup";
      documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
      after = [ "network.target" ];
      wantedBy = [ "multi-user.target" ];
      reloadIfChanged = true;
      serviceConfig = {
        Type = "oneshot";
        RemainAfterExit = true;
        ExecStartPre = "${pkgs.kmod}/bin/modprobe jool_siit";
        ExecStart    = "${jool-cli}/bin/jool_siit file handle ${siitConf}";
        ExecStop     = "${jool-cli}/bin/jool_siit -f ${siitConf} instance remove";
      } // hardening;
    };
    # Install services for each instance
    systemd.services = lib.mkMerge
      (lib.mapAttrsToList makeNat64Unit cfg.nat64 ++
       lib.mapAttrsToList makeSiitUnit cfg.siit);

    system.checks = lib.singleton (pkgs.runCommand "jool-validated" {
      nativeBuildInputs = [ pkgs.buildPackages.jool-cli ];
    # Check the configuration of each instance
    system.checks = lib.optional (cfg.nat64 != {} || cfg.siit != {})
      (pkgs.runCommand "jool-validated"
        {
          nativeBuildInputs = with pkgs.buildPackages; [ jool-cli ];
          preferLocalBuild = true;
    } ''
      printf 'Validating Jool configuration... '
      ${lib.optionalString cfg.siit.enable "jool_siit file check ${siitConf}"}
      ${lib.optionalString cfg.nat64.enable "jool file check ${nat64Conf}"}
      printf 'ok\n'
      touch "$out"
    '');

    networking.jool.nat64.config = mkDefaultAttrs defaultNat64;
    networking.jool.siit.config  = mkDefaultAttrs defaultSiit;

        }
        (lib.concatStrings
          (lib.mapAttrsToList checkNat64 cfg.nat64 ++
           lib.mapAttrsToList checkSiit cfg.siit)));
  };

  meta.maintainers = with lib.maintainers; [ rnhmjoj ];
+2 −1
Original line number Diff line number Diff line
@@ -134,6 +134,7 @@ in {
        # Update user directories.
        xdg-user-dirs
      ]
      ++ lib.optional config.networking.networkmanager.enable pkgs.networkmanagerapplet
      ++ (utils.removePackagesByName [
          cinnamon.nemo
          mate.eom
@@ -192,7 +193,7 @@ in {
    # Required by Budgie Panel plugins and/or Budgie Control Center panels.
    networking.networkmanager.enable = mkDefault true; # for BCC's Network panel.
    programs.nm-applet.enable = config.networking.networkmanager.enable; # Budgie has no Network applet.
    programs.nm-applet.indicator = false; # Budgie doesn't support AppIndicators.
    programs.nm-applet.indicator = true; # Budgie uses AppIndicators.

    hardware.bluetooth.enable = mkDefault true; # for Budgie's Status Indicator and BCC's Bluetooth panel.
    hardware.pulseaudio.enable = mkDefault true; # for Budgie's Status Indicator and BCC's Sound panel.
Loading