114 lines
5.0 KiB
Bash
114 lines
5.0 KiB
Bash
#!/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"
|