Skip to content

Support a custom host for repositories (GitHub Enterprise, self-hosted GitLab) #143

Closed

Description

@roxblnfk

DLoad always talks to api.github.com / gitlab.com: the API base is hardcoded in the repository API classes, and the GitHub factory keeps only the org/repo part of uri. So there is no way to point a <repository> at GitHub Enterprise Server, a self-hosted GitLab, or any other on-premise instance.

Proposal

A host attribute on <repository>: a host name with an optional port, no scheme and no path. Defaults to the public host of the repository type (github.com / gitlab.com).

<registry>
    <software name="RoadRunner" alias="rr">
        <repository type="github" uri="roadrunner-server/roadrunner" host="ghe.example.com"/>
    </software>
    <software name="Tool" alias="tool">
        <repository type="gitlab" uri="group/tool" host="gitlab.example.com:8443"/>
    </software>
</registry>
  • No host → behaviour stays exactly as today.
  • With host, the repository API derives its base URL from it (e.g. for GitHub Enterprise Server https://<host>/api/v3, for GitLab https://<host>/api/v4) instead of the hardcoded constants.

Open questions

  • Tokens. GITHUB_TOKEN / GITLAB_TOKEN are currently sent only to the public hosts. A custom host needs a way to opt in, otherwise private enterprise repositories can't be reached, while blindly sending the token to any configured host is a leak risk.
  • Scheme. Real instances are HTTPS. A local test server (127.0.0.1:<port>) is usually plain HTTP — decide whether loopback hosts may use http://, or tests must serve TLS.

Side benefit

This also lets tests run DLoad against a local fake API server (e.g. host="127.0.0.1:8080"), which is what roadrunner-php/cli needs: its rr get acceptance tests (roadrunner-php/cli#66) run against such a server, and roadrunner-php/cli#49 (switching rr get to DLoad) can only pass them once DLoad supports host.

Activity

  1. changed the title [-]Support custom hosts in repository uri (GitHub Enterprise, self-hosted GitLab)[/-] [+]Support a custom host for repositories (GitHub Enterprise, self-hosted GitLab)[/+] on Oct 9, 2026
  2. roxblnfk commented on Oct 10, 2026

    @roxblnfk
    MemberAuthor

    Design

    server attribute

    The attribute is named server rather than host: it carries the scheme too (same meaning as GITHUB_SERVER_URL in GitHub Actions).

    <repository type="github" uri="org/repo" server="https://ghe.example.com"/>
    <repository type="gitlab" uri="group/tool" server="gitlab.example.com:8443"/>
    <repository type="github" uri="org/repo" server="http://127.0.0.1:8080"/>
    • Format: [scheme://]host[:port], no path, query or credentials. The scheme defaults to https; only http and https are accepted.
    • No server → behaviour stays exactly as today. An explicit https://github.com / https://gitlab.com is the same as the default.
    • The value is normalized (lower case, default port dropped).

    API base URL

    type default custom server
    github https://api.github.com {server}/api/v3
    gitlab https://gitlab.com/api/v4 {server}/api/v4

    Tokens

    A token is declared per server in the environment: DLOAD_TOKEN_ + host and port, upper-cased, every non-alphanumeric character replaced with _:

    • ghe.example.com → DLOAD_TOKEN_GHE_EXAMPLE_COM
    • gitlab.example.com:8443 → DLOAD_TOKEN_GITLAB_EXAMPLE_COM_8443
    server token source, by priority
    github.com (default) DLOAD_TOKEN_GITHUB_COM, then GITHUB_TOKEN
    gitlab.com (default) DLOAD_TOKEN_GITLAB_COM, then GITLAB_TOKEN
    custom DLOAD_TOKEN_<HOST> only
    • GITHUB_TOKEN / GITLAB_TOKEN are never sent to a custom server.
    • The config cannot choose which variable is read: only the user's environment opts a host in, so a foreign dload.xml can't exfiltrate a token or any other variable.
    • A custom server's token is attached only to requests to the same scheme, host and port (no subdomains). The default servers keep today's rule (api.github.com, github.com, *.githubusercontent.com).
    • No token over plain http, except loopback (localhost, 127.0.0.0/8, ::1), so a local fake server can still test authentication.
    • The GitLab client stops attaching the token to every request and gets the same host check.
    • Error messages (401 / 403 / rate limit) name the variable that was actually consulted.

    Version registry

    • Repository::getId(): RepositoryId; the downloader takes the registry key from the repository instead of building it from the config.
    • RepositoryId gets an optional server (null for the public host). A custom server is stored under github@ghe.example.com/org/repo; default paths are unchanged, so existing registries stay valid.
    • RepositoryRecord gets an optional repository.server field; records without it read as the public host, so no format version bump.
  3. roxblnfk commented on Oct 12, 2026

    @roxblnfk
    MemberAuthor

    Change of design: the server comes from uri, not a server attribute

    The design above added a server attribute next to uri. Review of #148 showed that uri already accepted a full URL and silently dropped its host: uri="https://ghe.corp.com/infra/tool" downloaded infra/tool from github.com. Keeping both attributes would leave two places to name a server and a conflict between them to resolve, while the URL alone carries everything the attribute did (scheme, host, port). The attribute was never released, so it is dropped.

    Now:

    <repository type="github" uri="https://ghe.example.com/owner/repo"/>
    <repository type="gitlab" uri="https://gitlab.example.com:8443/group/sub/project"/>
    <repository type="github" uri="http://127.0.0.1:8080/owner/repo"/>
    • owner/repo and https://github.com/owner/repo (or gitlab.com) work as before, with the same registry keys and tokens.
    • A value without a scheme never names a server. github.com/owner/repo still reads as the public host; for GitHub a scheme-less foreign host (ghe.example.com/owner/repo) is an error instead of a silent download from github.com.
    • The rest of the design stands: {server}/api/v3 / {server}/api/v4, plain http only for loopback, per-server registry keys, and per-server tokens — with an injective variable name now (. → _, - → __, port after ___), so ghe-example.com cannot read the token of ghe.example.com. Tokens are also dropped on redirects that leave their server.
  4. added 2 commits that reference this issue on Oct 12, 2026
    d181637
    a90a2f7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions