diff --git a/.env.example b/.env.example index 8ebb335..9e7dc0c 100644 --- a/.env.example +++ b/.env.example @@ -27,6 +27,8 @@ SMTP_FROM=MC-Manager # --- Docker --- MC_SERVERS_PATH=/opt/mc-servers DOCKER_SOCKET=/var/run/docker.sock +DOCKER_UID=1000 +DOCKER_GID=1000 # --- App --- NEXT_PUBLIC_APP_URL=http://localhost:3000 diff --git a/src/lib/docker.ts b/src/lib/docker.ts index 4b63082..7a8d609 100644 --- a/src/lib/docker.ts +++ b/src/lib/docker.ts @@ -82,6 +82,9 @@ export async function createServerContainer(options: CreateContainerOptions): Pr `MAX_PLAYERS=${options.maxPlayers}`, ] + const uid = process.env.DOCKER_UID || '1000' + const gid = process.env.DOCKER_GID || '1000' + // Only set itzg-specific env vars for the default image if (isItzg) { env.push( @@ -90,6 +93,8 @@ export async function createServerContainer(options: CreateContainerOptions): Pr `MEMORY=${options.memoryMax}M`, `JVM_XX_OPTS=${options.jvmArgs.join(' ')}`, 'CREATE_CONSOLE_IN_PIPE=true', + `UID=${uid}`, + `GID=${gid}`, ) } @@ -125,19 +130,21 @@ export async function createServerContainer(options: CreateContainerOptions): Pr } /** - * Ensures the server data directory exists with correct ownership (uid=1000) - * for the itzg/minecraft-server container. + * Ensures the server data directory exists with correct ownership + * for the container user (configured via DOCKER_UID / DOCKER_GID). */ export async function ensureServerDirectory(serverPath: string): Promise { if (!existsSync(serverPath)) { await mkdir(serverPath, { recursive: true }) } - // itzg/minecraft-server runs as uid=1000 gid=1000 + const uid = parseInt(process.env.DOCKER_UID || '1000', 10) + const gid = parseInt(process.env.DOCKER_GID || '1000', 10) + try { - await chown(serverPath, 1000, 1000) + await chown(serverPath, uid, gid) } catch (err) { - console.warn(`[Docker] Could not chown ${serverPath} to 1000:1000 — container may have permission issues:`, (err as Error).message) + console.warn(`[Docker] Could not chown ${serverPath} to ${uid}:${gid} — container may have permission issues:`, (err as Error).message) } }