Skip to content

Deployment

dev-mondoshawan edited this page Apr 29, 2026 · 5 revisions

Server Deployment Guide


Prerequisites

Requirement Minimum Recommended
OS Ubuntu 22.04 LTS Ubuntu 22.04 LTS
Python 3.10 3.11 or 3.12
RAM 2 GB 4 GB+
Disk 20 GB 40 GB+
CPU 2 cores 4 cores+

Required software:

  • Python 3.10+ with venv
  • nginx
  • certbot (Let's Encrypt)
  • git

Docker Deployment

Docker is the recommended deployment method for CI environments, local development, and any host where you prefer not to install external tools (Foundry, Slither, Mythril, Aderyn, Medusa) directly. The multi-stage Dockerfile bundles the complete 21-analyzer stack on Python 3.12 (image size ~1.5 GB).

Building the Image

cd sentinel-engine
docker build -t counterscarp-engine:5.1.0 .

Running with docker-compose

The project's docker-compose.yml defines four services:

Service Purpose
counterscarp Main audit service (all 21 analyzers)
doctor Diagnostics / health check
heuristic Heuristic-only scan (no external tools required)
symbolic Mythril symbolic execution only
# Full audit
docker compose run --rm counterscarp scan /scan/MyContract.sol

# Health check
docker compose run --rm doctor

# Heuristic-only scan
docker compose run --rm heuristic scan /scan/MyContract.sol

# Symbolic execution only
docker compose run --rm symbolic scan /scan/MyContract.sol

Volume Mounts

Two mount points are defined for contract input and report output:

Mount Purpose
/scan Mount your contract source directory here
/output Audit reports are written here
docker compose run --rm \
  -v /path/to/contracts:/scan \
  -v /path/to/reports:/output \
  counterscarp scan /scan/MyContract.sol

Resource Limits

Pre-configured in docker-compose.yml under deploy.resources:

Resource Limit
CPU 4.0 cores
Memory 4 GB

Adjust these values in the deploy.resources section of docker-compose.yml to match your host's capacity.

Health Checks

All services include an automatic health check that runs counterscarp --doctor:

Setting Value
Interval 60s
Timeout 30s
Retries 3

Use docker compose ps to view current health status for each service.

Environment Variables

Variable Description
COUNTERSCARP_PRO_LICENSE Set your Pro license key to enable premium features
docker compose run --rm \
  -e COUNTERSCARP_PRO_LICENSE=your-key \
  counterscarp scan /scan/MyContract.sol

For persistent configuration, add COUNTERSCARP_PRO_LICENSE to a .env file in the project root — Docker Compose picks it up automatically.

Production Considerations

# Run the main service in the background
docker compose up -d counterscarp

# Follow live logs
docker compose logs -f counterscarp

# Stop all services
docker compose down
  • The foundry-cache named volume persists the Foundry compilation cache across runs, significantly reducing re-compilation time.
  • Bind-mount a dedicated output directory so reports survive container restarts.
  • Rotate or prune the foundry-cache volume periodically if disk space is constrained: docker volume rm sentinel-engine_foundry-cache.

Automated Setup

The deploy/setup.sh script automates the full deployment. Run as root:

sudo bash deploy/setup.sh

What the script does (8 steps)

Step Action
1/8 Creates service user counterscarp (no login shell)
2/8 Clones/updates repository to /opt/counterscarp-engine
3/8 Creates Python venv and installs counterscarp-engine[web]
4/8 Creates uploads/ and results/ directories
5/8 Sets ownership to counterscarp:counterscarp
6/8 Installs nginx config and reloads nginx
7/8 Obtains SSL certificate via certbot (if not already present)
8/8 Installs systemd service and starts it

Manual Deployment

If you prefer to deploy manually:

# 1. Create service user
useradd -r -s /bin/false counterscarp

# 2. Setup directory (choose one method)

# Method A: Install from PyPI (recommended for production)
mkdir -p /opt/counterscarp-engine
cd /opt/counterscarp-engine
python3 -m venv venv
./venv/bin/pip install --upgrade pip
./venv/bin/pip install "counterscarp-engine[web]"

# Method B: Clone from GitHub (for development/customization)
# mkdir -p /opt/counterscarp-engine
# cd /opt/counterscarp-engine
# git clone https://github.com/RunTimeAdmin/counterscarp.git .
# python3 -m venv venv
# ./venv/bin/pip install --upgrade pip
# ./venv/bin/pip install -e ".[web]"

# 3. Create directories
mkdir -p /opt/counterscarp-engine/uploads
mkdir -p /opt/counterscarp-engine/results

# 4. Set ownership
chown -R counterscarp:counterscarp /opt/counterscarp-engine

# 5. Configure nginx
cp deploy/nginx-counterscarp.conf /etc/nginx/sites-available/counterscarp
ln -sf /etc/nginx/sites-available/counterscarp /etc/nginx/sites-enabled/counterscarp
nginx -t && systemctl reload nginx

# 6. SSL certificate
certbot certonly --nginx -d app.counterscarp.io --non-interactive --agree-tos -m your@email.com

# 7. Start service
cp deploy/counterscarp-engine.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable counterscarp-engine
systemctl start counterscarp-engine

Nginx Configuration

The nginx configuration is located at deploy/nginx-counterscarp.conf:

server {
    listen 80;
    listen [::]:80;
    server_name app.counterscarp.io;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name app.counterscarp.io;

    ssl_certificate /etc/letsencrypt/live/app.counterscarp.io/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.counterscarp.io/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    client_max_body_size 10M;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    location / {
        proxy_pass http://127.0.0.1:8001;
        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;
        proxy_read_timeout 120s;
        proxy_connect_timeout 10s;
    }

    location /static/ {
        alias /opt/counterscarp-engine/webapp/static/;
        expires 7d;
        add_header Cache-Control "public, immutable";
    }
}

Key Configuration Points

  • Port 8001 — The app runs on port 8001 (not 8000) to avoid conflicts
  • client_max_body_size 10M — Matches the web app's 10 MB upload limit
  • Security headers — X-Frame-Options, X-Content-Type-Options, XSS-Protection, Referrer-Policy
  • Static file caching/static/ served directly by nginx with 7-day cache
  • Proxy timeouts — 120s read timeout to handle long-running analyses

Warning: If you change the domain, update both the server_name and the SSL certificate paths.


SSL/Let's Encrypt

Initial Certificate

sudo certbot certonly --nginx -d app.counterscarp.io --non-interactive --agree-tos -m your@email.com

Certificate Renewal

Certbot installs a systemd timer for automatic renewal. Verify it's active:

systemctl list-timers | grep certbot

Manual renewal test:

sudo certbot renew --dry-run

Certificate Files

File Path
Full chain /etc/letsencrypt/live/app.counterscarp.io/fullchain.pem
Private key /etc/letsencrypt/live/app.counterscarp.io/privkey.pem
SSL options /etc/letsencrypt/options-ssl-nginx.conf
DH params /etc/letsencrypt/ssl-dhparams.pem

Systemd Service Management

The service unit file is at deploy/counterscarp-engine.service:

[Unit]
Description=Counterscarp Engine Web Application
After=network.target

[Service]
Type=exec
User=counterscarp
Group=counterscarp
WorkingDirectory=/opt/counterscarp-engine
ExecStart=/opt/counterscarp-engine/venv/bin/uvicorn webapp.main:app --host 127.0.0.1 --port 8001 --workers 4
Restart=always
RestartSec=5
Environment=PYTHONUNBUFFERED=1
Environment=COUNTERSCARP_UPLOAD_DIR=/opt/counterscarp-engine/uploads
Environment=COUNTERSCARP_RESULTS_DIR=/opt/counterscarp-engine/results

[Install]
WantedBy=multi-user.target

Service Commands

# Start the service
sudo systemctl start counterscarp-engine

# Stop the service
sudo systemctl stop counterscarp-engine

# Restart the service
sudo systemctl restart counterscarp-engine

# Check status
sudo systemctl status counterscarp-engine

# Enable auto-start on boot
sudo systemctl enable counterscarp-engine

# View live logs
sudo journalctl -u counterscarp-engine -f

# View recent logs
sudo journalctl -u counterscarp-engine -n 50

Note: After modifying the unit file, always run systemctl daemon-reload before restarting.


Stripe Environment Variables

Important: Stripe API keys and webhook secrets must be set via systemd override, never in code or version-controlled files.

Create Override File

sudo systemctl edit counterscarp-engine

Add the following:

[Service]
Environment="STRIPE_SECRET_KEY=sk_live_..."
Environment="STRIPE_WEBHOOK_SECRET=whsec_..."
Environment="STRIPE_PUBLISHABLE_KEY=pk_live_..."

Reload and Restart

sudo systemctl daemon-reload
sudo systemctl restart counterscarp-engine

Verify Environment

sudo systemctl show counterscarp-engine --property=Environment

Security Notes:

  • Never commit Stripe keys to Git (GitHub Push Protection will block)
  • Use sk_live_ for production, sk_test_ for testing
  • Webhook secrets are different for test and live modes
  • Rotate keys immediately if accidentally exposed

Update Procedures

Quick Update

Use the deploy/update.sh script:

sudo bash deploy/update.sh

This script:

  1. Pulls latest code from main
  2. Reinstalls Python dependencies
  3. Fixes ownership
  4. Restarts the service
  5. Verifies health

Manual Update

cd /opt/counterscarp-engine

# Method A: Update from PyPI (if installed via pip)
./venv/bin/pip install --upgrade "counterscarp-engine[web]"

# Method B: Update from Git (if cloned)
# git pull origin main
# ./venv/bin/pip install -e ".[web]" --quiet

chown -R counterscarp:counterscarp /opt/counterscarp-engine
sudo systemctl restart counterscarp-engine

Verify Update

curl -s http://127.0.0.1:8001/health | python3 -m json.tool

Monitoring

Health Check

curl http://127.0.0.1:8001/health

Expected response:

{"status": "ok", "timestamp": "2024-01-15T10:30:00.000000"}

Common Issues

Symptom Likely Cause Fix
502 Bad Gateway App not running systemctl restart counterscarp-engine
413 Request Entity Too Large File exceeds 10 MB Increase client_max_body_size in nginx config
SSL errors Certificate expired certbot renew && systemctl reload nginx
Slow responses Analysis taking long Increase proxy_read_timeout in nginx
Upload fails Permissions wrong chown -R counterscarp:counterscarp /opt/counterscarp-engine/uploads

Check Disk Space

df -h /opt/counterscarp-engine

Uploads and results accumulate over time. Consider setting up a cron job to clean old audit data:

# Remove results older than 30 days
find /opt/counterscarp-engine/results -type d -mtime +30 -exec rm -rf {} +
find /opt/counterscarp-engine/uploads -type d -mtime +30 -exec rm -rf {} +

Check Running Processes

ps aux | grep uvicorn
ss -tlnp | grep 8001

Log Management

Application Logs

# Follow live logs
sudo journalctl -u counterscarp-engine -f

# Last 100 lines
sudo journalctl -u counterscarp-engine -n 100

# Logs since yesterday
sudo journalctl -u counterscarp-engine --since yesterday

# Logs with specific severity
sudo journalctl -u counterscarp-engine -p err

Nginx Logs

# Access log
sudo tail -f /var/log/nginx/access.log

# Error log
sudo tail -f /var/log/nginx/error.log

Log Rotation

Journal logs are auto-rotated by systemd. Configure retention:

# Keep only last 7 days of journal logs
sudo journalctl --vacuum-time=7d

Nginx logs are rotated by logrotate (installed by default on Ubuntu).


Counterscarp Engine • counterscarp.io

Clone this wiki locally