gitlab-org/gitlab
Internal API
The endpoints under /api/v4/internal/ exist so other GitLab services can talk back to Rails. They are not part of the public API.
Callers
- GitLab Shell (SSH entry point) →
/api/v4/internal/allowed,/lfs_authenticate, etc. - Workhorse →
/authorizeendpoints and "preauthorize" handshakes for uploads / git-over-HTTP. - KAS →
/api/v4/internal/kubernetes/*. - Pages →
/api/v4/internal/pages/*. - GitLab Zoekt indexer →
/api/v4/internal/search/zoekt/*. - GitLab Elasticsearch indexer →
/api/v4/internal/elastic/*. - Geo secondaries →
/api/v4/geo/*. - Gitaly hooks →
/api/v4/internal/post_receive,/internal/pre_receive, etc. - Bulk imports source →
/api/v4/internal/bulk_imports/*. - Cloud Connector / AI Gateway →
/api/v4/internal/ai/....
Source
lib/api/internal/
├── base.rb # /allowed, /authorized_keys, /lfs_authenticate, /post_receive
├── kubernetes.rb # KAS callbacks
├── pages.rb # Pages metadata
├── workhorse.rb # Workhorse preauth
├── shell.rb # GitLab Shell helpers
├── observability.rb
├── bulk_imports/
├── search/zoekt/
├── elastic/ # EE
└── ...
ee/lib/api/internal/ # Geo and EE-only endpointsAuthentication
Internal endpoints use shared-secret JWT or an API token. Notable schemes:
- GitLab Shell secret (
/etc/gitlab/gitlab-shell-secret): a long-lived shared secret for SSH callbacks. - Workhorse secret (
/etc/gitlab/.gitlab_workhorse_secret): a shared HMAC for the X-Workhorse-Token header. - KAS JWT: per-agent token stored in
Clusters::AgentToken. - Gitaly hook token:
Gitlab::Shell::Hookshared secret.
The guard API::Helpers::InternalHelpers validates each request.
Examples
/api/v4/internal/allowed (called by Shell on every SSH push/pull)
Inputs: action (git-receive-pack etc.), key id or user id, project, ref, oldrev/newrev. Outputs: GL_ID, GL_USERNAME, GL_REPOSITORY, GL_PROJECT_PATH, gitaly addr+token, "status: true/false" with reason.
This call is the trust boundary that decides whether a git push proceeds.
/api/v4/internal/post_receive
Called by Gitaly's post-receive hook. Triggers downstream pipelines, hooks, and emits the "push" domain event.
/api/v4/internal/kubernetes/agent_info
Called by KAS to validate an agent token and return agent metadata.
/api/v4/internal/lfs_authenticate
Called by Shell when a user pushes/pulls LFS over SSH.
Why a separate API?
- Different auth model — shared secret instead of per-user PATs.
- Different rate-limit profile — high-volume, machine-to-machine.
- Allows internal contracts to evolve quickly without breaking external clients.
Where to make changes
- New internal endpoint: add to
lib/api/internal/<area>.rband mount inlib/api/api.rb. - New auth scheme: extend
API::Helpers::InternalHelpersand document the shared secret.
Related
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.