diff --git a/Dockerfile.service b/Dockerfile.service index 83ddb8a..d49471d 100644 --- a/Dockerfile.service +++ b/Dockerfile.service @@ -39,8 +39,8 @@ RUN pnpm turbo build --filter='./packages/shared/*' --filter=@it0/${SERVICE_NAME # ===== Production Stage ===== FROM node:18-alpine -# Install bash (required by Claude Agent SDK Bash tool) + openssh-client (for SSH to managed servers) -RUN apk add --no-cache bash openssh-client +# Install bash (required by Claude Agent SDK Bash tool) + openssh-client (for SSH to managed servers) + su-exec (for privilege drop) +RUN apk add --no-cache bash openssh-client su-exec RUN corepack enable @@ -79,12 +79,15 @@ COPY --from=builder /app/packages/shared/database/src/migrations packages/servic WORKDIR /app/packages/services/${SERVICE_NAME} -# Run as non-root user (required for SDK bypassPermissions mode) +# Create non-root user for service runtime RUN adduser -D -h /home/appuser appuser && \ mkdir -p /data/claude-tenants && \ mkdir -p /home/appuser/.ssh && chmod 700 /home/appuser/.ssh && \ chown -R appuser:appuser /app /data/claude-tenants /home/appuser/.ssh -USER appuser + +# Copy entrypoint script (runs as root to fix SSH key permissions, then drops to appuser) +COPY deploy/docker/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh ARG SERVICE_PORT=3000 EXPOSE ${SERVICE_PORT} @@ -93,5 +96,4 @@ ENV SERVICE_NAME=${SERVICE_NAME} ENV NODE_OPTIONS="--experimental-global-webcrypto" ENV SHELL=/bin/bash -# Entrypoint: copy host-mounted SSH key with correct ownership, then start service -CMD sh -c 'if [ -f /tmp/host-ssh-key ]; then cp /tmp/host-ssh-key /home/appuser/.ssh/id_ed25519 && chmod 600 /home/appuser/.ssh/id_ed25519; fi && node dist/services/${SERVICE_NAME}/src/main' +ENTRYPOINT ["/entrypoint.sh"] diff --git a/deploy/docker/entrypoint.sh b/deploy/docker/entrypoint.sh new file mode 100644 index 0000000..773f73d --- /dev/null +++ b/deploy/docker/entrypoint.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# Copy host-mounted SSH key with correct ownership before dropping to appuser +if [ -f /tmp/host-ssh-key ]; then + cp /tmp/host-ssh-key /home/appuser/.ssh/id_ed25519 + chmod 600 /home/appuser/.ssh/id_ed25519 + chown appuser:appuser /home/appuser/.ssh/id_ed25519 +fi + +# Drop privileges and start the service +exec su-exec appuser node dist/services/${SERVICE_NAME}/src/main