Unverified Commit 7cceab52 authored by Silvan Mosberger's avatar Silvan Mosberger Committed by GitHub
Browse files

pds: init at 0.4.74, nixos/pds: init (#350645)

parents 966a592c 6d0241eb
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -121,6 +121,8 @@

- [Fider](https://fider.io/), an open platform to collect and prioritize feedback. Available as [services.fider](#opt-services.fider.enable).

- [PDS](https://github.com/bluesky-social/pds), Personal Data Server for [bsky](https://bsky.social/). Available as [services.pds](option.html#opt-services.pds).

- [mqtt-exporter](https://github.com/kpetremann/mqtt-exporter/), a Prometheus exporter for exposing messages from MQTT. Available as [services.prometheus.exporters.mqtt](#opt-services.prometheus.exporters.mqtt.enable).

- [nvidia-gpu](https://github.com/utkuozdemir/nvidia_gpu_exporter), a Prometheus exporter that scrapes `nvidia-smi` for GPU metrics. Available as [services.prometheus.exporters.nvidia-gpu](#opt-services.prometheus.exporters.nvidia-gpu.enable).
+1 −0
Original line number Diff line number Diff line
@@ -1547,6 +1547,7 @@
  ./services/web-apps/mobilizon.nix
  ./services/web-apps/openwebrx.nix
  ./services/web-apps/outline.nix
  ./services/web-apps/pds.nix
  ./services/web-apps/peering-manager.nix
  ./services/web-apps/peertube.nix
  ./services/web-apps/pgpkeyserver-lite.nix
+233 −0
Original line number Diff line number Diff line
{
  lib,
  pkgs,
  config,
  ...
}:
let
  cfg = config.services.pds;

  inherit (lib)
    getExe
    mkEnableOption
    mkIf
    mkOption
    mkPackageOption
    escapeShellArgs
    concatMapStringsSep
    types
    literalExpression
    ;

  pdsadminWrapper =
    let
      cfgSystemd = config.systemd.services.pds.serviceConfig;
    in
    pkgs.writeShellScriptBin "pdsadmin" ''
      DUMMY_PDS_ENV_FILE="$(mktemp)"
      trap 'rm -f "$DUMMY_PDS_ENV_FILE"' EXIT
      env "PDS_ENV_FILE=$DUMMY_PDS_ENV_FILE"                                                   \
          ${escapeShellArgs cfgSystemd.Environment}                                            \
          ${concatMapStringsSep " " (envFile: "$(cat ${envFile})") cfgSystemd.EnvironmentFile} \
          ${getExe pkgs.pdsadmin} "$@"
    '';
in
# All defaults are from https://github.com/bluesky-social/pds/blob/8b9fc24cec5f30066b0d0b86d2b0ba3d66c2b532/installer.sh
{
  options.services.pds = {
    enable = mkEnableOption "pds";

    package = mkPackageOption pkgs "pds" { };

    settings = mkOption {
      type = types.submodule {
        freeformType = types.attrsOf (
          types.oneOf [
            (types.nullOr types.str)
            types.port
          ]
        );
        options = {
          PDS_PORT = mkOption {
            type = types.port;
            default = 3000;
            description = "Port to listen on";
          };

          PDS_HOSTNAME = mkOption {
            type = types.str;
            example = "pds.example.com";
            description = "Instance hostname (base domain name)";
          };

          PDS_BLOB_UPLOAD_LIMIT = mkOption {
            type = types.str;
            default = "52428800";
            description = "Size limit of uploaded blobs in bytes";
          };

          PDS_DID_PLC_URL = mkOption {
            type = types.str;
            default = "https://plc.directory";
            description = "URL of DID PLC directory";
          };

          PDS_BSKY_APP_VIEW_URL = mkOption {
            type = types.str;
            default = "https://api.bsky.app";
            description = "URL of bsky frontend";
          };

          PDS_BSKY_APP_VIEW_DID = mkOption {
            type = types.str;
            default = "did:web:api.bsky.app";
            description = "DID of bsky frontend";
          };

          PDS_REPORT_SERVICE_URL = mkOption {
            type = types.str;
            default = "https://mod.bsky.app";
            description = "URL of mod service";
          };

          PDS_REPORT_SERVICE_DID = mkOption {
            type = types.str;
            default = "did:plc:ar7c4by46qjdydhdevvrndac";
            description = "DID of mod service";
          };

          PDS_CRAWLERS = mkOption {
            type = types.str;
            default = "https://bsky.network";
            description = "URL of crawlers";
          };

          PDS_DATA_DIRECTORY = mkOption {
            type = types.str;
            default = "/var/lib/pds";
            description = "Directory to store state";
          };

          PDS_BLOBSTORE_DISK_LOCATION = mkOption {
            type = types.nullOr types.str;
            default = "/var/lib/pds/blocks";
            description = "Store blobs at this location, set to null to use e.g. S3";
          };

          LOG_ENABLED = mkOption {
            type = types.nullOr types.str;
            default = "true";
            description = "Enable logging";
          };
        };
      };

      description = ''
        Environment variables to set for the service. Secrets should be
        specified using {option}`environmentFile`.

        Refer to <https://github.com/bluesky-social/atproto/blob/main/packages/pds/src/config/env.ts> for available environment variables.
      '';
    };

    environmentFiles = mkOption {
      type = types.listOf types.path;
      default = [ ];
      description = ''
        File to load environment variables from. Loaded variables override
        values set in {option}`environment`.

        Use it to set values of `PDS_JWT_SECRET`, `PDS_ADMIN_PASSWORD`,
        and `PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX` secrets.
        `PDS_JWT_SECRET` and `PDS_ADMIN_PASSWORD` can be generated with
        ```
        openssl rand --hex 16
        ```
        `PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX` can be generated with
        ```
        openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32
        ```
      '';
    };

    pdsadmin = {
      enable = mkOption {
        type = types.bool;
        default = cfg.enable;
        defaultText = literalExpression "config.services.pds.enable";
        description = "Add pdsadmin script to PATH";
      };
    };
  };

  config = mkIf cfg.enable {
    environment = mkIf cfg.pdsadmin.enable {
      systemPackages = [ pdsadminWrapper ];
    };

    systemd.services.pds = {
      description = "pds";

      after = [ "network-online.target" ];
      wants = [ "network-online.target" ];
      wantedBy = [ "multi-user.target" ];

      serviceConfig = {
        ExecStart = getExe cfg.package;
        Environment = lib.mapAttrsToList (k: v: "${k}=${if builtins.isInt v then toString v else v}") (
          lib.filterAttrs (_: v: v != null) cfg.settings
        );

        EnvironmentFile = cfg.environmentFiles;
        User = "pds";
        Group = "pds";
        StateDirectory = "pds";
        StateDirectoryMode = "0755";
        Restart = "always";

        # Hardening
        RemoveIPC = true;
        CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
        NoNewPrivileges = true;
        PrivateDevices = true;
        ProtectClock = true;
        ProtectKernelLogs = true;
        ProtectControlGroups = true;
        ProtectKernelModules = true;
        PrivateMounts = true;
        SystemCallArchitectures = [ "native" ];
        MemoryDenyWriteExecute = false; # required by V8 JIT
        RestrictNamespaces = true;
        RestrictSUIDSGID = true;
        ProtectHostname = true;
        LockPersonality = true;
        ProtectKernelTunables = true;
        RestrictAddressFamilies = [
          "AF_UNIX"
          "AF_INET"
          "AF_INET6"
        ];
        RestrictRealtime = true;
        DeviceAllow = [ "" ];
        ProtectSystem = "strict";
        ProtectProc = "invisible";
        ProcSubset = "pid";
        ProtectHome = true;
        PrivateUsers = true;
        PrivateTmp = true;
        UMask = "0077";
      };
    };

    users = {
      users.pds = {
        group = "pds";
        isSystemUser = true;
      };
      groups.pds = { };
    };

  };

  meta.maintainers = with lib.maintainers; [ t4ccer ];
}
+1 −0
Original line number Diff line number Diff line
@@ -810,6 +810,7 @@ in {
  parsedmarc = handleTest ./parsedmarc {};
  password-option-override-ordering = handleTest ./password-option-override-ordering.nix {};
  pdns-recursor = handleTest ./pdns-recursor.nix {};
  pds = handleTest ./pds.nix {};
  peerflix = handleTest ./peerflix.nix {};
  peering-manager = handleTest ./web-apps/peering-manager.nix {};
  peertube = handleTestOn ["x86_64-linux"] ./web-apps/peertube.nix {};

nixos/tests/pds.nix

0 → 100644
+29 −0
Original line number Diff line number Diff line
import ./make-test-python.nix (
  { lib, ... }:
  {
    name = "PDS";

    nodes.machine = {
      services.pds = {
        enable = true;
        settings = {
          PDS_PORT = 3000;
          PDS_HOSTNAME = "example.com";

          # Snake oil testing credentials
          PDS_JWT_SECRET = "7b93fee53be046bf59c27a32a0fb2069";
          PDS_ADMIN_PASSWORD = "3a4077bc0d5f04eca945ef0509f7e809";
          PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX = "ae4f5028d04c833ba630f29debd5ff80b7700e43e9f4bf70f729a88cd6a6ce35";
        };
      };
    };

    testScript = ''
      machine.wait_for_unit("pds.service")
      machine.wait_for_open_port(3000)
      machine.succeed("curl --fail http://localhost:3000")
    '';

    meta.maintainers = with lib.maintainers; [ t4ccer ];
  }
)
Loading