summaryrefslogtreecommitdiffstats
path: root/nixos/modules/services/misc/orthanc.nix
blob: 9cf21c1e18d545567de7498a646907b199ab7f46 (plain)
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
{
  config,
  options,
  lib,
  pkgs,
  ...
}:
let
  inherit (lib) types;

  cfg = config.services.orthanc;
  opt = options.services.orthanc;

  settingsFormat = pkgs.formats.json { };
in
{
  options = {
    services.orthanc = {
      enable = lib.mkEnableOption "Orthanc server";
      package = lib.mkPackageOption pkgs "orthanc" { };

      stateDir = lib.mkOption {
        type = types.path;
        default = "/var/lib/orthanc";
        example = "/home/foo";
        description = "State directory of Orthanc.";
      };

      environment = lib.mkOption {
        type = types.attrsOf types.str;
        default = {
        };
        example = ''
          {
            ORTHANC_NAME = "Orthanc server";
          }
        '';
        description = ''
          Extra environment variables
          For more details see <https://orthanc.uclouvain.be/book/users/configuration.html>
        '';
      };

      environmentFile = lib.mkOption {
        description = ''
          Environment file to be passed to the systemd service.
          Useful for passing secrets to the service to prevent them from being
          world-readable in the Nix store.
        '';
        type = lib.types.nullOr lib.types.path;
        default = null;
        example = "/var/lib/secrets/orthancSecrets";
      };

      settings = lib.mkOption {
        type = lib.types.submodule {
          freeformType = settingsFormat.type;
        };
        default = {
          HttpPort = lib.mkDefault 8042;
          IndexDirectory = lib.mkDefault "/var/lib/orthanc/";
          StorageDirectory = lib.mkDefault "/var/lib/orthanc/";
        };
        example = {
          Name = "My Orthanc Server";
          HttpPort = 12345;
        };
        description = ''
          Configuration written to a json file that is read by orthanc.
          See <https://orthanc.uclouvain.be/book/index.html> for more.
        '';
      };

      openFirewall = lib.mkOption {
        type = types.bool;
        default = false;
        description = ''
          Whether to open the firewall for Orthanc.
          This adds `services.orthanc.settings.HttpPort` to `networking.firewall.allowedTCPPorts`.
        '';
      };
    };
  };

  config = lib.mkIf cfg.enable {
    services.orthanc.settings = opt.settings.default;

    systemd.services.orthanc = {
      description = "Orthanc is a lightweight, RESTful DICOM server for healthcare and medical research";
      wantedBy = [ "multi-user.target" ];
      after = [ "network.target" ];

      environment = cfg.environment;

      serviceConfig =
        let
          config-json = settingsFormat.generate "orthanc-config.json" (cfg.settings);
        in
        {
          ExecStart = "${lib.getExe cfg.package} ${config-json}";
          EnvironmentFile = lib.optional (cfg.environmentFile != null) cfg.environmentFile;
          WorkingDirectory = cfg.stateDir;
          BindReadOnlyPaths = [
            "-/etc/localtime"
          ];
          StateDirectory = "orthanc";
          RuntimeDirectory = "orthanc";
          RuntimeDirectoryMode = "0755";
          PrivateTmp = true;
          DynamicUser = true;
          DevicePolicy = "closed";
          LockPersonality = true;
          PrivateUsers = true;
          ProtectHome = true;
          ProtectHostname = true;
          ProtectKernelLogs = true;
          ProtectKernelModules = true;
          ProtectKernelTunables = true;
          ProtectControlGroups = true;
          RestrictNamespaces = true;
          RestrictRealtime = true;
          SystemCallArchitectures = "native";
          UMask = "0077";
        };
    };

    networking.firewall = lib.mkIf cfg.openFirewall { allowedTCPPorts = [ cfg.settings.HttpPort ]; };

    # Orthanc requires /etc/localtime to be present
    time.timeZone = lib.mkDefault "UTC";
  };

  meta.maintainers = [ ];
}