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:
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)¶
- Update FastAPI titles/descriptions
- Create service runner module
- Update documentation
- Commit and push
Phase 2: Infrastructure (Brief Downtime ~2 min)¶
- Create new NGINX configs
- Create
cbintel.service - Stop old services:
sudo systemctl stop cbjobs cbcluster - Enable new service:
sudo systemctl enable cbintel - Reload NGINX:
sudo nginx -t && sudo systemctl reload nginx - Start new service:
sudo systemctl start cbintel - Remove old configs and services
Phase 3: Verification¶
- Test https://intel.nominate.ai/docs
- Test https://network.nominate.ai/docs
- Verify job submission works
- Verify cluster API works
- 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.