projects/org/pirotehnika/app/pim/DEPLOYMENT.md

PIM Service Deployment Guide

Prerequisites

Development Setup

1. Create Virtual Environment

cd /opt/claude-workspace/L1-SERVICE/pirotehnika/pim
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

2. Install Dependencies

pip install -r requirements.txt

3. Configure Environment

Create a .env file in the project root:

# Database
DATABASE_HOST=91.218.142.168
DATABASE_PORT=5432
DATABASE_USER=noco
DATABASE_PASSWORD=your_password
DATABASE_NAME=nocodb_data
DATABASE_SCHEMA=pt7k98pv0fwi1el

# API
API_V1_PREFIX=/api/v1
API_TITLE=PIM Service API
API_VERSION=1.0.0
API_DESCRIPTION=Product Information Management for pirotehnika

# Logging
LOG_LEVEL=INFO

4. Run Development Server

python -m uvicorn main:app --reload --host 0.0.0.0 --port 8000

The API will be available at: http://localhost:8000/api/v1

Interactive documentation:
- Swagger UI: http://localhost:8000/api/v1/docs
- ReDoc: http://localhost:8000/api/v1/redoc

Production Deployment

Option 1: Using Gunicorn + Uvicorn

# Install production dependencies
pip install gunicorn

# Run with gunicorn
gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app \
  --bind 0.0.0.0:8000 \
  --access-logfile - \
  --error-logfile - \
  --log-level info

Option 2: Using Docker

Create Dockerfile:

FROM python:3.10-slim

WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y \
    gcc \
    postgresql-client \
    && rm -rf /var/lib/apt/lists/*

# Copy requirements
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application
COPY . .

# Expose port
EXPOSE 8000

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD python -c "import requests; requests.get('http://localhost:8000/health')"

# Run application
CMD ["gunicorn", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", \
     "main:app", "--bind", "0.0.0.0:8000"]

Create docker-compose.yml:

version: '3.8'

services:
  pim-service:
    build: .
    ports:
      - "8000:8000"
    environment:
      DATABASE_HOST: postgres
      DATABASE_USER: ${DATABASE_USER}
      DATABASE_PASSWORD: ${DATABASE_PASSWORD}
      DATABASE_NAME: ${DATABASE_NAME}
      LOG_LEVEL: info
    depends_on:
      - postgres
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: ${DATABASE_USER}
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
      POSTGRES_DB: ${DATABASE_NAME}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

volumes:
  postgres_data:

Deploy with Docker:

# Create .env file
echo "DATABASE_USER=noco" >> .env
echo "DATABASE_PASSWORD=your_password" >> .env
echo "DATABASE_NAME=nocodb_data" >> .env

# Build and run
docker-compose up -d

Option 3: Using systemd

Create /etc/systemd/system/pim-service.service:

[Unit]
Description=PIM Service API
After=network.target

[Service]
Type=notify
User=www-data
WorkingDirectory=/opt/claude-workspace/L1-SERVICE/pirotehnika/pim
Environment="PATH=/opt/claude-workspace/L1-SERVICE/pirotehnika/pim/venv/bin"
ExecStart=/opt/claude-workspace/L1-SERVICE/pirotehnika/pim/venv/bin/gunicorn \
    -w 4 \
    -k uvicorn.workers.UvicornWorker \
    main:app \
    --bind 0.0.0.0:8000

Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable pim-service
sudo systemctl start pim-service
sudo systemctl status pim-service

Nginx Configuration

Create /etc/nginx/sites-available/pim-service:

upstream pim_backend {
    server 127.0.0.1:8000;
}

server {
    listen 80;
    server_name api.pirotehnika.local;

    # Redirect HTTP to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name api.pirotehnika.local;

    # SSL configuration
    ssl_certificate /etc/letsencrypt/live/api.pirotehnika.local/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.pirotehnika.local/privkey.pem;

    # SSL best practices
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    client_max_body_size 20M;

    location / {
        proxy_pass http://pim_backend;
        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;

        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Enable site:

sudo ln -s /etc/nginx/sites-available/pim-service /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Database Setup

Create Tables

-- This is typically done via SQLAlchemy ORM
-- Create tables manually if needed:

CREATE SCHEMA IF NOT EXISTS pt7k98pv0fwi1el;

CREATE TABLE pt7k98pv0fwi1el.pim_products (
    article VARCHAR PRIMARY KEY,
    name VARCHAR NOT NULL,
    brand VARCHAR,
    category VARCHAR,
    base_price NUMERIC(10, 2),
    cost_price NUMERIC(10, 2),
    discount_percent NUMERIC(5, 2),
    product_type VARCHAR,
    code_1c VARCHAR,
    barcode VARCHAR,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE pt7k98pv0fwi1el.price_cost_rules (
    id SERIAL PRIMARY KEY,
    brand VARCHAR UNIQUE NOT NULL,
    discount_percent NUMERIC(5, 2) NOT NULL,
    description VARCHAR,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_products_brand ON pt7k98pv0fwi1el.pim_products(brand);
CREATE INDEX idx_products_category ON pt7k98pv0fwi1el.pim_products(category);
CREATE INDEX idx_cost_rules_brand ON pt7k98pv0fwi1el.price_cost_rules(brand);

Health Checks

Check Service Status

curl http://localhost:8000/health

Response:

{
  "status": "healthy",
  "service": "PIM Service",
  "version": "1.0.0"
}

Check Database Connection

# In Python
from pirotehnika.pim.database import get_db_session

db = get_db_session()
result = db.execute("SELECT 1")
print(result.scalar())

Monitoring

Logs

Development:

# Check logs in console (with --reload flag)
tail -f /tmp/pim-service.log

Production (systemd):

sudo journalctl -u pim-service -f

Docker:

docker-compose logs -f pim-service

Performance Monitoring

Install monitoring tools:

pip install prometheus-client

See API metrics at /metrics endpoint (after implementation).

Backup and Recovery

Database Backup

# Backup
pg_dump -h 91.218.142.168 -U noco nocodb_data > backup.sql

# Restore
psql -h 91.218.142.168 -U noco nocodb_data < backup.sql

Troubleshooting

Connection Issues

# Test database connection
psql -h 91.218.142.168 -U noco -d nocodb_data -c "SELECT 1"

Memory Issues

# Increase worker processes for more load
gunicorn -w 8 -k uvicorn.workers.UvicornWorker main:app

Check Service Status

# Systemd
sudo systemctl status pim-service

# Docker
docker-compose ps
docker-compose logs pim-service

# Manual
curl http://localhost:8000/health

Security Considerations

  1. Use HTTPS in production
  2. Implement authentication (JWT)
  3. Add rate limiting
  4. Validate all inputs
  5. Use environment variables for secrets
  6. Keep dependencies updated
  7. Run behind a reverse proxy (Nginx)
  8. Use strong database passwords
  9. Implement request logging
  10. Regular security audits

Scaling

For high-traffic deployments:

  1. Load Balancing: Use Nginx or HAProxy
  2. Caching: Implement Redis for caching
  3. Database Optimization: Add indexes, connection pooling
  4. Horizontal Scaling: Run multiple instances
  5. CDN: Serve static content via CDN
  6. Queue Management: Use Celery for async tasks

Rollback Procedure

If an issue occurs:

# Stop the service
sudo systemctl stop pim-service

# Restore from backup
psql -h 91.218.142.168 -U noco nocodb_data < backup.sql

# Verify
curl http://localhost:8000/health

# Start the service
sudo systemctl start pim-service