460 lines
16 KiB
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";
|
|
};
|
|
}];
|
|
};
|
|
};
|
|
}
|
|
|