powerdns-admin: fix and add module
- Add the migrations directory to the package - Add postgres support to the package - Add a service for powerdns-admin Co-authored-by: Zhaofeng Li <hello@zhaofeng.li>
This commit is contained in:
parent
040d6eb51a
commit
368b22d09b
@ -36,6 +36,13 @@
|
||||
<link linkend="opt-services.filebeat.enable">services.filebeat</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/ngoduykhanh/PowerDNS-Admin">PowerDNS-Admin</link>,
|
||||
a web interface for the PowerDNS server. Available at
|
||||
<link xlink:href="options.html#opt-services.powerdns-admin.enable">services.powerdns-admin</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="sec-release-22.05-incompatibilities">
|
||||
|
@ -12,6 +12,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
|
||||
- [filebeat](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html), a lightweight shipper for forwarding and centralizing log data. Available as [services.filebeat](#opt-services.filebeat.enable).
|
||||
|
||||
- [PowerDNS-Admin](https://github.com/ngoduykhanh/PowerDNS-Admin), a web interface for the PowerDNS server. Available at [services.powerdns-admin](options.html#opt-services.powerdns-admin.enable).
|
||||
|
||||
## Backward Incompatibilities {#sec-release-22.05-incompatibilities}
|
||||
|
||||
- `pkgs.ghc` now refers to `pkgs.targetPackages.haskellPackages.ghc`.
|
||||
|
@ -1026,6 +1026,7 @@
|
||||
./services/web-apps/plantuml-server.nix
|
||||
./services/web-apps/plausible.nix
|
||||
./services/web-apps/pgpkeyserver-lite.nix
|
||||
./services/web-apps/powerdns-admin.nix
|
||||
./services/web-apps/matomo.nix
|
||||
./services/web-apps/moinmoin.nix
|
||||
./services/web-apps/openwebrx.nix
|
||||
|
149
nixos/modules/services/web-apps/powerdns-admin.nix
Normal file
149
nixos/modules/services/web-apps/powerdns-admin.nix
Normal file
@ -0,0 +1,149 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.powerdns-admin;
|
||||
|
||||
configText = ''
|
||||
${cfg.config}
|
||||
''
|
||||
+ optionalString (cfg.secretKeyFile != null) ''
|
||||
with open('${cfg.secretKeyFile}') as file:
|
||||
SECRET_KEY = file.read()
|
||||
''
|
||||
+ optionalString (cfg.saltFile != null) ''
|
||||
with open('${cfg.saltFile}') as file:
|
||||
SALT = file.read()
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.services.powerdns-admin = {
|
||||
enable = mkEnableOption "the PowerDNS web interface";
|
||||
|
||||
extraArgs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = literalExpression ''
|
||||
[ "-b" "127.0.0.1:8000" ]
|
||||
'';
|
||||
description = ''
|
||||
Extra arguments passed to powerdns-admin.
|
||||
'';
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = ''
|
||||
BIND_ADDRESS = '127.0.0.1'
|
||||
PORT = 8000
|
||||
SQLALCHEMY_DATABASE_URI = 'postgresql://powerdnsadmin@/powerdnsadmin?host=/run/postgresql'
|
||||
'';
|
||||
description = ''
|
||||
Configuration python file.
|
||||
See <link xlink:href="https://github.com/ngoduykhanh/PowerDNS-Admin/blob/v${pkgs.powerdns-admin.version}/configs/development.py">the example configuration</link>
|
||||
for options.
|
||||
'';
|
||||
};
|
||||
|
||||
secretKeyFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
example = "/etc/powerdns-admin/secret";
|
||||
description = ''
|
||||
The secret used to create cookies.
|
||||
This needs to be set, otherwise the default is used and everyone can forge valid login cookies.
|
||||
Set this to null to ignore this setting and configure it through another way.
|
||||
'';
|
||||
};
|
||||
|
||||
saltFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
example = "/etc/powerdns-admin/salt";
|
||||
description = ''
|
||||
The salt used for serialization.
|
||||
This should be set, otherwise the default is used.
|
||||
Set this to null to ignore this setting and configure it through another way.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.powerdns-admin = {
|
||||
description = "PowerDNS web interface";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "networking.target" ];
|
||||
|
||||
environment.FLASK_CONF = builtins.toFile "powerdns-admin-config.py" configText;
|
||||
environment.PYTHONPATH = pkgs.powerdns-admin.pythonPath;
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.powerdns-admin}/bin/powerdns-admin --pid /run/powerdns-admin/pid ${escapeShellArgs cfg.extraArgs}";
|
||||
ExecStartPre = "${pkgs.coreutils}/bin/env FLASK_APP=${pkgs.powerdns-admin}/share/powerdnsadmin/__init__.py ${pkgs.python3Packages.flask}/bin/flask db upgrade -d ${pkgs.powerdns-admin}/share/migrations";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
ExecStop = "${pkgs.coreutils}/bin/kill -TERM $MAINPID";
|
||||
PIDFile = "/run/powerdns-admin/pid";
|
||||
RuntimeDirectory = "powerdns-admin";
|
||||
User = "powerdnsadmin";
|
||||
Group = "powerdnsadmin";
|
||||
|
||||
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
|
||||
BindReadOnlyPaths = [
|
||||
"/nix/store"
|
||||
"-/etc/resolv.conf"
|
||||
"-/etc/nsswitch.conf"
|
||||
"-/etc/hosts"
|
||||
"-/etc/localtime"
|
||||
]
|
||||
++ (optional (cfg.secretKeyFile != null) cfg.secretKeyFile)
|
||||
++ (optional (cfg.saltFile != null) cfg.saltFile);
|
||||
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
|
||||
# ProtectClock= adds DeviceAllow=char-rtc r
|
||||
DeviceAllow = "";
|
||||
# Implies ProtectSystem=strict, which re-mounts all paths
|
||||
#DynamicUser = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateMounts = true;
|
||||
# Needs to start a server
|
||||
#PrivateNetwork = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
# Would re-mount paths ignored by temporary root
|
||||
#ProtectSystem = "strict";
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
# gunicorn needs setuid
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged @resources @keyring"
|
||||
# These got removed by the line above but are needed
|
||||
"@setuid @chown"
|
||||
];
|
||||
TemporaryFileSystem = "/:ro";
|
||||
# Does not work well with the temporary root
|
||||
#UMask = "0066";
|
||||
};
|
||||
};
|
||||
|
||||
users.groups.powerdnsadmin = { };
|
||||
users.users.powerdnsadmin = {
|
||||
description = "PowerDNS web interface user";
|
||||
isSystemUser = true;
|
||||
group = "powerdnsadmin";
|
||||
};
|
||||
};
|
||||
}
|
@ -381,6 +381,7 @@ in
|
||||
postgresql = handleTest ./postgresql.nix {};
|
||||
postgresql-wal-receiver = handleTest ./postgresql-wal-receiver.nix {};
|
||||
powerdns = handleTest ./powerdns.nix {};
|
||||
powerdns-admin = handleTest ./powerdns-admin.nix {};
|
||||
power-profiles-daemon = handleTest ./power-profiles-daemon.nix {};
|
||||
pppd = handleTest ./pppd.nix {};
|
||||
predictable-interface-names = handleTest ./predictable-interface-names.nix {};
|
||||
|
117
nixos/tests/powerdns-admin.nix
Normal file
117
nixos/tests/powerdns-admin.nix
Normal file
@ -0,0 +1,117 @@
|
||||
# Test powerdns-admin
|
||||
{ system ? builtins.currentSystem
|
||||
, config ? { }
|
||||
, pkgs ? import ../.. { inherit system config; }
|
||||
}:
|
||||
|
||||
with import ../lib/testing-python.nix { inherit system pkgs; };
|
||||
with pkgs.lib;
|
||||
let
|
||||
defaultConfig = ''
|
||||
BIND_ADDRESS = '127.0.0.1'
|
||||
PORT = 8000
|
||||
'';
|
||||
|
||||
makeAppTest = name: configs: makeTest {
|
||||
name = "powerdns-admin-${name}";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ Flakebi zhaofengli ];
|
||||
};
|
||||
|
||||
nodes.server = { pkgs, config, ... }: mkMerge ([
|
||||
{
|
||||
services.powerdns-admin = {
|
||||
enable = true;
|
||||
secretKeyFile = "/etc/powerdns-admin/secret";
|
||||
saltFile = "/etc/powerdns-admin/salt";
|
||||
};
|
||||
# It's insecure to have secrets in the world-readable nix store, but this is just a test
|
||||
environment.etc."powerdns-admin/secret".text = "secret key";
|
||||
environment.etc."powerdns-admin/salt".text = "salt";
|
||||
environment.systemPackages = [
|
||||
(pkgs.writeShellScriptBin "run-test" config.system.build.testScript)
|
||||
];
|
||||
}
|
||||
] ++ configs);
|
||||
|
||||
testScript = ''
|
||||
server.wait_for_unit("powerdns-admin.service")
|
||||
server.wait_until_succeeds("run-test", timeout=10)
|
||||
'';
|
||||
};
|
||||
|
||||
matrix = {
|
||||
backend = {
|
||||
mysql = {
|
||||
services.powerdns-admin = {
|
||||
config = ''
|
||||
${defaultConfig}
|
||||
SQLALCHEMY_DATABASE_URI = 'mysql://powerdnsadmin@/powerdnsadmin?unix_socket=/run/mysqld/mysqld.sock'
|
||||
'';
|
||||
};
|
||||
systemd.services.powerdns-admin = {
|
||||
after = [ "mysql.service" ];
|
||||
serviceConfig.BindPaths = "/run/mysqld";
|
||||
};
|
||||
|
||||
services.mysql = {
|
||||
enable = true;
|
||||
package = pkgs.mariadb;
|
||||
ensureDatabases = [ "powerdnsadmin" ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "powerdnsadmin";
|
||||
ensurePermissions = {
|
||||
"powerdnsadmin.*" = "ALL PRIVILEGES";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
postgresql = {
|
||||
services.powerdns-admin = {
|
||||
config = ''
|
||||
${defaultConfig}
|
||||
SQLALCHEMY_DATABASE_URI = 'postgresql://powerdnsadmin@/powerdnsadmin?host=/run/postgresql'
|
||||
'';
|
||||
};
|
||||
systemd.services.powerdns-admin = {
|
||||
after = [ "postgresql.service" ];
|
||||
serviceConfig.BindPaths = "/run/postgresql";
|
||||
};
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
ensureDatabases = [ "powerdnsadmin" ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "powerdnsadmin";
|
||||
ensurePermissions = {
|
||||
"DATABASE powerdnsadmin" = "ALL PRIVILEGES";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
listen = {
|
||||
tcp = {
|
||||
services.powerdns-admin.extraArgs = [ "-b" "127.0.0.1:8000" ];
|
||||
system.build.testScript = ''
|
||||
curl -sSf http://127.0.0.1:8000/
|
||||
'';
|
||||
};
|
||||
unix = {
|
||||
services.powerdns-admin.extraArgs = [ "-b" "unix:/run/powerdns-admin/http.sock" ];
|
||||
system.build.testScript = ''
|
||||
curl -sSf --unix-socket /run/powerdns-admin/http.sock http://somehost/
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
with matrix; {
|
||||
postgresql = makeAppTest "postgresql" [ backend.postgresql listen.tcp ];
|
||||
mysql = makeAppTest "mysql" [ backend.mysql listen.tcp ];
|
||||
unix-listener = makeAppTest "unix-listener" [ backend.postgresql listen.unix ];
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
{ lib, stdenv, fetchFromGitHub, mkYarnPackage, writeText, python3 }:
|
||||
{ lib, stdenv, fetchFromGitHub, mkYarnPackage, nixosTests, writeText, python3 }:
|
||||
|
||||
let
|
||||
version = "0.2.3";
|
||||
@ -23,8 +23,8 @@ let
|
||||
|
||||
pythonDeps = with python.pkgs; [
|
||||
flask flask_assets flask_login flask_sqlalchemy flask_migrate flask-seasurf flask_mail flask-sslify
|
||||
mysqlclient sqlalchemy
|
||||
configobj bcrypt requests ldap pyotp qrcode dnspython
|
||||
mysqlclient psycopg2 sqlalchemy
|
||||
cffi configobj cryptography bcrypt requests ldap pyotp qrcode dnspython
|
||||
gunicorn python3-saml pyopenssl pytz cssmin jsmin authlib bravado-core
|
||||
lima pytimeparse pyyaml
|
||||
];
|
||||
@ -91,6 +91,7 @@ in stdenv.mkDerivation rec {
|
||||
|
||||
postPatch = ''
|
||||
rm -r powerdnsadmin/static powerdnsadmin/assets.py
|
||||
sed -i "s/id:/'id':/" migrations/versions/787bdba9e147_init_db.py
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
@ -100,7 +101,7 @@ in stdenv.mkDerivation rec {
|
||||
wrapPythonPrograms
|
||||
|
||||
mkdir -p $out/share $out/bin
|
||||
cp -r powerdnsadmin $out/share/powerdnsadmin
|
||||
cp -r migrations powerdnsadmin $out/share/
|
||||
|
||||
ln -s ${assets} $out/share/powerdnsadmin/static
|
||||
ln -s ${assetsPy} $out/share/powerdnsadmin/assets.py
|
||||
@ -114,6 +115,12 @@ in stdenv.mkDerivation rec {
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
passthru = {
|
||||
# PYTHONPATH of all dependencies used by the package
|
||||
pythonPath = python3.pkgs.makePythonPath pythonDeps;
|
||||
tests = nixosTests.powerdns-admin;
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
description = "A PowerDNS web interface with advanced features";
|
||||
homepage = "https://github.com/ngoduykhanh/PowerDNS-Admin";
|
||||
|
Loading…
Reference in New Issue
Block a user