Deployment
CI/CD pipeline
Code Quality
ESLint for frontend
Black/Pylint for backend
TypeScript compilation
Deployment
Automatic Vercel deployment
Docker image building
Environment configuration
Frontend Deployment (Vercel)
Configuration:
// vercel.json
{
"functions": {
"app/api/ask/route.ts": {
"maxDuration": 60
}
},
"headers": [
{
"source": "/api/ask",
"headers": [
{
"key": "Cache-Control",
"value": "no-cache, no-store, must-revalidate, proxy-revalidate"
}
]
}
]
}Environment Variables:
· `NEXT_PUBLIC_SUPABASE_URL`
· `NEXT_PUBLIC_SUPABASE_ANON_KEY`
· `NEXT_PUBLIC_EXTERNAL_API_URL`
Backend Deployment (Docker + EC2)
Dockerfile:
FROM python:3.13.3-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "run.py"]Environment Variables:
· `OPENAI_API_KEY`
· `BIGQUERY_PROJECT_ID`
· `BIGQUERY_DATASET`
· `SUPABASE_URL`
· `SUPABASE_SERVICE_ROLE_KEY`
· `SENTRY_DSN`
· `LANGCHAIN_API_KEY`
Database Setup
Supabase Setup
Run `complete-database-setup.sql`
Configure RLS policies
Set up authentication
BigQuery Setup
Create service account
Configure dataset permissions
Upload data
Step 1: Environment Setup
This step covers the complete setup of the EC2 server environment where the usheru development backend application is deployed.
Step 1.1: Connect the server and Install Required Packages
sudo apt update
sudo apt install -y git docker.io
sudo systemctl enable dockerStep 1.2: Clone the Application Repository
cd /home/ubuntu
git clone <repository-url> usheru-distributionAI-BE
Create Deployment Directory
A dedicated directory for deployment scripts:
mkdir /home/ubuntu/usheru-devCreate Deployment Script
File path:
/home/ubuntu/usheru-dev/deploy-dev.sh
Content:
#!/bin/bash
cd /home/ubuntu/usheru-distributionAI-BE || exit 1
git fetch origin
git reset --hard origin/develop
echo "Building Docker image..."
sudo docker build -t usheru-dev .
echo "Stopping old container..."
sudo docker kill usheru-dev 2>/dev/null || true
sudo docker rm usheru-dev 2>/dev/null || true
echo "Starting new container..."
sudo docker run -d --name usheru-dev -p 8001:8000 --restart always \
-v /home/ubuntu/usheru-dev/service_account.json:/app/service_account.json:ro \
usheru-dev:latest
echo "Cleaning up old images..."
sudo docker image prune -f
echo "Deployment complete!"Make it executable:
chmod +x /home/ubuntu/usheru-dev/deploy-dev.shStep 2 – CI/CD Setup (GitHub Actions)
This step configures automatic deployment through GitHub Actions whenever code is pushed to the develop branch.
Step 2.1: Configure GitHub Secrets
In the GitHub repository: Settings → Secrets and Variables → ActionsThese secrets are used securely inside the pipeline.
AWS_INSTANCE_SG_ID = EC2 Security Group ID for SSH whitelisting
SSH_PRIVATE_KEY= Private SSH key to connect to the EC2 server
SSH_SERVER_IP = Public IP of the EC2 instance
DEV_ENV_FILE = Contents of the .env file used by the application
Step 2.2: Create CI/CD Workflow
File path:
.github/workflows/deploy-develop.ymlPurpose:
Automatically deploy the latest code from the develop branch to the EC2 server.Main Workflow Steps:
# ===========================================
# GitHub Actions Workflow
# Build and Deploy to Dev Environment (develop branch)
# ===========================================
name: Build and Deploy to develop
on:
push:
branches:
- develop # Trigger this workflow when code is pushed to 'develop' branch
jobs:
build_and_deploy:
name: Build and Deploy to Dev
runs-on: ubuntu-latest # Use the latest Ubuntu runner for CI/CD
steps:
# Step 1: Checkout code from the GitHub repository
- name: Checkout code
uses: actions/checkout@v2
# Step 2: Configure AWS credentials using secrets
# Allows this runner to run AWS CLI commands (like whitelist/revoke)
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1 # Region where EC2 security group exists
# Step 3: Get the GitHub runner's public IP (used for temporary SSH access)
- name: Get runner IP address
id: ip
uses: haythem/public-ip@v1.2
# Step 4: Whitelist the runner IP in EC2 security group for SSH (port 22)
# This allows the GitHub runner to SSH into the EC2 instance temporarily
- name: Whitelist runner IP address
run: |
aws ec2 authorize-security-group-ingress \
--group-id $AWS_INSTANCE_SG_ID \
--protocol tcp \
--port 22 \
--cidr ${{ steps.ip.outputs.ipv4 }}/32
env:
AWS_INSTANCE_SG_ID: ${{ secrets.AWS_INSTANCE_SG_ID }}
# Step 5: Create .env file from the GitHub secret
# This secret contains all environment variables for the app
- name: Write .env from secret
run: |
cat <<'EOF' > .env
${{ secrets.DEV_ENV_FILE }}
EOF
# Step 6: Upload the .env file to the EC2 server via SCP
# The file will be placed inside the backend code directory
- name: Upload .env to server
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.SSH_SERVER_IP }} >> ~/.ssh/known_hosts
scp -o StrictHostKeyChecking=no .env ubuntu@${{ secrets.SSH_SERVER_IP }}:/home/ubuntu/usheru-distributionAI-BE/.env
# Step 7: Setup SSH connection configuration
# Prepares the SSH key and known_hosts for secure access
- name: Set up SSH
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.SSH_SERVER_IP }} >> ~/.ssh/known_hosts
# Step 8: Deploy code to EC2 by executing the deploy-dev.sh script
# This script handles Docker build, container restart, and cleanup
- name: Deploy to dev server
run: |
echo "Connecting to SSH server ubuntu@${{ secrets.SSH_SERVER_IP }}"
ssh -o StrictHostKeyChecking=no "ubuntu@${{ secrets.SSH_SERVER_IP }}" << 'EOF'
if [ -f /home/ubuntu/usheru-dev/deploy-dev.sh ]; then
chmod +x /home/ubuntu/usheru-dev/deploy-dev.sh &&
/usr/bin/bash /home/ubuntu/usheru-dev/deploy-dev.sh;
else
echo 'deploy-dev.sh not found';
exit 1;
fi
EOF
# Step 9: Revoke the runner IP from EC2 SG after deployment
# This step ensures the SSH access is closed after pipeline completion
- name: Revoke runner IP address
if: always() # Run even if previous steps fail
run: |
aws ec2 revoke-security-group-ingress \
--group-id $AWS_INSTANCE_SG_ID \
--protocol tcp \
--port 22 \
--cidr ${{ steps.ip.outputs.ipv4 }}/32
env:
AWS_INSTANCE_SG_ID: ${{ secrets.AWS_INSTANCE_SG_ID }}
CRON JOB CONFIGURATION DOCUMENTATION
Overview
Cron jobs are scheduled automated tasks configured on the server to run specific scripts at defined times.
In this setup, cron is used to trigger Python scripts running inside a Docker container (usheru-dev) that performs background operations like token refills and weekly report generation.
Location
All cron jobs are configured under the root user’s crontab.
You can view or edit the cron jobs using:
sudo crontab -eTo check the existing jobs:
sudo crontab -lCron Jobs Defined
Token Refill Job
0 0 * * * docker exec usheru-dev bash -c "cd /app/supabase_utils && python cron_token_refill.py" >> /home/ubuntu/cron-logs/cron_token_refill.log 2>&1Description:
This cron runs the cron_token_refill.py script inside the Docker container usheru-dev.
The script is located at /app/supabase_utils/ inside the container.
It executes every day at 12:00 AM (UTC).
The output (including any errors) is saved to:
/home/ubuntu/cron-logs/cron_token_refill.log
Purpose:
This script automatically refills authentication tokens or keys required by the system to maintain uninterrupted access to third-party services or APIs.
Weekly Insight Generation Job
0 8 * * 5 docker exec usheru-dev bash -c "python insight_generate_weekly.py >> /home/ubuntu/cron-logs/insight_generate_weekly.log 2>&1"Description:
Runs the insight_generate_weekly.py script inside the same Docker container (usheru-dev).
Executes every Friday at 08:00 AM (UTC).
Output and error logs are saved to:
/home/ubuntu/cron-logs/insight_generate_weekly.log
Purpose:
This script generates weekly insight reports or analytics summaries, ensuring that up-to-date insights are automatically available each week without manual execution.
Log Files
Each cron job redirects its output and error messages to dedicated log files located at:
/home/ubuntu/cron-logs/
This ensures you can easily review the execution history and troubleshoot if needed.
Example:
cat /home/ubuntu/cron-logs/cron_token_refill.log
cat /home/ubuntu/cron-logs/insight_generate_weekly.logLocal Development
Frontend Setup
cd usheru-distributionAI-FE
npm install
cp .env.example .env.local
npm run dev
Backend Setup
cd usheru-sql-agent
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
python run.py
Step 1: Download code from github
git clone git@github.com:UsheruHQ/usheru-distributionAI-BE.git
Step 2:Install python 3.13
Windows → Python Releases for Windows

MacOs → Python Releases for macOS

Linux(Debia/Ubuntu) →
Step 1:
sudo apt update && sudo apt install -y \
build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev \
libffi-dev liblzma-devStep2:
curl https://pyenv.run | bashStep3 : Add this to ~/.bashrc or ~/.zshrc:
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init -)"Step4: Install phytho 3.13
pyenv install 3.13.0
pyenv global 3.13.0
Step 3:Install Depencencies via .venv
1) create the environment
python3 -m venv .venv2) activate the environment (zsh/bash)
source .venv/bin/activate3) update basic tools
python -m pip install --upgrade pip setuptools wheel4) install dependencies
pip install -r requirements.txt
Step 4: Setup BigQuery Service Account
Get your service account JSON file:
Go to [Google Cloud Console]
Navigate to IAM & Admin > Service Accounts
Create or select a service account with BigQuery permissions
Click Keys > Add Key > Create New Key
Choose JSON format and download
Rename the file to service_account.json
Place it in the project root directory (same folder as this README)
Step 5:Configure Environment
Create .env file in the project root directory and ask about some key values
GOOGLE_APPLICATION_CREDENTIALS=./service-account.json
LANGSMITH_TRACING=TRUE
LANGSMITH_ENDPOINT=
LANGSMITH_API_KEY=
LANGSMITH_PROJECT=
OPENAI_API_KEY=
BIGQUERY_PROJECT_ID=
BIGQUERY_DATASET=
LLM_MODEL=gpt-4o-mini
LLM_PROVIDER=openai
LLM_TEMPERATURE=0
MAX_BYTES_BILLED=100000000000
QUERY_TIMEOUT=90
ANTHROPIC_API_KEY=
GOOGLE_API_KEY=
SUPABASE_SERVICE_ROLE_KEY=
SUPABASE_URL=
SUPABASE_ANON_KEY=
SENTRY_DSN=
SENTRY_ENVIRONMENT=development
SENTRY_RELEASE=1.0.0
SENTRY_DEBUG=FALSE
SENTRY_TRACES_SAMPLE_RATE=0.1
SENTRY_PROFILES_SAMPLE_RATE=0.1
Step 6:Run the Agent
python run.py