# GitLab Self-Hosted Personal Access Token Setup

When connecting a self-hosted GitLab instance to Elestio CI/CD, you must provide a **Personal Access Token (PAT)** with the `api` scope. This guide explains exactly how to create it and why that specific scope is required.

---

##### Step-by-step: Create a Personal Access Token

1. Sign in to your self-hosted GitLab instance.
2. Click your avatar (top-right) → **Preferences** → **Access Tokens**  
    *(or go directly to `/-/profile/personal_access_tokens`)*
3. Fill in:
    
    
    - **Token name** — e.g. `elestio-cicd`
    - **Expiration date** — optional, depending on your team’s policy
4. Under **"Select scopes,"** enable **only** the `api` scope (details below).
5. Click **Create personal access token**.
6. **Copy the token immediately** — GitLab will not display it again.

[![image.png](https://docs.elest.io/uploads/images/gallery/2026-05/scaled-1680-/image.png)](https://docs.elest.io/uploads/images/gallery/2026-05/image.png)

---

##### Required scope: `api` (mandatory, no substitutes)

<table id="bkmrk-scope-why-it-is-need" style="width: 100%;"><thead><tr><th style="width: 7.74696%;">Scope</th><th style="width: 92.2247%;">Why it is needed</th></tr></thead><tbody><tr><td style="width: 7.74696%;">`api`</td><td style="width: 92.2247%;">**Mandatory.** Grants full REST API read/write access. Elestio requires this for creating and deleting **webhooks** (to track pushes), managing **deploy keys** (SSH access for CI runners), creating **projects from templates**, listing projects and groups, reading repository content, and performing git-over-HTTPS operations (`oauth2:<token>@...`) during deployments.</td></tr></tbody></table>

---

##### Why narrower scopes are not enough

It may seem possible to combine smaller scopes, but in practice, they do not cover what CI/CD needs:

<table id="bkmrk-scope-what-it-covers"><thead><tr><th>Scope</th><th>What it covers</th><th>What it is missing</th></tr></thead><tbody><tr><td>`read_api`</td><td>Read-only REST API</td><td>No write access</td></tr><tr><td>`read_repository`</td><td>`git clone` over HTTPS</td><td>No API access</td></tr><tr><td>`write_repository`</td><td>`git push` over HTTPS</td><td>No API access</td></tr><tr><td>`read_user`</td><td>Basic user info (`GET /api/v4/user`)</td><td>No repo/project access</td></tr></tbody></table>

Even combining all of the above **still does not allow the following:**

- Creating webhooks
- Managing deploy keys
- Creating projects

These require **REST API write permissions**, which are only available via the `api` scope.

If you attempt to use limited scopes, deployments will fail with the following:

```
insufficient_scope
```

---

##### GitLab version note

Elestio verifies token scopes using the following:

```
GET /api/v4/personal_access_tokens/self
```

This endpoint was introduced in **GitLab 13.5 (October 2020)**.

- On newer versions → scope is validated directly
- On older versions → validation is skipped

However, **the `api` scope is still required** for CI/CD to function correctly, regardless of version.

---

##### Admin settings required for template-based project creation

If you use **“Create repo from Elestio template,"** GitLab must allow imports from external URLs.

##### Enable this setting:

1. Go to **Admin Area**
2. Navigate to **Settings → General**
3. Expand **Import and export settings**
4. Enable **Allow imports from external URLs**
5. Save changes

[![image.png](https://docs.elest.io/uploads/images/gallery/2026-05/scaled-1680-/N2nimage.png)](https://docs.elest.io/uploads/images/gallery/2026-05/N2nimage.png)

If disabled, GitLab may return the following:

- `insufficient_scope`
- `404`

Even when your token is correctly configured.

👉 This is **not a token issue**, but a GitLab instance configuration restriction.

---

##### Troubleshooting

<table id="bkmrk-symptom-likely-cause" style="width: 100%;"><thead><tr><th style="width: 39.4405%;">Symptom</th><th style="width: 20.3756%;">Likely cause</th><th style="width: 40.1555%;">Fix</th></tr></thead><tbody><tr><td style="width: 39.4405%;">`AUTH_FAILED` at connection</td><td style="width: 20.3756%;">Wrong token or instance URL</td><td style="width: 40.1555%;">Verify URL format (`http://` or `https://`, no trailing slash) and re-copy token</td></tr><tr><td style="width: 39.4405%;">`INSUFFICIENT_SCOPES` at connection</td><td style="width: 20.3756%;">Missing `api` scope</td><td style="width: 40.1555%;">Edit or recreate the token with only `api`</td></tr><tr><td style="width: 39.4405%;">`insufficient_scope` during deployment (project creation)</td><td style="width: 20.3756%;">Using limited scopes</td><td style="width: 40.1555%;">Recreate the token with `api`</td></tr><tr><td style="width: 39.4405%;">`insufficient_scope` during template import</td><td style="width: 20.3756%;">Import setting disabled</td><td style="width: 40.1555%;">Enable “Allow imports from external URLs."</td></tr><tr><td style="width: 39.4405%;">Repositories not loading</td><td style="width: 20.3756%;">Missing or expired token</td><td style="width: 40.1555%;">Reconnect with a valid token</td></tr><tr><td style="width: 39.4405%;">Webhook not created</td><td style="width: 20.3756%;">No `api` scope</td><td style="width: 40.1555%;">`read_api` is not sufficient</td></tr><tr><td style="width: 39.4405%;">Deploy fails at git clone</td><td style="width: 20.3756%;">Missing `api` scope</td><td style="width: 40.1555%;">Use `api` (covers HTTPS git access too)</td></tr></tbody></table>

---

##### Key takeaway

For GitLab + Elestio CI/CD integrations:

> **Always use a Personal Access Token with the `api` scope nothing else will fully work.**

Trying to minimize scopes here will break core deployment functionality.