Skip to content
4 changes: 4 additions & 0 deletions docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ services:
# 502 is default on macos, 1000 on linux
USER_ID: 1000
GROUP_ID: 1000
# Optional: Add extra groups to the beetle user for file permissions
# Format: "group_name1:gid1,group_name2:gid2"
# Example: EXTRA_GROUPS: "nas_shares:1001,media:1002"
# EXTRA_GROUPS: ""
volumes:
- /wherever/config/:/config
# for music folders, match paths inside and out of container!
Expand Down
66 changes: 66 additions & 0 deletions docker/entrypoints/entrypoint_fix_permissions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,69 @@ if [ ! -z "$USER_ID" ] && [ ! -z "$GROUP_ID" ]; then
chown -R beetle:beetle /repo
chown -R beetle:beetle /logs
fi

# Add extra groups to the beetle user if EXTRA_GROUPS is set
# Format: "group_name1:gid1,group_name2:gid2" e.g., "nas_shares:1001,media:1002"
if [ ! -z "$EXTRA_GROUPS" ]; then
echo "[Entrypoint] Adding extra groups to beetle user: $EXTRA_GROUPS"
# Split by comma and iterate
OLD_IFS="$IFS"
IFS=','
for group_spec in $EXTRA_GROUPS; do
# Validate that the format contains a colon
case "$group_spec" in
*:*) ;;
*)
echo "[Entrypoint] Warning: Invalid group specification '$group_spec', skipping. Format should be 'group_name:gid'"
continue
;;
esac

# Split by colon to get group_name and gid
group_name=$(echo "$group_spec" | cut -d':' -f1)
gid=$(echo "$group_spec" | cut -d':' -f2)

# Validate that both group_name and gid are provided
if [ -z "$group_name" ] || [ -z "$gid" ]; then
echo "[Entrypoint] Warning: Invalid group specification '$group_spec', skipping. Format should be 'group_name:gid'"
continue
fi

# Validate that gid is a positive integer
case "$gid" in
*[!0-9]*)
echo "[Entrypoint] Warning: GID '$gid' is not a valid positive integer in '$group_spec', skipping"
continue
;;
esac
if [ "$gid" -le 0 ] 2>/dev/null; then
echo "[Entrypoint] Warning: GID '$gid' must be a positive integer in '$group_spec', skipping"
continue
fi

# Check if the group already exists
if getent group "$group_name" > /dev/null 2>&1; then
echo "[Entrypoint] Group '$group_name' already exists, skipping creation"
else
# Create the group with the specified gid
error_output=$(addgroup -g "$gid" "$group_name" 2>&1)
add_result=$?
if [ $add_result -eq 0 ]; then
echo "[Entrypoint] Created group '$group_name' with gid $gid"
else
echo "[Entrypoint] Warning: Failed to create group '$group_name' with gid $gid: $error_output"
continue
fi
fi

# Add beetle user to the group
error_output=$(adduser beetle "$group_name" 2>&1)
add_result=$?
if [ $add_result -eq 0 ]; then
echo "[Entrypoint] Added beetle user to group '$group_name'"
else
echo "[Entrypoint] Warning: Failed to add beetle user to group '$group_name': $error_output"
fi
done
IFS="$OLD_IFS"
fi
40 changes: 40 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,43 @@ You can use multiple workers to fetch candidates before importing (previewing).
However, the import itself is always done sequentially.
This is to ensure that the import process is not interrupted by other operations.
```

## Docker Environment Variables

These environment variables are set in the `docker-compose.yaml` file and control the container's behavior.

### `USER_ID` and `GROUP_ID`

The `USER_ID` and `GROUP_ID` environment variables are used to set the UID and GID of the `beetle` user inside the container. This is useful to match the user and group IDs of the host system. The default value is `1000` for both.

```yaml
environment:
USER_ID: 1000
GROUP_ID: 1000
```
### `EXTRA_GROUPS`

The `EXTRA_GROUPS` environment variable allows you to add additional groups to the `beetle` user. This is useful when you need the container to have access to files owned by different groups on the host system.

The format is a comma-separated list of `group_name:gid` pairs:

```yaml
environment:
EXTRA_GROUPS: "nas_shares:1001,media:1002"
```

This is particularly useful in scenarios where:
- Files in the inbox are created by external services running as different users/groups
- You're using ACL-based permissions with specific group access
- You're running in environments like LXC/Proxmox with mapped group IDs
- You need the container to manage files from network shares with specific group ownership

Example: If your download client (e.g., slskd, transmission) creates files with group ownership `nas_shares` (gid 1001), you can add that group to the beetle user:

```yaml
environment:
EXTRA_GROUPS: "nas_shares:1001"
```

This will allow the beets-flask container to delete and manage those files via the web UI.