#!/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 Mailjet API keys) # Get keys from: https://app.mailjet.com/account/apikeys ############################################################ SMTP_ADMIN_EMAIL=admin@mylder.io SMTP_HOST=in-v3.mailjet.com SMTP_PORT=587 SMTP_USER=f42a859cc0e03f91af90849be4c981fc SMTP_PASS=22fc7cbc55e4b515702b5264f4b1636e 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_USER/SMTP_PASS in .env with Mailjet API keys)" echo "3. Access Studio and create your database schema"