Skip to content

Commit

Permalink
openfire: init at 4.9.0 (#360)
Browse files Browse the repository at this point in the history
* openfire: init at 4.9.0

* openfire: init project

Co-authored-by: Valentin Gagarin <[email protected]>

---------

Co-authored-by: Valentin Gagarin <[email protected]>
  • Loading branch information
eljamm and fricklerhandwerk authored Oct 2, 2024
1 parent 7704882 commit e40efee
Show file tree
Hide file tree
Showing 5 changed files with 326 additions and 0 deletions.
56 changes: 56 additions & 0 deletions pkgs/by-name/openfire/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
lib,
maven,
fetchFromGitHub,
jdk_headless,
makeWrapper,
}:
maven.buildMavenPackage rec {
pname = "openfire";
version = "4.9.0";

src = fetchFromGitHub {
owner = "igniterealtime";
repo = "Openfire";
rev = "v${version}";
hash = "sha256-exZDH3wROQyw8WIQU1WZB3QoXseiSHueo3hiQrjQZGM=";
};

mvnJdk = jdk_headless;
mvnHash = "sha256-PovHnAR10IxDTyoXCH4LCWZzIv6cNMl9JI0B4stDBo8=";

# some deps require internet for tests
mvnParameters = "-Dmaven.test.skip";

nativeBuildInputs = [makeWrapper];

installPhase = ''
runHook preInstall
mkdir -p $out/{bin,opt}
cp -R ./distribution/target/distribution-base/* $out/opt
ln -s $out/opt/lib $out/lib
for file in openfire.sh openfirectl; do
wrapProgram $out/opt/bin/$file \
--set JAVA_HOME ${jdk_headless.home}
install -Dm555 $out/opt/bin/$file -t $out/bin
done
# Used to determine if the Openfire state directory needs updating
echo ${version} > $out/opt/version
runHook postInstall
'';

meta = {
description = "An XMPP server licensed under the Open Source Apache License";
homepage = "https://github.com/igniterealtime/Openfire";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [];
mainProgram = "openfire";
platforms = lib.platforms.all;
};
}
15 changes: 15 additions & 0 deletions projects/Openfire-IPv6/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{pkgs, ...} @ args: {
packages = {
inherit (pkgs) openfire;
};
nixos = {
modules.services.openfire-server = ./service.nix;
examples = {
base = {
path = ./example.nix;
description = "Basic configuration, mainly used for testing purposes.";
};
};
tests.openfire-server = import ./test.nix args;
};
}
6 changes: 6 additions & 0 deletions projects/Openfire-IPv6/example.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{...}: {
services.openfire-server = {
enable = true;
openFirewall = true;
};
}
185 changes: 185 additions & 0 deletions projects/Openfire-IPv6/service.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
{
config,
lib,
pkgs,
...
}: let
cfg = config.services.openfire-server;
in {
options.services.openfire-server = {
enable = lib.mkEnableOption "Openfire XMPP server";
package = lib.mkPackageOption pkgs "openfire" {};

autoUpdateState = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
When enabled, the state directory will be automatically updated to
match the installed package version.
For manually doing this, please refer to the
[Openfire Upgrade Guide](https://download.igniterealtime.org/openfire/docs/latest/documentation/upgrade-guide.html).
'';
};

servicePort = lib.mkOption {
type = lib.types.port;
default = 9090;
description = ''
The port on which Openfire should listen for insecure Admin Console access.
'';
};

securePort = lib.mkOption {
type = lib.types.port;
default = 9091;
description = ''
The port on which Openfire should listen for secure Admin Console access.
'';
};

openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Whether to open ports in the firewall for the server.
'';
};

dataDir = lib.mkOption {
type = lib.types.str;
default = "${cfg.package}/opt";
defaultText = lib.literalExpression ''"''${config.services.openfire.package}/opt"'';
description = ''
Where to load readonly data from.
'';
};

stateDir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/openfire";
description = ''
Where to store runtime data (logs, plugins, ...).
If left at the default, this will be automatically created on server
startup if it does not already exist. If changed, it is the admin's
responsibility to make sure that the directory exists and is writeable
by the `openfire` user.
'';
};
};

config = lib.mkIf cfg.enable {
users.users.openfire = {
description = "openfire server daemon user";
home = cfg.stateDir;
createHome = false;
isSystemUser = true;
group = "openfire";
};
users.groups.openfire = {};

systemd.services.openfire-server = {
path = [pkgs.rsync];
description = "Openfire Server Daemon";
serviceConfig = lib.mkMerge [
{
ExecStart = "${cfg.stateDir}/bin/openfire.sh";
User = "openfire";
Group = "openfire";
Restart = "on-failure";
WorkingDirectory = cfg.stateDir;
}
(lib.mkIf (cfg.stateDir == "/var/lib/openfire") {
StateDirectory = "openfire";
})
];
environment.OPENFIRE_HOME = cfg.stateDir;
wantedBy = ["multi-user.target"];
after = ["network.target"];

# Files under `OPENFIRE_HOME` require read-write permissions for Openfire
# to work correctly, so we can't directly run it from the nix store.
#
# Instead, we need to copy those files into a directory which has proper
# permissions, but we must only do this once, otherwise we risk
# ovewriting server state information every time the server is upgraded.
#
# As such, if `version` already exists, we assume the rest of
# the files do as well, and copy nothing.
preStart = let
# Update Openfire
# https://download.igniterealtime.org/openfire/docs/latest/documentation/upgrade-guide.html
updateState = ''
tmpDir="/tmp/openfire-backup"
oldVersion=$(cat "${cfg.stateDir}/version")
newVersion=$(cat "${cfg.dataDir}/version")
if [ $oldVersion != $newVersion ]; then
echo "Attempting to update Openfire from $oldVersion to $newVersion"
# Back up the Openfire state directory
rsync -a "${cfg.stateDir}/" $tmpDir/
# Clear old state
rm -rf "${cfg.stateDir}/*"
# Install new state
rsync -a --chmod=u=rwX,go=rX "${cfg.package}/opt/" "${cfg.stateDir}/"
# Copy old configuration
# TODO: only backup these directories?
rsync -a $tmpDir/plugins/ ${cfg.stateDir}/ --exclude=admin
for dir in conf embedded-db enterprise resources/security; do
[ -e $tmpDir/$dir ] && rsync -a $tmpDir/$dir ${cfg.stateDir}/;
done
rm -rf $tmpDir
echo "Update complete"
fi
'';

oldStateMessage = ''
oldVersion=$(cat "${cfg.stateDir}/version")
newVersion=$(cat "${cfg.dataDir}/version")
cat <<EOF
You are trying to run Openfire $newVersion
with a systemd state directory created by Openfire $oldVersion.
Until you update the state directory, Openfire will continue using $oldVersion.
Possible workarounds:
1. Enable "services.openfire-server.autoUpdateState" to automatically handle this.
2. Export your data from Openfire $oldVersion,
clear the state directory, and
import your data to Openfire $newVersion
See Openfire documentation for migrating state:
https://download.igniterealtime.org/openfire/docs/latest/documentation/upgrade-guide.html
EOF
'';
in ''
set -e
# Install package to state directory (initial run)
if [ ! -e "${cfg.stateDir}"/version ]; then
rsync -a --chmod=u=rwX,go=rX "${cfg.package}/opt/" "${cfg.stateDir}/"
else
if [ ${toString cfg.autoUpdateState} ]; then
${updateState}
else
${oldStateMessage}
fi
fi
'';
};

networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [
cfg.servicePort
cfg.securePort
];
};
};
}
64 changes: 64 additions & 0 deletions projects/Openfire-IPv6/test.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
lib,
pkgs,
sources,
...
}: {
# NOTE:
# - Run the test interactively to access the server: nix run .#nixosTests.Openfire-IPv6.openfire-server.driverInteractive
# - Diable `Restrict Admin Console Access` in the `Server Settings`, else you won't be able to login.

name = "openfire";
meta = {
maintainers = [];
};

nodes = {
server = {config, ...}: {
imports = [
sources.modules.default
sources.modules."services.openfire-server"
];

services.openfire-server = {
enable = true;
openFirewall = true;
};

services.openssh = {
enable = true;
settings = {
PermitRootLogin = "yes";
PermitEmptyPasswords = "yes";
};
};
security.pam.services.sshd.allowNullPassword = true;

virtualisation.forwardPorts = let
cfg = config.services.openfire-server;
in [
{
from = "host";
host.port = 2222;
guest.port = 22;
}
{
from = "host";
host.port = cfg.servicePort;
guest.port = cfg.servicePort;
}
{
from = "host";
host.port = cfg.securePort;
guest.port = cfg.securePort;
}
];
};
};

testScript = ''
start_all()
server.wait_for_unit("openfire-server.service")
server.wait_for_open_port(9090)
'';
}

0 comments on commit e40efee

Please sign in to comment.