#!/usr/bin/env bash # LDV staging/production setup script # Run as root or with sudo on a fresh Ubuntu/Debian server: # sudo bash deploy/setup.sh set -euo pipefail # ── config ──────────────────────────────────────────────────────────────────── INSTALL_DIR="/opt/ldv" APP_DIR="$INSTALL_DIR/ldv-backend" DATA_DIR="$INSTALL_DIR/data" BACKUP_DIR="/var/backups/ldv" LOG_DIR="/var/log/ldv" APP_USER="www-data" REPO_URL="https://github.com/vadhh/cra.git" ENV_FILE="$APP_DIR/.env" SERVICE_NAME="ldv" NGINX_SITE="ldv" # ────────────────────────────────────────────────────────────────────────────── RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' info() { echo -e "${GREEN}[ldv]${NC} $*"; } warn() { echo -e "${YELLOW}[warn]${NC} $*"; } die() { echo -e "${RED}[error]${NC} $*"; exit 1; } [[ $EUID -eq 0 ]] || die "Run with sudo: sudo bash deploy/setup.sh" # ── 1. system deps ──────────────────────────────────────────────────────────── info "Installing system dependencies..." apt-get update -qq apt-get install -y -qq python3 python3-pip libmagic1 rsync git nginx # ── 2. clone or update ──────────────────────────────────────────────────────── if [[ -d "$INSTALL_DIR/.git" ]]; then info "Repo already cloned — pulling latest..." git -C "$INSTALL_DIR" pull else info "Cloning repo to $INSTALL_DIR..." git clone "$REPO_URL" "$INSTALL_DIR" fi # ── 3. python deps ──────────────────────────────────────────────────────────── info "Installing Python dependencies..." pip3 install -q -r "$APP_DIR/requirements.txt" # ── 4. directories ──────────────────────────────────────────────────────────── info "Creating directories..." mkdir -p "$DATA_DIR" "$BACKUP_DIR" "$LOG_DIR" chown -R "$APP_USER:$APP_USER" "$DATA_DIR" "$BACKUP_DIR" "$LOG_DIR" "$INSTALL_DIR" # ── 5. .env ─────────────────────────────────────────────────────────────────── if [[ -f "$ENV_FILE" ]]; then warn ".env already exists at $ENV_FILE — skipping generation." warn "Edit it manually if you need to change values." else info "Generating .env..." SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))") ENC_KEY=$(cd "$APP_DIR" && python3 manage.py gen-key) read -rp "Admin email: " ADMIN_EMAIL read -rsp "Admin password: " ADMIN_PASSWORD; echo read -rp "Server domain or IP (e.g. 192.168.1.10 or app.example.com): " SERVER_HOST read -rp "Backup rsync target (leave blank to skip, e.g. user@host:/backups/ldv): " BACKUP_REMOTE cat > "$ENV_FILE" </dev/null || true) info "Database ready." # ── 7. systemd service ──────────────────────────────────────────────────────── info "Installing systemd service..." GUNICORN_BIN=$(which gunicorn || echo "/usr/local/bin/gunicorn") cat > /etc/systemd/system/${SERVICE_NAME}.service < /etc/nginx/sites-available/$NGINX_SITE < /etc/cron.d/ldv-backup chmod 644 /etc/cron.d/ldv-backup info "Backup cron installed (runs nightly at 02:00)." # ── 10. health check ───────────────────────────────────────────────────────── info "Waiting for server to start..." sleep 3 HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:5000/health) if [[ "$HTTP_STATUS" == "200" ]]; then info "Health check passed (HTTP 200)." curl -s http://127.0.0.1:5000/health | python3 -m json.tool else warn "Health check returned HTTP $HTTP_STATUS — check logs:" warn " journalctl -u $SERVICE_NAME -n 50" fi # ── done ────────────────────────────────────────────────────────────────────── echo "" echo -e "${GREEN}Setup complete.${NC}" echo "" echo " App running at : http://$SERVER_HOST" echo " Logs : $LOG_DIR/" echo " DB : $DATA_DIR/sydeco.db" echo " Backups : $BACKUP_DIR/" echo " Service : systemctl status $SERVICE_NAME" echo "" echo "Next steps:" echo " 1. Follow docs/staging-runbook.md sections 7-12 to validate" echo " 2. Set LDV_COOKIE_SECURE=1 in $ENV_FILE once you add HTTPS" echo " (add HTTPS with: sudo apt install certbot python3-certbot-nginx)" echo " (then run: sudo certbot --nginx -d $SERVER_HOST)"