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 { };