Improve deploy.sh: TOC/plan summary, per-section confirm, nginx setup
- Collect all config upfront then print a plan showing every step (active or skipped) before doing any work - Prompt "Proceed? [Y/n]" at each section for granular control - Add nginx reverse proxy setup with certbot SSL support - Add overall "Continue?" confirmation after plan is shown Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
619e83acb6
commit
fde9e31b14
425
deploy.sh
425
deploy.sh
@ -1,8 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# Dataflow Deploy Script
|
# Dataflow Deploy Script
|
||||||
# First run: creates DB user/database, deploys schema, builds UI, installs service
|
# First run: full install (database, schema, UI, nginx, systemd)
|
||||||
# Subsequent runs: updates functions, rebuilds UI, restarts service
|
# Subsequent runs: update functions, UI, and restart service
|
||||||
#
|
#
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
@ -10,74 +10,174 @@ set -e
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
cd "$SCRIPT_DIR"
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
echo "Dataflow Deploy"
|
# ── Helpers ───────────────────────────────────────────────────────────────────
|
||||||
echo "==============="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# ── First-time setup ──────────────────────────────────────────────────────────
|
BOLD='\033[1m'
|
||||||
|
DIM='\033[2m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
RESET='\033[0m'
|
||||||
|
|
||||||
|
section() { echo ""; echo -e "${BOLD}── $1 ──${RESET}"; }
|
||||||
|
step() { printf " %-42s" "$1..."; }
|
||||||
|
ok() { echo -e "${GREEN}✓${RESET}"; }
|
||||||
|
fail() { echo -e "${RED}✗ $1${RESET}"; exit 1; }
|
||||||
|
info() { echo -e " ${DIM}$1${RESET}"; }
|
||||||
|
warn() { echo -e " ${YELLOW}$1${RESET}"; }
|
||||||
|
|
||||||
|
confirm() {
|
||||||
|
# confirm "Section name" — prints section header, asks to proceed
|
||||||
|
# Returns 0 to proceed, 1 to skip
|
||||||
|
section "$1"
|
||||||
|
read -p " Proceed? [Y/n]: " _yn
|
||||||
|
[[ ! "$_yn" =~ ^[Nn]$ ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Mode detection ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
section "Mode"
|
||||||
if [ ! -f .env ]; then
|
if [ ! -f .env ]; then
|
||||||
echo "No .env found — running first-time setup."
|
echo " No .env found — first-time install"
|
||||||
echo ""
|
MODE=install
|
||||||
|
else
|
||||||
|
echo " .env found — update mode"
|
||||||
|
MODE=update
|
||||||
|
export $(cat .env | grep -v '^#' | xargs)
|
||||||
|
fi
|
||||||
|
|
||||||
# Admin credentials (needed to create user/database)
|
# ── Phase 1: Collect all config ───────────────────────────────────────────────
|
||||||
echo "PostgreSQL Admin Credentials"
|
|
||||||
|
if [ "$MODE" = "install" ]; then
|
||||||
|
|
||||||
|
section "PostgreSQL Admin"
|
||||||
|
info "Needed to create the app user and database"
|
||||||
read -p " Admin username [postgres]: " ADMIN_USER; ADMIN_USER=${ADMIN_USER:-postgres}
|
read -p " Admin username [postgres]: " ADMIN_USER; ADMIN_USER=${ADMIN_USER:-postgres}
|
||||||
read -s -p " Admin password: " ADMIN_PASS; echo ""
|
read -s -p " Admin password: " ADMIN_PASS; echo ""
|
||||||
echo ""
|
|
||||||
|
|
||||||
# App credentials
|
section "Application Database"
|
||||||
echo "Application Database"
|
|
||||||
read -p " Host [localhost]: " DB_HOST; DB_HOST=${DB_HOST:-localhost}
|
read -p " Host [localhost]: " DB_HOST; DB_HOST=${DB_HOST:-localhost}
|
||||||
read -p " Port [5432]: " DB_PORT; DB_PORT=${DB_PORT:-5432}
|
read -p " Port [5432]: " DB_PORT; DB_PORT=${DB_PORT:-5432}
|
||||||
read -p " Database name [dataflow]: " DB_NAME; DB_NAME=${DB_NAME:-dataflow}
|
read -p " Database [dataflow]: " DB_NAME; DB_NAME=${DB_NAME:-dataflow}
|
||||||
read -p " App username [dataflow]: " DB_USER; DB_USER=${DB_USER:-dataflow}
|
read -p " App user [dataflow]: " DB_USER; DB_USER=${DB_USER:-dataflow}
|
||||||
read -s -p " App password: " DB_PASSWORD; echo ""
|
read -s -p " App password: " DB_PASSWORD; echo ""
|
||||||
echo ""
|
|
||||||
|
|
||||||
# API config
|
section "API"
|
||||||
echo "API Configuration"
|
|
||||||
read -p " Port [3020]: " API_PORT; API_PORT=${API_PORT:-3020}
|
read -p " Port [3020]: " API_PORT; API_PORT=${API_PORT:-3020}
|
||||||
read -p " Environment [production]: " NODE_ENV; NODE_ENV=${NODE_ENV:-production}
|
read -p " Environment [production]:" NODE_ENV; NODE_ENV=${NODE_ENV:-production}
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Install Node dependencies
|
section "Nginx"
|
||||||
echo "Installing Node.js dependencies..."
|
read -p " Set up nginx reverse proxy? [Y/n]: " _yn
|
||||||
npm install --prefix . --omit=dev -q
|
if [[ ! "$_yn" =~ ^[Nn]$ ]]; then
|
||||||
cd ui && npm install -q && cd ..
|
read -p " Domain (e.g. dataflow.example.com): " NGINX_DOMAIN
|
||||||
echo "✓ Dependencies installed"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test admin connection
|
|
||||||
echo "Testing admin connection..."
|
|
||||||
export PGPASSWORD="$ADMIN_PASS"
|
|
||||||
if ! psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres -c '\q' 2>/dev/null; then
|
|
||||||
echo "✗ Cannot connect as $ADMIN_USER — check credentials"
|
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
echo "✓ Admin connection OK"
|
|
||||||
|
|
||||||
# Create app user
|
DO_DEPS=y; DO_DB=y; DO_SCHEMA=y; DO_FN=y; DO_BUILD=y; DO_SERVICE=y; DO_RESTART=y
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
section "Database"
|
||||||
|
echo " Current: ${DB_USER}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
|
||||||
|
read -p " Change target? [y/N]: " _yn
|
||||||
|
if [[ "$_yn" =~ ^[Yy]$ ]]; then
|
||||||
|
read -p " Host [${DB_HOST}]: " _in; DB_HOST=${_in:-$DB_HOST}
|
||||||
|
read -p " Port [${DB_PORT}]: " _in; DB_PORT=${_in:-$DB_PORT}
|
||||||
|
read -p " Database [${DB_NAME}]: " _in; DB_NAME=${_in:-$DB_NAME}
|
||||||
|
read -p " User [${DB_USER}]: " _in; DB_USER=${_in:-$DB_USER}
|
||||||
|
read -s -p " Password (blank = keep): " _in; echo ""
|
||||||
|
if [ -n "$_in" ]; then DB_PASSWORD=$_in; fi
|
||||||
|
CHANGE_DB=y
|
||||||
|
fi
|
||||||
|
|
||||||
|
section "Select steps to run"
|
||||||
|
read -p " Redeploy SQL functions? [Y/n]: " DO_FN; DO_FN=${DO_FN:-y}
|
||||||
|
read -p " Rebuild UI? [Y/n]: " DO_BUILD; DO_BUILD=${DO_BUILD:-y}
|
||||||
|
read -p " Set up / update nginx? [y/N]: " DO_NGINX
|
||||||
|
read -p " Restart API service? [Y/n]: " DO_RESTART; DO_RESTART=${DO_RESTART:-y}
|
||||||
|
|
||||||
|
if [[ "$DO_NGINX" =~ ^[Yy]$ ]]; then
|
||||||
|
read -p " Nginx domain: " NGINX_DOMAIN
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Phase 2: Plan summary ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
section "Plan"
|
||||||
|
echo " Mode: $( [ "$MODE" = "install" ] && echo "First-time install" || echo "Update" )"
|
||||||
|
echo " Database: ${DB_USER}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
|
||||||
|
echo " API port: ${API_PORT:-3020}"
|
||||||
|
echo ""
|
||||||
|
echo " Steps:"
|
||||||
|
|
||||||
|
if [ "$MODE" = "install" ]; then
|
||||||
|
echo " • Install Node.js dependencies"
|
||||||
|
echo " • Test admin connection and create DB user/database"
|
||||||
|
echo " • Deploy schema and SQL functions"
|
||||||
|
[ -n "$NGINX_DOMAIN" ] && echo " • Configure nginx → $NGINX_DOMAIN" \
|
||||||
|
|| echo " • Nginx — skipped (no domain provided)"
|
||||||
|
echo " • Build UI"
|
||||||
|
echo " • Install systemd service"
|
||||||
|
echo " • Start service"
|
||||||
|
else
|
||||||
|
[ "${CHANGE_DB}" = "y" ] && echo " • Update .env with new database target"
|
||||||
|
[[ ! "$DO_FN" =~ ^[Nn]$ ]] && echo " • Redeploy SQL functions" \
|
||||||
|
|| echo " • SQL functions — skipped"
|
||||||
|
[[ ! "$DO_BUILD" =~ ^[Nn]$ ]] && echo " • Rebuild UI" \
|
||||||
|
|| echo " • UI build — skipped"
|
||||||
|
[ -n "$NGINX_DOMAIN" ] && echo " • Configure nginx → $NGINX_DOMAIN" \
|
||||||
|
|| echo " • Nginx — skipped"
|
||||||
|
[[ ! "$DO_RESTART" =~ ^[Nn]$ ]] && echo " • Restart API service" \
|
||||||
|
|| echo " • Service restart — skipped"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
read -p " Continue? [Y/n]: " _yn
|
||||||
|
[[ "$_yn" =~ ^[Nn]$ ]] && echo " Aborted." && exit 0
|
||||||
|
|
||||||
|
# ── Phase 3: Execute ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if [ "$MODE" = "install" ]; then
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
if confirm "Dependencies"; then
|
||||||
|
step "API (npm install)"
|
||||||
|
npm install --omit=dev -q && ok || fail "npm install failed"
|
||||||
|
|
||||||
|
step "UI (npm install)"
|
||||||
|
cd ui && npm install -q && cd .. && ok || fail "ui npm install failed"
|
||||||
|
else
|
||||||
|
info "skipped"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# PostgreSQL
|
||||||
|
if confirm "PostgreSQL"; then
|
||||||
|
step "Testing admin connection"
|
||||||
|
export PGPASSWORD="$ADMIN_PASS"
|
||||||
|
psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres -c '\q' 2>/dev/null && ok \
|
||||||
|
|| fail "Cannot connect as $ADMIN_USER"
|
||||||
|
|
||||||
|
step "Creating user '$DB_USER'"
|
||||||
if psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres -tAc \
|
if psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres -tAc \
|
||||||
"SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" | grep -q 1; then
|
"SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" 2>/dev/null | grep -q 1; then
|
||||||
echo "✓ User '$DB_USER' already exists"
|
echo -e "${DIM}already exists${RESET}"
|
||||||
else
|
else
|
||||||
psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres \
|
psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres \
|
||||||
-c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';" > /dev/null
|
-c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';" > /dev/null && ok \
|
||||||
echo "✓ User '$DB_USER' created"
|
|| fail "Could not create user"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create database
|
step "Creating database '$DB_NAME'"
|
||||||
if psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -lqt \
|
if psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -lqt \
|
||||||
| cut -d'|' -f1 | grep -qw "$DB_NAME"; then
|
| cut -d'|' -f1 | grep -qw "$DB_NAME"; then
|
||||||
echo "✓ Database '$DB_NAME' already exists"
|
echo -e "${DIM}already exists${RESET}"
|
||||||
else
|
else
|
||||||
psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres \
|
psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres \
|
||||||
-c "CREATE DATABASE $DB_NAME OWNER $DB_USER;" > /dev/null
|
-c "CREATE DATABASE $DB_NAME OWNER $DB_USER;" > /dev/null && ok \
|
||||||
echo "✓ Database '$DB_NAME' created"
|
|| fail "Could not create database"
|
||||||
fi
|
fi
|
||||||
unset PGPASSWORD
|
unset PGPASSWORD
|
||||||
|
|
||||||
# Write .env
|
step "Writing .env"
|
||||||
cat > .env << ENVEOF
|
cat > .env << ENVEOF
|
||||||
# Database Configuration
|
# Database Configuration
|
||||||
DB_HOST=$DB_HOST
|
DB_HOST=$DB_HOST
|
||||||
@ -90,35 +190,27 @@ DB_PASSWORD=$DB_PASSWORD
|
|||||||
API_PORT=$API_PORT
|
API_PORT=$API_PORT
|
||||||
NODE_ENV=$NODE_ENV
|
NODE_ENV=$NODE_ENV
|
||||||
ENVEOF
|
ENVEOF
|
||||||
echo "✓ .env written"
|
ok
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Deploy schema (first time only)
|
|
||||||
export PGPASSWORD="$DB_PASSWORD"
|
export PGPASSWORD="$DB_PASSWORD"
|
||||||
echo "Deploying schema..."
|
|
||||||
psql -U "$DB_USER" -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -f database/schema.sql -q
|
|
||||||
echo "✓ Schema deployed"
|
|
||||||
|
|
||||||
DEPLOY_FN=y
|
step "Deploying schema"
|
||||||
BUILD_UI=y
|
psql -U "$DB_USER" -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -f database/schema.sql -q && ok \
|
||||||
INSTALL_SERVICE=y
|
|| fail "Schema deploy failed"
|
||||||
RESTART=y
|
|
||||||
|
step "Deploying functions"
|
||||||
|
psql -U "$DB_USER" -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -f database/functions.sql -q && ok \
|
||||||
|
|| fail "Functions deploy failed"
|
||||||
|
else
|
||||||
|
info "skipped"
|
||||||
|
fi
|
||||||
|
|
||||||
# ── Update mode ───────────────────────────────────────────────────────────────
|
|
||||||
else
|
else
|
||||||
export $(cat .env | grep -v '^#' | xargs)
|
|
||||||
|
|
||||||
echo "Current database: ${DB_USER}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
|
|
||||||
read -p "Change database target? [y/N]: " IN
|
|
||||||
if [[ "$IN" =~ ^[Yy]$ ]]; then
|
|
||||||
echo ""
|
|
||||||
read -p " Host [${DB_HOST}]: " IN; DB_HOST=${IN:-$DB_HOST}
|
|
||||||
read -p " Port [${DB_PORT}]: " IN; DB_PORT=${IN:-$DB_PORT}
|
|
||||||
read -p " Database name [${DB_NAME}]: " IN; DB_NAME=${IN:-$DB_NAME}
|
|
||||||
read -p " User [${DB_USER}]: " IN; DB_USER=${IN:-$DB_USER}
|
|
||||||
read -s -p " Password (blank = keep current): " IN; echo ""
|
|
||||||
if [ -n "$IN" ]; then DB_PASSWORD=$IN; fi
|
|
||||||
|
|
||||||
|
# Update: save .env if DB target changed
|
||||||
|
section ".env"
|
||||||
|
if [ "${CHANGE_DB}" = "y" ]; then
|
||||||
|
step "Writing updated .env"
|
||||||
cat > .env << ENVEOF
|
cat > .env << ENVEOF
|
||||||
# Database Configuration
|
# Database Configuration
|
||||||
DB_HOST=$DB_HOST
|
DB_HOST=$DB_HOST
|
||||||
@ -131,69 +223,174 @@ DB_PASSWORD=$DB_PASSWORD
|
|||||||
API_PORT=${API_PORT:-3020}
|
API_PORT=${API_PORT:-3020}
|
||||||
NODE_ENV=${NODE_ENV:-production}
|
NODE_ENV=${NODE_ENV:-production}
|
||||||
ENVEOF
|
ENVEOF
|
||||||
echo "✓ .env updated"
|
ok
|
||||||
|
else
|
||||||
|
info "no changes"
|
||||||
fi
|
fi
|
||||||
echo ""
|
|
||||||
|
|
||||||
|
# Test connection
|
||||||
|
section "Database Connection"
|
||||||
|
step "Testing"
|
||||||
export PGPASSWORD="$DB_PASSWORD"
|
export PGPASSWORD="$DB_PASSWORD"
|
||||||
echo "Testing database connection..."
|
psql -U "$DB_USER" -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -c '\q' 2>/dev/null && ok \
|
||||||
if ! psql -U "$DB_USER" -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -c '\q' 2>/dev/null; then
|
|| fail "Cannot connect — check credentials"
|
||||||
echo "✗ Cannot connect — check credentials"
|
|
||||||
exit 1
|
# SQL functions
|
||||||
|
if [[ ! "$DO_FN" =~ ^[Nn]$ ]]; then
|
||||||
|
if confirm "SQL Functions"; then
|
||||||
|
step "Deploying functions"
|
||||||
|
psql -U "$DB_USER" -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -f database/functions.sql -q && ok \
|
||||||
|
|| fail "Functions deploy failed"
|
||||||
|
else
|
||||||
|
info "skipped"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
section "SQL Functions"
|
||||||
|
info "skipped"
|
||||||
fi
|
fi
|
||||||
echo "✓ Connected to ${DB_NAME} on ${DB_HOST}:${DB_PORT}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Redeploy SQL functions? [Y/n]: " DEPLOY_FN
|
|
||||||
read -p "Rebuild UI? [Y/n]: " BUILD_UI
|
|
||||||
read -p "Restart API server? [Y/n]: " RESTART
|
|
||||||
INSTALL_SERVICE=n
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Shared steps ──────────────────────────────────────────────────────────────
|
# ── UI ────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
if [[ ! "$DEPLOY_FN" =~ ^[Nn]$ ]]; then
|
if [ "$MODE" = "install" ] || [[ ! "$DO_BUILD" =~ ^[Nn]$ ]]; then
|
||||||
echo ""
|
if confirm "UI Build"; then
|
||||||
echo "Deploying SQL functions..."
|
step "Building"
|
||||||
export PGPASSWORD="$DB_PASSWORD"
|
cd ui && npm run build > /dev/null 2>&1 && cd .. && ok \
|
||||||
psql -U "$DB_USER" -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -f database/functions.sql -q
|
|| fail "UI build failed"
|
||||||
echo "✓ Functions deployed"
|
else
|
||||||
|
info "skipped"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
section "UI Build"
|
||||||
|
info "skipped"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! "$BUILD_UI" =~ ^[Nn]$ ]]; then
|
# ── Nginx ─────────────────────────────────────────────────────────────────────
|
||||||
echo ""
|
|
||||||
echo "Building UI..."
|
if [ -n "$NGINX_DOMAIN" ]; then
|
||||||
cd ui && npm run build && cd ..
|
if confirm "Nginx ($NGINX_DOMAIN)"; then
|
||||||
echo "✓ UI built"
|
CONF_NAME=$(echo "$NGINX_DOMAIN" | cut -d. -f1)
|
||||||
|
CONF_PATH="/etc/nginx/sites-enabled/$CONF_NAME"
|
||||||
|
CERT_PATH="/etc/letsencrypt/live/$NGINX_DOMAIN/fullchain.pem"
|
||||||
|
TMP_CONF=$(mktemp)
|
||||||
|
|
||||||
|
if [ -f "$CERT_PATH" ]; then
|
||||||
|
cat > "$TMP_CONF" << NGINXEOF
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name $NGINX_DOMAIN;
|
||||||
|
location / { return 301 https://\$host\$request_uri; }
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
listen [::]:443 ssl http2;
|
||||||
|
server_name $NGINX_DOMAIN;
|
||||||
|
|
||||||
|
ssl_certificate $CERT_PATH;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/$NGINX_DOMAIN/privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
ssl_session_cache shared:SSL:10m;
|
||||||
|
|
||||||
|
keepalive_timeout 70;
|
||||||
|
sendfile on;
|
||||||
|
client_max_body_size 80m;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:${API_PORT:-3020};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NGINXEOF
|
||||||
|
else
|
||||||
|
cat > "$TMP_CONF" << NGINXEOF
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name $NGINX_DOMAIN;
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:${API_PORT:-3020};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NGINXEOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
step "Writing /etc/nginx/sites-enabled/$CONF_NAME"
|
||||||
|
sudo cp "$TMP_CONF" "$CONF_PATH" && rm "$TMP_CONF" && ok \
|
||||||
|
|| fail "Could not write nginx config (check sudo)"
|
||||||
|
|
||||||
|
step "Testing nginx config"
|
||||||
|
sudo nginx -t > /dev/null 2>&1 && ok \
|
||||||
|
|| fail "nginx config invalid — run: sudo nginx -t"
|
||||||
|
|
||||||
|
step "Reloading nginx"
|
||||||
|
sudo systemctl reload nginx && ok \
|
||||||
|
|| fail "nginx reload failed"
|
||||||
|
|
||||||
|
if [ ! -f "$CERT_PATH" ]; then
|
||||||
|
warn "No SSL cert found for $NGINX_DOMAIN"
|
||||||
|
read -p " Run certbot now? [Y/n]: " _yn
|
||||||
|
if [[ ! "$_yn" =~ ^[Nn]$ ]]; then
|
||||||
|
step "Running certbot"
|
||||||
|
sudo certbot --nginx -d "$NGINX_DOMAIN" --non-interactive --agree-tos \
|
||||||
|
--redirect -m "admin@$NGINX_DOMAIN" > /dev/null 2>&1 && ok \
|
||||||
|
|| fail "certbot failed — run manually: sudo certbot --nginx -d $NGINX_DOMAIN"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
info "skipped"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
section "Nginx"
|
||||||
|
info "skipped"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Systemd service
|
# ── Systemd service ───────────────────────────────────────────────────────────
|
||||||
echo ""
|
|
||||||
SERVICE_FILE="/etc/systemd/system/dataflow.service"
|
SERVICE_FILE="/etc/systemd/system/dataflow.service"
|
||||||
if [ ! -f "$SERVICE_FILE" ] && [[ "$INSTALL_SERVICE" =~ ^[Yy]$ ]]; then
|
|
||||||
read -p "Install systemd service? (requires sudo) [Y/n]: " IN
|
|
||||||
if [[ ! "$IN" =~ ^[Nn]$ ]]; then
|
|
||||||
sudo cp "$SCRIPT_DIR/dataflow.service" "$SERVICE_FILE"
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable dataflow
|
|
||||||
echo "✓ Service installed and enabled"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! "$RESTART" =~ ^[Nn]$ ]]; then
|
if confirm "Systemd Service"; then
|
||||||
echo ""
|
|
||||||
if [ -f "$SERVICE_FILE" ]; then
|
if [ -f "$SERVICE_FILE" ]; then
|
||||||
sudo systemctl restart dataflow
|
info "already installed"
|
||||||
sleep 1
|
|
||||||
if systemctl is-active --quiet dataflow; then
|
|
||||||
echo "✓ Service restarted and running"
|
|
||||||
else
|
else
|
||||||
echo "✗ Service failed — check: journalctl -u dataflow -n 30"
|
step "Installing service"
|
||||||
fi
|
sudo cp "$SCRIPT_DIR/dataflow.service" "$SERVICE_FILE" && ok \
|
||||||
else
|
|| fail "Could not install service"
|
||||||
echo " Systemd service not installed. Start manually: node api/server.js"
|
|
||||||
|
step "Enabling on boot"
|
||||||
|
sudo systemctl daemon-reload && sudo systemctl enable dataflow > /dev/null 2>&1 && ok \
|
||||||
|
|| fail "Could not enable service"
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
info "skipped"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ── API Server ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if [ "$MODE" = "install" ] || [[ ! "$DO_RESTART" =~ ^[Nn]$ ]]; then
|
||||||
|
if confirm "API Server"; then
|
||||||
|
if [ -f "$SERVICE_FILE" ]; then
|
||||||
|
step "Restarting dataflow service"
|
||||||
|
sudo systemctl restart dataflow && sleep 1
|
||||||
|
systemctl is-active --quiet dataflow && ok \
|
||||||
|
|| fail "Service failed — check: journalctl -u dataflow -n 30"
|
||||||
|
else
|
||||||
|
info "systemd service not installed — start manually: node api/server.js"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
info "skipped"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
section "API Server"
|
||||||
|
info "skipped"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Done ──────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
section "Done"
|
||||||
|
echo " API: http://localhost:${API_PORT:-3020}"
|
||||||
|
[ -n "$NGINX_DOMAIN" ] && echo " Web: https://$NGINX_DOMAIN"
|
||||||
|
echo " Logs: journalctl -u dataflow -f"
|
||||||
echo ""
|
echo ""
|
||||||
echo "✓ Done — http://localhost:${API_PORT}"
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user