summary refs log tree commit diff
path: root/nixos/modules/services/databases/pgmanage.nix
blob: 8508e76b5cd6eed4d3df296c93de6c178cb3b3d4 (plain) (blame)
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
{ lib, pkgs, config, ... } :

with lib;

let
  cfg = config.services.pgmanage;

  confFile = pkgs.writeTextFile {
    name = "pgmanage.conf";
    text =  ''
      connection_file = ${pgmanageConnectionsFile}

      allow_custom_connections = ${builtins.toJSON cfg.allowCustomConnections}

      pgmanage_port = ${toString cfg.port}

      super_only = ${builtins.toJSON cfg.superOnly}

      ${optionalString (cfg.loginGroup != null) "login_group = ${cfg.loginGroup}"}

      login_timeout = ${toString cfg.loginTimeout}

      web_root = ${cfg.package}/etc/pgmanage/web_root

      sql_root = ${cfg.sqlRoot}

      ${optionalString (cfg.tls != null) ''
      tls_cert = ${cfg.tls.cert}
      tls_key = ${cfg.tls.key}
      ''}

      log_level = ${cfg.logLevel}
    '';
  };

  pgmanageConnectionsFile = pkgs.writeTextFile {
    name = "pgmanage-connections.conf";
    text = concatStringsSep "\n"
      (mapAttrsToList (name : conn : "${name}: ${conn}") cfg.connections);
  };

  pgmanage = "pgmanage";

in {

  options.services.pgmanage = {
    enable = mkEnableOption "PostgreSQL Administration for the web";

    package = mkOption {
      type = types.package;
      default = pkgs.pgmanage;
      defaultText = "pkgs.pgmanage";
      description = ''
        The pgmanage package to use.
      '';
    };

    connections = mkOption {
      type = types.attrsOf types.str;
      default = {};
      example = {
        nuc-server  = "hostaddr=192.168.0.100 port=5432 dbname=postgres";
        mini-server = "hostaddr=127.0.0.1 port=5432 dbname=postgres sslmode=require";
      };
      description = ''
        pgmanage requires at least one PostgreSQL server be defined.
        </para><para>
        Detailed information about PostgreSQL connection strings is available at:
        <link xlink:href="http://www.postgresql.org/docs/current/static/libpq-connect.html"/>
        </para><para>
        Note that you should not specify your user name or password. That
        information will be entered on the login screen. If you specify a
        username or password, it will be removed by pgmanage before attempting to
        connect to a database.
      '';
    };

    allowCustomConnections = mkOption {
      type = types.bool;
      default = false;
      description = ''
        This tells pgmanage whether or not to allow anyone to use a custom
        connection from the login screen.
      '';
    };

    port = mkOption {
      type = types.int;
      default = 8080;
      description = ''
        This tells pgmanage what port to listen on for browser requests.
      '';
    };

    localOnly = mkOption {
      type = types.bool;
      default = true;
      description = ''
        This tells pgmanage whether or not to set the listening socket to local
        addresses only.
      '';
    };

    superOnly = mkOption {
      type = types.bool;
      default = true;
      description = ''
        This tells pgmanage whether or not to only allow super users to
        login. The recommended value is true and will restrict users who are not
        super users from logging in to any PostgreSQL instance through
        pgmanage. Note that a connection will be made to PostgreSQL in order to
        test if the user is a superuser.
      '';
    };

    loginGroup = mkOption {
      type = types.nullOr types.str;
      default = null;
      description = ''
        This tells pgmanage to only allow users in a certain PostgreSQL group to
        login to pgmanage. Note that a connection will be made to PostgreSQL in
        order to test if the user is a member of the login group.
      '';
    };

    loginTimeout = mkOption {
      type = types.int;
      default = 3600;
      description = ''
        Number of seconds of inactivity before user is automatically logged
        out.
      '';
    };

    sqlRoot = mkOption {
      type = types.str;
      default = "/var/lib/pgmanage";
      description = ''
        This tells pgmanage where to put the SQL file history. All tabs are saved
        to this location so that if you get disconnected from pgmanage you
        don't lose your work.
      '';
    };

    tls = mkOption {
      type = types.nullOr (types.submodule {
        options = {
          cert = mkOption {
            type = types.str;
            description = "TLS certificate";
          };
          key = mkOption {
            type = types.str;
            description = "TLS key";
          };
        };
      });
      default = null;
      description = ''
        These options tell pgmanage where the TLS Certificate and Key files
        reside. If you use these options then you'll only be able to access
        pgmanage through a secure TLS connection. These options are only
        necessary if you wish to connect directly to pgmanage using a secure TLS
        connection. As an alternative, you can set up pgmanage in a reverse proxy
        configuration. This allows your web server to terminate the secure
        connection and pass on the request to pgmanage. You can find help to set
        up this configuration in:
        <link xlink:href="https://github.com/pgManage/pgManage/blob/master/INSTALL_NGINX.md"/>
      '';
    };

    logLevel = mkOption {
      type = types.enum ["error" "warn" "notice" "info"];
      default = "error";
      description = ''
        Verbosity of logs
      '';
    };
  };

  config = mkIf cfg.enable {
    systemd.services.pgmanage = {
      description = "pgmanage - PostgreSQL Administration for the web";
      wants    = [ "postgresql.service" ];
      after    = [ "postgresql.service" ];
      wantedBy = [ "multi-user.target" ];
      serviceConfig = {
        User         = pgmanage;
        Group        = pgmanage;
        ExecStart    = "${pkgs.pgmanage}/sbin/pgmanage -c ${confFile}" +
                       optionalString cfg.localOnly " --local-only=true";
      };
    };
    users = {
      users.${pgmanage} = {
        name  = pgmanage;
        group = pgmanage;
        home  = cfg.sqlRoot;
        createHome = true;
        isSystemUser = true;
      };
      groups.${pgmanage} = {
        name = pgmanage;
      };
    };
  };
}