Improve Docker support with configurable permissions and SMB compatibility

Added flexible user/group ID handling to support different storage backends:

- Configurable PUID/PGID environment variables for NFS and local storage
- RUN_AS_ROOT mode for SMB mounts that only allow root writes
- Pre-chown app files during build to enable non-root rsync
- Improved error messages with troubleshooting guidance
- Updated documentation with setup examples for different scenarios

This allows the container to work correctly with Unraid SMB shares, NFS mounts,
and local storage by adapting to how different filesystems handle permissions.

Default behavior (PUID=99, PGID=100) remains compatible with Unraid nobody:users.
This commit is contained in:
shane keulen
2025-11-04 00:36:40 -05:00
parent 0c55d6d6d6
commit 0f671ccdf2
3 changed files with 137 additions and 40 deletions

View File

@@ -5,6 +5,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
p7zip-full \
unrar-free \
curl \
rsync \
gosu \
&& rm -rf /var/lib/apt/lists/*
# Create required directories

View File

@@ -5,10 +5,20 @@ Run RGSX as a web-only service without the Pygame UI. Perfect for homelab/server
## Quick Start
```bash
# Clone and start
git clone https://github.com/RetroGameSets/RGSX.git
cd RGSX
docker-compose up -d
# Build the image
docker build -t rgsx .
# Run with docker
docker run -d \
--name rgsx \
-p 5000:5000 \
-e PUID=99 \
-e PGID=100 \
-e RGSX_HEADLESS=1 \
-v ./data/saves:/userdata/saves/ports/rgsx \
-v ./data/roms:/userdata/roms/ports \
-v ./data/logs:/userdata/roms/ports/RGSX/logs \
rgsx
# Access the web interface
open http://localhost:5000
@@ -23,22 +33,47 @@ open http://localhost:5000
## Configuration
### User Permissions (Important!)
**For SMB mounts (Unraid, Windows shares):**
Don't set PUID/PGID. The container runs as root, and the SMB server maps files to your authenticated user.
```bash
docker run \
-e RGSX_HEADLESS=1 \
...
```
**For NFS/local storage:**
Set PUID and PGID to match your host user. Files will be owned by that user.
```bash
docker run \
-e PUID=1000 \
-e PGID=1000 \
-e RGSX_HEADLESS=1 \
...
```
**Find your user ID:**
```bash
id -u # Your UID
id -g # Your GID
```
### Change Port
Edit `docker-compose.yml`:
```yaml
ports:
- "8080:5000" # Host port : Container port
```bash
docker run -p 8080:5000 ... # Access on port 8080
```
### Custom ROM Location
Map to your existing ROM collection:
```yaml
volumes:
- ./data/saves:/userdata/saves/ports/rgsx
- /your/existing/roms:/userdata/roms # Change this
- ./data/logs:/app/RGSX/logs
```bash
docker run -v /your/existing/roms:/userdata/roms/ports ...
```
### API Keys
@@ -46,9 +81,6 @@ volumes:
Add your download service API keys to `./data/saves/`:
```bash
# Start container once to create directories
docker-compose up -d
# Add your API key (just the key, no extra text)
echo "YOUR_KEY_HERE" > ./data/saves/1FichierAPI.txt
@@ -57,24 +89,25 @@ echo "YOUR_KEY" > ./data/saves/AllDebridAPI.txt
echo "YOUR_KEY" > ./data/saves/RealDebridAPI.txt
# Restart to apply
docker-compose restart
docker restart rgsx
```
## Commands
```bash
# Start
docker-compose up -d
docker start rgsx
# View logs
docker-compose logs -f
docker logs -f rgsx
# Stop
docker-compose down
docker stop rgsx
# Update (after git pull)
docker-compose build --no-cache
docker-compose up -d
docker build --no-cache -t rgsx .
docker stop rgsx && docker rm rgsx
# Then re-run the docker run command
```
## Directory Structure
@@ -95,20 +128,39 @@ RGSX already has a headless mode (`RGSX_HEADLESS=1`) and the web server (`rgsx_w
## Troubleshooting
**Port already in use:**
**Permission denied errors / Can't delete files:**
The container creates files with the UID/GID specified by PUID/PGID environment variables:
```bash
# Use different port
sed -i '' 's/5000:5000/8080:5000/' docker-compose.yml
# Set correct PUID/PGID for your environment
docker run -e PUID=1000 -e PGID=1000 ...
```
**Permission errors:**
**Changed PUID/PGID and container won't start:**
When you change PUID/PGID, old files with different ownership will cause rsync to fail. You MUST fix ownership on the storage server:
```bash
sudo chown -R $USER:$USER ./data
# On your NAS/Unraid (via SSH), either:
# Option 1: Delete old files (easiest)
rm -rf /mnt/user/roms/rgsx/roms/ports/RGSX/*
# Option 2: Change ownership to new PUID/PGID
chown -R 1000:1000 /mnt/user/roms/rgsx/roms/ports/RGSX/
```
Then restart the container.
**Port already in use:**
```bash
docker run -p 8080:5000 ... # Use port 8080 instead
```
**Container won't start:**
```bash
docker-compose logs
docker logs rgsx
```
## vs Traditional Install
@@ -116,8 +168,8 @@ docker-compose logs
| Feature | Docker | Batocera/RetroBat |
|---------|--------|-------------------|
| Interface | Web only | Pygame UI + Web |
| Install | `docker-compose up` | Manual setup |
| Updates | `docker-compose build` | git pull |
| Install | `docker run` | Manual setup |
| Updates | `docker build` | git pull |
| Access | Any device on network | Device only |
| Use Case | Server/homelab | Gaming device |

View File

@@ -1,29 +1,72 @@
#!/bin/bash
set -e
# If PUID/PGID are set, create user and run as that user
# If not set, run as root (works for SMB mounts)
if [ -n "$PUID" ] && [ -n "$PGID" ]; then
echo "=== Creating user with PUID=$PUID, PGID=$PGID ==="
# Create group if it doesn't exist
if ! getent group $PGID >/dev/null 2>&1; then
groupadd -g $PGID rgsx
fi
# Create user if it doesn't exist
if ! getent passwd $PUID >/dev/null 2>&1; then
useradd -u $PUID -g $PGID -m -s /bin/bash rgsx
fi
# Fix ownership of app files
chown -R $PUID:$PGID /app /userdata 2>/dev/null || true
echo "=== Running as user $(id -un $PUID) (UID=$PUID, GID=$PGID) ==="
RUN_USER="gosu rgsx"
else
echo "=== Running as root (no PUID/PGID set) - for SMB mounts ==="
RUN_USER=""
fi
# Always sync RGSX app code to the mounted volume (for updates)
echo "Syncing RGSX app code to /userdata/roms/ports/RGSX..."
mkdir -p /userdata/roms/ports/RGSX
cp -rf /app/RGSX/* /userdata/roms/ports/RGSX/
echo "RGSX app code synced!"
$RUN_USER mkdir -p /userdata/roms/ports/RGSX
# Try rsync
if ! $RUN_USER rsync -av --delete /app/RGSX/ /userdata/roms/ports/RGSX/ 2>&1; then
echo ""
echo "=========================================="
echo "WARNING: rsync partially failed!"
echo "=========================================="
echo "Some files may not have synced. Container will continue for debugging."
echo ""
if [ -n "$PUID" ] && [ -n "$PGID" ]; then
echo "If using SMB, try removing PUID/PGID to run as root"
fi
echo ""
fi
echo "RGSX app code sync attempted."
# Create Batocera folder structure only if folders don't exist
[ ! -d "/userdata/saves/ports/rgsx/images" ] && mkdir -p /userdata/saves/ports/rgsx/images
[ ! -d "/userdata/saves/ports/rgsx/games" ] && mkdir -p /userdata/saves/ports/rgsx/games
[ ! -d "/userdata/roms/ports/RGSX/logs" ] && mkdir -p /userdata/roms/ports/RGSX/logs
$RUN_USER mkdir -p /userdata/saves/ports/rgsx/images
$RUN_USER mkdir -p /userdata/saves/ports/rgsx/games
$RUN_USER mkdir -p /userdata/roms/ports/RGSX/logs
# Create default settings with show_unsupported_platforms enabled if config doesn't exist
SETTINGS_FILE="/userdata/saves/ports/rgsx/rgsx_settings.json"
if [ ! -f "$SETTINGS_FILE" ]; then
echo "Creating default settings with all platforms visible..."
cat > "$SETTINGS_FILE" << 'EOF'
$RUN_USER bash -c "cat > '$SETTINGS_FILE' << 'EOF'
{
"show_unsupported_platforms": true
\"show_unsupported_platforms\": true
}
EOF
EOF"
echo "Default settings created!"
fi
# Run the command
cd /userdata/roms/ports/RGSX
exec "$@"
if [ -z "$RUN_USER" ]; then
exec "$@"
else
exec $RUN_USER "$@"
fi