Environment Variables
glci reads environment variables to control its own behavior and sets CI/CD variables inside job containers to emulate GitLab CI. This page covers both categories.
glci control variables#
These variables configure glci itself. Set them in your shell or .glci.env before running glci.
Paths & data directory#
| Variable | Default | Description |
|---|---|---|
GLCI_HOME | ~/.glci | Override the data directory where glci stores daemon state, pipeline history, registry data, and logs. Useful for test isolation or running multiple daemon instances. |
GLCI_NO_DEFAULT_CONFIG | (unset) | Set to 1 to prevent glci from auto-creating a .glciconfig.toml when none exists. By default, glci creates one with [skip] stages = [".pre"]. |
# Use a custom data directory
export GLCI_HOME=/tmp/glci-test
glci run
# Disable auto-creation of .glciconfig.toml
GLCI_NO_DEFAULT_CONFIG=1 glci run
Daemon#
| Variable | Default | Description |
|---|---|---|
GLCI_DAEMON_SOCK | ~/.glci/daemon.sock | Override the Unix socket path for daemon communication. Useful when running parallel daemon instances (e.g. in CI). |
export GLCI_DAEMON_SOCK=/tmp/my-glci.sock
glci run
Container engine (Docker / Podman)#
| Variable | Default | Description |
|---|---|---|
DOCKER_HOST | (auto-detected) | Docker daemon endpoint, used when the engine is Docker. Outranks the active Docker context — see Endpoint resolution order. |
DOCKER_CONTEXT | (unset) | Selects a named Docker context. glci does not read it to pick an endpoint; it resolves the current context, which the docker CLI derives from DOCKER_CONTEXT first and ~/.docker/config.json second. Outranked by DOCKER_HOST. The name in effect at resolution is recorded, so changing it is reported as drift. |
CONTAINER_HOST | (auto-detected) | Podman’s endpoint variable, used when the engine is Podman ([docker] engine = "podman"). |
CONTAINER_CONNECTION | (unset) | Selects a named podman system connection. Podman ranks this above CONTAINER_HOST, and so does glci. Left in place for podman commands so the connection’s own SSH identity still applies. |
CONTAINER_SSHKEY | (auto-detected) | SSH identity for an ssh:// CONTAINER_HOST — the form used by podman machine (the macOS/Windows default) and remote Podman hosts. Exported alongside CONTAINER_HOST when the endpoint was resolved from the default connection, using its Identity, because setting CONTAINER_HOST overrides the named connection podman would otherwise read the key from. An inherited value is left alone. |
DOCKER_CONFIG | ~/.docker | Directory containing Docker config.json. Used for Docker Hub credentials that are propagated into DinD containers. Read from the environment the daemon was spawned with, so changing it takes effect after glci daemon stop. |
DOCKER_CERT_PATH | (unset) | Directory containing TLS client certificates (ca.pem, cert.pem, key.pem). Per-runner override: tls_cert_path in [runners.<name>]. Docker only — Podman does not honor it. |
DOCKER_TLS_VERIFY | (unset) | Set to 1 to enable TLS verification. Per-runner override: tls_verify in [runners.<name>]. Docker only — Podman does not honor it. |
The config keys that back these variables — [docker] engine/host/container_socket and the per-runner engine, docker_host, docker_context, container_socket, tls_cert_path, tls_verify — are honored only in ~/.glci/config.toml. A project .glciconfig.toml that sets them has them dropped with a warning. See Config files > Container-endpoint keys.
Whenever a named runner targets its own endpoint — via either docker_host or docker_context — glci strips DOCKER_HOST, DOCKER_CONTEXT, CONTAINER_HOST, CONTAINER_CONNECTION, CONTAINER_SSHKEY, DOCKER_CERT_PATH, and DOCKER_TLS_VERIFY from that command’s environment before applying the runner’s own settings. The --context/--connection flags do outrank the variables, so for that path stripping is defence in depth; it is load-bearing for the raw-endpoint path, because Podman ranks CONTAINER_CONNECTION above CONTAINER_HOST and would otherwise send a runner that sets docker_host to whatever connection the ambient variable names.
Endpoint resolution order#
The daemon resolves one endpoint at startup, mirroring each engine’s own precedence:
| Docker | Podman | |
|---|---|---|
| 1 | [docker] host in ~/.glci/config.toml | [docker] host in ~/.glci/config.toml |
| 2 | DOCKER_HOST | CONTAINER_CONNECTION (named connection) |
| 3 | active context (docker context use / DOCKER_CONTEXT) | CONTAINER_HOST |
| 4 | Docker CLI default | default podman system connection, then Podman’s default |
Only [docker] host outranks the environment. Two endpoint values are refused rather than passed to the engine:
- A value whose scheme is not
unix://,tcp://,ssh://,npipe://, orfd://is ignored with a log line (a bogusunix://path would otherwise become the socket bind-mount source inside runner containers). - Whitespace-only values, from either the environment or a heredoc-written config, are treated as unset.
When the endpoint does not come from the environment (config, context, or connection), glci also drops inherited DOCKER_CERT_PATH/DOCKER_TLS_VERIFY: those name trust anchors for one specific daemon, and keeping them against a different endpoint is a false assurance of TLS.
Because the TLS variables are Docker-only, a runner with engine = "podman" and a tcp:// docker_host gets no TLS even with tls_cert_path/tls_verify set (glci config --network warns about this). For a remote Podman endpoint, use an ssh:// endpoint — Podman’s only authenticated and encrypted remote transport. A podman system connection referenced via docker_context is only as secure as its own URI: a connection pointing at tcp:// is still unencrypted and unauthenticated.
# Point glci at a remote Docker daemon
export DOCKER_HOST=ssh://remote-host
glci run
# Point glci at a remote Podman endpoint
export CONTAINER_HOST=ssh://podman-host
glci run
# Use a custom Docker config directory
export DOCKER_CONFIG=/path/to/docker-config
glci run
An exported endpoint variable takes precedence over the active Docker context (and over the default podman system connection), matching how the docker and podman CLIs themselves behave. So a remote daemon can be selected per shell, with no config file changes:
DOCKER_HOST=tcp://build-box:2375 glci run
Security: glci sends more to the resolved endpoint than
dockeralone does — the repository tree, your~/.docker/config.jsonregistry credentials, and the forwarded GitLab token all land on that daemon. A plaintcp://endpoint carries them unencrypted and unauthenticated, so glci prints a warning when it resolves one without TLS. Preferssh://, or configure Docker TLS.
Endpoint changes and the shared daemon#
The glci daemon is process-global and resolves its endpoint once at startup, inheriting the environment of the CLI invocation that spawned it. A later command that selects a different endpoint does not restart it — glci reports the mismatch once and leaves the daemon alone:
glci: warning: daemon is using unix:///var/run/docker.sock but $DOCKER_HOST selects tcp://build-box:2375
glci: run `glci daemon stop` to pick it up (the daemon re-starts on the next command)
Restarting is deliberately not automatic. Endpoint selection is per-shell while the daemon is global, so auto-restarting would let two shells with different DOCKER_HOST values evict each other’s daemon on every command — and a restart races any pipeline that starts while it is being decided. glci daemon stop is the explicit switch; the daemon re-starts with the new endpoint on the next command. If pipelines are still running, the warning says how many, because stopping the daemon cancels them.
Four mismatches are reported:
- A different endpoint is selected than the daemon resolved.
- An explicit selection was removed — you ran
DOCKER_HOST=… glci runearlier and this shell has none. Without this, a one-shot variable would keep serving every later clean shell for the daemon’s whole lifetime. - The selection is for the other engine — an unreachable
DOCKER_HOSTmakes a fresh daemon fall back to Podman, which would silently drop the endpoint you asked for. - A different context/connection is selected —
DOCKER_CONTEXT/CONTAINER_CONNECTIONdiffers from the name the daemon resolved with. The name is compared, not the endpoint it maps to, so this costs no subprocess.
One case is not detected: running docker context use other, which changes the current context on disk without changing any variable. Catching that would mean asking the docker CLI for the context’s endpoint on every glci command. glci daemon status and glci doctor both report the endpoint in use (and the context it came from), and doctor says explicitly when a value was not compared.
GitLab API#
| Variable | Default | Description |
|---|---|---|
GITLAB_URL | (auto-detected from git remote) | GitLab instance URL. Overrides auto-detection from git remote and config file settings. Falls back to https://gitlab.com. |
GITLAB_TOKEN | (unset) | GitLab personal access token or CI job token. Used for cross-project includes, fetching remote CI/CD variables, and auto-cloning trigger targets. |
GITLAB_PRIVATE_TOKEN | (unset) | Alias for GITLAB_TOKEN. If both are set, GITLAB_TOKEN takes precedence. |
export GITLAB_URL=https://gitlab.example.com
export GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
glci run
Parsing behavior#
| Variable | Default | Description |
|---|---|---|
GLCI_PREFER_API | (unset) | Set to 1 to use the GitLab Lint API as the primary CI config parser instead of the offline parser. The offline parser is the default (with API as fallback). |
GLCI_PREFER_API=1 glci run
Cache (internal, mock server)#
These variables are set internally by the daemon when launching the mock server container. They are documented here for completeness but are not typically set by users.
| Variable | Default | Description |
|---|---|---|
GLCI_MOCK_PORT | 39741 | Port the mock server listens on inside its container. Set by the daemon from the resolved mock_server_port config value. Configurable via [network] mock_server_port in config.toml. |
GLCI_CACHE_DIR | (unset) | Disk-backed cache directory for the mock server. Set by the daemon to /cache-store inside the mock container. When unset, cache stays in memory. |
GLCI_CACHE_MAX_SIZE | 500MB | Maximum total size for CI cache entries. Uploads are rejected when this limit is exceeded. Accepts suffixes: KB, MB, GB. |
GLCI_CACHE_TTL | 24h | Time-to-live for cached entries. Entries older than this are expired. Uses Go duration format (e.g. 1h30m, 24h). |
Editor#
| Variable | Default | Description |
|---|---|---|
EDITOR | (unset) | Used by glci config edit to open the project config file. Falls back to VISUAL if unset. |
VISUAL | (unset) | Fallback editor when EDITOR is not set. |
export EDITOR=vim
glci config edit
Simulation#
| Variable | Description |
|---|---|
GLCI_SIMULATE | Set to true inside job containers when running in --simulate mode. Not typically set by users; scripts can check this to detect simulation. |
CI/CD variables set in jobs#
glci populates standard GitLab CI/CD predefined variables inside job containers. Commit, project, server, pipeline, job, user, and runner variables are all derived from local git state and mock server configuration, matching what GitLab CI would set.
The following variables behave differently in glci compared to GitLab CI:
Variables with fixed/local values#
| Variable | glci value | Why it differs |
|---|---|---|
CI_COMMIT_BEFORE_SHA | 0000000000... (null SHA) | No previous pipeline to compare against locally |
CI_COMMIT_REF_PROTECTED | false | Protected branch status is not available locally |
CI_PROJECT_ID | 0 | No real project ID locally |
CI_PROJECT_NAMESPACE_ID | 0 | No real namespace ID locally |
CI_PROJECT_VISIBILITY | private | Not detectable locally |
CI_PIPELINE_IID | Same as CI_PIPELINE_ID | No project-scoped counter separation locally |
GITLAB_USER_LOGIN | Same as GITLAB_USER_NAME | No GitLab account mapping; uses git config user.name |
GITLAB_USER_ID | 0 | No real user ID locally |
CI_RUNNER_ID | 1 (default runner) | Per-runner ID; named runners ([runners.<name>]) get unique IDs |
CI_RUNNER_DESCRIPTION | glci-local-runner (default runner) | Per-runner description; named runners use their container name |
CI_JOB_TOKEN | Synthetic mock token | Unless real token is forwarded via [token] config |
Registry variables#
Set when the embedded container registry is active (default).
| Variable | Source |
|---|---|
CI_REGISTRY | Embedded registry address (e.g. host.docker.internal:12345) |
CI_REGISTRY_USER | gitlab-ci-token |
CI_REGISTRY_PASSWORD | Set per-job; equals CI_JOB_TOKEN |
CI_REGISTRY_IMAGE | Registry address + project path |
DOCKER_AUTH_CONFIG | Docker auth JSON merged with host ~/.docker/config.json |
Environment and release variables#
CI_ENVIRONMENT_* variables are set when a job has an environment: keyword. CI_RELEASE_DESCRIPTION is set when a job has a release: keyword (truncated to 1024 chars).
Merge request variables#
Set when using --context merge_request.
| Variable | glci value |
|---|---|
CI_PIPELINE_SOURCE | merge_request_event |
CI_MERGE_REQUEST_SOURCE_BRANCH_NAME | Current git branch (or --mr-source) |
CI_MERGE_REQUEST_TARGET_BRANCH_NAME | Default branch (or --mr-target) |
CI_MERGE_REQUEST_IID | 1 |
CI_MERGE_REQUEST_TITLE | local |
Variable precedence#
See Variables & Secrets for the full precedence table and details on remote secrets, .glci.env, and token resolution.