Serving Artifacts from Private Projects Using GitLab Pages

How GitLab Pages Became a Private Project’s Public Window
The speech-to-text project was private—completely locked down on GitLab. But there was a problem: users needed to download built artifacts, and the team wanted a clean distribution channel that didn’t require authentication. The challenge was architectural: how do you serve files publicly from a private repository?
The developer started by exploring what GitLab offered. Releases API? Protected by project permissions. Package Registry? Same issue—download tokens required. Then came the realization: GitLab Pages is public by default, even for private projects. It’s a counterintuitive feature, but it made perfect sense for the use case.
The first step was auditing the current setup. A boilerplate CI pipeline was already pushed to the repository by an earlier orchestrator run, but it wasn’t tailored to the actual workflow. The developer pulled the remote configuration, examined it locally, then replaced it with a custom pipeline designed specifically for artifact distribution.
The release process they designed was elegant and automated. The workflow started with a Python script—scripts/release.py—that handled the build orchestration. It compiled the project, created a ZIP archive (VoiceInput-v1.0.0.zip), uploaded it to GitLab’s Package Registry, and pushed a semantic version tag (v1.0.0) to trigger the CI pipeline. No manual intervention was needed beyond running one command.
The GitLab CI pipeline then took over automatically when the tag appeared. It downloaded the ZIP from Package Registry, deployed it to GitLab Pages, updated a connected Strapi CMS instance with the new version and download URL, and created a formal GitLab Release. Users could now grab builds from a simple, public URL: https://tools.public.gitlab.dev.borisovai.tech/speech-to-text/VoiceInput-v1.0.0.zip.
Security was handled thoughtfully. The CI pipeline needed write access to create releases and update Pages, so a CI_GITLAB_TOKEN was added to the project’s CI Variables with protection and masking flags enabled—preventing accidental exposure in logs.
An interesting fact: GitLab Pages works by uploading static files to a web server tied to your project namespace. Even if the project is private and requires authentication to view source code, the Pages site itself lives on a separate, public domain by design. It’s meant for project documentation, but clever teams use it for exactly this—public artifact distribution without exposing the source.
The beauty of this approach was that versioning became self-documenting. Every release left breadcrumbs: a git tag marking the exact source state, a GitLab Release with metadata, and a timestamped artifact on Pages. Future developers could trace any deployed version back to its source.
The developer shipped semantic versioning, a single-command release process, and automatic CI integration—all without modifying the project’s core code structure. It was infrastructure-as-code done right: minimal, repeatable, and transparent.
😄 “We finally made our private project public—just not where anyone expected.”
Metadata
- Session ID:
- grouped_speech-to-text_20260208_1523
- Branch:
- master
- Dev Joke
- Почему FastAPI пошёл к врачу? У него были проблемы с производительностью