Ansible playbooks for an Arch-based distrobox named gaming. Sets up ES-DE,
standalone emulators (shadPS4, Dolphin, PCSX2, DuckStation, Flycast, xemu,
RPCS3, PPSSPP, Eden, Cemu, Vita3K), RetroArch cores, host-side Walker desktop
launcher rendering/install scripts, DLC/patch batch installers for PS3 and Switch, per-game RPCS3
optimization configs, optional Wine-managed Xenia Manager for Xbox 360,
Hedge Mod Manager for Sonic mods, optional native Unleashed Recompiled for
Sonic Unleashed, and a minimal zsh + starship shell inside the box.
cd ansible
ansible-galaxy collection install -r collections/requirements.yml
cp host_vars/localhost.yml.example host_vars/localhost.yml
$EDITOR host_vars/localhost.yml
ansible-playbook site.ymlFor a full run with optional Xbox 360/Xenia Manager:
ansible-playbook site.yml
ansible-playbook install-xenia.ymlAll commands run from the ansible/ directory:
ansible-playbook site.yml # full setup from scratch
ansible-playbook reset-configs.yml # reset emulator configs without rebuilding
ansible-playbook backup.yml # backup before destructive testing
ansible-playbook restore.yml # restore from backup
ansible-playbook refresh-shadps4.yml # update shadPS4 builds
ansible-playbook install-xenia.yml # install/update Xenia Manager (optional)
ansible-playbook install-hedgemodmanager.yml # install/update Hedge Mod Manager
ansible-playbook install-pc-racing.yml # prepare/install optional Windows PC racing games
ansible-playbook install-outrun-2006.yml # install/update OutRun 2006
ansible-playbook install-sega-rally-revo.yml # install/update Sega Rally Revo
ansible-playbook install-sonic-p06.yml # install/update Sonic Project '06
ansible-playbook install-unleashed-recomp.yml # install/update Unleashed RecompiledTags allow running subsets:
ansible-playbook site.yml --tags check # host path and UID/GID validation
ansible-playbook site.yml --tags create # create the distrobox
ansible-playbook site.yml --tags bootstrap # install pacman + AUR packages
ansible-playbook site.yml --tags shadps4 # install/update shadPS4
ansible-playbook site.yml --tags hedgemodmanager # install/update Hedge Mod Manager
ansible-playbook site.yml --tags configure # configs, desktop entries, ES-DE
ansible-playbook site.yml --tags scripts # deploy box helper scripts
ansible-playbook site.yml --tags shell # deploy zsh + starship
ansible-playbook site.yml --tags verify # post-setup assertions
ansible-playbook reset-configs.yml --tags esde # reset only ES-DE
ansible-playbook reset-configs.yml --tags configs # reset only emulator INIs
ansible-playbook reset-configs.yml --tags desktop # reset only desktop entries
ansible-playbook reset-configs.yml --tags shell # reset only zsh/starshipThese roles touch your specific ROM/NAS layout or perform large downloads, so they only run when the matching tag is explicitly passed:
ansible-playbook site.yml --tags dlcs # install PS3 DLCs + Switch NSPs
ansible-playbook site.yml --tags cheats # link Switch cheats to Eden
ansible-playbook site.yml --tags rpcs3_configs # per-game RPCS3 tuning
ansible-playbook site.yml --tags retroarch # download RA cores + assets
ansible-playbook site.yml --tags pcsx2_textures # PCSX2 HD texture packs + per-game settings + .pnach patches
ansible-playbook site.yml --tags pc_racing # prepare tested Windows PC racing games via Wine
ansible-playbook site.yml --tags sonic_p06 # install Sonic Project '06 via system Wine
ansible-playbook site.yml --tags unleashed_recomp # install native Unleashed Recompiled FlatpakAll paths are configurable via Ansible variables. Defaults match the current machine's NAS layout:
dg_box_name: gaming
dg_host_uid: 1026 # NAS requires this UID
dg_host_gid: 1026
dg_data_root: /mnt/data
dg_box_home: /mnt/data/distrobox/gaming
dg_external_games_root: /mnt/terachad/Emulators
dg_roms_final_root: "{{ dg_external_games_root }}/ROMS_FINAL"
dg_emudeck_root: "{{ dg_external_games_root }}/EmuDeck"
dg_bios_root: "{{ dg_emudeck_root }}/Emulation/bios"
dg_rom_root: "{{ dg_emudeck_root }}/roms"
dg_rom_heavy_root: "{{ dg_emudeck_root }}/roms_heavy"
dg_ps3_dlc_source: "{{ dg_rom_heavy_root }}/ps3-DLC"
dg_switch_updates_source: "{{ dg_rom_heavy_root }}/switch_updates"
dg_switch_cheats_source: "{{ dg_rom_heavy_root }}/switch_cheats"For another machine, create ansible/host_vars/localhost.yml and override any
variable. Or pass overrides on the command line:
ansible-playbook site.yml -e dg_data_root=/home/me/gaming -e dg_external_games_root=/media/gamesOn systems with both an NVIDIA dGPU and an AMD iGPU, emulators are forced to
use NVIDIA by injecting VK_ICD_FILENAMES into every desktop launcher and
ES-DE command. The distrobox is also created with --nvidia so NVIDIA drivers
are bind-mounted into the container. Controlled by dg_nvidia_enabled: true
in group_vars/all/gpu.yml. Set to false to disable.
For Steam/Proton, the launcher also exports
PRESSURE_VESSEL_APP_LD_LIBRARY_PATH to an Ansible-managed extraction of the
matching lib32-nvidia-utils package. This avoids a distrobox --nvidia
edge case where host 64-bit NVIDIA libraries can appear under /usr/lib32,
breaking 32-bit DXVK games such as Sonic Adventure DX.
If you screw up your emulator configs (ES-DE, DuckStation, PCSX2, etc.) and want to restore to Ansible-managed defaults without reinstalling the box:
ansible-playbook reset-configs.yml # reset everything
ansible-playbook reset-configs.yml --tags esde # reset only ES-DE
ansible-playbook reset-configs.yml --tags configs # reset only emulator INIs
ansible-playbook reset-configs.yml --tags shell # reset only zsh/starshipThis re-applies seed_configs, desktop_apps, configure_esde, and
shell_config roles. Existing files are backed up automatically before
overwriting.
Before destructive testing (e.g. rebuilding from scratch):
ansible-playbook backup.yml # commits container image + archives configs
ansible-playbook restore.yml # prompts for timestamp, restores bothBackups are stored under $DG_BOX_HOME/backups/.
The NAS requires UID/GID 1026 for file access. The check_host role asserts
the host user matches dg_host_uid before proceeding. The container user
inherits the host UID/GID through distrobox.
Override for another machine:
# ansible/host_vars/localhost.yml
dg_host_uid: 1000
dg_host_gid: 1000- Arch-based distrobox named
gamingwith--nvidiadrivers bind-mounted - Pacman and AUR emulator packages (see
group_vars/all/packages.yml) - ES-DE (emulationstation-de) as the frontend
- RetroArch plus 21 buildbot cores (fbneo, mednafen variants, etc.) and all 8 asset packs (info, assets, autoconfig, cheats, databases, shaders, overlays) — ~760 MB total
- Minimal zsh + starship prompt inside the box
- Flycast high-resolution wrapper at
$DG_BOX_HOME/bin/flycast-hires - PCSX2: Vulkan @ 4x upscale (4K from PS2 480p), widescreen 16:9, 16x AF,
PS2 bilinear filtering, built-in widescreen patches enabled, full
Xbox-style Pad1 binding via SDL backend,
Select+Startshutdown hotkey - Dolphin 8BitDo Ultimate 2 defaults for GameCube and Wii profiles
- DuckStation Vulkan/PGXP/widescreen defaults
- xemu config plus BIOS/HDD links from
$DG_BIOS_ROOT - shadPS4 wrapper launching QtLauncher-managed builds, Driveclub-specific
CUSA00003.tomlconfig with v1.28 patch XML, PS4 11.00 sys_module symlinks
-
PS3 DLCs and patches:
install_dlcsrole batch-extracts every .pkg from$DG_PS3_DLC_SOURCEinto RPCS3'sdev_hdd0/game/— bypasses the GUI-only installer limitation -
Switch updates and DLC: same role extracts NSPs from
$DG_SWITCH_UPDATES_SOURCEinto Eden's NAND at~/.local/share/eden/nand/user/Contents/registered/ -
Switch cheats:
switch_cheatsrole symlinks Atmosphere-format cheats from$DG_SWITCH_CHEATS_SOURCEinto Eden's load path -
Per-game RPCS3 configs:
rpcs3_per_game_configsrole scans installed PS3 games, queries the RPCS3 compatibility API, and writes tunedcustom_configs/<TITLE_ID>_config.ymlfor games with "Ingame" or "Loadable" status. Hand-curated overrides for known-problematic titles (Gran Turismo 6, Gran Turismo 5, Metal Gear Solid 4). -
PCSX2 HD texture packs + per-game settings + .pnach patches:
pcsx2_texturesrole symlinks per-game texture replacement directories into~/.config/PCSX2/textures/<SERIAL>/replacements/<link_as>/(no copy — textures live on NAS, PCSX2 caches in RAM after first load), symlinks.pnachpatch files into~/.config/PCSX2/patches/, mass-symlinks~/.config/PCSX2/cheats/from a NAS cheats source, downloads a curated list of public.pnachURLs (e.g. Silent's GT4 USA patches from his GitHub), and writes per-game override INIs to~/.config/PCSX2/gamesettings/<SERIAL>.ini. Initial configs cover Gran Turismo 4 (SCUS-97328) with Silentwarior112's HD HUD/UI pack + update 2.1- blocky-haze-fix overlay + Silent's adjusted triggers / GT3 cam / far
chase cam patches, and Enthusia Professional Racing (SLUS-20967) HD
textures. Adding more games is a YAML data change to
dg_pcsx2_texture_packs,dg_pcsx2_per_game_settings,dg_pcsx2_extra_patches, anddg_pcsx2_patch_urlsingroup_vars/all/pcsx2.yml.
Texture pack updates are a manual process — the source forums (GTPlanet, Nexus Mods, Silent's Blog) are Cloudflare-walled and Drive/MEGA links throttle scripted downloads. Check periodically:
- GT4 retexture mod: https://www.gtplanet.net/forum/threads/gran-turismo-4-retexture-mod-v2-2.408852/
- Silentwarior's HD HUD/UI pack: https://cookieplmonster.github.io/mods/gran-turismo-4/
- Silent's pnach patches: https://silentsblog.com/mods/gran-turismo-4/
When a new version drops, download manually and drop into the existing pack directory in your NAS — the role re-symlinks on next run.
- blocky-haze-fix overlay + Silent's adjusted triggers / GT3 cam / far
chase cam patches, and Enthusia Professional Racing (SLUS-20967) HD
textures. Adding more games is a YAML data change to
- Repo-managed Walker desktop entries for every emulator, defined as data in
group_vars/all/launchers.ymland rendered via a single Jinja2 template. Each Exec line is wrapped with the NVIDIA-preference env vars. - Entries cover: ES-DE, Dolphin, DuckStation, PCSX2, PPSSPP, RPCS3, xemu, Eden, Cemu, Vita3K, shadPS4 (Driveclub + No Patch + GUI), Flycast, Xenia Manager, Sonic P-06, and Unleashed Recompiled when their wrappers exist.
- Ansible renders entries into
config/desktop/rendered/; it does not write into the host applications directory from inside the distrobox. Install or refresh host menu entries from the host with:
scripts/install-host-launchers.shThe script validates every rendered .desktop file, skips optional apps that
are not installed in the box, removes stale installed entries for missing
optional apps, and restarts Walker if it is running.
- Wine-managed Xenia Manager with .NET/VC++ runtimes for Xbox 360
The install_dlcs role also deploys standalone scripts into the box that you
can run manually for advanced tasks:
# List / download missing PS3 patches from PSN's public update server
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \
"$DG_ROM_HEAVY_ROOT/ps3" \
--dlc-dir "$DG_PS3_DLC_SOURCE" --list
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \
"$DG_ROM_HEAVY_ROOT/ps3" \
--dlc-dir "$DG_PS3_DLC_SOURCE" \
--download-dir "$DG_BOX_HOME/dlc-temp" --download
# List outdated Switch games (Nintendo's CDN needs console auth, so no download)
python3 $DG_BOX_HOME/scripts/check_switch_updates.py \
"$DG_ROM_HEAVY_ROOT/switch" \
--updates-dir "$DG_SWITCH_UPDATES_SOURCE"
# Reorganize a messy switch_updates dump into per-title-ID folders
# (handles .nsp/.nsz/.xci/.xcz; mods and non-patch files are left alone)
python3 $DG_BOX_HOME/scripts/reorganize_switch_nsps.py \
"$DG_SWITCH_UPDATES_SOURCE" --dry-runNote on Switch updates: Nintendo's update CDN requires device-specific
certificates from a hacked Switch. check_switch_updates.py only reports
what's outdated (using the public blawar/titledb version database) — you
source the NSPs yourself.
- Check what's outdated:
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \ $DG_ROM_HEAVY_ROOT/ps3 --dlc-dir $DG_ROM_HEAVY_ROOT/ps3-DLC --list
- Download missing patches to a temp dir (keeps the NAS dir read-only
until you review):
python3 $DG_BOX_HOME/scripts/check_ps3_updates.py \ $DG_ROM_HEAVY_ROOT/ps3 --dlc-dir $DG_ROM_HEAVY_ROOT/ps3-DLC \ --download-dir $DG_BOX_HOME/dlc-temp --download
- Review
$DG_BOX_HOME/dlc-temp, then copy into the canonical cache:rsync -av $DG_BOX_HOME/dlc-temp/ $DG_ROM_HEAVY_ROOT/ps3-DLC/
- Re-run the install_dlcs role to extract them into RPCS3:
cd ansible && ansible-playbook site.yml --tags dlcs
The extract_ps3_dlc.py extractor uses the PKG's filename version
(e.g. -A0122-V0100-) and compares against the destination's
PARAM.SFO VERSION to decide whether to re-extract. Re-running after
all patches are applied is a no-op.
Some PS3 games regress on current RPCS3 when patched to the latest version (GT6 is notorious — older RPCS3 builds broke above 1.12 or so). To cap a game at a specific patch level:
# Wipe the current patch content dir so the version check doesn't block
rm -rf $DG_BOX_HOME/.config/rpcs3/dev_hdd0/game/<CONTENT_ID>
# Re-extract only patches up to the target version
python3 $DG_BOX_HOME/scripts/extract_ps3_dlc.py \
$DG_ROM_HEAVY_ROOT/ps3-DLC/<TITLE_ID> \
--max-version 01.12--max-version skips any patch PKG whose filename-encoded version
exceeds the limit. Without the rm -rf first, the version-aware
idempotency check would refuse to downgrade.
The expected layout is clean extracted title directories, not raw .pkg files:
$DG_PS4_ROM_ROOT/
CUSA00003/
eboot.bin
...
Xbox 360 support uses Xenia Manager inside a dedicated Wine prefix.
ansible-playbook install-xenia.yml will:
- Enable
multilibinside the box - Install
wineandwinetricks - Create the Wine prefix with .NET and VC++ runtimes
- Download the latest Xenia Manager release
- Write the launcher wrapper and render its desktop entry
After that, launch Xenia Manager and use its Manage page to install Canary.
Sonic mod support uses Hedge Mod Manager 8 built natively inside the distrobox,
not host Flatpak. The default site.yml run installs it; rerun only that role
with:
ansible-playbook install-hedgemodmanager.ymlThe wrapper is written to {{ dg_box_home }}/bin/hedge-mod-manager.
It sees the same Steam install and external library paths as Steam inside the
box, including the Proton prefixes under steamapps/compatdata.
Windows PC racing games are optional and live outside the normal rebuild path. They use system Wine inside the distrobox:
ansible-playbook install-pc-racing.ymlThe install root is {{ dg_pc_racing_install_root }}; per-game prefixes stay
under {{ dg_pc_racing_prefix_root }}.
Installer GUIs are only launched when explicitly requested with
-e dg_pc_racing_run_installers=true.
Sonic P-06 is an optional Windows Unity fangame install managed outside Steam with system Wine, DXVK, core fonts, GStreamer codecs, and a dedicated prefix:
ansible-playbook install-sonic-p06.ymlThe source is the already extracted Silver Release under
{{ dg_sonic_p06_source_dir }}. The managed copy lives at
{{ dg_sonic_p06_install_root }}.
ansible/ # Ansible playbooks and roles (primary)
site.yml # full setup playbook
reset-configs.yml # config-only reset playbook
backup.yml / restore.yml # backup and restore
refresh-shadps4.yml # standalone shadPS4 update
install-xenia.yml # standalone Xenia Manager install
install-hedgemodmanager.yml # standalone Hedge Mod Manager install
install-pc-racing.yml # optional Windows PC racing setup
install-outrun-2006.yml # focused OutRun 2006 install
install-sega-rally-revo.yml # focused Sega Rally Revo install
install-sonic-p06.yml # optional Sonic Project '06 setup
install-unleashed-recomp.yml # optional Unleashed Recompiled install
group_vars/all/ # all dg_* variable defaults
main.yml # paths, UID/GID, box identity
packages.yml # pacman + AUR package lists
emulators.yml # per-emulator INI settings
esde.yml # ES-DE system definitions
launchers.yml # rendered host desktop launcher definitions
gpu.yml # NVIDIA preference config
shadps4.yml # shadPS4 release / path config
xenia.yml # Xenia Manager config
hedgemodmanager.yml # Hedge Mod Manager source-build config
pc_racing.yml # Windows PC racing source/install metadata
sonic_p06.yml # Sonic Project '06 Wine config
unleashed_recomp.yml # Unleashed Recompiled source staging config
pcsx2.yml # PCSX2 texture packs and per-game overrides
host_vars/localhost.yml.example # machine-specific overrides template
roles/ # one role per setup phase
check_host/ # host validation
create_box/ # distrobox creation (--nvidia)
bootstrap_packages/ # pacman + AUR packages
link_storage/ # BIOS/firmware symlinks
seed_configs/ # emulator INI settings, wrappers
scripts_in_box/ # deploy Python helpers into box
install_dlcs/ # PS3 PKG + Switch NSP batch install
switch_cheats/ # symlink cheats into Eden load path
rpcs3_per_game_configs/ # per-title RPCS3 tuning from API
retroarch_extras/ # 21 buildbot cores + 8 asset packs
pcsx2_textures/ # PCSX2 HD textures + per-game settings + .pnach patches
desktop_apps/ # .desktop entry rendering
configure_esde/ # ES-DE custom systems XML
shell_config/ # minimal zsh + starship
verify/ # post-setup assertions
refresh_shadps4/ # shadPS4 GitHub release management
install_xenia/ # Wine prefix and Xenia Manager
install_hedgemodmanager/ # native HMM 8 source build
install_pc_racing/ # Wine wrappers for tested Windows racing games
install_sonic_p06/ # Wine wrapper for Sonic Project '06
install_unleashed_recomp/ # native Unleashed Recompiled Flatpak install
bin/ # legacy shell CLI (reference)
scripts/ # legacy numbered scripts (reference)
lib/ # legacy shell helpers (reference)
config/ # static config files and package lists
docs/ # historical notes and focused docs
Historical notes:
Focused docs:
- Driveclub shadPS4 — working v1.00 install recipe via DriveClubFS, all dead ends captured (read before touching Driveclub again)
- Flycast Resolution
- Controller Hotkeys
- Rebuild Runbook
- Xenia Manager
- Hedge Mod Manager
- PC Racing Games
- Sonic Project '06
- Project Forza Plus (FM2/3/4/FH1 on Xenia)
- Xbox 360 Title Updates — archive.org batch fetch + Xenia Manager install flow
- Xbox 360 PGR3 / PGR4
- GT4 Spec II on PCSX2
- PS1 60 FPS patches (Colin McRae Rally)
This repo does not provide ROMs, BIOS files, firmware, keys, or game packages.
Playbooks only detect, link, and configure files that already exist on your machine. They should not delete ROMs, BIOS, saves, firmware, or game data.
Generated emulator state, shader caches, saves, logs, firmware modules, and ROMs must not be committed.