Self-managed GitLab

Every connection detail labdash needs for a self-managed instance is a per-instance key in the settings file: the host, the API host, a subfolder, TLS material, a proxy, and custom headers.

Personal access tokens

On a self-managed instance a personal access token is the recommended path. OAuth needs an application registered on that instance, and the gitlab.com application id means nothing on gitlab.example.com.

A token also lasts longer: up to 365 days, against two hours for an OAuth access token.

Create it at https://gitlab.example.com/-/user_settings/personal_access_tokens with the api scope, or read_api for read-only mode. Then run labdash, choose a self-managed instance, name the host, and paste the token. For a script:

echo "$TOKEN" | labdash auth login --hostname gitlab.example.com --with-token

Registering an OAuth application

If an administrator registers an application, OAuth works and renews itself. The form is at https://gitlab.example.com/-/user_settings/applications, or the instance-wide equivalent.

FieldValueWhy
NamelabdashShown on the consent screen
Redirect URIhttp://localhost:7171/auth/redirectOnly the browser fallback uses it, and --web fails without it. Port 7171 matches glab's, so an administrator who registered that reuses the value
ConfidentialuncheckedA CLI binary is a public client. It cannot keep a secret, so it must not be issued one
Device authorization grantcheckedThe load-bearing box. Unchecked, every login falls back to the browser flow
Scopesapi, read_api, read_userThe maximum a login may request, not what it grants

Name the application in your settings, then log in:

settings.yml
instances:
  gitlab.example.com:
    clientId: <the application id>
Minimum version for the device flow

GitLab 17.9, where the device authorization grant became generally available. Below that, labdash falls back to the loopback browser flow automatically, or you use a token.

Transport settings

Every key below is per instance.

settings.yml
defaultHost: gitlab.example.com

instances:
  gitlab.example.com:
    # Authentication
    clientId: <application id>       # OAuth application registered on this instance
    tokenEnv: GITLAB_WORK_TOKEN      # or skip OAuth: name a variable holding a PAT

    # Where the API lives
    apiHost: api.example.com         # only if the API is on a different hostname
    apiProtocol: https
    subfolder: gitlab                # only if GitLab is not at the domain root

    # TLS
    caCert: /etc/ssl/corp-root.pem
    clientCert: /etc/ssl/client.pem
    clientKey: /etc/ssl/client-key.pem
    insecureSkipVerify: false

    # Network
    proxy: http://proxy.internal:3128
    customHeaders:
      - name: Cf-Access-Client-Secret
        valueFromEnv: CF_ACCESS_SECRET

A host with no entry still works and gets the defaults, which is correct for gitlab.com. HTTPS_PROXY and NO_PROXY from the environment are honoured, and an explicit proxy: overrides them. Each instance gets its own HTTP client, with its own CA pool, its own client certificate and its own proxy, so one unreachable instance degrades only its own rows.

The private CA is added to the system pool rather than replacing it, so an instance behind a corporate root still reaches the public hosts it redirects to. A clientCert without its clientKey is refused at startup, with the host named, rather than failing later as a handshake error nobody can read.

Field-by-field reference: instances.

Writing the entry from the application

You do not have to create the file by hand. Signing in to a host with no entry offers to write one, and that is the moment the settings file is created. Nothing writes a starter file before then.

Subfolder installs

If GitLab lives at https://example.com/gitlab/ rather than at a domain root, set subfolder: gitlab. Every URL labdash builds then includes it: the GraphQL endpoint, the REST endpoint, and the OAuth endpoints.

https://api.example.com/gitlab/api/graphql

OAuth endpoints hang off the web host rather than apiHost. Only the API is ever proxied elsewhere.

Custom headers

valueFromEnv reads the value at runtime from the named environment variable. The secret never enters the settings file, so the file stays safe to commit or to share with a colleague.

Tokens from the environment

The cleanest multi-instance setup puts no credential on disk at all:

settings.yml
instances:
  gitlab.example.com:
    tokenEnv: GITLAB_WORK_TOKEN
  gitlab.com:
    tokenEnv: GITLAB_OSS_TOKEN

An instance's tokenEnv is the most explicit signal available, so it wins over a credential labdash stored itself.

Warning

GITLAB_TOKEN applies to the default host only GITLAB_TOKEN, GITLAB_ACCESS_TOKEN and OAUTH_TOKEN are not host-scoped. Applying them to a named host would send one instance's token to another, so labdash does not. For a named host, use that instance's tokenEnv.

Diagnostics

labdash auth status --hostname gitlab.example.com
labdash settings show

auth status reports who the credential belongs to, where it is stored, when it expires and which settings file was read. settings show prints the instances and calls out any host with TLS verification switched off. Neither ever prints a credential. More at diagnostics.