diff --git a/docker-compose.yaml b/docker-compose.yaml index 6f141c5..e920bcf 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -11,6 +11,8 @@ services: - "8000:8000" env_file: - .env + volumes: + - shared_credentials:/shared:ro # Mount as read-only depends_on: main_db: condition: service_healthy @@ -58,7 +60,9 @@ services: - soaricarus-network # --- storage service --- maze: - image: dxflrs/garage:v2.3.0 + build: + context: ./garage + dockerfile: Dockerfile container_name: maze restart: unless-stopped ports: @@ -68,11 +72,20 @@ services: - "3903:3903" # Admin API volumes: - ./garage.toml:/etc/garage.toml:ro + - shared_credentials:/shared - object_data:/var/lib/garage + # - ./scripts:/scripts:ro # ← ADD THIS - mount the scripts directory env_file: - .env + environment: + - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} + - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} + - GARAGE_RPC_SECRET=${GARAGE_RPC_SECRET} + - BUCKET_NAME=${S3_BUCKET_NAME} healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:3901/v0/status || exit 1"] + # test: ["CMD-SHELL", "echo 'What is to be done?'"] + # test: ["CMD-SHELL", "nc -z localhost 3900 || exit 1"] interval: 10s timeout: 5s retries: 5 @@ -80,30 +93,6 @@ services: networks: - soaricarus-network - # --- Storage Initialization --- - maze-init: - # image: dxflrs/garage:v2.3.0 - image: docker:dind - container_name: maze-init - depends_on: - maze: - condition: service_started - volumes: - - /var/run/docker.sock:/var/run/docker.sock # Mount Docker socket - - object_data:/var/lib/garage - - ./scripts:/scripts:ro # ← ADD THIS - mount the scripts directory - environment: - - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} - - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} - - GARAGE_RPC_SECRET=${GARAGE_RPC_SECRET} - - BUCKET_NAME=${S3_BUCKET_NAME} - env_file: - - .env - entrypoint: ["/bin/sh"] - command: ["/scripts/init-garage.sh"] - restart: "no" # Run once and exit - networks: - - soaricarus-network # PostgreSQL Database Service main_db: @@ -162,6 +151,8 @@ volumes: driver: local # Use the default local driver object_data: driver: local # Use the default local driver + shared_credentials: # New shared volume + driver: local networks: soaricarus-network: diff --git a/garage/Dockerfile b/garage/Dockerfile new file mode 100644 index 0000000..a0a6e15 --- /dev/null +++ b/garage/Dockerfile @@ -0,0 +1,21 @@ +# FROM dxflrs/garage:v2.3.0 +# Stage 1: Extract the garage binary from the official image +FROM dxflrs/garage:v2.3.0 as garage-base + +# Stage 2: Create a new image with a shell +FROM alpine:latest + +# Install necessary tools (curl, busybox for sh, etc.) +# The Garage image is based on Alpine, so we use apk +RUN apk add --no-cache curl busybox + +# Copy the garage binary from the official image +COPY --from=garage-base /garage /usr/local/bin/garage + +# Copy the init script +COPY init-garage.sh /init-garage.sh +RUN chmod +x /init-garage.sh + +# Use the init script as the entrypoint +# It will run setup, then exec garage +ENTRYPOINT ["/init-garage.sh"] diff --git a/garage/full-init-garage.sh b/garage/full-init-garage.sh new file mode 100644 index 0000000..c93be4b --- /dev/null +++ b/garage/full-init-garage.sh @@ -0,0 +1,109 @@ +#!/bin/sh +set -e + +BUCKET_NAME="${BUCKET_NAME:-soaricarus-storage}" +CREDENTIALS_FILE="/shared/garage-credentials.env" +SETUP_DONE="/shared/setup.done" + +# Function to write credentials to shared volume +write_credentials() { + local access_key="$1" + local secret_key="$2" + mkdir -p "$(dirname "$CREDENTIALS_FILE")" + cat > "$CREDENTIALS_FILE" << EOF +GARAGE_ACCESS_KEY_ID=$access_key +GARAGE_SECRET_ACCESS_KEY=$secret_key +GARAGE_BUCKET_NAME=$BUCKET_NAME +GARAGE_ENDPOINT=http://maze:3900 +EOF + touch "$SETUP_DONE" + echo "✅ Credentials saved to $CREDENTIALS_FILE" +} + +# Check if setup already done +if [ -f "$SETUP_DONE" ]; then + echo "ℹ️ Setup already completed. Starting Garage..." + # Source credentials if needed for the main Garage process + # shellcheck source=/dev/null + [ -f "$CREDENTIALS_FILE" ] && . "$CREDENTIALS_FILE" + exec /usr/local/bin/garage "$@" +fi + +echo "🔧 Running initial setup..." + +# Start Garage in background for setup +echo "⏳ Starting Garage in background..." +/usr/local/bin/garage "$@" & +GARAGE_PID=$! + +# Wait for Garage API to be ready +echo "⏳ Waiting for Garage API..." +# until curl -s -f "http://localhost:3900/v0/status" > /dev/null 2>&1; do +# echo " Not ready yet, sleeping 2s..." +# sleep 2 +#done +echo "✅ Garage API is responding!" + +# Apply layout if not already applied +if ! /usr/local/bin/garage layout show 2>/dev/null | grep -q "Current cluster layout"; then + echo "📦 Applying cluster layout..." + NODE_ID=$(/usr/local/bin/garage node id | head -n1) + /usr/local/bin/garage layout assign --version 1 "$NODE_ID" + /usr/local/bin/garage layout apply --version 1 + echo " ✅ Layout applied" + sleep 3 +else + echo "ℹ️ Layout already applied" +fi + +echo "Laid out" + +# Create bucket if it doesn't exist +if ! /usr/local/bin/garage bucket info "$BUCKET_NAME" 2>/dev/null; then + echo "📦 Creating bucket: $BUCKET_NAME" + /usr/local/bin/garage bucket create "$BUCKET_NAME" +else + echo "ℹ️ Bucket $BUCKET_NAME already exists" +fi + +# Create or import key +# We'll use the credentials from .env if provided, otherwise generate new ones +if [ -n "$AWS_ACCESS_KEY_ID" ] && [ -n "$AWS_SECRET_ACCESS_KEY" ]; then + echo "🔑 Using pre-defined AWS credentials from .env" + if ! /usr/local/bin/garage key info "$AWS_ACCESS_KEY_ID" 2>/dev/null; then + # Key doesn't exist, import it + /usr/local/bin/garage key import "$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY" "app-key" + echo " ✅ Key imported: $AWS_ACCESS_KEY_ID" + else + echo " ℹ️ Key already exists: $AWS_ACCESS_KEY_ID" + fi + ACCESS_KEY="$AWS_ACCESS_KEY_ID" + SECRET_KEY="$AWS_SECRET_ACCESS_KEY" +else + echo "🔑 Generating new key..." + KEY_OUTPUT=$(/usr/local/bin/garage key create --name "app-key") + echo "$KEY_OUTPUT" + ACCESS_KEY=$(echo "$KEY_OUTPUT" | grep 'Key ID:' | awk '{print $3}') + SECRET_KEY=$(echo "$KEY_OUTPUT" | grep 'Secret key:' | awk '{print $3}') + echo " ✅ Key generated: $ACCESS_KEY" +fi + +# Grant permissions +/usr/local/bin/garage bucket allow --read --write --owner "$BUCKET_NAME" --key "$ACCESS_KEY" +echo " ✅ Permissions granted" + +# Write credentials to shared volume +write_credentials "$ACCESS_KEY" "$SECRET_KEY" + +echo "🎉 Setup complete!" +echo " Bucket: $BUCKET_NAME" +echo " Access Key: $ACCESS_KEY" + +# Stop the background Garage process +echo "⏹️ Stopping background Garage process..." +kill "$GARAGE_PID" +wait "$GARAGE_PID" 2>/dev/null || true + +echo "🚀 Starting Garage in foreground..." +exec /usr/local/bin/garage "$@" + diff --git a/garage/init-garage.sh b/garage/init-garage.sh new file mode 100755 index 0000000..1650ede --- /dev/null +++ b/garage/init-garage.sh @@ -0,0 +1,36 @@ +#!/bin/sh +set -e + +BUCKET_NAME="${BUCKET_NAME:-soaricarus-storage}" +CREDENTIALS_FILE="/shared/garage-credentials.env" +SETUP_DONE="/shared/setup.done" + +echo "🔧 Running initial setup..." + +# Start Garage in background for setup +echo "⏳ Starting Garage in background..." +/usr/local/bin/garage "$@" & +GARAGE_PID=$! + +# Wait for Garage API to be ready +echo "⏳ Waiting for Garage API..." +# until curl -s -f "http://localhost:3900/v0/status" > /dev/null 2>&1; do +# echo " Not ready yet, sleeping 2s..." +# sleep 2 +#done +echo "✅ Garage API is responding!" + +# Apply layout if not already applied +#if ! /usr/local/bin/garage layout show 2>/dev/null | grep -q "Current cluster layout"; then +# echo "📦 Applying cluster layout..." +# NODE_ID=$(/usr/local/bin/garage node id | head -n1) +# echo $NODE_ID + # /usr/local/bin/garage layout assign --version 1 "$NODE_ID" + # /usr/local/bin/garage layout apply --version 1 +# echo " ✅ Layout applied" +# sleep 3 +#else + # echo "ℹ️ Layout already applied" +# fi + +echo "Laid out" diff --git a/scripts/init-garage.sh b/scripts/init-garage.sh index 2f26dd7..b6b3792 100755 --- a/scripts/init-garage.sh +++ b/scripts/init-garage.sh @@ -4,7 +4,8 @@ set -e BUCKET_NAME="soaricarus-storage" echo "⏳ Waiting for Garage to be ready..." -until docker exec maze curl -s -f "http://localhost:3901/v0/status" > /dev/null 2>&1; do +# until docker exec maze curl -s -f "http://localhost:3901/v0/status" > /dev/null 2>&1; do +until docker exec maze nc -z "localhost 3900" > /dev/null 2>&1; do echo " Garage not ready yet, retrying in 2s..." sleep 2 done