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.
Architecture
Section titled “Architecture”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.
Authentication
Section titled “Authentication”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.
What Is Not Available
Section titled “What Is Not Available”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.aicallbacks. - 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.
Requirements
Section titled “Requirements”- Docker with Compose v2
- At least 4 GB of RAM and 40 GB of disk space
Installation
Section titled “Installation”Clone the public hounddogai/hounddog repository and run the interactive
installer:
git clone https://github.com/hounddogai/hounddog.gitcd hounddog/self-hosted./install.shThe 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.
- 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.
- Production — connects HoundDog.ai to your own Postgres server. You provide a
postgres://USER:PASSWORD@HOST:PORT/DATABASE(orpostgresql://) 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).
What the Installer Creates
Section titled “What the Installer Creates”| 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.
First-Run Setup
Section titled “First-Run Setup”When the installation finishes:
- Open the HoundDog.ai URL printed by the installer, such as
http://localhost:3300. - Enter the one-time setup key printed by the installer. If you missed it, it is stored as
HOUNDDOG_SETUP_KEYin./.env. - 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:
docker compose exec api python manage.py create_root_user \ --first-name Jane --last-name Doe --org-name AcmeAdd --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.
Run Your First Scan
Section titled “Run Your First Scan”In Trial mode the CLI is already configured with an API key, so you can scan a repository right away:
hounddog scan /path/to/repositoryIn Production mode, first create a personal API key in the web app and add it to ~/.config/hounddog/.env —
see Scanner Setup.
Configuration
Section titled “Configuration”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:
docker compose up -d --force-recreateRequired Settings
Section titled “Required Settings”| 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). |
Database
Section titled “Database”Pick one of two options:
Option 1: Bundled Postgres (recommended for local testing). Docker Compose manages a Postgres container for you:
COMPOSE_PROFILES=postgresPOSTGRES_USER=hounddogPOSTGRES_PASSWORD=hounddogPOSTGRES_DB=hounddogHOUNDDOG_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:
HOUNDDOG_POSTGRES_URL=postgres://user:password@host:5432/databaseThe bundled container runs postgres:18.4-alpine; use a comparable Postgres 18 server for your own deployment.
Optional Settings
Section titled “Optional Settings”| 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. |
Advanced Settings
Section titled “Advanced Settings”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. |
Scanner Setup
Section titled “Scanner Setup”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:
HOUNDDOG_ENV=self-hosted \HOUNDDOG_URL=http://localhost:3300 \HOUNDDOG_API_KEY=<api key> \hounddog scan /path/to/repositoryCLI Configuration File
Section titled “CLI Configuration File”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):
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.
API Keys
Section titled “API Keys”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/CD Pipelines
Section titled “CI/CD Pipelines”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.
Operations
Section titled “Operations”All commands below run from the hounddog/self-hosted directory of your cloned repository.
Upgrade
Section titled “Upgrade”Upgrading keeps your configuration and data:
git pull && ./install.shThe 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:
docker compose up -d --scale api=3 --scale worker=2Back Up
Section titled “Back Up”Three things are worth backing up:
- The
.envfile — above allHOUNDDOG_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_dataDocker volume; usepg_dumpor back up your own server if you brought your own database. - The
hounddog_dataDocker volume — raw scan result files mounted at/data. These are pruned automatically afterHOUNDDOG_SCAN_RESULTS_RETENTION_DAYS(default 7 days), so back this up only if you need to keep downloadable raw results across a host migration.
Logs and Troubleshooting
Section titled “Logs and Troubleshooting”# Container status and healthdocker compose ps
# Logs for the whole stack, or one servicedocker compose logsdocker compose logs apiThe 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:
./reset.shIt 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.
Uninstall
Section titled “Uninstall”./uninstall.shUninstalling 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.
