The administrator sets secrets and environment values in .env and non-secret application settings in config.yaml. Use the files shipped with the installed CodeGraph version. After a change, restart the affected services and verify readiness using the steps below.
Configuration sources
| Source | Purpose | Customer deployment location |
|---|---|---|
.env.example |
Version-bound list of supported environment variables | Reference only; do not store real secrets in it |
.env |
Secrets and deployment-specific environment values | /opt/codegraph/.env |
config.yaml |
Non-secret application behavior and ${VARIABLE} interpolation |
/opt/codegraph/config.yaml |
projects.yaml |
Declared project configuration where the deployment profile uses it | /opt/codegraph/projects.yaml |
The environment variable reference lists all shipped server variables, sample values, and Docker Compose fallbacks.
Configure the deployment through .env and config.yaml. Store credentials in the protected .env or the customer secret store; keep them out of Git, command-line arguments, service files, and logs.
Required production values
Start from the .env.example shipped with the exact installed release. At minimum, set:
POSTGRES_PASSWORD=<secret-from-approved-store>
API_JWT_SECRET=<random-secret-at-least-64-characters>
API_ADMIN_PASSWORD=<unique-initial-admin-secret>
API_PROVIDER_SECRET_KEY=<independent-random-encryption-secret>
ENVIRONMENT=production
Also configure every required Eva integrity key and at least one approved model-provider credential listed by that release. Replace placeholders with environment-specific values and keep sample values in the documentation only.
Use a random value of at least 64 characters for API_JWT_SECRET.
This is the recommended configuration size; the application rejects an empty
secret and the shipped default value. Rotating it invalidates existing
tokens, so coordinate the restart and user reauthentication. Treat the initial admin credential
as a bootstrap secret and rotate it under the customer’s identity procedure.
In the standard Ubuntu installation, docker-compose.yml forwards
API_PROVIDER_SECRET_KEY and CODEGRAPH_OUTBOUND_GIT_ORIGIN_ALLOWLIST
to api and temporal-worker. The following connection-encryption and
private-Git-origin steps apply to that profile. The standalone
docker-compose.prod.yml does not forward these variables in this version.
Use the standard profile to configure these two values.
API_PROVIDER_SECRET_KEY encrypts Git-provider tokens and webhook secrets stored through
the UI or REST API. It is empty by default; production cannot store an inline connection
token without it. Generate a separate random value, for example with
python3 -c 'import secrets; print(secrets.token_urlsafe(48))', and store it in the protected
.env. Generate it in a protected terminal without recording its output in logs or evidence. From /opt/codegraph, use Bash and the Compose files selected for this deployment to recreate the API and worker containers:
sudo docker compose up -d --no-deps --force-recreate api temporal-worker
Keep the key with the protected configuration backup: it decrypts tokens after database restoration. Preserve it during normal upgrades. Replacing it requires re-entering the previously stored connection tokens.
Network and browser origins
Set the externally reachable hosts and browser origins explicitly:
CORS_ALLOWED_ORIGINS=https://codegraph.customer.example
API_ALLOWED_HOSTS=codegraph.customer.example,api,codegraph-api
Do not use a wildcard origin with credentialed browser access. Terminate TLS according to the customer deployment design and expose only approved endpoints. For model, repository, telemetry and notification integrations, supply credentials and the approved network destinations for the selected service.
If an internal Git server resolves to a private address, the administrator can approve its
exact HTTPS origin in the protected .env:
CODEGRAPH_OUTBOUND_GIT_ORIGIN_ALLOWLIST=https://git.internal.example
The default is empty: no private Git origins are exempted. Separate multiple origins with
commas. List only trusted servers; IP ranges and wildcards are unsupported. Recreate api
and temporal-worker after changing the value, then test connection creation in the UI or
through POST /api/v1/integrations/repositories/provider-connections. The request schema
is available at <API_BASE_URL>/api/docs. Provide a Git access token when creating the connection.
Non-secret application settings
Use config.yaml to select runtime capabilities, limits, providers, and ${VARIABLE} references. Check parameter names and types against the config.yaml shipped with the installed version. Preserve the other settings when changing a section.
Change individual project settings through the dashboard project page or API. The next section gives a complete API example for configuring the audit scope.
Project audit scope
In versions supporting metadata.audit.scope, configure each project separately.
You need administrator permissions or the group’s editor role with access to the
project. See RBAC for role and project assignment.
This setting selects directories within that repository.
| Field | Default | Purpose |
|---|---|---|
version |
1 |
Format version; other values are rejected |
include_paths |
["."] |
Nonempty list of included paths relative to the project root |
exclude_paths |
Standard exclusions below | An explicit list replaces the standard exclusions |
test_paths |
[] |
Test paths and patterns within the included scope |
Standard exclusions are .git, .svn, .hg, node_modules, __pycache__, .venv,
venv, vendor, third_party, build, dist, target, bin, obj, .idea, and .vscode.
Version-control directories remain excluded even with an empty exclude_paths.
Paths are case-sensitive. Patterns support *, ?, and **; absolute paths,
.., and patterns containing !, {}, or [] are rejected. test_paths cannot
expand the scope: include test directories and do not exclude them.
This example includes the entire project with standard exclusions and classifies
tests as a test directory. Replace test_paths with your project’s paths. Save
the code as configure-audit-scope.py on your workstation. Python 3 is required;
no third-party packages are needed. Run python3 configure-audit-scope.py on
Linux/macOS or py -3 configure-audit-scope.py on Windows. Obtain the API URL from
your administrator, for example https://codegraph.customer.example. Swagger is
available at <API_BASE_URL>/api/docs.
import getpass
import json
import urllib.request
from urllib.parse import urlsplit
base = input("API base URL: ").strip().rstrip("/")
parsed = urlsplit(base)
local_http = parsed.scheme == "http" and parsed.hostname in {"localhost", "127.0.0.1", "::1"}
if not parsed.hostname or parsed.username or parsed.password:
raise ValueError("API URL must contain a host and no credentials")
if parsed.scheme != "https" and not local_http:
raise ValueError("Use HTTPS; HTTP is allowed only for a local loopback API")
username = input("Username: ").strip()
password = getpass.getpass("Password: ")
def call(path, token=None, data=None, method=None):
headers = {"Content-Type": "application/json"}
if token:
headers["Authorization"] = "Bearer " + token
request = urllib.request.Request(
base + path, headers=headers, method=method,
data=None if data is None else json.dumps(data).encode(),
)
with urllib.request.urlopen(request, timeout=60) as response:
return json.load(response)
token = call("/api/v1/auth/token", data={
"username": username, "password": password
})["access_token"]
del password
projects = call("/api/v1/projects", token)["projects"]
print("Available projects:", ", ".join(p["name"] for p in projects))
name = input("Project name: ").strip()
project_id = next(p["id"] for p in projects if p["name"] == name)
project = call("/api/v1/projects/" + project_id, token)
metadata = project["metadata"]
scope = {"version": 1, "include_paths": ["."], "test_paths": ["tests"]}
metadata.setdefault("audit", {})["scope"] = scope
call("/api/v1/projects/" + project_id, token,
data={"metadata": metadata}, method="PUT")
saved = call("/api/v1/projects/" + project_id, token)
assert saved["metadata"]["audit"]["scope"] == scope
print("Saved scope:", json.dumps(scope))
The script accepts HTTPS URLs and local loopback HTTP URLs only. It rejects credentials embedded in the URL before requesting a password. Use this example only for an approved project-scope change.
The example reads existing metadata and preserves other fields, including the
architecture policy. Coordinate the update with colleagues; do not edit this object
concurrently. Then start a new audit through the UI or Swagger:
POST /api/v1/traceability/projects/{project_name}/audit-report-jobs, with
{"language":"en","force_refresh":true} and your Bearer token. Use the project
name returned by the API; UUIDs are used only for /api/v1/projects/{id} requests.
Poll GET /api/v1/traceability/audit-report-jobs/{id} using the job id returned
by the start request. A scope change requires a new CPG freshness check even without
a new Git commit. Check source_revision and scope_digest in the downloaded report
and its manifest. Download the report using download_url and check analysis completeness.
For report_quality_status: "incomplete", use the report to diagnose the run:
find sections marked unsupported, not_measured or timeout and their reasons.
These identify an unsupported check, an absent measurement or an expired execution
deadline. Use the reasons to prepare the next run. When score_eligible: false,
the overall score is unavailable.
A job with status: "failed" and report_quality_status: "incomplete" can provide a diagnostic report. If the response contains a nonempty download_url, download it with the same Bearer token. If the link is empty, use error, report_quality_reason and stage_history to identify the cause and prepare the next run.
Audit report directory
Markdown reports and their integrity manifests are stored in
dashboard.audit_report_output_dir. The default is data/dashboard-audit-reports,
relative to the server working directory. In the standard Compose deployment this is
/app/data/dashboard-audit-reports: the data directory is mounted from the server
and survives container recreation.
To select another persistent location, add this parameter to the existing
dashboard section of config.yaml, preserving its other settings:
dashboard:
audit_report_output_dir: data/dashboard-audit-reports
A custom directory must be mounted into the api container as persistent storage
and writable by its user. Wait for active audits to finish, then restart the API
using the same Compose files as the installed deployment. Run an audit through the
UI or REST, download the available report, and repeat the download after recreating
the container. Keep each report and its .manifest.json together. The server
administrator configures this path in config.yaml.
Optional OpenViking memory
OpenViking supports document search and long-term memory. Embedding maps text to vectors for
search, rerank reorders retrieved results, and VLM generates text summaries and handles
images when the model supports them. These are separate settings. If you only need CPG and
deterministic source audit, disable document import with import_docs: false in REST or
--no-docs in the CLI.
On the Ubuntu server, deploy/openviking/ov.local-models.conf sets local embedding and
rerank. Check the listed models’ license terms before use. Set these values in the protected
.env:
COMPOSE_PROFILES=local-models
OPENVIKING_CONFIG_TEMPLATE=ov.local-models.conf
OPENVIKING_API_KEY=<secret-from-approved-store>
The shipped template configures Yandex VLM by default. For that provider, also set
YANDEX_API_KEY and YANDEX_FOLDER_ID in .env. For OpenAI, copy the template and
replace its vlm section: set provider: "openai",
api_base: "https://api.openai.com/v1", an available model, and an api_key through a
secret environment variable. Select the copy using OPENVIKING_CONFIG_TEMPLATE; add the key
variable to the openviking service environment and its startup substitution list in Compose.
The main API’s GIGACHAT_* variables do not configure OpenViking. GigaChat needs a compatible
endpoint with OAuth token refresh or a verified adapter.
After the change, run this on the server from the installation directory:
sudo docker compose -f docker-compose.yml up -d --force-recreate openviking
sudo docker compose -f docker-compose.yml exec -T openviking curl -fsS http://127.0.0.1:1933/health
After /health confirms service availability, import project documentation.
Check the import result with codegraph_project_context_sync_status and {}.
Configure automatic project checks
After importing the repository, connect its events. A push webhook supplies new commits for CPG updates; pull request or merge request events start review preparation. Follow the guide for your Git server:
- GitHub: repository connection, webhooks and pull request review.
- GitLab: repository connection, webhooks and merge request review.
- GitVerse: webhooks, synchronization and pull request review publication.
- SourceCraft: repository coordinates, webhooks and merge request review.
Choose events for the branches you use and verify a test push: wait for the synchronization job, then compare the CPG commit with the repository commit. For a PR/MR, inspect the review result and its publication in the target request.
Architecture control explains how to describe components and allowed dependencies in YAML, validate rules and apply them when checking changes.
To run checks regularly, configure automatic project audits: choose the cadence, time zone, service account and missed-run policy. Verify the first run and its saved report.
Apply and verify a change
- Back up the current
.env,config.yaml, and project declaration. - Change only the approved values; preserve file owner and restricted permissions.
- Restart CodeGraph through the service manager.
- Run the shared readiness command from the installation guide.
- Verify authentication, project visibility, CPG freshness, and the integration that changed.
For production acceptance, record container health, dependency readiness, access control, source provenance, and connectivity to the customer’s systems after the change.
Troubleshooting
- Startup rejects the JWT secret: generate a new 64+ character value and update the protected
.envfile. - Browser requests are rejected: compare the exact scheme and host with
CORS_ALLOWED_ORIGINSandAPI_ALLOWED_HOSTS. - A provider is unavailable: verify that provider’s secret reference, egress policy, and CA trust; do not disable TLS verification.
- A setting is unknown: compare it with the exact release’s
.env.exampleandconfig.yamlinstead of editing application source.
Next: Installation · Quick start