#!/bin/bash # prepare-app.sh — Deploy ShortLink to Google Cloud (Ubuntu 22.04 VM) # Conditions: Run on a fresh GCP Compute Engine VM with Ubuntu 22.04. # Port 80 and 443 must be open in firewall. # DNS A record for DOMAIN must already point to this VM's external IP. # The .env file must exist (copy from .env.example and fill in values). set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" echo "======================================================" echo " ShortLink — Cloud Deployment Script" echo "======================================================" echo "" # ── 1. Load and validate environment ───────────────────────────────────────── if [ ! -f ".env" ]; then echo "ERROR: .env file not found!" echo " Run: cp .env.example .env" echo " Then edit .env with your values." exit 1 fi set -a # shellcheck disable=SC1091 source .env set +a : "${DOMAIN:?Set DOMAIN in .env (e.g. shortlink.example.com)}" : "${EMAIL:?Set EMAIL in .env (used for SSL certificate)}" : "${DB_NAME:?Set DB_NAME in .env}" : "${DB_USER:?Set DB_USER in .env}" : "${DB_PASSWORD:?Set DB_PASSWORD in .env}" : "${BASE_URL:?Set BASE_URL in .env (e.g. https://shortlink.example.com)}" echo "[ENV] Domain: $DOMAIN" echo "[ENV] Base URL: $BASE_URL" echo "" # ── 2. Install Docker ───────────────────────────────────────────────────────── if ! command -v docker &>/dev/null; then echo "[1/5] Installing Docker..." curl -fsSL https://get.docker.com | sudo sh sudo usermod -aG docker "$USER" # Re-exec with docker group applied so the rest of the script can use docker exec sg docker "$0" "$@" else echo "[1/5] Docker already installed: $(docker --version)" fi # ── 3. Install Docker Compose plugin ───────────────────────────────────────── if ! docker compose version &>/dev/null 2>&1; then echo "[2/5] Installing Docker Compose plugin..." sudo apt-get update -qq sudo apt-get install -y docker-compose-plugin else echo "[2/5] Docker Compose installed: $(docker compose version)" fi # ── 4. Install Certbot ──────────────────────────────────────────────────────── if ! command -v certbot &>/dev/null; then echo "[3/5] Installing Certbot..." sudo apt-get update -qq sudo apt-get install -y certbot else echo "[3/5] Certbot already installed: $(certbot --version)" fi # ── 5. Obtain SSL certificate ───────────────────────────────────────────────── if [ ! -d "/etc/letsencrypt/live/${DOMAIN}" ]; then echo "[4/5] Obtaining SSL certificate for ${DOMAIN}..." echo " (Certbot will temporarily listen on port 80 — ensure it is open)" sudo certbot certonly \ --standalone \ --non-interactive \ --agree-tos \ --email "${EMAIL}" \ -d "${DOMAIN}" echo " Certificate obtained successfully." else echo "[4/5] SSL certificate already exists for ${DOMAIN}." fi # ── 6. Generate nginx.conf from template ────────────────────────────────────── echo "[5/5] Generating nginx configuration..." sed "s/DOMAIN_PLACEHOLDER/${DOMAIN}/g" nginx/nginx.conf.template > nginx/nginx.conf # ── 7. Build and start containers ──────────────────────────────────────────── echo "[5/5] Building images and starting containers..." docker compose up -d --build # ── 8. Configure automatic SSL renewal ─────────────────────────────────────── APP_DIR="$SCRIPT_DIR" RENEW_CMD="certbot renew --quiet --pre-hook 'docker stop shortlink_nginx' --post-hook 'docker start shortlink_nginx' >> /var/log/certbot-renew.log 2>&1" (sudo crontab -l 2>/dev/null | grep -v certbot; echo "0 3 * * 0 $RENEW_CMD") | sudo crontab - echo " SSL auto-renewal cron job configured (every Sunday 03:00)." echo "" echo "╔══════════════════════════════════════════════╗" echo "║ ✅ Deployment Successful! ║" echo "╚══════════════════════════════════════════════╝" echo "" echo " Application URL : https://${DOMAIN}" echo " Health endpoint : https://${DOMAIN}/health" echo "" echo "Container status:" docker compose ps echo "" echo "To view logs: docker compose logs -f" echo "To stop: ./remove-app.sh" echo "To backup: ./scripts/backup.sh"