# Custom Documentation Deployment Server

Complete guide for setting up and configuring custom deployment servers for mdBook documentation.

## Overview

VAPORA supports multiple custom deployment methods:

- **SSH/SFTP** — Direct file synchronization to remote servers
- **HTTP** — API-based deployment with REST endpoints
- **Docker** — Container registry deployment
- **AWS S3** — Cloud object storage with CloudFront CDN
- **Google Cloud Storage** — GCS with cache control

## 🔐 Prerequisites

### Repository Secrets Setup

Add these secrets to GitHub repository (**Settings** → **Secrets and variables** → **Actions**):

#### Core Secrets (all methods)
```
DOCS_DEPLOY_METHOD        # ssh, sftp, http, docker, s3, gcs
```

#### SSH/SFTP Method
```
DOCS_DEPLOY_HOST          # docs.your-domain.com
DOCS_DEPLOY_USER          # docs (remote user)
DOCS_DEPLOY_PATH          # /var/www/vapora-docs
DOCS_DEPLOY_KEY           # SSH private key (base64 encoded)
```

#### HTTP Method
```
DOCS_DEPLOY_ENDPOINT      # https://deploy.your-domain.com/api/deploy
DOCS_DEPLOY_TOKEN         # Authentication bearer token
```

#### AWS S3 Method
```
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_DOCS_BUCKET           # vapora-docs-prod
AWS_REGION                # us-east-1
```

#### Google Cloud Storage Method
```
GCS_CREDENTIALS_FILE      # Service account JSON (base64 encoded)
GCS_DOCS_BUCKET           # vapora-docs-prod
```

#### Docker Registry Method
```
DOCKER_REGISTRY           # registry.your-domain.com
DOCKER_USERNAME
DOCKER_PASSWORD
```

---

## 📝 Deployment Script

The deployment script is located at: `.scripts/deploy-docs.sh`

### Script Features

- ✅ Supports 6 deployment methods
- ✅ Pre-flight validation (connectivity, required files)
- ✅ Automatic backups (SSH/SFTP)
- ✅ Post-deployment verification
- ✅ Detailed logging
- ✅ Rollback capability (SSH)

### Configuration Files

```
.scripts/
├── deploy-docs.sh                (Main deployment script)
├── .deploy-config.production     (Production config)
└── .deploy-config.staging        (Staging config)
```

### Running Locally

```bash
# Build locally first
cd docs && mdbook build

# Deploy to production
bash .scripts/deploy-docs.sh production

# Deploy to staging
bash .scripts/deploy-docs.sh staging

# View logs
tail -f /tmp/docs-deploy-*.log
```

---

## 🔧 SSH/SFTP Deployment Setup

### 1. Create Deployment User on Remote Server

```bash
# SSH into your server
ssh user@docs.your-domain.com

# Create docs user
sudo useradd -m -d /var/www/vapora-docs -s /bin/bash docs

# Set up directory
sudo mkdir -p /var/www/vapora-docs/backups
sudo chown -R docs:docs /var/www/vapora-docs
sudo chmod 755 /var/www/vapora-docs
```

### 2. Configure SSH Key

```bash
# On your deployment server
sudo -u docs mkdir -p /var/www/vapora-docs/.ssh
sudo -u docs chmod 700 /var/www/vapora-docs/.ssh

# Create authorized_keys
sudo -u docs touch /var/www/vapora-docs/.ssh/authorized_keys
sudo -u docs chmod 600 /var/www/vapora-docs/.ssh/authorized_keys
```

### 3. Add Public Key to Server

```bash
# Locally, generate key (if needed)
ssh-keygen -t ed25519 -f ~/.ssh/vapora-docs -N ""

# Add to server's authorized_keys
cat ~/.ssh/vapora-docs.pub | ssh user@docs.your-domain.com \
  "sudo -u docs tee -a /var/www/vapora-docs/.ssh/authorized_keys"

# Test connection
ssh -i ~/.ssh/vapora-docs docs@docs.your-domain.com "ls -la"
```

### 4. Add to GitHub Secrets

```bash
# Encode private key (base64)
cat ~/.ssh/vapora-docs | base64 -w0 | pbcopy

# Paste into GitHub Secrets:
# Settings → Secrets → New repository secret
# Name: DOCS_DEPLOY_KEY
# Value: [paste base64-encoded key]
```

### 5. Add SSH Configuration Secrets

```
DOCS_DEPLOY_METHOD    = ssh
DOCS_DEPLOY_HOST      = docs.your-domain.com
DOCS_DEPLOY_USER      = docs
DOCS_DEPLOY_PATH      = /var/www/vapora-docs
DOCS_DEPLOY_KEY       = [base64-encoded private key]
```

### 6. Set Up Web Server

```bash
# On remote server, configure nginx
sudo tee /etc/nginx/sites-available/vapora-docs > /dev/null << 'EOF'
server {
    listen 80;
    server_name docs.your-domain.com;
    root /var/www/vapora-docs/docs;

    location / {
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    location ~ \.(js|css|fonts|images)$ {
        expires 1h;
        add_header Cache-Control "public, immutable";
    }
}
EOF

# Enable site
sudo ln -s /etc/nginx/sites-available/vapora-docs \
  /etc/nginx/sites-enabled/vapora-docs

# Test and reload
sudo nginx -t && sudo systemctl reload nginx
```

---

## 🌐 HTTP API Deployment Setup

### 1. Create Deployment Endpoint

Implement an HTTP endpoint that accepts deployments:

```python
# Example: Flask deployment API
from flask import Flask, request, jsonify
import tarfile
import os
from pathlib import Path

app = Flask(__name__)

DOCS_PATH = "/var/www/vapora-docs"
BACKUP_PATH = f"{DOCS_PATH}/backups"

@app.route('/api/deploy', methods=['POST'])
def deploy():
    # Verify token
    token = request.headers.get('Authorization', '').replace('Bearer ', '')
    if not verify_token(token):
        return {'error': 'Unauthorized'}, 401

    # Check for archive
    if 'archive' not in request.files:
        return {'error': 'No archive provided'}, 400

    archive = request.files['archive']

    # Create backup
    os.makedirs(BACKUP_PATH, exist_ok=True)
    backup_name = f"backup_{int(time.time())}"
    os.rename(f"{DOCS_PATH}/current",
              f"{BACKUP_PATH}/{backup_name}")

    # Extract archive
    os.makedirs(f"{DOCS_PATH}/current", exist_ok=True)
    with tarfile.open(fileobj=archive) as tar:
        tar.extractall(f"{DOCS_PATH}/current")

    # Update symlink
    os.symlink(f"{DOCS_PATH}/current", f"{DOCS_PATH}/docs")

    return {'status': 'deployed', 'backup': backup_name}, 200

@app.route('/health', methods=['GET'])
def health():
    return {'status': 'healthy'}, 200

def verify_token(token):
    # Implement your token verification
    return token == os.getenv('DEPLOY_TOKEN')

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000)
```

### 2. Configure Nginx Reverse Proxy

```nginx
upstream deploy_api {
    server 127.0.0.1:5000;
}

server {
    listen 443 ssl http2;
    server_name deploy.your-domain.com;

    ssl_certificate /etc/letsencrypt/live/deploy.your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/deploy.your-domain.com/privkey.pem;

    # API endpoint
    location /api/deploy {
        proxy_pass http://deploy_api;
        client_max_body_size 100M;
    }

    # Health check
    location /health {
        proxy_pass http://deploy_api;
    }
}
```

### 3. Add GitHub Secrets

```
DOCS_DEPLOY_METHOD      = http
DOCS_DEPLOY_ENDPOINT    = https://deploy.your-domain.com/api/deploy
DOCS_DEPLOY_TOKEN       = your-secure-token
```

---

## ☁️ AWS S3 Deployment Setup

### 1. Create S3 Bucket and IAM User

```bash
# Create bucket
aws s3 mb s3://vapora-docs-prod --region us-east-1

# Create IAM user
aws iam create-user --user-name vapora-docs-deployer

# Create access key
aws iam create-access-key --user-name vapora-docs-deployer

# Create policy
cat > /tmp/s3-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::vapora-docs-prod",
        "arn:aws:s3:::vapora-docs-prod/*"
      ]
    }
  ]
}
EOF

# Attach policy
aws iam put-user-policy \
  --user-name vapora-docs-deployer \
  --policy-name S3Access \
  --policy-document file:///tmp/s3-policy.json
```

### 2. Configure CloudFront (Optional)

```bash
# Create distribution
aws cloudfront create-distribution \
  --origin-domain-name vapora-docs-prod.s3.amazonaws.com \
  --default-root-object index.html
```

### 3. Add GitHub Secrets

```
DOCS_DEPLOY_METHOD      = s3
AWS_ACCESS_KEY_ID       = AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY   = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
AWS_DOCS_BUCKET         = vapora-docs-prod
AWS_REGION              = us-east-1
```

---

## 🐳 Docker Registry Deployment Setup

### 1. Create Docker Registry

```bash
# Using Docker Registry (self-hosted)
docker run -d \
  -p 5000:5000 \
  --restart always \
  --name registry \
  -e REGISTRY_STORAGE_DELETE_ENABLED=true \
  registry:2

# Or use managed: AWS ECR, Docker Hub, etc.
```

### 2. Configure Registry Authentication

```bash
# Create credentials
echo "username:$(openssl passwd -crypt password)" > /auth/htpasswd

# Docker login
docker login registry.your-domain.com \
  -u username -p password
```

### 3. Add GitHub Secrets

```
DOCS_DEPLOY_METHOD      = docker
DOCKER_REGISTRY         = registry.your-domain.com
DOCKER_USERNAME         = username
DOCKER_PASSWORD         = password
```

---

## 🔔 Webhooks & Notifications

### Slack Notification

Add webhook URL to secrets:

```
NOTIFICATION_WEBHOOK = https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXX
```

Workflow sends JSON payload:

```json
{
  "status": "success",
  "environment": "production",
  "commit": "abc123...",
  "branch": "main",
  "timestamp": "2026-01-12T14:30:00Z",
  "run_url": "https://github.com/vapora-platform/vapora/actions/runs/123"
}
```

### Custom Webhook Handler

```python
@app.route('/webhook/deployment', methods=['POST'])
def deployment_webhook():
    data = request.json

    if data['status'] == 'success':
        send_slack_message(f"✅ Docs deployed: {data['commit']}")
    else:
        send_slack_message(f"❌ Deployment failed: {data['commit']}")

    return {'ok': True}
```

---

## 🔄 Deployment Workflow

### Automatic Deployment Flow

```
Push to main (docs/ changes)
    ↓
mdBook Build & Deploy Workflow
    ├─ Build (2-3s)
    ├─ Quality Check
    └─ Upload Artifact
    ↓
mdBook Publish Workflow (triggered)
    ├─ Download Artifact
    ├─ Deploy to Custom Server
    │  ├─ Pre-flight Checks
    │  ├─ Deployment Method
    │  │  ├─ SSH: rsync files + backup
    │  │  ├─ HTTP: upload tarball
    │  │  ├─ S3: sync to bucket
    │  │  └─ Docker: push image
    │  └─ Post-deployment Verify
    ├─ Create Deployment Record
    └─ Send Notifications
    ↓
Documentation Live
```

### Manual Deployment

```bash
# Local build
cd docs && mdbook build

# Deploy using script
bash .scripts/deploy-docs.sh production

# Or specific environment
bash .scripts/deploy-docs.sh staging
```

---

## 🆘 Troubleshooting

### SSH Deployment Fails

**Error**: `Permission denied (publickey)`

**Fix**:
```bash
# Verify key is in authorized_keys
cat ~/.ssh/vapora-docs.pub | ssh user@server \
  "sudo -u docs cat >> /var/www/vapora-docs/.ssh/authorized_keys"

# Test connection
ssh -i ~/.ssh/vapora-docs -v docs@server.com
```

### HTTP Deployment Fails

**Error**: `HTTP 401 Unauthorized`

**Fix**:
- Verify token in GitHub Secrets matches server
- Check HTTPS certificate validity
- Verify endpoint is reachable

```bash
curl -H "Authorization: Bearer $TOKEN" https://deploy.server.com/health
```

### S3 Deployment Fails

**Error**: `NoSuchBucket`

**Fix**:
- Verify bucket name in secrets
- Check IAM policy allows the action
- Verify AWS credentials

```bash
aws s3 ls s3://vapora-docs-prod/
```

### Docker Deployment Fails

**Error**: `unauthorized: authentication required`

**Fix**:
- Verify credentials in secrets
- Test Docker login locally

```bash
docker login registry.your-domain.com
```

---

## 📊 Deployment Configuration Reference

### Production Template

```bash
# .deploy-config.production

DEPLOY_METHOD="ssh"
DEPLOY_HOST="docs.vapora.io"
DEPLOY_USER="docs"
DEPLOY_PATH="/var/www/vapora-docs"
BACKUP_RETENTION_DAYS=30
NOTIFY_ON_SUCCESS="true"
NOTIFY_ON_FAILURE="true"
```

### Staging Template

```bash
# .deploy-config.staging

DEPLOY_METHOD="ssh"
DEPLOY_HOST="staging-docs.vapora.io"
DEPLOY_USER="docs-staging"
DEPLOY_PATH="/var/www/vapora-docs-staging"
BACKUP_RETENTION_DAYS=7
NOTIFY_ON_SUCCESS="false"
NOTIFY_ON_FAILURE="true"
```

---

## ✅ Verification Checklist

- [ ] SSH/SFTP user created and configured
- [ ] SSH keys generated and added to server
- [ ] Web server (nginx/apache) configured
- [ ] GitHub secrets added for deployment method
- [ ] Test push to main with docs/ changes
- [ ] Monitor Actions tab for workflow
- [ ] Verify deployment completed
- [ ] Check documentation site
- [ ] Test rollback procedure (if applicable)
- [ ] Set up monitoring/alerts

---

## 📚 Additional Resources

- [AWS S3 Documentation](https://docs.aws.amazon.com/s3/)
- [Google Cloud Storage](https://cloud.google.com/storage/docs)
- [Docker Registry](https://docs.docker.com/registry/)
- [GitHub Actions Documentation](https://docs.github.com/en/actions)

---

**Last Updated**: 2026-01-12
**Status**: ✅ Production Ready

For deployment script details, see: `.scripts/deploy-docs.sh`
