ldv-pilot / deploy /setup.sh
vadhhh's picture
Sync with GitHub master: CI, offline multilingual proof, MFA exemption
4cef597 verified
Raw
History Blame Contribute Delete
8.14 kB
#!/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" <<EOF
# Auto-generated by setup.sh — $(date -u +%Y-%m-%dT%H:%M:%SZ)
LDV_SECRET_KEY=$SECRET_KEY
LDV_ENCRYPTION_KEY=$ENC_KEY
LDV_PRODUCTION=1
LDV_COOKIE_SECURE=0
LDV_CORS_ORIGINS=http://$SERVER_HOST
LDV_DB_PATH=$DATA_DIR/sydeco.db
LDV_RETENTION_DAYS=30
LDV_BACKUP_DIR=$BACKUP_DIR
LDV_BACKUP_REMOTE=$BACKUP_REMOTE
LDV_BACKUP_KEEP_DAYS=30
LDV_MAX_UPLOAD_MB=10
LDV_DOWNLOAD_LINK_TTL=900
LDV_REMOTE_TRANSLATION=0
LDV_DEBUG=0
LDV_ADMIN_EMAIL=$ADMIN_EMAIL
LDV_ADMIN_PASSWORD=$ADMIN_PASSWORD
EOF
chmod 600 "$ENV_FILE"
chown "$APP_USER:$APP_USER" "$ENV_FILE"
info ".env written to $ENV_FILE"
fi
# ── 6. database init ──────────────────────────────────────────────────────────
info "Initialising database..."
(cd "$APP_DIR" && set -a && source "$ENV_FILE" && set +a && \
python3 -c "import database; database.init_db()" && \
python3 manage.py seed-admin 2>/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 <<EOF
[Unit]
Description=LDV Contract Analyzer
After=network.target
[Service]
User=$APP_USER
WorkingDirectory=$APP_DIR
EnvironmentFile=$ENV_FILE
ExecStart=$GUNICORN_BIN -w 2 -b 127.0.0.1:5000 --timeout 120 \\
--access-logfile $LOG_DIR/access.log \\
--error-logfile $LOG_DIR/error.log \\
app:app
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable "$SERVICE_NAME"
systemctl restart "$SERVICE_NAME"
info "Service $SERVICE_NAME started."
# ── 8. nginx ──────────────────────────────────────────────────────────────────
info "Configuring nginx..."
# read SERVER_HOST from .env if we skipped generation
SERVER_HOST=${SERVER_HOST:-$(grep LDV_CORS_ORIGINS "$ENV_FILE" | cut -d= -f2 | sed 's|https\?://||')}
cat > /etc/nginx/sites-available/$NGINX_SITE <<EOF
server {
listen 80;
server_name $SERVER_HOST;
client_max_body_size 15M;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_read_timeout 120s;
}
}
EOF
ln -sf /etc/nginx/sites-available/$NGINX_SITE /etc/nginx/sites-enabled/$NGINX_SITE
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl reload nginx
info "nginx configured."
# ── 9. backup cron ────────────────────────────────────────────────────────────
info "Installing backup cron..."
sed "s|/opt/ldv|$INSTALL_DIR|g" "$INSTALL_DIR/deploy/ldv-backup.cron" \
> /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)"