diff --git a/PROXMOX_DEPLOY_TEMPLATE.md b/PROXMOX_DEPLOY_TEMPLATE.md new file mode 100644 index 0000000..5d21676 --- /dev/null +++ b/PROXMOX_DEPLOY_TEMPLATE.md @@ -0,0 +1,211 @@ +# 🚀 Proxmox Deployment Template (TurnKey Node.js) + +**Use this guide to deploy ANY Node.js application to a TurnKey Linux LXC Container.** + +--- + +## 📋 Prerequisites + +1. **Project**: A Node.js application (Express, Next.js, etc.) in a Git repository. +2. **Server**: A Proxmox TurnKey Node.js Container. +3. **Access**: Root SSH password for the container. +4. **Domain (Optional)**: If using Cloudflare Tunnel. + +--- + +## 🛠️ Step 1: Prepare Your Project + +Ensure your project is ready for production: + +1. **Port Configuration**: Ensure your app listens on a configurable port or a fixed internal port (e.g., `4001`). + ```javascript + // server.js + const PORT = process.env.PORT || 4001; + app.listen(PORT, ...); + ``` + +2. **Git Ignore**: Ensure `node_modules` and config files with secrets are ignored. + ```gitignore + node_modules/ + .env + config.json + ``` + +--- + +## 🖥️ Step 2: One-Time Server Setup + +SSH into your new container: +```bash +ssh root@ +``` + +Run these commands to prepare the environment: + +### 1. Install Essentials +```bash +apt-get update && apt-get install -y git +``` + +### 2. Prepare Directory +```bash +# Standard web directory +mkdir -p /var/www/ +cd /var/www/ + +# Clone your repo (Use Basic Auth with Token if private) +# Format: https://:@github.com//.git +git clone . + +# Install dependencies +npm install +``` + +### 3. Setup Permissions +```bash +# Give ownership to www-data (Nginx user) +chown -R www-data:www-data /var/www/ +``` + +--- + +## ⚙️ Step 3: Application Configuration + +### 1. Systemd Service +Create a service file to keep your app running. + +Create `/etc/systemd/system/.service`: +```ini +[Unit] +Description= Service +After=network.target + +[Service] +Type=simple +User=root +# OR use 'www-data' if app doesn't need root ports +# User=www-data +WorkingDirectory=/var/www/ +ExecStart=/usr/local/bin/node server.js +Restart=always +Environment=NODE_ENV=production +Environment=PORT=4001 + +[Install] +WantedBy=multi-user.target +``` + +Enable and start: +```bash +systemctl daemon-reload +systemctl enable +systemctl start +``` + +### 2. Nginx Reverse Proxy +Configure Nginx to forward port 80 to your app (Port 4001). + +Create `/etc/nginx/sites-available/`: +```nginx +server { + listen 80; + server_name _; + + root /var/www/; + index index.html; + + # Serve static files (Optional) + location / { + try_files $uri $uri/ =404; + } + + # Proxy API/Dynamic requests + location /api { + proxy_pass http://localhost:4001; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} +``` + +Enable site: +```bash +# Remove defaults +rm -f /etc/nginx/sites-enabled/default +rm -f /etc/nginx/sites-enabled/nodejs + +# Link new site +ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/ + +# Reload +nginx -t && systemctl reload nginx +``` + +--- + +## ☁️ Step 4: Cloudflare Tunnel (Secure Access) + +Expose your app securely without opening router ports. + +### 1. Install Cloudflared +```bash +# Add Key +mkdir -p --mode=0755 /usr/share/keyrings +curl -fsSL https://pkg.cloudflare.com/cloudflare-public-v2.gpg | tee /usr/share/keyrings/cloudflare-public-v2.gpg >/dev/null + +# Add Repo +echo 'deb [signed-by=/usr/share/keyrings/cloudflare-public-v2.gpg] https://pkg.cloudflare.com/cloudflared any main' | tee /etc/apt/sources.list.d/cloudflared.list + +# Install +apt-get update && apt-get install -y cloudflared +``` + +### 2. Create Tunnel +```bash +cloudflared tunnel login +cloudflared tunnel create +# Follow on-screen instructions to map domain -> http://localhost:4001 +``` + +--- + +## 🔄 Step 5: Automated Updates (PowerShell) + +Create a script `deploy-remote.ps1` in your project root to automate updates. + +**Pre-requisite**: Create `deploy-config.json` (Add to .gitignore!): +```json +{ + "host": "", + "username": "root", + "password": "", + "remotePath": "/var/www/" +} +``` + +**Script `deploy-remote.ps1`**: +```powershell +# Reads config and updates remote server +$Config = Get-Content "deploy-config.json" | ConvertFrom-Json +$User = $Config.username; $HostName = $Config.host; $Pass = $Config.password +$RemotePath = $Config.remotePath + +# Commands to run remotely +$Cmds = " + cd $RemotePath + echo '⬇️ Pulling code...' + git pull + echo '📦 Installing deps...' + npm install + echo '🚀 Restarting service...' + systemctl restart + systemctl status --no-pager +" + +echo y | plink -ssh -t -pw $Pass "$User@$HostName" $Cmds +``` + +**Usage**: Just run `./deploy-remote.ps1` to deploy! diff --git a/README.md b/README.md index a240813..af38529 100644 --- a/README.md +++ b/README.md @@ -156,34 +156,54 @@ The server will start on **http://localhost:3000** --- -## 🚀 Production Deployment +## 🚀 Production Deployment (Proxmox + TurnKey Linux) -We support **Zero-Downtime Reliability** and **Auto-Start**. +We recommend using a **Proxmox TurnKey Node.js Container** for production. -### 1. Automated Deployment -Use our deployment script to setup Nginx/Apache and Node.js automatically: +### ✅ 1. One-Click Remote Deployment (Windows) +Easily deploy from your local Windows machine to the remote server using the included PowerShell script. -```bash -sudo bash deploy.sh +**Pre-requisite:** Create `deploy-config.json` in your project root (this file is ignored by git): +```json +{ + "host": "172.16.69.214", + "username": "root", + "password": "YOUR_SSH_PASSWORD", + "remotePath": "/var/www/connect5", + "gitToken": "YOUR_GITHUB_TOKEN" +} ``` -### 2. Auto-Start on Reboot (Systemd) -Never worry about server restarts again. Install the systemd service: - -```bash -sudo bash setup-auto-start.sh +**To Deploy or Update:** +```powershell +.\deploy-remote.ps1 ``` -*This ensures the app starts automatically and waits for the database to be ready.* +*This script automatically updates code, installs dependencies, and restarts the service.* -### 3. Auto-Deploy (Git Hooks) -Enable automatic updates when you `git pull`: +### 🔄 2. Automated Updates (Cron Job) +The server is configured to **automatically pull updates from GitHub every 5 minutes**. +- **No changes?** Nothing happens. +- **New code?** The server pulls changes, runs `npm install`, and restarts the app using the `post-merge` hook. +### 🛡️ 3. Cloudflare Tunnel (Secure Access) +The application is securely exposed using a Cloudflare Tunnel, eliminating the need to open router ports. + +**Service Status:** ```bash -bash setup-auto-deploy.sh +systemctl status connect5 ``` -*This installs a hook to restart the service automatically after code changes.* -See [DEPLOYMENT.md](DEPLOYMENT.md) for full details. +**Logs:** +```bash +journalctl -u connect5 -f +``` + +### 🔒 4. Security & Configuration +- **Systemd**: The app runs as a `systemd` service (`connect5`), ensuring it auto-starts on boot. +- **Nginx**: Configured as a reverse proxy on Port 80. +- **Secrets**: Database credentials are stored in `db.config.js` and excluded from source control. + +See [PROXMOX_DEPLOY_TEMPLATE.md](PROXMOX_DEPLOY_TEMPLATE.md) for the manual setup guide. --- diff --git a/deploy-remote.ps1 b/deploy-remote.ps1 new file mode 100644 index 0000000..0d63c97 --- /dev/null +++ b/deploy-remote.ps1 @@ -0,0 +1,53 @@ +<# +.SYNOPSIS + Automated Update Script for Vendor Inventory (Remote) +.DESCRIPTION + Reads configuration from deploy-config.json. + Connects to the remote server, pulls the latest code, installs dependencies, and restarts the service. +#> + +$ErrorActionPreference = "Stop" +$ConfigPath = Join-Path $PSScriptRoot "deploy-config.json" + +if (-not (Test-Path $ConfigPath)) { + Write-Error "Configuration file not found: $ConfigPath" + exit 1 +} + +$Config = Get-Content $ConfigPath | ConvertFrom-Json +$HostName = $Config.host +$User = $Config.username +$Password = $Config.password +$RemotePath = $Config.remotePath + +Write-Host "Connecting to $User@$HostName for update..." -ForegroundColor Cyan + +# Check for plink +if (-not (Get-Command "plink" -ErrorAction SilentlyContinue)) { + Write-Error "Plink (PuTTY Link) is required but not found. Please install PuTTY." + exit 1 +} + +# Commands to run on remote +$RemoteCommands = " + echo '📂 Navigating to $RemotePath...' + cd $RemotePath + + echo '⬇️ Pulling latest changes...' + git pull + + echo '📦 Installing dependencies...' + npm install + + echo '🚀 Restarting Service...' + systemctl restart connect5 + + echo '✅ Status Check:' + systemctl status connect5 --no-pager +" + +# Execute +$RemoteCommands = $RemoteCommands -replace "`r`n", "`n" +echo y | plink -ssh -P 22 -t -pw $Password "$User@$HostName" $RemoteCommands + +Write-Host "`nUpdate Sequence Completed." -ForegroundColor Green diff --git a/initial-deploy.ps1 b/initial-deploy.ps1 new file mode 100644 index 0000000..dc6fb4c --- /dev/null +++ b/initial-deploy.ps1 @@ -0,0 +1,125 @@ + +# Initial Deployment Script for Connect-5 +# Usage: ./initial-deploy.ps1 +$ErrorActionPreference = "Stop" + +# Load Configuration +$ConfigPath = Join-Path $PSScriptRoot "deploy-config.json" +if (-not (Test-Path $ConfigPath)) { Write-Error "Config file not found"; exit 1 } +$Config = Get-Content $ConfigPath | ConvertFrom-Json + +$HostName = $Config.host +$User = $Config.username +$Password = $Config.password +$RemotePath = $Config.remotePath +$GitToken = $Config.gitToken +$GitRepo = "https://${GitToken}@github.com/DeNNiiInc/Connect-5.git" +$DBPassword = "SecurePassword123!" # Hardcoded secure password for automation + +Write-Host "🚀 Starting Remote Deployment to $User@$HostName..." -ForegroundColor Cyan + +# Check for plink +if (-not (Get-Command "plink" -ErrorAction SilentlyContinue)) { + Write-Error "Plink not found. Please install PuTTY." + exit 1 +} + +# Construct the massive command string +# We use a heredoc for the remote bash script +$RemoteScript = @" +set -e + +echo '📦 Step 1: Installing System Dependencies...' +apt-get update +apt-get install -y git postgresql postgresql-contrib + +echo '📂 Step 2: Preparing Directory...' +mkdir -p $RemotePath +chown -R root:root $RemotePath + +echo '⬇️ Step 3: Cloning Repository...' +if [ -d "$RemotePath/.git" ]; then + echo "Repo already exists, pulling..." + cd $RemotePath + git pull +else + git clone "$GitRepo" "$RemotePath" + cd "$RemotePath" +fi + +echo '📦 Step 4: Installing Node Modules...' +npm install + +echo '🔐 Step 5: Configuring Database...' +systemctl start postgresql +systemctl enable postgresql + +# Create DB Config File +cat > db.config.js < /etc/nginx/sites-available/connect5 <<'NGINX' +server { + listen 80; + server_name _; + root $RemotePath; + + location / { + proxy_pass http://localhost:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade `$http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host `$host; + proxy_cache_bypass `$http_upgrade; + } + + location /socket.io/ { + proxy_pass http://localhost:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade `$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host `$host; + proxy_set_header X-Real-IP `$remote_addr; + } +} +NGINX + +# Enable Site +ln -sf /etc/nginx/sites-available/connect5 /etc/nginx/sites-enabled/ +nginx -t +systemctl restart nginx + +echo '✅ Deployment Complete!' +"@ + + +# Execute via Plink +# We echo 'y' to accept the host key (blindly, for automation) +# Fix CRLF to LF for Linux compatibility +$RemoteScript = $RemoteScript -replace "`r`n", "`n" +plink -batch -P 22 -ssh -pw $Password "$User@$HostName" $RemoteScript + +Write-Host "Done!" -ForegroundColor Green diff --git a/setup.sh b/setup.sh new file mode 100644 index 0000000..30e1bd8 --- /dev/null +++ b/setup.sh @@ -0,0 +1,90 @@ +#!/bin/bash +set -e + +# Configuration +DB_PASSWORD="SecurePassword123!" +REMOTE_PATH="/var/www/connect5" +GIT_TOKEN="${GIT_TOKEN}" # Ensure this is passed as an env var or replaced before running +GIT_REPO="https://${GIT_TOKEN}@github.com/DeNNiiInc/Connect-5.git" + +echo '📦 Step 1: Installing System Dependencies...' +apt-get update +apt-get install -y git postgresql postgresql-contrib + +echo '📂 Step 2: Preparing Directory...' +mkdir -p $REMOTE_PATH +chown -R root:root $REMOTE_PATH + +echo '⬇️ Step 3: Cloning Repository...' +if [ -d "$REMOTE_PATH/.git" ]; then + echo "Repo already exists, pulling..." + cd $REMOTE_PATH + git pull +else + git clone "$GIT_REPO" "$REMOTE_PATH" + cd "$REMOTE_PATH" +fi + +echo '📦 Step 4: Installing Node Modules...' +npm install + +echo '🔐 Step 5: Configuring Database...' +systemctl start postgresql +systemctl enable postgresql + +# Create DB Config File +cat > db.config.js < /etc/nginx/sites-available/connect5 <