Setting up Maze #254
@@ -11,3 +11,19 @@ POSTGRES_MAIN_DB=soaricarus_db
|
||||
POSTGRES_MAIN_HOST=main_db
|
||||
POSTGRES_MAIN_PORT=5432
|
||||
DATABASE_URL=postgres://${POSTGRES_MAIN_USER}:${POSTGRES_MAIN_PASSWORD}@${POSTGRES_MAIN_HOST}:${POSTGRES_MAIN_PORT}/${POSTGRES_MAIN_DB}
|
||||
|
||||
GARAGE_RPC_SECRET=c2bde5c3f9c04116a7563e25ea5ba6fab25319daa2fe8a952ad57d0b8159b590
|
||||
GARAGE_METADATA_DIR=/var/lib/garage/meta
|
||||
GARAGE_DATA_DIR=/var/lib/garage/data
|
||||
GARAGE_DB_ENGINE=sqlite
|
||||
GARAGE_REPLICATION_FACTOR=1
|
||||
GARAGE_RPC_BIND_ADDR=[::]:3901
|
||||
GARAGE_S3_API_BIND_ADDR=[::]:3900
|
||||
GARAGE_S3_WEB_BIND_ADDR=[::]:3902
|
||||
GARAGE_S3_REGION=maze
|
||||
GARAGE_ROOT_DOMAIN=.localhost
|
||||
AWS_DEFAULT_REGION=maze
|
||||
AWS_SECRET_ACCESS_KEY=3o4n7yfo34985yrfcq9238765ry3928475rcy349857ty394578cy
|
||||
AWS_ACCESS_KEY_ID=2q39fnoy59q2347yfdrc327894ryfc0q2834rcyq023897
|
||||
|
||||
S3_BUCKET_NAME=soaricarus-storage
|
||||
|
||||
@@ -30,6 +30,10 @@ RUN --mount=type=ssh mkdir src && \
|
||||
COPY src ./src
|
||||
COPY .env ./.env
|
||||
COPY migrations ./migrations
|
||||
COPY scripts/init-garage.sh /scripts/init-garage.sh
|
||||
|
||||
# Make it executable
|
||||
RUN chmod +x /scripts/init-garage.sh
|
||||
|
||||
RUN --mount=type=ssh \
|
||||
cargo build --release --quiet
|
||||
|
||||
@@ -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
|
||||
@@ -56,6 +58,44 @@ services:
|
||||
- auth_db
|
||||
networks:
|
||||
- soaricarus-network
|
||||
# --- storage service ---
|
||||
maze:
|
||||
build:
|
||||
context: ./garage
|
||||
dockerfile: Dockerfile
|
||||
container_name: maze
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3900:3900" # S3 API
|
||||
- "3901:3901" # RPC for cluster communication
|
||||
- "3902:3902" # S3 web interface
|
||||
- "3903:3903" # Admin API
|
||||
volumes:
|
||||
- ./garage.toml:/etc/garage.toml:ro
|
||||
- ./garage/entrypoint.sh:/entrypoint.sh: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}
|
||||
# entrypoint: ["/entrypoint.sh"]
|
||||
# command: []
|
||||
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"]
|
||||
# test: ["CMD-SHELL", "/garage status | grep -q 'Health: ok' || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
networks:
|
||||
- soaricarus-network
|
||||
|
||||
|
||||
# PostgreSQL Database Service
|
||||
@@ -113,6 +153,10 @@ volumes:
|
||||
driver: local # Use the default local driver
|
||||
postgres_data_auth:
|
||||
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:
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
metadata_dir = "/var/lib/garage/meta"
|
||||
data_dir = "/var/lib/garage/data"
|
||||
db_engine = "sqlite"
|
||||
replication_factor = 1
|
||||
|
||||
rpc_bind_addr = "[::]:3901"
|
||||
rpc_secret = "${GARAGE_RPC_SECRET}"
|
||||
|
||||
[s3_api]
|
||||
s3_region = "maze"
|
||||
api_bind_addr = "[::]:3900"
|
||||
root_domain = ".localhost"
|
||||
|
||||
[s3_web]
|
||||
bind_addr = "[::]:3902"
|
||||
root_domain = ".localhost"
|
||||
@@ -0,0 +1,18 @@
|
||||
# Use a base image with a shell (Alpine)
|
||||
FROM alpine:latest
|
||||
|
||||
# Install necessary tools
|
||||
RUN apk add --no-cache curl
|
||||
|
||||
# Copy the Garage binary from the official image
|
||||
COPY --from=dxflrs/garage:v2.3.0 /garage /usr/local/bin/garage
|
||||
|
||||
# Copy the entrypoint script
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
# Set the entrypoint
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
|
||||
# Pass through any arguments to Garage
|
||||
CMD []
|
||||
Executable
+103
@@ -0,0 +1,103 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
BUCKET_NAME="${BUCKET_NAME:-soaricarus-storage}"
|
||||
CREDENTIALS_FILE="/shared/garage-credentials.env"
|
||||
SETUP_DONE="/shared/setup.done"
|
||||
GARAGE_BIN="/usr/local/bin/garage"
|
||||
|
||||
# Function to write credentials
|
||||
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://localhost:3900
|
||||
EOF
|
||||
touch "$SETUP_DONE"
|
||||
echo "✅ Credentials saved to $CREDENTIALS_FILE"
|
||||
}
|
||||
|
||||
# Check if setup already completed
|
||||
if [ -f "$SETUP_DONE" ]; then
|
||||
echo "ℹ️ Setup already completed. Starting Garage..."
|
||||
exec $GARAGE_BIN "$@"
|
||||
fi
|
||||
|
||||
echo "🔧 First-time setup - initializing Garage..."
|
||||
|
||||
# Start Garage in background for setup (just the binary, no daemon subcommand)
|
||||
echo "⏳ Starting Garage in background..."
|
||||
$GARAGE_BIN "$@" &
|
||||
GARAGE_PID=$!
|
||||
|
||||
# Wait for Garage to be ready
|
||||
echo "⏳ Waiting for Garage API..."
|
||||
until curl -s -f "http://localhost:3901/v0/status" > /dev/null 2>&1; do
|
||||
echo " Not ready yet, sleeping 2s..."
|
||||
sleep 2
|
||||
done
|
||||
echo "✅ Garage API is responding!"
|
||||
|
||||
# Apply cluster layout
|
||||
if ! $GARAGE_BIN layout show 2>/dev/null | grep -q "Current cluster layout"; then
|
||||
echo "📦 Applying cluster layout..."
|
||||
NODE_ID=$($GARAGE_BIN node id | head -n1)
|
||||
$GARAGE_BIN layout assign --version 1 "$NODE_ID"
|
||||
$GARAGE_BIN layout apply --version 1
|
||||
echo " ✅ Layout applied"
|
||||
sleep 2
|
||||
else
|
||||
echo "ℹ️ Layout already applied"
|
||||
fi
|
||||
|
||||
# Create bucket
|
||||
if ! $GARAGE_BIN bucket info "$BUCKET_NAME" 2>/dev/null; then
|
||||
echo "📦 Creating bucket: $BUCKET_NAME"
|
||||
$GARAGE_BIN bucket create "$BUCKET_NAME"
|
||||
else
|
||||
echo "ℹ️ Bucket $BUCKET_NAME already exists"
|
||||
fi
|
||||
|
||||
# Handle key
|
||||
if [ -n "$AWS_ACCESS_KEY_ID" ] && [ -n "$AWS_SECRET_ACCESS_KEY" ]; then
|
||||
echo "🔑 Using pre-defined credentials from .env"
|
||||
if ! $GARAGE_BIN key info "$AWS_ACCESS_KEY_ID" 2>/dev/null; then
|
||||
$GARAGE_BIN 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=$($GARAGE_BIN 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
|
||||
$GARAGE_BIN bucket allow --read --write --owner "$BUCKET_NAME" --key "$ACCESS_KEY"
|
||||
echo " ✅ Permissions granted"
|
||||
|
||||
# Save credentials
|
||||
write_credentials "$ACCESS_KEY" "$SECRET_KEY"
|
||||
|
||||
echo "🎉 Setup complete!"
|
||||
echo " Bucket: $BUCKET_NAME"
|
||||
echo " Access Key: $ACCESS_KEY"
|
||||
|
||||
# Stop background Garage
|
||||
echo "⏹️ Stopping background Garage..."
|
||||
kill "$GARAGE_PID"
|
||||
wait "$GARAGE_PID" 2>/dev/null || true
|
||||
|
||||
# Start Garage in foreground
|
||||
echo "🚀 Starting Garage in foreground..."
|
||||
exec $GARAGE_BIN "$@"
|
||||
@@ -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 "$@"
|
||||
|
||||
Executable
+36
@@ -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"
|
||||
Executable
+84
@@ -0,0 +1,84 @@
|
||||
#!/bin/sh
|
||||
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 nc -z "localhost 3900" > /dev/null 2>&1; do
|
||||
echo " Garage not ready yet, retrying in 2s..."
|
||||
sleep 2
|
||||
done
|
||||
echo "✅ Garage API is responding!"
|
||||
|
||||
sleep 3
|
||||
|
||||
# Check if layout is already applied
|
||||
if docker exec maze garage layout show 2>/dev/null | grep -q "Current cluster layout"; then
|
||||
echo "ℹ️ Layout already applied, checking bucket..."
|
||||
else
|
||||
echo "📦 Applying cluster layout..."
|
||||
|
||||
# Get node ID
|
||||
MAX_RETRIES=10
|
||||
RETRY_COUNT=0
|
||||
NODE_ID=""
|
||||
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
|
||||
NODE_ID=$(docker exec maze garage node id 2>/dev/null | head -n1)
|
||||
if [ -n "$NODE_ID" ]; then
|
||||
break
|
||||
fi
|
||||
RETRY_COUNT=$((RETRY_COUNT + 1))
|
||||
echo " Waiting for node ID (attempt $RETRY_COUNT/$MAX_RETRIES)..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
if [ -z "$NODE_ID" ]; then
|
||||
echo "❌ Failed to get node ID after $MAX_RETRIES attempts"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo " Node ID: $NODE_ID"
|
||||
docker exec maze garage layout assign --version 1 "$NODE_ID"
|
||||
docker exec maze garage layout apply --version 1
|
||||
echo " ✅ Layout applied"
|
||||
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
# Check if bucket exists
|
||||
if docker exec maze garage bucket info "${BUCKET_NAME}" 2>/dev/null; then
|
||||
echo "ℹ️ Bucket '${BUCKET_NAME}' already exists. Skipping setup."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "📦 Creating bucket and configuring permissions..."
|
||||
|
||||
# Create the bucket
|
||||
docker exec maze garage bucket create "${BUCKET_NAME}"
|
||||
echo " ✅ Bucket created: ${BUCKET_NAME}"
|
||||
|
||||
# Check if key exists
|
||||
if docker exec maze garage key info "${AWS_ACCESS_KEY_ID}" 2>/dev/null; then
|
||||
echo " ℹ️ Key already exists: ${AWS_ACCESS_KEY_ID}"
|
||||
else
|
||||
docker exec maze garage key create \
|
||||
--name "app-key" \
|
||||
"${AWS_ACCESS_KEY_ID}" \
|
||||
"${AWS_SECRET_ACCESS_KEY}"
|
||||
echo " ✅ Key created: ${AWS_ACCESS_KEY_ID}"
|
||||
fi
|
||||
|
||||
# Grant permissions
|
||||
docker exec maze garage bucket allow \
|
||||
--read \
|
||||
--write \
|
||||
--owner \
|
||||
"${BUCKET_NAME}" \
|
||||
--key "${AWS_ACCESS_KEY_ID}"
|
||||
echo " ✅ Permissions granted"
|
||||
|
||||
echo "🎉 Setup complete!"
|
||||
echo " Bucket: ${BUCKET_NAME}"
|
||||
echo " Access Key: ${AWS_ACCESS_KEY_ID}"
|
||||
echo " Endpoint: http://maze:3900"
|
||||
Reference in New Issue
Block a user