File size: 8,143 Bytes
4cef597
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/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)"