Add deployment script
This commit is contained in:
191
supabase/deploy.sh
Normal file
191
supabase/deploy.sh
Normal file
@@ -0,0 +1,191 @@
|
||||
#!/bin/bash
|
||||
# Supabase Self-Hosted Deployment Script for Mylder VPS
|
||||
# Run this script on the VPS as root
|
||||
|
||||
set -e
|
||||
|
||||
echo "=== Supabase Self-Hosted Deployment ==="
|
||||
echo ""
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
SUPABASE_DIR="/srv/supabase"
|
||||
COMPOSE_FILE="$SUPABASE_DIR/docker-compose.yml"
|
||||
ENV_FILE="$SUPABASE_DIR/.env"
|
||||
|
||||
# Step 1: Create directory structure
|
||||
echo -e "${YELLOW}Step 1: Creating directory structure...${NC}"
|
||||
mkdir -p $SUPABASE_DIR/volumes/{api,db/data,db/init,storage,functions/main,logs}
|
||||
cd $SUPABASE_DIR
|
||||
|
||||
# Step 2: Generate secrets
|
||||
echo -e "${YELLOW}Step 2: Generating secrets...${NC}"
|
||||
POSTGRES_PASSWORD=$(openssl rand -hex 24)
|
||||
JWT_SECRET=$(openssl rand -hex 32)
|
||||
SECRET_KEY_BASE=$(openssl rand -base64 48 | tr -d '\n')
|
||||
VAULT_ENC_KEY=$(openssl rand -hex 16)
|
||||
PG_META_CRYPTO_KEY=$(openssl rand -hex 16)
|
||||
DASHBOARD_PASSWORD=$(openssl rand -base64 16 | tr -d '\n')
|
||||
LOGFLARE_API_KEY=$(openssl rand -hex 16)
|
||||
|
||||
echo -e "${GREEN}Generated secrets (save these!):${NC}"
|
||||
echo "POSTGRES_PASSWORD: $POSTGRES_PASSWORD"
|
||||
echo "JWT_SECRET: $JWT_SECRET"
|
||||
echo "DASHBOARD_PASSWORD: $DASHBOARD_PASSWORD"
|
||||
|
||||
# Step 3: Generate JWT tokens
|
||||
echo -e "${YELLOW}Step 3: Generating JWT tokens...${NC}"
|
||||
|
||||
# Install Node.js jwt-cli if not present
|
||||
if ! command -v node &> /dev/null; then
|
||||
echo "Node.js not found. Installing..."
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
||||
apt-get install -y nodejs
|
||||
fi
|
||||
|
||||
# Generate ANON and SERVICE_ROLE keys using Node.js
|
||||
ANON_KEY=$(node -e "
|
||||
const crypto = require('crypto');
|
||||
const header = Buffer.from(JSON.stringify({alg:'HS256',typ:'JWT'})).toString('base64url');
|
||||
const payload = Buffer.from(JSON.stringify({role:'anon',iss:'supabase',iat:Math.floor(Date.now()/1000),exp:Math.floor(Date.now()/1000)+315360000})).toString('base64url');
|
||||
const signature = crypto.createHmac('sha256','$JWT_SECRET').update(header+'.'+payload).digest('base64url');
|
||||
console.log(header+'.'+payload+'.'+signature);
|
||||
")
|
||||
|
||||
SERVICE_ROLE_KEY=$(node -e "
|
||||
const crypto = require('crypto');
|
||||
const header = Buffer.from(JSON.stringify({alg:'HS256',typ:'JWT'})).toString('base64url');
|
||||
const payload = Buffer.from(JSON.stringify({role:'service_role',iss:'supabase',iat:Math.floor(Date.now()/1000),exp:Math.floor(Date.now()/1000)+315360000})).toString('base64url');
|
||||
const signature = crypto.createHmac('sha256','$JWT_SECRET').update(header+'.'+payload).digest('base64url');
|
||||
console.log(header+'.'+payload+'.'+signature);
|
||||
")
|
||||
|
||||
echo "ANON_KEY: $ANON_KEY"
|
||||
echo "SERVICE_ROLE_KEY: $SERVICE_ROLE_KEY"
|
||||
|
||||
# Step 4: Create .env file
|
||||
echo -e "${YELLOW}Step 4: Creating .env file...${NC}"
|
||||
cat > $ENV_FILE << EOF
|
||||
############################################################
|
||||
# SECRETS
|
||||
############################################################
|
||||
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
|
||||
JWT_SECRET=$JWT_SECRET
|
||||
ANON_KEY=$ANON_KEY
|
||||
SERVICE_ROLE_KEY=$SERVICE_ROLE_KEY
|
||||
DASHBOARD_USERNAME=admin
|
||||
DASHBOARD_PASSWORD=$DASHBOARD_PASSWORD
|
||||
SECRET_KEY_BASE=$SECRET_KEY_BASE
|
||||
VAULT_ENC_KEY=$VAULT_ENC_KEY
|
||||
PG_META_CRYPTO_KEY=$PG_META_CRYPTO_KEY
|
||||
|
||||
############################################################
|
||||
# DATABASE
|
||||
############################################################
|
||||
POSTGRES_DB=postgres
|
||||
POSTGRES_PORT=5432
|
||||
PGRST_DB_SCHEMAS=public,storage,graphql_public
|
||||
|
||||
############################################################
|
||||
# URLS
|
||||
############################################################
|
||||
SITE_URL=https://mylder.io
|
||||
API_EXTERNAL_URL=https://supabase.mylder.io
|
||||
SUPABASE_PUBLIC_URL=https://supabase.mylder.io
|
||||
ADDITIONAL_REDIRECT_URLS=
|
||||
|
||||
############################################################
|
||||
# AUTH
|
||||
############################################################
|
||||
JWT_EXPIRY=3600
|
||||
DISABLE_SIGNUP=false
|
||||
ENABLE_EMAIL_SIGNUP=true
|
||||
ENABLE_EMAIL_AUTOCONFIRM=false
|
||||
ENABLE_ANONYMOUS_SIGN_INS=false
|
||||
ENABLE_PHONE_SIGNUP=false
|
||||
ENABLE_PHONE_AUTOCONFIRM=false
|
||||
|
||||
############################################################
|
||||
# SMTP (configure with Resend API key)
|
||||
############################################################
|
||||
SMTP_ADMIN_EMAIL=admin@mylder.io
|
||||
SMTP_HOST=smtp.resend.com
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=resend
|
||||
SMTP_PASS=REPLACE_WITH_RESEND_API_KEY
|
||||
SMTP_SENDER_NAME=Mylder
|
||||
|
||||
MAILER_URLPATHS_INVITE=/auth/v1/verify
|
||||
MAILER_URLPATHS_CONFIRMATION=/auth/v1/verify
|
||||
MAILER_URLPATHS_RECOVERY=/auth/v1/verify
|
||||
MAILER_URLPATHS_EMAIL_CHANGE=/auth/v1/verify
|
||||
|
||||
############################################################
|
||||
# STUDIO
|
||||
############################################################
|
||||
STUDIO_DEFAULT_ORGANIZATION=Mylder
|
||||
STUDIO_DEFAULT_PROJECT=Main
|
||||
IMGPROXY_ENABLE_WEBP_DETECTION=true
|
||||
|
||||
############################################################
|
||||
# FUNCTIONS & ANALYTICS
|
||||
############################################################
|
||||
FUNCTIONS_VERIFY_JWT=true
|
||||
LOGFLARE_API_KEY=$LOGFLARE_API_KEY
|
||||
EOF
|
||||
|
||||
chmod 600 $ENV_FILE
|
||||
echo -e "${GREEN}.env file created${NC}"
|
||||
|
||||
# Step 5: Check if docker-compose.yml exists
|
||||
if [ ! -f "$COMPOSE_FILE" ]; then
|
||||
echo -e "${RED}docker-compose.yml not found at $COMPOSE_FILE${NC}"
|
||||
echo "Please copy the docker-compose.yml file to $SUPABASE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 6: Check if kong.yml exists
|
||||
if [ ! -f "$SUPABASE_DIR/volumes/api/kong.yml" ]; then
|
||||
echo -e "${RED}kong.yml not found${NC}"
|
||||
echo "Please copy volumes/api/kong.yml to $SUPABASE_DIR/volumes/api/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 7: Pull images
|
||||
echo -e "${YELLOW}Step 5: Pulling Docker images...${NC}"
|
||||
docker compose pull
|
||||
|
||||
# Step 8: Start services
|
||||
echo -e "${YELLOW}Step 6: Starting Supabase services...${NC}"
|
||||
docker compose up -d
|
||||
|
||||
# Step 9: Wait for health checks
|
||||
echo -e "${YELLOW}Step 7: Waiting for services to be healthy...${NC}"
|
||||
sleep 30
|
||||
|
||||
# Step 10: Check status
|
||||
echo -e "${YELLOW}Step 8: Checking service status...${NC}"
|
||||
docker compose ps
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}=== Deployment Complete ===${NC}"
|
||||
echo ""
|
||||
echo "Access Supabase Studio at: https://supabase.mylder.io"
|
||||
echo "Username: admin"
|
||||
echo "Password: $DASHBOARD_PASSWORD"
|
||||
echo ""
|
||||
echo "API URL: https://supabase.mylder.io"
|
||||
echo "ANON_KEY: $ANON_KEY"
|
||||
echo "SERVICE_ROLE_KEY: $SERVICE_ROLE_KEY"
|
||||
echo ""
|
||||
echo -e "${YELLOW}IMPORTANT: Save these credentials securely!${NC}"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Add DNS A record for supabase.mylder.io pointing to this server"
|
||||
echo "2. Configure SMTP (replace SMTP_PASS in .env with Resend API key)"
|
||||
echo "3. Access Studio and create your database schema"
|
||||
Reference in New Issue
Block a user