A pkgs/by-name/openfire/package.nix => pkgs/by-name/openfire/package.nix +56 -0
@@ 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;
+ };
+}
A projects/Openfire-IPv6/default.nix => projects/Openfire-IPv6/default.nix +15 -0
@@ 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;
+ };
+}
A projects/Openfire-IPv6/example.nix => projects/Openfire-IPv6/example.nix +6 -0
@@ 0,0 1,6 @@
+{...}: {
+ services.openfire-server = {
+ enable = true;
+ openFirewall = true;
+ };
+}
A projects/Openfire-IPv6/service.nix => projects/Openfire-IPv6/service.nix +185 -0
@@ 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
+ ];
+ };
+ };
+}
A projects/Openfire-IPv6/test.nix => projects/Openfire-IPv6/test.nix +64 -0
@@ 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)
+ '';
+}