✅ Server-Tailored Deployment Guide

CSR2MODS V2

Deployment steps adapted to this server's exact stack — no wasted installs.

🐍 Python 3.12.3 ⚛️ Node.js 22.21.1 🗄️ PostgreSQL 16.13 ⚡ Redis ✓ running 🌐 OpenLiteSpeed only 👷 2 uvicorn workers
OS
Ubuntu 24.04 LTS
Kernel 6.8.0-106
RAM
15 GB
~10 GB available
CPU
4 vCPUs
→ workers: 2
Disk
193 GB
85 GB used (45%)
Web Server
OpenLiteSpeed
No Nginx → Option A
PostgreSQL
16.13
Running ✓
Redis
Running
PONG ✓
Python
3.12.3
3.11 not installed
🔄

What Changed From the Original Guide

Stack adjusted to match what's actually on this server.
ComponentGuide SaidThis ServerAction
Python 3.11 3.12.3 ADJUSTED Use python3.12 -m venv — no install needed
PostgreSQL 15 16.13 ✓ RUNNING Skip install — use existing PG16
Redis Install if missing Running ✓ PONG Skip install — already live
Node.js 20 22.21.1 ✓ INSTALLED Skip install — v22 is compatible
Web server OLS or Nginx OLS only → Option A Use CyberPanel Reverse Proxy UI
Uvicorn workers 1 or 2 4 CPUs, 15 GB RAM → 2 workers --workers 2
DATABASE_URL postgresql+asyncpg://...5432/csr2mods Same format PG16 No URL change needed — asyncpg works with PG16

1

What You Can Skip (Already Installed)

Nothing to install for Python, Node.js, PostgreSQL, or Redis — all present and running.

All runtimes already present
Python 3.12.3 · Node.js 22.21.1 · PostgreSQL 16.13 (active) · Redis (active, PONG) · Git 2.43.0 — skip the entire "Install Dependencies" step from the original guide.
⚠️
PostgreSQL 16, not 15
The original guide says PG15 — this server has PG16. The asyncpg driver and Alembic work fine with PG16. No changes to your app code are needed, but do not run apt install postgresql-15.

You may need these system libs for Python packages that compile C extensions:

bash — only if pip install fails
apt install -y libpq-dev build-essential python3.12-dev python3.12-venv
2

Set Up PostgreSQL Database + Redis

PostgreSQL 16 and Redis are running. Create the csr2mods user + database using the repo script.

bash
# Run the repo's DB setup script — targets the local PG16 instance
DB_PASSWORD="CHOOSE_A_STRONG_PASSWORD" bash /path/to/repo/backend/scripts/setup_db.sh

# Verify the DB was created:
sudo -u postgres psql -c "\l" | grep csr2

# Redis is already configured and running — nothing to do:
redis-cli ping   # should return: PONG
ℹ️
PG16 socket path
If setup_db.sh uses a hardcoded socket path for PG15 (/var/run/postgresql/15-main), edit it to /var/run/postgresql or just connect via localhost.
3

Clone the Repository

Repo not yet present on the server. Clone it under the domain home.

bash
cd /home/store.csr2racer.com
git clone https://github.com/YOUR_USERNAME/csr2-store-clone.git
cd csr2-store-clone
4

Python 3.12 Virtualenv CHANGED

Use python3.12 — Python 3.11 is not installed and we're not installing it.

bash
cd /home/store.csr2racer.com/csr2-store-clone/backend

# Use python3.12 (NOT python3.11 — it's not installed)
python3.12 -m venv venv
source venv/bin/activate

# Verify:
python --version   # should show: Python 3.12.x

pip install --upgrade pip
pip install -r requirements.txt
⚠️
If requirements.txt pins python_requires>=3.11,<3.12
Python 3.12 is forward-compatible with 3.11 code. If any dependency hard-fails on 3.12, report it and we'll address it case by case.
5

Create .env on the Server

Never commit this file. Fill in real values before starting the service.

bash
cat > /home/store.csr2racer.com/csr2-store-clone/backend/.env << 'EOF'
# PostgreSQL 16 — asyncpg driver (works with PG16 unchanged)
DATABASE_URL=postgresql+asyncpg://csr2mods:YOUR_DB_PASSWORD@localhost:5432/csr2mods

SECRET_KEY=REPLACE_WITH_GENERATED_KEY
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=1440

REDIS_URL=redis://localhost:6379

STRIPE_SECRET_KEY=sk_live_placeholder
STRIPE_WEBHOOK_SECRET=whsec_placeholder
RESEND_API_KEY=re_placeholder
FROM_EMAIL=noreply@store.csr2racer.com

APP_ENV=production
FRONTEND_URL=https://store.csr2racer.com
EOF

# Generate SECRET_KEY — paste output into the .env above:
openssl rand -hex 32
6

Run Migrations and Seed

Apply Alembic schema then seed the initial data.

bash
cd /home/store.csr2racer.com/csr2-store-clone/backend
source venv/bin/activate

alembic upgrade head
python scripts/seed.py

# Change the insecure default admin password before going live!
7

Systemd Service 2 WORKERS

4 CPUs + 15 GB RAM → run 2 uvicorn workers. Edit the service file paths before copying.

bash
# If the service file hardcodes /home/csr2mods/ paths, update them first:
sed -i 's|/home/csr2mods/csr2-store-clone|/home/store.csr2racer.com/csr2-store-clone|g' \
  /home/store.csr2racer.com/csr2-store-clone/backend/scripts/csr2mods-api.service

# Make sure the workers flag is set to 2 — 4 CPUs justifies it:
grep -i workers /home/store.csr2racer.com/csr2-store-clone/backend/scripts/csr2mods-api.service

cp /home/store.csr2racer.com/csr2-store-clone/backend/scripts/csr2mods-api.service \
   /etc/systemd/system/

systemctl daemon-reload
systemctl enable csr2mods-api
systemctl start csr2mods-api
systemctl status csr2mods-api --no-pager

# Health check — must return {"status":"ok","version":"2.0.0"}:
curl http://127.0.0.1:8001/health
8

OLS Reverse Proxy — Option A THIS SERVER

No Nginx on this server. Use CyberPanel's built-in reverse proxy UI for store.csr2racer.com.

🖥️ Via CyberPanel UI
  • Websites → store.csr2racer.com
  • Rewrite Rules → Add Rule
  • Context: /api
  • Type: Reverse Proxy
  • URI: http://127.0.0.1:8001
📄 Or via OLS vhost config
apache
context /api {
  type proxy
  handler 127.0.0.1:8001
  addDefaultCharset off
}

rewrite {
  enable 1
  rules <<<END_rules
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
  END_rules
}
ℹ️
Do NOT restart OLS without checking live sites first
There are 15+ other live vhosts on this server. Use graceful restart from CyberPanel → Server Status → Restart Web Server.
9

SSL Certificate

Issue Let's Encrypt via CyberPanel — same flow used for all other domains on this server.

  • CyberPanel → Websites → store.csr2racer.com → SSL → Issue Let's Encrypt
  • Verify: curl -I https://store.csr2racer.com/api/health
10

Deploy Frontend LATER — Plan 3

The frontend/ directory doesn't exist yet. Node.js 22 is already installed and ready.

Skip for now
Node.js 22.21.1 is installed — no action needed when the frontend is ready. Build command will be:
npm run build → sync dist/ to /home/store.csr2racer.com/public_html/

📊

What to Report Back

After deployment completes.
#ItemNotes
1Server summaryUbuntu 24.04 · 15 GB RAM · 4 vCPU · OLS · PG16 · Redis ✓
2What was installedNothing new — all runtimes pre-existing
3Deployment approachOption A (OLS only) · Option C (2 workers)
4FastAPI port127.0.0.1:8001
5Repo location/home/store.csr2racer.com/csr2-store-clone
6Health checkcurl http://127.0.0.1:8001/health{"status":"ok","version":"2.0.0"}
7Issues encountered
8Remaining stepsReal Stripe/Resend keys · Admin password · Frontend (Plan 3)

🛡️

Important Notes

⛔ Don't install PostgreSQL 15PG16 is running. Installing PG15 alongside will conflict. Use what's here.
⛔ Don't install Python 3.11Python 3.12 works. Installing 3.11 is wasted space and complexity.
🔒 15+ live sites on this serverDon't touch existing vhosts. Only add config for store.csr2racer.com.
🤫 .env never in gitLives only at backend/.env on the server.
🔑 Change default admin passwordCHANGE_ADMIN_PASSWORD_BEFORE_DEPLOY in seed.py is insecure.
💳 API keys are placeholdersSet real Stripe and Resend keys in .env before going live.
🚨
Security Critical
Generate SECRET_KEY with openssl rand -hex 32. Never reuse keys across environments. Never commit .env.