11#! /usr/bin/env bash
22# Bootstrap script for partner.711web.com on the UK box (18.134.35.3).
3- # Idempotent: safe to re-run. Run AS THE APP USER (ubuntu) with sudo available.
3+ # This box is SHARED with ClaimPilot, 711web.com, fitpanda, jnews, policychecker,
4+ # systempulse — so this script is deliberately additive and uses existing services
5+ # where possible. It will NOT install Node, Postgres, or nginx if already present.
46#
5- # Prerequisites:
6- # - You've already cloned this repo to /srv/referral-platform (chown ubuntu:ubuntu)
7- # - DNS A record partner.711web.com -> 18.134.35.3 is INSYNC (it is)
8- # - nginx + certbot are already installed on the box (from existing 711web.com setup)
7+ # Idempotent: safe to re-run.
98#
10- # This script will:
11- # 1. Install Node 20 (via nvm), pnpm, PM2 for the current user
12- # 2. Install Postgres 16 + Redis 7 via apt (idempotent)
13- # 3. Create the `referral` Postgres role + database with a freshly generated random password
14- # 4. Write /srv/referral-platform/.env with that password
15- # 5. Install the nginx vhost for partner.711web.com
16- # 6. Obtain a TLS certificate via certbot (webroot)
17- # 7. Reload nginx
9+ # Run as the app user (ubuntu) from /srv/referral-platform. The user needs sudo.
1810#
19- # After this script: run `bash deploy/scripts/deploy.sh` to do the first deploy.
11+ # What this script does:
12+ # 1. Verifies Node + pnpm + PM2 are present (does NOT install nvm — uses system Node)
13+ # 2. Installs Redis ONLY if missing, configures it with maxmemory=128M for safety
14+ # 3. Adds Postgres role `referral` + database `referral` to the existing cluster
15+ # (does NOT install postgres — assumes it's already running)
16+ # 4. Writes /srv/referral-platform/.env with a freshly generated DB password
17+ # 5. Installs nginx vhost for partner.711web.com
18+ # 6. Obtains a TLS cert via certbot --webroot
19+ # 7. Reloads nginx
20+ #
21+ # After this: run `bash deploy/scripts/deploy.sh` to do the first deploy.
2022
2123set -euo pipefail
2224
@@ -25,78 +27,64 @@ APP_USER=${USER}
2527ENV_FILE=$APP_DIR /.env
2628CERT_EMAIL=711webservices@gmail.com
2729DOMAIN=partner.711web.com
30+ APP_PORT=3002
2831
2932if [ ! -d " $APP_DIR /.git" ]; then
3033 echo " ERROR: $APP_DIR is not a git checkout. Clone the repo there first:"
3134 echo " sudo mkdir -p $APP_DIR "
3235 echo " sudo chown $APP_USER :$APP_USER $APP_DIR "
3336 echo " git clone https://github.com/711web/referral-platform $APP_DIR "
34- echo " Then re-run this script."
3537 exit 1
3638fi
3739
3840cd " $APP_DIR "
3941
40- # 1. Node + pnpm + PM2 (for current user)
41- if [ ! -d " $HOME /.nvm" ]; then
42- echo " >> installing nvm"
43- curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
44- fi
45- export NVM_DIR=" $HOME /.nvm"
46- # shellcheck disable=SC1091
47- . " $NVM_DIR /nvm.sh"
48- if ! nvm ls 20 > /dev/null 2>&1 ; then
49- echo " >> installing node 20"
50- nvm install 20
51- fi
52- nvm alias default 20 > /dev/null
53- nvm use 20 > /dev/null
54- corepack enable
55- corepack prepare pnpm@9.12.3 --activate
56- if ! command -v pm2 > /dev/null; then
57- echo " >> installing pm2"
58- npm install -g pm2
59- fi
60-
61- # 2. System packages (idempotent)
62- echo " >> ensuring postgres-16 + redis-server are installed"
63- if ! command -v psql > /dev/null || ! dpkg -l postgresql-16 > /dev/null 2>&1 ; then
64- # Postgres 16 isn't in default Ubuntu repos before 24.04 — add PGDG repo
65- if [ ! -f /etc/apt/sources.list.d/pgdg.list ]; then
66- echo " deb http://apt.postgresql.org/pub/repos/apt $( lsb_release -cs) -pgdg main" \
67- | sudo tee /etc/apt/sources.list.d/pgdg.list
68- curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
69- | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
42+ # 1. Verify Node + pnpm + PM2 (DO NOT install if missing — flag instead)
43+ for tool in node pnpm pm2 nginx psql certbot; do
44+ if ! command -v " $tool " > /dev/null; then
45+ echo " ERROR: $tool not found. This is a shared box — install $tool manually before re-running this script."
46+ exit 1
7047 fi
71- sudo apt-get update
72- sudo DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql-16
73- fi
48+ done
49+ echo " >> node $( node -v) , pnpm $( pnpm -v) , pm2 $( pm2 -v) detected"
50+
51+ # 2. Install Redis only if missing
7452if ! command -v redis-cli > /dev/null; then
53+ echo " >> installing redis-server (not present on box)"
54+ sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq
7555 sudo DEBIAN_FRONTEND=noninteractive apt-get install -y redis-server
56+ # Cap memory at 128MB so we can't OOM the shared box
57+ sudo sed -i ' s/^# *maxmemory .*/maxmemory 128mb/' /etc/redis/redis.conf
58+ sudo sed -i ' s/^# *maxmemory-policy .*/maxmemory-policy allkeys-lru/' /etc/redis/redis.conf
59+ grep -q ' ^maxmemory ' /etc/redis/redis.conf || echo ' maxmemory 128mb' | sudo tee -a /etc/redis/redis.conf > /dev/null
60+ grep -q ' ^maxmemory-policy ' /etc/redis/redis.conf || echo ' maxmemory-policy allkeys-lru' | sudo tee -a /etc/redis/redis.conf > /dev/null
61+ sudo systemctl enable --now redis-server
62+ sudo systemctl restart redis-server
63+ else
64+ echo " >> redis already installed"
7665fi
77- sudo systemctl enable --now postgresql redis-server
66+ redis-cli ping > /dev/null || { echo " ERROR: redis didn't respond " ; exit 1 ; }
7867
79- # 3. DB role + database
80- echo " >> ensuring postgres role + database"
81- DB_PW =$( sudo -u postgres psql -tA -c " SELECT 'EXISTS' FROM pg_roles WHERE rolname='referral'" || echo " " )
82- if [ " $DB_PW " != " EXISTS " ]; then
68+ # 3. DB role + database (additive — checks if already exists)
69+ echo " >> ensuring postgres role + database (additive) "
70+ ROLE_EXISTS =$( sudo -u postgres psql -tA -c " SELECT 1 FROM pg_roles WHERE rolname='referral'" 2> /dev/null || echo " " )
71+ if [ -z " $ROLE_EXISTS " ]; then
8372 NEW_PW=$( openssl rand -base64 32 | tr -d ' =+/' )
8473 sudo -u postgres psql << SQL
8574CREATE ROLE referral LOGIN PASSWORD '$NEW_PW ';
8675CREATE DATABASE referral OWNER referral;
8776SQL
8877 EFFECTIVE_PW=$NEW_PW
89- echo " >> generated new DB password (saved in .env below) "
78+ echo " >> created role + db with new random password "
9079else
91- # Role already exists — keep existing pw if .env already has it, otherwise rotate
9280 if [ -f " $ENV_FILE " ] && grep -q ' ^DATABASE_URL=' " $ENV_FILE " ; then
93- echo " >> role exists and .env already has DATABASE_URL — keeping current password"
81+ echo " >> role exists and .env has DATABASE_URL — keeping current password"
9482 EFFECTIVE_PW=$( grep ' ^DATABASE_URL=' " $ENV_FILE " | sed -n ' s|.*://referral:\([^@]*\)@.*|\1|p' )
9583 else
9684 NEW_PW=$( openssl rand -base64 32 | tr -d ' =+/' )
9785 sudo -u postgres psql -c " ALTER ROLE referral PASSWORD '$NEW_PW ';"
9886 EFFECTIVE_PW=$NEW_PW
99- echo " >> rotated DB password"
87+ echo " >> rotated DB password (role existed without .env) "
10088 fi
10189fi
10290
@@ -107,6 +95,7 @@ DATABASE_URL=postgres://referral:${EFFECTIVE_PW}@localhost:5432/referral
10795REDIS_URL=redis://localhost:6379
10896SHORT_DOMAIN=partner.711web.com
10997NODE_ENV=production
98+ PORT=${APP_PORT}
11099EOF
111100chmod 600 " $ENV_FILE "
112101
@@ -124,19 +113,22 @@ if [ ! -d "/etc/letsencrypt/live/$DOMAIN" ]; then
124113 sudo nginx -t && sudo systemctl reload nginx
125114 sudo certbot certonly --webroot -w /var/www/certbot -d " $DOMAIN " \
126115 --non-interactive --agree-tos -m " $CERT_EMAIL "
127- # Uncomment the 443 server block
128116 sudo sed -i ' s/^#TLS_TEMP#//' " /etc/nginx/sites-available/$DOMAIN .conf"
129117fi
130118sudo nginx -t && sudo systemctl reload nginx
131119
132- # PM2 systemd startup hook (run once)
133- if ! systemctl list-unit-files | grep -q " ^pm2-${APP_USER} \.service" ; then
120+ # PM2 systemd startup hook (run once per user )
121+ if ! systemctl list-unit-files 2> /dev/null | grep -q " ^pm2-${APP_USER} \.service" ; then
134122 echo " >> setting up pm2 systemd hook"
135- pm2 startup systemd -u " $APP_USER " --hp " $HOME " | tail -1 | sudo bash || true
123+ STARTUP_CMD=$( pm2 startup systemd -u " $APP_USER " --hp " $HOME " 2>&1 | tail -1)
124+ if [[ " $STARTUP_CMD " == sudo* ]]; then
125+ eval " $STARTUP_CMD " || true
126+ fi
136127fi
137128
138129echo " "
139130echo " =========================================="
140131echo " Bootstrap complete."
132+ echo " App will listen on 127.0.0.1:${APP_PORT} (proxied by nginx for $DOMAIN )."
141133echo " Next: bash deploy/scripts/deploy.sh"
142134echo " =========================================="
0 commit comments