---
title: "Infrastructure"
description: "Deployment infrastructure, containerization, orchestration, and cloud architecture for TraceRTM"
---

# Infrastructure

TraceRTM is designed for flexible deployment across various environments, from local development to enterprise-scale Kubernetes clusters.

## Deployment Options

| Option | Best For | Complexity |
|--------|----------|------------|
| **Docker Compose** | Development, small teams | Low |
| **Kubernetes** | Production, enterprise | Medium |
| **Cloud Managed** | Minimal ops overhead | Low |
| **Hybrid** | Compliance requirements | High |

---

## Docker Architecture

### Container Images

```
┌─────────────────────────────────────────────────────────────────┐
│                     TraceRTM Containers                          │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐           │
│  │   API        │  │   Worker     │  │   Web        │           │
│  │   Server     │  │   (Celery)   │  │   Frontend   │           │
│  │              │  │              │  │              │           │
│  │  FastAPI     │  │  Background  │  │  React/Nginx │           │
│  │  Uvicorn     │  │  Tasks       │  │  Static      │           │
│  └──────────────┘  └──────────────┘  └──────────────┘           │
│                                                                  │
├─────────────────────────────────────────────────────────────────┤
│                     Data Services                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐           │
│  │  PostgreSQL  │  │    Neo4j     │  │    Redis     │           │
│  │              │  │              │  │              │           │
│  │  Primary DB  │  │  Graph DB    │  │  Cache/Queue │           │
│  └──────────────┘  └──────────────┘  └──────────────┘           │
│                                                                  │
│  ┌──────────────┐  ┌──────────────┐                             │
│  │  Meilisearch │  │    MinIO     │                             │
│  │              │  │              │                             │
│  │  Full-text   │  │  Object      │                             │
│  │  Search      │  │  Storage     │                             │
│  └──────────────┘  └──────────────┘                             │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

### API Server Dockerfile

```dockerfile
# Dockerfile.api
FROM python:3.11-slim as builder

WORKDIR /app

# Install build dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    libpq-dev \
    && rm -rf /var/lib/apt/lists/*

# Install Python dependencies
COPY pyproject.toml poetry.lock ./
RUN pip install poetry && \
    poetry config virtualenvs.create false && \
    poetry install --no-dev --no-interaction

# Production image
FROM python:3.11-slim

WORKDIR /app

# Install runtime dependencies
RUN apt-get update && apt-get install -y \
    libpq5 \
    && rm -rf /var/lib/apt/lists/*

# Copy installed packages
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin

# Copy application
COPY src/tracertm ./tracertm
COPY alembic ./alembic
COPY alembic.ini .

# Create non-root user
RUN useradd -m -u 1000 tracertm && chown -R tracertm:tracertm /app
USER tracertm

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8000/health || exit 1

EXPOSE 8000

CMD ["uvicorn", "tracertm.api.main:app", "--host", "0.0.0.0", "--port", "8000"]
```

### Web Frontend Dockerfile

```dockerfile
# Dockerfile.web
FROM node:20-alpine as builder

WORKDIR /app

# Install dependencies
COPY frontend/package.json frontend/pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile

# Build
COPY frontend/ ./
RUN pnpm build

# Production image
FROM nginx:alpine

# Copy build output
COPY --from=builder /app/dist /usr/share/nginx/html

# Copy nginx config
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Health check
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
    CMD wget -q --spider http://localhost:80/health || exit 1

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
```

### Docker Compose

```yaml
# docker-compose.yml
version: '3.8'

services:
  # API Server
  api:
    build:
      context: .
      dockerfile: Dockerfile.api
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql+asyncpg://tracertm:password@postgres:5432/tracertm
      - NEO4J_URI=bolt://neo4j:7687
      - NEO4J_USER=neo4j
      - NEO4J_PASSWORD=password
      - REDIS_URL=redis://redis:6379/0
      - MEILISEARCH_URL=http://meilisearch:7700
      - MEILISEARCH_KEY=${MEILISEARCH_KEY}
      - SECRET_KEY=${SECRET_KEY}
    depends_on:
      postgres:
        condition: service_healthy
      neo4j:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # Celery Worker
  worker:
    build:
      context: .
      dockerfile: Dockerfile.api
    command: celery -A tracertm.tasks worker -l info
    environment:
      - DATABASE_URL=postgresql+asyncpg://tracertm:password@postgres:5432/tracertm
      - REDIS_URL=redis://redis:6379/0
      - CELERY_BROKER_URL=redis://redis:6379/1
    depends_on:
      - api
      - redis

  # Web Frontend
  web:
    build:
      context: .
      dockerfile: Dockerfile.web
    ports:
      - "3000:80"
    depends_on:
      - api

  # PostgreSQL
  postgres:
    image: postgres:16-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=tracertm
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=tracertm
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U tracertm"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Neo4j
  neo4j:
    image: neo4j:5-community
    volumes:
      - neo4j_data:/data
    environment:
      - NEO4J_AUTH=neo4j/password
      - NEO4J_PLUGINS=["apoc"]
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7474"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis
  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Meilisearch
  meilisearch:
    image: getmeili/meilisearch:v1.6
    volumes:
      - meilisearch_data:/meili_data
    environment:
      - MEILI_MASTER_KEY=${MEILISEARCH_KEY}

  # MinIO (Object Storage)
  minio:
    image: minio/minio
    volumes:
      - minio_data:/data
    environment:
      - MINIO_ROOT_USER=tracertm
      - MINIO_ROOT_PASSWORD=password
    command: server /data --console-address ":9001"
    ports:
      - "9000:9000"
      - "9001:9001"

volumes:
  postgres_data:
  neo4j_data:
  redis_data:
  meilisearch_data:
  minio_data:
```

---

## Kubernetes Architecture

### Cluster Layout

```
┌─────────────────────────────────────────────────────────────────┐
│                     Kubernetes Cluster                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌────────────────────────────────────────────────────────┐     │
│  │                    Ingress Controller                   │     │
│  │              (nginx-ingress / traefik)                 │     │
│  └─────────────────────────┬──────────────────────────────┘     │
│                            │                                     │
│  ┌─────────────────────────┼──────────────────────────────┐     │
│  │                    tracertm namespace                   │     │
│  │                                                         │     │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐     │     │
│  │  │ API         │  │ Web         │  │ Worker      │     │     │
│  │  │ Deployment  │  │ Deployment  │  │ Deployment  │     │     │
│  │  │ (3 pods)    │  │ (2 pods)    │  │ (2 pods)    │     │     │
│  │  └─────────────┘  └─────────────┘  └─────────────┘     │     │
│  │         │                │                │             │     │
│  │  ┌──────┴────────────────┴────────────────┴──────┐     │     │
│  │  │              Internal Services                 │     │     │
│  │  │  (ClusterIP: api-svc, web-svc)                │     │     │
│  │  └───────────────────────────────────────────────┘     │     │
│  └─────────────────────────────────────────────────────────┘     │
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐     │
│  │                    data namespace                        │     │
│  │                                                          │     │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐      │     │
│  │  │ PostgreSQL  │  │ Neo4j       │  │ Redis       │      │     │
│  │  │ StatefulSet │  │ StatefulSet │  │ StatefulSet │      │     │
│  │  └─────────────┘  └─────────────┘  └─────────────┘      │     │
│  └─────────────────────────────────────────────────────────┘     │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

### API Deployment

```yaml
# k8s/api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tracertm-api
  namespace: tracertm
  labels:
    app: tracertm
    component: api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: tracertm
      component: api
  template:
    metadata:
      labels:
        app: tracertm
        component: api
    spec:
      serviceAccountName: tracertm-api
      containers:
        - name: api
          image: tracertm/api:latest
          ports:
            - containerPort: 8000
              name: http
          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: tracertm-secrets
                  key: database-url
            - name: NEO4J_URI
              valueFrom:
                secretKeyRef:
                  name: tracertm-secrets
                  key: neo4j-uri
            - name: REDIS_URL
              valueFrom:
                secretKeyRef:
                  name: tracertm-secrets
                  key: redis-url
          resources:
            requests:
              memory: "512Mi"
              cpu: "250m"
            limits:
              memory: "1Gi"
              cpu: "1000m"
          livenessProbe:
            httpGet:
              path: /health
              port: 8000
            initialDelaySeconds: 10
            periodSeconds: 30
          readinessProbe:
            httpGet:
              path: /ready
              port: 8000
            initialDelaySeconds: 5
            periodSeconds: 10
          volumeMounts:
            - name: config
              mountPath: /app/config
              readOnly: true
      volumes:
        - name: config
          configMap:
            name: tracertm-config
---
apiVersion: v1
kind: Service
metadata:
  name: tracertm-api
  namespace: tracertm
spec:
  selector:
    app: tracertm
    component: api
  ports:
    - port: 80
      targetPort: 8000
      name: http
  type: ClusterIP
```

### Horizontal Pod Autoscaler

```yaml
# k8s/api-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: tracertm-api-hpa
  namespace: tracertm
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: tracertm-api
  minReplicas: 3
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Pods
          value: 4
          periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 10
          periodSeconds: 60
```

### Ingress Configuration

```yaml
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tracertm-ingress
  namespace: tracertm
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/rate-limit-window: "1m"
spec:
  tls:
    - hosts:
        - app.tracertm.dev
        - api.tracertm.dev
      secretName: tracertm-tls
  rules:
    - host: app.tracertm.dev
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: tracertm-web
                port:
                  number: 80
    - host: api.tracertm.dev
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: tracertm-api
                port:
                  number: 80
```

---

## Cloud Services

### AWS Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                           AWS VPC                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                    Public Subnets                         │   │
│  │                                                           │   │
│  │  ┌─────────────┐         ┌─────────────┐                 │   │
│  │  │     ALB     │         │   NAT GW    │                 │   │
│  │  │ (api, web)  │         │             │                 │   │
│  │  └─────────────┘         └─────────────┘                 │   │
│  └──────────────────────────────────────────────────────────┘   │
│                              │                                   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                   Private Subnets                         │   │
│  │                                                           │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐       │   │
│  │  │    EKS      │  │    RDS      │  │ ElastiCache │       │   │
│  │  │  Cluster    │  │ PostgreSQL  │  │   Redis     │       │   │
│  │  └─────────────┘  └─────────────┘  └─────────────┘       │   │
│  │                                                           │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐       │   │
│  │  │   Neptune   │  │ OpenSearch  │  │     S3      │       │   │
│  │  │  (Graph)    │  │  (Search)   │  │  (Storage)  │       │   │
│  │  └─────────────┘  └─────────────┘  └─────────────┘       │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

### Terraform Example

```hcl
# terraform/main.tf

# EKS Cluster
module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 19.0"

  cluster_name    = "tracertm-${var.environment}"
  cluster_version = "1.28"

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnets

  eks_managed_node_groups = {
    main = {
      min_size     = 3
      max_size     = 10
      desired_size = 3

      instance_types = ["t3.large"]
      capacity_type  = "ON_DEMAND"
    }
  }
}

# RDS PostgreSQL
module "rds" {
  source  = "terraform-aws-modules/rds/aws"
  version = "~> 6.0"

  identifier = "tracertm-${var.environment}"

  engine               = "postgres"
  engine_version       = "16.1"
  instance_class       = "db.r6g.large"
  allocated_storage    = 100
  max_allocated_storage = 500

  db_name  = "tracertm"
  username = "tracertm"
  port     = 5432

  multi_az               = true
  db_subnet_group_name   = module.vpc.database_subnet_group_name
  vpc_security_group_ids = [module.security_group.security_group_id]

  backup_retention_period = 7
  deletion_protection     = true
}

# ElastiCache Redis
module "elasticache" {
  source  = "terraform-aws-modules/elasticache/aws"
  version = "~> 1.0"

  cluster_id           = "tracertm-${var.environment}"
  engine               = "redis"
  engine_version       = "7.0"
  node_type            = "cache.r6g.large"
  num_cache_nodes      = 2
  parameter_group_name = "default.redis7"

  subnet_group_name = module.vpc.elasticache_subnet_group_name
  security_group_ids = [module.security_group.security_group_id]
}

# S3 Bucket
resource "aws_s3_bucket" "attachments" {
  bucket = "tracertm-attachments-${var.environment}"

  tags = {
    Name        = "TraceRTM Attachments"
    Environment = var.environment
  }
}

resource "aws_s3_bucket_versioning" "attachments" {
  bucket = aws_s3_bucket.attachments.id
  versioning_configuration {
    status = "Enabled"
  }
}
```

---

## Monitoring & Observability

### Prometheus Metrics

```yaml
# k8s/prometheus-servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: tracertm-api
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: tracertm
      component: api
  endpoints:
    - port: http
      path: /metrics
      interval: 30s
  namespaceSelector:
    matchNames:
      - tracertm
```

### Grafana Dashboard

```json
{
  "dashboard": {
    "title": "TraceRTM API",
    "panels": [
      {
        "title": "Request Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(http_requests_total{app=\"tracertm\"}[5m])"
          }
        ]
      },
      {
        "title": "Response Time (P95)",
        "type": "graph",
        "targets": [
          {
            "expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket{app=\"tracertm\"}[5m]))"
          }
        ]
      },
      {
        "title": "Error Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(http_requests_total{app=\"tracertm\",status=~\"5..\"}[5m])"
          }
        ]
      }
    ]
  }
}
```

### Logging with ELK

```yaml
# k8s/filebeat-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
  namespace: logging
data:
  filebeat.yml: |
    filebeat.inputs:
      - type: container
        paths:
          - /var/log/containers/tracertm-*.log
        processors:
          - add_kubernetes_metadata:
              host: ${NODE_NAME}
              matchers:
                - logs_path:
                    logs_path: "/var/log/containers/"

    output.elasticsearch:
      hosts: ["${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}"]
      index: "tracertm-%{+yyyy.MM.dd}"
```

---

## Security

### Network Policies

```yaml
# k8s/network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tracertm-api-policy
  namespace: tracertm
spec:
  podSelector:
    matchLabels:
      app: tracertm
      component: api
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-nginx
      ports:
        - protocol: TCP
          port: 8000
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              name: data
      ports:
        - protocol: TCP
          port: 5432
        - protocol: TCP
          port: 7687
        - protocol: TCP
          port: 6379
    - to:
        - namespaceSelector: {}
      ports:
        - protocol: UDP
          port: 53
```

### Secrets Management

```yaml
# k8s/external-secrets.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: tracertm-secrets
  namespace: tracertm
spec:
  refreshInterval: 1h
  secretStoreRef:
    kind: ClusterSecretStore
    name: aws-secrets-manager
  target:
    name: tracertm-secrets
  data:
    - secretKey: database-url
      remoteRef:
        key: tracertm/production/database
        property: url
    - secretKey: redis-url
      remoteRef:
        key: tracertm/production/redis
        property: url
```

---

## Related Documentation

- [Docker Deployment](/docs/development/deployment/docker) - Docker setup guide
- [Kubernetes Deployment](/docs/development/deployment/kubernetes) - K8s deployment
- [Cloud Deployment](/docs/getting-started/installation/cloud) - Cloud provider guides
- [Monitoring](/docs/development/deployment/monitoring) - Observability setup
