385 lines
14 KiB
Bash
385 lines
14 KiB
Bash
#!/bin/bash
|
|
|
|
# NextGen PDF Installation Script for PDF Renamer Flask App
|
|
# This script sets up the PDF renamer application with reverse proxy on Ubuntu
|
|
# Domain: nextgenpdf.trbc.org
|
|
|
|
set -e
|
|
|
|
echo "Starting installation of PDF Renamer Flask App..."
|
|
|
|
# Interactive configuration
|
|
echo ""
|
|
echo "=== PDF Renamer Configuration ==="
|
|
echo ""
|
|
|
|
# Get domain name
|
|
read -p "Enter the domain name for this installation (e.g., nextgenpdf.trbc.org): " DOMAIN_NAME
|
|
if [ -z "$DOMAIN_NAME" ]; then
|
|
echo "ERROR: Domain name is required"
|
|
exit 1
|
|
fi
|
|
|
|
# Get Microsoft Entra ID configuration
|
|
echo ""
|
|
echo "=== Microsoft Entra ID Configuration ==="
|
|
echo "If you don't have these values yet, you can get them after installation."
|
|
echo "Leave blank to configure later."
|
|
echo ""
|
|
|
|
read -p "Microsoft Entra Tenant ID (optional): " TENANT_ID
|
|
read -p "Microsoft Entra Client ID (optional): " CLIENT_ID
|
|
read -p "Microsoft Entra Client Secret (optional): " CLIENT_SECRET
|
|
|
|
# Get admin credentials
|
|
echo ""
|
|
echo "=== Admin Login Configuration ==="
|
|
read -p "Admin username (default: trbcit): " ADMIN_USER
|
|
ADMIN_USER=${ADMIN_USER:-trbcit}
|
|
|
|
read -s -p "Admin password (default: atdrmbicn): " ADMIN_PASS
|
|
echo ""
|
|
ADMIN_PASS=${ADMIN_PASS:-atdrmbicn}
|
|
|
|
echo ""
|
|
echo "Configuration complete!"
|
|
echo "Domain: $DOMAIN_NAME"
|
|
echo "Admin User: $ADMIN_USER"
|
|
echo ""
|
|
|
|
# Check if already installed
|
|
if systemctl is-active --quiet pdf-renamer 2>/dev/null; then
|
|
echo "WARNING: PDF Renamer service is already running."
|
|
echo "This will reinstall/update the application."
|
|
echo "Press Ctrl+C to cancel or Enter to continue..."
|
|
read -r || exit 1
|
|
fi
|
|
|
|
# Check if running with sudo
|
|
if [ "$EUID" -ne 0 ]; then
|
|
echo "ERROR: This script must be run with sudo privileges"
|
|
echo "Usage: sudo ./ubuntu-install.sh"
|
|
exit 1
|
|
fi
|
|
|
|
# Update system packages
|
|
echo "Updating system packages..."
|
|
sudo apt update && sudo apt upgrade -y
|
|
|
|
# Install required packages
|
|
echo "Installing required packages..."
|
|
sudo apt install -y python3 python3-pip python3-venv nginx git
|
|
|
|
# Clone the repository (replace with your actual repo URL if different)
|
|
echo "Cloning the repository..."
|
|
# Check if we're already in the repository directory
|
|
if [ -d ".git" ]; then
|
|
echo "Already in repository directory, skipping clone..."
|
|
else
|
|
# Try HTTPS first, fallback to SSH if available
|
|
if git clone https://gitlab.com/trbc-dev/pdf-rename-sort.git 2>/dev/null; then
|
|
echo "Cloned via HTTPS"
|
|
cd pdf-rename-sort
|
|
elif git clone git@gitlab.com:trbc-dev/pdf-rename-sort.git 2>/dev/null; then
|
|
echo "Cloned via SSH"
|
|
cd pdf-rename-sort
|
|
else
|
|
echo "ERROR: Could not clone repository. Please check:"
|
|
echo "1. Repository URL is correct"
|
|
echo "2. SSH keys are configured (for SSH clone)"
|
|
echo "3. Internet connection is working"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Create virtual environment and install dependencies
|
|
echo "Setting up Python virtual environment..."
|
|
python3 -m venv venv
|
|
source venv/bin/activate
|
|
pip install --upgrade pip
|
|
pip install -r requirements.txt
|
|
pip install gunicorn
|
|
|
|
# Create application directory structure
|
|
echo "Setting up application directory..."
|
|
mkdir -p static
|
|
mkdir -p processed # Ensure processed directory exists
|
|
# Copy logo if it exists in repo, otherwise you'll need to add it
|
|
# cp path/to/trbc-logo-full.png static/ # Uncomment and adjust if needed
|
|
|
|
# Get the actual user who invoked sudo (not root)
|
|
if [ -n "$SUDO_USER" ]; then
|
|
CURRENT_USER=$SUDO_USER
|
|
elif [ -n "$LOGNAME" ] && [ "$LOGNAME" != "root" ]; then
|
|
CURRENT_USER=$LOGNAME
|
|
else
|
|
CURRENT_USER=ubuntu
|
|
fi
|
|
|
|
echo "Installing for user: $CURRENT_USER"
|
|
|
|
# Create systemd service file
|
|
echo "Creating systemd service..."
|
|
sudo tee /etc/systemd/system/pdf-renamer.service > /dev/null <<EOF
|
|
[Unit]
|
|
Description=PDF Renamer Flask App
|
|
After=network.target
|
|
|
|
[Service]
|
|
User=$CURRENT_USER
|
|
WorkingDirectory=/home/$CURRENT_USER/pdf-rename-sort
|
|
Environment="PATH=/home/$CURRENT_USER/pdf-rename-sort/venv/bin"
|
|
Environment="SECRET_KEY=CHANGE_THIS_SECRET_KEY_IN_PRODUCTION"
|
|
$(if [ -n "$TENANT_ID" ] && [ "$TENANT_ID" != "YOUR_MICROSOFT_ENTRA_TENANT_ID" ]; then echo "Environment=\"TENANT_ID=$TENANT_ID\""; fi)
|
|
$(if [ -n "$CLIENT_ID" ] && [ "$CLIENT_ID" != "YOUR_MICROSOFT_ENTRA_CLIENT_ID" ]; then echo "Environment=\"CLIENT_ID=$CLIENT_ID\""; fi)
|
|
$(if [ -n "$CLIENT_SECRET" ] && [ "$CLIENT_SECRET" != "YOUR_MICROSOFT_ENTRA_CLIENT_SECRET" ]; then echo "Environment=\"CLIENT_SECRET=$CLIENT_SECRET\""; fi)
|
|
Environment="ADMIN_USERNAME=$ADMIN_USER"
|
|
Environment="ADMIN_PASSWORD=$ADMIN_PASS"
|
|
ExecStart=/home/$CURRENT_USER/pdf-rename-sort/venv/bin/gunicorn --bind 127.0.0.1:3000 pdf_renamer:app
|
|
Restart=always
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
# Set proper permissions for web application
|
|
echo "Setting proper permissions for web application..."
|
|
sudo chown -R $CURRENT_USER:$CURRENT_USER /home/$CURRENT_USER/pdf-rename-sort
|
|
|
|
# Make static files accessible to nginx (and other users if needed)
|
|
sudo chmod -R 755 /home/$CURRENT_USER/pdf-rename-sort/static
|
|
sudo chmod -R 755 /home/$CURRENT_USER/pdf-rename-sort/processed
|
|
|
|
# Ensure the processed directory exists and is accessible
|
|
sudo mkdir -p /home/$CURRENT_USER/pdf-rename-sort/processed
|
|
sudo chown -R $CURRENT_USER:$CURRENT_USER /home/$CURRENT_USER/pdf-rename-sort/processed
|
|
sudo chmod -R 755 /home/$CURRENT_USER/pdf-rename-sort/processed
|
|
|
|
# Enable and start the service
|
|
echo "Starting the application service..."
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable pdf-renamer
|
|
sudo systemctl start pdf-renamer
|
|
|
|
# Configure Nginx reverse proxy for PDF Renamer (multi-domain setup)
|
|
echo "Configuring Nginx reverse proxy for PDF Renamer..."
|
|
sudo tee /etc/nginx/sites-available/pdf-renamer > /dev/null <<EOF
|
|
server {
|
|
listen 80;
|
|
server_name $DOMAIN_NAME; # Configured domain
|
|
|
|
# Handle large file uploads (500MB)
|
|
client_max_body_size 500M;
|
|
|
|
# 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;
|
|
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
|
|
|
|
# Handle static files
|
|
location /static {
|
|
alias /home/$CURRENT_USER/pdf-rename-sort/static;
|
|
expires 1y;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
|
|
# Proxy to Flask app on port 3000
|
|
location / {
|
|
proxy_pass http://127.0.0.1:3000;
|
|
proxy_set_header Host \$host;
|
|
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;
|
|
|
|
# WebSocket support (if needed in future)
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade \$http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
# Timeout settings for large files
|
|
proxy_connect_timeout 60s;
|
|
proxy_send_timeout 300s; # Increased for large uploads
|
|
proxy_read_timeout 300s; # Increased for large uploads
|
|
}
|
|
|
|
# Gzip compression
|
|
gzip on;
|
|
gzip_vary on;
|
|
gzip_min_length 1024;
|
|
gzip_proxied expired no-cache no-store private auth;
|
|
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss;
|
|
}
|
|
EOF
|
|
|
|
# Enable the PDF Renamer site (doesn't remove existing sites)
|
|
sudo ln -s /etc/nginx/sites-available/pdf-renamer /etc/nginx/sites-enabled/ 2>/dev/null || true
|
|
|
|
# Don't remove default nginx site - let existing apps continue working
|
|
# sudo rm -f /etc/nginx/sites-enabled/default
|
|
|
|
# Test nginx configuration
|
|
echo "Testing Nginx configuration..."
|
|
sudo nginx -t
|
|
|
|
# Reload nginx
|
|
echo "Reloading Nginx..."
|
|
sudo systemctl reload nginx
|
|
|
|
# Install SSL certificate with Let's Encrypt
|
|
echo "Installing SSL certificate with Let's Encrypt..."
|
|
sudo apt install -y certbot python3-certbot-nginx
|
|
|
|
# Try Let's Encrypt first, fall back to self-signed if it fails
|
|
if sudo certbot --nginx -d $DOMAIN_NAME --non-interactive --agree-tos --email admin@$DOMAIN_NAME 2>/dev/null; then
|
|
echo "✅ Let's Encrypt certificate installed successfully"
|
|
else
|
|
echo "⚠️ Let's Encrypt failed (DNS not configured?), creating self-signed certificate..."
|
|
|
|
# Create self-signed certificate
|
|
sudo mkdir -p /etc/ssl/private
|
|
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
|
-keyout /etc/ssl/private/$DOMAIN_NAME.key \
|
|
-out /etc/ssl/certs/$DOMAIN_NAME.crt \
|
|
-subj "/C=US/ST=State/L=City/O=Organization/CN=$DOMAIN_NAME"
|
|
|
|
# Update Nginx configuration to use self-signed certificate
|
|
sudo tee /etc/nginx/sites-available/pdf-renamer > /dev/null <<EOF
|
|
server {
|
|
listen 80;
|
|
server_name $DOMAIN_NAME;
|
|
|
|
# Redirect HTTP to HTTPS
|
|
return 301 https://\$server_name\$request_uri;
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name $DOMAIN_NAME;
|
|
|
|
# Self-signed SSL certificate
|
|
ssl_certificate /etc/ssl/certs/$DOMAIN_NAME.crt;
|
|
ssl_certificate_key /etc/ssl/private/$DOMAIN_NAME.key;
|
|
|
|
# SSL settings
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
ssl_prefer_server_ciphers on;
|
|
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
|
|
|
|
# Handle large file uploads (500MB)
|
|
client_max_body_size 500M;
|
|
|
|
# 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;
|
|
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
|
|
|
|
# Handle static files
|
|
location /static {
|
|
alias /home/$CURRENT_USER/pdf-rename-sort/static;
|
|
expires 1y;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
|
|
# Proxy to Flask app on port 3000
|
|
location / {
|
|
proxy_pass http://127.0.0.1:3000;
|
|
proxy_set_header Host \$host;
|
|
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;
|
|
|
|
# WebSocket support (if needed in future)
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade \$http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
# Timeout settings for large files
|
|
proxy_connect_timeout 60s;
|
|
proxy_send_timeout 300s;
|
|
proxy_read_timeout 300s;
|
|
}
|
|
|
|
# Gzip compression
|
|
gzip on;
|
|
gzip_vary on;
|
|
gzip_min_length 1024;
|
|
gzip_proxied expired no-cache no-store private auth;
|
|
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss;
|
|
}
|
|
EOF
|
|
|
|
# Reload Nginx with new configuration
|
|
sudo systemctl reload nginx
|
|
|
|
echo "⚠️ Self-signed certificate created. You'll see browser warnings."
|
|
echo " To get a trusted certificate, configure DNS and run:"
|
|
echo " sudo certbot --nginx -d $DOMAIN_NAME"
|
|
fi
|
|
|
|
# Configure firewall (UFW)
|
|
echo "Configuring firewall..."
|
|
sudo ufw allow ssh
|
|
sudo ufw allow 'Nginx Full'
|
|
sudo ufw --force enable
|
|
|
|
echo ""
|
|
echo "Installation completed successfully!"
|
|
echo ""
|
|
echo "IMPORTANT: Configure Microsoft Entra ID authentication:"
|
|
echo "1. Go to Azure Portal > Microsoft Entra ID > App registrations"
|
|
echo "2. Create a new registration or use existing one"
|
|
echo "3. Note the Application (client) ID and Directory (tenant) ID"
|
|
echo "4. Add a client secret under Certificates & secrets"
|
|
echo "5. Add redirect URI: https://$DOMAIN_NAME/auth/microsoft/callback"
|
|
echo "6. Grant appropriate permissions if needed"
|
|
echo ""
|
|
echo "If you provided Entra credentials during installation:"
|
|
echo " - The service has been configured automatically"
|
|
echo " - Skip to step 6 below"
|
|
echo ""
|
|
echo "If you left Entra credentials blank during installation:"
|
|
echo " - Edit the service file: sudo nano /etc/systemd/system/pdf-renamer.service"
|
|
echo " - Add the following lines (replace with your actual values):"
|
|
echo " Environment=\"TENANT_ID=your-tenant-id\""
|
|
echo " Environment=\"CLIENT_ID=your-client-id\""
|
|
echo " Environment=\"CLIENT_SECRET=your-client-secret\""
|
|
echo " - Save and run: sudo systemctl daemon-reload && sudo systemctl restart pdf-renamer"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo "1. Update the environment variables in /etc/systemd/system/pdf-renamer.service:"
|
|
echo " - SECRET_KEY: Set a secure random key (use: openssl rand -hex 32)"
|
|
echo " - TENANT_ID: Your Microsoft Entra tenant ID"
|
|
echo " - CLIENT_ID: Your Microsoft Entra application ID"
|
|
echo " - CLIENT_SECRET: Your Microsoft Entra client secret"
|
|
echo " - ADMIN_USERNAME and ADMIN_PASSWORD: Set secure admin credentials"
|
|
echo ""
|
|
echo "2. Update the server_name in /etc/nginx/sites-available/pdf-renamer:"
|
|
echo " - Change 'pdf-renamer.your-domain.com' to '$DOMAIN_NAME'"
|
|
echo " - Point your DNS for $DOMAIN_NAME to this server's IP"
|
|
echo ""
|
|
echo "3. SSL certificate has been installed"
|
|
echo " - If Let's Encrypt succeeded: Certificate is trusted"
|
|
echo " - If self-signed: You'll see browser warnings (this is normal)"
|
|
echo " - To upgrade to Let's Encrypt after DNS is configured:"
|
|
echo " sudo certbot --nginx -d $DOMAIN_NAME"
|
|
echo "4. Reload systemd after updating environment variables:"
|
|
echo " sudo systemctl daemon-reload"
|
|
echo " sudo systemctl restart pdf-renamer"
|
|
echo ""
|
|
echo "5. Check service status:"
|
|
echo " sudo systemctl status pdf-renamer"
|
|
echo " sudo systemctl status nginx"
|
|
echo ""
|
|
echo "6. Test OAuth configuration:"
|
|
echo " cd /home/$CURRENT_USER/pdf-rename-sort"
|
|
echo " source venv/bin/activate"
|
|
echo " python3 test_oauth_config.py # This checks systemd service environment variables"
|
|
echo ""
|
|
echo "NOTE: This setup runs alongside your existing app on port 5000."
|
|
echo "The PDF Renamer will be accessible at https://$DOMAIN_NAME."
|
|
echo "File permissions have been set for web access (755 for directories)."
|
|
echo "Installed for user: $CURRENT_USER" |