gabriel / musehub public
setup-ec2.sh bash
131 lines 5.5 KB
Raw
sha256:0997d6250ae6476362f6fe2025af7789f46d03df3e9f34356d5e8ee79b201923 fix(issues): use issue number as pagination cursor, not cre… Sonnet 4.6 patch 9 days ago
1 #!/usr/bin/env bash
2 # Run this ON the EC2 instance (via SSH) after provisioning.
3 # Installs Docker and nginx, then configures the Cloudflare Origin Certificate.
4 # No Certbot or Let's Encrypt — Cloudflare terminates SSL at the edge.
5 #
6 # Prerequisites:
7 # 1. Generate a Cloudflare Origin Certificate for musehub.ai:
8 # Cloudflare Dashboard → musehub.ai → SSL/TLS → Origin Server
9 # → Create Certificate → RSA 2048 → 15 years
10 # Save certificate → /etc/ssl/cloudflare/origin.pem
11 # Save private key → /etc/ssl/cloudflare/origin.key
12 #
13 # 2. In Cloudflare: SSL/TLS → Overview → set mode to "Full (Strict)"
14 #
15 # Usage (from your Mac):
16 # scp -i ~/.ssh/musehub-key.pem -r deploy/ [email protected]:/home/ubuntu/
17 # # Copy cert files:
18 # scp -i ~/.ssh/musehub-key.pem origin.pem origin.key [email protected]:/home/ubuntu/
19 # ssh -i ~/.ssh/musehub-key.pem [email protected]
20 # chmod +x ~/deploy/setup-ec2.sh && ~/deploy/setup-ec2.sh
21
22 set -euo pipefail
23
24 DOMAIN="musehub.ai www.musehub.ai"
25 SITE_NAME="musehub"
26 APP_DIR="/opt/musehub"
27
28 echo "==> [1/7] System update"
29 sudo apt-get update -qq && sudo apt-get upgrade -y -qq
30
31 echo "==> [2/7] Install Docker"
32 curl -fsSL https://get.docker.com | sudo sh
33 sudo usermod -aG docker ubuntu
34 echo " Docker installed. NOTE: You may need to log out/in for the group to take effect."
35 echo " For this script we use 'sudo docker' throughout."
36
37 echo "==> [3/7] Install nginx"
38 sudo apt-get install -y -qq nginx
39
40 echo "==> [4/7] Install Cloudflare Origin Certificate"
41 sudo mkdir -p /etc/ssl/cloudflare
42
43 # Copy certs from home dir if present (scp'd in before running this script)
44 if [ -f ~/origin.pem ] && [ -f ~/origin.key ]; then
45 sudo cp ~/origin.pem /etc/ssl/cloudflare/origin.pem
46 sudo cp ~/origin.key /etc/ssl/cloudflare/origin.key
47 sudo chmod 644 /etc/ssl/cloudflare/origin.pem
48 sudo chmod 640 /etc/ssl/cloudflare/origin.key
49 sudo chown root:root /etc/ssl/cloudflare/origin.pem /etc/ssl/cloudflare/origin.key
50 echo " Origin certificate installed."
51 else
52 echo ""
53 echo " !! CERT FILES NOT FOUND — install them manually before nginx will start:"
54 echo " scp origin.pem origin.key ubuntu@<IP>:/home/ubuntu/"
55 echo " sudo cp ~/origin.pem /etc/ssl/cloudflare/origin.pem"
56 echo " sudo cp ~/origin.key /etc/ssl/cloudflare/origin.key"
57 echo " sudo chmod 640 /etc/ssl/cloudflare/origin.key"
58 echo " sudo nginx -s reload"
59 echo ""
60 fi
61
62 echo "==> [5/7] Configure nginx"
63
64 # Blue-green active-port file: deploy.sh rewrites this and does nginx -s reload
65 echo "server 127.0.0.1:1337;" | sudo tee /etc/nginx/musehub-active-port > /dev/null
66
67 # Install the Cloudflare-ready nginx config, substituting the domain(s)
68 sudo sed "s/DOMAIN_PLACEHOLDER/$DOMAIN/g" \
69 "$(dirname "$0")/nginx-cf.conf" \
70 | sudo tee /etc/nginx/sites-available/$SITE_NAME > /dev/null
71
72 sudo ln -sf /etc/nginx/sites-available/$SITE_NAME /etc/nginx/sites-enabled/$SITE_NAME
73 sudo rm -f /etc/nginx/sites-enabled/default
74 sudo nginx -t
75 sudo systemctl reload nginx
76 echo " nginx configured for $DOMAIN"
77
78 echo "==> [6/7] Create app directory"
79 sudo mkdir -p "$APP_DIR"
80 sudo chown ubuntu:ubuntu "$APP_DIR"
81 echo " $APP_DIR ready — sync code from your Mac with:"
82 echo " rsync -az --exclude='.env' --exclude='node_modules/' --exclude='__pycache__/' \\"
83 echo " --exclude='.muse/' --exclude='*.pyc' \\"
84 echo " -e 'ssh -i ~/.ssh/musehub-key.pem' \\"
85 echo " ~/musehub/ ubuntu@\$(hostname -I | awk '{print \$1}'):$APP_DIR/"
86
87 echo "==> [7/7] Create production .env"
88 if [ ! -f "$APP_DIR/.env" ]; then
89 DB_PASSWORD=$(openssl rand -hex 16)
90 WEBHOOK_SECRET_KEY=$(python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" 2>/dev/null || echo "GENERATE_ME_WITH_FERNET")
91
92 cat > "$APP_DIR/.env" << EOF
93 DEBUG=false
94 DATABASE_URL=postgresql+asyncpg://musehub:${DB_PASSWORD}@postgres:5432/musehub
95 DB_PASSWORD=${DB_PASSWORD}
96 CORS_ORIGINS=["https://musehub.ai", "https://www.musehub.ai"]
97 WEBHOOK_SECRET_KEY=${WEBHOOK_SECRET_KEY}
98 MUSEHUB_ALLOWED_ORIGINS=["musehub.ai", "www.musehub.ai"]
99 EOF
100 echo " .env created with generated secrets"
101 echo ""
102 echo " !! SAVE THESE — they are in $APP_DIR/.env !!"
103 cat "$APP_DIR/.env"
104 echo ""
105 else
106 echo " .env already exists, skipping generation"
107 fi
108
109 echo ""
110 echo "============================================================"
111 echo " SETUP COMPLETE"
112 echo "============================================================"
113 echo " https://$DOMAIN is live"
114 echo " App dir : $APP_DIR"
115 echo " Secrets : $APP_DIR/.env (back these up!)"
116 echo ""
117 echo " Next: sync code, run migrations, start the stack:"
118 echo " rsync -az ... ~/musehub/ ubuntu@<IP>:$APP_DIR/"
119 echo " cd $APP_DIR && sudo docker compose up -d postgres musehub-runner"
120 echo " sudo docker compose build musehub"
121 echo " sudo docker compose run --rm --no-deps musehub alembic upgrade head"
122 echo " sudo docker run -d --name musehub-blue --network musehub-internal \\"
123 echo " --env-file .env -e SKIP_MIGRATIONS=1 \\"
124 echo " -e DATABASE_URL=postgresql+asyncpg://musehub:\$(grep ^DB_PASSWORD .env | cut -d= -f2)@postgres:5432/musehub \\"
125 echo " -v musehub_data:/data -p 127.0.0.1:1337:1337 --restart unless-stopped musehub/musehub"
126 echo " bash deploy/deploy.sh --init"
127 echo ""
128 echo " Subsequent deploys (zero downtime):"
129 echo " rsync ... && bash deploy/deploy.sh"
130 echo " Run deploy/seed.sh to create your account + repos"
131 echo "============================================================"
File History 1 commit
sha256:0997d6250ae6476362f6fe2025af7789f46d03df3e9f34356d5e8ee79b201923 fix(issues): use issue number as pagination cursor, not cre… Sonnet 4.6 patch 9 days ago