diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 6d713cd..37204d3 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,4 +1,4 @@ -name: Deploy con Docker Compose +name: Deploy Cirux to VPS using Docker Compose on: push: branches: @@ -14,4 +14,39 @@ jobs: - name: Construir y levantar contenedores run: | # Reconstruye las imágenes si hubo cambios en el Dockerfile y levanta en segundo plano - docker compose up --build -d \ No newline at end of file + docker compose up --build -d + docker image prune -f # Limpiar imágenes obsoletas + + +name: Deploy Cirux to VPS using Docker Compose + +on: + push: + branches: + - main # O la rama que uses como producción (ej. master) + +jobs: + deploy: + runs-on: ubuntu-latest # O la etiqueta que le hayas asignado a tu act_runner + + steps: + - name: Deploy via SSH + uses: https://github.com/appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.SSH_HOST }} + username: ${{ secrets.SSH_USER }} + key: ${{ secrets.SSH_KEY }} + port: ${{ secrets.SSH_PORT || 22 }} + script: | + # 1. Navegar al directorio donde está tu docker-compose y el clon del repo + cd /home/ubuntu/cirux + + # 2. Descargar los últimos cambios desde tu Gitea local + git pull origin main + + # 3. Reconstruir solo el servicio de Next.js de forma silenciosa + # Cambia 'nextjs-service' por el nombre exacto de tu servicio en el docker-compose.yml + docker compose up -d --build cirux + + # 4. Limpieza opcional de imágenes huérfanas/antiguas para no llenar el disco + docker image prune -f \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 4f90415..ac5c8b0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,50 +1,27 @@ # ─── Stage 1: Builder ─────────────────────────────────────────────────────── -FROM node:20-alpine AS builder -RUN apk add --no-cache libc6-compat +FROM node:20-alpine AS deps WORKDIR /app - COPY package.json package-lock.json ./ +RUN apk add --no-cache libc6-compat RUN npm ci && npm cache clean --force +FROM node:20-alpine AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules COPY . . - -ARG NEXT_PUBLIC_SUPABASE_URL -ARG NEXT_PUBLIC_SUPABASE_ANON_KEY -ENV NEXT_PUBLIC_SUPABASE_URL=$NEXT_PUBLIC_SUPABASE_URL -ENV NEXT_PUBLIC_SUPABASE_ANON_KEY=$NEXT_PUBLIC_SUPABASE_ANON_KEY - +# Next.js compila aquí (esta es la parte que consume RAM) RUN npm run build # ─── Stage 2: Production Runner ──────────────────────────────────────────── -FROM node:20-alpine AS runner +FROM node:18-alpine AS runner WORKDIR /app - -ENV NODE_ENV=production +ENV NODE_ENV production ENV PORT=3020 -ENV HOSTNAME=0.0.0.0 -RUN addgroup --system --gid 1001 nodejs && \ - adduser --system --uid 1001 nextjs - -# Copy full standalone output (may be flat or contain a subdir) -COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ - -# Ensure server.js exists at /app/server.js (create symlink if nested) -RUN if [ ! -f /app/server.js ]; then \ - SERVER_PATH=$(find /app -maxdepth 2 -name server.js | head -1) && \ - if [ -n "$SERVER_PATH" ]; then \ - ln -s "$SERVER_PATH" /app/server.js && \ - echo "Symlinked server.js: $SERVER_PATH -> /app/server.js"; \ - else \ - echo "ERROR: server.js not found" && exit 1; \ - fi; \ - fi - -# Copy static assets -COPY --from=builder --chown=nextjs:nodejs /app/public ./public -COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static - -USER nextjs +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/package.json ./package.json EXPOSE 3020 diff --git a/deploy-auto.sh b/deploy-auto.sh deleted file mode 100644 index 5dd5e9f..0000000 --- a/deploy-auto.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash -# ─── EnFlow Auto-Deploy Script ─────────────────────────────────────────────── -# Called by Gitea post-receive hook or manually -# Usage: /home/ubuntu/cirux/deploy-auto.sh - -set -e - -APP_DIR="/home/ubuntu/cirux" -LOG_FILE="/var/log/cirux-deploy.log" -BRANCH="main" - -echo "─────────────────────────────────────────" >> "$LOG_FILE" -echo "$(date '+%Y-%m-%d %H:%M:%S') - Starting deploy" >> "$LOG_FILE" - -cd "$APP_DIR" - -# Pull latest code -echo "Pulling latest code..." >> "$LOG_FILE" -git fetch origin >> "$LOG_FILE" 2>&1 -git reset --hard "origin/$BRANCH" >> "$LOG_FILE" 2>&1 - -# Install deps (if package.json changed) -if git diff --name-only HEAD~1 HEAD | grep -q "package.json\|package-lock.json"; then - echo "Dependencies changed, running npm ci..." >> "$LOG_FILE" - npm ci >> "$LOG_FILE" 2>&1 -fi - -# Rebuild Docker containers -echo "Rebuilding Docker containers..." >> "$LOG_FILE" -docker compose down >> "$LOG_FILE" 2>&1 -docker compose build --no-cache >> "$LOG_FILE" 2>&1 -docker compose up -d >> "$LOG_FILE" 2>&1 - -# Cleanup old images -docker image prune -f >> "$LOG_FILE" 2>&1 - -# Health check -echo "Running health check..." >> "$LOG_FILE" -sleep 10 - -RETRIES=5 -while [ $RETRIES -gt 0 ]; do - if curl -sf http://localhost:3020/api/health > /dev/null 2>&1; then - echo "$(date '+%Y-%m-%d %H:%M:%S') - Deploy successful ✅" >> "$LOG_FILE" - exit 0 - fi - sleep 3 - RETRIES=$((RETRIES - 1)) -done - -echo "$(date '+%Y-%m-%d %H:%M:%S') - Health check failed after deploy ⚠️" >> "$LOG_FILE" -exit 1 diff --git a/deploy.sh b/deploy.sh deleted file mode 100644 index d548056..0000000 --- a/deploy.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash -set -e - -# ─── EnFlow VPS Deploy Script ──────────────────────────────────────────────── -# Usage: ./deploy.sh [domain] [email] -# Example: ./deploy.sh cirux.silvioalzate.shop silvio@example.com - -DOMAIN=${1:-cirux.silvioalzate.shop} -EMAIL=${2:-help@silvioalzate.shop} -APP_DIR=$(pwd) - -echo "🚀 Cirux Deploy Script" -echo " Domain: $DOMAIN" -echo " Email: $EMAIL" -echo "" - -# ─── Prerequisites Check ───────────────────────────────────────────────────── -echo "📋 Checking prerequisites..." - -if ! command -v docker &> /dev/null; then - echo "❌ Docker not found. Installing..." - curl -fsSL https://get.docker.com | sh - sudo usermod -aG docker $USER -fi - -if ! command -v docker-compose &> /dev/null; then - echo "❌ Docker Compose not found. Installing..." - sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - sudo chmod +x /usr/local/bin/docker-compose -fi - -# ─── SSL Certificates ────────────────────────────────────────────────────── -echo "🔐 Setting up SSL certificates..." - -mkdir -p certbot/conf certbot/www - -if [ ! -d "certbot/conf/live/$DOMAIN" ]; then - echo " Obtaining initial certificate for $DOMAIN..." - - # Start nginx temporarily for certbot challenge - docker-compose up -d nginx - sleep 5 - - # Get certificate - docker-compose run --rm certbot certonly \ - --webroot \ - --webroot-path=/var/www/certbot \ - --email "$EMAIL" \ - --agree-tos \ - --no-eff-email \ - -d "$DOMAIN" - - # Stop temporary nginx - docker-compose down -fi - -# ─── Update nginx.conf domain ──────────────────────────────────────────────── -echo "📝 Updating nginx configuration..." -sed -i "s/cirux.silvioalzate.shop/$DOMAIN/g" nginx.conf - -# ─── Environment Variables ───────────────────────────────────────────────── -echo "🔧 Checking environment variables..." - -if [ ! -f ".env.local" ]; then - echo "⚠️ .env.local not found! Creating from example..." - cp .env.local.example .env.local - echo "❌ IMPORTANT: Edit .env.local with your real credentials before continuing!" - exit 1 -fi - -# ─── Build & Deploy ──────────────────────────────────────────────────────── -echo "🏗️ Building Docker images..." -docker-compose down 2>/dev/null || true -docker-compose build --no-cache - -echo "🚀 Starting services..." -docker-compose up -d - -# ─── Verify Deployment ───────────────────────────────────────────────────── -echo "✅ Verifying deployment..." -sleep 10 - -if curl -sf http://localhost:3020/api/health > /dev/null 2>&1; then - echo "✅ App is responding on port 3020" -else - echo "⚠️ App health check failed. Check logs: docker-compose logs cirux-app" -fi - -echo "" -echo "─────────────────────────────────────────" -echo "🎉 Deployment Complete!" -echo "" -echo " App: https://$DOMAIN" -echo " Logs: docker-compose logs -f cirux-app" -echo " Restart: docker-compose restart cirux-app" -echo " Update: git pull && ./deploy.sh" -echo "" -echo " SSL cert will auto-renew via certbot." -echo "─────────────────────────────────────────" diff --git a/docker-compose.yml b/docker-compose.yml index 002e95b..8499b73 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,13 +1,13 @@ services: # ─── EnFlow Next.js App ────────────────────────────────────────────────── - cirux-app: + cirux: build: context: . dockerfile: Dockerfile args: - NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL} - NEXT_PUBLIC_SUPABASE_ANON_KEY=${NEXT_PUBLIC_SUPABASE_ANON_KEY} - container_name: cirux-app + container_name: cirux restart: unless-stopped env_file: - .env @@ -15,9 +15,16 @@ services: - NODE_ENV=production ports: - "127.0.0.1:3020:3020" + network: + - gitea-network healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:3020/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"] interval: 30s timeout: 5s retries: 3 start_period: 10s + + +networks: + gitea-network: + external: true \ No newline at end of file diff --git a/gitea-post-receive-hook.sh b/gitea-post-receive-hook.sh deleted file mode 100644 index aa9ee60..0000000 --- a/gitea-post-receive-hook.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -# ─── Gitea Post-Receive Hook ──────────────────────────────────────────────── -# Location: /home/ubuntu/gitea/gitea/git/repositories/silvioalzate/cirux.git/hooks/post-receive -# Owner: ubuntu (run as gitea service user) -# Make executable: chmod +x post-receive - -set -e - -APP_DIR="/home/ubuntu/cirux" -LOG_FILE="/var/log/cirux-deploy.log" -BRANCH="main" -DEPLOY_SCRIPT="/home/ubuntu/cirux/deploy-auto.sh" - -echo "$(date '+%Y-%m-%d %H:%M:%S') - Push received, starting deploy..." >> "$LOG_FILE" - -# Read refs from stdin (standard git hook input) -while read oldrev newrev refname; do - # Only deploy on main branch pushes - if [ "$refname" = "refs/heads/$BRANCH" ]; then - echo "$(date '+%Y-%m-%d %H:%M:%S') - Deploying branch: $BRANCH" >> "$LOG_FILE" - - cd "$APP_DIR" - - # Run deploy script - /home/ubuntu/cirux/deploy-auto.sh >> "$LOG_FILE" 2>&1 - - # Verify health - sleep 5 - if curl -sf http://localhost:3020/api/health > /dev/null 2>&1; then - echo "$(date '+%Y-%m-%d %H:%M:%S') - Deploy successful ✅" >> "$LOG_FILE" - else - echo "$(date '+%Y-%m-%d %H:%M:%S') - Health check failed ⚠️" >> "$LOG_FILE" - fi - fi -done - -echo "$(date '+%Y-%m-%d %H:%M:%S') - Hook finished" >> "$LOG_FILE" diff --git a/setup-vps-deploy.sh b/setup-vps-deploy.sh deleted file mode 100644 index 49ecda7..0000000 --- a/setup-vps-deploy.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/bash -# ─── EnFlow VPS Auto-Deploy Setup ─────────────────────────────────────────── -# Run this ONCE on your VPS as root or with sudo -# This configures Gitea hook + Docker deploy automation - -set -e - -APP_DIR="/home/ubuntu/cirux" -GITEA_USER="ubuntu" -GITEA_REPO="/home/ubuntu/gitea/gitea/git/repositories/silvioalzate/cirux.git" -HOOK_DIR="$GITEA_REPO/hooks" -LOG_FILE="/var/log/cirux-deploy.log" -BRANCH="main" - -echo "🚀 Cirux Auto-Deploy Setup" -echo " App Dir: $APP_DIR" -echo " Gitea User: $GITEA_USER" -echo " Hook Dir: $HOOK_DIR" -echo "" - -# ─── 1. Verify Gitea user ───────────────────────────────────────────────── -echo "📋 Verifying Gitea user..." -if ! id "$GITEA_USER" &>/dev/null; then - echo "❌ User $GITEA_USER does not exist!" - echo " Check: ps aux | grep gitea" - exit 1 -fi - -# ─── 2. Add user to docker group ──────────────────────────────────────────── -echo "🔧 Adding $GITEA_USER to docker group..." -if ! groups "$GITEA_USER" | grep -q docker; then - sudo usermod -aG docker "$GITEA_USER" - echo " ✅ Added. IMPORTANT: You MUST run 'newgrp docker' or logout/login for this to take effect." -fi - -# ─── 3. Create app directory ───────────────────────────────────────────────── -echo "📁 Setting up app directory..." -if [ ! -d "$APP_DIR" ]; then - echo " Cloning repository..." - sudo -u "$GITEA_USER" git clone "$GITEA_REPO" "$APP_DIR" -else - echo " App directory exists. Updating remote..." - cd "$APP_DIR" - sudo -u "$GITEA_USER" git remote set-url origin "$GITEA_REPO" || true - sudo -u "$GITEA_USER" git fetch origin - sudo -u "$GITEA_USER" git reset --hard "origin/$BRANCH" -fi - -# Set ownership -sudo chown -R "$GITEA_USER":"$GITEA_USER" "$APP_DIR" -sudo chmod -R 755 "$APP_DIR" - -# ─── 4. Create log file with correct permissions ───────────────────────────── -echo "📝 Creating log file..." -sudo touch "$LOG_FILE" -sudo chown "$GITEA_USER":"$GITEA_USER" "$LOG_FILE" -sudo chmod 644 "$LOG_FILE" - -# ─── 5. Install post-receive hook ──────────────────────────────────────────── -echo "🔌 Installing Gitea post-receive hook..." -if [ ! -d "$HOOK_DIR" ]; then - echo "❌ Hook directory not found: $HOOK_DIR" - exit 1 -fi - -sudo cp "$APP_DIR/gitea-post-receive-hook.sh" "$HOOK_DIR/post-receive" -sudo chown "$GITEA_USER":"$GITEA_USER" "$HOOK_DIR/post-receive" -sudo chmod +x "$HOOK_DIR/post-receive" - -# ─── 6. Make deploy-auto.sh executable ───────────────────────────────────────── -echo "🔧 Setting up deploy script..." -sudo chmod +x "$APP_DIR/deploy-auto.sh" - -# ─── 7. Verify Docker access ───────────────────────────────────────────────── -echo "🐳 Verifying Docker access..." -if sudo -u "$GITEA_USER" docker ps > /dev/null 2>&1; then - echo " ✅ Docker access OK" -else - echo " ⚠️ Docker access failed. Run: newgrp docker (or logout/login)" -fi - -# ─── 8. Test deploy ────────────────────────────────────────────────────────── -echo "🧪 Testing deploy..." -cd "$APP_DIR" -sudo -u "$GITEA_USER" bash "$APP_DIR/deploy-auto.sh" - -echo "" -echo "─────────────────────────────────────────" -echo "✅ Setup Complete!" -echo "" -echo " Push to main branch → Auto deploy triggers" -echo " Logs: tail -f $LOG_FILE" -echo " App: http://localhost:3020" -echo "" -echo " If Docker failed: logout and login again, or run 'newgrp docker'" -echo "─────────────────────────────────────────"