mirror of
https://github.com/thecyberlearn/hostinger-django-demo.git
synced 2026-08-18 14:12:57 +00:00
🎯 Remove redundant single project script
- Removed deploy/production-deploy.sh (redundant) - deploy-project.sh handles both single and multi-project perfectly - Updated README.md to reflect single deployment method - Even simpler: ONE deployment script for everything - Auto-extracts GitHub repo names for clean organization
This commit is contained in:
parent
629124f0d5
commit
c544d15e02
15
README.md
15
README.md
@ -34,16 +34,10 @@ ssh-keygen -f '/home/amit/.ssh/known_hosts' -R '69.62.81.168'
|
|||||||
scp setup-django-user.sh akvps:/root/
|
scp setup-django-user.sh akvps:/root/
|
||||||
ssh akvps "sudo bash /root/setup-django-user.sh"
|
ssh akvps "sudo bash /root/setup-django-user.sh"
|
||||||
|
|
||||||
# 3. Clone and deploy (choose one option below)
|
# 3. Clone and deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
### Option 1: Simple Single Project
|
### Deploy Your Project
|
||||||
```bash
|
|
||||||
ssh akvps "cd /home/django && git clone https://github.com/thecyberlearn/hostinger-django-demo.git"
|
|
||||||
ssh akvps "cd /home/django/hostinger-django-demo && sudo bash deploy/production-deploy.sh"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Option 2: Multi-Project System
|
|
||||||
```bash
|
```bash
|
||||||
ssh akvps "cd /home/django && git clone https://github.com/thecyberlearn/hostinger-django-demo.git"
|
ssh akvps "cd /home/django && git clone https://github.com/thecyberlearn/hostinger-django-demo.git"
|
||||||
ssh akvps "cd /home/django/hostinger-django-demo && sudo bash deploy/deploy-project.sh https://github.com/thecyberlearn/hostinger-django-demo.git"
|
ssh akvps "cd /home/django/hostinger-django-demo && sudo bash deploy/deploy-project.sh https://github.com/thecyberlearn/hostinger-django-demo.git"
|
||||||
@ -53,9 +47,8 @@ ssh akvps "cd /home/django/hostinger-django-demo && sudo bash deploy/deploy-proj
|
|||||||
|
|
||||||
## 📁 Key Files
|
## 📁 Key Files
|
||||||
|
|
||||||
**Main Deployment Scripts:**
|
**Main Deployment Script:**
|
||||||
- `deploy/production-deploy.sh` - Simple single project deployment
|
- `deploy/deploy-project.sh` - Deploys any Django project with auto repo naming
|
||||||
- `deploy/deploy-project.sh` - Multi-project system with auto repo naming
|
|
||||||
|
|
||||||
**Documentation:**
|
**Documentation:**
|
||||||
- `MULTI_PROJECT_SETUP.md` - Complete multi-project guide
|
- `MULTI_PROJECT_SETUP.md` - Complete multi-project guide
|
||||||
|
|||||||
@ -1,307 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Django Production Deployment Script
|
|
||||||
# Tested and battle-hardened for VPS deployment
|
|
||||||
# Usage: sudo bash production-deploy.sh
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Configuration
|
|
||||||
PROJECT_NAME="demo_project" # Change this to your Django project name
|
|
||||||
APP_NAME="django-app"
|
|
||||||
REPO_URL="" # Will be set by user input
|
|
||||||
DOMAIN="" # Will be set by user input
|
|
||||||
VPS_IP="" # Will be set by user input
|
|
||||||
|
|
||||||
echo -e "${BLUE}🚀 Django Production Deployment Script${NC}"
|
|
||||||
echo -e "${BLUE}======================================${NC}"
|
|
||||||
|
|
||||||
# Check if running as root
|
|
||||||
if [ "$EUID" -ne 0 ]; then
|
|
||||||
echo -e "${RED}❌ Please run this script as root (use sudo)${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get user input
|
|
||||||
echo -e "${YELLOW}📝 Configuration Setup${NC}"
|
|
||||||
read -p "Enter your Git repository URL: " REPO_URL
|
|
||||||
read -p "Enter your domain name (or press Enter to skip): " DOMAIN
|
|
||||||
read -p "Enter your VPS IP address: " VPS_IP
|
|
||||||
|
|
||||||
if [ -z "$REPO_URL" ]; then
|
|
||||||
echo -e "${RED}❌ Repository URL is required${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$VPS_IP" ]; then
|
|
||||||
echo -e "${RED}❌ VPS IP address is required${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "${GREEN}✅ Configuration set:${NC}"
|
|
||||||
echo -e "Repository: $REPO_URL"
|
|
||||||
echo -e "Domain: ${DOMAIN:-'Not set - will use IP'}"
|
|
||||||
echo -e "VPS IP: $VPS_IP"
|
|
||||||
echo
|
|
||||||
|
|
||||||
# Function to print status
|
|
||||||
print_status() {
|
|
||||||
echo -e "${GREEN}✅ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_progress() {
|
|
||||||
echo -e "${YELLOW}🔄 $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Step 1: System packages
|
|
||||||
print_progress "Installing system packages..."
|
|
||||||
apt update
|
|
||||||
apt install -y python3 python3-pip python3-venv python3-dev \
|
|
||||||
nginx postgresql postgresql-contrib libpq-dev \
|
|
||||||
build-essential curl git ufw
|
|
||||||
print_status "System packages installed"
|
|
||||||
|
|
||||||
# Step 2: Create user
|
|
||||||
print_progress "Creating django user..."
|
|
||||||
if ! id "django" &>/dev/null; then
|
|
||||||
adduser django --disabled-password --gecos ''
|
|
||||||
usermod -aG sudo django
|
|
||||||
print_status "Django user created"
|
|
||||||
else
|
|
||||||
print_status "Django user already exists"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Copy SSH keys if they exist
|
|
||||||
if [ -d "/root/.ssh" ] && [ -f "/root/.ssh/authorized_keys" ]; then
|
|
||||||
print_progress "Copying SSH keys to django user..."
|
|
||||||
mkdir -p /home/django/.ssh
|
|
||||||
cp /root/.ssh/authorized_keys /home/django/.ssh/
|
|
||||||
chown -R django:django /home/django/.ssh
|
|
||||||
chmod 700 /home/django/.ssh
|
|
||||||
chmod 600 /home/django/.ssh/authorized_keys
|
|
||||||
print_status "SSH keys copied"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 3: Project setup
|
|
||||||
print_progress "Setting up project directory..."
|
|
||||||
mkdir -p /var/www
|
|
||||||
chown django:www-data /var/www
|
|
||||||
|
|
||||||
# Clone or update project
|
|
||||||
if [ -d "/var/www/$APP_NAME" ]; then
|
|
||||||
print_progress "Updating existing project..."
|
|
||||||
sudo -u django bash -c "cd /var/www/$APP_NAME && git pull origin main"
|
|
||||||
else
|
|
||||||
print_progress "Cloning project..."
|
|
||||||
sudo -u django bash -c "cd /var/www && git clone $REPO_URL $APP_NAME"
|
|
||||||
fi
|
|
||||||
|
|
||||||
print_status "Project setup complete"
|
|
||||||
|
|
||||||
# Step 4: Virtual environment
|
|
||||||
print_progress "Setting up virtual environment..."
|
|
||||||
sudo -u django bash -c "
|
|
||||||
cd /var/www/$APP_NAME
|
|
||||||
rm -rf venv
|
|
||||||
python3 -m venv venv
|
|
||||||
source venv/bin/activate
|
|
||||||
pip install --upgrade pip
|
|
||||||
pip install -r requirements.txt
|
|
||||||
"
|
|
||||||
print_status "Virtual environment created"
|
|
||||||
|
|
||||||
# Step 5: Environment configuration
|
|
||||||
print_progress "Configuring environment..."
|
|
||||||
if [ ! -f "/var/www/$APP_NAME/.env" ]; then
|
|
||||||
sudo -u django bash -c "
|
|
||||||
cd /var/www/$APP_NAME
|
|
||||||
cp .env.example .env
|
|
||||||
"
|
|
||||||
|
|
||||||
# Generate secret key
|
|
||||||
SECRET_KEY=$(python3 -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())')
|
|
||||||
|
|
||||||
# Configure .env
|
|
||||||
sudo -u django bash -c "
|
|
||||||
cd /var/www/$APP_NAME
|
|
||||||
sed -i 's/SECRET_KEY=.*/SECRET_KEY=$SECRET_KEY/' .env
|
|
||||||
sed -i 's/DEBUG=.*/DEBUG=False/' .env
|
|
||||||
sed -i 's/ALLOWED_HOSTS=.*/ALLOWED_HOSTS=${DOMAIN:-$VPS_IP},$VPS_IP,localhost,127.0.0.1/' .env
|
|
||||||
sed -i 's/SECURE_SSL_REDIRECT=.*/SECURE_SSL_REDIRECT=False/' .env
|
|
||||||
"
|
|
||||||
print_status "Environment configured"
|
|
||||||
else
|
|
||||||
print_status "Environment file already exists"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 6: Django setup
|
|
||||||
print_progress "Running Django setup..."
|
|
||||||
sudo -u django bash -c "
|
|
||||||
cd /var/www/$APP_NAME
|
|
||||||
source venv/bin/activate
|
|
||||||
python manage.py collectstatic --noinput
|
|
||||||
python manage.py migrate
|
|
||||||
"
|
|
||||||
print_status "Django setup complete"
|
|
||||||
|
|
||||||
# Step 7: Systemd configuration
|
|
||||||
print_progress "Setting up Gunicorn service..."
|
|
||||||
|
|
||||||
# Create socket file
|
|
||||||
cat > /etc/systemd/system/gunicorn.socket << EOF
|
|
||||||
[Unit]
|
|
||||||
Description=gunicorn socket
|
|
||||||
|
|
||||||
[Socket]
|
|
||||||
ListenStream=/run/gunicorn.sock
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=sockets.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Create service file
|
|
||||||
cat > /etc/systemd/system/gunicorn.service << EOF
|
|
||||||
[Unit]
|
|
||||||
Description=Gunicorn daemon for Django app
|
|
||||||
Requires=gunicorn.socket
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
User=django
|
|
||||||
Group=www-data
|
|
||||||
WorkingDirectory=/var/www/$APP_NAME
|
|
||||||
Environment=DJANGO_SETTINGS_MODULE=$PROJECT_NAME.settings
|
|
||||||
EnvironmentFile=/var/www/$APP_NAME/.env
|
|
||||||
ExecStart=/var/www/$APP_NAME/venv/bin/gunicorn \\
|
|
||||||
--workers 3 \\
|
|
||||||
--bind unix:/run/gunicorn.sock \\
|
|
||||||
$PROJECT_NAME.wsgi:application
|
|
||||||
Restart=always
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl start gunicorn.socket
|
|
||||||
systemctl enable gunicorn.socket
|
|
||||||
print_status "Gunicorn service configured"
|
|
||||||
|
|
||||||
# Step 8: Nginx configuration
|
|
||||||
print_progress "Setting up Nginx..."
|
|
||||||
|
|
||||||
NGINX_CONFIG="/etc/nginx/sites-available/$APP_NAME"
|
|
||||||
cat > $NGINX_CONFIG << EOF
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name ${DOMAIN:-$VPS_IP} $VPS_IP;
|
|
||||||
|
|
||||||
# Security headers
|
|
||||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
||||||
add_header X-XSS-Protection "1; mode=block" always;
|
|
||||||
add_header X-Content-Type-Options "nosniff" always;
|
|
||||||
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
|
||||||
|
|
||||||
# Gzip compression
|
|
||||||
gzip on;
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_min_length 1024;
|
|
||||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
include proxy_params;
|
|
||||||
proxy_pass http://unix:/run/gunicorn.sock;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /static/ {
|
|
||||||
alias /var/www/$APP_NAME/staticfiles/;
|
|
||||||
expires 1y;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
}
|
|
||||||
|
|
||||||
location /media/ {
|
|
||||||
alias /var/www/$APP_NAME/media/;
|
|
||||||
expires 1y;
|
|
||||||
add_header Cache-Control "public";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Block access to sensitive files
|
|
||||||
location ~* /\.(?!well-known\/) {
|
|
||||||
deny all;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~* /(requirements\\.txt|\\.env|deploy/|\\.git/) {
|
|
||||||
deny all;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Enable site
|
|
||||||
ln -sf $NGINX_CONFIG /etc/nginx/sites-enabled/
|
|
||||||
rm -f /etc/nginx/sites-enabled/default
|
|
||||||
|
|
||||||
# Test and restart nginx
|
|
||||||
nginx -t
|
|
||||||
systemctl restart nginx
|
|
||||||
print_status "Nginx configured"
|
|
||||||
|
|
||||||
# Step 9: Firewall
|
|
||||||
print_progress "Configuring firewall..."
|
|
||||||
ufw default deny incoming
|
|
||||||
ufw default allow outgoing
|
|
||||||
ufw allow ssh
|
|
||||||
ufw allow 'Nginx Full'
|
|
||||||
ufw --force enable
|
|
||||||
print_status "Firewall configured"
|
|
||||||
|
|
||||||
# Step 10: Final checks
|
|
||||||
print_progress "Running final checks..."
|
|
||||||
|
|
||||||
# Check services
|
|
||||||
if systemctl is-active --quiet gunicorn.socket && systemctl is-active --quiet nginx; then
|
|
||||||
print_status "All services are running"
|
|
||||||
else
|
|
||||||
echo -e "${RED}❌ Some services are not running. Check logs:${NC}"
|
|
||||||
echo "sudo systemctl status gunicorn.service"
|
|
||||||
echo "sudo systemctl status nginx"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test HTTP response
|
|
||||||
echo -e "${YELLOW}🔍 Testing application...${NC}"
|
|
||||||
sleep 2
|
|
||||||
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://$VPS_IP || echo "000")
|
|
||||||
|
|
||||||
if [ "$HTTP_STATUS" = "200" ]; then
|
|
||||||
print_status "Application is responding correctly"
|
|
||||||
else
|
|
||||||
echo -e "${YELLOW}⚠️ HTTP Status: $HTTP_STATUS (check configuration)${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "${GREEN}🎉 Deployment Complete!${NC}"
|
|
||||||
echo -e "${BLUE}===================${NC}"
|
|
||||||
echo -e "🌐 Application URL: http://$VPS_IP"
|
|
||||||
if [ -n "$DOMAIN" ]; then
|
|
||||||
echo -e "🌐 Domain URL: http://$DOMAIN"
|
|
||||||
fi
|
|
||||||
echo -e "🔧 Admin Panel: http://$VPS_IP/admin"
|
|
||||||
echo
|
|
||||||
echo -e "${YELLOW}📋 Next Steps:${NC}"
|
|
||||||
echo -e "1. Create Django superuser: sudo -u django bash -c 'cd /var/www/$APP_NAME && source venv/bin/activate && python manage.py createsuperuser'"
|
|
||||||
if [ -n "$DOMAIN" ]; then
|
|
||||||
echo -e "2. Set up SSL certificate: sudo certbot --nginx -d $DOMAIN"
|
|
||||||
echo -e "3. Update SECURE_SSL_REDIRECT=True in .env after SSL setup"
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
echo -e "${YELLOW}🔧 Useful Commands:${NC}"
|
|
||||||
echo -e "Restart Django: sudo systemctl restart gunicorn.service"
|
|
||||||
echo -e "View logs: sudo journalctl -u gunicorn.service -f"
|
|
||||||
echo -e "Update code: sudo -u django bash -c 'cd /var/www/$APP_NAME && git pull && source venv/bin/activate && python manage.py migrate && python manage.py collectstatic --noinput' && sudo systemctl restart gunicorn.service"
|
|
||||||
|
|
||||||
echo -e "${GREEN}✅ Ready for production!${NC}"
|
|
||||||
Loading…
Reference in New Issue
Block a user