Repo hosts
A repo host is a saved connection to a Git provider: a GitLab instance, a Gitea or Forgejo instance, or a GitHub account or organisation. You add it once per workspace, and every repository you connect afterwards reuses it. Loha never stores your source; the host is only the credential and address it uses to read your repos.
Manage them at Settings → Repo hosts.
Anyone who can see the workspace can view the list. Adding, editing, validating, and deleting a host are limited to Owners and Admins. See Members & roles. A personal access token used against the API needs connections:read to list hosts, or connections:write to change them. The stored access token is never returned by any endpoint.
Supported hosts
All four external providers connect the same way, under Settings → Repo hosts → Connect repo host: a name, an API URL, and an access token.
| Host | What you provide |
|---|---|
| GitLab | The instance URL (Loha appends /api/v4 if you leave it off) plus an access token |
| GitHub | https://api.github.com, or your GitHub Enterprise Server API base, plus an access token |
| Gitea | The instance URL (Loha appends /api/v1 itself) plus an access token |
| Forgejo | Same as Gitea: Forgejo keeps Gitea's /api/v1 surface |
| Loha Repos | Opt-in preview, not generally available |
Both self-managed and hosted instances work. Loha only needs to reach the API URL you give it.
Forgejo is its own choice rather than a "Gitea / Forgejo" label even though the two speak an identical API dialect: the provider is shown on every repository, and a repo on your own Forgejo should say so.
A GitHub App installation is a different mechanism from the token flow above: organisation-scoped, with short-lived tokens Loha mints per request instead of one you paste and rotate. Loha's backend understands App-backed hosts, but there is no way to create one from the portal today; the install flow is not shipped. Connect GitHub with an access token, as above. A workspace that already has an App-backed host from an earlier release keeps it, and it still works. Only its name is editable.
Connecting a repo host
Open Settings → Repo hosts → Connect repo host and fill in:
| Field | What to enter |
|---|---|
| Name | A label for this connection, e.g. Company GitLab. Must be unique in the workspace. |
| Provider | GitLab, GitHub, Gitea, or Forgejo. This cannot be changed later: to switch, delete the host and add a new one. |
| API URL | GitLab: https://gitlab.example.com (/api/v4 is added). GitHub: https://api.github.com, or your GHES API base. Gitea/Forgejo: https://gitea.example.com (/api/v1 is added). |
| Access token | A token that can read the repositories you want to connect (see the scopes below). |
The token is encrypted before it is stored and is never shown again; see Editing a host to rotate it.
What permissions the token needs
Loha does three things with this token, and only the first is required. It reads your repositories: listing the ones you can connect, fetching .loha.yml, listing branches. It posts a build status back to the commit and merge request. And it registers the webhook that starts a build on push. It never pushes code.
| Provider | Read repositories (required) | Report build status (optional) | Register webhooks (optional) |
|---|---|---|---|
| GitLab | read_api | api | api |
| GitHub, fine-grained | Contents: Read-only and Metadata: Read-only | Commit statuses: Read and write | Webhooks: Read and write |
| GitHub, classic | repo, or public_repo if every repo is public | already covered by repo | admin:repo_hook |
| Gitea / Forgejo | read:repository | write:repository | write:repository |
Pick the widest scope you want rather than several overlapping ones: GitLab's api covers all three columns on its own, and Gitea's write:repository covers all three of its.
Both optional columns buy you something specific, and skipping either is a normal choice. Without the status permission your builds still run. The pass/fail check simply never appears on the commit. Without the webhook permission your triggers still work: Loha just hands you the URL and secret to paste into your host yourself, once per trigger, instead of adding the webhook for you. Neither is required to build.
Gitea and Forgejo issue scoped tokens from version 1.20; older releases issue a token carrying your full account access, with no scopes to select.
read_repository on its own is not enoughThat scope covers Git-over-HTTP and the Repository Files API, but Loha discovers your repositories through GET /projects on the REST API, which it does not cover. The host will save (the connection probe only reads a file) and then list nothing when you go to connect a repository. Use read_api, or api if you also want status checks.
Loha registers the webhook that starts a build on push only if you grant the third column. It is the one permission that lets Loha write anything to your repository settings, so it is deliberately opt-in. See Connecting repositories from a host for what happens either way.
What Loha checks when you connect
Before saving, Loha probes your host live: it asks for a file in a repository that deliberately does not exist. A 404 is the success signal: it proves the token authenticated and was allowed to look. Only two answers count as a failure:
Invalid access token. Check that the token is correct and not expired.: the token is wrong, expired, or was revoked.Insufficient permissions…: the token is real but too narrow. The rest of the message names the scope your provider needs, and matches the table above.
If the probe fails, the host is not saved and nothing is stored. The same two messages come back from Validate on an existing host, and from Edit when you paste a replacement token.
Two limits are worth knowing, both because the probe only reads a file. It does not prove that repository listing works: a token that can read contents but cannot enumerate repositories passes here and then finds nothing (see the troubleshooting entry). And it does not prove the token can register webhooks; that is only discovered when you create a trigger, which is why a refusal there is reported calmly rather than as a failure.
Connecting repositories from a host
Once a host exists, go to Repositories → Connect repository, pick the host, and Loha lists the projects that token can see. Choose one and it is connected. You never paste a token per repository. (You can also add a host inline from that dialog; it is saved to Settings → Repo hosts just the same.)
Connecting a repository does not register a webhook. The trigger does. When you create one, Loha adds the webhook to the repository for you if the host's token carries the webhook permission from the table above. If it doesn't, you get the URL and secret to add by hand instead, once per trigger. Either way, until the webhook exists pushes will not reach Loha.
Validating a host
Validate on a host row re-runs the same probe used at connect time and updates the status badge:
- Connected: the token still works.
- Invalid: the token no longer authenticates. The host and its repositories are left in place; fix it by editing the host and pasting a new token.
A host that worked when you added it can go invalid later, most often because the token expired, was revoked, or the account that owns it lost access to the group.
Editing a host
Open Edit on a host row:
- Name can always be changed.
- API URL and Access token can be changed on any token-based host: GitLab, GitHub, Gitea, Forgejo. The token field starts blank: leave it blank to keep the current token, or paste a new one to replace it. Rotating a token is exactly this flow, and it is also how you widen a token whose scopes turned out to be too narrow.
- Provider cannot be changed.
- For a GitHub App host, only the name is editable: there is no URL or token to change. Manage its access from the App's installation settings on GitHub.
Deleting a host
A host cannot be deleted while repositories still use it. The attempt is refused with a conflict (409) and Loha names the repositories that are still attached. Disconnect those repositories first, then delete the host.
Deleting a GitHub App host also removes the stored installation record. It does not uninstall the App from GitHub. Do that from GitHub's own settings.
Loha Repos
Repositories hosted by Loha itself are an opt-in preview and are not generally available. Workspaces without it see only the external hosts above; nothing here changes for them. Progress is tracked on the roadmap.
Troubleshooting
The host shows Invalid, but it worked yesterday. The stored token stopped authenticating: expired, revoked, or the owning account lost access to the group or organisation. Edit the host, paste a fresh token, and run Validate to confirm.
Connecting fails with Insufficient permissions.
The token authenticated but cannot read repository contents. The message names the scope to add for your provider; the scopes table has the same answer with more context.
The host saved fine, but no repositories are listed.
The token can read file contents but cannot enumerate repositories, so it passed the probe and then found nothing. On GitLab this is read_repository without read_api (the usual cause). Edit the host and paste a token with the read scope from the table.
The build's pass/fail check never appears on the commit or merge request.
Reporting status is a separate, optional permission: api on GitLab, Commit statuses: Read and write on a fine-grained GitHub token, write:repository on Gitea or Forgejo. Builds run either way, so nothing else looks broken. Rotate the token with the wider scope to turn checks on.
Connecting fails and the API URL is a private or internal address. Loha refuses API URLs that resolve to internal network addresses, on every provider. A self-managed instance must be reachable from Loha at a public address.
Deleting the host is refused. Repositories still reference it. The error lists them; disconnect each one under Repositories, then delete the host.
I connected a repository but no builds start on push. A repository alone starts nothing. Check it has a trigger. If it does, check the webhook exists in your Git host: Loha adds it only when the stored token carries the webhook permission, and otherwise hands you the URL and secret to add yourself. The trigger's Settings tab shows a Managed by Loha badge when Loha created the webhook.
Where to go next
- Repositories & Git hosts: what a repository is in Loha
- Triggers: registering the webhook and choosing what starts a build
- Container registries: where the images your builds produce are pushed
- Members & roles: who can manage repo hosts