ininventer/deploy.sh

286 lines
7.5 KiB
Bash
Executable File

#!/bin/bash
# InInventer Deployment Script for Debian 12
# This script will deploy the application to a Linode server
set -e # Exit on error
echo "======================================"
echo "InInventer Deployment Script"
echo "======================================"
# Variables
DOMAIN_NAME=""
EMAIL_FOR_SSL=""
APP_DIR="/opt/ininventer"
REPO_URL=""
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
echo -e "${GREEN}[STATUS]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
# Check if running as root
if [[ $EUID -ne 0 ]]; then
print_error "This script must be run as root"
exit 1
fi
# Get domain name from user
read -p "Enter your domain name (e.g., inventory.example.com): " DOMAIN_NAME
read -p "Enter email for SSL certificate: " EMAIL_FOR_SSL
print_status "Starting deployment for domain: $DOMAIN_NAME"
# Update system
print_status "Updating system packages..."
apt-get update
apt-get upgrade -y
# Install required packages
print_status "Installing required packages..."
apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release \
git \
ufw
# Install Docker
print_status "Installing Docker..."
if ! command -v docker &> /dev/null; then
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io
systemctl enable docker
systemctl start docker
else
print_status "Docker is already installed"
fi
# Install Docker Compose
print_status "Installing Docker Compose..."
if ! command -v docker-compose &> /dev/null; then
curl -L "https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
else
print_status "Docker Compose is already installed"
fi
# Configure firewall
print_status "Configuring firewall..."
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
# Create application directory
print_status "Creating application directory..."
mkdir -p $APP_DIR
cd $APP_DIR
# Copy application files
print_status "Setting up application files..."
# Note: You'll need to upload your files to the server first
# Create production environment file
print_status "Creating production environment configuration..."
cat > .env.production << EOL
# MongoDB Configuration
MONGO_URI=mongodb://mongodb:27017/ininventer
MONGO_INITDB_ROOT_USERNAME=admin
MONGO_INITDB_ROOT_PASSWORD=$(openssl rand -base64 32)
MONGO_INITDB_DATABASE=ininventer
# JWT Configuration
JWT_SECRET=$(openssl rand -base64 64)
JWT_EXPIRATION=24h
# Node Environment
NODE_ENV=production
PORT=5000
# Domain Configuration
DOMAIN_NAME=$DOMAIN_NAME
EMAIL_FOR_SSL=$EMAIL_FOR_SSL
EOL
# Create production docker-compose file
print_status "Creating production docker-compose configuration..."
cat > docker-compose.production.yml << 'EOL'
services:
mongodb:
image: mongo:latest
container_name: ininventer-mongodb-prod
restart: always
volumes:
- mongodb_data:/data/db
environment:
- MONGO_INITDB_ROOT_USERNAME=${MONGO_INITDB_ROOT_USERNAME}
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_INITDB_ROOT_PASSWORD}
- MONGO_INITDB_DATABASE=${MONGO_INITDB_DATABASE}
networks:
- ininventer-network
backend:
build: ./backend
container_name: ininventer-backend-prod
restart: always
depends_on:
- mongodb
environment:
- NODE_ENV=production
- MONGO_URI=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongodb:27017/${MONGO_INITDB_DATABASE}?authSource=admin
- JWT_SECRET=${JWT_SECRET}
- JWT_EXPIRATION=${JWT_EXPIRATION}
- PORT=5000
networks:
- ininventer-network
frontend:
build:
context: ./frontend
args:
- VITE_API_URL=/api
container_name: ininventer-frontend-prod
restart: always
depends_on:
- backend
networks:
- ininventer-network
nginx:
image: nginx:alpine
container_name: ininventer-nginx-prod
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/production.conf:/etc/nginx/conf.d/default.conf
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
depends_on:
- frontend
- backend
networks:
- ininventer-network
command: '/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g "daemon off;"'''
certbot:
image: certbot/certbot
container_name: ininventer-certbot
restart: unless-stopped
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
volumes:
mongodb_data:
networks:
ininventer-network:
driver: bridge
EOL
# Create Nginx production configuration
print_status "Creating Nginx production configuration..."
mkdir -p nginx
cat > nginx/production.conf << EOL
server {
listen 80;
server_name $DOMAIN_NAME;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://\$server_name\$request_uri;
}
}
server {
listen 443 ssl;
server_name $DOMAIN_NAME;
ssl_certificate /etc/letsencrypt/live/$DOMAIN_NAME/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN_NAME/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
client_max_body_size 10M;
location / {
proxy_pass http://frontend:80;
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;
}
location /api {
proxy_pass http://backend:5000;
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;
}
}
EOL
# Create initial Nginx configuration for SSL setup
cat > nginx/initial.conf << EOL
server {
listen 80;
server_name $DOMAIN_NAME;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 200 'InInventer - Setting up SSL...';
add_header Content-Type text/plain;
}
}
EOL
print_status "Deployment preparation complete!"
print_warning "Next steps:"
echo "1. Upload your application code to $APP_DIR"
echo "2. Run: cd $APP_DIR && ./start-production.sh"
echo ""
echo "The start script will:"
echo "- Obtain SSL certificates"
echo "- Start all services"
echo "- Configure automatic SSL renewal"