Config File Reference
Ghost stores all its settings in a single configuration file written in TOML format — a simple, human-readable format that looks similar to INI files but supports nested sections and typed values. Think of it as Ghost’s “preferences file” — everything from which port the proxy listens on, to your AI provider API key, to whether noise detection is enabled, lives in this one file.
The file is created automatically on first launch with sensible defaults. You can edit it manually with any text editor, but most users change settings through Ghost’s Settings UI, which reads and writes this file through the REST API.
File Location and Directory Structure
Section titled “File Location and Directory Structure”Ghost keeps all its data in a single directory at ~/.ghost/ (your home folder, inside a hidden .ghost folder).
| File | Permissions | Description |
|---|---|---|
~/.ghost/ | 0700 (owner only) | The Ghost data directory. Created automatically on first launch. Only your user account can read or enter this directory. |
~/.ghost/config.toml | 0600 (owner read/write only) | The main configuration file. Contains encrypted API keys, so it’s restricted to prevent other users on the machine from reading your secrets. |
~/.ghost/ca.crt | 0644 (world readable) | The CA certificate that Ghost uses for HTTPS interception. Needs to be readable because it’s installed into browser/OS trust stores. |
~/.ghost/ca.key | 0600 (owner only) | The CA private key. This is the most sensitive file — anyone with this key could generate certificates that your machine trusts. |
~/.ghost/ghost.db | Created by SQLite | The SQLite database containing all captured flows, sessions, findings, conversations, and other persistent data. |
~/.ghost/workspaces/<session-id>/ | 0755 | Per-session workspace directories created for agent file output, containing subdirectories for findings/, scans/, and poc/. |
Atomic Config Writes
Section titled “Atomic Config Writes”When Ghost saves the config file, it never writes directly to config.toml. Instead, it uses a crash-safe atomic write pattern:
- Create a temporary file in the same directory (e.g.,
.config-abc123.tmp) - Write the TOML-encoded config to the temporary file
- Close the temporary file
- Set permissions to
0600on the temporary file - Atomically rename the temporary file to
config.toml
If any step fails (disk full, power loss, crash), the original config.toml remains intact. The temporary file is cleaned up on failure. This prevents the nightmare scenario where a half-written config file corrupts your settings.
Complete Configuration Reference
Section titled “Complete Configuration Reference”[proxy] — Proxy Engine Settings
Section titled “[proxy] — Proxy Engine Settings”Controls how the MITM (Man-in-the-Middle) proxy intercepts and processes HTTP/HTTPS traffic.
| Key | Type | Default | Description |
|---|---|---|---|
port | int | 4545 | The TCP port the proxy listens on. Browsers and devices are configured to send their traffic to this port. Changing this requires a restart — it cannot be hot-reloaded. |
cert_cache_size | int | 10000 | How many dynamically-generated leaf certificates to keep in memory. Each HTTPS domain Ghost intercepts needs its own certificate, and generating them takes CPU time. The LRU (Least Recently Used) cache keeps the most recently used certificates ready. 10,000 covers most usage patterns. Requires restart to change. |
host_include | string[] | [] (empty = capture all) | A whitelist of host patterns. When set, Ghost ONLY captures traffic to hosts matching these patterns. An empty list means “capture everything.” Patterns use glob syntax (e.g., *.example.com matches api.example.com). Hot-reloadable. |
host_exclude | string[] | 134 default patterns | A blacklist of host patterns to ignore. Traffic to these hosts passes through without being captured or displayed. The defaults cover Windows telemetry, browser telemetry, certificate/OCSP checks, connectivity probes, macOS noise, Edge/Bing, Google services, social media, streaming/media, analytics/ads, CDN infrastructure, and Microsoft services. Hot-reloadable. |
upstream_proxy | string | "" (direct) | URL of an upstream proxy to chain through. When set, Ghost forwards traffic through this proxy instead of connecting directly to the internet. Useful in corporate environments with mandatory proxies. Format: http://proxy.corp.com:8080. |
ssl_bypass_hosts | string[] | [] (none) | Hosts where Ghost should NOT perform HTTPS interception. Traffic to these hosts is tunneled through as-is, without decryption. Use this for apps with certificate pinning (like banking apps) that would break if Ghost intercepted their HTTPS. Supports wildcard suffix matching (e.g., *.apple.com). |
noise_enabled | bool* | true (when nil) | Master switch for noise detection. When enabled, Ghost automatically identifies and suppresses repetitive background traffic (like health checks, polling requests) that clutter the flow list. This is a pointer type — nil in TOML means “use default” which is true. |
noise_threshold | int | 20 (when 0) | How many requests from the same pattern within the window before Ghost classifies it as noise. A “pattern” is defined by the combination of HTTP method, host, and URL path. Zero means “use default.” Hot-reloadable. |
noise_sample_rate | int | 10 (when 0) | Once a pattern is classified as noisy, Ghost keeps 1 out of every N requests (e.g., 10 means keep 10%, discard 90%). This gives you visibility into noisy patterns without flooding the flow list. Zero means “use default.” Hot-reloadable. |
noise_window_secs | int | 30 (when 0) | The sliding window duration in seconds. Ghost counts how many times a pattern appears within this window to decide if it’s noisy. Zero means “use default.” Hot-reloadable. |
[api] — REST API Server Settings
Section titled “[api] — REST API Server Settings”Controls the HTTP server that the frontend (and any API clients) connect to.
| Key | Type | Default | Description |
|---|---|---|---|
port | int | 5565 | The TCP port the REST API and WebSocket server listen on. The Ghost frontend connects to this port. Changing this requires a restart. |
bearer_token | string | Auto-generated | The authentication token for all API access. If empty on first launch, Ghost generates a cryptographically random token (32 random bytes encoded as a 64-character hexadecimal string). This token is never exposed through the Settings API — the frontend receives it via the Tauri sidecar’s startup JSON output. |
[store] — Database and Storage Settings
Section titled “[store] — Database and Storage Settings”Controls how Ghost stores captured traffic data in its SQLite database.
| Key | Type | Default | Description |
|---|---|---|---|
max_flow_body_size | int | 10485760 (10 MB) | Maximum size of request/response bodies that Ghost stores inline in the database, in bytes. Bodies larger than this are still captured and forwarded to the browser, but they aren’t saved in the database. This prevents a single large file download from bloating the database. Requires restart to change. |
auto_purge_enabled | bool | false | When enabled, Ghost automatically cleans up old flows on a schedule (every 5 minutes). This keeps the database from growing unbounded during long-running sessions. |
auto_purge_max_age_hours | int | 0 (disabled) | Maximum age of flows in hours. When auto-purge runs, any flows older than this are deleted. Set to 0 to disable age-based purging. Only takes effect when auto_purge_enabled is true. |
auto_purge_max_flows | int | 0 (disabled) | Maximum total number of flows to keep. When auto-purge runs, the oldest flows beyond this count are deleted. Set to 0 to disable count-based purging. Only takes effect when auto_purge_enabled is true. |
[llm] — AI Provider Settings
Section titled “[llm] — AI Provider Settings”Configures which AI model provider Ghost uses for its agent features (test generation, security analysis, traffic understanding, bug reports).
| Key | Type | Default | Description |
|---|---|---|---|
provider | string | "anthropic" | Which AI provider to use. Options: "anthropic" (Claude models), "openai" (GPT models), "ollama" (local models running on your machine). |
api_key | string | "" (none) | Your API key for the selected cloud provider. Encrypted at rest using AES-256-GCM (see Encryption section below). Not needed for Ollama since it runs locally. When displayed in the Settings UI, only the last 4 characters are shown (e.g., ****ab12). |
model | string | "" (provider default) | The specific model to use. When empty, Ghost uses the provider’s default: Claude Sonnet 4.6 for Anthropic, GPT-4o for OpenAI, llama3.2 for Ollama. |
ollama_endpoint | string | "http://localhost:11434" | The URL of your Ollama server. Only relevant when provider is "ollama". The default points to a locally running Ollama instance on its standard port. |
[logging] — Log Output Settings
Section titled “[logging] — Log Output Settings”| Key | Type | Default | Description |
|---|---|---|---|
level | string | "info" | Controls how verbose Ghost’s log output is. Options from most to least verbose: "debug" (everything, including individual proxy operations), "info" (normal operations), "warn" (potential problems), "error" (only failures). Requires restart to change. |
[setup] — First-Run Wizard State
Section titled “[setup] — First-Run Wizard State”| Key | Type | Default | Description |
|---|---|---|---|
completed | bool | false | Whether the user has completed the first-run setup wizard. When false, Ghost shows the setup wizard instead of the main interface. Set to true automatically when the user finishes setup. |
proxy_method | string | "" (not chosen) | The connection method the user selected during setup: "system_proxy" (Ghost configures the OS to route all traffic through it), "manual" (user configures their browser or device manually), or "device" (user is primarily testing mobile devices). |
[security] — Security Scanning Settings
Section titled “[security] — Security Scanning Settings”| Key | Type | Default | Description |
|---|---|---|---|
target_hosts | string[] | [] (scan nothing) | Glob patterns defining which hosts the security interceptor should analyze. When empty, passive security scanning is disabled. Example: ["*.hepsiburada.com", "api.example.com"] would scan all hepsiburada.com subdomains and the specific api.example.com host. Hot-reloadable. |
disabled_tools | string[] | [] (all enabled) | Names of security tools the user has toggled off. Ghost’s 8 known security tools (Frida, Nuclei, Dalfox, ffuf, sqlmap, TruffleHog, Katana, Semgrep) are all enabled by default. Adding a tool name here prevents the agent from using it. Hot-reloadable via the Security Tools management UI. |
[telemetry] — Error Reporting and Usage Tracking
Section titled “[telemetry] — Error Reporting and Usage Tracking”| Key | Type | Default | Description |
|---|---|---|---|
sentry_dsn | string | "" (disabled) | Sentry DSN (Data Source Name) for crash and error reporting. When set, unhandled errors are reported to Sentry for debugging. Stripped from settings exports — never shared when you export your config. |
telemetry_enabled | bool* | true (when nil) | Whether anonymous usage telemetry is enabled. Ghost sends periodic heartbeats with basic usage statistics (no traffic content, no personal data). This is a pointer type — nil in TOML means “use default” which is true. |
telemetry_endpoint | string | "" (disabled) | URL endpoint for telemetry heartbeats. Must be a valid HTTP or HTTPS URL. When empty, heartbeats are not sent regardless of the telemetry_enabled setting. |
[testrail] — TestRail Integration
Section titled “[testrail] — TestRail Integration”| Key | Type | Default | Description |
|---|---|---|---|
url | string | "" (not configured) | URL of your TestRail instance (e.g., https://yourcompany.testrail.io). Must be HTTP or HTTPS. Validated against SSRF (Server-Side Request Forgery) — Ghost refuses to connect to private/local network addresses to prevent the server from being used to scan internal networks. |
email | string | "" | The email address associated with your TestRail account. Used for API authentication. |
api_key | string | "" | Your TestRail API key. Encrypted at rest using AES-256-GCM, same as the LLM API key. Masked in the Settings UI (last 4 characters visible). Never included in config exports or imports. |
API Key Encryption
Section titled “API Key Encryption”Ghost encrypts sensitive values (LLM API keys and TestRail API keys) at rest using AES-256-GCM — an industry-standard authenticated encryption algorithm. This means even if someone gains access to your config.toml file, they cannot read your API keys without also having access to your specific machine’s identity.
Key Derivation
Section titled “Key Derivation”The encryption key is derived from machine-specific values, making the encrypted config file non-portable between machines:
SHA-256("ghost:v1:{hostname}:{os}:{homedir}:ghost-local-encryption-salt")| Component | Source | Fallback |
|---|---|---|
hostname | os.Hostname() — your computer’s network name | "unknown-host" if the hostname can’t be determined |
os | runtime.GOOS — the operating system (e.g., "darwin", "windows", "linux") | No fallback (always available) |
homedir | os.UserHomeDir() — your home directory path | "unknown-home" if the home directory can’t be determined |
| Salt | Fixed string: "ghost-local-encryption-salt" | N/A |
The SHA-256 hash produces a 32-byte key (256 bits), which is exactly the key size that AES-256 requires.
Safety check: If both hostname AND home directory fail to resolve (both return fallbacks), the key derivation returns an error rather than producing a universal key that would be the same on every machine. At least one machine-specific component must be available.
Encryption Flow
Section titled “Encryption Flow”When Ghost saves an API key:
- If the key is empty, store it as empty (nothing to encrypt)
- Generate the 32-byte encryption key from machine identity (see above)
- Create an AES-256 cipher block
- Create a GCM (Galois/Counter Mode) wrapper — this provides both encryption AND integrity verification
- Generate a random nonce (one-time number) using
crypto/rand— this ensures encrypting the same key twice produces different ciphertext - Encrypt the key and prepend the nonce to the ciphertext
- Base64-encode the combined nonce+ciphertext
- Store as
"enc:"+ the base64 string
Encrypted Value Format
Section titled “Encrypted Value Format”In the TOML file, encrypted values look like this:
[llm]api_key = "enc:dGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIGV4YW1wbGU..."The enc: prefix tells Ghost that this value needs to be decrypted on load. Values without this prefix are treated as plaintext — this enables automatic migration from older configs (see below).
Decryption Flow
Section titled “Decryption Flow”When Ghost loads the config:
- If the value is empty or doesn’t start with
enc:, return it as-is (plaintext passthrough) - Strip the
enc:prefix - Base64-decode the remaining string
- Derive the encryption key from machine identity
- Split the decoded data into nonce (first N bytes) and ciphertext (remaining bytes)
- Decrypt using AES-256-GCM — this also verifies integrity (detects tampering)
- If decryption fails (wrong machine, corrupted data): the key is silently cleared to empty string
Automatic Migration
Section titled “Automatic Migration”When Ghost loads a config file and finds a plaintext API key (no enc: prefix), it automatically encrypts and re-saves the config. This is a one-time migration that happens transparently. If the migration save fails, Ghost logs a warning but continues running — the key works fine in memory, it just won’t be encrypted on disk until the next successful save.
What Happens When You Move Configs Between Machines
Section titled “What Happens When You Move Configs Between Machines”If you copy config.toml to a different computer (different hostname or home directory), the encryption key will be different and the encrypted API keys cannot be decrypted. Ghost handles this gracefully:
- The API keys are silently cleared to empty strings
- Ghost continues running normally — everything works except AI features
- You need to re-enter your API keys in the Settings UI
- The keys are then encrypted with the new machine’s identity
Runtime Behavior
Section titled “Runtime Behavior”Hot-Reload
Section titled “Hot-Reload”When you change settings through the Settings UI (or via PUT /api/v1/settings), some settings take effect immediately without restarting Ghost, while others require a restart:
Hot-reloaded immediately (5 subsystems):
| Subsystem | What gets updated |
|---|---|
| Security interceptor | Target host patterns — which domains get passive security scanning |
| Proxy host filters | Include/exclude patterns — which traffic gets captured vs ignored |
| Noise detector | Threshold, sample rate, window duration — noise detection sensitivity. Existing pattern state (which patterns are currently classified as noisy) is preserved across config changes. |
| LLM agent | Provider, API key, model — creates a new AI provider instance with updated credentials |
| TestRail client | URL, email, API key — swaps the TestRail HTTP client under a mutex |
Requires restart to change:
| Setting | Why |
|---|---|
proxy.port | The TCP listener is bound once at startup |
api.port | The HTTP server listener is bound once at startup |
proxy.cert_cache_size | The LRU cache is allocated once at startup |
store.max_flow_body_size | Used during SQLite store initialization |
logging.level | The logger is configured once at startup |
api.bearer_token | Only changed via the dedicated token rotation endpoint, not the general settings update |
Thread Safety
Section titled “Thread Safety”The config is managed by a Manager struct that uses a read-write mutex (sync.RWMutex) for thread safety:
- Reading (
Get()): Acquires a read lock and returns a pointer to the current config. Multiple goroutines can read simultaneously. The returned config must NOT be modified — it’s a shared read-only snapshot. - Writing (
Update()): Applies defaults to fill any zero-valued fields, saves to disk atomically, then acquires a write lock and swaps the config pointer. Until a reader callsGet()again, they continue seeing the old config — this is safe because Go’s garbage collector keeps the old config alive as long as anyone holds a reference.
Bearer Token Rotation
Section titled “Bearer Token Rotation”The API authentication token has its own dedicated rotation mechanism, separate from the general settings update:
POST /api/v1/settings/token/rotategenerates a new 32-byte random token- The new token is stored in an
atomic.Value(lock-free) for the fastest possible authentication checks - The new token is persisted to
config.toml - If the disk write fails, the in-memory token is reverted to the old value — this prevents a situation where the frontend has a new token but it’s lost on restart
Example Config
Section titled “Example Config”[proxy]port = 4545cert_cache_size = 10000host_exclude = ["*.google.com", "*.googleapis.com", "*.gstatic.com"]ssl_bypass_hosts = ["*.apple.com"]noise_enabled = truenoise_threshold = 20
[api]port = 5565
[store]max_flow_body_size = 10485760auto_purge_enabled = false
[llm]provider = "anthropic"api_key = "enc:dGhpcyBpcyBhIGJhc2U2NC..."model = "claude-sonnet-4-20250514"
[security]target_hosts = ["*.hepsiburada.com", "api.example.com"]
[logging]level = "info"
[telemetry]telemetry_enabled = true
[testrail]url = "https://yourcompany.testrail.io"email = "qa@company.com"api_key = "enc:YW5vdGhlciBiYXNlNjQgZXhhbXBsZQ..."Settings Export and Import Security
Section titled “Settings Export and Import Security”When you export your settings (GET /api/v1/settings/export), three sensitive fields are explicitly cleared before the file is generated:
llm.api_key— removed entirelytestrail.api_key— removed entirelytelemetry.sentry_dsn— removed entirely
When you import settings (POST /api/v1/settings/import), Ghost explicitly ignores the llm.api_key and testrail.api_key fields from the imported file. This means importing a config file from another user or machine will never overwrite your API keys — you always need to enter them manually through the Settings UI.