nixpkgs/nixos/tests/web-apps/movim/ejabberd-h2o.nix
2025-04-03 00:18:28 +07:00

275 lines
7.8 KiB
Nix

{ hostPkgs, lib, ... }:
let
movim = {
domain = "movim.local";
port = 8080;
info = "No ToS in tests";
description = "NixOS testing server";
};
ejabberd = {
domain = "ejabberd.local";
ports = {
c2s = 5222;
s2s = 5269;
http = 5280;
};
spoolDir = "/var/lib/ejabberd";
admin = rec {
JID = "${username}@${ejabberd.domain}";
username = "romeo";
password = "juliet";
};
};
# START OF EJABBERD CONFIG ##################################################
#
# Ejabberd has sparse defaults as it is a generic XMPP server. As such this
# config might be longer than expected for a test.
#
# Movim suggests: https://github.com/movim/movim/wiki/Configure ejabberd
#
# In the future this may be the default setup
# See: https://github.com/NixOS/nixpkgs/pull/312316
ejabberd_config_file =
let
settingsFormat = hostPkgs.formats.yaml { };
in
settingsFormat.generate "ejabberd.yml" {
loglevel = "info";
hide_sensitive_log_data = false;
hosts = [ ejabberd.domain ];
default_db = "mnesia";
acme.auto = false;
s2s_access = "s2s";
s2s_use_starttls = false;
new_sql_schema = true;
acl = {
admin = [
{ user = ejabberd.admin.JID; }
];
local.user_regexp = "";
loopback.ip = [
"127.0.0.1/8"
"::1/128"
];
};
access_rules = {
c2s = {
deny = "blocked";
allow = "all";
};
s2s = {
allow = "all";
};
local.allow = "local";
announce.allow = "admin";
configure.allow = "admin";
pubsub_createnode.allow = "local";
trusted_network.allow = "loopback";
};
api_permissions = {
"console commands" = {
from = [ "ejabberd_ctl" ];
who = "all";
what = "*";
};
};
shaper = {
normal = {
rate = 3000;
burst_size = 20000;
};
fast = 100000;
};
modules = {
mod_caps = { };
mod_disco = { };
mod_mam = { };
mod_http_upload = {
docroot = "${ejabberd.spoolDir}/uploads";
dir_mode = "0755";
file_mode = "0644";
get_url = "http://@HOST@/upload";
put_url = "http://@HOST@/upload";
max_size = 65536;
custom_headers = {
Access-Control-Allow-Origin = "http://@HOST@,http://${movim.domain}";
Access-Control-Allow-Methods = "GET,HEAD,PUT,OPTIONS";
Access-Control-Allow-Headers = "Content-Type";
};
};
# This PubSub block is required for Movim to work.
#
# See: https://github.com/movim/movim/wiki/Configure ejabberd#pubsub
mod_pubsub = {
hosts = [ "pubsub.@HOST@" ];
access_createnode = "pubsub_createnode";
ignore_pep_from_offline = false;
last_item_cache = false;
max_items_node = 2048;
default_node_config = {
max_items = 2048;
};
plugins = [
"flat"
"pep"
];
force_node_config = {
"storage:bookmarks".access_model = "whitelist";
"eu.siacs.conversations.axolotl.*".access_model = "open";
"urn:xmpp:bookmarks:0" = {
access_model = "whitelist";
send_last_published_item = "never";
max_items = "infinity";
persist_items = true;
};
"urn:xmpp:bookmarks:1" = {
access_model = "whitelist";
send_last_published_item = "never";
max_items = "infinity";
persist_items = true;
};
"urn:xmpp:pubsub:movim-public-subscription" = {
access_model = "whitelist";
max_items = "infinity";
persist_items = true;
};
"urn:xmpp:microblog:0" = {
notify_retract = true;
max_items = "infinity";
persist_items = true;
};
"urn:xmpp:microblog:0:comments*" = {
access_model = "open";
notify_retract = true;
max_items = "infinity";
persist_items = true;
};
};
};
mod_stream_mgmt = { };
};
listen = [
{
module = "ejabberd_c2s";
port = ejabberd.ports.c2s;
max_stanza_size = 262144;
access = "c2s";
starttls_required = false;
}
{
module = "ejabberd_s2s_in";
port = ejabberd.ports.s2s;
max_stanza_size = 524288;
shaper = "fast";
}
{
module = "ejabberd_http";
port = ejabberd.ports.http;
request_handlers = {
"/upload" = "mod_http_upload";
};
}
];
};
# END OF EJABBERD CONFIG ##################################################
in
{
name = "movim-ejabberd-h2o";
meta = {
maintainers = with lib.maintainers; [ toastal ];
};
nodes = {
server =
{ pkgs, ... }:
{
environment.systemPackages = [
# For testing
pkgs.websocat
];
services.movim = {
inherit (movim) domain port;
enable = true;
verbose = true;
podConfig = {
inherit (movim) description info;
xmppdomain = ejabberd.domain;
};
database = {
type = "postgresql";
createLocally = true;
};
h2o = { };
};
services.ejabberd = {
inherit (ejabberd) spoolDir;
enable = true;
configFile = ejabberd_config_file;
imagemagick = false;
};
services.h2o.settings = {
compress = "ON";
};
systemd.services.ejabberd = {
serviceConfig = {
# Certain misconfigurations can cause RAM usage to swell before
# crashing; fail sooner with more-than-liberal memory limits
StartupMemoryMax = "1G";
MemoryMax = "512M";
};
};
networking = {
firewall.allowedTCPPorts = with ejabberd.ports; [
c2s
s2s
];
extraHosts = ''
127.0.0.1 ${movim.domain}
127.0.0.1 ${ejabberd.domain}
'';
};
};
};
testScript = # python
''
ejabberdctl = "su ejabberd -s $(which ejabberdctl) "
server.wait_for_unit("phpfpm-movim.service")
server.wait_for_unit("h2o.service")
server.wait_for_open_port(${builtins.toString movim.port})
server.wait_for_open_port(80)
server.wait_for_unit("ejabberd.service")
ejabberd_status = server.succeed(ejabberdctl + "status")
assert "status: started" in ejabberd_status
server.succeed(ejabberdctl + "register ${ejabberd.admin.username} ${ejabberd.domain} ${ejabberd.admin.password}")
server.wait_for_unit("movim.service")
# Test unauthenticated
server.fail("curl -L --fail-with-body --max-redirs 0 http://${movim.domain}/chat")
# Test basic Websocket
server.succeed("echo | websocat --origin 'http://${movim.domain}' 'ws://${movim.domain}/ws/?path=login&offset=0'")
# Test login + create cookiejar
login_html = server.succeed("curl --fail-with-body -c /tmp/cookies http://${movim.domain}/login")
assert "${movim.description}" in login_html
assert "${movim.info}" in login_html
# Test authentication POST
server.succeed("curl --fail-with-body -b /tmp/cookies -X POST --data-urlencode 'username=${ejabberd.admin.JID}' --data-urlencode 'password=${ejabberd.admin.password}' http://${movim.domain}/login")
server.succeed("curl -L --fail-with-body --max-redirs 1 -b /tmp/cookies http://${movim.domain}/chat")
'';
}