Your Image Alt Text
Jazzed Technology Blog

Step-by-Step Guide to Deploying a Flask API with CloudPanel, Custom Domain, SSL, and GitHub Actions

Deploying a Flask API with CloudPanel, Custom Domain, SSL, and GitHub Actions CI/CD

This guide walks you through the process of deploying a Flask API on a CloudPanel server with a custom domain name, free SSL certificates, and automated deployments using GitHub Actions.

Prerequisites

Before you begin, you should have:

  • A CloudPanel server set up and running
  • A domain or subdomain you control
  • A GitHub repository containing your Flask application
  • Basic knowledge of Linux commands and SSH

Step 1: Create a Python Site in CloudPanel

  1. Log in to your CloudPanel dashboard
  2. Navigate to "Sites" in the left sidebar
  3. Click "Add Site"
  4. Fill in the following details:
    • Domain: your-domain.com (e.g., api.examplesite.com)
    • Select "Python" as the application type
    • Leave the port settings as default (note the port number, e.g., 8090)
  5. Click "Add" to create the site

CloudPanel will automatically set up a Python environment for your site.

Step 2: Configure DNS Records

  1. Log in to your domain registrar's dashboard
  2. Create an A record pointing your domain or subdomain to your CloudPanel server's IP address:

Type: A
Name: api (or @ for the root domain)
Value: YOUR_SERVER_IP
TTL: 3600 (or as recommended by your provider)

  1. Wait for DNS propagation (can take up to 24 hours, but usually much less)

Step 3: Create a SSH Account

  1. In CloudPanel, navigate to "Users & Permissions"
  2. Click "Add User"
  3. Create a new SSH user for your site:
    • Username: your-username (e.g., example-flask-ssh)
    • Choose appropriate permissions
  4. Save the user

Step 4: Generate and Configure SSH Keys

From your local computer:

  1. Generate a SSH key pair without a passphrase:
ssh-keygen -t ed25519 -C "github-actions" -f ./github-actions-key
  1. Add the public key to your CloudPanel SSH user:

    • In CloudPanel, go to "Users & Permissions"
    • Select your user
    • Click "Add Public Key"
    • Paste the content of github-actions-key.pub
    • Save
  2. Securely store the private key (github-actions-key) for use with GitHub Actions

Step 5: Note Site Directory

Take note of your site's directory path. In CloudPanel, Python sites typically follow this pattern:

/home/[site-name]/htdocs/[domain]

For example: /home/example-api/htdocs/api.examplesite.com

Step 6: Verify Manual Deployment

Connect to your server as the root user:

ssh root@YOUR_SERVER_IP

Navigate to your site directory and run the following commands to ensure your environment is ready:

cd /home/example-api/htdocs/api.examplesite.com

# Create a virtual environment
python3.12 -m venv venv

# Activate the virtual environment
source venv/bin/activate

# Install required packages
pip install flask waitress

Create a simple Flask application to test:

cat > app.py << 'EOL'
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/')
def home():
    return jsonify({"status": "success", "message": "API is running"})

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8090)
EOL

Create a startup script for Waitress:

cat > start_app.py << 'EOL'
from waitress import serve
from app import app

if __name__ == "__main__":
    serve(app, host="0.0.0.0", port=8090, threads=4)
EOL

Create a requirements file:

cat > requirements.txt << 'EOL'
flask
waitress
EOL

Step 7: Configure Proper Permissions

Set appropriate permissions for your SSH user:

# Replace these with your actual SSH username and site directory
SSH_USER="example-flask-ssh"
SITE_DIR="/home/example-api/htdocs/api.examplesite.com"

# Change ownership
sudo chown -R $SSH_USER:$SSH_USER $SITE_DIR

# Set permissions
sudo chmod -R u+rwX $SITE_DIR

Step 8: Set Up GitHub Actions

  1. In your Flask application repository, create a .github/workflows directory:
mkdir -p .github/workflows
  1. Create a deploy.yml file in this directory:
name: Deploy Flask App

on:
  push:
    branches: [ main, master ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Code
        uses: actions/checkout@v3

      - name: Copy Files to Server
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ vars.HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          source: "app.py,requirements.txt,start_app.py"
          target: "/tmp/deployment_temp"
          strip_components: 0

      - name: Deploy and Run Application
        uses: appleboy/ssh-action@master
        with:
          host: ${{ vars.HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            # Set up variables
            APP_DIR=${{ vars.DIRECTORY }}
            
            echo "๐Ÿ”„ Starting deployment process..."
            
            # Stop any existing PM2 processes for this app
            pm2 delete audit 2>/dev/null || echo "No existing PM2 process to delete"
            
            # Ensure target directory exists
            mkdir -p $APP_DIR
            
            # Move new files to target directory
            echo "๐Ÿ”„ Updating application files..."
            cp /tmp/deployment_temp/app.py $APP_DIR/app.py
            cp /tmp/deployment_temp/requirements.txt $APP_DIR/requirements.txt
            cp /tmp/deployment_temp/start_app.py $APP_DIR/start_app.py
            
            # Prepare Python environment
            echo "๐Ÿ“ฆ Setting up Python environment..."
            cd $APP_DIR
            
            # Determine Python version
            PYTHON_CMD=$(command -v python3.12 || command -v python3.11 || command -v python3.10 || command -v python3.9 || command -v python3)
            echo "Using Python: $PYTHON_CMD"
            
            # Create venv if it doesn't exist
            if [ ! -d "venv" ]; then
              echo "Creating new virtual environment..."
              $PYTHON_CMD -m venv venv || {
                echo "Failed to create venv, installing dependencies..."
                sudo apt-get update
                sudo apt-get install -y python3-venv python3-full
                $PYTHON_CMD -m venv venv
              }
            fi
            
            # Install dependencies
            echo "Installing Python dependencies..."
            ./venv/bin/pip install -r requirements.txt
            
            # Start the application with PM2
            echo "๐Ÿš€ Starting Flask app with PM2..."
            cd $APP_DIR
            pm2 start --name audit --interpreter ./venv/bin/python start_app.py
            
            # Save PM2 configuration to persist across reboots
            pm2 save
            
            # Check if the app is running
            echo "๐Ÿ“Š PM2 status:"
            pm2 list
            
            # Test the application
            echo "๐Ÿ” Testing the application endpoint..."
            curl -I http://127.0.0.1:8090 || echo "โŒ Curl failed, application may not be running correctly"
            
            # Clean up
            echo "๐Ÿงน Cleaning up temporary files..."
            rm -rf /tmp/deployment_temp
            
            echo "โœ… Deployment completed!"

Step 9: Configure GitHub Secrets and Variables

  1. In your GitHub repository, go to "Settings" > "Secrets and variables" > "Actions"

  2. Add the following secrets:

    • SSH_USERNAME: Your SSH username (e.g., example-flask-ssh)
    • SSH_PRIVATE_KEY: The content of your private key file (github-actions-key)
  3. Add the following variables:

    • HOST: Your server IP address
    • DIRECTORY: The path to your site directory (e.g., /home/example-api/htdocs/api.examplesite.com)

Step 10: Test the CI/CD Pipeline

  1. Make sure your repository contains at least these files:

    • app.py: Your Flask application
    • requirements.txt: List of dependencies
    • start_app.py: Script to start your application with Waitress
    • .github/workflows/deploy.yml: GitHub Actions workflow file
  2. Push a change to your main or master branch:

git add .
git commit -m "Set up CI/CD pipeline"
git push origin main
  1. Go to the "Actions" tab in your GitHub repository to monitor the workflow execution

  2. Once completed, visit your domain (e.g., https://api.examplesite.com) to verify the deployment

Monitoring and Troubleshooting

PM2 Commands

After deployment, you can SSH into your server and use these PM2 commands:

# List all applications
pm2 list

# View detailed information
pm2 show audit

# View logs
pm2 logs audit

# Restart application
pm2 restart audit

# Stop application
pm2 stop audit

# Set up PM2 to start on system boot (run once)
pm2 startup
# Then follow the instructions displayed

# Save current process list (run after updating processes)
pm2 save

SSL Configuration

CloudPanel automatically configures Let's Encrypt SSL certificates for your domain. You can check the SSL status in the CloudPanel dashboard under:

  1. Sites > Your Site
  2. Click on the site name
  3. Navigate to the "SSL/TLS" tab

If SSL isn't automatically configured, you can request a certificate through the CloudPanel interface.

Troubleshooting Common Issues

  1. Application not accessible:

    • Check if PM2 is running: pm2 list
    • Verify the port number in your code matches the one assigned by CloudPanel
    • Check firewall rules: sudo ufw status
  2. GitHub Actions failing:

    • Check the SSH keys are correctly set up
    • Verify permissions on the site directory
    • Review logs in the GitHub Actions tab
  3. SSL certificate issues:

    • Ensure DNS records are properly configured
    • Wait for DNS propagation
    • Try manually requesting a certificate in CloudPanel

This completes the documentation for deploying a Flask API on CloudPanel with a custom domain, free SSL, and automated CI/CD using GitHub Actions. The system uses PM2 as the process manager for reliable application hosting and automatic restarts if needed. If you need any assistance with such automated deployments, feel free to reach out to Jazzed Technology, the most well-established and responsive web development company in Surrey, BC, and serving all of Lower Mainland.

Toggle Theme:

Our mission is to deliver high-quality web design, SEO, and IT support services in Vancouver, tailored to the unique needs of our clients. We aim to be your trusted partner, providing exceptional customer service that exceeds your expectations.

ยฉ 2023 Jazzed Technology | Vancouver Web Design, SEO & IT Support Company. All rights reserved.