Skip to content

Commit 0429e97

Browse files
committed
infra: prod realities — port 3002, system Node v22, additive Redis/Postgres
1 parent a4102d6 commit 0429e97

4 files changed

Lines changed: 57 additions & 68 deletions

File tree

deploy/nginx/partner.711web.com.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
upstream partner_app {
2-
server 127.0.0.1:3000 fail_timeout=0;
2+
server 127.0.0.1:3002 fail_timeout=0;
33
keepalive 16;
44
}
55

deploy/pm2/ecosystem.config.cjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ module.exports = {
44
name: 'partner-app',
55
cwd: '/srv/referral-platform',
66
script: 'node_modules/next/dist/bin/next',
7-
args: 'start -p 3000',
7+
args: 'start -p 3002',
88
instances: 1,
99
exec_mode: 'fork',
1010
autorestart: true,
1111
max_memory_restart: '600M',
1212
env: {
1313
NODE_ENV: 'production',
14-
PORT: '3000',
14+
PORT: '3002',
1515
},
1616
env_file: '/srv/referral-platform/.env',
1717
},

deploy/scripts/bootstrap-server.sh

Lines changed: 53 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
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

2123
set -euo pipefail
2224

@@ -25,78 +27,64 @@ APP_USER=${USER}
2527
ENV_FILE=$APP_DIR/.env
2628
CERT_EMAIL=711webservices@gmail.com
2729
DOMAIN=partner.711web.com
30+
APP_PORT=3002
2831

2932
if [ ! -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
3638
fi
3739

3840
cd "$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
7452
if ! 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"
7665
fi
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
8574
CREATE ROLE referral LOGIN PASSWORD '$NEW_PW';
8675
CREATE DATABASE referral OWNER referral;
8776
SQL
8877
EFFECTIVE_PW=$NEW_PW
89-
echo ">> generated new DB password (saved in .env below)"
78+
echo ">> created role + db with new random password"
9079
else
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
10189
fi
10290

@@ -107,6 +95,7 @@ DATABASE_URL=postgres://referral:${EFFECTIVE_PW}@localhost:5432/referral
10795
REDIS_URL=redis://localhost:6379
10896
SHORT_DOMAIN=partner.711web.com
10997
NODE_ENV=production
98+
PORT=${APP_PORT}
11099
EOF
111100
chmod 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"
129117
fi
130118
sudo 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
136127
fi
137128

138129
echo ""
139130
echo "=========================================="
140131
echo "Bootstrap complete."
132+
echo "App will listen on 127.0.0.1:${APP_PORT} (proxied by nginx for $DOMAIN)."
141133
echo "Next: bash deploy/scripts/deploy.sh"
142134
echo "=========================================="

deploy/scripts/deploy.sh

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ set -euo pipefail
88
APP_DIR=/srv/referral-platform
99
cd "$APP_DIR"
1010

11-
export NVM_DIR="$HOME/.nvm"
12-
# shellcheck disable=SC1091
13-
. "$NVM_DIR/nvm.sh"
14-
nvm use 20 >/dev/null
11+
echo ">> using system node $(node -v) and pnpm $(pnpm -v)"
1512

1613
echo ">> git pull"
1714
git fetch --all --prune

0 commit comments

Comments
 (0)