nixos-combined-flake/modules/nixos/games/wow/azerothcore/default.nix

460 lines
16 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.azerothcore;
in
{
options.services.azerothcore = {
enable = mkEnableOption "AzerothCore service";
openFirewall = mkOption {
type = types.bool;
default = false;
description = mdDoc "Whether to open the firewall for the auth & world server ports.";
};
serverPackage = mkPackageOption pkgs "azerothcore" { };
clientDataPackage = mkPackageOption pkgs "azerothcore-data" { };
srcDir = mkOption {
type = types.path;
default = "${pkgs.azerothcore}/share";
description = mdDoc "The data directory";
};
dataDir = mkOption {
type = types.path;
default = "${pkgs.azerothcore-data}";
description = mdDoc "The data directory";
};
logDir = mkOption {
type = types.path;
default = "/var/log/azerothcore";
description = mdDoc "The log directory";
};
tmpDir = mkOption {
type = types.path;
default = "/tmp/azerothcore";
description = mdDoc "The tmp directory to use";
};
hostname = mkOption {
type = types.str;
default = "127.0.0.1";
description = lib.mdDoc "The hostname to reach the server.";
};
database = mkOption {
type = types.submodule {
options = {
user = mkOption {
type = types.str;
description = mdDoc "The MySQL database user to use for auth & world servers.";
};
password = mkOption {
type = types.str;
description = mdDoc "The MySQL database password to use for auth & world servers.";
};
host = mkOption {
type = types.str;
description = mdDoc "The MySQL host to use for auth & world servers.";
};
port = mkOption {
type = types.port;
description = mdDoc "The port host to use for auth & world servers.";
};
};
};
default = {
user = "acore";
password = "";
host = "127.0.0.1";
port = 3306;
};
description = mdDoc "Database configuration.";
};
auth = mkOption {
type = types.submodule {
options = {
port = mkOption {
type = types.port;
description = lib.mdDoc "Port to listen on for the auth server.";
};
address = mkOption {
type = types.str;
description = mdDoc "Address to listen on for the auth server.";
};
database = mkOption {
type = types.str;
description = "Database name for the auth server.";
};
};
};
default = {
port = 3724;
address = "0.0.0.0";
database = "acore_auth";
};
description = mdDoc "Auth server configuration.";
};
world = mkOption {
type = types.submodule {
options = {
realmId = mkOption {
type = types.int;
description = lib.mdDoc "Port to listen on for the worl server.";
};
port = mkOption {
type = types.port;
description = lib.mdDoc "Port to listen on for the worl server.";
};
address = mkOption {
type = types.str;
description = mdDoc "Address to listen on for the world server.";
};
database = mkOption {
type = types.str;
description = "Database name for the world server.";
};
charactersDatabase = mkOption {
type = types.str;
description = "Characters database name for the world server.";
};
};
};
default = {
realmId = 1;
port = 8085;
address = "0.0.0.0";
database = "acore_world";
charactersDatabase = "acore_characters";
};
description = mdDoc "World server configuration.";
};
npcbots = mkOption {
type = types.submodule {
options = {
botgiver = {
filterRaces = mkOption {
type = types.int;
};
};
classes = {
warrior = mkOption {
type = types.bool;
};
paladin = mkOption {
type = types.bool;
};
hunter = mkOption {
type = types.bool;
};
rogue = mkOption {
type = types.bool;
};
priest = mkOption {
type = types.bool;
};
deathKnight = mkOption {
type = types.bool;
};
shaman = mkOption {
type = types.bool;
};
mage = mkOption {
type = types.bool;
};
warlock = mkOption {
type = types.bool;
};
druid = mkOption {
type = types.bool;
};
blademaster = mkOption {
type = types.bool;
};
obsidianDestroyer = mkOption {
type = types.bool;
};
archmage = mkOption {
type = types.bool;
};
dreadlord = mkOption {
type = types.bool;
};
spellBreaker = mkOption {
type = types.bool;
};
darkRanger = mkOption {
type = types.bool;
};
necromancer = mkOption {
type = types.bool;
};
seaWitch = mkOption {
type = types.bool;
};
cryptLord = mkOption {
type = types.bool;
};
};
};
};
default = {
botgiver = {
filterRaces = 0;
};
classes = {
warrior = true;
paladin = true;
hunter = true;
rogue = true;
priest = true;
deathKnight = true;
shaman = true;
mage = true;
warlock = true;
druid = true;
blademaster = false;
obsidianDestroyer = true;
archmage = true;
dreadlord = true;
spellBreaker = true;
darkRanger = true;
necromancer = true;
seaWitch = true;
cryptLord = true;
};
};
};
ahbot = mkOption {
type = types.submodule {
options = {
EnableSeller = mkOption {
type = types.int;
};
EnableBuyer = mkOption {
type = types.int;
};
Account = mkOption {
type = types.int;
};
GUID = mkOption {
type = types.int;
};
ItemsPerCycle = mkOption {
type = types.int;
};
ElapsingTimeClass = mkOption {
type = types.int;
};
VendorItems = mkOption {
type = types.int;
};
VendorTradeGoods = mkOption {
type = types.int;
};
LootItems = mkOption {
type = types.int;
};
LootTradeGoods = mkOption {
type = types.int;
};
OtherItems = mkOption {
type = types.int;
};
OtherTradeGoods = mkOption {
type = types.int;
};
ProfessionItems = mkOption {
type = types.int;
};
};
};
default = {
EnableSeller = 0;
EnableBuyer = 0;
Account = 0;
GUID = 0;
ItemsPerCycle = 200;
ElapsingTimeClass = 1;
VendorItems = 0;
VendorTradeGoods = 0;
LootItems = 1;
LootTradeGoods = 1;
OtherItems = 0;
OtherTradeGoods = 0;
ProfessionItems = 0;
};
};
};
config = mkIf cfg.enable {
users.users.azerothcore = {
home = cfg.dataDir;
createHome = true;
isSystemUser = true;
group = "azerothcore";
};
users.groups.azerothcore.name = "azerothcore";
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [
cfg.auth.port
cfg.world.port
];
environment.etc =
{
"azerothcore/authserver.conf".source = pkgs.runCommand "authserver.conf"
{ } ''
cp ${cfg.serverPackage}/etc/authserver.conf.dist $out
'';
"azerothcore/worldserver.conf".source = pkgs.runCommand "worldserver.conf"
{ } ''
cp ${cfg.serverPackage}/etc/worldserver.conf.dist $out
'';
"azerothcore/dbimport.conf".source = pkgs.runCommand "dbimport.conf"
{ } ''
cp ${cfg.serverPackage}/etc/dbimport.conf.dist $out
'';
"azerothcore/modules/mod_ahbot.conf".source = pkgs.runCommand "mod_ahbot.conf"
{ } ''
cp ${cfg.serverPackage}/etc/modules/mod_ahbot.conf.dist $out
'';
};
systemd.services =
let
env_key = prefix: key: "${prefix}_${key}";
ac_env_key = env_key "AC";
npcbot_env_key = env_key "AC_NPC_BOT";
ahbot_env_key = env_key "AC_AUCTION_HOUSE_BOT";
mysqlHost = "${cfg.database.host}";
mysqlPort = toString cfg.database.port;
mysqlSocket = "/run/mysqld/mysqld.sock";
databaseInfo = (user: password: database: (if mysqlHost == "127.0.0.1" then ".;${mysqlSocket};${user};${password};${database}" else "${mysqlHost};${mysqlPort};${user};${password};${database}")) cfg.database.user cfg.database.password;
authDatabaseInfo = databaseInfo cfg.auth.database;
worldDatabaseInfo = databaseInfo cfg.world.database;
characterDatabaseInfo = databaseInfo cfg.world.charactersDatabase;
in
{
azerothcore-authserver = {
description = "AzerothCore Auth Server";
after = [ "network-online.target" "mysql.service" ];
wants = [ "network-online.target" "mysql.service" ];
environment = {
"${ac_env_key "CONSOLE_ENABLE"}" = "0";
"${ac_env_key "DATA_DIR"}" = cfg.clientDataPackage;
"${ac_env_key "LOGS_DIR"}" = cfg.logDir;
"${ac_env_key "TMP_DIR"}" = cfg.tmpDir;
"${ac_env_key "SOURCE_DIRECTORY"}" = toString cfg.serverPackage.srcDir;
"${ac_env_key "REALM_SERVER_PORT"}" = toString cfg.auth.port;
"${ac_env_key "BIND_IP"}" = cfg.auth.address;
"${ac_env_key "LOGIN_DATABASE_INFO"}" = authDatabaseInfo;
};
serviceConfig = {
Type = "simple";
User = "azerothcore";
Group = "azerothcore";
Restart = "on-failure";
ExecStart = "${cfg.serverPackage}/bin/authserver -c /etc/azerothcore/authserver.conf";
};
};
azerothcore-worldserver = {
description = "AzerothCore World Server";
after = [ "network-online.target" "mysql.service" ];
wants = [ "network-online.target" "mysql.service" ];
environment = {
"${ac_env_key "REALM_ID"}" = "${toString cfg.world.realmId}";
"${ac_env_key "CONSOLE_ENABLE"}" = "0";
"${ac_env_key "DATA_DIR"}" = "${cfg.clientDataPackage}";
"${ac_env_key "LOGS_DIR"}" = "${cfg.logDir}";
"${ac_env_key "TMP_DIR"}" = cfg.tmpDir;
"${ac_env_key "SOURCE_DIRECTORY"}" = cfg.serverPackage.srcDir;
"${ac_env_key "WORLD_SERVER_PORT"}" = toString cfg.world.port;
"${ac_env_key "BIND_IP"}" = cfg.world.address;
"${ac_env_key "LOGIN_DATABASE_INFO"}" = authDatabaseInfo;
"${ac_env_key "WORLD_DATABASE_INFO"}" = worldDatabaseInfo;
"${ac_env_key "CHARACTER_DATABASE_INFO"}" = characterDatabaseInfo;
"${npcbot_env_key "BOTGIVER_FILTER_RACES"}" = toString cfg.npcbots.botgiver.filterRaces;
"${npcbot_env_key "CLASSES_WARRIOR_ENABLE"}" = if cfg.npcbots.classes.warrior then "1" else "0";
"${npcbot_env_key "CLASSES_PALADIN_ENABLE"}" = if cfg.npcbots.classes.paladin then "1" else "0";
"${npcbot_env_key "CLASSES_HUNTER_ENABLE"}" = if cfg.npcbots.classes.hunter then "1" else "0";
"${npcbot_env_key "CLASSES_ROGUE_ENABLE"}" = if cfg.npcbots.classes.rogue then "1" else "0";
"${npcbot_env_key "CLASSES_PRIEST_ENABLE"}" = if cfg.npcbots.classes.priest then "1" else "0";
"${npcbot_env_key "CLASSES_DEATH_KNIGHT_ENABLE"}" = if cfg.npcbots.classes.deathKnight then "1" else "0";
"${npcbot_env_key "CLASSES_SHAMAN_ENABLE"}" = if cfg.npcbots.classes.shaman then "1" else "0";
"${npcbot_env_key "CLASSES_MAGE_ENABLE"}" = if cfg.npcbots.classes.mage then "1" else "0";
"${npcbot_env_key "CLASSES_WARLOCK_ENABLE"}" = if cfg.npcbots.classes.warlock then "1" else "0";
"${npcbot_env_key "CLASSES_DRUID_ENABLE"}" = if cfg.npcbots.classes.druid then "1" else "0";
"${npcbot_env_key "CLASSES_BLADEMASTER_ENABLE"}" = if cfg.npcbots.classes.blademaster then "1" else "0";
"${npcbot_env_key "CLASSES_OBSIDIAN_DESTROYER_ENABLE"}" = if cfg.npcbots.classes.obsidianDestroyer then "1" else "0";
"${npcbot_env_key "CLASSES_ARCHMAGE_ENABLE"}" = if cfg.npcbots.classes.archmage then "1" else "0";
"${npcbot_env_key "CLASSES_DREADLORD_ENABLE"}" = if cfg.npcbots.classes.dreadlord then "1" else "0";
"${npcbot_env_key "CLASSES_SPELL_BREAKER_ENABLE"}" = if cfg.npcbots.classes.spellBreaker then "1" else "0";
"${npcbot_env_key "CLASSES_DARK_RANGER_ENABLE"}" = if cfg.npcbots.classes.darkRanger then "1" else "0";
"${npcbot_env_key "CLASSES_NECROMANCER_ENABLE"}" = if cfg.npcbots.classes.necromancer then "1" else "0";
"${npcbot_env_key "CLASSES_SEA_WITCH_ENABLE"}" = if cfg.npcbots.classes.seaWitch then "1" else "0";
"${npcbot_env_key "CLASSES_CRYPT_LORD_ENABLE"}" = if cfg.npcbots.classes.cryptLord then "1" else "0";
"${ahbot_env_key "ENABLE_SELLER"}" = toString cfg.ahbot.EnableSeller;
"${ahbot_env_key "ENABLE_BUYER"}" = toString cfg.ahbot.EnableBuyer;
"${ahbot_env_key "ACCOUNT"}" = toString cfg.ahbot.Account;
"${ahbot_env_key "GUID"}" = toString cfg.ahbot.GUID;
"${ahbot_env_key "ITEMS_PER_CYCLE"}" = toString cfg.ahbot.ItemsPerCycle;
"${ahbot_env_key "ELAPSING_TIME_CLASS"}" = toString cfg.ahbot.ElapsingTimeClass;
"${ahbot_env_key "VENDOR_ITEMS"}" = toString cfg.ahbot.VendorItems;
"${ahbot_env_key "VENDOR_TRADE_GOODS"}" = toString cfg.ahbot.VendorTradeGoods;
"${ahbot_env_key "LOOT_ITEMS"}" = toString cfg.ahbot.LootItems;
"${ahbot_env_key "LOOT_TRADE_GOODS"}" = toString cfg.ahbot.LootTradeGoods;
"${ahbot_env_key "OTHER_ITEMS"}" = toString cfg.ahbot.OtherItems;
"${ahbot_env_key "OTHER_TRADE_GOODS"}" = toString cfg.ahbot.OtherTradeGoods;
"${ahbot_env_key "PROFESSION_ITEMS"}" = toString cfg.ahbot.ProfessionItems;
};
serviceConfig = {
Type = "simple";
User = "azerothcore";
Group = "azerothcore";
WorkingDirectory = "/etc/azerothcore";
Restart = "on-failure";
ExecStart = "${cfg.serverPackage}/bin/worldserver -c /etc/azerothcore/worldserver.conf";
};
};
azerothcore = rec {
description = "AzerothCore";
wantedBy = [ "multi-user.target" ];
wants = [ "azerothcore-auth.service" "azerothcore-world.service" ];
after = wants;
};
};
systemd.tmpfiles.rules = [
"d ${cfg.logDir} 1755 azerothcore azerothcore - -"
"d ${cfg.tmpDir} 1755 azerothcore azerothcore - -"
];
services.mysql = {
enable = true;
package = lib.mkDefault pkgs.mysql80;
ensureDatabases = [
cfg.auth.database
cfg.world.database
cfg.world.charactersDatabase
];
ensureUsers = [{
name = cfg.database.user;
ensurePermissions = {
"${cfg.auth.database}.*" = "ALL PRIVILEGES";
"${cfg.world.database}.*" = "ALL PRIVILEGES";
"${cfg.world.charactersDatabase}.*" = "ALL PRIVILEGES";
};
}];
};
};
}