#!/usr/bin/env bash # # BZOD Production Docker Deployment # # Privacy-First URL Shortener & Landing Page Platform # # Usage: # curl -fsSL https://bzo.in/deploy.sh | sudo bash # # Or: # sudo bash deploy.sh # # Environment overrides: # BZOD_VERSION=0.8.0 # BZOD_IMAGE=nx9-url-shortener # BZOD_ROOT=/DATA/AppData/nx9-url-shortener # BZOD_PORT=8654 # set -euo pipefail # ============================================================ # Configuration # ============================================================ BZOD_VERSION="${BZOD_VERSION:-0.8.0}" BZOD_IMAGE="${BZOD_IMAGE:-nx9-url-shortener}" BZOD_ROOT="${BZOD_ROOT:-/DATA/AppData/nx9-url-shortener}" BZOD_PORT="${BZOD_PORT:-8654}" BASE_URL="${BASE_URL:-https://bzo.in}" CONTAINER_NAME="${CONTAINER_NAME:-bzod}" DATA_DIR="${BZOD_ROOT}/data" CONFIG_DIR="${BZOD_ROOT}/config" IMAGES_DIR="${BZOD_ROOT}/images" COMPOSE_DIR="${BZOD_ROOT}/compose" COMPOSE_FILE="${COMPOSE_DIR}/docker-compose.yml" ENV_FILE="${COMPOSE_DIR}/bzod.env" BACKUP_ROOT="${BZOD_ROOT}/backups" IMAGE="${BZOD_IMAGE}:${BZOD_VERSION}" # ============================================================ # Output # ============================================================ RED='\033[0;31m' GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[1;33m' NC='\033[0m' info() { echo -e "${BLUE}$*${NC}" } success() { echo -e "${GREEN}$*${NC}" } warning() { echo -e "${YELLOW}$*${NC}" } error() { echo -e "${RED}$*${NC}" >&2 } die() { error "$*" exit 1 } # ============================================================ # Root check # ============================================================ if [[ "${EUID}" -ne 0 ]]; then die "This script must be run as root. Use: sudo bash deploy.sh" fi echo echo -e "${BLUE}============================================================${NC}" echo -e "${BLUE} BZOD — Production Docker Deployment${NC}" echo -e "${BLUE}============================================================${NC}" echo echo "Version: ${BZOD_VERSION}" echo "Image: ${IMAGE}" echo "Application: ${BZOD_ROOT}" echo "Data: ${DATA_DIR}" echo "Config: ${CONFIG_DIR}" echo "Images: ${IMAGES_DIR}" echo "Port: ${BZOD_PORT}" echo # ============================================================ # 1. Install Docker # ============================================================ info "[1/8] Checking Docker..." if ! command -v docker >/dev/null 2>&1; then info "Docker is not installed. Installing Docker..." apt-get update -qq apt-get install -y \ ca-certificates \ curl install -m 0755 -d /etc/apt/keyrings if [[ ! -f /etc/apt/keyrings/docker.asc ]]; then curl -fsSL \ https://download.docker.com/linux/debian/gpg \ -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc fi . /etc/os-release echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \ https://download.docker.com/linux/debian \ ${VERSION_CODENAME} stable" \ > /etc/apt/sources.list.d/docker.list apt-get update -qq apt-get install -y \ docker-ce \ docker-ce-cli \ containerd.io \ docker-buildx-plugin \ docker-compose-plugin fi if ! docker info >/dev/null 2>&1; then systemctl enable --now docker fi if ! docker compose version >/dev/null 2>&1; then die "Docker Compose plugin is unavailable." fi success "✓ Docker and Docker Compose available" # ============================================================ # 2. Create persistent directories # ============================================================ info "[2/8] Creating persistent application directories..." mkdir -p \ "${DATA_DIR}" \ "${CONFIG_DIR}" \ "${IMAGES_DIR}" \ "${COMPOSE_DIR}" \ "${BACKUP_ROOT}" chmod 700 "${CONFIG_DIR}" chmod 755 "${IMAGES_DIR}" success "✓ Persistent directories ready" # ============================================================ # 3. Configuration # ============================================================ info "[3/8] Preparing configuration..." if [[ ! -f "${ENV_FILE}" ]]; then cat > "${ENV_FILE}" </dev/null | grep -q '^true$'; then error "BZOD container failed to start." echo docker compose \ --env-file "${ENV_FILE}" \ -f "${COMPOSE_FILE}" \ logs --tail=100 error error "Deployment failed. Existing data was not removed." error "Backup: ${BACKUP_DIR}" exit 1 fi success "✓ Container is running" # ------------------------------------------------------------ # Health check # ------------------------------------------------------------ HEALTH_OK=0 for _ in {1..12}; do if curl -fsS \ "http://127.0.0.1:${BZOD_PORT}/status" \ >/dev/null 2>&1; then HEALTH_OK=1 break fi sleep 2 done if [[ "${HEALTH_OK}" -eq 1 ]]; then success "✓ HTTP health check passed" else warning "⚠ HTTP health check did not respond yet" warning "The container is running; inspect logs if necessary:" echo echo " docker compose -f ${COMPOSE_FILE} logs --tail=100" fi # ============================================================ # Verify image and binary # ============================================================ echo info "Installed image:" docker image inspect "${IMAGE}" \ --format ' {{.RepoTags}} ({{.Id}})' \ 2>/dev/null || true echo info "Container:" docker inspect "${CONTAINER_NAME}" \ --format ' {{.Name}} {{.Config.Image}}' \ 2>/dev/null || true echo info "Persistent mounts:" docker inspect "${CONTAINER_NAME}" \ --format '{{range .Mounts}} {{.Source}} -> {{.Destination}}{{"\n"}}{{end}}' \ 2>/dev/null || true # ============================================================ # Final status # ============================================================ echo echo -e "${GREEN}============================================================${NC}" echo -e "${GREEN} BZOD ${BZOD_VERSION} deployed successfully${NC}" echo -e "${GREEN}============================================================${NC}" echo echo "Web UI:" echo " http://:${BZOD_PORT}" echo echo "Persistent data:" echo " ${DATA_DIR}" echo echo "Persistent images:" echo " ${IMAGES_DIR}" echo echo "Docker Compose:" echo " ${COMPOSE_FILE}" echo echo "Backup:" echo " ${BACKUP_DIR}" echo echo "Useful commands:" echo " docker compose -f ${COMPOSE_FILE} ps" echo " docker compose -f ${COMPOSE_FILE} logs -f bzod" echo " docker compose -f ${COMPOSE_FILE} restart bzod" echo success "Deployment complete."