diff --git a/supabase/deploy.sh b/supabase/deploy.sh new file mode 100644 index 0000000..fb34882 --- /dev/null +++ b/supabase/deploy.sh @@ -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"