{ config, pkgs, lib, ... }: let mcDataDir = "/srv/minecraft/data"; modrinthMods = builtins.concatStringsSep "," [ # Performance "lithium" "krypton" "ferrite-core" "c2me-fabric" "noisium" "linearly-optimized" "vmp-fabric" "ksyxis" "scalablelux" "lmd" "structure-layout-optimizer" "threadtweak" "crashexploitfixer" # Anti-cheat "anti-xray" "grimac" "no-chat-reports" # Worldgen — terrain (Stardust Labs suite) "terralith" "tectonic" "amplified-nether" "nullscape" # Worldgen — structures (YUNG's suite) "yungs-api" "yungs-better-dungeons" "yungs-better-strongholds" "yungs-better-ocean-monuments" "yungs-better-mineshafts" "yungs-better-desert-temples" "yungs-better-jungle-temples" "yungs-better-witch-huts" "yungs-better-nether-fortresses" "yungs-better-end-island" "yungs-extras" "yungs-bridges" # Client mod compatibility (optional on client side) "appleskin" "simple-voice-chat" # QoL "oneplayersleep" "netherportalfix" # Moderation "luckperms" "banhammer" "ledger" "styled-chat" # Discord bridge "discord4fabric" # Utilities "chunky" ]; jvmFlags = builtins.concatStringsSep " " [ "-XX:+UseG1GC" "-XX:+ParallelRefProcEnabled" "-XX:MaxGCPauseMillis=200" "-XX:+UnlockExperimentalVMOptions" "-XX:+DisableExplicitGC" "-XX:G1NewSizePercent=30" "-XX:G1MaxNewSizePercent=40" "-XX:G1HeapRegionSize=8M" "-XX:G1ReservePercent=20" "-XX:G1MixedGCCountTarget=4" "-XX:InitiatingHeapOccupancyPercent=15" "-XX:G1MixedGCLiveThresholdPercent=90" "-XX:SurvivorRatio=32" "-XX:+PerfDisableSharedMem" "-XX:MaxTenuringThreshold=1" ]; in { virtualisation.docker.enable = true; virtualisation.oci-containers.backend = "docker"; virtualisation.oci-containers.containers.minecraft = { image = "itzg/minecraft-server:latest"; ports = [ "25565:25565" # Minecraft "24454:24454/udp" # Simple Voice Chat ]; volumes = [ "${mcDataDir}:/data" ]; environment = { EULA = "TRUE"; TYPE = "FABRIC"; VERSION = "1.21.4"; MEMORY = "2G"; MAX_PLAYERS = "10"; DIFFICULTY = "hard"; VIEW_DISTANCE = "10"; SIMULATION_DISTANCE = "10"; ENABLE_WHITELIST = "TRUE"; ENFORCE_WHITELIST = "TRUE"; WHITELIST = "player1,player2"; # TODO: add your players MOTD = "compsigh Minecraft"; # TODO: customize MODRINTH_PROJECTS = modrinthMods; JVM_XX_OPTS = jvmFlags; }; extraOptions = [ "--memory=3g" "--cpus=2" "--restart=unless-stopped" "--pids-limit=256" "--security-opt=no-new-privileges" ]; }; # Ensure data directory exists systemd.tmpfiles.rules = [ "d ${mcDataDir} 0755 root root -" ]; # Copy Chunky config (concurrency: 1 for background generation) systemd.services.minecraft-mod-configs = { description = "Copy mod configs into Minecraft data volume"; wantedBy = [ "multi-user.target" ]; before = [ "docker-minecraft.service" ]; serviceConfig = { Type = "oneshot"; ExecStart = pkgs.writeShellScript "setup-mod-configs" '' mkdir -p ${mcDataDir}/plugins/Chunky cp ${../configs/chunky.yml} ${mcDataDir}/plugins/Chunky/config.yml ''; }; }; }