mirror of
https://github.com/DeNNiiInc/Advanced-Raid-Calculator.git
synced 2026-04-17 12:45:59 +00:00
refactor: align deployment with proxmox template
This commit is contained in:
211
PROXMOX_DEPLOY_TEMPLATE.md
Normal file
211
PROXMOX_DEPLOY_TEMPLATE.md
Normal file
@@ -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@<YOUR_SERVER_IP>
|
||||||
|
```
|
||||||
|
|
||||||
|
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/<APP_NAME>
|
||||||
|
cd /var/www/<APP_NAME>
|
||||||
|
|
||||||
|
# Clone your repo (Use Basic Auth with Token if private)
|
||||||
|
# Format: https://<USER>:<TOKEN>@github.com/<ORG>/<REPO>.git
|
||||||
|
git clone <YOUR_REPO_URL> .
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Setup Permissions
|
||||||
|
```bash
|
||||||
|
# Give ownership to www-data (Nginx user)
|
||||||
|
chown -R www-data:www-data /var/www/<APP_NAME>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ Step 3: Application Configuration
|
||||||
|
|
||||||
|
### 1. Systemd Service
|
||||||
|
Create a service file to keep your app running.
|
||||||
|
|
||||||
|
Create `/etc/systemd/system/<APP_NAME>.service`:
|
||||||
|
```ini
|
||||||
|
[Unit]
|
||||||
|
Description=<APP_NAME> 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/<APP_NAME>
|
||||||
|
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 <APP_NAME>
|
||||||
|
systemctl start <APP_NAME>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Nginx Reverse Proxy
|
||||||
|
Configure Nginx to forward port 80 to your app (Port 4001).
|
||||||
|
|
||||||
|
Create `/etc/nginx/sites-available/<APP_NAME>`:
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /var/www/<APP_NAME>;
|
||||||
|
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/<APP_NAME> /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 <TUNNEL_NAME>
|
||||||
|
# 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": "<SERVER_IP>",
|
||||||
|
"username": "root",
|
||||||
|
"password": "<SSH_PASSWORD>",
|
||||||
|
"remotePath": "/var/www/<APP_NAME>"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**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 <APP_NAME>
|
||||||
|
systemctl status <APP_NAME> --no-pager
|
||||||
|
"
|
||||||
|
|
||||||
|
echo y | plink -ssh -t -pw $Pass "$User@$HostName" $Cmds
|
||||||
|
```
|
||||||
|
|
||||||
|
**Usage**: Just run `./deploy-remote.ps1` to deploy!
|
||||||
15
advanced-raid-calculator.service
Normal file
15
advanced-raid-calculator.service
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Advanced Raid Calculator Service
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=www-data
|
||||||
|
WorkingDirectory=/var/www/advanced-raid-calculator
|
||||||
|
ExecStart=/usr/bin/node server.js
|
||||||
|
Restart=always
|
||||||
|
Environment=NODE_ENV=production
|
||||||
|
Environment=PORT=4001
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
36
deploy.sh
36
deploy.sh
@@ -3,30 +3,38 @@
|
|||||||
# Ensure we are in the project directory
|
# Ensure we are in the project directory
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
echo "Deploying Advanced Raid Calculator..."
|
APP_NAME="advanced-raid-calculator"
|
||||||
|
INSTALL_DIR="/var/www/$APP_NAME"
|
||||||
|
SERVICE_NAME="$APP_NAME.service"
|
||||||
|
|
||||||
|
echo "Deploying $APP_NAME..."
|
||||||
|
|
||||||
|
# Ensure install directory exists (if running for the first time outside of it, though git clone usually does this)
|
||||||
|
# If we are running this script FROM the repo, we assume we are already in the right place or we are setting it up.
|
||||||
|
# This script assumes it is being run inside the destination directory /var/www/advanced-raid-calculator
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
echo "Installing dependencies..."
|
echo "Installing dependencies..."
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
# Restart the application using PM2
|
# Setup Systemd Service
|
||||||
if command -v pm2 &> /dev/null; then
|
echo "Configuring Systemd Service..."
|
||||||
echo "Restarting with PM2..."
|
if [ -f "$SERVICE_NAME" ]; then
|
||||||
# Check if the process is already running
|
cp "$SERVICE_NAME" "/etc/systemd/system/$SERVICE_NAME"
|
||||||
if pm2 list | grep -q "raid-calculator"; then
|
systemctl daemon-reload
|
||||||
pm2 reload raid-calculator
|
systemctl enable "$SERVICE_NAME"
|
||||||
else
|
systemctl restart "$SERVICE_NAME"
|
||||||
pm2 start server.js --name "raid-calculator"
|
echo "Service restarted."
|
||||||
fi
|
|
||||||
pm2 save
|
|
||||||
else
|
else
|
||||||
echo "PM2 not found. Please install PM2 globally (npm install -g pm2)."
|
echo "Error: $SERVICE_NAME not found!"
|
||||||
# Fallback for testing without PM2, though PM2 is expected on the TurnKey template
|
exit 1
|
||||||
# node server.js
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Run the proxy setup script
|
# Run the proxy setup script
|
||||||
chmod +x setup-proxy.sh
|
chmod +x setup-proxy.sh
|
||||||
./setup-proxy.sh
|
./setup-proxy.sh
|
||||||
|
|
||||||
|
# Fix permissions (ensure www-data owns the web dir)
|
||||||
|
chown -R www-data:www-data "$INSTALL_DIR"
|
||||||
|
|
||||||
echo "Deployment complete."
|
echo "Deployment complete."
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const app = express();
|
const app = express();
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 4001;
|
||||||
|
|
||||||
// Serve static files from the current directory
|
// Serve static files from the current directory
|
||||||
app.use(express.static(__dirname));
|
app.use(express.static(__dirname));
|
||||||
|
|||||||
@@ -8,15 +8,25 @@ fi
|
|||||||
|
|
||||||
echo "Configuring Nginx Reverse Proxy..."
|
echo "Configuring Nginx Reverse Proxy..."
|
||||||
|
|
||||||
|
APP_NAME="advanced-raid-calculator"
|
||||||
|
PORT=4001
|
||||||
|
|
||||||
# Create Nginx config for the app
|
# Create Nginx config for the app
|
||||||
cat > /etc/nginx/sites-available/app <<EOF
|
cat > /etc/nginx/sites-available/$APP_NAME <<EOF
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
listen [::]:80;
|
listen [::]:80;
|
||||||
server_name _;
|
server_name _;
|
||||||
|
|
||||||
|
root /var/www/$APP_NAME;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://localhost:3000;
|
try_files \$uri \$uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /api {
|
||||||
|
proxy_pass http://localhost:$PORT;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Upgrade \$http_upgrade;
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
proxy_set_header Connection 'upgrade';
|
proxy_set_header Connection 'upgrade';
|
||||||
@@ -30,14 +40,15 @@ EOF
|
|||||||
rm -f /etc/nginx/sites-enabled/default
|
rm -f /etc/nginx/sites-enabled/default
|
||||||
rm -f /etc/nginx/sites-enabled/tkl-default
|
rm -f /etc/nginx/sites-enabled/tkl-default
|
||||||
rm -f /etc/nginx/sites-enabled/node
|
rm -f /etc/nginx/sites-enabled/node
|
||||||
|
rm -f /etc/nginx/sites-enabled/app
|
||||||
|
|
||||||
# Enable the new app configuration
|
# Enable the new app configuration
|
||||||
ln -sf /etc/nginx/sites-available/app /etc/nginx/sites-enabled/app
|
ln -sf /etc/nginx/sites-available/$APP_NAME /etc/nginx/sites-enabled/$APP_NAME
|
||||||
|
|
||||||
# Restart Nginx to apply changes
|
# Restart Nginx to apply changes
|
||||||
if systemctl is-active --quiet nginx; then
|
if systemctl is-active --quiet nginx; then
|
||||||
systemctl restart nginx
|
systemctl reload nginx
|
||||||
echo "Nginx restarted successfully."
|
echo "Nginx reloaded successfully."
|
||||||
else
|
else
|
||||||
echo "Nginx is not running. Starting it..."
|
echo "Nginx is not running. Starting it..."
|
||||||
systemctl start nginx
|
systemctl start nginx
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ if [ $LOCAL = $REMOTE ]; then
|
|||||||
elif [ $LOCAL = $BASE ]; then
|
elif [ $LOCAL = $BASE ]; then
|
||||||
echo "Need to pull"
|
echo "Need to pull"
|
||||||
git pull
|
git pull
|
||||||
# Only run deploy/restart if we actually pulled changes
|
# Re-run deploy to handle deps, service updates, and permissions
|
||||||
./deploy.sh
|
./deploy.sh
|
||||||
elif [ $REMOTE = $BASE ]; then
|
elif [ $REMOTE = $BASE ]; then
|
||||||
echo "Need to push"
|
echo "Need to push"
|
||||||
|
|||||||
Reference in New Issue
Block a user