Centinel AnalyticaCentinel Analytica
Platforms

Nginx / OpenResty

Deploy Centinel Analytica protection on your Nginx or OpenResty server using a Lua module.

Overview

This quickstart outlines the installation workflow for the Centinel nginx module. The module runs in OpenResty or nginx with lua-nginx-module and validates requests against the Centinel API. Allow 2-3 minutes for installation.

Prerequisites

  • Centinel secret key (from your dashboard)
  • OpenResty 1.19+ or nginx with lua-nginx-module
  • Root/sudo access to install files and edit nginx config

Method 1: Quick Install Script

Run this single command to install the Centinel module:

curl -sSL https://docs.centinelanalytica.com/downloads/install-nginx.sh | bash

The script will:

  • Detect your OpenResty or nginx installation
  • Download the Centinel module and dependencies
  • Generate the nginx configuration snippet

After the script completes, follow the printed instructions to:

  1. Add the configuration to your nginx.conf
  2. Set your CENTINEL_SECRET_KEY environment variable
  3. Reload nginx

Method 2: Manual Installation

Download the module

Download the Centinel Lua module to your OpenResty/nginx Lua path:

# For OpenResty (default path)
curl -o /usr/local/openresty/site/lualib/centinel-nginx.lua \
  https://docs.centinelanalytica.com/downloads/centinel-nginx.lua

# Install lua-resty-http dependency (if not already installed)
opm get ledgetech/lua-resty-http

If opm is not available, install lua-resty-http manually:

mkdir -p /usr/local/openresty/site/lualib/resty
curl -o /usr/local/openresty/site/lualib/resty/http.lua \
  https://raw.githubusercontent.com/ledgetech/lua-resty-http/master/lib/resty/http.lua
curl -o /usr/local/openresty/site/lualib/resty/http_headers.lua \
  https://raw.githubusercontent.com/ledgetech/lua-resty-http/master/lib/resty/http_headers.lua
curl -o /usr/local/openresty/site/lualib/resty/http_connect.lua \
  https://raw.githubusercontent.com/ledgetech/lua-resty-http/master/lib/resty/http_connect.lua
Configure nginx.conf

Add the following to your nginx.conf inside the http {} block:

http {
    # SSL certificates for outbound HTTPS (required)
    lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
    lua_ssl_verify_depth 3;

    # DNS resolver (required)
    resolver 8.8.8.8 valid=30s ipv6=off;

    # Shared memory for circuit breaker (required)
    lua_shared_dict centinel_cache 10m;

    # Lua module path (adjust if needed)
    lua_package_path '/usr/local/openresty/site/lualib/?.lua;;';

    # Initialize Centinel at startup
    init_by_lua_block {
        centinel = require("centinel-nginx")
        centinel.init({
            secret_key = os.getenv("CENTINEL_SECRET_KEY")
        })
    }

    # ... your existing configuration ...
}

Then add the protection handler to locations you want to protect:

server {
    listen 80;

    location / {
        # Centinel bot protection
        access_by_lua_block {
            centinel.access_handler()
        }

        # Your existing proxy_pass or other directives
        proxy_pass http://backend;
    }
}
Set your secret key

Set the CENTINEL_SECRET_KEY environment variable before starting nginx:

export CENTINEL_SECRET_KEY="sk_live_your_key_here"

For systemd services, add to your unit file:

[Service]
Environment="CENTINEL_SECRET_KEY=sk_live_your_key_here"
Reload nginx

Test and reload the configuration:

nginx -t && nginx -s reload
Verify deployment
  • Visit your website to confirm normal traffic flow.
  • Check nginx error logs for [Centinel] entries:
    tail -f /var/log/nginx/error.log | grep Centinel
  • Enable debug mode for detailed logging (see Advanced Configuration).

Advanced Configuration

Customize Protected Paths

By default, all paths are protected except static assets. Customize this in centinel.init():

init_by_lua_block {
    centinel = require("centinel-nginx")
    centinel.init({
        secret_key = os.getenv("CENTINEL_SECRET_KEY"),

        -- Only protect specific paths (empty = protect all)
        protected_paths = {
            "^/api/",
            "^/admin",
            "^/checkout"
        },

        -- Add paths to skip (in addition to defaults)
        unprotected_paths = {
            "%.css$", "%.js$", "%.png$", "%.jpg$",
            "^/health$",
            "^/metrics$"
        }
    })
}

Default excluded patterns: Static assets like .css, .js, .png, .jpg, .gif, .svg, .woff, .woff2, .mp4, .mp3, .zip, and more.

Timeout Settings

Adjust API timeouts for your environment:

centinel.init({
    secret_key = os.getenv("CENTINEL_SECRET_KEY"),

    -- API request timeout (default: 100ms)
    timeout_ms = 200,

    -- Connection timeout (default: 100ms)
    connect_timeout_ms = 150,

    -- Allow requests if API is unavailable (default: true)
    fail_open = true
})

Circuit Breaker

The module implements exponential backoff when the API fails:

FailureBackoff Duration
1st1 second
2nd2 seconds
3rd4 seconds
4th8 seconds
Max5 minutes

During backoff, all requests are allowed (fail-open). The backoff resets on successful API response.

Enable Debug Logging

For troubleshooting, enable debug mode:

centinel.init({
    secret_key = os.getenv("CENTINEL_SECRET_KEY"),
    debug = true
})

Or via environment variable:

export CENTINEL_DEBUG=true

Debug logs include:

  • Validation requests and responses
  • Path protection decisions
  • Backoff/circuit breaker state

View logs with:

tail -f /var/log/nginx/error.log | grep Centinel

Docker Installation

For containerized deployments:

FROM openresty/openresty:alpine

# Install CA certificates
RUN apk add --no-cache ca-certificates

# Install lua-resty-http
RUN mkdir -p /usr/local/openresty/site/lualib/resty && \
    wget -q -O /usr/local/openresty/site/lualib/resty/http.lua \
    https://raw.githubusercontent.com/ledgetech/lua-resty-http/master/lib/resty/http.lua && \
    wget -q -O /usr/local/openresty/site/lualib/resty/http_headers.lua \
    https://raw.githubusercontent.com/ledgetech/lua-resty-http/master/lib/resty/http_headers.lua && \
    wget -q -O /usr/local/openresty/site/lualib/resty/http_connect.lua \
    https://raw.githubusercontent.com/ledgetech/lua-resty-http/master/lib/resty/http_connect.lua

# Install Centinel module
RUN wget -q -O /usr/local/openresty/site/lualib/centinel-nginx.lua \
    https://docs.centinelanalytica.com/downloads/centinel-nginx.lua

COPY nginx.conf /usr/local/openresty/nginx/conf/nginx.conf

EXPOSE 80
CMD ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"]

Run with:

docker run -e CENTINEL_SECRET_KEY="sk_live_xxx" -p 80:80 your-image

Configuration Reference

VariableTypeRequiredDefaultDescription
secret_keystringYesYour Centinel API key from the dashboard.
validator_urlstringNohttps://validator.centinelanalytica.com/validateValidator API endpoint.
timeout_msnumberNo100API request timeout in milliseconds.
connect_timeout_msnumberNo100Connection timeout in milliseconds.
fail_openbooleanNotrueAllow requests when API is unavailable.
ssl_verifybooleanNotrueVerify SSL certificates for API calls.
debugbooleanNofalseEnable debug logging.
log_enabledbooleanNotrueEnable all logging.
protected_pathstableNo{}Lua patterns for paths to protect. Empty table protects all paths.
unprotected_pathstableNo[static assets]Lua patterns for paths to skip (static assets by default).

Troubleshooting

SSL certificate errors

SSL certificate problem: unable to get local issuer certificate

Ensure lua_ssl_trusted_certificate points to your CA bundle:

  • Debian/Ubuntu/Alpine: /etc/ssl/certs/ca-certificates.crt
  • CentOS/RHEL: /etc/pki/tls/certs/ca-bundle.crt
  • macOS: /etc/ssl/cert.pem

Module not found

module 'centinel-nginx' not found

Check that lua_package_path matches where you installed the module:

lua_package_path '/usr/local/openresty/site/lualib/?.lua;;';

lua-resty-http not found

module 'resty.http' not found

Install via opm or manually download:

opm get ledgetech/lua-resty-http

Shared dict not configured

Shared dict 'centinel_cache' not configured

Add to your http {} block:

lua_shared_dict centinel_cache 10m;

DNS resolution failures

no resolver defined to resolve

Add a resolver to your http {} block:

resolver 8.8.8.8 valid=30s ipv6=off;

Changelog

  • 1.0.0 - Initial release with OpenResty support, circuit breaker, and path filtering.