From d86c2c30c52fd3bcf971b9d3e370823135a2c8b7 Mon Sep 17 00:00:00 2001 From: Markus Kohlhase Date: Tue, 2 Sep 2014 17:08:56 +0200 Subject: [PATCH] prosody: packaged as a service Conflicts: nixos/modules/misc/ids.nix --- nixos/modules/misc/ids.nix | 4 + nixos/modules/module-list.nix | 1 + nixos/modules/services/networking/prosody.nix | 275 ++++++++++++++++++ pkgs/servers/xmpp/prosody/default.nix | 45 +++ pkgs/top-level/all-packages.nix | 7 +- pkgs/top-level/lua-packages.nix | 55 +++- 6 files changed, 384 insertions(+), 3 deletions(-) create mode 100644 nixos/modules/services/networking/prosody.nix create mode 100644 pkgs/servers/xmpp/prosody/default.nix diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index fa51f831481..8472821f786 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -155,6 +155,8 @@ consul = 145; mailpile = 146; + prosody = 148; + # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! nixbld = 30000; # start of range of uids @@ -276,6 +278,8 @@ uhub = 142; mailpile = 146; + prosody = 148; + # When adding a gid, make sure it doesn't match an existing uid. And don't use gids above 399! users = 100; diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 3db44a4d8de..ba30c61bb8d 100755 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -250,6 +250,7 @@ ./services/networking/polipo.nix ./services/networking/prayer.nix ./services/networking/privoxy.nix + ./services/networking/prosody.nix ./services/networking/quassel.nix ./services/networking/radicale.nix ./services/networking/radvd.nix diff --git a/nixos/modules/services/networking/prosody.nix b/nixos/modules/services/networking/prosody.nix new file mode 100644 index 00000000000..51089d00244 --- /dev/null +++ b/nixos/modules/services/networking/prosody.nix @@ -0,0 +1,275 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.prosody; + + sslOpts = { ... }: { + + options = { + + # TODO: require attribute + key = mkOption { + type = types.str; + description = "Path to the key file"; + }; + + # TODO: require attribute + cert = mkOption { + type = types.str; + description = "Path to the certificate file"; + }; + }; + }; + + moduleOpts = { + + roster = mkOption { + default = true; + description = "Allow users to have a roster"; + }; + + saslauth = mkOption { + default = true; + description = "Authentication for clients and servers. Recommended if you want to log in."; + }; + + tls = mkOption { + default = true; + description = "Add support for secure TLS on c2s/s2s connections"; + }; + + dialback = mkOption { + default = true; + description = "s2s dialback support"; + }; + + disco = mkOption { + default = true; + description = "Service discovery"; + }; + + legacyauth = mkOption { + default = true; + description = "Legacy authentication. Only used by some old clients and bots"; + }; + + version = mkOption { + default = true; + description = "Replies to server version requests"; + }; + + uptime = mkOption { + default = true; + description = "Report how long server has been running"; + }; + + time = mkOption { + default = true; + description = "Let others know the time here on this server"; + }; + + ping = mkOption { + default = true; + description = "Replies to XMPP pings with pongs"; + }; + + console = mkOption { + default = false; + description = "telnet to port 5582"; + }; + + bosh = mkOption { + default = false; + description = "Enable BOSH clients, aka 'Jabber over HTTP'"; + }; + + httpserver = mkOption { + default = false; + description = "Serve static files from a directory over HTTP"; + }; + + }; + + createSSLOptsStr = o: + if o ? key && o ? cert then + ''ssl = { key = "${o.key}"; certificate = "${o.cert}"; };'' + else ""; + + vHostOpts = { ... }: { + + options = { + + # TODO: require attribute + domain = mkOption { + type = types.str; + description = "Domain name"; + }; + + enabled = mkOption { + default = false; + description = "Whether to enable the virtual host"; + }; + + ssl = mkOption { + description = "Paths to SSL files"; + default = null; + options = [ sslOpts ]; + }; + + extraConfig = mkOption { + default = ''''; + description = "Additional virtual host specific configuration"; + }; + + }; + + }; + +in + +{ + + ###### interface + + options = { + + services.prosody = { + + enable = mkOption { + default = false; + description = "Whether to enable the prosody server"; + }; + + allowRegistration = mkOption { + default = false; + description = "Allow account creation"; + }; + + modules = moduleOpts; + + extraModules = mkOption { + description = "Enable custom modules"; + default = []; + }; + + virtualHosts = mkOption { + + description = "Define the virtual hosts"; + + type = types.loaOf types.optionSet; + + example = { + myhost = { + domain = "my-xmpp-example-host.org"; + enabled = true; + }; + }; + + default = { + localhost = { + domain = "localhost"; + enabled = true; + }; + }; + + options = [ vHostOpts ]; + }; + + ssl = mkOption { + description = "Paths to SSL files"; + default = null; + options = [ sslOpts ]; + }; + + admins = mkOption { + description = "List of administrators of the current host"; + example = [ "admin1@example.com" "admin2@example.com" ]; + default = []; + }; + + extraConfig = mkOption { + default = ''''; + description = "Additional prosody configuration"; + }; + + }; + }; + + + ###### implementation + + config = mkIf cfg.enable { + + environment.systemPackages = [ pkgs.prosody ]; + + environment.etc."prosody/prosody.cfg.lua".text = '' + + pidfile = "/var/lib/prosody/prosody.pid" + + + log = "*syslog" + + data_path = "/var/lib/prosody" + + allow_registration = ${ if cfg.allowRegistration then "true" else "false" }; + + ${ optionalString cfg.modules.console "console_enabled = true;" } + + ${ optionalString (cfg.ssl != null) (createSSLOptsStr cfg.ssl) } + + admins = { ${lib.concatStringsSep ", " (map (n: "\"${n}\"") cfg.admins) } }; + + modules_enabled = { + + ${ lib.concatStringsSep "\n\ \ " (lib.mapAttrsToList + (name: val: optionalString val ''"${name}";'') + cfg.modules) } + + ${ optionalString cfg.allowRegistration "\"register\"\;" } + + ${ lib.concatStringsSep "\n" (map (x: "\"${x}\";") cfg.extraModules)} + + "posix"; + }; + + ${ cfg.extraConfig } + + ${ lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: '' + VirtualHost "${v.domain}" + enabled = ${if v.enabled then "true" else "false"}; + ${ optionalString (v.ssl != null) (createSSLOptsStr v.ssl) } + ${ v.extraConfig } + '') cfg.virtualHosts) } + ''; + + users.extraUsers.prosody = { + uid = config.ids.uids.prosody; + description = "Prosody user"; + createHome = true; + group = "prosody"; + home = "/var/lib/prosody"; + }; + + users.extraGroups.prosody = { + gid = config.ids.gids.prosody; + }; + + systemd.services.prosody = { + + description = "Prosody XMPP server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = "prosody"; + PIDFile = "/var/lib/prosody/prosody.pid"; + ExecStart = "${pkgs.prosody}/bin/prosodyctl start"; + }; + + }; + + }; + +} diff --git a/pkgs/servers/xmpp/prosody/default.nix b/pkgs/servers/xmpp/prosody/default.nix new file mode 100644 index 00000000000..4bd1b594c26 --- /dev/null +++ b/pkgs/servers/xmpp/prosody/default.nix @@ -0,0 +1,45 @@ +{ stdenv, fetchurl, lua5, luasocket, luasec, luaexpat, luafilesystem, libidn, openssl, makeWrapper }: + +let + libs = [ luasocket luasec luaexpat luafilesystem ]; + getPath = lib : type : "${lib}/lib/lua/${lua5.luaversion}/?.${type};${lib}/share/lua/${lua5.luaversion}/?.${type}"; + getLuaPath = lib : getPath lib "lua"; + getLuaCPath = lib : getPath lib "so"; + luaPath = stdenv.lib.concatStringsSep ";" (map getLuaPath libs); + luaCPath = stdenv.lib.concatStringsSep ";" (map getLuaCPath libs); +in + +stdenv.mkDerivation rec { + version = "0.9.4"; + name = "prosody-${version}"; + src = fetchurl { + url = "http://prosody.im/downloads/source/${name}.tar.gz"; + sha256 = "be87cf31901a25477869b4ebd52e298f63a5effacae526911a0be876cc82e1c6"; + }; + + buildInputs = [ lua5 luasocket luasec luaexpat libidn openssl makeWrapper ]; + + configureFlags = [ + "--ostype=linux" + "--with-lua-include=${lua5}/include" + "--with-lua=${lua5}" + ]; + + postInstall = '' + wrapProgram $out/bin/prosody \ + --set LUA_PATH '"${luaPath};"' \ + --set LUA_CPATH '"${luaCPath};"' + wrapProgram $out/bin/prosodyctl \ + --add-flags '--config "/etc/prosody/prosody.cfg.lua"' \ + --set LUA_PATH '"${luaPath};"' \ + --set LUA_CPATH '"${luaCPath};"' + ''; + + meta = { + description = "Open-source XMPP application server written in Lua"; + license = stdenv.lib.licenses.mit; + homepage = http://www.prosody.im; + platforms = stdenv.lib.platforms.linux; + maintainers = [ stdenv.lib.maintainers.flosse ]; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index f8382928e0b..593156215d2 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -3771,7 +3771,6 @@ let lua = lua5; lua51Packages = recurseIntoAttrs (callPackage ./lua-packages.nix { lua = lua5_1; }); - lua52Packages = recurseIntoAttrs (callPackage ./lua-packages.nix { lua = lua5_2; }); luaPackages = lua52Packages; @@ -7137,6 +7136,12 @@ let erlang = erlangR16; }; + prosody = recurseIntoAttrs ( + callPackage ../servers/xmpp/prosody { + lua5 = lua5_1; + inherit (lua51Packages) luasocket luasec luaexpat luafilesystem; + }); + elasticmq = callPackage ../servers/elasticmq { }; etcdctl = callPackage ../development/tools/etcdctl { }; diff --git a/pkgs/top-level/lua-packages.nix b/pkgs/top-level/lua-packages.nix index 8a44a997c07..a69009a34fe 100644 --- a/pkgs/top-level/lua-packages.nix +++ b/pkgs/top-level/lua-packages.nix @@ -7,7 +7,7 @@ { fetchurl, stdenv, lua, callPackage, unzip, zziplib, pcre, oniguruma, gnulib, tre, glibc, -sqlite }: +sqlite, openssl, expat }: let isLua51 = lua.luaversion == "5.1"; @@ -23,7 +23,32 @@ let inherit lua; }; - luafilesystem = buildLuaPackage { + luaexpat = buildLuaPackage rec { + version = "1.3.0"; + name = "expat-${version}"; + isLibrary = true; + src = fetchurl { + url = "https://matthewwild.co.uk/projects/luaexpat/luaexpat-${version}.tar.gz"; + sha256 = "1hvxqngn0wf5642i5p3vcyhg3pmp102k63s9ry4jqyyqc1wkjq6h"; + }; + + buildInputs = [ expat ]; + + preBuild = '' + makeFlagsArray=( + LUA_LDIR="$out/share/lua/${lua.luaversion}" + LUA_INC="-I${lua}/include" LUA_CDIR="$out/lib/lua/${lua.luaversion}" + EXPAT_INC="-I${expat}/include"); + ''; + + meta = { + homepage = "http://matthewwild.co.uk/projects/luaexpat"; + hydraPlatforms = stdenv.lib.platforms.linux; + maintainers = [ stdenv.lib.maintainers.flosse ]; + }; + }; + + luafilesystem = buildLuaPackage rec { name = "filesystem-1.6.2"; src = fetchurl { url = "https://github.com/keplerproject/luafilesystem/archive/v1_6_2.tar.gz"; @@ -36,6 +61,32 @@ let }; }; + luasec = buildLuaPackage rec { + version = "0.5"; + name = "sec-${version}"; + src = fetchurl { + url = "https://github.com/brunoos/luasec/archive/luasec-${version}.tar.gz"; + sha256 = "08rm12cr1gjdnbv2jpk7xykby9l292qmz2v0dfdlgb4jfj7mk034"; + }; + + buildInputs = [ openssl ]; + + preBuild = '' + makeFlagsArray=( + linux + LUAPATH="$out/lib/lua/${lua.luaversion}" + LUACPATH="$out/lib/lua/${lua.luaversion}" + INC_PATH="-I${lua}/include" + LIB_PATH="-L$out/lib"); + ''; + + meta = { + homepage = "https://github.com/brunoos/luasec"; + hydraPlatforms = stdenv.lib.platforms.linux; + maintainers = [ stdenv.lib.maintainers.flosse ]; + }; + }; + luasocket = buildLuaPackage rec { name = "socket-${version}"; version = "2.0.2";