Degoog Environment variables
Everything you configure before Degoog starts, rather than from the settings page.
How to set them
Degoog reads its configuration from the process environment at startup. The
usual way to supply it is a .env file: one
KEY=value per line, no export prefix,
# for comments.
Some things can only be set this way.
DEGOOG_SETTINGS_PASSWORDS in particular is read exclusively from
the environment; there is no settings UI and no on-disk file for it. If your
instance is reachable from the internet, set it before the first start. An
unlocked instance lets anyone install extensions, and extensions run code on
your server.
# .env
DEGOOG_PORT=4444
DEGOOG_SETTINGS_PASSWORDS=your-secure-password
LOG_LEVEL=info
# Optional: listen on a Unix socket instead of a port
# DEGOOG_UNIX_SOCKET=/run/degoog/degoog.sock
Docker and Podman
Put .env next to your compose file and add
env_file: .env to the service, or pass
--env-file .env to docker run /
podman run. Container images also honour PUID and
PGID so ownership on mounted volumes matches your host user.
services:
degoog:
image: ghcr.io/degoog-org/degoog:latest
env_file: .env
volumes:
- ./data:/app/data
ports:
- "4444:4444"
Native install or release tarball
Save .env in the project root next to package.json;
Bun loads it automatically when you start from that directory. Always start
Degoog from that directory, because paths like
data/plugins resolve relative to the working directory.
Prebuilt archives are attached to each GitHub release. You also need bun, git, and curl on the host.
systemd
[Service]
WorkingDirectory=/opt/degoog
EnvironmentFile=/opt/degoog/.env
ExecStart=/usr/local/bin/bun run src/server/index.ts
Restart=on-failure
Viewing server logs
LOG_LEVEL controls how much gets printed. Where to read it:
- Docker Compose:
docker compose logs -f - Podman:
podman logs -f degoog - systemd:
journalctl -u degoog -f - Tarball or native: the terminal you started it in. Redirect stdout and stderr to a file if you run detached.
Server and networking
| Variable | Description | Default |
|---|---|---|
DEGOOG_BIND_ADDRESS |
The IP address the server listens on. | 0.0.0.0 (all interfaces) |
DEGOOG_PORT |
The port the server listens on. | 4444 |
DEGOOG_UNIX_SOCKET |
Listen on a Unix domain socket instead of a TCP ip/port, for example
/run/degoog/degoog.sock. Degoog detects and removes a stale
socket left behind by an unclean shutdown.
|
|
DEGOOG_BASE_URL |
Where Degoog is reachable from outside. Give it a path to serve under
a sub-path, for example /degoog, or a full URL such as
https://search.example.com/degoog to also pin the scheme
and hostname. See
How Degoog works out its own URL below.
|
|
DEGOOG_DISTRUST_PROXY |
Whether to ignore X-Forwarded-For, X-Real-IP,
and X-Forwarded-Proto when determining the client IP and
protocol. Defaults to distrusting them, which is correct when Degoog is
exposed directly, since otherwise any client could spoof its source IP.
Set to 0 or false only behind a reverse proxy
you control that strips those headers on the way in.
|
1 |
DEGOOG_OUTGOING_ALLOWED_HOSTS |
Comma-separated allowlist of hostnames Degoog may reach for outgoing
requests made by engines, extensions, the image proxy and core
features. *.example.com matches any subdomain of
example.com but not example.com itself, and
* matches everything. Only the requested URL is checked,
not redirects a transport follows on its own. Store and compatibility
layer installs are not affected. Unset means no hostname restriction.
|
|
DEGOOG_PROXY_ENV_ALLOWLIST |
Comma-separated list of environment variable names that proxy URLs in
Server settings may pull in with ${NAME}, so proxy
passwords can stay out of the settings file. PREFIX_*
allows every name starting with PREFIX_ and *
allows any. Placeholders for names not on the list are left as typed.
|
|
DEGOOG_ANUBIS_MAX_DIFFICULTY |
The hardest Anubis proof-of-work challenge Degoog will solve for engines that ask for it, such as Startpage. Each step costs 16 times the CPU of the one before, and 6 is the highest value it accepts. A challenge above the limit fails that engine's search. | 4 |
DEGOOG_BODY_SIZE |
The largest request body, in KB, that public routes like search,
autocomplete and result panels will read. Anything bigger is refused
with a 413. Set it to 0 to remove the limit.
Max request body in
server settings overrides
it when filled in.
|
3072 |
How Degoog works out its own URL
A few things have to name Degoog in full rather than by a relative path: the
opensearch.xml descriptor your browser reads to offer Degoog as a
search engine, and the honeypot sitemap. Degoog has no way to know its own
public address, so it works it out per request, in this order.
-
The scheme and host of
DEGOOG_BASE_URL, if you set it to a full URL. This wins over everything below, so use it when the steps below cannot work. -
The
X-Forwarded-ProtoandX-Forwarded-Hostheaders from your reverse proxy. Most proxies send these, which is why Degoog needs no configuration on a normal setup. If the header holds a comma-separated list, Degoog takes the first entry. -
The
Hostheader, then the address the request actually arrived on.
The default order is deliberate. It lets one image serve several hostnames,
which a hardcoded URL cannot do. If your descriptor shows
http://localhost:4444, your proxy reached step 3, so either
forward the two X-Forwarded-* headers, preserve the original
Host, or set DEGOOG_BASE_URL to the full public URL.
Redirects do not use any of this. Degoog sends them as paths, so the browser resolves them against whatever address it already used, and a proxy that rewrites nothing still lands the user in the right place.
Access and settings gate
| Variable | Description | Default |
|---|---|---|
DEGOOG_SETTINGS_PASSWORDS |
Comma-separated list of passwords for the settings page. If unset and the gate is not explicitly disabled, Degoog generates a one-off password for that run and prints it in the startup logs. | |
DEGOOG_DANGEROUSLY_NO_PASSWORD |
Set to true to remove the settings gate entirely. Degoog
logs a loud warning at startup when this is on. Only sensible on a
trusted local network.
|
false |
DEGOOG_PUBLIC_INSTANCE |
Set to true or 1 to run in public mode.
Visitors get a cut-down settings page (appearance, search options,
engine toggles) and every server-side mutation API returns Unauthorized.
The admin panel moves to /admin, and is only reachable if a
password is configured too.
|
|
DEGOOG_SETTINGS_PATH |
Moves the admin settings panel to a custom path. Defaults to
settings on a normal instance and admin on a
public one. Leading slashes are stripped. On a public instance the panel
at this path returns 404 with no hint that it exists unless a password
is also configured.
|
Behaviour and localisation
| Variable | Description | Default |
|---|---|---|
DEGOOG_DEFAULT_SEARCH_LANGUAGE |
Language applied to searches when the user has not picked one. Only the
primary subtag is used, so en-US becomes en.
Unset means no language is sent and each engine uses its own default.
|
|
DEGOOG_I18N |
Forces the UI locale for every request, overriding
Accept-Language. For example en-US,
fr-FR, it, he.
|
|
DEGOOG_WIZARD |
Set to false to suppress the first-run setup wizard
regardless of persisted state. Useful when provisioning instances
automatically.
|
|
DEGOOG_BETA_STORE |
Set to 1 to prefer the develop branch of every
store repository over main or master, falling
back silently when it does not exist. For extension developers and
nightly testers.
|
|
DEGOOG_AUTOCOMPLETE_TIMEOUT_MS |
How long an autocomplete provider gets to answer before Degoog gives up on it. | 8000 |
DEGOOG_SLOT_TIMEOUT_MS |
How long a slot plugin (a panel above, below or beside the results) gets to answer before Degoog drops it. | 10000 |
DEGOOG_FAVICON_PROVIDER_TIMEOUT_MS |
How long each favicon provider gets to answer for one domain. A provider that runs over counts as having no icon, and Degoog asks the next one. | 5000 |
LOG_LEVEL |
Console verbosity, from most to least severe: fatal,
error, warn, info,
log, debug. Each level includes the more
severe ones. debug also prints plugin execution times.
|
info |
LOG_TRANSLATION |
Set to true for translation-specific logging: missing keys,
locale resolution, broken locale files. Independent of
LOG_LEVEL.
|
false |
NO_COLOR |
Set to any value to strip ANSI colour from all console output. Follows the no-color convention. |
Cache
| Variable | Description | Default |
|---|---|---|
DEGOOG_VALKEY_URL |
Connection URL for Valkey, or any RESP-compatible server (Redis, KeyDB,
Dragonfly). When set, Degoog uses it as a shared cache and cross-process
invalidation bus, so replicas share search and autocomplete results and
react to settings changes instantly. Without it, all caching is
per-process and in memory. Example: redis://valkey:6379.
|
|
DEGOOG_CACHE_TTL_MS |
Default lifetime for cached search responses and autocomplete suggestions, in milliseconds. | 43200000 (12 hours) |
DEGOOG_CACHE_SHORT_TTL_MS |
Shorter lifetime used when a search came back with failed engines, so the next attempt refetches sooner. Also used by short-lived extension caches. | 120000 (2 minutes) |
DEGOOG_CACHE_MAX_ENTRIES |
Maximum entries per in-memory cache namespace. The least recently used
entry is evicted on insert once the cap is reached. Only bounds the
in-process cache; a shared Valkey cache is governed by Valkey's own
maxmemory policy.
|
1000 |
Docker
| Variable | Description | Default |
|---|---|---|
PUID |
User ID the container process runs as. Match it to your host user so the
mounted data directory stays writable.
|
1000 |
PGID |
Group ID the container process runs as. | 1000 |
DEGOOG_DOCKER |
Set to 1 to tell Degoog it runs in a container when it
cannot spot /.dockerenv itself. Restart server then just
exits and leaves the restart to your restart policy, instead of
spawning a new process.
|
Data directories and files
Everything below defaults to somewhere inside the data directory, so
overriding DEGOOG_DATA_DIR alone usually gets you what you want.
| Variable | Description | Default |
|---|---|---|
DEGOOG_DATA_DIR |
Root directory for all on-disk state. | data (relative to the working directory) |
DEGOOG_PLUGINS_DIR |
Installed plugins. | data/plugins |
DEGOOG_ENGINES_DIR |
Installed search engines. | data/engines |
DEGOOG_THEMES_DIR |
Installed themes. | data/themes |
DEGOOG_TRANSPORTS_DIR |
Installed transports. | data/transports |
DEGOOG_AUTOCOMPLETE_DIR |
Installed autocomplete providers. | data/autocomplete |
DEGOOG_FAVICON_DIR |
Installed favicon providers. | data/favicon |
DEGOOG_SHORTCUTS_DIR |
Installed keyboard shortcuts. | data/shortcuts |
DEGOOG_ENGINE_HOSTS_FILE |
Remembers which site each engine searches, for the engine icons in the results sidebar. | data/engine-hosts.json |
DEGOOG_PLUGIN_SETTINGS_FILE |
Per-extension settings for plugins, themes, engines, autocomplete providers, favicon providers, and transports. | data/plugin-settings.json |
DEGOOG_SERVER_SETTINGS_FILE |
Instance-level settings: honeypot, streaming, rate limits, API secret, wizard state, and the per-instance identifier used to namespace the shared cache. | data/server-settings.json |
DEGOOG_DEFAULT_ENGINES_FILE |
The instance's default enabled and disabled engines. | data/default-engines.json |
DEGOOG_SEARCH_LISTS_FILE |
Domain blocking, replacement, and scoring lists. Edit this directly when a list grows too large for the UI to render. | data/search/search-lists.json |
DEGOOG_ALIASES_FILE |
Your custom bang command aliases. | data/aliases.json |
DEGOOG_BLOCKLIST_FILE |
Banned IP addresses. | data/blocklist.json |
DEGOOG_SETTINGS_TOKENS_FILE |
Active settings session tokens. | data/settings-tokens.json |
Indexer
| Variable | Description | Default |
|---|---|---|
DEGOOG_POSTGRES |
Postgres connection URL. When set, the
indexer uses Postgres instead of SQLite,
which scales concurrent writes and full-text search far better on a busy
instance. Takes precedence over the discrete
DEGOOG_POSTGRES_* vars below. The
favicon store uses the same
connection with its own degoog_favicon schema.
|
|
DEGOOG_POSTGRES_HOST |
Use this in place of the URL. When DEGOOG_POSTGRES is
unset and this is set, Degoog builds the connection from the variables
below. Lets Kubernetes setups (CNPG, bjw-s app-template) inject
credentials as separate secret keys instead of assembling a connection
string. A value that starts with / is a Unix socket
directory (for example /var/run/postgresql) and connects
with peer auth, no password required.
|
|
DEGOOG_POSTGRES_PORT |
Postgres port, used with DEGOOG_POSTGRES_HOST. |
5432 |
DEGOOG_POSTGRES_USER |
Postgres user, used with DEGOOG_POSTGRES_HOST. |
degoog |
DEGOOG_POSTGRES_PASSWORD |
Postgres password, used with DEGOOG_POSTGRES_HOST.
Required unless the host is a socket path.
|
|
DEGOOG_POSTGRES_DATABASE |
Postgres database name, used with DEGOOG_POSTGRES_HOST. |
degoog |
DEGOOG_POSTGRES_SSLMODE |
require, verify-full, or true.
Degoog refuses allow, prefer and
false as not secure enough. With a network host and a
password it defaults to require.
|
|
DEGOOG_INDEXER_DIR |
Directory holding the index databases (one
index-<type>.db per search type on SQLite), its
config, and the favicon store's favicon.db.
|
data/indexer |
DEGOOG_INDEXER_CONFIG_FILE |
Indexer filters and limits. Edit directly when a list is too large for the UI. | data/indexer/indexer-config.json |
Connecting to Postgres
The indexer uses SQLite and needs no configuration. To point it at Postgres
instead, there are three ways to give it a connection. Pick one. If
DEGOOG_POSTGRES is set, Degoog uses it and ignores the rest.
A connection URL. The original form. Nothing about it has changed, so an existing instance keeps working untouched.
DEGOOG_POSTGRES=postgresql://degoog:changeme@degoog-postgres:5432/degoog
Separate values. Use these when your deployment hands you
credentials as individual keys and you cannot build the URL yourself, as
with a Kubernetes secret from the CNPG operator or the bjw-s app-template
chart. Leave DEGOOG_POSTGRES unset and set
DEGOOG_POSTGRES_HOST. Only the host and password have no
default.
DEGOOG_POSTGRES_HOST=cnpg-postgres-rw
DEGOOG_POSTGRES_PORT=5432
DEGOOG_POSTGRES_USER=degoog
DEGOOG_POSTGRES_PASSWORD=changeme
DEGOOG_POSTGRES_DATABASE=degoog
A password containing @, :, / or
# works here. Degoog passes each value straight to the driver,
so there is no connection string for them to break.
A unix socket. Give DEGOOG_POSTGRES_HOST a
path starting with / and Degoog connects over that socket using
peer authentication, with no password. This is the route for a Postgres
running on the same host, and the one the Nix module needs.
DEGOOG_POSTGRES_HOST=/var/run/postgresql
DEGOOG_POSTGRES_USER=degoog
DEGOOG_POSTGRES_DATABASE=degoog
A socket path cannot go in a connection URL, so
DEGOOG_POSTGRES is TCP only. The separate values above are
the only way to reach a unix socket.
If DEGOOG_POSTGRES_HOST is set but a TCP host has no password,
or the port is not a number, Degoog logs the problem and falls back to
SQLite instead of refusing to start. So if the
indexer page reports SQLite on an instance you
expected to be on Postgres, grep your logs for [indexer].
SearX compatibility layer
| Variable | Description | Default |
|---|---|---|
DEGOOG_SEARX_ENGINES_DIR |
Where downloaded SearXNG engine files are kept. | data/searx/engines |
DEGOOG_SEARX_EXTRA_ENGINES |
Comma-separated SearXNG engine codes to treat as supported in addition
to the built-in compatibility list. This only lets Degoog load them,
you still have to put each .py file (and any engine it
imports) in DEGOOG_SEARX_ENGINES_DIR yourself. Most of the
time it is easier to
add the engine from the
browser, which downloads everything it needs.
|
|
DEGOOG_PYTHON_BIN |
Python interpreter used to run SearXNG engine files. | python3 |
4get compatibility layer
| Variable | Description | Default |
|---|---|---|
DEGOOG_FOURGET_DIR |
Where downloaded 4get scrapers are kept. | data/fourget |
DEGOOG_FOURGET_EXTRA_SCRAPERS |
Comma-separated 4get scraper codes to offer on top of the built-in list. For trying scrapers that have not been checked yet. | |
DEGOOG_PHP_BIN |
PHP interpreter used to run 4get scrapers. Needs PHP 8.1 or newer. | php |
The degoog-mcp sidecar has its own
DEGOOG_MCP_* variables, documented in the
MCP README
rather than here, since it is a separate process.