The Infersec self-hosted edition combines the console and API into a single service that you run on your own hardware.

Running with Docker

The self-hosted image is published as a single container that bundles the console UI, the public API, and the resource management layer. It is multi-arch (linux/amd64, linux/arm64) and available from the public registry. The :latest tag always points at the current release; pin to a specific version (e.g. :1.83.0) for reproducible deployments.

docker run -d \
  --name infersec-selfhosted \
  --hostname infersec-selfhosted \
  -p 9507:9507 \
  -e SELFHOSTED_PUBLIC_URL=https://selfhosted.example.com \
  -e LICENSE_KEY=your-license-key \
  -e SESSION_SECRET=your-session-secret \
  -e DB_PRIMARY_HOST=... \
  -e DB_PRIMARY_PORT=... \
  -e DB_PRIMARY_DATABASE=... \
  -e DB_PRIMARY_USER=... \
  -e DB_PRIMARY_PASSWORD=... \
  -e REDIS_HOST=... \
  -e REDIS_PORT=... \
  -e REDIS_PASSWORD=... \
  -e REDIS_DB=... \
  -e REDIS_LOCK_DB=... \
  -e REDIS_API_CACHE_DB=... \
  rg.nl-ams.scw.cloud/infersec-public/selfhosted:latest

Or with Compose. This example bundles the three dependencies the instance needs - a MySQL-compatible database (MariaDB), Redis, and an S3-compatible gateway (Versity, see S3 (model storage)) - alongside the self-hosted service:

services:
    mariadb:
        image: mariadb:12
        environment:
            MARIADB_DATABASE: infersec
            MARIADB_PASSWORD: infersec-password
            MARIADB_ROOT_PASSWORD: root-password-change-me
            MARIADB_USER: infersec
        volumes:
            - mariadb-data:/var/lib/mysql
    redis:
        image: bitnami/redis:latest
        environment:
            REDIS_PASSWORD: redis-password-change-me
        volumes:
            - redis-data:/bitnami/redis/data
    versity:
        command: ["mkdir -p /data/infersec && exec versitygw --port :7070 posix /data"]
        environment:
            ROOT_ACCESS_KEY: versity-access-key
            ROOT_SECRET_KEY: versity-secret-key
        entrypoint: ["/bin/sh", "-c"]
        image: versity/versitygw:latest
        volumes:
            - versity-data:/data
    selfhosted:
        image: rg.nl-ams.scw.cloud/infersec-public/selfhosted:latest
        container_name: infersec-selfhosted
        depends_on: [mariadb, redis, versity]
        hostname: infersec-selfhosted
        ports:
            - "9507:9507"
        environment:
            DB_PRIMARY_DATABASE: infersec
            DB_PRIMARY_HOST: mariadb
            DB_PRIMARY_PASSWORD: infersec-password
            DB_PRIMARY_PORT: "3306"
            DB_PRIMARY_USER: infersec
            HTTPS: "true"
            INFERSEC_SECRET_MASTER_KEY_PATH: /data/infersec/master.key
            LICENSE_KEY: your-license-key
            REDIS_API_CACHE_DB: "2"
            REDIS_DB: "0"
            REDIS_HOST: redis
            REDIS_LOCK_DB: "1"
            REDIS_PASSWORD: redis-password-change-me
            REDIS_PORT: "6379"
            S3_ACCESS_KEY_ID: versity-access-key
            S3_BUCKET: infersec
            S3_ENDPOINT: http://versity:7070
            S3_REGION: us-east-1
            S3_SECRET_ACCESS_KEY: versity-secret-key
            SELFHOSTED_PUBLIC_URL: https://selfhosted.example.com
            SESSION_SECRET: your-session-secret
        volumes:
            - selfhosted-data:/data/infersec
volumes:
    mariadb-data:
    redis-data:
    selfhosted-data:
    versity-data:

The instance requires a MySQL-compatible database, Redis, and (for model storage) an S3-compatible service. Provide your LICENSE_KEY (issued from the Self Hosted - Licenses section of the console) before starting the container. The selfhosted-data volume keeps the generated secret master key (INFERSEC_SECRET_MASTER_KEY_PATH) stable across container recreation — without it, previously encrypted values become unreadable after a redeploy.

Keep the container identity stable. The license validation fingerprint includes the container hostname. Set a fixed hostname (and container_name) and preserve it across redeployments — do not let it be generated randomly. Running the same LICENSE_KEY under a different hostname within 3 hours is detected as use on a second instance and will automatically blacklist the license. If you are migrating hosts, decommission the old container first.

Environment variables

Variable Purpose Required
PORT Service port (default 9507) Yes
SELFHOSTED_PUBLIC_URL Public URL for template substitution Yes
SELFHOSTED_ALLOWED_HOSTS Host whitelist (comma-separated) No
HTTPS Marks the session cookie as secure (HTTPS-only). Defaults to true; set to false for plain-HTTP dev No
LICENSE_KEY License key issued from the console Yes
SESSION_SECRET Session encryption secret Yes
DB_PRIMARY_DATABASE MySQL database name Yes
DB_PRIMARY_HOST MySQL host Yes
DB_PRIMARY_PASSWORD MySQL password Yes
DB_PRIMARY_PORT MySQL port Yes
DB_PRIMARY_USER MySQL user Yes
REDIS_API_CACHE_DB Redis database for API response caching Yes
REDIS_DB Redis database number Yes
REDIS_HOST Redis host Yes
REDIS_LOCK_DB Redis database for locking Yes
REDIS_PASSWORD Redis password Yes
REDIS_PORT Redis port Yes
DB_SEED Seed database on startup (defaults to false) No
DB_SEED_EMAIL Seeded user email. Required when DB_SEED=true No
DB_SEED_NAME Seeded user display name. Required when DB_SEED=true No
DB_SEED_PASSWORD Seeded user password. Required when DB_SEED=true No
EMAIL_* SMTP configuration. All vars must be set together — see Email (SMTP) below No
HUGGINGFACE_API_KEY HuggingFace API key No
INFERSEC_SECRET_MASTER_KEY 64-hex-character master key value. Overrides the path-based file (used by the SaaS platform) No
INFERSEC_SECRET_MASTER_KEY_PATH Path to the master key file (auto-generated on first boot). Required when INFERSEC_SECRET_MASTER_KEY is unset; must be on a writable, persistent volume Conditional
S3_* S3 storage configuration. All vars must be set together — see S3 (model storage) below No

Email (SMTP)

Name Required Default Note
EMAIL_ACTION_BASE_URL All-or-nothing Base URL for links inside emails (e.g. password reset)
EMAIL_FROM_ADDRESS All-or-nothing Sender email address
EMAIL_FROM_NAME All-or-nothing Sender display name
EMAIL_HOST All-or-nothing SMTP host
EMAIL_PASSWORD All-or-nothing SMTP password
EMAIL_PORT All-or-nothing SMTP port (integer)
EMAIL_SECURE All-or-nothing true for TLS on connect (port 465), false for STARTTLS
EMAIL_USER All-or-nothing SMTP username

All EMAIL_* variables must be set together. If any are missing, outbound email is disabled and the queue drainer no-ops.

S3 (model storage)

Name Required Default Note
S3_ACCESS_KEY_ID All-or-nothing S3 access key
S3_BUCKET All-or-nothing Bucket name
S3_SECRET_ACCESS_KEY All-or-nothing S3 secret key
S3_ENDPOINT All-or-nothing S3-compatible endpoint URL
S3_REGION All-or-nothing Bucket region

All S3_* variables must be set together. If any are missing, S3 storage is disabled and database seeding of models is skipped.

If you are not using a cloud S3 provider, Versity is a self-hostable S3-compatible gateway that serves a plain filesystem over the S3 API. It is stateless and pairs well with a single-node deployment. Run it with the posix backend, pointing S3_ENDPOINT at the gateway and pre-creating the configured bucket as a directory:

docker run -d \
  --name versity \
  -p 7070:7070 \
  -e ROOT_ACCESS_KEY=versity-access-key \
  -e ROOT_SECRET_KEY=versity-secret-key \
  -v versity-data:/data \
  --entrypoint /bin/sh \
  versity/versitygw:latest \
  -c "mkdir -p /data/infersec && exec versitygw --port :7070 posix /data"

Then set S3_BUCKET=infersec and the matching access/secret keys. The S3_ENDPOINT=http://versity:7070 form (service-name hostname) applies to the Compose example above, where the services share a network. When running the gateway and the self-hosted service as separate docker run containers, the versity name does not resolve between them — either attach both containers to a shared user-defined network (docker network create infersec, then --network infersec on both) or point S3_ENDPOINT at the host's address (for example http://host.docker.internal:7070).

Licensing and legitimate use

Each self-hosted license is intended for a single deployment on a single server. When your instance starts, it validates its license key with the Infersec licensing service and reports a fingerprint made up of its container name, a persisted instance ID, and its source IP address.

  • One license key covers one running instance.
  • If two or more distinct instances (different IP address, container name, or instance ID) validate the same key within a three-hour window, the key is automatically blacklisted.
  • A blacklisted key behaves exactly like an invalid key: the instance will fail to start or will shut down.

You can submit an appeal from the Self Hosted - Licenses section of your Infersec console. Blacklist state can only be cleared by Infersec staff via the admin tooling.

If you need to relocate your deployment, stop the old instance and wait at least three hours (the fingerprint retention window) before starting a new one on the same key. Stopping the old instance does not immediately remove its fingerprint from the recent-window count — only after the window elapses is the key free to validate from a new host/container identity. If you cannot wait, request a manual reset via the appeal process above.

Setting a stable container name

Because the container name forms part of the license fingerprint, you must assign a stable hostname to your container. Without a stable name, each redeploy produces a new container name and, combined with the persisted instance ID, can trip the duplicate-detection rule within the three-hour window.

Set a fixed hostname when running the container:

docker run --hostname infersec-selfhosted ...

Or in Compose:

services:
    selfhosted:
        container_name: infersec-selfhosted
        hostname: infersec-selfhosted

Behaviour when the licensing service is unreachable

  • At startup, the instance must reach the licensing service successfully. If it cannot, it will not start.
  • While running, if the licensing service becomes temporarily unreachable, the instance continues to serve requests for a 72-hour grace period. If the service remains unreachable beyond that window, the instance shuts down.
  • A license that is reported as invalid, expired, or blacklisted causes an immediate shutdown.

Plans and limits

Each self-hosted tier caps the number of active endpoints, connected sources, active tool services, and simultaneous requests per endpoint. See the pricing page for the current tiers and limits. Bypassing or attempting to bypass these limits is prohibited under the Terms of Use and may result in immediate license suspension.