Skip to content

Service Renaming Plan

Overview

Consolidate cbintel services under a single systemd unit and rename domains for clarity.

Current State

Domain Port Service Purpose
intel.nominate.ai 32203 cbcluster.service VPN cluster management
jobs.nominate.ai 9003 cbjobs.service Async job processing

Target State

Domain Port Service Purpose
network.nominate.ai 32203 cbintel.service VPN cluster management
intel.nominate.ai 9003 cbintel.service Async job processing (crawl, lazarus, vectl, screenshots)

Changes Required

1. DNS (No Changes Needed)

Both domains already resolve via wildcard:

network.nominate.ai → 104.11.127.142 ✓
intel.nominate.ai   → 127.0.0.1      ✓ (will use wildcard cert)

2. Systemd Service

Create: /etc/systemd/system/cbintel.service

[Unit]
Description=cbintel - Intelligence Gathering Platform
After=network.target redis.service

[Service]
Type=forking
User=bisenbek
Group=bisenbek
WorkingDirectory=/home/bisenbek/projects/nominate/cbintel
EnvironmentFile=/home/bisenbek/projects/nominate/cbintel/.env
Environment="PATH=/home/bisenbek/.pyenv/versions/nominates/bin:/usr/local/bin:/usr/bin:/bin"

# Start both services
ExecStart=/home/bisenbek/.pyenv/versions/nominates/bin/python -m cbintel.service start
ExecStop=/home/bisenbek/.pyenv/versions/nominates/bin/python -m cbintel.service stop
ExecReload=/home/bisenbek/.pyenv/versions/nominates/bin/python -m cbintel.service reload

Restart=always
RestartSec=5
SyslogIdentifier=cbintel
StandardOutput=journal
StandardError=journal

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/tmp /var/lib/vpn-banks
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Alternative: Use systemd template or simple script to run both uvicorn instances.

Remove: - /etc/systemd/system/cbjobs.service - /etc/systemd/system/cbcluster.service

3. NGINX Configuration

3.1 Create network.nominate.ai.conf

# VPN Network Cluster API - network.nominate.ai
# Geographic VPN routing and cluster management
# API: 32203

server {
    server_name network.nominate.ai;

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/wildcard.nominate.ai/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/wildcard.nominate.ai/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # PIN Gate Auth
    include snippets/pin-gate-auth.conf;

    # Logging
    access_log /var/log/nginx/network.nominate.ai.access.log;
    error_log /var/log/nginx/network.nominate.ai.error.log;

    location / {
        auth_request /internal/auth/verify;
        error_page 401 = @pin_redirect;

        proxy_pass http://127.0.0.1:32203;
        proxy_http_version 1.1;
        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;
    }

    # API docs
    location /docs { proxy_pass http://127.0.0.1:32203; proxy_set_header Host $host; }
    location /redoc { proxy_pass http://127.0.0.1:32203; proxy_set_header Host $host; }
    location /openapi.json { proxy_pass http://127.0.0.1:32203; proxy_set_header Host $host; }
}

server {
    listen 80;
    server_name network.nominate.ai;
    return 301 https://$host$request_uri;
}

3.2 Update intel.nominate.ai.conf

# cbintel Jobs API - intel.nominate.ai
# Async job processing: crawl, lazarus, vectl, screenshots
# API: 9003

server {
    server_name intel.nominate.ai;

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/wildcard.nominate.ai/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/wildcard.nominate.ai/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # PIN Gate Auth
    include snippets/pin-gate-auth.conf;

    # Logging
    access_log /var/log/nginx/intel.nominate.ai.access.log;
    error_log /var/log/nginx/intel.nominate.ai.error.log;

    location / {
        auth_request /internal/auth/verify;
        error_page 401 = @pin_redirect;

        proxy_pass http://127.0.0.1:9003;
        proxy_http_version 1.1;
        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;

        # Longer timeouts for long-running jobs
        proxy_read_timeout 300s;
        proxy_connect_timeout 60s;
    }

    # API docs
    location /docs { proxy_pass http://127.0.0.1:9003; proxy_set_header Host $host; }
    location /redoc { proxy_pass http://127.0.0.1:9003; proxy_set_header Host $host; }
    location /openapi.json { proxy_pass http://127.0.0.1:9003; proxy_set_header Host $host; }
}

server {
    listen 80;
    server_name intel.nominate.ai;
    return 301 https://$host$request_uri;
}

3.3 Remove

  • /etc/nginx/sites-enabled/jobs.nominate.ai.conf

4. FastAPI Application Updates

4.1 Jobs API (src/cbintel/jobs/service.py)

app = FastAPI(
    title="cbintel Intelligence API",
    description="""
    Async job processing for intelligence gathering operations.

    ## Job Types
    - **crawl** - AI-powered web crawling with iterative discovery
    - **lazarus** - Historical web archive retrieval
    - **vectl** - Vector embeddings and semantic search
    - **screenshots** - Browser automation and PDF generation
    - **fetch** - Synchronous URL fetching with parsing

    ## Geographic Routing
    All jobs support `geo` parameter for VPN routing (e.g., "us:ca", "de").
    """,
    version="1.0.0",
    docs_url="/docs",
    redoc_url="/redoc",
    lifespan=lifespan,
)

4.2 Cluster API (src/cbintel/cluster/main.py)

app = FastAPI(
    title="cbintel Network API",
    description="""
    VPN cluster management for geographic routing.

    ## Features
    - Create isolated VPN banks by geography (country, state, type)
    - Control OpenWRT workers (VPN, proxy, deployment)
    - Monitor cluster health and HAProxy statistics
    - Transactional configuration management
    """,
    version="1.0.0",
    docs_url="/docs",
    redoc_url="/redoc",
    lifespan=lifespan,
)

5. Service Runner Module

Create: src/cbintel/service.py

"""cbintel service runner - manages both API processes."""

import subprocess
import sys
from pathlib import Path

SERVICES = {
    "intel": {
        "module": "cbintel.jobs.service:app",
        "port": 9003,
        "host": "127.0.0.1",
    },
    "network": {
        "module": "cbintel.cluster.main:app",
        "port": 32203,
        "host": "127.0.0.1",
    },
}

def start():
    """Start all services."""
    for name, config in SERVICES.items():
        cmd = [
            sys.executable, "-m", "uvicorn",
            config["module"],
            "--host", config["host"],
            "--port", str(config["port"]),
        ]
        subprocess.Popen(cmd)
        print(f"Started {name} on port {config['port']}")

def stop():
    """Stop all services."""
    # Kill by port
    for config in SERVICES.values():
        subprocess.run(["fuser", "-k", f"{config['port']}/tcp"], capture_output=True)

if __name__ == "__main__":
    if len(sys.argv) > 1:
        if sys.argv[1] == "start":
            start()
        elif sys.argv[1] == "stop":
            stop()

6. Documentation Updates

6.1 README.md

Update Services section:

## Services

| Service | Domain | Port | Description |
|---------|--------|------|-------------|
| cbintel | intel.nominate.ai | 9003 | Jobs API (crawl, lazarus, vectl, screenshots) |
| cbintel | network.nominate.ai | 32203 | VPN cluster management |

```bash
# Start cbintel (both services)
sudo systemctl start cbintel

# Check status
sudo systemctl status cbintel
#### 6.2 docs/index.md

Update Services table:
```markdown
## Services

| Service | Domain | Port | Description |
|---------|--------|------|-------------|
| intel | intel.nominate.ai | 9003 | Jobs API - async job processing |
| network | network.nominate.ai | 32203 | VPN cluster management |

7. Client Updates

Update cbintel-client default base URL if hardcoded.


Execution Order

Phase 1: Code Changes (No Downtime)

  1. Update FastAPI titles/descriptions
  2. Create service runner module
  3. Update documentation
  4. Commit and push

Phase 2: Infrastructure (Brief Downtime ~2 min)

  1. Create new NGINX configs
  2. Create cbintel.service
  3. Stop old services: sudo systemctl stop cbjobs cbcluster
  4. Enable new service: sudo systemctl enable cbintel
  5. Reload NGINX: sudo nginx -t && sudo systemctl reload nginx
  6. Start new service: sudo systemctl start cbintel
  7. Remove old configs and services

Phase 3: Verification

  1. Test https://intel.nominate.ai/docs
  2. Test https://network.nominate.ai/docs
  3. Verify job submission works
  4. Verify cluster API works
  5. Check logs: journalctl -u cbintel -f

Rollback Plan

If issues arise: 1. Stop cbintel: sudo systemctl stop cbintel 2. Restore old NGINX configs 3. Start old services: sudo systemctl start cbjobs cbcluster 4. Reload NGINX

Keep old service files for 7 days before deletion.