deployment script
This commit is contained in:
197
deploy.sh
Executable file
197
deploy.sh
Executable file
@@ -0,0 +1,197 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Deployment script for Hex's Garage Sale Catalog
|
||||||
|
# This script automates the deployment process on a Debian server
|
||||||
|
|
||||||
|
set -e # Exit immediately if a command exits with a non-zero status
|
||||||
|
|
||||||
|
# Color codes for better readability
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Function to print colored messages
|
||||||
|
print_message() {
|
||||||
|
echo -e "${GREEN}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_warning() {
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$(id -u)" != "0" ]; then
|
||||||
|
print_error "This script must be run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get deployment configuration
|
||||||
|
read -p "Enter domain name (e.g., garagesale.example.com): " DOMAIN_NAME
|
||||||
|
read -p "Enter admin password (default: admin123): " ADMIN_PASSWORD
|
||||||
|
ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin123}
|
||||||
|
read -p "Use PostgreSQL instead of SQLite? (y/N): " USE_POSTGRES
|
||||||
|
USE_POSTGRES=${USE_POSTGRES:-n}
|
||||||
|
|
||||||
|
# Generate a secure secret key
|
||||||
|
SECRET_KEY=$(openssl rand -hex 24)
|
||||||
|
|
||||||
|
print_message "Beginning deployment process..."
|
||||||
|
|
||||||
|
# Update system packages
|
||||||
|
print_message "Updating system packages..."
|
||||||
|
apt update && apt upgrade -y
|
||||||
|
|
||||||
|
# Install required packages
|
||||||
|
print_message "Installing required packages..."
|
||||||
|
apt install -y python3 python3-venv python3-pip nginx wkhtmltopdf
|
||||||
|
|
||||||
|
# Setup PostgreSQL if requested
|
||||||
|
if [[ "$USE_POSTGRES" =~ ^[Yy]$ ]]; then
|
||||||
|
print_message "Setting up PostgreSQL..."
|
||||||
|
apt install -y postgresql postgresql-contrib
|
||||||
|
systemctl start postgresql
|
||||||
|
systemctl enable postgresql
|
||||||
|
|
||||||
|
# Generate a secure PostgreSQL password
|
||||||
|
PG_PASSWORD=$(openssl rand -hex 12)
|
||||||
|
|
||||||
|
# Create PostgreSQL user and database
|
||||||
|
su -c "psql -c \"CREATE DATABASE garagesale;\"" postgres
|
||||||
|
su -c "psql -c \"CREATE USER garagesaleuser WITH PASSWORD '$PG_PASSWORD';\"" postgres
|
||||||
|
su -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE garagesale TO garagesaleuser;\"" postgres
|
||||||
|
|
||||||
|
DB_URL="postgresql://garagesaleuser:$PG_PASSWORD@localhost/garagesale"
|
||||||
|
print_message "PostgreSQL setup complete."
|
||||||
|
print_warning "PostgreSQL password: $PG_PASSWORD (Please save this somewhere secure)"
|
||||||
|
else
|
||||||
|
DB_URL="sqlite:////var/www/garagesale/garage_sale.db"
|
||||||
|
print_message "Using SQLite for database."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a dedicated user for the application
|
||||||
|
print_message "Creating application user..."
|
||||||
|
useradd -m -s /bin/bash garagesale || print_warning "User already exists, continuing..."
|
||||||
|
|
||||||
|
# Set up application directory
|
||||||
|
print_message "Setting up application directory..."
|
||||||
|
mkdir -p /var/www/garagesale
|
||||||
|
cp -r $(dirname "$0")/* /var/www/garagesale/
|
||||||
|
chown -R garagesale:www-data /var/www/garagesale
|
||||||
|
chmod -R 755 /var/www/garagesale
|
||||||
|
|
||||||
|
# Create uploads directory with proper permissions
|
||||||
|
mkdir -p /var/www/garagesale/app/static/uploads
|
||||||
|
chown -R garagesale:www-data /var/www/garagesale/app/static/uploads
|
||||||
|
chmod -R 775 /var/www/garagesale/app/static/uploads
|
||||||
|
|
||||||
|
# Set up virtual environment and install dependencies
|
||||||
|
print_message "Setting up Python virtual environment and dependencies..."
|
||||||
|
cd /var/www/garagesale
|
||||||
|
su -c "python3 -m venv venv" garagesale
|
||||||
|
su -c "source venv/bin/activate && pip install -r requirements.txt && pip install gunicorn" garagesale
|
||||||
|
|
||||||
|
if [[ "$USE_POSTGRES" =~ ^[Yy]$ ]]; then
|
||||||
|
su -c "source venv/bin/activate && pip install psycopg2-binary" garagesale
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create environment file
|
||||||
|
print_message "Creating environment file..."
|
||||||
|
cat > /var/www/garagesale/.env << EOF
|
||||||
|
SECRET_KEY="$SECRET_KEY"
|
||||||
|
ADMIN_PASSWORD="$ADMIN_PASSWORD"
|
||||||
|
DATABASE_URL="$DB_URL"
|
||||||
|
EOF
|
||||||
|
chown garagesale:garagesale /var/www/garagesale/.env
|
||||||
|
chmod 600 /var/www/garagesale/.env
|
||||||
|
|
||||||
|
# Create wsgi.py file
|
||||||
|
print_message "Creating WSGI file..."
|
||||||
|
cat > /var/www/garagesale/wsgi.py << 'EOF'
|
||||||
|
from app import create_app
|
||||||
|
|
||||||
|
app = create_app()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run()
|
||||||
|
EOF
|
||||||
|
chown garagesale:garagesale /var/www/garagesale/wsgi.py
|
||||||
|
|
||||||
|
# Initialize the database
|
||||||
|
print_message "Initializing the database..."
|
||||||
|
cd /var/www/garagesale
|
||||||
|
su -c "source venv/bin/activate && python init_db.py" garagesale
|
||||||
|
|
||||||
|
# Set up Gunicorn service
|
||||||
|
print_message "Setting up Gunicorn service..."
|
||||||
|
cat > /etc/systemd/system/garagesale.service << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=Gunicorn instance to serve Hex's Garage Sale Catalog
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=garagesale
|
||||||
|
Group=www-data
|
||||||
|
WorkingDirectory=/var/www/garagesale
|
||||||
|
Environment="PATH=/var/www/garagesale/venv/bin"
|
||||||
|
EnvironmentFile=/var/www/garagesale/.env
|
||||||
|
ExecStart=/var/www/garagesale/venv/bin/gunicorn --workers 3 --bind unix:garagesale.sock -m 007 wsgi:app
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Enable and start Gunicorn service
|
||||||
|
print_message "Starting Gunicorn service..."
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl start garagesale
|
||||||
|
systemctl enable garagesale
|
||||||
|
|
||||||
|
# Set up Nginx
|
||||||
|
print_message "Setting up Nginx..."
|
||||||
|
cat > /etc/nginx/sites-available/garagesale << EOF
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name $DOMAIN_NAME;
|
||||||
|
|
||||||
|
location /static {
|
||||||
|
alias /var/www/garagesale/app/static;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://unix:/var/www/garagesale/garagesale.sock;
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Enable the Nginx site
|
||||||
|
ln -sf /etc/nginx/sites-available/garagesale /etc/nginx/sites-enabled/
|
||||||
|
nginx -t && systemctl restart nginx
|
||||||
|
|
||||||
|
print_message "Basic deployment complete!"
|
||||||
|
|
||||||
|
# Set up SSL with Let's Encrypt
|
||||||
|
read -p "Do you want to set up SSL with Let's Encrypt? (y/N): " SETUP_SSL
|
||||||
|
SETUP_SSL=${SETUP_SSL:-n}
|
||||||
|
|
||||||
|
if [[ "$SETUP_SSL" =~ ^[Yy]$ ]]; then
|
||||||
|
print_message "Setting up SSL with Let's Encrypt..."
|
||||||
|
apt install -y certbot python3-certbot-nginx
|
||||||
|
certbot --nginx -d "$DOMAIN_NAME"
|
||||||
|
print_message "SSL setup complete!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_message "Deployment completed successfully!"
|
||||||
|
print_message "You can now access your application at: http://$DOMAIN_NAME"
|
||||||
|
if [[ "$SETUP_SSL" =~ ^[Yy]$ ]]; then
|
||||||
|
print_message "Or securely at: https://$DOMAIN_NAME"
|
||||||
|
fi
|
||||||
|
print_message "Admin interface is available at: http://$DOMAIN_NAME/admin"
|
||||||
|
print_message "Admin password: $ADMIN_PASSWORD"
|
||||||
|
|
||||||
|
exit 0
|
||||||
90
update.sh
Executable file
90
update.sh
Executable file
@@ -0,0 +1,90 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Update script for Hex's Garage Sale Catalog
|
||||||
|
# This script updates an existing deployment with the latest code
|
||||||
|
|
||||||
|
set -e # Exit immediately if a command exits with a non-zero status
|
||||||
|
|
||||||
|
# Color codes for better readability
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Function to print colored messages
|
||||||
|
print_message() {
|
||||||
|
echo -e "${GREEN}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_warning() {
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$(id -u)" != "0" ]; then
|
||||||
|
print_error "This script must be run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get deployment configuration
|
||||||
|
APP_DIR=${1:-/var/www/garagesale}
|
||||||
|
BACKUP_DIR="/var/backups/garagesale/$(date +%Y%m%d_%H%M%S)"
|
||||||
|
|
||||||
|
print_message "Beginning update process..."
|
||||||
|
|
||||||
|
# Create backup directory
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
|
# Backup the current database and uploads
|
||||||
|
print_message "Creating backup..."
|
||||||
|
if [ -f "$APP_DIR/garage_sale.db" ]; then
|
||||||
|
cp "$APP_DIR/garage_sale.db" "$BACKUP_DIR/"
|
||||||
|
print_message "SQLite database backed up to $BACKUP_DIR/garage_sale.db"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backup uploads directory
|
||||||
|
if [ -d "$APP_DIR/app/static/uploads" ]; then
|
||||||
|
cp -r "$APP_DIR/app/static/uploads" "$BACKUP_DIR/"
|
||||||
|
print_message "Uploads directory backed up to $BACKUP_DIR/uploads"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy environment file
|
||||||
|
if [ -f "$APP_DIR/.env" ]; then
|
||||||
|
cp "$APP_DIR/.env" "$BACKUP_DIR/"
|
||||||
|
print_message "Environment file backed up to $BACKUP_DIR/.env"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy new code
|
||||||
|
print_message "Updating application code..."
|
||||||
|
rsync -av --exclude 'venv' --exclude '.env' --exclude 'garage_sale.db' \
|
||||||
|
--exclude 'app/static/uploads' "$(dirname "$0")/" "$APP_DIR/"
|
||||||
|
|
||||||
|
# Set correct ownership and permissions
|
||||||
|
print_message "Setting correct permissions..."
|
||||||
|
chown -R garagesale:www-data "$APP_DIR"
|
||||||
|
chmod -R 755 "$APP_DIR"
|
||||||
|
chmod -R 775 "$APP_DIR/app/static/uploads"
|
||||||
|
|
||||||
|
# Install or update dependencies
|
||||||
|
print_message "Updating Python dependencies..."
|
||||||
|
cd "$APP_DIR"
|
||||||
|
su -c "source venv/bin/activate && pip install -r requirements.txt" garagesale
|
||||||
|
|
||||||
|
# Run database migrations if needed
|
||||||
|
print_message "Running database updates..."
|
||||||
|
cd "$APP_DIR"
|
||||||
|
su -c "source venv/bin/activate && python update_database.py" garagesale
|
||||||
|
|
||||||
|
# Restart services
|
||||||
|
print_message "Restarting services..."
|
||||||
|
systemctl restart garagesale
|
||||||
|
systemctl restart nginx
|
||||||
|
|
||||||
|
print_message "Update completed successfully!"
|
||||||
|
print_message "Backup created at: $BACKUP_DIR"
|
||||||
|
print_message "If you encounter any issues, you can restore from the backup."
|
||||||
|
|
||||||
|
exit 0
|
||||||
Reference in New Issue
Block a user