Replace all ~1,086 occurrences of Wizamart/wizamart/WIZAMART/WizaMart with Orion/orion/ORION across 184 files. This includes database identifiers, email addresses, domain references, R2 bucket names, DNS prefixes, encryption salt, Celery app name, config defaults, Docker configs, CI configs, documentation, seed data, and templates. Renames homepage-wizamart.html template to homepage-orion.html. Fixes duplicate file_pattern key in api.yaml architecture rule. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
401 lines
8.2 KiB
Markdown
401 lines
8.2 KiB
Markdown
# GitLab CI/CD Deployment Guide
|
|
|
|
This document describes how to deploy the Orion platform to a **DigitalOcean Droplet** using **bare-metal systemd + Nginx**, with automated deployments from **GitLab CI/CD**.
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
- DigitalOcean Droplet (Ubuntu 22.04+ recommended)
|
|
- Domain name pointing to your server
|
|
- GitLab repository with CI/CD enabled
|
|
- SSH key pair for deployment
|
|
|
|
---
|
|
|
|
## 1. Server Folder Structure
|
|
|
|
The application will be deployed to:
|
|
|
|
```
|
|
/var/www/orion/
|
|
├── app/ # FastAPI application
|
|
├── static/
|
|
│ ├── admin/
|
|
│ ├── store/
|
|
│ ├── shop/
|
|
│ └── shared/
|
|
├── templates/
|
|
├── alembic/ # Database migrations
|
|
├── .venv/ # Python virtual environment
|
|
├── .env # Environment variables (created manually)
|
|
└── pyproject.toml
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Server Setup
|
|
|
|
### Create Deploy User (Recommended)
|
|
|
|
```bash
|
|
sudo adduser deploy --disabled-password
|
|
sudo usermod -aG sudo deploy
|
|
sudo mkdir -p /var/www/orion
|
|
sudo chown -R deploy:deploy /var/www/orion
|
|
```
|
|
|
|
### Install System Dependencies
|
|
|
|
```bash
|
|
sudo apt update
|
|
sudo apt install -y python3.11 python3.11-venv python3-pip \
|
|
build-essential libpq-dev nginx postgresql postgresql-contrib \
|
|
nodejs npm certbot python3-certbot-nginx
|
|
```
|
|
|
|
### Install uv (Python Package Manager)
|
|
|
|
```bash
|
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
source ~/.bashrc
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Database Setup (PostgreSQL)
|
|
|
|
```bash
|
|
# Create database and user
|
|
sudo -u postgres psql << EOF
|
|
CREATE USER orion WITH PASSWORD 'your_secure_password';
|
|
CREATE DATABASE orion OWNER orion;
|
|
GRANT ALL PRIVILEGES ON DATABASE orion TO orion;
|
|
EOF
|
|
```
|
|
|
|
---
|
|
|
|
## 4. systemd Service
|
|
|
|
Create `/etc/systemd/system/orion.service`:
|
|
|
|
```ini
|
|
[Unit]
|
|
Description=Orion FastAPI Application
|
|
After=network.target postgresql.service
|
|
|
|
[Service]
|
|
User=deploy
|
|
Group=deploy
|
|
WorkingDirectory=/var/www/orion
|
|
Environment="PATH=/var/www/orion/.venv/bin"
|
|
EnvironmentFile=/var/www/orion/.env
|
|
ExecStart=/var/www/orion/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 4
|
|
Restart=always
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
Enable the service:
|
|
|
|
```bash
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable orion
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Nginx Configuration
|
|
|
|
Create `/etc/nginx/sites-available/orion`:
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
server_name yourdomain.com www.yourdomain.com;
|
|
|
|
# Static files
|
|
location /static/ {
|
|
alias /var/www/orion/static/;
|
|
expires 30d;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
|
|
# Media/uploads
|
|
location /uploads/ {
|
|
alias /var/www/orion/uploads/;
|
|
expires 7d;
|
|
}
|
|
|
|
# Proxy to FastAPI
|
|
location / {
|
|
proxy_pass http://127.0.0.1:8000;
|
|
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;
|
|
proxy_read_timeout 300;
|
|
proxy_connect_timeout 300;
|
|
}
|
|
}
|
|
```
|
|
|
|
Enable the site:
|
|
|
|
```bash
|
|
sudo ln -s /etc/nginx/sites-available/orion /etc/nginx/sites-enabled/
|
|
sudo rm /etc/nginx/sites-enabled/default # Remove default site
|
|
sudo nginx -t
|
|
sudo systemctl restart nginx
|
|
```
|
|
|
|
---
|
|
|
|
## 6. HTTPS with Let's Encrypt
|
|
|
|
```bash
|
|
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
|
|
```
|
|
|
|
Certbot will automatically configure HTTPS and set up auto-renewal.
|
|
|
|
---
|
|
|
|
## 7. Firewall Configuration
|
|
|
|
```bash
|
|
sudo ufw allow OpenSSH
|
|
sudo ufw allow 'Nginx Full'
|
|
sudo ufw enable
|
|
```
|
|
|
|
---
|
|
|
|
## 8. GitLab CI/CD Pipeline
|
|
|
|
Create `.gitlab-ci.yml` in your project root:
|
|
|
|
```yaml
|
|
stages:
|
|
- test
|
|
- build
|
|
- deploy
|
|
|
|
variables:
|
|
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
|
|
UV_CACHE_DIR: "$CI_PROJECT_DIR/.cache/uv"
|
|
|
|
# Test stage
|
|
test:
|
|
stage: test
|
|
image: python:3.11
|
|
before_script:
|
|
- pip install uv
|
|
- uv venv
|
|
- source .venv/bin/activate
|
|
- uv pip install -r requirements.txt
|
|
script:
|
|
- python -m pytest tests/ -v --tb=short
|
|
only:
|
|
- merge_requests
|
|
- main
|
|
|
|
# Build Tailwind CSS
|
|
build:
|
|
stage: build
|
|
image: node:20
|
|
script:
|
|
- npm install
|
|
- npx tailwindcss -i ./static/src/input.css -o ./static/dist/output.css --minify
|
|
artifacts:
|
|
paths:
|
|
- static/dist/
|
|
expire_in: 1 week
|
|
only:
|
|
- main
|
|
|
|
# Deploy to production
|
|
deploy:
|
|
stage: deploy
|
|
image: alpine:latest
|
|
before_script:
|
|
- apk add --no-cache openssh-client rsync
|
|
- mkdir -p ~/.ssh
|
|
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_ed25519
|
|
- chmod 600 ~/.ssh/id_ed25519
|
|
- ssh-keyscan -H $SERVER_HOST >> ~/.ssh/known_hosts
|
|
script:
|
|
# Sync files to server (excluding sensitive files)
|
|
- rsync -avz --delete
|
|
--exclude='.git'
|
|
--exclude='.env'
|
|
--exclude='*.pyc'
|
|
--exclude='__pycache__'
|
|
--exclude='.pytest_cache'
|
|
--exclude='htmlcov'
|
|
--exclude='*.db'
|
|
./ $SERVER_USER@$SERVER_HOST:$SERVER_PATH/
|
|
|
|
# Install dependencies and run migrations
|
|
- ssh $SERVER_USER@$SERVER_HOST "
|
|
cd $SERVER_PATH &&
|
|
~/.cargo/bin/uv venv --python 3.11 &&
|
|
source .venv/bin/activate &&
|
|
~/.cargo/bin/uv pip install -r requirements.txt &&
|
|
python -m alembic upgrade head
|
|
"
|
|
|
|
# Restart the service
|
|
- ssh $SERVER_USER@$SERVER_HOST "sudo systemctl restart orion"
|
|
|
|
# Verify deployment
|
|
- ssh $SERVER_USER@$SERVER_HOST "sudo systemctl status orion --no-pager"
|
|
only:
|
|
- main
|
|
environment:
|
|
name: production
|
|
url: https://yourdomain.com
|
|
```
|
|
|
|
---
|
|
|
|
## 9. GitLab CI/CD Variables
|
|
|
|
Configure these in **Settings > CI/CD > Variables**:
|
|
|
|
| Variable | Description | Example |
|
|
|----------|-------------|---------|
|
|
| `SSH_PRIVATE_KEY` | Private key for server access | `-----BEGIN OPENSSH PRIVATE KEY-----...` |
|
|
| `SERVER_USER` | SSH user on server | `deploy` |
|
|
| `SERVER_HOST` | Server IP or hostname | `203.0.113.50` |
|
|
| `SERVER_PATH` | Application directory | `/var/www/orion` |
|
|
|
|
Mark `SSH_PRIVATE_KEY` as **Protected** and **Masked**.
|
|
|
|
---
|
|
|
|
## 10. Environment Variables
|
|
|
|
Create `/var/www/orion/.env` on the server:
|
|
|
|
```bash
|
|
# Application
|
|
APP_ENV=production
|
|
DEBUG=false
|
|
SECRET_KEY=your-super-secret-key-change-this
|
|
|
|
# Database
|
|
DATABASE_URL=postgresql://orion:password@localhost:5432/orion
|
|
|
|
# Stripe (if using billing)
|
|
STRIPE_SECRET_KEY=sk_live_...
|
|
STRIPE_WEBHOOK_SECRET=whsec_...
|
|
|
|
# Email
|
|
SMTP_HOST=smtp.your-provider.com
|
|
SMTP_PORT=587
|
|
SMTP_USER=your-email@domain.com
|
|
SMTP_PASSWORD=your-smtp-password
|
|
EMAILS_FROM=noreply@yourdomain.com
|
|
|
|
# Letzshop Integration (if applicable)
|
|
LETZSHOP_API_URL=https://api.letzshop.lu
|
|
```
|
|
|
|
Secure the file:
|
|
|
|
```bash
|
|
chmod 600 /var/www/orion/.env
|
|
```
|
|
|
|
---
|
|
|
|
## 11. Deployment Flow
|
|
|
|
1. Developer pushes to `main` branch
|
|
2. GitLab runs tests
|
|
3. GitLab builds Tailwind CSS
|
|
4. GitLab syncs files to server via rsync
|
|
5. Server installs/updates Python dependencies
|
|
6. Alembic runs database migrations
|
|
7. systemd restarts the FastAPI service
|
|
8. Nginx serves the application over HTTPS
|
|
|
|
---
|
|
|
|
## 12. Maintenance Commands
|
|
|
|
```bash
|
|
# View application logs
|
|
sudo journalctl -u orion -f
|
|
|
|
# Restart application
|
|
sudo systemctl restart orion
|
|
|
|
# Check application status
|
|
sudo systemctl status orion
|
|
|
|
# Run migrations manually
|
|
cd /var/www/orion
|
|
source .venv/bin/activate
|
|
python -m alembic upgrade head
|
|
|
|
# Rollback migration
|
|
python -m alembic downgrade -1
|
|
```
|
|
|
|
---
|
|
|
|
## 13. Security Recommendations
|
|
|
|
- [ ] Use a non-root deploy user (as shown above)
|
|
- [ ] Enable fail2ban for SSH protection
|
|
- [ ] Configure PostgreSQL to only allow local connections
|
|
- [ ] Set up automated backups for the database
|
|
- [ ] Enable log rotation
|
|
- [ ] Consider using Docker for isolation
|
|
- [ ] Set up monitoring (e.g., Prometheus + Grafana)
|
|
- [ ] Configure rate limiting in Nginx
|
|
|
|
---
|
|
|
|
## 14. Troubleshooting
|
|
|
|
### Application won't start
|
|
|
|
```bash
|
|
# Check logs
|
|
sudo journalctl -u orion -n 100
|
|
|
|
# Verify environment file
|
|
cat /var/www/orion/.env
|
|
|
|
# Test manually
|
|
cd /var/www/orion
|
|
source .venv/bin/activate
|
|
uvicorn app.main:app --host 127.0.0.1 --port 8000
|
|
```
|
|
|
|
### Database connection issues
|
|
|
|
```bash
|
|
# Test PostgreSQL connection
|
|
psql -U orion -h localhost -d orion
|
|
|
|
# Check PostgreSQL status
|
|
sudo systemctl status postgresql
|
|
```
|
|
|
|
### Nginx errors
|
|
|
|
```bash
|
|
# Test configuration
|
|
sudo nginx -t
|
|
|
|
# Check error logs
|
|
sudo tail -f /var/log/nginx/error.log
|
|
```
|