~aasg/nixexprs

ref: b0d0abb40316ca47caedc31965dd8dcd5af86695 nixexprs/modules/services/cluster/ipfs-cluster.nix -rw-r--r-- 4.7 KiB
b0d0abb4 — Aluísio Augusto Silva Gonçalves ipfs-cluster: Use more systemd features to ease new cluster setup 4 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
{ config, lib, pkgs, ... }:
with lib;
let
  settingsToEnv =
    let
      settingToNVP = prefix: name: value:
        let
          envName = toUpper "${prefix}_${name}";
        in
        if builtins.isAttrs value then
          settingsToNVP envName value
        else if builtins.isList value then
          nameValuePair envName (concatStringsSep "," value)
        else
          nameValuePair envName (toString value);
      settingsToNVP = prefix: settings:
        flatten (mapAttrsToList (settingToNVP prefix) settings);
    in
    settings: builtins.listToAttrs (settingsToNVP "cluster" settings);

  cfg = config.services.ipfs-cluster;

  # Is the cluster secret file in a home directory?
  secretInHome = cfg.secretFile != null && (
    hasPrefix "/root" cfg.secretFile || hasPrefix "/home" cfg.secretFile
  );
in
{
  options = {
    services.ipfs-cluster = {
      enable = mkEnableOption "IPFS Cluster daemon";

      package = mkOption {
        type = types.package;
        default = pkgs.ipfs-cluster;
        defaultText = "pkgs.ipfs-cluster";
        description = "ipfs-cluster package to use.";
      };

      user = mkOption {
        type = types.str;
        default = "ipfs";
        description = "User under which the IPFS Cluster daemon runs";
      };

      group = mkOption {
        type = types.str;
        default = "ipfs";
        description = "Group under which the IPFS Cluster daemon runs";
      };

      dataDir = mkOption {
        type = types.str;
        default = "/var/lib/ipfs-cluster";
        description = "Directory where cluster management data lives.";
      };

      secretEnvFile = mkOption {
        type = with types; nullOr str;
        default = null;
        description = ''
          File containing the cluster secret as an assignment to the CLUSTER_SECRET variable.
          If none is given, a secret is generated during cluster creation.
        '';
      };

      secretFile = mkOption {
        type = with types; nullOr str;
        default = null;
        description = ''
          File containing the cluster secret.
          If none is given, a secret is generated during cluster creation.
          Deprecated: use `services.ipfs-cluster-secretEnvFile` instead.
        '';
      };

      consensus = mkOption {
        type = types.enum [ "crdt" "raft" ];
        description = "Consensus component utilized by the cluster. This option has no effect on already existing clusters.";
      };

      bootstrapPeers = mkOption {
        type = with types; listOf str;
        default = [ ];
        description = "List of peers to bootstrap the node with. This option has no effect on already existing clusters.";
      };

      settings = mkOption {
        type = types.attrs;
        default = { };
        description = "Additional IPFS Cluster settings. These follow the names for configuration environment variables, not for the service.json file.";
      };
    };
  };

  config = mkIf cfg.enable {
    environment.systemPackages = [ cfg.package ];

    systemd.services.ipfs-cluster = {
      description = "IPFS Cluster daemon";
      after = [ "network-online.target" "ipfs.service" ];
      wants = [ "network-online.target" ];
      wantedBy = [ "multi-user.target" ];
      environment = {
        IPFS_CLUSTER_PATH = cfg.dataDir;
      } // settingsToEnv cfg.settings;
      serviceConfig = {
        Type = "simple";
        User = cfg.user;
        Group = cfg.group;
        Restart = "on-abnormal";
        AmbientCapabilities = "cap_net_bind_service";
        CapabilityBoundingSet = "cap_net_bind_service";
        NoNewPrivileges = true;
        LimitNOFILE = 1048576;
        PrivateTmp = true;
        PrivateDevices = true;
        ProtectHome = if secretInHome then "read-only" else true;
        ProtectSystem = "full";
        ReadWriteDirectories = cfg.dataDir;
        TimeoutStopSec = "5s";
        EnvironmentFile = optional (cfg.secretEnvFile != null) cfg.secretEnvFile;
        StateDirectory = optional (cfg.dataDir == "/var/lib/ipfs-cluster") "ipfs-cluster";
        StateDirectoryMode = "0700";
      };
      preStart = ''
        ${optionalString (cfg.secretFile != null) ''
        read -r CLUSTER_SECRET <${cfg.secretFile}
        export CLUSTER_SECRET
        ''}
        if [[ ! -f ${cfg.dataDir}/service.json ]]; then
          ${cfg.package}/bin/ipfs-cluster-service init \
            --consensus ${cfg.consensus} \
            ${optionalString (cfg.bootstrapPeers != [ ]) "--peers ${concatStringsSep "," cfg.bootstrapPeers}"}
        fi
      '';
      script = ''
        ${optionalString (cfg.secretFile != null) ''
        read -r CLUSTER_SECRET <${cfg.secretFile}
        export CLUSTER_SECRET
        ''}
        exec ${cfg.package}/bin/ipfs-cluster-service daemon
      '';
    };
  };
}