Skip to content

TINAA Deployment Guide

Overview

This guide covers deployment options for TINAA in various environments, from local development to production cloud deployments.

Deployment Architecture

%%{init: {
  'theme': 'dark',
  'themeVariables': {
    'fontFamily': 'monospace',
    'primaryBorderColor': '#6BB4DD',
    'primaryColor': '#2D3A4D',
    'primaryTextColor': '#fff',
    'lineColor': '#6BB4DD'
  },
  'themeCSS': '.node rect, .node circle, .node polygon { stroke-width: 2px; stroke-dasharray: 3,3; }'
}}%%
flowchart TD
    subgraph Development["Development Environment"]
        LocalDocker[Local Docker]
        Claude[Claude Desktop]
    end

    subgraph Staging["Staging Environment"]
        DockerCompose[Docker Compose]
        TestData[Test Data]
    end

    subgraph Production["Production Environment"]
        K8s[Kubernetes]
        LoadBalancer[Load Balancer]
        Monitoring[Monitoring]
    end

    subgraph Storage["Persistent Storage"]
        Logs[Log Storage]
        Screenshots[Screenshot Storage]
        Config[Configuration]
    end

    LocalDocker -.-> DockerCompose
    DockerCompose -.-> K8s

    K8s -.-> LoadBalancer
    K8s -.-> Monitoring

    Development -.-> Storage
    Staging -.-> Storage
    Production -.-> Storage

Local Development

The fastest deployment method using pre-built images from GitHub Container Registry.

HTTP Mode (for API access):

# Download production docker-compose file
curl -O https://raw.githubusercontent.com/aj-geddes/tinaa-playwright-msp/main/docker-compose.prod.yml

# Start with pre-built image
docker-compose -f docker-compose.prod.yml up -d

# Access at http://localhost:8765

Building from Source

For development and customization.

MCP Mode (for Claude Desktop):

# Build and run
docker-compose up -d

# View logs
docker-compose logs -f

# Stop
docker-compose down

HTTP Mode (for API access):

# Build and run with HTTP server
docker-compose -f docker-compose.http.yml up -d

# Access at http://localhost:8765

Configuration Files

docker-compose.prod.yml (Pre-built image - Recommended):

version: '3.8'

services:
  tinaa-http:
    image: ghcr.io/aj-geddes/tinaa-playwright-msp:latest
    container_name: tinaa-playwright-msp-http
    command: ["python", "/app/app/http_server.py"]
    ports:
      - "8765:8765"
    environment:
      - PYTHONUNBUFFERED=1
      - PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
      - TINAA_MODE=http
    volumes:
      - ./logs:/app/logs
      - ${PWD}:/mnt/workspace
    restart: unless-stopped

docker-compose.yml (Build from source - MCP mode):

version: '3.8'

services:
  tinaa-mcp:
    image: tinaa-playwright-msp:latest
    build:
      context: .
      dockerfile: Dockerfile
    container_name: tinaa-playwright-msp
    environment:
      - PYTHONUNBUFFERED=1
      - PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
    volumes:
      - ./logs:/app/logs
      - ${PWD}:/mnt/workspace
    stdin_open: true
    tty: true

docker-compose.http.yml (Build from source - HTTP mode):

version: '3.8'

services:
  tinaa-http:
    image: tinaa-playwright-msp:latest
    build:
      context: .
      dockerfile: Dockerfile
    container_name: tinaa-playwright-msp-http
    command: ["python", "/app/app/http_server.py"]
    ports:
      - "8765:8765"
    environment:
      - PYTHONUNBUFFERED=1
      - PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
      - TINAA_MODE=http
    volumes:
      - ./logs:/app/logs
      - ${PWD}:/mnt/workspace

Production Deployment

Using Pre-built Images in Production

Pre-built images from GitHub Container Registry are recommended for production deployments as they are: - Tested and verified - Consistently built - Easy to deploy and update - Available for specific versions/tags

# Pull latest stable version
docker pull ghcr.io/aj-geddes/tinaa-playwright-msp:latest

# Or pull a specific version
docker pull ghcr.io/aj-geddes/tinaa-playwright-msp:v1.0.0

Kubernetes Deployment

For scalable production deployments using pre-built images.

%%{init: {
  'theme': 'dark',
  'themeVariables': {
    'fontFamily': 'monospace',
    'primaryBorderColor': '#6BB4DD',
    'primaryColor': '#2D3A4D',
    'primaryTextColor': '#fff',
    'lineColor': '#6BB4DD'
  },
  'themeCSS': '.node rect, .node circle, .node polygon { stroke-width: 2px; stroke-dasharray: 3,3; }'
}}%%
flowchart TD
    subgraph Cluster["Kubernetes Cluster"]
        Ingress[Ingress Controller]

        subgraph Services["Services"]
            HTTPService[HTTP Service]
            MCPService[MCP Service]
        end

        subgraph Deployments["Deployments"]
            HTTPPods[HTTP Pods<br/>Replicas: 3]
            MCPPods[MCP Pods<br/>Replicas: 2]
        end

        subgraph Storage["Storage"]
            PVC[Persistent Volume]
            ConfigMap[ConfigMap]
            Secrets[Secrets]
        end
    end

    Users[Users] -.-> Ingress
    Ingress -.-> Services
    Services -.-> Deployments
    Deployments -.-> Storage

deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tinaa-http
  labels:
    app: tinaa
    component: http
spec:
  replicas: 3
  selector:
    matchLabels:
      app: tinaa
      component: http
  template:
    metadata:
      labels:
        app: tinaa
        component: http
    spec:
      containers:
      - name: tinaa
        image: ghcr.io/aj-geddes/tinaa-playwright-msp:latest
        command: ["python", "/app/app/http_server.py"]
        ports:
        - containerPort: 8765
        env:
        - name: PYTHONUNBUFFERED
          value: "1"
        - name: PLAYWRIGHT_BROWSERS_PATH
          value: "/ms-playwright"
        - name: TINAA_MODE
          value: "http"
        resources:
          requests:
            memory: "1Gi"
            cpu: "500m"
          limits:
            memory: "2Gi"
            cpu: "1000m"
        volumeMounts:
        - name: logs
          mountPath: /app/logs
        - name: config
          mountPath: /app/config
      volumes:
      - name: logs
        persistentVolumeClaim:
          claimName: tinaa-logs-pvc
      - name: config
        configMap:
          name: tinaa-config

service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: tinaa-http-service
spec:
  selector:
    app: tinaa
    component: http
  ports:
  - port: 80
    targetPort: 8765
  type: LoadBalancer

Docker Swarm Deployment

Alternative to Kubernetes for simpler orchestration.

version: '3.8'

services:
  tinaa:
    image: ghcr.io/aj-geddes/tinaa-playwright-msp:latest
    deploy:
      replicas: 3
      restart_policy:
        condition: on-failure
      resources:
        limits:
          cpus: '1.0'
          memory: 2G
        reservations:
          cpus: '0.5'
          memory: 1G
    ports:
      - "8765:8765"
    environment:
      - PYTHONUNBUFFERED=1
      - PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
    volumes:
      - tinaa-logs:/app/logs
    networks:
      - tinaa-network

volumes:
  tinaa-logs:
    driver: local

networks:
  tinaa-network:
    driver: overlay

Cloud Provider Deployments

AWS ECS

task-definition.json:

{
  "family": "tinaa-playwright",
  "taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
  "executionRoleArn": "arn:aws:iam::123456789012:role/ecsExecutionRole",
  "networkMode": "awsvpc",
  "containerDefinitions": [
    {
      "name": "tinaa",
      "image": "ghcr.io/aj-geddes/tinaa-playwright-msp:latest",
      "cpu": 1024,
      "memory": 2048,
      "essential": true,
      "portMappings": [
        {
          "containerPort": 8765,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "PYTHONUNBUFFERED",
          "value": "1"
        },
        {
          "name": "PLAYWRIGHT_BROWSERS_PATH",
          "value": "/ms-playwright"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/tinaa",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ],
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "1024",
  "memory": "2048"
}

Google Cloud Run

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: tinaa-playwright
spec:
  template:
    metadata:
      annotations:
        run.googleapis.com/execution-environment: gen2
    spec:
      containerConcurrency: 100
      timeoutSeconds: 300
      containers:
      - image: gcr.io/PROJECT_ID/tinaa-playwright-msp:latest
        ports:
        - containerPort: 8765
        env:
        - name: PYTHONUNBUFFERED
          value: "1"
        - name: PLAYWRIGHT_BROWSERS_PATH
          value: "/ms-playwright"
        resources:
          limits:
            cpu: "2"
            memory: "2Gi"

Azure Container Instances

apiVersion: 2019-12-01
location: eastus
name: tinaa-playwright-container
properties:
  containers:
  - name: tinaa
    properties:
      image: ghcr.io/aj-geddes/tinaa-playwright-msp:latest
      resources:
        requests:
          cpu: 1.0
          memoryInGb: 2.0
      ports:
      - port: 8765
      environmentVariables:
      - name: PYTHONUNBUFFERED
        value: '1'
      - name: PLAYWRIGHT_BROWSERS_PATH
        value: '/ms-playwright'
  osType: Linux
  restartPolicy: Always
  ipAddress:
    type: Public
    ports:
    - protocol: tcp
      port: 8765

Environment Configuration

Environment Variables

Variable Description Default Required
PYTHONUNBUFFERED Disable Python output buffering 1 Yes
PLAYWRIGHT_BROWSERS_PATH Browser installation path /ms-playwright Yes
TINAA_MODE Operation mode (mcp/http) mcp No
LOG_LEVEL Logging level INFO No
MAX_WORKERS Maximum concurrent operations 5 No
TIMEOUT Default operation timeout (seconds) 30 No

Volume Mounts

Path Purpose Persistence
/app/logs Application logs Recommended
/mnt/workspace Workspace for file operations Optional
/app/config Configuration files Optional
/app/screenshots Screenshot storage Optional

Security Considerations

Network Security

%%{init: {
  'theme': 'dark',
  'themeVariables': {
    'fontFamily': 'monospace',
    'primaryBorderColor': '#6BB4DD',
    'primaryColor': '#2D3A4D',
    'primaryTextColor': '#fff',
    'lineColor': '#6BB4DD'
  },
  'themeCSS': '.node rect, .node circle, .node polygon { stroke-width: 2px; stroke-dasharray: 3,3; }'
}}%%
flowchart TD
    Internet[Internet] -.-> WAF[Web Application Firewall]
    WAF -.-> LB[Load Balancer<br/>TLS Termination]

    LB -.-> SG[Security Group<br/>Port 8765 only]

    SG -.-> Container1[TINAA Container 1]
    SG -.-> Container2[TINAA Container 2]
    SG -.-> Container3[TINAA Container 3]

    Container1 -.-> Private[Private Network]
    Container2 -.-> Private
    Container3 -.-> Private

    Private -.-> NAT[NAT Gateway]
    NAT -.-> Internet2[Internet<br/>Outbound Only]

Security Checklist

  • Use TLS/SSL for all external communications
  • Implement authentication (API keys, JWT, OAuth)
  • Enable rate limiting
  • Use least-privilege IAM roles
  • Encrypt sensitive data at rest
  • Regular security updates
  • Network isolation
  • Audit logging

Secrets Management

# Kubernetes Secret
apiVersion: v1
kind: Secret
metadata:
  name: tinaa-secrets
type: Opaque
data:
  api-key: <base64-encoded-api-key>
  test-credentials: <base64-encoded-credentials>

Monitoring and Observability

Metrics to Monitor

  1. Application Metrics
  2. Request rate
  3. Response time
  4. Error rate
  5. Test execution time

  6. Resource Metrics

  7. CPU usage
  8. Memory usage
  9. Disk I/O
  10. Network traffic

  11. Browser Metrics

  12. Browser launch time
  13. Page load time
  14. Screenshot capture time
  15. Browser crashes

Logging Strategy

%%{init: {
  'theme': 'dark',
  'themeVariables': {
    'fontFamily': 'monospace',
    'primaryBorderColor': '#6BB4DD',
    'primaryColor': '#2D3A4D',
    'primaryTextColor': '#fff',
    'lineColor': '#6BB4DD'
  },
  'themeCSS': '.node rect, .node circle, .node polygon { stroke-width: 2px; stroke-dasharray: 3,3; }'
}}%%
flowchart LR
    App[TINAA Application] -.-> LocalLogs[Local Log Files]
    LocalLogs -.-> LogShipper[Log Shipper<br/>Fluentd/Filebeat]

    LogShipper -.-> LogAggregator[Log Aggregator<br/>ELK/Splunk]

    LogAggregator -.-> Dashboard[Dashboard]
    LogAggregator -.-> Alerts[Alert System]

    Alerts -.-> Slack[Slack]
    Alerts -.-> Email[Email]
    Alerts -.-> PagerDuty[PagerDuty]

Health Checks

# Health check endpoint implementation
@app.get("/health")
async def health_check():
    checks = {
        "status": "healthy",
        "timestamp": datetime.utcnow(),
        "checks": {
            "browser": await check_browser_health(),
            "disk_space": check_disk_space(),
            "memory": check_memory_usage()
        }
    }
    return checks

Scaling Considerations

Horizontal Scaling

# Kubernetes HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: tinaa-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: tinaa-http
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Resource Requirements

Component Minimum Recommended Notes
CPU 0.5 cores 1-2 cores Per container
Memory 1 GB 2-4 GB Includes browser overhead
Storage 10 GB 50 GB For logs and screenshots
Network 10 Mbps 100 Mbps Per container

Backup and Recovery

Backup Strategy

  1. Configuration Backup
  2. Version control for config files
  3. Regular snapshots of ConfigMaps/Secrets

  4. Log Backup

  5. Automated log rotation
  6. Archive to object storage
  7. Retention policy (30-90 days)

  8. Screenshot Backup

  9. Compress and archive
  10. Store in object storage
  11. Cleanup policy for old files

Disaster Recovery

%%{init: {
  'theme': 'dark',
  'themeVariables': {
    'fontFamily': 'monospace',
    'primaryBorderColor': '#6BB4DD',
    'primaryColor': '#2D3A4D',
    'primaryTextColor': '#fff',
    'lineColor': '#6BB4DD'
  },
  'themeCSS': '.node rect, .node circle, .node polygon { stroke-width: 2px; stroke-dasharray: 3,3; }'
}}%%
flowchart TD
    Primary[Primary Region] -.-> Backup[Backup Region]

    Primary -.-> Replication[Data Replication]
    Replication -.-> Backup

    Primary -.-> Monitor[Health Monitor]
    Monitor -.-> FailoverTrigger{Failure Detected?}

    FailoverTrigger -.->|Yes| DNSUpdate[Update DNS]
    DNSUpdate -.-> Backup

    FailoverTrigger -.->|No| Continue[Continue Monitoring]
    Continue -.-> Monitor

Maintenance

Update Process

  1. Rolling Updates

    # Kubernetes
    kubectl set image deployment/tinaa-http tinaa=ghcr.io/aj-geddes/tinaa-playwright-msp:v2.0
    
    # Docker Swarm
    docker service update --image ghcr.io/aj-geddes/tinaa-playwright-msp:v2.0 tinaa
    

  2. Blue-Green Deployment

  3. Deploy new version to separate environment
  4. Test thoroughly
  5. Switch traffic via load balancer
  6. Keep old version for rollback

  7. Canary Deployment

  8. Deploy to small percentage of traffic
  9. Monitor metrics
  10. Gradually increase traffic
  11. Full rollout or rollback

Maintenance Windows

  • Schedule during low-traffic periods
  • Notify users in advance
  • Have rollback plan ready
  • Monitor closely after updates