commit 75222000a0956fabdb2e50efd454efb1e4a98397 Author: rfoley20 Date: Fri Jul 3 17:01:35 2026 +0000 Upload files to "/" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6c40b07 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,57 @@ +# ========================================================================= +# IW4X / MW2 dedicated-server base image +# Extends the Pterodactyl wine yolk and adds the FULL 32-bit Wine tree +# that MW2 (a 2009 32-bit Windows game) needs but the stock yolk lacks. +# +# Build: docker build -t /iw4x-wine:latest . +# Push: docker push /iw4x-wine:latest +# ========================================================================= +FROM ghcr.io/pterodactyl/yolks:wine_latest + +USER root + +# ---- 1. Install the 32-bit Wine libraries the stock image is missing ----- +# The stock yolk enables i386 but never installs wine32:i386 / libwine:i386, +# which is why a win32 prefix can't load 32-bit kernel32/user32/etc. +# We add the WineHQ repo to get matching 32-bit builds, then install winbind +# (needed for NTLM), cabextract (winetricks needs it) and the 32-bit tree. +RUN dpkg --add-architecture i386 \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + wget \ + gnupg2 \ + cabextract \ + winbind \ + xvfb \ + xauth \ + wine32:i386 \ + libwine:i386 \ + fonts-wine \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# ---- 2. Bake a clean 32-bit prefix + runtimes into the image ------------- +# Doing this at BUILD time (as root) avoids the unprivileged-runtime apt wall +# and means every container starts from a known-good win32 prefix. +ENV WINEARCH=win32 +ENV WINEPREFIX=/opt/wine-prefix +ENV WINEDEBUG=-all + +# winetricks is already present in the yolk; if not, grab it. +RUN if ! command -v winetricks >/dev/null 2>&1; then \ + wget -O /usr/local/bin/winetricks \ + https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks \ + && chmod +x /usr/local/bin/winetricks ; \ + fi + +# Initialise the prefix headless, then install the runtimes IW4X/MW2 want. +# vcrun2019 + d3dcompiler_47 are the ones the IW4X Linux docs call for. +RUN xvfb-run -a wineboot --init \ + && xvfb-run -a winetricks -q vcrun2019 d3dcompiler_47 \ + && wineserver -w \ + && chmod -R 777 /opt/wine-prefix + +USER container +ENV USER=container HOME=/home/container +WORKDIR /home/container diff --git a/iw4x-custom-egg.json b/iw4x-custom-egg.json new file mode 100644 index 0000000..af49bd4 --- /dev/null +++ b/iw4x-custom-egg.json @@ -0,0 +1,102 @@ +{ + "_comment": "IW4X egg rebuilt for a custom 32-bit wine image. No Steam login. Game files supplied by you; IW4X files fetched from GitHub at install.", + "meta": { + "version": "PTDL_v2", + "update_url": null + }, + "exported_at": "2026-07-03T00:00:00+00:00", + "name": "IW4x (Custom 32-bit Wine)", + "author": "you@yourlab.local", + "description": "IW4x dedicated server for Call of Duty: Modern Warfare 2 (2009), running on a custom 32-bit Wine image. Game files are provided by the operator; IW4X client files are fetched from GitHub via the official launcher.", + "features": null, + "docker_images": { + "IW4X Wine (custom 32-bit)": "REGISTRY.your-lab.local/iw4x-wine:latest" + }, + "file_denylist": [], + "startup": "bash ./start-iw4x.sh", + "config": { + "files": "{\r\n \"userraw/server.cfg\": {\r\n \"parser\": \"file\",\r\n \"find\": {\r\n \"sv_hostname\": \"sv_hostname \\\"{{server.build.env.SERVER_NAME}}\\\"\",\r\n \"set g_password\": \"set g_password \\\"{{server.build.env.SERVER_PASSWORD}}\\\"\"\r\n }\r\n }\r\n}", + "startup": "{\r\n \"done\": \"Sending heartbeat to master\"\r\n}", + "logs": "{}", + "stop": "^C" + }, + "scripts": { + "installation": { + "script": "#!/bin/bash\r\n# IW4X install script - NO STEAM LOGIN.\r\n# Game (MW2) files are supplied by the operator via upload / volume.\r\n# This script only lays down the IW4X launcher, client dll, rawfiles,\r\n# server configs, and the startup wrapper.\r\n\r\nset -e\r\napt-get update && apt-get install -y --no-install-recommends curl wget unzip tar xz-utils ca-certificates\r\n\r\ncd /mnt/server\r\n\r\n## --- IW4X launcher (Linux) ---\r\necho \"Fetching IW4X launcher...\"\r\nwget -q https://github.com/iw4x/launcher/releases/latest/download/launcher-x86_64-linux-glibc.tar.xz -O launcher.tar.xz || \\\r\n wget -q https://github.com/iw4x/launcher/releases/download/v1.1.8-b.18/launcher-1.1.8-b.18-x86_64-linux-glibc.tar.xz -O launcher.tar.xz\r\ntar xf launcher.tar.xz\r\nrm -f launcher.tar.xz\r\nchmod +x iw4x-launcher || true\r\n\r\n## --- IW4X client dll (the mod itself) ---\r\necho \"Fetching iw4x.dll...\"\r\ncurl -L https://github.com/iw4x/iw4x-client/releases/latest/download/iw4x.dll -o iw4x.dll\r\n\r\n## --- IW4X raw files (assets + iw4x.exe) ---\r\necho \"Fetching raw files...\"\r\ncurl -L https://github.com/iw4x/iw4x-rawfiles/releases/latest/download/release.zip -o release.zip\r\nunzip -o release.zip -d /mnt/server\r\nrm -f release.zip\r\n\r\n## --- Server configs + launch scripts ---\r\necho \"Fetching server configs...\"\r\nwget -q https://github.com/iw4x/iw4-server-configs/archive/refs/heads/main.zip -O configs.zip\r\nunzip -o configs.zip\r\ncp -rf iw4-server-configs-main/* /mnt/server/ 2>/dev/null || true\r\nrm -rf iw4-server-configs-main configs.zip\r\nrm -f LICENSE README.md 2>/dev/null || true\r\n\r\necho \"-----------------------------------------\"\r\necho \"IW4X files installed.\"\r\necho \"IMPORTANT: upload your legally-owned MW2 game files into /home/container\"\r\necho \"(iw4mp.exe and the game assets) if they are not already present.\"\r\necho \"Also upload start-iw4x.sh to /home/container and it will be used at boot.\"\r\necho \"-----------------------------------------\"", + "container": "ghcr.io/pterodactyl/installers:debian", + "entrypoint": "bash" + } + }, + "variables": [ + { + "name": "Mod Dir", + "description": "Name of the directory where the mod lives (fs_game). Leave blank for none.", + "env_variable": "MOD_DIR", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string", + "field_type": "text" + }, + { + "name": "Server Port", + "description": "UDP port the server listens on (default 28960).", + "env_variable": "SERVER_PORT", + "default_value": "28960", + "user_viewable": true, + "user_editable": true, + "rules": "required|integer", + "field_type": "text" + }, + { + "name": "LAN Mode", + "description": "0 = public (send heartbeats to master list). 1 = LAN/unlisted.", + "env_variable": "LAN_MODE", + "default_value": "0", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Server Config File", + "description": "Which cfg in userraw/ to exec. server.cfg (dedicated) or partyserver.cfg (lobby).", + "env_variable": "SERVER_CFG", + "default_value": "server.cfg", + "user_viewable": true, + "user_editable": true, + "rules": "required|string", + "field_type": "text" + }, + { + "name": "Log File", + "description": "Enable server logging (1 on, 0 off).", + "env_variable": "LOG_FILE", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Server Name", + "description": "Sets sv_hostname. Color codes: ^1 Red ^2 Green ^3 Yellow ^4 Blue ^5 Cyan ^6 Pink ^7 White.", + "env_variable": "SERVER_NAME", + "default_value": "My IW4X Server", + "user_viewable": true, + "user_editable": true, + "rules": "required|string|max:100", + "field_type": "text" + }, + { + "name": "Server Password", + "description": "Leave blank for public, or set a password for a private server.", + "env_variable": "SERVER_PASSWORD", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string|max:100", + "field_type": "text" + } + ] +} diff --git a/start-iw4x.sh b/start-iw4x.sh new file mode 100644 index 0000000..ddeb5a1 --- /dev/null +++ b/start-iw4x.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# ========================================================================== +# IW4X startup wrapper (place at /home/container/start-iw4x.sh, chmod +x) +# Called by the egg's Startup Command. +# ========================================================================== +cd /home/container || exit 1 + +export WINEARCH=win32 +export WINEPREFIX=/home/container/.wine +export WINEDEBUG="${WINEDEBUG:--all}" + +# --- Seed the known-good 32-bit prefix baked into the image (first boot) --- +# The image ships a fully-initialised win32 prefix at /opt/wine-prefix with +# vcrun2019 + d3dcompiler_47 already installed. If the volume doesn't have a +# valid win32 prefix yet, copy it in. This avoids the stock entrypoint +# rebuilding a broken win64 prefix. +if [ ! -f "${WINEPREFIX}/system.reg" ] || ! grep -q '#arch=win32' "${WINEPREFIX}/system.reg" 2>/dev/null; then + echo "[iw4x] Seeding fresh win32 wine prefix from image..." + rm -rf "${WINEPREFIX}" + cp -a /opt/wine-prefix "${WINEPREFIX}" + echo "[iw4x] Prefix ready: $(head -1 ${WINEPREFIX}/system.reg)" +else + echo "[iw4x] Existing win32 prefix detected, reusing it." +fi + +# --- Update IW4X client files via the official launcher (no Steam login) --- +if [ -f ./iw4x-launcher ]; then + echo "[iw4x] Running launcher update..." + ./iw4x-launcher --update +fi + +# --- Launch the dedicated server ------------------------------------------ +# Mirrors the official DedicatedServer.sh invocation. +echo "[iw4x] Launching server..." +exec wine iw4x.exe -dedicated -stdout \ + +set fs_game "${MOD_DIR}" \ + +set sv_lanonly "${LAN_MODE:-0}" \ + +set net_port "${SERVER_PORT}" \ + +exec "${SERVER_CFG:-server.cfg}" \ + +set logfile "${LOG_FILE:-1}" \ + +set party_enable "0" \ + +map_rotate