feat: Add flexible UID/GID configuration support in Dockerfile and documentation

- Updated Dockerfile to allow configurable user and group IDs via environment variables `PALMR_UID` and `PALMR_GID`, enhancing compatibility with host systems.
- Introduced a new documentation file `uid-gid-configuration.mdx` detailing the configuration process and troubleshooting for permission issues, particularly for NAS systems.
- Updated `meta.json` to include a reference to the new UID/GID configuration guide.
This commit is contained in:
Daniel Luiz Alves
2025-06-17 10:46:36 -03:00
parent 54bd987b9a
commit 2ea7343e0c
3 changed files with 321 additions and 6 deletions

View File

@@ -72,9 +72,13 @@ ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV API_BASE_URL=http://127.0.0.1:3333
# Create application user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 palmr
# Define build arguments for user/group configuration (defaults to current values)
ARG PALMR_UID=1001
ARG PALMR_GID=1001
# Create application user with configurable UID/GID
RUN addgroup --system --gid ${PALMR_GID} nodejs
RUN adduser --system --uid ${PALMR_UID} --ingroup nodejs palmr
# Create application directories and set permissions
# Include storage directories for filesystem mode and SQLite database directory
@@ -95,7 +99,6 @@ COPY --from=server-builder --chown=palmr:nodejs /app/server/package.json ./
# Copy password reset script and make it executable
COPY --from=server-builder --chown=palmr:nodejs /app/server/reset-password.sh ./
COPY --from=server-builder --chown=palmr:nodejs /app/server/src/scripts/ ./src/scripts/
COPY --from=server-builder --chown=palmr:nodejs /app/server/PASSWORD_RESET_GUIDE.md ./
RUN chmod +x ./reset-password.sh
# Ensure storage directories have correct permissions
@@ -152,17 +155,65 @@ priority=200
startsecs=10
EOF
# Create main startup script
# Create main startup script with UID/GID runtime support
COPY <<EOF /app/start.sh
#!/bin/sh
set -e
echo "Starting Palmr Application..."
echo "Storage Mode: \${ENABLE_S3:-false}"
echo "Database: SQLite"
# Runtime UID/GID configuration - only apply if environment variables are set
if [ -n "\${PALMR_UID}" ] || [ -n "\${PALMR_GID}" ]; then
RUNTIME_UID=\${PALMR_UID:-${PALMR_UID}}
RUNTIME_GID=\${PALMR_GID:-${PALMR_GID}}
echo "Runtime UID/GID configuration detected: UID=\$RUNTIME_UID, GID=\$RUNTIME_GID"
# Get current user/group IDs
CURRENT_UID=\$(id -u palmr 2>/dev/null || echo "${PALMR_UID}")
CURRENT_GID=\$(id -g palmr 2>/dev/null || echo "${PALMR_GID}")
# Only modify if different from current
if [ "\$CURRENT_UID" != "\$RUNTIME_UID" ] || [ "\$CURRENT_GID" != "\$RUNTIME_GID" ]; then
echo "Adjusting user/group IDs from \$CURRENT_UID:\$CURRENT_GID to \$RUNTIME_UID:\$RUNTIME_GID"
# Modify group if needed
if [ "\$CURRENT_GID" != "\$RUNTIME_GID" ]; then
if getent group \$RUNTIME_GID >/dev/null 2>&1; then
EXISTING_GROUP=\$(getent group \$RUNTIME_GID | cut -d: -f1)
echo "Using existing group with GID \$RUNTIME_GID: \$EXISTING_GROUP"
usermod -g \$EXISTING_GROUP palmr 2>/dev/null || echo "Warning: Could not change user group"
else
groupmod -g \$RUNTIME_GID nodejs 2>/dev/null || echo "Warning: Could not modify group GID"
fi
fi
# Modify user if needed
if [ "\$CURRENT_UID" != "\$RUNTIME_UID" ]; then
if getent passwd \$RUNTIME_UID >/dev/null 2>&1; then
EXISTING_USER=\$(getent passwd \$RUNTIME_UID | cut -d: -f1)
echo "Warning: UID \$RUNTIME_UID already exists as user '\$EXISTING_USER'"
echo "Container will continue but may have permission issues"
else
usermod -u \$RUNTIME_UID palmr 2>/dev/null || echo "Warning: Could not modify user UID"
fi
fi
# Update file ownership for application directories
echo "Updating file ownership for application directories..."
chown -R palmr:nodejs /app /home/palmr 2>/dev/null || echo "Warning: Could not update all file ownership"
else
echo "Runtime UID/GID matches current values, no changes needed"
fi
else
echo "No runtime UID/GID configuration provided, using defaults"
fi
# Ensure storage directories exist with correct permissions
mkdir -p /app/server/uploads /app/server/temp-chunks /app/server/uploads/logo /app/server/prisma
chown -R palmr:nodejs /app/server/uploads /app/server/temp-chunks /app/server/prisma
chown -R palmr:nodejs /app/server/uploads /app/server/temp-chunks /app/server/prisma 2>/dev/null || echo "Warning: Could not set permissions on storage directories"
# Start supervisor
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf

View File

@@ -14,6 +14,7 @@
"---Configuration---",
"configuring-smtp",
"available-languages",
"uid-gid-configuration",
"password-reset-without-smtp",
"oidc-authentication",
"---Developers---",

View File

@@ -0,0 +1,263 @@
---
title: UID/GID Configuration
icon: "Users"
---
Having trouble with **permission denied** errors when using bind-mounted directories? This guide will help you configure <span className="font-bold">Palmr.</span> to work seamlessly with your host system's <span className="font-bold italic">user and group permissions</span>.
This is particularly common on **NAS systems** like Synology or QNAP, where the container's default UID/GID doesn't match your host system. Instead of manually changing directory ownership on your host, Palmr. now supports <span className="font-bold italic">flexible UID/GID configuration</span> to automatically handle these permission conflicts.
## The Problem
By default, Palmr. runs with UID 1001 and GID 1001 inside the container. When you bind-mount a directory from your host system (like `./data:/app/server`), permission conflicts can occur if:
- Your host user has a different UID/GID
- You're running on a NAS system with specific user configurations
- The mounted directory ownership doesn't match the container user
This results in errors like:
- **Access denied** even with 777 permissions
- **Database connection failures** (SQLite can't create/access files)
- **File upload failures** in the application
## The Solution
Palmr. now supports **runtime UID/GID configuration** through environment variables. The container will automatically adjust its internal user permissions to match your host system, eliminating the need to manually change directory ownership.
## Environment Variables
Configure these **optional** environment variables in your `docker-compose.yml`:
| Variable | Description | Default | When to Use |
| ----------- | ---------------------------------- | ------- | ------------------------------------------- |
| `PALMR_UID` | User ID for the container process | 1001 | When host directory owner has different UID |
| `PALMR_GID` | Group ID for the container process | 1001 | When host directory group has different GID |
> **Important**: These variables are **completely optional**. If you don't set them, Palmr. works exactly as before with UID/GID 1001.
## Finding Your Host UID/GID
Before configuring, you need to find your host system's user and group IDs:
```bash
# Find your user ID
id -u
# Find your group ID
id -g
# See both together
id
```
Example output:
```bash
$ id
uid=1000(myuser) gid=1000(mygroup) groups=1000(mygroup),27(sudo)
```
In this example, you would use `PALMR_UID=1000` and `PALMR_GID=1000`.
## Configuration Examples
### Basic Linux System
Most Linux desktop systems use UID/GID 1000 for the first user:
```yaml
services:
palmr:
image: docker.io/kyantech/palmr:latest
container_name: palmr
environment:
- ENABLE_S3=false
- ENCRYPTION_KEY=change-this-key-in-production-min-32-chars
# Add these lines to match your host user
- PALMR_UID=1000
- PALMR_GID=1000
ports:
- "5487:5487"
volumes:
- ./data:/app/server
restart: unless-stopped
```
### Synology NAS
Synology systems commonly use these UID/GID combinations:
```yaml
services:
palmr:
image: docker.io/kyantech/palmr:latest
container_name: palmr
environment:
- ENABLE_S3=false
- ENCRYPTION_KEY=change-this-key-in-production-min-32-chars
# Common Synology configuration
- PALMR_UID=1026
- PALMR_GID=100
ports:
- "5487:5487"
volumes:
- /volume1/docker/palmr/data:/app/server
restart: unless-stopped
```
### QNAP NAS
QNAP systems typically use:
```yaml
services:
palmr:
image: docker.io/kyantech/palmr:latest
container_name: palmr
environment:
- ENABLE_S3=false
- ENCRYPTION_KEY=change-this-key-in-production-min-32-chars
# Common QNAP configuration
- PALMR_UID=1000
- PALMR_GID=100
ports:
- "5487:5487"
volumes:
- /share/Container/palmr/data:/app/server
restart: unless-stopped
```
### No Configuration Needed
If you're not experiencing permission issues, you don't need to set these variables:
```yaml
services:
palmr:
image: docker.io/kyantech/palmr:latest
container_name: palmr
environment:
- ENABLE_S3=false
- ENCRYPTION_KEY=change-this-key-in-production-min-32-chars
# No PALMR_UID/PALMR_GID needed - uses defaults
ports:
- "5487:5487"
volumes:
- ./data:/app/server
restart: unless-stopped
```
## Migration for Existing Installations
If you already have Palmr. running and want to add UID/GID configuration:
### Step 1: Backup Your Data
```bash
docker-compose down
cp -r ./data ./data-backup
```
### Step 2: Update docker-compose.yml
Add the UID/GID environment variables to your existing configuration:
```yaml
services:
palmr:
image: docker.io/kyantech/palmr:latest
container_name: palmr
environment:
- ENABLE_S3=false
- ENCRYPTION_KEY=your-existing-key
# Add these new lines
- PALMR_UID=1000 # Your host user UID
- PALMR_GID=1000 # Your host group GID
# ... rest of your configuration
```
### Step 3: Restart Palmr.
```bash
docker-compose up -d
```
The container will automatically detect the new UID/GID configuration and adjust permissions accordingly.
## Troubleshooting
### Checking Current Configuration
To verify your container is running with the correct UID/GID:
```bash
# Check the user ID inside the container
docker exec palmr id
# Check file ownership in the mounted volume
docker exec palmr ls -la /app/server/
```
### Permission Issues Persist
If you're still having permission issues after configuration:
```bash
# Check container logs for UID/GID adjustment messages
docker-compose logs palmr | grep -i "uid\|gid"
# Manually fix permissions if needed
docker exec -u root palmr chown -R palmr:nodejs /app/server
```
### Finding NAS-Specific UID/GID
For NAS systems, check your system's user management interface or use SSH:
```bash
# On your NAS, check existing users
cat /etc/passwd | grep -v nobody
# Check groups
cat /etc/group
```
## How It Works
When you set `PALMR_UID` and/or `PALMR_GID` environment variables:
1. **Container startup**: The container detects the environment variables
2. **User adjustment**: Automatically modifies the internal `palmr` user to use your specified UID/GID
3. **Ownership update**: Updates file ownership of application directories
4. **Conflict handling**: Gracefully handles cases where the UID/GID already exists
5. **Logging**: Provides clear feedback about what changes were made
The process is completely automatic and requires no manual intervention.
## Build-Time Customization
For advanced users who want to build custom images with different default UID/GID:
```bash
docker build \
--build-arg PALMR_UID=2000 \
--build-arg PALMR_GID=2000 \
-t palmr:custom .
```
This sets new defaults at build time, which can still be overridden with environment variables at runtime.
---
## Summary
The UID/GID configuration feature makes Palmr. **universally compatible** with different host systems without requiring manual permission changes. Key benefits:
- ✅ **Automatic permission handling** - No manual `chown` commands needed
- ✅ **NAS system compatibility** - Tested with Synology and QNAP
- ✅ **Backward compatible** - Existing installations continue to work unchanged
- ✅ **Optional configuration** - Only use when needed
- ✅ **Runtime flexibility** - Change UID/GID without rebuilding images
If you're experiencing permission issues with bind-mounted directories, try adding the appropriate `PALMR_UID` and `PALMR_GID` environment variables to your configuration. The container will handle the rest automatically!