Khoj — your self-hosted AI second brain: chat with your documents and the web, run local or cloud LLMs, and search your notes semantically. Deployed as an all-in-one host-networked Nomad job (PostgreSQL + pgvector + the Khoj server). First start downloads embedding models, so give it ~2 GB RAM.
Needs nomad-pack on PATH. The script only adds the nomploy registry and runs this pack.
Source ↗ Project ↗ ★ 37.6k ⚑ Report an issue
Save as values.hcl, edit, then run:
# The name of the Nomad job.
job_name = "khoj"
# The Nomad namespace to deploy into.
namespace = "default"
# The datacenters to deploy to.
datacenters = ["*"]
# The Khoj server image. Pin a tag in production.
image = "ghcr.io/khoj-ai/khoj:latest"
# The PostgreSQL + pgvector image for the bundled database (Khoj needs the vector extension).
postgres_image = "pgvector/pgvector:pg15"
# Host port for the Khoj web UI / API.
port = 42110
# Host port for the bundled PostgreSQL (loopback only).
db_port = 5432
# Password for the bundled PostgreSQL. CHANGE THIS.
db_password = "khoj_change_me"
# Django secret key used to sign sessions (openssl rand -base64 32). CHANGE THIS and keep it stable.
django_secret_key = "change_me_django_secret_to_a_long_random_value"
# Email for the initial Khoj admin account.
admin_email = "admin@example.com"
# Password for the initial Khoj admin account. CHANGE THIS.
admin_password = "khoj_admin_change_me"
# Optional SearXNG base URL for web search (e.g. http://127.0.0.1:8888). Leave blank to disable web search. Deploy the searxng pack separately on its own port.
searxng_url = ""
# Optional Terrarium URL for the code-execution sandbox. Leave blank to disable. See the Khoj docs to run ghcr.io/khoj-ai/terrarium separately.
terrarium_url = ""
# Named volume for Khoj config and index.
config_volume = "khoj_config"
# Named volume for downloaded embedding models (torch / huggingface caches).
models_volume = "khoj_models"
# Named volume for PostgreSQL data.
db_data_volume = "khoj_db_data"
# Placement constraints. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true".
constraints = []
# Resources for the Khoj server task (needs room for embedding models).
resources = {
cpu = 1000
memory = 2048
}
# Resources for the bundled PostgreSQL task.
db_resources = {
cpu = 500
memory = 512
}
| Name | Type | Default | Description |
|---|---|---|---|
| job_name | string | "khoj" | The name of the Nomad job. |
| namespace | string | "default" | The Nomad namespace to deploy into. |
| datacenters | list | ["*"] | The datacenters to deploy to. |
| image | string | "ghcr.io/khoj-ai/khoj:latest" | The Khoj server image. Pin a tag in production. |
| postgres_image | string | "pgvector/pgvector:pg15" | The PostgreSQL + pgvector image for the bundled database (Khoj needs the vector extension). |
| port | number | 42110 | Host port for the Khoj web UI / API. |
| db_port | number | 5432 | Host port for the bundled PostgreSQL (loopback only). |
| db_password set me | string | "khoj_change_me" | Password for the bundled PostgreSQL. CHANGE THIS. |
| django_secret_key set me | string | "change_me_django_secret_to_a_long_random_value" | Django secret key used to sign sessions (openssl rand -base64 32). CHANGE THIS and keep it stable. |
| admin_email set me | string | "admin@example.com" | Email for the initial Khoj admin account. |
| admin_password set me | string | "khoj_admin_change_me" | Password for the initial Khoj admin account. CHANGE THIS. |
| searxng_url | string | "" | Optional SearXNG base URL for web search (e.g. http://127.0.0.1:8888). Leave blank to disable web search. Deploy the searxng pack separately on its own port. |
| terrarium_url | string | "" | Optional Terrarium URL for the code-execution sandbox. Leave blank to disable. See the Khoj docs to run ghcr.io/khoj-ai/terrarium separately. |
| config_volume | string | "khoj_config" | Named volume for Khoj config and index. |
| models_volume | string | "khoj_models" | Named volume for downloaded embedding models (torch / huggingface caches). |
| db_data_volume | string | "khoj_db_data" | Named volume for PostgreSQL data. |
| constraints | list | [] | Placement constraints. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true". |
| resources | object | {
cpu = 1000
memory = 2048
} | Resources for the Khoj server task (needs room for embedding models). |
| db_resources | object | {
cpu = 500
memory = 512
} | Resources for the bundled PostgreSQL task. |
No variables match.
This pack stores data in 3 Docker named volumes:
khoj_db_datakhoj_configkhoj_models
⚠ This pack bundles a database. A cold copy of the volume can be inconsistent — for a reliable backup, dump the DB (pg_dump / mysqldump) or stop the job while backing up.
restic
# Run on the node hosting this pack. Point restic at your repo first: # export RESTIC_REPOSITORY="s3:https://<account>.r2.cloudflarestorage.com/<bucket>" # export RESTIC_PASSWORD="<repo-password>" # export AWS_ACCESS_KEY_ID=<key> AWS_SECRET_ACCESS_KEY=<secret> restic backup \ /var/lib/docker/volumes/khoj_db_data/_data \ /var/lib/docker/volumes/khoj_config/_data \ /var/lib/docker/volumes/khoj_models/_data
rclone (sync to S3/R2)
rclone sync /var/lib/docker/volumes/khoj_db_data/_data backup:<bucket>/khoj_db_data rclone sync /var/lib/docker/volumes/khoj_config/_data backup:<bucket>/khoj_config rclone sync /var/lib/docker/volumes/khoj_models/_data backup:<bucket>/khoj_models
Paths assume the default Docker volume location (/var/lib/docker/volumes). Restore by stopping the job, restoring files into the same volume, and re-running the pack.
Khoj is a self-hosted AI second brain — chat with your documents and the web, run local (Ollama) or cloud LLMs, and search your notes semantically.
This pack runs Khoj all-in-one as a single host-networked Nomad job:
ghcr.io/khoj-ai/khoj:latest)Both share the host network and talk over 127.0.0.1, so no mesh networking is required.
On first start Khoj downloads its embedding models into the khoj_models volume and runs
database migrations automatically.
Give the server task ~2 GB RAM (embedding models) and some disk for the model cache.
nomad-pack run khoj --registry=nomploy
Then open http://<node-ip>:42110. Configure a chat model (a local Ollama endpoint or a
cloud API key) in the admin settings.
| Variable | Default | Notes |
|---|---|---|
port |
42110 |
Web UI / API host port |
db_password |
change me | Bundled PostgreSQL password |
django_secret_key |
change me | Session signing key — keep stable |
admin_email / admin_password |
change me | Initial admin account |
searxng_url |
(blank) | Optional: enable web search (point at a searxng instance) |
terrarium_url |
(blank) | Optional: enable the code-execution sandbox |
This pack runs Khoj in --anonymous-mode (matching the upstream docker-compose), which
means there is no login wall — anyone who can reach the port has full access. Keep it
behind your VPN or a reverse proxy that enforces authentication.
Khoj's web search and code-execution features need two extra services that both default to port 8080, so they aren't bundled here (they'd collide on host networking):
searxng_url.ghcr.io/khoj-ai/terrarium separately and set terrarium_url.Data persists in the khoj_db_data, khoj_config and khoj_models named volumes.