feat: add deployment guide, backup functionality, and cron jobs for automated backups
This commit is contained in:
410
DEPLOYMENT_GUIDE_TEMPLATE.md
Normal file
410
DEPLOYMENT_GUIDE_TEMPLATE.md
Normal file
@@ -0,0 +1,410 @@
|
|||||||
|
# Docker Git Deployment Strategy - Quick Guide
|
||||||
|
|
||||||
|
A proven deployment strategy for Next.js apps (or any Node.js app) on a VPS using Docker with Git integration.
|
||||||
|
|
||||||
|
## Quick Overview
|
||||||
|
|
||||||
|
**Strategy**: Docker containers + Git repo integration + Zero-downtime deployments
|
||||||
|
**Benefits**: Reproducible builds, easy rollbacks, consistent environments
|
||||||
|
**Time to setup**: ~30 minutes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1: Create Docker Files
|
||||||
|
|
||||||
|
### `Dockerfile` (Production)
|
||||||
|
```dockerfile
|
||||||
|
FROM node:22.11.0
|
||||||
|
|
||||||
|
# Set timezone (adjust for your region)
|
||||||
|
ENV TZ=Europe/Warsaw
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
|
# Install git for repo cloning
|
||||||
|
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Support building from Git repo
|
||||||
|
ARG GIT_REPO_URL
|
||||||
|
ARG GIT_BRANCH=main
|
||||||
|
ARG GIT_COMMIT
|
||||||
|
|
||||||
|
# Clone from git OR use local files
|
||||||
|
RUN if [ -n "$GIT_REPO_URL" ]; then \
|
||||||
|
git clone --branch ${GIT_BRANCH} ${GIT_REPO_URL} . && \
|
||||||
|
if [ -n "$GIT_COMMIT" ]; then git checkout ${GIT_COMMIT}; fi; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Copy entrypoint script
|
||||||
|
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
RUN chmod +x /docker-entrypoint.sh
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### `docker-entrypoint.sh`
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
echo "🚀 Starting application..."
|
||||||
|
|
||||||
|
# Create necessary directories
|
||||||
|
mkdir -p /app/data
|
||||||
|
mkdir -p /app/public/uploads
|
||||||
|
|
||||||
|
# Initialize database, create admin, etc.
|
||||||
|
node scripts/init-setup.js
|
||||||
|
|
||||||
|
# Start the app
|
||||||
|
exec npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
### `docker-compose.prod.yml`
|
||||||
|
```yaml
|
||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
- GIT_REPO_URL=${GIT_REPO_URL}
|
||||||
|
- GIT_BRANCH=${GIT_BRANCH:-main}
|
||||||
|
- GIT_COMMIT=${GIT_COMMIT}
|
||||||
|
ports:
|
||||||
|
- "3001:3000" # HOST:CONTAINER
|
||||||
|
volumes:
|
||||||
|
- ./data:/app/data # Persist database
|
||||||
|
- ./uploads:/app/public/uploads # Persist files
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- TZ=Europe/Warsaw
|
||||||
|
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
||||||
|
- NEXTAUTH_URL=${NEXTAUTH_URL}
|
||||||
|
- AUTH_TRUST_HOST=true
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2: Create Deployment Script
|
||||||
|
|
||||||
|
### `deploy.sh` (Linux/Mac)
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
GIT_REPO_URL=${1:-""}
|
||||||
|
GIT_BRANCH=${2:-"main"}
|
||||||
|
GIT_COMMIT=${3:-""}
|
||||||
|
|
||||||
|
# Load environment variables
|
||||||
|
if [ -f .env.production ]; then
|
||||||
|
export $(grep -v '^#' .env.production | xargs)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate critical vars
|
||||||
|
if [ -z "$NEXTAUTH_SECRET" ] || [ -z "$NEXTAUTH_URL" ]; then
|
||||||
|
echo "ERROR: Set NEXTAUTH_SECRET and NEXTAUTH_URL in .env.production"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build from Git or local files
|
||||||
|
if [ -z "$GIT_REPO_URL" ]; then
|
||||||
|
echo "Building from local files..."
|
||||||
|
docker-compose -f docker-compose.prod.yml build
|
||||||
|
else
|
||||||
|
echo "Building from git: $GIT_REPO_URL (branch: $GIT_BRANCH)"
|
||||||
|
GIT_REPO_URL=$GIT_REPO_URL GIT_BRANCH=$GIT_BRANCH GIT_COMMIT=$GIT_COMMIT \
|
||||||
|
docker-compose -f docker-compose.prod.yml build
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Deploy
|
||||||
|
echo "Deploying..."
|
||||||
|
docker-compose -f docker-compose.prod.yml down
|
||||||
|
docker-compose -f docker-compose.prod.yml up -d
|
||||||
|
|
||||||
|
echo "✅ Deployment completed!"
|
||||||
|
echo "Application running at: $NEXTAUTH_URL (port 3001 on host)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Make it executable:
|
||||||
|
```bash
|
||||||
|
chmod +x deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 3: Configure Environment
|
||||||
|
|
||||||
|
### `.env.production`
|
||||||
|
```bash
|
||||||
|
# Generate secret: openssl rand -base64 32
|
||||||
|
NEXTAUTH_SECRET=your-super-long-random-secret-at-least-32-chars
|
||||||
|
|
||||||
|
# Your public URL
|
||||||
|
NEXTAUTH_URL=https://yourdomain.com
|
||||||
|
|
||||||
|
NODE_ENV=production
|
||||||
|
AUTH_TRUST_HOST=true
|
||||||
|
```
|
||||||
|
|
||||||
|
**⚠️ NEVER commit `.env.production` to Git!**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 4: Setup VPS
|
||||||
|
|
||||||
|
### Initial VPS Setup
|
||||||
|
```bash
|
||||||
|
# SSH to VPS
|
||||||
|
ssh user@your-vps-ip
|
||||||
|
|
||||||
|
# Install Docker & Docker Compose
|
||||||
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||||
|
sudo sh get-docker.sh
|
||||||
|
sudo usermod -aG docker $USER
|
||||||
|
sudo apt install docker-compose-plugin
|
||||||
|
|
||||||
|
# Logout and login again for docker group to take effect
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setup Project Directory
|
||||||
|
```bash
|
||||||
|
ssh user@your-vps-ip
|
||||||
|
|
||||||
|
# Create project directory
|
||||||
|
mkdir -p ~/app
|
||||||
|
cd ~/app
|
||||||
|
|
||||||
|
# Copy deployment files (from local machine):
|
||||||
|
# scp docker-compose.prod.yml deploy.sh user@vps-ip:~/app/
|
||||||
|
# scp .env.production user@vps-ip:~/app/
|
||||||
|
|
||||||
|
# OR clone entire repo if using local file deployment:
|
||||||
|
git clone https://your-repo-url.git .
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 5: Setup Nginx Reverse Proxy
|
||||||
|
|
||||||
|
### Install Nginx
|
||||||
|
```bash
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install nginx certbot python3-certbot-nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configure Nginx
|
||||||
|
Create `/etc/nginx/sites-available/yourapp`:
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name yourdomain.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:3001;
|
||||||
|
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;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Enable site:
|
||||||
|
```bash
|
||||||
|
sudo ln -s /etc/nginx/sites-available/yourapp /etc/nginx/sites-enabled/
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl restart nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setup SSL (HTTPS)
|
||||||
|
```bash
|
||||||
|
sudo certbot --nginx -d yourdomain.com
|
||||||
|
# Follow prompts to get free SSL certificate
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 6: Deploy!
|
||||||
|
|
||||||
|
### Deployment Methods
|
||||||
|
|
||||||
|
**Method 1: From Local Files**
|
||||||
|
```bash
|
||||||
|
cd ~/app
|
||||||
|
git pull origin main # Update code
|
||||||
|
./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Method 2: From Git Repository**
|
||||||
|
```bash
|
||||||
|
cd ~/app
|
||||||
|
./deploy.sh https://git.yourserver.com/user/repo.git main
|
||||||
|
```
|
||||||
|
|
||||||
|
**Method 3: Specific Commit**
|
||||||
|
```bash
|
||||||
|
./deploy.sh https://git.yourserver.com/user/repo.git main abc123def
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ongoing Maintenance
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.prod.yml logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restart App
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.prod.yml restart
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Rebuild (for Dockerfile changes)
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.prod.yml down
|
||||||
|
docker-compose -f docker-compose.prod.yml build --no-cache
|
||||||
|
docker-compose -f docker-compose.prod.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Container Status
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.prod.yml ps
|
||||||
|
docker-compose -f docker-compose.prod.yml exec app date # Check timezone
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup Data
|
||||||
|
```bash
|
||||||
|
# Automated daily database backups are scheduled at 2 AM
|
||||||
|
# Backups are stored in ./backups/ directory, keeping last 30
|
||||||
|
# Check backup logs: docker-compose -f docker-compose.prod.yml exec app cat /app/data/backup.log
|
||||||
|
|
||||||
|
# Manual backup (if needed)
|
||||||
|
tar -czf backup-$(date +%Y%m%d).tar.gz data/ uploads/
|
||||||
|
|
||||||
|
# Download backups to local machine
|
||||||
|
scp user@vps-ip:~/app/backups/backup-*.sqlite ./local-backups/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rollback to Previous Version
|
||||||
|
```bash
|
||||||
|
# If using Git commits
|
||||||
|
./deploy.sh https://git.yourserver.com/user/repo.git main PREVIOUS_COMMIT_HASH
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Container won't start
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.prod.yml logs app
|
||||||
|
docker-compose -f docker-compose.prod.yml exec app sh # Get shell inside container
|
||||||
|
```
|
||||||
|
|
||||||
|
### Timezone issues
|
||||||
|
- Make sure `TZ` env var is set in docker-compose
|
||||||
|
- Rebuild image: timezone config is baked in during build
|
||||||
|
- Verify: `docker-compose -f docker-compose.prod.yml exec app date`
|
||||||
|
|
||||||
|
### Permission issues with volumes
|
||||||
|
```bash
|
||||||
|
# Fix ownership
|
||||||
|
sudo chown -R $USER:$USER data/ uploads/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Port already in use
|
||||||
|
```bash
|
||||||
|
# Check what's using port 3001
|
||||||
|
sudo netstat -tulpn | grep 3001
|
||||||
|
# Change port in docker-compose.prod.yml if needed
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security Checklist
|
||||||
|
|
||||||
|
- [ ] Strong `NEXTAUTH_SECRET` generated (min 32 chars)
|
||||||
|
- [ ] `.env.production` has secure permissions: `chmod 600 .env.production`
|
||||||
|
- [ ] Firewall configured: `sudo ufw allow 80,443/tcp`
|
||||||
|
- [ ] SSL certificate installed via Certbot
|
||||||
|
- [ ] Regular security updates: `sudo apt update && sudo apt upgrade`
|
||||||
|
- [ ] Docker images updated periodically
|
||||||
|
- [ ] Database backups automated
|
||||||
|
- [ ] Git credentials NOT stored in environment files
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy from Git
|
||||||
|
./deploy.sh https://git.server.com/user/repo.git main
|
||||||
|
|
||||||
|
# Deploy from local files
|
||||||
|
git pull && ./deploy.sh
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker-compose -f docker-compose.prod.yml logs -f
|
||||||
|
|
||||||
|
# Restart
|
||||||
|
docker-compose -f docker-compose.prod.yml restart
|
||||||
|
|
||||||
|
# Rebuild completely
|
||||||
|
docker-compose -f docker-compose.prod.yml down
|
||||||
|
docker-compose -f docker-compose.prod.yml build --no-cache
|
||||||
|
docker-compose -f docker-compose.prod.yml up -d
|
||||||
|
|
||||||
|
# Backup
|
||||||
|
tar -czf backup-$(date +%Y%m%d).tar.gz data/ uploads/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Advantages of This Strategy
|
||||||
|
|
||||||
|
✅ **Git Integration**: Deploy specific commits, branches, or tags
|
||||||
|
✅ **Reproducible**: Same build every time
|
||||||
|
✅ **Easy Rollbacks**: Just deploy previous commit
|
||||||
|
✅ **Isolated**: Container doesn't pollute host system
|
||||||
|
✅ **Persistent Data**: Volumes survive container rebuilds
|
||||||
|
✅ **Zero-Config Deployment**: Clone and run `./deploy.sh`
|
||||||
|
✅ **Works Offline**: Can build from local files without Git
|
||||||
|
✅ **Auto-Restart**: Container restarts on crash or reboot
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes to Future Self
|
||||||
|
|
||||||
|
1. **Always use volumes** for data persistence (database, uploads)
|
||||||
|
2. **Timezone matters**: Set it in both Dockerfile and docker-compose
|
||||||
|
3. **Rebuild vs Restart**: Dockerfile changes need rebuild, code changes just restart
|
||||||
|
4. **Port mapping**: Be consistent (I use 3001:3000 - HOST:CONTAINER)
|
||||||
|
5. **Environment secrets**: Never commit, always use `.env.production`
|
||||||
|
6. **Nginx**: Don't forget to setup reverse proxy and SSL
|
||||||
|
7. **Git auth**: For private repos, use SSH keys or tokens in URL
|
||||||
|
8. **Test locally first**: Use `docker-compose.yml` with `Dockerfile.dev`
|
||||||
|
9. **Monitor logs**: Set up log rotation if app is chatty
|
||||||
|
10. **Automate backups**: Cron job for daily database/file backups
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Time to deploy a new app with this strategy: ~20 minutes** ⚡
|
||||||
|
|
||||||
|
Copy these files, adjust for your app (mainly environment variables and init scripts), and you're production-ready!
|
||||||
@@ -5,8 +5,8 @@ FROM node:22.11.0
|
|||||||
ENV TZ=Europe/Warsaw
|
ENV TZ=Europe/Warsaw
|
||||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
# Install git
|
# Install git and cron
|
||||||
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y git cron && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Set the working directory
|
# Set the working directory
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ FROM node:22.11.0
|
|||||||
ENV TZ=Europe/Warsaw
|
ENV TZ=Europe/Warsaw
|
||||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
# Install git for development
|
# Install git and cron for development
|
||||||
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y git cron && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Set the working directory
|
# Set the working directory
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
40
backup-db.mjs
Normal file
40
backup-db.mjs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import Database from "better-sqlite3";
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
const dbPath = "data/database.sqlite";
|
||||||
|
const backupDir = "backups";
|
||||||
|
|
||||||
|
// Ensure backup directory exists
|
||||||
|
if (!fs.existsSync(backupDir)) {
|
||||||
|
fs.mkdirSync(backupDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate timestamp for backup filename
|
||||||
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
||||||
|
const backupPath = path.join(backupDir, `backup-${timestamp}.sqlite`);
|
||||||
|
|
||||||
|
// Create backup by copying the database file
|
||||||
|
fs.copyFileSync(dbPath, backupPath);
|
||||||
|
|
||||||
|
console.log(`✅ Backup created: ${backupPath}`);
|
||||||
|
|
||||||
|
// Cleanup: keep only last 30 backups
|
||||||
|
const files = fs.readdirSync(backupDir)
|
||||||
|
.filter(f => f.startsWith('backup-'))
|
||||||
|
.map(f => ({
|
||||||
|
name: f,
|
||||||
|
path: path.join(backupDir, f),
|
||||||
|
mtime: fs.statSync(path.join(backupDir, f)).mtime
|
||||||
|
}))
|
||||||
|
.sort((a, b) => b.mtime - a.mtime); // Sort by modification time, newest first
|
||||||
|
|
||||||
|
if (files.length > 30) {
|
||||||
|
const toDelete = files.slice(30);
|
||||||
|
toDelete.forEach(f => {
|
||||||
|
fs.unlinkSync(f.path);
|
||||||
|
console.log(`🗑️ Deleted old backup: ${f.name}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`📁 Total backups kept: ${Math.min(files.length, 30)}`);
|
||||||
@@ -14,6 +14,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
- ./uploads:/app/public/uploads
|
- ./uploads:/app/public/uploads
|
||||||
|
- ./backups:/app/backups
|
||||||
environment:
|
environment:
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
- TZ=Europe/Warsaw
|
- TZ=Europe/Warsaw
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ services:
|
|||||||
- .:/app
|
- .:/app
|
||||||
- /app/node_modules
|
- /app/node_modules
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
|
- ./backups:/app/backups
|
||||||
environment:
|
environment:
|
||||||
- NODE_ENV=development
|
- NODE_ENV=development
|
||||||
- TZ=Europe/Warsaw
|
- TZ=Europe/Warsaw
|
||||||
|
|||||||
@@ -20,6 +20,13 @@ chmod -R 755 /app/public/uploads
|
|||||||
echo "🔧 Setting up admin account..."
|
echo "🔧 Setting up admin account..."
|
||||||
node scripts/create-admin.js
|
node scripts/create-admin.js
|
||||||
|
|
||||||
|
# Set up daily backup cron job (runs at 2 AM daily)
|
||||||
|
echo "⏰ Setting up daily backup cron job..."
|
||||||
|
echo "0 2 * * * cd /app && node backup-db.mjs >> /app/data/backup.log 2>&1" > /etc/cron.d/backup-cron
|
||||||
|
chmod 0644 /etc/cron.d/backup-cron
|
||||||
|
crontab /etc/cron.d/backup-cron
|
||||||
|
service cron start
|
||||||
|
|
||||||
# Start the development server
|
# Start the development server
|
||||||
echo "✅ Starting development server..."
|
echo "✅ Starting development server..."
|
||||||
exec npm run dev
|
exec npm run dev
|
||||||
|
|||||||
@@ -24,6 +24,13 @@ node scripts/create-admin.js
|
|||||||
echo "🔄 Running database migrations..."
|
echo "🔄 Running database migrations..."
|
||||||
./run-migrations.sh
|
./run-migrations.sh
|
||||||
|
|
||||||
|
# Set up daily backup cron job (runs at 2 AM daily)
|
||||||
|
echo "⏰ Setting up daily backup cron job..."
|
||||||
|
echo "0 2 * * * cd /app && node backup-db.mjs >> /app/data/backup.log 2>&1" > /etc/cron.d/backup-cron
|
||||||
|
chmod 0644 /etc/cron.d/backup-cron
|
||||||
|
crontab /etc/cron.d/backup-cron
|
||||||
|
service cron start
|
||||||
|
|
||||||
# Start the application
|
# Start the application
|
||||||
echo "✅ Starting production server..."
|
echo "✅ Starting production server..."
|
||||||
exec npm start
|
exec npm start
|
||||||
|
|||||||
Reference in New Issue
Block a user