Merge pull request #117073 from sternenseemann/inspircd-3.9.0

inspircd: init at 3.9.0
This commit is contained in:
Profpatsch 2021-03-23 11:25:58 +01:00 committed by GitHub
commit c25ffa8b76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 382 additions and 0 deletions

View file

@ -682,6 +682,7 @@
./services/networking/i2p.nix
./services/networking/icecream/scheduler.nix
./services/networking/icecream/daemon.nix
./services/networking/inspircd.nix
./services/networking/iodine.nix
./services/networking/iperf3.nix
./services/networking/ircd-hybrid/default.nix

View file

@ -0,0 +1,62 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.inspircd;
configFile = pkgs.writeText "inspircd.conf" cfg.config;
in {
meta = {
maintainers = [ lib.maintainers.sternenseemann ];
};
options = {
services.inspircd = {
enable = lib.mkEnableOption "InspIRCd";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.inspircd;
defaultText = lib.literalExample "pkgs.inspircd";
example = lib.literalExample "pkgs.inspircdMinimal";
description = ''
The InspIRCd package to use. This is mainly useful
to specify an overridden version of the
<literal>pkgs.inspircd</literal> dervivation, for
example if you want to use a more minimal InspIRCd
distribution with less modules enabled or with
modules enabled which can't be distributed in binary
form due to licensing issues.
'';
};
config = lib.mkOption {
type = lib.types.lines;
description = ''
Verbatim <literal>inspircd.conf</literal> file.
For a list of options, consult the
<link xlink:href="https://docs.inspircd.org/3/configuration/">InspIRCd documentation</link>, the
<link xlink:href="https://docs.inspircd.org/3/modules/">Module documentation</link>
and the example configuration files distributed
with <literal>pkgs.inspircd.doc</literal>
'';
};
};
};
config = lib.mkIf cfg.enable {
systemd.services.inspircd = {
description = "InspIRCd - the stable, high-performance and modular Internet Relay Chat Daemon";
wantedBy = [ "multi-user.target" ];
requires = [ "network.target" ];
serviceConfig = {
Type = "simple";
ExecStart = ''
${lib.getBin cfg.package}/bin/inspircd start --config ${configFile} --nofork --nopid
'';
DynamicUser = true;
};
};
};
}

View file

@ -176,6 +176,7 @@ in
initrd-network-ssh = handleTest ./initrd-network-ssh {};
initrdNetwork = handleTest ./initrd-network.nix {};
initrd-secrets = handleTest ./initrd-secrets.nix {};
inspircd = handleTest ./inspircd.nix {};
installer = handleTest ./installer.nix {};
iodine = handleTest ./iodine.nix {};
ipfs = handleTest ./ipfs.nix {};

93
nixos/tests/inspircd.nix Normal file
View file

@ -0,0 +1,93 @@
let
clients = [
"ircclient1"
"ircclient2"
];
server = "inspircd";
ircPort = 6667;
channel = "nixos-cat";
iiDir = "/tmp/irc";
in
import ./make-test-python.nix ({ pkgs, lib, ... }: {
name = "inspircd";
nodes = {
"${server}" = {
networking.firewall.allowedTCPPorts = [ ircPort ];
services.inspircd = {
enable = true;
package = pkgs.inspircdMinimal;
config = ''
<bind address="" port="${toString ircPort}" type="clients">
<connect name="main" allow="*" pingfreq="15">
'';
};
};
} // lib.listToAttrs (builtins.map (client: lib.nameValuePair client {
imports = [
./common/user-account.nix
];
systemd.services.ii = {
requires = [ "network.target" ];
wantedBy = [ "default.target" ];
serviceConfig = {
Type = "simple";
ExecPreStartPre = "mkdir -p ${iiDir}";
ExecStart = ''
${lib.getBin pkgs.ii}/bin/ii -n ${client} -s ${server} -i ${iiDir}
'';
User = "alice";
};
};
}) clients);
testScript =
let
msg = client: "Hello, my name is ${client}";
clientScript = client: [
''
${client}.wait_for_unit("network.target")
${client}.systemctl("start ii")
${client}.wait_for_unit("ii")
${client}.wait_for_file("${iiDir}/${server}/out")
''
# wait until first PING from server arrives before joining,
# so we don't try it too early
''
${client}.wait_until_succeeds("grep 'PING' ${iiDir}/${server}/out")
''
# join ${channel}
''
${client}.succeed("echo '/j #${channel}' > ${iiDir}/${server}/in")
${client}.wait_for_file("${iiDir}/${server}/#${channel}/in")
''
# send a greeting
''
${client}.succeed(
"echo '${msg client}' > ${iiDir}/${server}/#${channel}/in"
)
''
# check that all greetings arrived on all clients
] ++ builtins.map (other: ''
${client}.succeed(
"grep '${msg other}$' ${iiDir}/${server}/#${channel}/out"
)
'') clients;
# foldl', but requires a non-empty list instead of a start value
reduce = f: list:
builtins.foldl' f (builtins.head list) (builtins.tail list);
in ''
start_all()
${server}.wait_for_open_port(${toString ircPort})
# run clientScript for all clients so that every list
# entry is executed by every client before advancing
# to the next one.
'' + lib.concatStrings
(reduce
(lib.zipListsWith (cs: c: cs + c))
(builtins.map clientScript clients));
})

View file

@ -0,0 +1,221 @@
let
# inspircd ships a few extra modules that users can load
# via configuration. Upstream thus recommends to ship as
# many of them as possible. There is however a problem:
# inspircd is licensed under the GPL version 2 only and
# some modules link libraries that are incompatible with
# the GPL 2. Therefore we can't provide them as binaries
# via our binary-caches, but users should still be able
# to override this package and build the incompatible
# modules themselves.
#
# This means for us we need to a) prevent hydra from
# building a module set with a GPL incompatibility
# and b) dynamically figure out the largest possible
# set of modules to use depending on stdenv, because
# the used libc needs to be compatible as well.
#
# For an overview of all modules and their licensing
# situation, see https://docs.inspircd.org/packaging/
# Predicate for checking license compatibility with
# GPLv2. Since this is _only_ used for libc compatibility
# checking, only whitelist licenses used by notable
# libcs in nixpkgs (musl and glibc).
compatible = lib: drv:
lib.any (lic: lic == drv.meta.license) [
lib.licenses.mit # musl
lib.licenses.lgpl2Plus # glibc
];
# compatible if libc is compatible
libcModules = [
"regex_posix"
"sslrehashsignal"
];
# compatible if libc++ is compatible
# TODO(sternenseemann):
# we could enable "regex_stdlib" automatically, but only if
# we are using libcxxStdenv which is compatible with GPLv2,
# since the gcc libstdc++ license is GPLv2-incompatible
libcxxModules = [
"regex_stdlib"
];
compatibleModules = lib: stdenv: [
# GPLv2 compatible dependencies
"argon2"
"ldap"
"mysql"
"pgsql"
"regex_pcre"
"regex_re2"
"regex_tre"
"sqlite3"
"ssl_gnutls"
] ++ lib.optionals (compatible lib stdenv.cc.libc) libcModules;
in
{ lib
, stdenv
, fetchFromGitHub
, nixosTests
, perl
, pkg-config
, libargon2
, openldap
, postgresql
, libmysqlclient
, pcre
, tre
, re2
, sqlite
, gnutls
, libmaxminddb
, openssl
, mbedtls
# For a full list of module names, see https://docs.inspircd.org/packaging/
, extraModules ? compatibleModules lib stdenv
}:
let
extras = {
# GPLv2 compatible
argon2 = [
(libargon2 // {
meta = libargon2.meta // {
# use libargon2 as CC0 since ASL20 is GPLv2-incompatible
# updating this here is important that meta.license is accurate
# libargon2 is licensed under either ASL20 or CC0.
license = lib.licenses.cc0;
};
})
];
ldap = [ openldap ];
mysql = [ libmysqlclient ];
pgsql = [ postgresql ];
regex_pcre = [ pcre ];
regex_re2 = [ re2 ];
regex_tre = [ tre ];
sqlite3 = [ sqlite ];
ssl_gnutls = [ gnutls ];
# depends on stdenv.cc.libc
regex_posix = [];
sslrehashsignal = [];
# depends on used libc++
regex_stdlib = [];
# GPLv2 incompatible
geo_maxmind = [ libmaxminddb ];
ssl_mbedtls = [ mbedtls ];
ssl_openssl = [ openssl ];
};
# buildInputs necessary for the enabled extraModules
extraInputs = lib.concatMap
(m: extras."${m}" or (builtins.throw "Unknown extra module ${m}"))
extraModules;
# if true, we can't provide a binary version of this
# package without violating the GPL 2
gpl2Conflict =
let
allowed = compatibleModules lib stdenv;
in
!lib.all (lib.flip lib.elem allowed) extraModules;
# return list of the license(s) of the given derivation
getLicenses = drv:
let
lics = drv.meta.license or [];
in
if lib.isAttrs lics || lib.isString lics
then [ lics ]
else lics;
# Whether any member of list1 is also member of list2, i. e. set intersection.
anyMembers = list1: list2:
lib.any (m1: lib.elem m1 list2) list1;
in
stdenv.mkDerivation rec {
pname = "inspircd";
version = "3.9.0";
src = fetchFromGitHub {
owner = pname;
repo = pname;
rev = "v${version}";
sha256 = "0x3paasf4ynx4ddky2nq613vyirbhfnxzkjq148k7154pz3q426s";
};
outputs = [ "bin" "lib" "man" "doc" "out" ];
nativeBuildInputs = [
perl
pkg-config
];
buildInputs = extraInputs;
configurePhase = ''
patchShebangs configure make/*.pl
# configure is executed twice, once to set the extras
# to use and once to do the Makefile setup
./configure \
--enable-extras \
${lib.escapeShellArg (lib.concatStringsSep " " extraModules)}
# this manually sets the flags instead of using configureFlags, because otherwise stdenv passes flags like --bindir, which make configure fail
./configure \
--disable-auto-extras \
--distribution-label nixpkgs${version} \
--uid 0 \
--gid 0 \
--binary-dir ${placeholder "bin"}/bin \
--config-dir /etc/inspircd \
--data-dir ${placeholder "lib"}/lib/inspircd \
--example-dir ${placeholder "doc"}/share/doc/inspircd \
--log-dir /var/log/inspircd \
--manual-dir ${placeholder "man"}/share/man/man1 \
--module-dir ${placeholder "lib"}/lib/inspircd \
--runtime-dir /var/run \
--script-dir ${placeholder "bin"}/share/inspircd \
'';
postInstall = ''
# for some reasons the executables are not executable
chmod +x $bin/bin/*
'';
enableParallelBuilding = true;
passthru.tests = {
nixos-test = nixosTests.inspircd;
};
meta = {
description = "A modular C++ IRC server";
license = [ lib.licenses.gpl2Only ]
++ lib.concatMap getLicenses extraInputs
++ lib.optionals (anyMembers extraModules libcModules) (getLicenses stdenv.cc.libc)
# FIXME(sternenseemann): get license of used lib(std)c++ somehow
++ lib.optional (anyMembers extraModules libcxxModules) "Unknown"
# Hack: Definitely prevent a hydra from building this package on
# a GPL 2 incompatibility even if it is not in a top-level attribute,
# but pulled in indirectly somehow.
++ lib.optional gpl2Conflict lib.licenses.unfree;
maintainers = [ lib.maintainers.sternenseemann ];
# windows is theoretically possible, but requires extra work
# which I am not willing to do and can't test.
# https://github.com/inspircd/inspircd/blob/master/win/README.txt
platforms = lib.platforms.unix;
homepage = "https://www.inspircd.org/";
} // lib.optionalAttrs gpl2Conflict {
# make sure we never distribute a GPLv2-violating module
# in binary form. They can be built locally of course.
hydraPlatforms = [];
};
}

View file

@ -18251,6 +18251,10 @@ in
theme-spring = callPackage ../servers/icingaweb2/theme-spring { };
};
inspircd = callPackage ../servers/irc/inspircd { };
inspircdMinimal = inspircd.override { extraModules = []; };
imgproxy = callPackage ../servers/imgproxy { };
ircdog = callPackage ../applications/networking/irc/ircdog { };