#!/bin/bash
# ==========================================
# AegisOne Engineering — Full Deployment Script
# ==========================================
# Usage: bash deploy.sh [--skip-ssl]
# Run on VPS as angel user
set -e
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
log() { echo -e "${CYAN}[$(date +%H:%M:%S)]${NC} $1"; }
ok() { echo -e " ${GREEN}✅ $1${NC}"; }
info() { echo -e " ${YELLOW}ℹ️ $1${NC}"; }
fail() { echo -e " ${RED}❌ $1${NC}"; exit 1; }
SKIP_SSL=false
for arg in "$@"; do [ "$arg" = "--skip-ssl" ] && SKIP_SSL=true; done
cd "$(dirname "$0")"
echo -e "${CYAN}"
echo "=========================================="
echo " AegisOne Engineering — Deploy v2.0"
echo "=========================================="
echo -e "${NC}"
# ==========================================
# PART 1: Server Preparation
# ==========================================
log "PART 1: Server preparation"
if ! command -v docker &>/dev/null; then
log "Installing Docker..."
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker "$USER"
ok "Docker installed. Re-login required for docker group"
newgrp docker
else
ok "Docker already installed: $(docker --version)"
fi
# Create project structure
log "Creating /opt/projects/ structure..."
sudo mkdir -p /opt/projects/{nginx-proxy,gitea,aegisone-php,aegisone-py,portainer,project2,backups,certs,data}
sudo chown -R "$USER":"$USER" /opt/projects
ok "Structure created"
# Create Docker networks
log "Creating Docker networks..."
docker network inspect proxy-net &>/dev/null || docker network create proxy-net && ok "proxy-net"
docker network inspect aegisone-net &>/dev/null || docker network create aegisone-net && ok "aegisone-net"
docker network inspect gitea-net &>/dev/null || docker network create gitea-net && ok "gitea-net"
# ==========================================
# PART 2: Deploy nginx-proxy
# ==========================================
log "PART 2: Deploy nginx-proxy"
NGX="/opt/projects/nginx-proxy"
cp nginx/nginx.conf "$NGX/"
cp -r nginx/conf.d/* "$NGX/conf.d/"
# Generate self-signed cert as placeholder
mkdir -p "$NGX/certs/live/aegisone.ru" "$NGX/html/.well-known/acme-challenge"
cat > "$NGX/html/index.html" <<< "
AegisOneAegisOne Engineering
"
if [ ! -f "$NGX/certs/live/aegisone.ru/fullchain.pem" ]; then
log "Generating self-signed SSL cert..."
openssl req -x509 -nodes -days 30 -newkey rsa:2048 \
-keyout "$NGX/certs/live/aegisone.ru/privkey.pem" \
-out "$NGX/certs/live/aegisone.ru/fullchain.pem" \
-subj "/CN=aegisone.ru" 2>/dev/null || {
docker run --rm -v "$NGX/certs:/certs" alpine:latest sh -c "
apk add openssl >/dev/null 2>&1
mkdir -p /certs/live/aegisone.ru
openssl req -x509 -nodes -days 30 -newkey rsa:2048 \
-keyout /certs/live/aegisone.ru/privkey.pem \
-out /certs/live/aegisone.ru/fullchain.pem \
-subj '/CN=aegisone.ru'
"
}
ok "Self-signed cert created"
fi
cp nginx/docker-compose.yml "$NGX/"
cd "$NGX" && docker compose up -d
ok "nginx-proxy started"
# ==========================================
# PART 3: Deploy aegisone-py (FastAPI + PostgreSQL)
# ==========================================
log "PART 3: Deploy aegisone-py (FastAPI + PostgreSQL)"
PY="/opt/projects/aegisone-py"
# Copy all py_service files
rsync -a --delete py_service/ "$PY/" 2>/dev/null || cp -r py_service/* "$PY/"
# Override docker-compose.yml with updated network config
cp py_service/docker-compose.yml "$PY/"
cd "$PY" && docker compose up -d --build
ok "aegisone-py started"
# ==========================================
# PART 3B: Deploy max_bot (MAX messenger bot)
# ==========================================
log "PART 3B: Deploy max_bot (MAX messenger bot on port 8002)"
BOT="/opt/projects/aegisone-py/max_bot"
mkdir -p "$BOT"
rsync -a --delete max_bot/ "$BOT/" 2>/dev/null || cp -r max_bot/* "$BOT/"
# Copy nginx config for max.aegisone.ru
cp max_bot/nginx/max-aegisone.conf "$NGX/conf.d/max-aegisone.conf"
docker compose -f "$NGX/docker-compose.yml" exec nginx nginx -s reload 2>/dev/null || true
ok "max_bot nginx config deployed"
cd "$BOT" && docker compose up -d --build
ok "max_bot started on port 8002"
# ==========================================
# PART 4: Deploy aegisone-php (Public site)
# ==========================================
log "PART 4: Deploy aegisone-php (Public site)"
PHP="/opt/projects/aegisone-php"
# Copy PHP source files from repo root (excluding certain dirs)
mkdir -p "$PHP/src"
rsync -a --delete \
--exclude='.git' --exclude='node_modules' --exclude='*.zip' \
--exclude='py_service' --exclude='aegisone-php' --exclude='nginx' \
--exclude='gitea' --exclude='portainer' --exclude='opencode.json' \
--exclude='site_aegisone.zip' \
./ "$PHP/src/"
# Copy Docker infrastructure
cp aegisone-php/Dockerfile "$PHP/"
cp aegisone-php/nginx.conf "$PHP/"
cp aegisone-php/docker-compose.yml "$PHP/"
cd "$PHP" && docker compose up -d --build
ok "aegisone-php started"
# ==========================================
# PART 5: Deploy Gitea
# ==========================================
log "PART 5: Deploy Gitea"
GITEA="/opt/projects/gitea"
cp gitea/docker-compose.yml "$GITEA/"
cd "$GITEA" && docker compose up -d
ok "Gitea started"
# ==========================================
# PART 6: Deploy Portainer (port 9000)
# ==========================================
log "PART 6: Deploy Portainer"
P="/opt/projects/portainer"
cp portainer/docker-compose.yml "$P/"
cd "$P" && docker compose up -d
ok "Portainer started on port 9000"
# ==========================================
# PART 7: Configure UFW
# ==========================================
log "PART 7: Configure UFW"
if ! sudo ufw status | grep -q "Status: active"; then
sudo ufw --force disable 2>/dev/null || true
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'SSH'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw allow 9000/tcp comment 'Portainer'
sudo ufw --force enable
ok "UFW configured"
else
ok "UFW already active"
fi
# ==========================================
# PART 8: Get SSL certificates
# ==========================================
if [ "$SKIP_SSL" = false ]; then
log "PART 8: Obtaining Let's Encrypt SSL certificates"
cd "$NGX"
docker compose run --rm certbot certonly --webroot \
--webroot-path=/var/www/certbot \
-d aegisone.ru -d www.aegisone.ru \
-d service.aegisone.ru \
-d max.aegisone.ru \
-d git.aegisone.ru \
--email admin@aegisone.ru \
--agree-tos --non-interactive 2>/dev/null && {
ok "SSL certificates obtained"
docker compose exec nginx nginx -s reload
ok "Nginx reloaded with real certs"
} || info "Certbot failed — run manually after DNS propagation"
else
info "SSL step skipped (--skip-ssl)"
fi
# ==========================================
# Done
# ==========================================
echo ""
echo -e "${GREEN}=========================================="
echo " Deploy complete!"
echo "==========================================${NC}"
echo ""
echo " nginx-proxy: http://81.177.141.34 → aegisone.ru"
echo " Portainer: http://81.177.141.34:9000"
echo " FastAPI (direct): http://81.177.141.34:8000"
echo " Gitea (direct): http://81.177.141.34:3000"
echo ""
echo " After DNS propagation, run certbot:"
echo " cd /opt/projects/nginx-proxy"
echo " docker compose run --rm certbot certonly --webroot \\"
echo " --webroot-path=/var/www/certbot \\"
echo " -d aegisone.ru -d www.aegisone.ru \\"
echo " -d service.aegisone.ru -d max.aegisone.ru \\"
echo " -d git.aegisone.ru \\"
echo " --email admin@aegisone.ru --agree-tos --non-interactive"
echo " docker compose exec nginx nginx -s reload"
echo ""