Self Hosting Gitlab on Cycle.

Self-Hosting Gitlab on Cycle

A walkthrough for deploying GitLab Community Edition on Cycle using theĀ Cycle portal.

End state: a stateful GitLab container running in an isolated environment, addressable over a TLS-terminated hostname, and backing itself up on a schedule.

Prerequisites

You need:

  • An account on a Cycle and access to a hub with at least one cluster and one server attached. If you're new to Cycle, run throughĀ Getting StartedĀ first.
  • A DNS zone added to the hub. SeeĀ Configuring a DNS Zone.
  • A backup destination integration (Backblaze) connected at the hub level if you want automated backups. SeeĀ Configure Backblaze.
  • Capacity for GitLab CE's minimum recommended resources: 4 GB RAM, 4 cores. 8 GB+ is comfortable. (Keep in mind that CycleOS and services will take up a few hundred MB of RAM and a bit of CPU).

1. Sign in to the Hub

OpenĀ US portalĀ orĀ EU portalĀ and sign in. Custom-cluster hubs use a different URL — check with your teams admin.

The left-hand nav is where the rest of this guide happens. The entries you'll use:Ā Images,Ā Environments,Ā DNS,Ā Integrations.

2. Create the image source

An image source tells Cycle where to fetch an image from. Each source can be imported repeatedly to produce point-in-time images, which makes pinning and rollback straightforward.

  1. Left nav:Ā Images → Sources.
  2. ClickĀ CreateĀ in the top right.
  3. Fill in:
    • Name:Ā GitLab CE
    • Source type:Ā Docker Hub
    • Target:Ā gitlab/gitlab-ce:latest, or a pinned tag likeĀ gitlab/gitlab-ce:17.5.0-ce.0Ā for reproducibility
  4. The image is public, so no credentials are needed. ClickĀ Create Image Source.

Creating the source doesn't pull anything yet. That happens in the next step.

Docs:Ā Image sourcesĀ Ā·Ā Creating an image source

3. Import the image

On the image source detail page, find theĀ Import ImageĀ button at the top.

Click and holdĀ the button until it triggers. A single click does nothing, this is intentional friction to prevent accidental re-pulls.

Cycle pulls the image, processes it, and the resulting image lands inĀ liveĀ state. It's now selectable when you create a container.

Each import produces a new point-in-time copy. Old copies aren't replaced; they accumulate until you prune them.

Docs:Ā Importing an image

4. Create the environment

An environment is Cycle's network boundary. Containers in the same environment share a private, encrypted network. Containers in different environments don't see each other by default.

  1. Left nav:Ā Environments → Create.
  2. Fill in:
    • Name:Ā gitlab
    • Cluster:Ā the cluster that should host this environment
    • Description:Ā optional
  3. LeaveĀ Legacy NetworkingĀ off unless you have a specific reason to enable IPv4 inside the private network.
  4. ClickĀ Create Environment.

Docs:Ā Create an environmentĀ Ā·Ā Introduction to environmentsĀ Ā·Ā Legacy Environments

5. Create the GitLab container (stateful)

From the environment dashboard, clickĀ Deploy ContainerĀ in the top right.

In the deploy wizard:

  • Container Name:Ā gitlab
  • Stateful:Ā ChooseĀ StatefulĀ from the dropdown, the container needs persistent volumes for config, data, and logs.
  • Deployment StrategyĀ can be left as default.
  • Image:Ā select the GitLab image you imported in step 3 from theĀ Recent ImagesĀ dropdown.
  • Desired Instances:Ā 1

Volumes

GitLab omnibus needs three persistent paths:

Mount path

Size for Demo

Suggested for Production

Purpose

/etc/gitlab

5 GB

5 GB

configuration

/var/opt/gitlab

5 GB

100 GB+

repositories, database, attachments, CI artifacts

/var/log/gitlab

5 GB

10 GB

logs

Network

Mark theĀ Public NetworkĀ setting to enabled for this demo as we will be reaching this container over public networking. Gitlab can be run behind theĀ Cycle VPN serviceĀ if preferred but that configuration is not covered here.

ClickĀ Deploy ContainerĀ to finish the wizard. The container is created but not yet running.

Docs:Ā Deploying a containerĀ Ā·Ā Container volumes

6. Start the environment

From the environment dashboard, clickĀ Start AllĀ in the top right. This boots Discovery and the GitLab container.

Because the Gitlab container has the public network setting of "Enabled", the load balancer will automatically start here. Give it 10-15 seconds to negotiate its IP from the provider.

Docs:Ā Managing containers

7. Verify the container is running

Open the GitLab container from the containers dashboard (environment dashboard - clickĀ ContainersĀ from the horizontal nav), then go to theĀ InstancesĀ tab.

The instance row shows health status. Click into the instance to open theĀ Instance Console, live stdout/stderr from the running process. The first boot takes a few seconds to minutes depending on GitLab's omnibus initialĀ reconfigure.

The container is healthy when:

  • Instance state isĀ running
  • The console shows GitLab's reconfigure completing without errors
  • Requesting the container's internal address returns the GitLab login page

If the instance is stuck inĀ startingĀ or restarting on a loop, check the Instance Console for the actual error. Common causes: under-sized volumes, malformedĀ GITLAB_OMNIBUS_CONFIG, port conflicts.

Docs:Ā Container instances

8. Add a LINKED DNS record

A LINKED record is a Cycle DNS record type that associates a domain with container(s). It resolves to the environment's Load Balancer and can terminate TLS automatically using Let's Encrypt or user uploaded certificates like Cloudflare's Origin certs.

  1. Left nav:Ā DNS → Zones → select your zone.
  2. ClickĀ Add Record.
  3. In the wizard:
    • Type:Ā LINKED
    • Name:Ā the subdomain.Ā gitlabĀ forĀ gitlab.yourdomain.com, orĀ @Ā for the zone apex.
    • Environment:Ā the environment from step 4
    • Link to Container:Ā the GitLab container
    • TLS Enabled:Ā ON
  4. ClickĀ Create.

DNS propagation takes a few minutes. TLS cert generation is rate-limited to 3 certs per domain per hour; if you exceed it, Cycle backs off for an hour before retrying.

Docs:Ā Creating a LINKED recordĀ Ā·Ā DNS records

9. Configure automated backups

Cycle's backup model is command-based, not snapshot-based. The container declares a backup command that writes to stdout and a restore command that reads from stdin. Cycle runs them on a schedule and ships the result to your backup destination.

GitLab's native backup tooling streams cleanly into this model. The canonical commands are:

backup

gitlab-backup create BACKUP=streamed_backup SKIP=registry >/dev/stderr 2>&1 && tar -czf - /etc/gitlab /var/log/gitlab /var/opt/gitlab/backups/streamed_backup_gitlab_backup.tar && rm /var/opt/gitlab/backups/streamed_backup_gitlab_backup.tar

restore

tar -xzf - -C && gitlab-ctl stop puma && gitlab-ctl stop sidekiq && gitlab-backup restore BACKUP=streamed_backup force=yes >/dev/stderr && gitlab-ctl reconfigure && gitlab-ctl restart

Setup in the Hub:

  1. Open the GitLab container.
  2. Go to theĀ BackupsĀ tab.
  3. Configure:
    • Backup command:Ā the streaming backup one-liner from the runbook
    • Restore command:Ā the streaming restore one-liner from the runbook
    • Schedule:Ā daily is typical. Pick an off-peak hour.
    • Destination:Ā the Backblaze integration configured at the hub level
  4. Save.

The first scheduled run produces a backup. Restores are also done through theĀ BackupsĀ tab — Cycle pipes the archive into your restore command on stdin.

Restoring doesĀ notĀ restart the container automatically. After a restore, GitLab may needĀ gitlab-ctl reconfigureĀ and a restart.

Docs:Ā Container backups conceptĀ Ā·Ā Backup/restore commandsĀ Ā·Ā Configure Backblaze

Operating notes

A few things worth knowing once GitLab is running:

Resources.Ā GitLab CE is heavy. 4 GB RAM is the floor; 8 GB or more is comfortable. Storage forĀ /var/opt/gitlabĀ grows with the number of repos and CI artifacts.

Upgrades.Ā Re-import the image source to pull a newer Docker Hub tag. The import produces a new image;Ā reimage the containerĀ if needed.

Git over SSH.Ā GitLab's SSH listens on port 22 inside the container. If you want git-over-SSH externally, either remap it viaĀ gitlab_rails['gitlab_shell_ssh_port']Ā inĀ GITLAB_OMNIBUS_CONFIG, or have the Load Balancer expose a different external port.

Backup destination housekeeping.Ā Manage the Backblaze bucket from the Cycle Portal only. Editing or deleting backup files directly in Backblaze de-syncs Cycle's record of what exists.


Cookies

Cookies Preferences

We run basic, anonymous analytics by default to measure site traffic. By clicking "Accept," you allow additional cookies for advanced app improvements and tailored advertising. Choose what you share by clicking "Customize."