Ask0 logoAsk0

Self-Host

Deploy Ask0 on your own infrastructure for complete control and privacy. Self-hosting guide with Docker, Kubernetes, and cloud options.

Deploy Ask0 on your own infrastructure to maintain complete control over your data, customize the platform, and meet specific compliance requirements.

Why Self-Host?

Benefits

  • Complete Data Control: Your data never leaves your infrastructure
  • Customization: Modify code, add features, integrate with internal systems
  • Compliance: Meet strict regulatory requirements (HIPAA, GDPR, SOC2)
  • Cost Predictability: No usage-based pricing, fixed infrastructure costs
  • Performance: Optimize for your specific use case
  • Air-gapped Deployment: Run in completely isolated environments

Considerations

  • Requires infrastructure management
  • Responsible for updates and maintenance
  • Need to handle scaling and monitoring
  • Security is your responsibility

Architecture Overview

Ask0 consists of three main components:

Components:
  1. Next.js Application:
     - Admin console
     - API server
     - Widget server

  2. Crawler Service:
     - Web scraping
     - Content processing
     - Scheduled updates

  3. PostgreSQL Database:
     - Data storage
     - Vector search (pgvector)
     - Session management

Quick Start with Docker

Clone the Repository

git clone https://github.com/ask0/ask0.git
cd ask0

Configure Environment

Create .env file:

DATABASE_URL=postgresql://ask0:password@postgres:5432/ask0
REDIS_URL=redis://redis:6379

NEXTAUTH_URL=https://your-domain.com
NEXTAUTH_SECRET=generate-random-secret-here

OPENAI_API_KEY=your-openai-key
ANTHROPIC_API_KEY=your-anthropic-key
OLLAMA_URL=http://ollama:11434

STORAGE_TYPE=local  # or s3
S3_BUCKET=ask0-assets
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=your-key
S3_SECRET_ACCESS_KEY=your-secret

ENCRYPTION_KEY=generate-32-byte-key
JWT_SECRET=generate-jwt-secret

Start with Docker Compose

docker-compose up -d

This starts:

  • PostgreSQL with pgvector extension
  • Redis for caching
  • Ask0 application
  • Crawler service
  • Nginx reverse proxy

Access the Application

Open http://localhost:3000 and complete initial setup:

  1. Create admin account
  2. Configure organization
  3. Add your first project
  4. Start adding sources

Production Deployment

Kubernetes Deployment

helm repo add ask0 https://charts.ask0.ai
helm repo update

helm install ask0 ask0/ask0 \
  --namespace ask0 \
  --create-namespace \
  --values values.yaml

Example values.yaml:

replicaCount:
  app: 3
  crawler: 2

postgresql:
  enabled: true
  auth:
    postgresPassword: secure-password
    database: ask0

redis:
  enabled: true
  auth:
    enabled: true
    password: redis-password

ingress:
  enabled: true
  className: nginx
  hosts:
    - host: ask0.company.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: ask0-tls
      hosts:
        - ask0.company.com

resources:
  app:
    requests:
      memory: "512Mi"
      cpu: "500m"
    limits:
      memory: "2Gi"
      cpu: "2000m"

Deploy components individually:

apiVersion: v1
kind: Namespace
metadata:
  name: ask0

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgresql
  namespace: ask0
spec:
  serviceName: postgresql
  replicas: 1
  selector:
    matchLabels:
      app: postgresql
  template:
    metadata:
      labels:
        app: postgresql
    spec:
      containers:
      - name: postgresql
        image: pgvector/pgvector:pg16
        env:
        - name: POSTGRES_DB
          value: ask0
        - name: POSTGRES_USER
          value: ask0
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: postgres-secret
              key: password
        volumeMounts:
        - name: postgres-storage
          mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
  - metadata:
      name: postgres-storage
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 50Gi

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ask0-app
  namespace: ask0
spec:
  replicas: 3
  selector:
    matchLabels:
      app: ask0-app
  template:
    metadata:
      labels:
        app: ask0-app
    spec:
      containers:
      - name: app
        image: ask0/ask0:latest
        ports:
        - containerPort: 3000
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: ask0-secrets
              key: database-url
        livenessProbe:
          httpGet:
            path: /api/health
            port: 3000
          initialDelaySeconds: 30
        readinessProbe:
          httpGet:
            path: /api/ready
            port: 3000
          initialDelaySeconds: 10

Use operators for automated management:

apiVersion: ask0.ai/v1
kind: Ask0Cluster
metadata:
  name: production
  namespace: ask0
spec:
  version: v1.0.0
  replicas:
    app: 3
    crawler: 2
  database:
    type: postgresql
    size: 100Gi
    backup:
      enabled: true
      schedule: "0 2 * * *"
  monitoring:
    enabled: true
    prometheus: true
    grafana: true
  autoscaling:
    enabled: true
    minReplicas: 2
    maxReplicas: 10
    targetCPU: 70

Database Setup

PostgreSQL with pgvector

-- Install pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;

-- Create database
CREATE DATABASE ask0;

-- Connect to ask0 database
\c ask0;

-- Run migrations
-- These are automatically applied on first start

High Availability Setup

PostgreSQL HA:
  Primary: postgres-primary.local
  Replicas:
    - postgres-replica-1.local
    - postgres-replica-2.local
  Backup:
    Type: WAL-G
    Storage: S3
    Schedule: "0 */6 * * *"
  Monitoring:
    - PostgreSQL Exporter
    - PgBouncer for connection pooling

Storage Configuration

STORAGE_TYPE=local
STORAGE_PATH=/var/lib/ask0/storage

Ensure sufficient disk space and backup strategy.

STORAGE_TYPE=s3
S3_ENDPOINT=https://s3.amazonaws.com
S3_BUCKET=ask0-storage
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-key

Works with AWS S3, MinIO, Wasabi, etc.

STORAGE_TYPE=azure
AZURE_STORAGE_ACCOUNT=ask0storage
AZURE_STORAGE_KEY=your-storage-key
AZURE_CONTAINER=ask0
STORAGE_TYPE=gcs
GCS_PROJECT_ID=your-project
GCS_BUCKET=ask0-storage
GCS_KEY_FILE=/path/to/service-account.json

AI Model Configuration

Bring Your Own Model

AI_PROVIDER=openai
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4-turbo-preview
OPENAI_EMBEDDING_MODEL=text-embedding-3-large
AI_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_MODEL=claude-3-opus
AI_PROVIDER=ollama
OLLAMA_URL=http://ollama:11434
OLLAMA_MODEL=llama2:70b
OLLAMA_EMBEDDING_MODEL=all-minilm

Run Ollama:

docker run -d -v ollama:/root/.ollama -p 11434:11434 ollama/ollama
docker exec -it ollama ollama pull llama2:70b
AI_PROVIDER=azure
AZURE_OPENAI_ENDPOINT=https://your-instance.openai.azure.com
AZURE_OPENAI_KEY=your-key
AZURE_OPENAI_DEPLOYMENT=gpt-4
AZURE_OPENAI_API_VERSION=2024-02-15-preview

Implement custom provider:

// providers/custom.js
export class CustomAIProvider {
  async complete(prompt, options) {
    // Your implementation
  }

  async embed(text) {
    // Your implementation
  }
}

Security Hardening

Network Security

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ask0-network-policy
spec:
  podSelector:
    matchLabels:
      app: ask0
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: nginx
    ports:
    - protocol: TCP
      port: 3000
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgresql
    ports:
    - protocol: TCP
      port: 5432

Authentication & SSO

Configure SSO providers:

GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-secret

SAML_ENTRY_POINT=https://idp.company.com/sso
SAML_ISSUER=ask0
SAML_CERT=base64-encoded-cert

LDAP_URL=ldap://ldap.company.com
LDAP_BIND_DN=cn=admin,dc=company,dc=com
LDAP_BIND_PASSWORD=password
LDAP_SEARCH_BASE=dc=company,dc=com

Encryption

ENCRYPTION_AT_REST=true
ENCRYPTION_KEY=32-byte-key-here

TLS_CERT=/path/to/cert.pem
TLS_KEY=/path/to/key.pem
TLS_MIN_VERSION=1.2

POSTGRES_SSL_MODE=require
POSTGRES_SSL_CERT=/path/to/client-cert.pem

Monitoring & Observability

Metrics with Prometheus

scrape_configs:
  - job_name: 'ask0-app'
    static_configs:
      - targets: ['ask0-app:9090']

  - job_name: 'postgresql'
    static_configs:
      - targets: ['postgres-exporter:9187']

Logging with ELK Stack

filebeat.inputs:
- type: container
  paths:
    - /var/lib/docker/containers/*/*.log
  processors:
    - add_kubernetes_metadata:
        host: ${NODE_NAME}
        matchers:
        - logs_path:
            logs_path: "/var/lib/docker/containers/"

output.elasticsearch:
  hosts: ["elasticsearch:9200"]
  index: "ask0-%{+yyyy.MM.dd}"

Tracing with OpenTelemetry

OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
OTEL_SERVICE_NAME=ask0
OTEL_TRACES_ENABLED=true
OTEL_METRICS_ENABLED=true

Backup & Recovery

Automated Backups

apiVersion: batch/v1
kind: CronJob
metadata:
  name: ask0-backup
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: ask0/backup:latest
            command:
            - /bin/bash
            - -c
            - |
              pg_dump $DATABASE_URL > backup.sql
              aws s3 cp backup.sql s3://backups/$(date +%Y%m%d).sql

Disaster Recovery

psql $DATABASE_URL < backup.sql

aws s3 sync s3://backups/files /var/lib/ask0/storage

Scaling Considerations

Horizontal Scaling

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: ask0-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: ask0-app
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Performance Tuning

NODE_OPTIONS="--max-old-space-size=4096"
WORKERS=4

POSTGRES_MAX_CONNECTIONS=200
POSTGRES_SHARED_BUFFERS=2GB
POSTGRES_EFFECTIVE_CACHE_SIZE=6GB

REDIS_MAXMEMORY=2gb
REDIS_MAXMEMORY_POLICY=allkeys-lru

Maintenance

Updates

docker pull ask0/ask0:latest

kubectl set image deployment/ask0-app app=ask0/ask0:v1.2.0 -n ask0

kubectl rollout undo deployment/ask0-app -n ask0

Health Checks

Endpoints:
  - /api/health - Overall health
  - /api/ready - Readiness check
  - /api/metrics - Prometheus metrics
  - /api/status - Detailed status

Important: Always test updates in a staging environment before applying to production. Maintain regular backups and have a rollback plan ready.

Support for Self-Hosted

Community Support

  • GitHub Issues
  • Discord Community
  • Community Forums

Enterprise Support

  • Priority support tickets
  • Installation assistance
  • Custom development
  • SLA agreements

Next Steps