Skip to main content
Gå til innhold

GitLab Package Registry

warning

The package registry is in test phase.The test instance is running in a sandbox aws account and is available under https://gitlab-test.sandbox.platon.sikt.no url.

All users interested in testing the package registry please contact Artur Ferfecki on Slack.

Table of Contents

Overview

The GitLab Package Registry is an integrated feature of GitLab that allows to use GitLab as a private or public repository for various common software package managers. It enables teams to publish, share, and consume software packages and their dependencies alongside their source code within the same platform. GitLab Package Registry will replace Artifactory, as Artifactory is being phased out.

Only package types that are generally available will be accepted by the package registry. For full list of supported packages (also those under development) see docs.

Supported Package Types

  • NPM
  • PyPI (Python)
  • Maven
  • NuGet
  • Generic packages

Roles and Permissions

Roles define which actions a user is able to perform. The role types are defined by default in GitLab and are assigned per group or project. Group Owners and/or project Maintainers are able to assign or change users role.

Project permissions for package registry:

ActionGuestPlannerReporterDeveloperMaintainerOwner
Pull packagexxxxxx
Publish packagexxx
Delete Packagexx
Delete files associated with a packagexx

Guest roles can only pull packages on public and internal projects. External users must be given explicit access (at least the Reporter role) even if the project is internal.

Group permissions for package registry:

ActionGuestPlannerReporterDeveloperMaintainerOwner
Pull packagexxxx
Publish packagexxx
Delete Packagexx
Manage package settingsx

Authentication

For Publishing Packages

One must be authenticated when publishing package to the package registry. Packages have to be published to a specific project. It is not possible to push packages to a GitLab group, one can only pull packages from group.

For Pulling Packages

To install package from private project one needs to be authenticated. The owner of the project can allow for an anonymous pull from package registry in:

project Settings → General → Visibility, project features, permissions → Package registry → Allow anyone to pull from package registry

Packages can be pulled from group or project endpoints. The group endpoint collects published packages from the projects it contains and makes them available as a single collection.

1. CI/CD Job Token

This is the preferred method for publishing packages to the registry from GitLab pipeline. The short-lived $CI_JOB_TOKEN is managed by the GitLab instance and has permission to publish packages to the same project by default. If the team has a need to push a package to repository in different project, one can add the source project to the CI/CD job token allowlist of the receiver project:

receiver project Settings → CI/CD → CI/CD job token allowlist

The job token is automatically provisioned to pull packages from the same project.

2. Deploy Token

For CI/CD and automated systems:

  1. Go to Project Settings → Repository → Deploy Tokens
  2. Create token with read_package_registry and/or write_package_registry scope
  3. Save the token as CI/CD variable or locally

3. Access Tokens

Create a personal/group/project access token with api scope:

  1. Go to Settings → Access Tokens
  2. Create token with required api
  3. Save the token securely

Useful GitLab Predefined Environment Variables

GitLab comes with number of predefined environment variables. The list below is a selection of the complete list, handy when working with packages in GitLab pipeline.

VariableDescription
CI_API_V4_URLThe GitLab API v4 root URL
CI_SERVER_HOSTThe host of the GitLab instance URL, without protocol or port - gitlab.sikt.no
CI_PROJECT_IDThe ID of the current project. This ID is unique across all projects on the GitLab instance.
CI_PROJECT_ROOT_NAMESPACEThe root project namespace (username or group name) of the job. For example, if CI_PROJECT_NAMESPACE is root-group/child-group/grandchild-group, CI_PROJECT_ROOT_NAMESPACE is root-group.
CI_PROJECT_PATHThe project namespace with the project name included.
CI_JOB_TOKENA token to authenticate with package registry. The token is valid as long as the job is running.
CI_COMMIT_TAGThe commit tag name. Available only in pipelines for tags.

NPM Packages

Official documentation for npm package type with examples can be found in GitLab documentation.

Setup

Project-level:

# .npmrc
@scope:registry=https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/npm/
//gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/npm/:_authToken=${TOKEN}

Group-level:

# .npmrc
@scope:registry=https://gitlab.sikt.no/api/v4/groups/${GROUP_ID}/-/packages/npm/
//gitlab.sikt.no/api/v4/groups/${GROUP_ID}/-/packages/npm/:_authToken=${TOKEN}

When authenticating in the GitLab pipeline one can substitute the GROUP_ID env var with predefined CI_PROJECT_NAMESPACE_ID. The CI_PROJECT_NAMESPACE_ID contains the ID of the first parent group of the project.

2. Using npm config

npm config set @scope:registry https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/npm/
npm config set //gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/npm/:_authToken ${TOKEN}

where TOKEN represents deploy token, group access token, project access token, or personal access token

Push NPM Package

  1. Update package.json:
{
"name": "@scope/my-package",
"version": "1.0.0",
"publishConfig": {
"@scope:registry": "https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/npm/"
}
}
  1. Publish:
npm publish

Pull NPM Package

# Install specific package
npm install @scope/my-package

# Or add to package.json and run
npm install

Example .gitlab-ci.yml

publish:
image: node:18
script:
- echo "@scope:registry=https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/" >> .npmrc
- echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}" >> .npmrc
- npm publish

Python Packages (PyPI)

Official documentation for PyPI package type with examples can be found in GitLab documentation.

Setup

Configure pip

# ~/.pip/pip.conf (Linux/macOS) or %APPDATA%\pip\pip.ini (Windows)
[global]
index-url = https://__token__:${TOKEN}@gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/pypi/simple

Or use environment variable:

export PIP_INDEX_URL=https://__token__:${TOKEN}@gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/pypi/simple

Push Python Package

You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first. If you attempt to publish the same package more than once, a 400 Bad Request error occurs.

  1. Install Twine
pip install twine
  1. Configure .pypirc:
# ~/.pypirc
[distutils]
index-servers =
gitlab

[gitlab]
repository = https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/pypi
username = ${PERSONAL_ACCESS_TOKEN_USERNAME}
password = ${PERSONAL_ACCESS_TOKEN}
  1. Upload:
python3 -m twine upload --repository gitlab dist/*

Or using environment variables:

TWINE_USERNAME=${PERSONAL_ACCESS_TOKEN_USERNAME}\
TWINE_PASSWORD=${PERSONAL_ACCESS_TOKEN} \
python3 -m twine upload --repository-url https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/pypi dist/*

Pull Python Package

pip install --index-url https://${PERSONAL_ACCESS_TOKEN_USERNAME}:${PERSONAL_ACCESS_TOKEN}@gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/pypi/simple --no-deps my-package

Example .gitlab-ci.yml

publish:
image: python:3.14
script:
- pip install build twine
- python -m build
- TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url https://gitlab.sikt.no/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*

Maven Packages

Official documentation for maven package type with examples can be found in GitLab documentation.

Setup

Configure settings.xml

<!-- ~/.m2/settings.xml -->
<settings>
<servers>
<server>
<id>gitlab-maven</id>
<configuration>
<httpHeaders>
<property>
<name>Job-Token</name>
<value>${CI_JOB_TOKEN}</value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
</settings>

Or with username/password:

<settings>
<servers>
<server>
<id>gitlab-maven</id>
<username>GITLAB_USERNAME</username>
<password>PERSONAL_ACCESS_TOKEN</password>
</server>
</servers>
</settings>

Push Maven Package

  1. Configure pom.xml:
<project>
<!-- ... -->
<distributionManagement>
<repository>
<id>gitlab-maven</id>
<url>https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/maven</url>
</repository>
<snapshotRepository>
<id>gitlab-maven</id>
<url>https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/maven</url>
</snapshotRepository>
</distributionManagement>

<repositories>
<repository>
<id>gitlab-maven</id>
<url>https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/maven</url>
</repository>
</repositories>
</project>
  1. Deploy:
mvn deploy -s settings.xml

Pull Maven Package

Add repository to pom.xml (shown above) and add dependency:

<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-package</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>

Then:

mvn install

Example .gitlab-ci.yml

deploy:
image: maven:3.8-openjdk-11
script:
- mvn deploy -s ci_settings.xml

NuGet Packages

Official documentation for nuget package type with examples can be found in GitLab documentation.

Setup

Add source

dotnet nuget add source "https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/nuget/index.json" \
--name gitlab \
--username USERNAME \
--password ${TOKEN} \
--store-password-in-clear-text

Push NuGet Package

  1. Build package:
dotnet pack --configuration Release
  1. Push:
dotnet nuget push "bin/Release/*.nupkg" \
--source gitlab \
--api-key ${TOKEN}

Or directly to URL:

dotnet nuget push "bin/Release/*.nupkg" \
--source "https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/nuget/index.json" \
--api-key ${TOKEN}

Pull NuGet Package

dotnet add package MyPackage --version 1.0.0 --source gitlab

Or restore from nuget.config:

<!-- nuget.config -->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="gitlab" value="https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/nuget/index.json" />
</packageSources>
<packageSourceCredentials>
<gitlab>
<add key="Username" value="USERNAME" />
<add key="ClearTextPassword" value="${TOKEN}" />
</gitlab>
</packageSourceCredentials>
</configuration>

Example .gitlab-ci.yml

publish:
image: mcr.microsoft.com/dotnet/sdk:7.0
script:
- dotnet pack --configuration Release
- dotnet nuget push "bin/Release/*.nupkg" --source "https://gitlab.sikt.no/api/v4/projects/${CI_PROJECT_ID}/packages/nuget/index.json" --api-key ${CI_JOB_TOKEN}

Generic Packages

Generic packages are useful for binary files, archives, or custom package formats. Official documentation for generic packages with examples can be found in GitLab documentation.

Push Generic Package

curl --header "PRIVATE-TOKEN: ${TOKEN}" \
--upload-file path/to/file.tar.gz \
"https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/generic/${PACKAGE_NAME}/${VERSION}/file.tar.gz"

With additional metadata:

curl --header "PRIVATE-TOKEN: ${TOKEN}" \
--upload-file artifact.zip \
"https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/generic/my-package/1.0.0/artifact.zip?status=default"

Pull Generic Package

curl --header "PRIVATE-TOKEN: ${TOKEN}" \
"https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/generic/${PACKAGE_NAME}/${VERSION}/file.tar.gz" \
--output file.tar.gz

Or using wget:

wget --header="PRIVATE-TOKEN: ${TOKEN}" \
"https://gitlab.sikt.no/api/v4/projects/${PROJECT_ID}/packages/generic/${PACKAGE_NAME}/${VERSION}/file.tar.gz"

Example .gitlab-ci.yml

upload:
script:
- 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file build/artifact.zip "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my-package/${CI_COMMIT_TAG}/artifact.zip"'
only:
- tags

download:
script:
- 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my-package/1.0.0/artifact.zip" -o artifact.zip'

Best Practices

1. Version Management

  • Use semantic versioning (semver)
  • Tag releases consistently
  • Don't overwrite existing versions

2. Security

  • Use deploy tokens for CI/CD (not personal tokens)
  • Rotate tokens regularly
  • Use scoped tokens (minimal permissions)

3. Organization

  • Use group-level registries for shared packages
  • Use project-level registries for project-specific packages
  • Establish naming conventions (scopes, prefixes)

4. Cleanup

  • Set up cleanup policies for old packages
  • Remove unused packages
  • Document retention policies

Additional Resources