diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 961b6aca4f08..e7609354ac4c 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -191,6 +191,7 @@
./services/databases/openldap.nix
./services/databases/opentsdb.nix
./services/databases/postage.nix
+ ./services/databases/pgmanage.nix
./services/databases/postgresql.nix
./services/databases/redis.nix
./services/databases/riak.nix
diff --git a/nixos/modules/services/databases/pgmanage.nix b/nixos/modules/services/databases/pgmanage.nix
new file mode 100644
index 000000000000..db5cc01a054c
--- /dev/null
+++ b/nixos/modules/services/databases/pgmanage.nix
@@ -0,0 +1,205 @@
+{ 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 (!isNull cfg.loginGroup) "login_group = ${cfg.loginGroup}"}
+
+ login_timeout = ${toString cfg.loginTimeout}
+
+ web_root = ${cfg.package}/etc/pgmanage/web_root
+
+ data_root = ${cfg.dataRoot}
+
+ ${optionalString (!isNull cfg.tls) ''
+ 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.
+
+ Detailed information about PostgreSQL connection strings is available at:
+
+
+ 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.
+ '';
+ };
+
+ dataRoot = 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:
+
+ '';
+ };
+
+ 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.dataRoot;
+ createHome = true;
+ };
+ groups."${pgmanage}" = {
+ name = pgmanage;
+ };
+ };
+ };
+}
diff --git a/nixos/modules/services/databases/postage.nix b/nixos/modules/services/databases/postage.nix
index d49c9a83a46f..0b2f3c6b0274 100644
--- a/nixos/modules/services/databases/postage.nix
+++ b/nixos/modules/services/databases/postage.nix
@@ -178,6 +178,11 @@ in {
};
config = mkIf cfg.enable {
+ warnings = [
+ ''postage has been deprecated in favour of pgmanage and will be removed in NixOS-18.03.
+ To get rid of this warning change your 'services.postage' options to 'services.pgmanage'.''
+ ];
+
systemd.services.postage = {
description = "postage - PostgreSQL Administration for the web";
wants = [ "postgresql.service" ];
diff --git a/nixos/release.nix b/nixos/release.nix
index 1d162d96f4e4..e99aaf277157 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -299,6 +299,7 @@ in rec {
tests.peerflix = callTest tests/peerflix.nix {};
tests.php-pcre = callTest tests/php-pcre.nix {};
tests.postgresql = callSubTests tests/postgresql.nix {};
+ tests.pgmanage = callTest tests/pgmanage.nix {};
#tests.pgjwt = callTest tests/pgjwt.nix {};
tests.printing = callTest tests/printing.nix {};
tests.prometheus = callTest tests/prometheus.nix {};
diff --git a/nixos/tests/pgmanage.nix b/nixos/tests/pgmanage.nix
new file mode 100644
index 000000000000..110cbd5c5b40
--- /dev/null
+++ b/nixos/tests/pgmanage.nix
@@ -0,0 +1,39 @@
+import ./make-test.nix ({ pkgs, ... } :
+let
+ role = "test";
+ password = "secret";
+ conn = "local";
+in
+{
+ name = "pgmanage";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ basvandijk ];
+ };
+ nodes = {
+ one = { config, pkgs, ... }: {
+ services = {
+ postgresql = {
+ enable = true;
+ initialScript = pkgs.writeText "pg-init-script" ''
+ CREATE ROLE ${role} SUPERUSER LOGIN PASSWORD '${password}';
+ '';
+ };
+ pgmanage = {
+ enable = true;
+ connections = {
+ "${conn}" = "hostaddr=127.0.0.1 port=${toString config.services.postgresql.port} dbname=postgres";
+ };
+ };
+ };
+ };
+ };
+
+ testScript = ''
+ startAll;
+ $one->waitForUnit("default.target");
+ $one->requireActiveUnit("pgmanage.service");
+
+ # Test if we can log in.
+ $one->waitUntilSucceeds("curl 'http://localhost:8080/pgmanage/auth' --data 'action=login&connname=${conn}&username=${role}&password=${password}' --fail");
+ '';
+})
diff --git a/pkgs/applications/misc/pgmanage/default.nix b/pkgs/applications/misc/pgmanage/default.nix
new file mode 100644
index 000000000000..fd66ce8fc31c
--- /dev/null
+++ b/pkgs/applications/misc/pgmanage/default.nix
@@ -0,0 +1,27 @@
+{ stdenv, fetchFromGitHub, runCommand, postgresql, openssl } :
+
+stdenv.mkDerivation rec {
+ name = "pgmanage-${version}";
+ version = "10.0.2";
+
+ src = fetchFromGitHub {
+ owner = "pgManage";
+ repo = "pgManage";
+ rev = "v${version}";
+ sha256 = "0g9kvhs9b6kc1s7j90fqv71amiy9v0w5p906yfvl0j7pf3ayq35a";
+ };
+
+ buildInputs = [ postgresql openssl ];
+
+ meta = with stdenv.lib; {
+ description = "A fast replacement for PGAdmin";
+ longDescription = ''
+ At the heart of Postage is a modern, fast, event-based C-binary, built in
+ the style of NGINX and Node.js. This heart makes Postage as fast as any
+ PostgreSQL interface can hope to be.
+ '';
+ homepage = https://github.com/pgManage/pgManage;
+ license = licenses.postgresql;
+ maintainers = [ maintainers.basvandijk ];
+ };
+}
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 87c724e787b3..233b2c1463ab 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -19024,6 +19024,7 @@ with pkgs;
opkg-utils = callPackage ../tools/package-management/opkg-utils { };
postage = callPackage ../applications/misc/postage { };
+ pgmanage = callPackage ../applications/misc/pgmanage { };
pgadmin = callPackage ../applications/misc/pgadmin { };