Skip to content

HoundDog.ai Self-Hosted Platform runs the full HoundDog.ai platform — the web application, REST API, and background worker — inside your own infrastructure. It is distributed as the public hounddogai/hounddog-self-hosted Docker image and orchestrated with Docker Compose. Your source code, scan results, and reports never leave your network.

The Self-Hosted Platform is included in the Enterprise plan. Visit hounddog.ai to get in touch.

A single Docker image runs in three roles, selected by the container command:

Service Role Port
caddy Serves the web UI and proxies /api requests across API replicas. The only publicly exposed service. 3300 (published)
api REST API. Applies database migrations and updates scan rules on startup. 8800 (internal only)
worker Background worker for asynchronous jobs such as report generation and AI reviews.

Everything is reachable through one public origin: the web app at HOUNDDOG_URL and the API at HOUNDDOG_URL/api. The api and worker services scale horizontally — see Operations.

Data is stored in PostgreSQL — either a bundled Postgres container managed by Docker Compose, or your own Postgres server (recommended for production). Scan result files are kept on a local Docker volume.

Self-Hosted uses built-in email and password authentication with database-backed sessions and API keys. No external identity provider is required. The first Owner account is created during a one-time setup step protected by a setup key (see Installation); after that, roles and permissions work exactly as on the Cloud Platform.

Self-Hosted has no email delivery, so there are no email invitations. Owners and Admins add users directly under Settings → Users → Add User, which returns a one-time temporary password to hand to the new user, and can reset a user’s password the same way.

Self-Hosted runs entirely inside your network, so features that depend on HoundDog-hosted services are disabled:

  • Email notifications and email invitations (the cloud deployment sends these through AWS SES).
  • Slack and Linear integrations, the HoundDog GitHub App, and Bitbucket Cloud — all of which rely on HoundDog-owned OAuth apps with hounddog.ai callbacks.
  • HoundDog-managed AI. AI-powered features such as dataflow reviews and privacy report generation require your own provider: configure and activate an integration under Settings → AI.

Integrations that use your own credentials — Jira, Checkmarx, Bitbucket Data Center, and GitHub Enterprise — work the same as on the Cloud Platform. No telemetry or error reporting leaves a Self-Hosted deployment.

  • Docker with Compose v2
  • At least 4 GB of RAM and 40 GB of disk space

Clone the public hounddogai/hounddog repository and run the interactive installer:

bash
git clone https://github.com/hounddogai/hounddog.git
cd hounddog/self-hosted
./install.sh

The installer checks that Docker, Docker Compose v2, awk, and curl are available, then asks you to choose the installation type. Trial installs additionally need openssl, shasum, or sha256sum to hash the generated API key, and git is required to clone the repository and to upgrade later.

  1. Trial — the quickest way to try HoundDog.ai. Postgres runs as a bundled container, and a personal CLI API key is created and written into your CLI configuration automatically.
  2. Production — connects HoundDog.ai to your own Postgres server. You provide a postgres://USER:PASSWORD@HOST:PORT/DATABASE (or postgresql://) connection URL, and you create your CLI API key in the web app after setup. Single quotes in the URL must be percent-encoded.

The installer also prompts for the port to publish (default 3300).

File Purpose
./.env Server configuration for Docker Compose: generated secrets, port, database settings. Keep it private — it contains secrets.
~/.config/hounddog/.env CLI configuration pointing the hounddog scanner at your deployment. An existing file is backed up before being replaced.

It then starts the stack with docker compose up -d --wait, applies database migrations, loads the latest scan rules, and installs the HoundDog CLI.

When the installation finishes:

  1. Open the HoundDog.ai URL printed by the installer, such as http://localhost:3300.
  2. Enter the one-time setup key printed by the installer. If you missed it, it is stored as HOUNDDOG_SETUP_KEY in ./.env.
  3. Create your organization and owner account.

For headless or automated installs, create the organization and Owner from the command line instead of the browser form:

bash
docker compose exec api python manage.py create_root_user \
--email [email protected] --password '<12+ characters>' \
--first-name Jane --last-name Doe --org-name Acme

Add --org-domain @example.com to set a company email domain, and --skip-if-exists to make the command a no-op when an account already exists. The organization name must contain only letters.

In Trial mode the CLI is already configured with an API key, so you can scan a repository right away:

bash
hounddog scan /path/to/repository

In Production mode, first create a personal API key in the web app and add it to ~/.config/hounddog/.env — see Scanner Setup.

HoundDog.ai Self-Hosted is configured through the .env file next to compose.yaml in hounddog/self-hosted. The installer generates it for you, or you can copy .env.example to .env and fill in the values yourself. Keep the file safe and private — it contains secrets.

After changing .env, apply the new values by recreating the containers:

bash
docker compose up -d --force-recreate
Variable Description
HOUNDDOG_SECRET_KEY Stable random string of 50+ characters used to encrypt sensitive data at rest. Generate one with openssl rand -base64 48. Keep a copy somewhere safe — changing or losing it makes encrypted settings unrecoverable.
HOUNDDOG_SETUP_KEY Random key required to create the first owner account. Generate one with openssl rand -base64 48. Keep it private and paste it only into the first-run setup form. Required only until the first Owner account exists; you can remove it from .env afterwards.
HOUNDDOG_POSTGRES_URL Postgres connection URL. Points at the bundled Postgres container or your own server (see below).

Pick one of two options:

Option 1: Bundled Postgres (recommended for local testing). Docker Compose manages a Postgres container for you:

.env
COMPOSE_PROFILES=postgres
POSTGRES_USER=hounddog
POSTGRES_PASSWORD=hounddog
POSTGRES_DB=hounddog
HOUNDDOG_POSTGRES_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}

For any non-local deployment, change the user, password, and database before the first start. These values are interpolated into the database URL, so use only ASCII letters, numbers, hyphens, periods, underscores, and tildes. An already-initialized Postgres volume keeps its original credentials — changing these values later does not update the database.

Option 2: Bring-your-own Postgres (recommended for production). Remove the bundled Postgres settings and set your provider’s connection URL:

.env
HOUNDDOG_POSTGRES_URL=postgres://user:password@host:5432/database

The bundled container runs postgres:18.4-alpine; use a comparable Postgres 18 server for your own deployment.

Variable Default Description
HOUNDDOG_PORT 3300 Port published by the Compose stack. HOUNDDOG_URL falls back to http://localhost:<HOUNDDOG_PORT> only when it is unset; the installer always writes HOUNDDOG_URL, so update both when you change the port.
HOUNDDOG_BIND_ADDRESS unset (all interfaces) Leave unset to publish the port on all IPv4 and IPv6 interfaces. Set 127.0.0.1 to restrict access to the Docker host.
HOUNDDOG_URL http://localhost:3300 Public HTTP or HTTPS origin, without a path. The API is served at HOUNDDOG_URL/api. Set this when using a domain or reverse proxy. A trailing slash is allowed and removed.

These are read by the application containers and can be added to the environment section of compose.yaml (or an override file) for advanced setups:

Variable Default Description
HOUNDDOG_SESSION_TTL_HOURS 168 How long web sessions stay valid, in hours.
HOUNDDOG_SCAN_RESULTS_RETENTION_DAYS 7 How long raw scan result files are retained.
HOUNDDOG_ALLOWED_HOSTS * Comma-separated list of allowed HTTP hosts.
HOUNDDOG_CORS_ALLOWED_ORIGINS HOUNDDOG_URL Comma-separated list of allowed CORS origins.
HOUNDDOG_CORS_ALLOW_ALL_ORIGINS false Allow CORS requests from any origin. Leave off unless you know you need it.
HOUNDDOG_DATA_DIR /data Container path for locally stored data such as scan result files. Must stay on the hounddog_data volume.
HOUNDDOG_LLM_BAD_OUTPUT_RETRIES 2 Corrective retries when an AI provider returns output that fails validation.

The HoundDog CLI scanner works with Self-Hosted the same way it works with HoundDog.ai Cloud — it just needs to know where your deployment is and which API key to use. Three environment variables point the scanner at a self-hosted deployment:

Variable Value
HOUNDDOG_ENV self-hosted
HOUNDDOG_URL The public origin of your deployment, e.g. http://localhost:3300. The API is reached at HOUNDDOG_URL/api.
HOUNDDOG_API_KEY A personal or organization API key created in the web app.

For example:

bash
HOUNDDOG_ENV=self-hosted \
HOUNDDOG_URL=http://localhost:3300 \
HOUNDDOG_API_KEY=<api key> \
hounddog scan /path/to/repository

Instead of exporting variables in every shell, set them once in the CLI configuration file at ~/.config/hounddog/.env (Linux/macOS) or %APPDATA%\hounddog\.env (Windows):

bash
export HOUNDDOG_ENV='self-hosted'
export HOUNDDOG_URL='http://localhost:3300'
export HOUNDDOG_API_KEY='hd_pk_...'

The installer writes this file for you — in Trial mode it already contains a working API key. Environment variables set in the shell take precedence over values in the file. See Configuration for everything the file supports.

Create API keys in the web app under API Keys:

  • Personal API keys (hd_pk_...) are for everyday use, such as development on your personal device.
  • Organization API keys (hd_ok_...) are for CI/CD pipelines and shared automation.

See API Keys for details.

CI integration works exactly as with HoundDog.ai Cloud — set HOUNDDOG_ENV, HOUNDDOG_URL, and an organization API key as pipeline variables, then run hounddog scan. See CI/CD Pipelines. Note that your CI runners must be able to reach HOUNDDOG_URL over the network.

All commands below run from the hounddog/self-hosted directory of your cloned repository.

Upgrading keeps your configuration and data:

bash
git pull && ./install.sh

The installer detects the existing .env, pulls the latest images, recreates the containers while keeping Docker volumes, applies any database migrations, updates scan rules, and reinstalls the latest HoundDog CLI.

The api and worker services scale horizontally. Caddy load-balances API requests across replicas automatically:

bash
docker compose up -d --scale api=3 --scale worker=2

Three things are worth backing up:

  • The .env file — above all HOUNDDOG_SECRET_KEY. Encrypted settings derive from it; if it is lost, they are unrecoverable.
  • The Postgres database — the bundled Postgres stores data in the postgres_data Docker volume; use pg_dump or back up your own server if you brought your own database.
  • The hounddog_data Docker volume — raw scan result files mounted at /data. These are pruned automatically after HOUNDDOG_SCAN_RESULTS_RETENTION_DAYS (default 7 days), so back this up only if you need to keep downloadable raw results across a host migration.
bash
# Container status and health
docker compose ps
# Logs for the whole stack, or one service
docker compose logs
docker compose logs api

The stack is healthy when caddy responds on the published port: the web app at / and the API health check at /api/health.

Reset deletes your local configuration and data, then starts a fresh installation:

bash
./reset.sh

It stops and removes the containers, deletes local Docker volumes, deletes the active server (./.env) and CLI (~/.config/hounddog/.env) configuration, and re-runs the installer. Configuration backups are kept. External Postgres data is not deleted — use a new or empty database during reinstallation.

bash
./uninstall.sh

Uninstalling stops and removes the containers, deletes local Docker volumes, and deletes the active server and CLI configuration. It keeps configuration backups, the HoundDog CLI, Docker images, and any external Postgres database.