Documentation
Guides
Self-Hosted Setup

Self-Hosted Setup

⚠️

Looking for the quickest way to get started? Try NAT Cloud — sign up at app.nat-testing.io (opens in a new tab) for instant access with no infrastructure setup. Come back here when you need to run NAT entirely on your own infrastructure.

NAT can be deployed entirely on your own infrastructure. No data leaves your network — scans run locally, reports are stored locally, and the dashboard is served from your own server.

Self-hosting is available on all NAT plans. The self-hosted engine is installed via pip install nat-engine and includes the full scanning engine, REST API, and web dashboard.

Overview

A self-hosted NAT deployment consists of:

  1. NAT Engine — the core scanning process (installed via pip or Docker)
  2. NAT Server — a local web server that exposes the REST API and dashboard
  3. (Optional) Reverse proxy — nginx or Caddy for TLS termination and external access

Prerequisites

RequirementValue
Python3.10 or later
RAM2 GB minimum, 4 GB recommended
Disk5 GB for engine + scan data storage
OSLinux (Ubuntu 20.04+, Debian 11+), macOS 12+
NetworkOutbound access to APIs under test

Installation

Install Python 3.10+

# Ubuntu/Debian
sudo apt update && sudo apt install python3 python3-pip python3-venv
 
# macOS
brew install python@3.11

Verify:

python3 --version  # Python 3.11.x

Create a virtual environment (recommended)

python3 -m venv /opt/nat-engine
source /opt/nat-engine/bin/activate

Install nat-engine

pip install nat-engine

Verify:

nat --version
# nat-engine 1.x.x

Generate a secret key

python3 -c "import secrets; print(secrets.token_hex(32))"

Save this as your NAT_SECRET_KEY — it signs session tokens for the dashboard.

Create the configuration file

mkdir -p /etc/nat
cat > /etc/nat/config.yaml << 'EOF'
server:
  host: 127.0.0.1   # Change to 0.0.0.0 for external access
  port: 8080
  data_dir: /var/lib/nat/data
 
log:
  level: info
  file: /var/log/nat/nat.log
EOF

Start the server

NAT_SECRET_KEY="your-secret-key" nat server start \
  --config /etc/nat/config.yaml

The dashboard is now available at http://localhost:8080.

After installation, run nat setup for an interactive wizard that configures your mode, database, authentication, and exporters in one step. Then run nat doctor to validate that everything is set up correctly before your first scan.

Running as a systemd service (Linux)

For production Linux deployments, run NAT as a systemd service:

Create a system user

sudo useradd --system --no-create-home --shell /bin/false nat
sudo mkdir -p /var/lib/nat/data /var/log/nat
sudo chown nat:nat /var/lib/nat /var/log/nat

Install into a system-wide virtualenv

sudo python3 -m venv /opt/nat-engine
sudo /opt/nat-engine/bin/pip install nat-engine

Create the systemd unit file

sudo cat > /etc/systemd/system/nat.service << 'EOF'
[Unit]
Description=NAT API Security Engine
After=network.target
 
[Service]
Type=simple
User=nat
Group=nat
WorkingDirectory=/var/lib/nat
ExecStart=/opt/nat-engine/bin/nat server start --config /etc/nat/config.yaml
Restart=always
RestartSec=5
EnvironmentFile=/etc/nat/environment
 
[Install]
WantedBy=multi-user.target
EOF

Create the environment file

sudo cat > /etc/nat/environment << 'EOF'
NAT_SECRET_KEY=your-secret-key-here
NAT_LOG_LEVEL=info
EOF
 
sudo chmod 600 /etc/nat/environment

Enable and start the service

sudo systemctl daemon-reload
sudo systemctl enable nat
sudo systemctl start nat
sudo systemctl status nat

TLS with a reverse proxy

For production use, put NAT behind nginx or Caddy for TLS termination.

# /etc/nginx/sites-available/nat
server {
    listen 443 ssl http2;
    server_name docs-api.example.com;
 
    ssl_certificate     /etc/ssl/certs/nat.crt;
    ssl_certificate_key /etc/ssl/private/nat.key;
 
    location / {
        proxy_pass         http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection "upgrade";
        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;
    }
}
 
server {
    listen 80;
    server_name docs-api.example.com;
    return 301 https://$host$request_uri;
}

Upgrading nat-engine

# In your virtualenv
source /opt/nat-engine/bin/activate
pip install --upgrade nat-engine
 
# Restart the service
sudo systemctl restart nat

If the upgrade includes database schema changes, run nat upgrade --migrate (or alembic upgrade head manually) before restarting the service. nat doctor will warn you if pending migrations are detected.

Configuration reference

# /etc/nat/config.yaml — all options with defaults
server:
  host: 127.0.0.1
  port: 8080
  data_dir: /var/lib/nat/data
  max_concurrent_scans: 3
 
scan:
  concurrency: 5
  timeout: 30
  depth: 3
 
log:
  level: info          # debug | info | warn | error
  file: ""             # empty = stdout only
  max_size_mb: 100
  max_backups: 5

Environment variables

All settings can be overridden via environment variables:

VariableDescription
NAT_SECRET_KEYRequired — secret key for session signing
NAT_SERVER_HOSTBind address
NAT_SERVER_PORTListen port
NAT_DATA_DIRData storage directory
NAT_LOG_LEVELLog verbosity

Network security recommendations

For a production self-hosted deployment:

  • Bind to 127.0.0.1 and use a reverse proxy for external access
  • Enable TLS with a certificate from Let's Encrypt or your internal CA
  • Restrict dashboard access to your VPN or internal network
  • Use a firewall to block direct access to port 8080 from external networks
  • Rotate NAT_SECRET_KEY periodically (invalidates all active sessions)

Troubleshooting

See Common Issues and Connection Errors for self-hosted troubleshooting guidance.

Next steps

Was this helpful?