diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml new file mode 100644 index 0000000..c296f06 --- /dev/null +++ b/.forgejo/workflows/deploy.yml @@ -0,0 +1,43 @@ +name: Deploy Waveform to VPS + +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Trigger Build & Deploy via SSH + uses: https://github.com/appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.VPS_HOST }} + username: ${{ secrets.VPS_USER }} + key: ${{ secrets.VPS_SSH_KEY }} + port: ${{ secrets.VPS_PORT }} + script_stop: true + script: | + echo "Starting deployment..." + cd /opt/containers/projects/waveform + + echo "Pulling latest code..." + git pull origin main + + echo "Applying DB migrations..." + docker compose exec -T waveform-studio npx drizzle-kit push --config=drizzle.config.ts + + echo "Rebuilding Docker containers..." + docker compose up -d --build + + echo "Cleaning up unused Docker images..." + docker image prune -f + + echo "Deployment completed successfully." + + - name: Send Telegram notification on failure + if: failure() + run: | + curl -s -X POST "https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendMessage" \ + -d chat_id="${{ secrets.TELEGRAM_CHAT_ID }}" \ + -d text="❌ Deployment Failed! Repository: $GITHUB_REPOSITORY (Commit: $GITHUB_SHA)" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bb15266 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,61 @@ +# Syntax directive specifying the Dockerfile format version. +# ============================================================================== +# @file Dockerfile +# @description Multi-stage Docker build for Next.js production deployments utilizing standalone output and secure user privileges. +# ============================================================================== + +# ------------------------------------------------------------------------------ +# Stage 1: Install Dependencies +# ------------------------------------------------------------------------------ +FROM node:20-alpine AS deps +WORKDIR /app + +# Copy package descriptors and install all project dependencies +COPY package*.json ./ +RUN npm install + +# ------------------------------------------------------------------------------ +# Stage 2: Build Application +# ------------------------------------------------------------------------------ +FROM node:20-alpine AS builder +WORKDIR /app + +# Copy node_modules from the dependencies stage and source code +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Argument aus docker-compose.yml übernehmen +ARG DATABASE_URL +ENV DATABASE_URL=$DATABASE_URL + +# Build the Next.js application for production +RUN npm run build + +# ------------------------------------------------------------------------------ +# Stage 3: Production Execution Server +# ------------------------------------------------------------------------------ +FROM node:20-alpine AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV PORT=3003 + +# Create a dedicated system user and group for security isolation +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +# Copy static assets and optimized standalone bundle from the build stage +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +# Prepare local persistent storage directory with correct user permissions +RUN mkdir -p /app/data && chown -R nextjs:nodejs /app/data + +# Switch to non-root user +USER nextjs + +EXPOSE 3003 + +# Start the standalone Node.js server +CMD ["node", "server.js"] \ No newline at end of file