Files
orion/docs/deployment/gitlab.md
Samir Boulahtit e9253fbd84 refactor: rename Wizamart to Orion across entire codebase
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>
2026-02-14 16:46:56 +01:00

8.2 KiB

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

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

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)

curl -LsSf https://astral.sh/uv/install.sh | sh
source ~/.bashrc

3. Database Setup (PostgreSQL)

# 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:

[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:

sudo systemctl daemon-reload
sudo systemctl enable orion

5. Nginx Configuration

Create /etc/nginx/sites-available/orion:

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:

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

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot will automatically configure HTTPS and set up auto-renewal.


7. Firewall Configuration

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:

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:

# 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:

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

# 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

# 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

# Test PostgreSQL connection
psql -U orion -h localhost -d orion

# Check PostgreSQL status
sudo systemctl status postgresql

Nginx errors

# Test configuration
sudo nginx -t

# Check error logs
sudo tail -f /var/log/nginx/error.log