Skip to content

Blueprint - Batocera

This advanced example demonstrates how to use the Blueprint FlatImage (an empty container) to create a custom Batocera Linux portable gaming system. Batocera is a retro-gaming distribution, and this example shows how to fetch an external system image, extract it, customize it (removing Nvidia packages), and integrate it into a FlatImage.

This guide uses an Alpine FlatImage as a toolbox to provide all necessary build tools without installing anything on your host system.


Overview

This example demonstrates:

  • Using Alpine FlatImage as a portable toolbox for build dependencies
  • Using the Blueprint (empty) FlatImage as a base
  • Fetching and extracting an external Linux distribution
  • Modifying the extracted system (removing specific packages)
  • Dumping the root filesystem into a FlatImage layer
  • Creating a completely custom portable gaming environment

Prerequisites

Download the the Alpine FlatImage to create a toolbox:

wget -O toolbox.flatimage https://github.com/flatimage/flatimage/releases/latest/download/alpine-x86_64.flatimage
chmod +x ./toolbox.flatimage

Configure the toolbox with necessary permissions and tools:

# Bind mount the working directory so toolbox can access it
./toolbox.flatimage fim-bind add rw $PWD $PWD
# Grant network access
./toolbox.flatimage fim-perms set network
# Install required tools inside the Alpine container
./toolbox.flatimage fim-root apk add wget curl xz squashfs-tools-ng util-linux coreutils findutils
# Set default boot command so we can run commands directly
./toolbox.flatimage fim-boot set bash -c '"$@"' --

Now the toolbox can be used like a regular command without fim-exec!


Step 1 - Download Blueprint FlatImage

The Blueprint image is an empty container with no pre-installed distribution:

wget -O batocera.flatimage https://github.com/flatimage/flatimage/releases/latest/download/blueprint-x86_64.flatimage
# Make it executable
chmod +x ./batocera.flatimage
# Set permissions
./batocera.flatimage fim-perms set media,audio,wayland,xorg,dev,udev,dbus_user,usb,input,gpu,network

Step 2 - Download Batocera Image

Use the Alpine toolbox to fetch the latest Batocera Linux image:

# Download Batocera (x86_64 version) using the toolbox
./toolbox.flatimage wget -O boot.tar.xz https://mirrors.o2switch.fr/batocera/x86_64/stable/last/boot.tar.xz

Step 3 - Extract Batocera Root Filesystem

Use the Alpine toolbox to extract the SquashFS filesystem without needing root:

# Extract the tarball
tar xf boot.tar.xz boot/batocera.update
# Extract the sqfs image
./toolbox.flatimage rdsquashfs -C -u / -p ./root ./boot/batocera.update
# Set executable permission bits for binaries
chmod -R 755 root/bin root/usr/bin

Step 4 - Remove Unused Packages

Use the Alpine toolbox to remove Nvidia proprietary drivers and other packages. Nvidia drivers are bound from the host, so there is no need to keep the ones in the guest.

# Remote builtin nvidia drivers
./toolbox.flatimage find root -iname "*nvidia*" -exec rm -rf "{}" \; || true
# Remote kernel modules
rm -rf root/lib/modules
# Remote firmware files
rm -rf root/lib/firmware

Step 5 - Create required files/directories

mkdir -p root/userdata/system/logs
mkdir -p root/var/run

--

Step 6 - Create FlatImage Layer from Batocera Root

Create a layer from the root directory and append it to the image.

# Create layer
./batocera.flatimage fim-layer create ./root root.layer
# Append layer
./batocera.flatimage fim-layer add root.layer

Step 7 - Configure Environment

Set up the Batocera environment:

# Set environment variables
./batocera.flatimage fim-env add \
  'HOME=/userdata' \
  'USER=batocera' \
  'XDG_CONFIG_HOME=/userdata/system/configs' \
  'XDG_CACHE_HOME=/userdata/system/cache' \
  'XDG_DATA_HOME=/userdata/system/data'

Step 8 - Set Boot Command

Configure Batocera's startup command as emulationstation:

./batocera.flatimage fim-boot set emulationstation

Step 9 - Desktop Integration (Optional)

Create desktop integration for launching Batocera:

# Create desktop integration configuration
tee batocera.json <<-'EOF'
{
  "name": "batocera",
  "icon": "https://upload.wikimedia.org/wikipedia/commons/e/ef/Batocera-logo-art.png",
  "categories": ["Game"],
}
EOF

# Setup desktop integration
./batocera.flatimage fim-desktop setup ./batocera.json

# Enable integrations
./batocera.flatimage fim-desktop enable icon,entry,mimetype

# Enable startup notification
./batocera.flatimage fim-notify on

Running Batocera

Launch Batocera with:

./batocera.flatimage

All Batocera data (ROMs, saves, configurations) will be stored in the .batocera.flatimage.data directory, making it fully portable.


Complete Script

Here's a complete automated script combining all steps using the Alpine toolbox:

#!/bin/bash
set -euo pipefail

# Step 0 - Download and configure Alpine toolbox
echo "Setting up Alpine toolbox..."
wget -O toolbox.flatimage https://github.com/flatimage/flatimage/releases/latest/download/alpine-x86_64.flatimage
chmod +x ./toolbox.flatimage

# Configure the toolbox
./toolbox.flatimage fim-bind add rw $PWD $PWD
./toolbox.flatimage fim-perms set network
./toolbox.flatimage fim-root apk add wget curl xz squashfs-tools-ng util-linux coreutils findutils || true
./toolbox.flatimage fim-boot set bash -c '"$@"' --

# Step 1 - Download Blueprint FlatImage
echo "Downloading Blueprint FlatImage..."
wget -O batocera.flatimage https://github.com/flatimage/flatimage/releases/latest/download/blueprint-x86_64.flatimage
chmod +x ./batocera.flatimage
./batocera.flatimage fim-perms set media,audio,wayland,xorg,dev,udev,dbus_user,usb,input,gpu,network

# Step 2 - Download Batocera Image
echo "Downloading Batocera image..."
./toolbox.flatimage wget -O boot.tar.xz https://mirrors.o2switch.fr/batocera/x86_64/stable/last/boot.tar.xz

# Step 3 - Extract Batocera Root Filesystem
echo "Extracting Batocera root filesystem..."
tar xf boot.tar.xz boot/batocera.update
./toolbox.flatimage rdsquashfs -C -u / -p ./root ./boot/batocera.update
chmod -R 755 root/bin root/usr/bin

# Step 4 - Remove Unused Packages
echo "Removing unused packages..."
./toolbox.flatimage find root -iname "*nvidia*" -exec rm -rf "{}" \; || true
rm -rf root/lib/modules
rm -rf root/lib/firmware

# Step 5 - Create required files/directories
mkdir -p root/userdata/system/logs
mkdir -p root/var/run

# Step 6 - Create FlatImage Layer from Batocera Root
echo "Creating FlatImage layer..."
./batocera.flatimage fim-layer create ./root root.layer
./batocera.flatimage fim-layer add root.layer

# Step 7 - Configure Environment
echo "Configuring environment..."
./batocera.flatimage fim-env add \
  'HOME=/userdata' \
  'USER=batocera' \
  'XDG_CONFIG_HOME=/userdata/system/configs' \
  'XDG_CACHE_HOME=/userdata/system/cache' \
  'XDG_DATA_HOME=/userdata/system/data'

# Step 8 - Set Boot Command
echo "Setting boot command..."
./batocera.flatimage fim-boot set emulationstation

# Step 9 - Desktop Integration (Optional)
echo "Setting up desktop integration..."
tee batocera.json <<-'EOF'
{
  "name": "batocera",
  "icon": "https://upload.wikimedia.org/wikipedia/commons/e/ef/Batocera-logo-art.png",
  "categories": ["Game"],
}
EOF

./batocera.flatimage fim-desktop setup ./batocera.json
./batocera.flatimage fim-desktop enable icon,entry,mimetype
./batocera.flatimage fim-notify on

echo "Batocera FlatImage setup complete!"
echo "Run with: ./batocera.flatimage"

Next Steps

Setup Bindings

  • By default use RO, but for scraping use RW
  • List bindings with fim-bind list
  • Erase bindings with fim-bind del <index>
./batocera.flatimage fim-bind add ro '$FIM_DIR_DATA/batocera/roms' /userdata/roms
./batocera.flatimage fim-bind add ro '$FIM_DIR_DATA/batocera/bios' /userdata/bios

Bios and Roms

In the same directory as batocera.flatimage create the rom/bios folders.

mkdir -p .batocera.flatimage.data/batocera/roms .batocera.flatimage.data/batocera/bios

Now copy the bios files and rom files to these directories, for example:

.batocera.flatimage.data
└── batocera
    ├── bios
    │   ├──cph1001.bin
    │   ├── ...
    │   ├──cph5502.bin
    │   └──cph7001.bin
    └── roms
        └── psx
            └── game.chd

References