services:
  mc:
    image: itzg/minecraft-server:latest
    container_name: minecraft-mc
    environment:
      EULA: "TRUE"
      # TYPE=CUSTOM bypasses itzg's auto-loader detection; honors MODRINTH_LOADER override
      TYPE: CUSTOM
      CUSTOM_SERVER: "https://api.purpurmc.org/v2/purpur/1.21.11/latest/download"
      VERSION: "1.21.11"

      # H3 (2026-05-07): Xmx lowered 16384M -> 14336M to leave ~3.5G headroom
      # for off-heap (Netty buffers, native mmaps, plugin metadata) inside the
      # 18G container limit. See AUDIT-2026-05-07.md F-05.
      MEMORY_SIZE: "14G"
      JVM_OPTS: "-Xms8192M -Xmx14336M"

      DIFFICULTY: hard
      GAMEMODE: survival
      HARDCORE: "false"
      MAX_PLAYERS: "69"
      VIEW_DISTANCE: 20
      SIMULATION_DISTANCE: 10
      ONLINE_MODE: "false"
      SPAWN_PROTECTION: 0
      MOTD: "racked.ru — experience the game the way it should have always been"

      USE_AIKAR_FLAGS: "true"
      MAX_TICK_TIME: "-1"

      ENABLE_RCON: "true"
      RCON_PASSWORD: "*redacted*"

      TZ: "Europe/London"
      ENABLE_ROLLING_LOGS: "true"

      UID: "1000"
      GID: "1000"

      # Modrinth auto-DL — TYPE=CUSTOM lets MODRINTH_LOADER=paper actually work
      MODRINTH_PROJECTS: |
        luckperms
        placeholderapi
        fastasyncworldedit
        simple-voice-chat
        minimotd
        skinsrestorer
        vaultunlocked
        proantitab
        voidworldgenerator
        homestead-plugin
      # EssentialsX + spark not on Modrinth as paper jars — direct GH/CI URLs.
      # ExcellentShop/CoinsEngine/nightcore are mounted via COPY_PLUGINS_SRC,
      # not URL'd here, so they survive even if NightExpress's reposilite goes
      # dark.
      PLUGINS: |
        https://github.com/EssentialsX/Essentials/releases/download/2.21.2/EssentialsX-2.21.2.jar
        https://ci.lucko.me/job/spark/lastSuccessfulBuild/artifact/spark-bukkit/build/libs/spark-1.10.172-bukkit.jar
        https://github.com/HaHaWTH/AuthMeReReloaded/releases/download/b49/AuthMe-5.6.0-FORK-Universal.jar
        https://github.com/dmulloy2/ProtocolLib/releases/download/dev-build/ProtocolLib.jar
        https://github.com/VoidemLIVE/Help-Command-Plugin/releases/download/v2.9.2/HelpCommand-2.9.2.jar
        https://cdn.modrinth.com/data/Lu3KuzdV/versions/HD2IvrxS/CoreProtect-CE-23.1.jar
        https://cdn.modrinth.com/data/gG7VFbG0/versions/uWACk3HR/TAB%20v6.0.1.jar
      MODRINTH_DOWNLOAD_DEPENDENCIES: none
      MODRINTH_PROJECTS_DEFAULT_VERSION_TYPE: release
      MODRINTH_LOADER: paper
      SPIGET_RESOURCES: ""
      REMOVE_OLD_MODS: "true"
      REMOVE_OLD_MODS_INCLUDE: "*.jar"
      # Custom-built jars survive the wipe via this exclude list.
      # ExcellentShop, CoinsEngine, nightcore arrive via COPY_PLUGINS_SRC bind.
      REMOVE_OLD_MODS_EXCLUDE: "AuthLimbo*.jar,ExcellentShop*.jar,CoinsEngine*.jar,nightcore*.jar"
      COPY_PLUGINS_SRC: "/plugins-custom"
    volumes:
      - /opt/docker/minecraft:/data
      - /opt/docker/minecraft-custom-plugins:/plugins-custom:ro
    ports:
      - "25565:25565/tcp"
      - "25575:25575/tcp"
    networks:
      - proxy
    restart: unless-stopped
    # H2 (2026-05-07): Container hardening per AUDIT-2026-05-07.md F-06.
    # Drop the default Docker capability set (CAP_NET_RAW, CAP_SYS_CHROOT, ...)
    # which the JVM/Paper does not need. Re-add only the minimum needed by
    # itzg's entrypoint chown/gosu flow. DAC_OVERRIDE intentionally omitted —
    # add back only if entrypoint fails. NOT applied live until next restart.
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETUID
      - SETGID
      - FOWNER
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: ["CMD", "mc-health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 240s
    deploy:
      resources:
        limits:
          memory: 18G
          cpus: '6'
          pids: 4096
        reservations:
          memory: 8G
    labels:
      - "traefik.enable=false"

networks:
  proxy:
    external: true
