Running GitLab on OpenShift with the GitLab Operator
Running GitLab on OpenShift with the GitLab Operator suits a platform team that must keep source code, code review and CI/CD inside clusters it controls and wants the Operator to manage the install and upgrades instead of a hand-maintained Helm release. The Operator path fits when OpenShift is the standard platform, the team accepts the Operator's custom resource model, and it can keep PostgreSQL, Redis and object storage outside the cluster. GitLab lists five installation methods: the Linux package, the Helm chart, the GitLab Operator, Docker and source. For a team on OpenShift, the choice is mainly between the Operator and the Helm chart, and the Operator is the one that puts upgrade sequencing inside a managed controller.
Before you choose, confirm the boundary of what runs in the cluster. The reference architecture documentation says running stateful components such as PostgreSQL and Redis inside Kubernetes is not supported. The Cloud Native Hybrid architecture is the layout to plan for: stateless GitLab components run on OpenShift, while PostgreSQL, Redis and object storage run on virtual machines or managed services. Ask your DBA and storage team to confirm which database service, Redis deployment and object store they will provide, their network path from the cluster, and who owns backups for each. These services carry most of the recovery work, so they should be sized and owned before the Operator custom resource is written.
Plan the upgrade path and the security context work before installation. GitLab requires upgrades to pass through required upgrade stops, which since GitLab 17.5 fall at versions x.2, x.5, x.8 and x.11, so your change calendar must reflect those stops rather than the monthly minor release. OpenShift applies security context constraints that can restrict the user IDs and volume types the GitLab pods request, so confirm with your cluster administrators which SCC applies to the GitLab service accounts before the first install. Check the Operator release against the GitLab version you intend to run, and confirm its supported OpenShift versions with GitLab and Red Hat documentation, since this page does not state them.
Choosing between the Operator, the Helm chart and the Linux package
Teams that already run OpenShift as their standard application platform usually want GitLab managed with the same cluster policy, lifecycle and operator tooling as everything else. The GitLab Operator fits this model because the platform team declares GitLab as a custom resource and lets the Operator reconcile the deployment, so the team does not hand-maintain chart values for each change.
- What the team operates: the OpenShift cluster, security context constraints, routes, storage classes, node pools for runners, and the GitLab custom resource.
- How upgrades are driven: through the Operator and its version settings. The platform team still has to stop at the required upgrade stops and check each Operator release against the current upgrade documentation.
- Where stateful services live: PostgreSQL, Redis and object storage belong on VMs or managed services. The reference architectures state that running PostgreSQL and Redis inside Kubernetes is not supported.
- Platform fit: Gitaly storage and runner capacity need to match the cluster's storage classes and autoscaling model, which is a separate design task from the install itself.
Confirm which external services the Operator can connect to, and how it handles upgrade stops, against the current GitLab documentation before you commit to this path.
Teams that already run conventional Kubernetes and deliver workloads with Helm usually want GitLab to follow the same chart, values and pipeline conventions. The Helm chart keeps GitLab in that familiar workflow, but the team owns more of the sequencing around it, including the Kubernetes version and the GitLab version.
- What the team operates: the Kubernetes distribution, the control plane, etcd backups, the values files and the pipeline that applies them.
- How upgrades are driven: by the team's own
helm upgraderuns. The team must order GitLab upgrade stops and Kubernetes changes itself, and Kubernetes requires kube-apiserver to move first within the version skew limits. - Where stateful services live: outside the cluster in a Cloud Native Hybrid layout, because the reference architectures do not support PostgreSQL or Redis inside Kubernetes.
- Drift risk: chart versions, values and the live cluster can diverge over time. Record the chart version next to each GitLab version and keep the values in version control.
Check the chart's current support statements and the required upgrade stops before you pin a chart version for production.
Teams that run their infrastructure on virtual machines and do not want a Kubernetes layer for GitLab usually choose the Linux package. GitLab's installation methods page describes it as the most mature and scalable method, and it bundles PostgreSQL, Redis and Sidekiq, which makes it the simplest starting point for a single node.
- What the team operates: Linux hosts, operating system patching, the
gitlab.rbconfiguration file, backups and the Gitaly storage layout. - How upgrades are driven: by the team's own change calendar. Plan around the monthly minor release and the required upgrade stops, and treat multi-node zero-downtime steps as a separate procedure.
- Where stateful services live: on the same node at small scale. As user counts and CI load grow, the reference architectures place PostgreSQL, Redis and Gitaly on dedicated VMs or managed services.
- Offline operation: the offline environments guidance covers air-gapped installs, so confirm which install method and version it applies to for your network.
Confirm your target user count and CI load against the reference architectures before you choose between a single node and a multi-node layout.
GitLab on OpenShift configuration options and when each fits
This table compares the main configuration choices for GitLab on OpenShift with the GitLab Operator, from database placement to high availability and Geo. Read each row against your user count, CI load and recovery requirements, then confirm the Operator's supported topology for your GitLab version before you commit.
| Decision | Option | When it fits |
|---|---|---|
| PostgreSQL placement | External PostgreSQL on VMs or a managed service | GitLab's reference architecture docs say stateful components such as PostgreSQL are not supported inside Kubernetes, so plan an external database for production. |
| PostgreSQL placement | PostgreSQL inside the cluster | Only for disposable evaluation. Confirm with GitLab whether the Operator's bundled database is acceptable for your scale and support position. |
| Redis | External Redis service | Choose it for production with the Cloud Native Hybrid pattern, since Redis is a stateful component that the reference architecture keeps outside Kubernetes. |
| Object storage | Object storage for artifacts, registry and uploads | Needed when CI artifacts, packages or registry data grow. Confirm which object types the Operator's configuration exposes for your version. |
| Architecture | Cloud Native Hybrid | Fits when you want stateless GitLab components on OpenShift and stateful services on VMs or managed services, as the reference architectures describe. |
| Sizing | Single-node or small footprint | Suitable for smaller user populations. Size against the reference architectures, which start at 1,000 users. |
| Sizing | High availability layout | Generally recommended from 3,000 or more users, using Gitaly Cluster with Praefect, PostgreSQL with Patroni, Redis Sentinel and Consul. |
| Disaster recovery | GitLab Geo secondary site | Consider it when you need a warm-standby site in another region. Geo requires Premium or Ultimate for self-managed GitLab. |
Setup sequence for GitLab on OpenShift with the Operator
This sequence takes a team from a confirmed GitLab version and upgrade path to a running, signed-in instance on OpenShift, with external stateful services and a tested backup and restore. Each step closes with a check so the next one starts from a known state.
Confirm the target version and upgrade path
Before any cluster work, the platform owner picks the GitLab version to deploy and checks the required upgrade stops in GitLab's upgrade paths documentation. Choose a release that is currently maintained under the maintenance policy, and record the Operator version that pairs with it. Confirm exact compatibility, manifests and Operator versions with the current GitLab docs, since these change between releases. Done when the version, the stop path from any existing installation, and the Operator release are written down and approved.
Provision external PostgreSQL and Redis
Stateful services run outside the cluster, on VMs or a managed service, because GitLab's reference architectures do not support running PostgreSQL or Redis inside Kubernetes. The database team creates the PostgreSQL instance, roles and required extensions, and sizes Redis for the expected load. Confirm supported PostgreSQL and Redis versions for the chosen GitLab release with the current requirements. Done when the team can connect from the OpenShift network using the planned credentials and the connection test succeeds from a test pod.
Provision object storage
GitLab stores artifacts, uploads, LFS objects, packages and registry data in object storage, so buckets and access keys must exist before deployment. The storage team creates the buckets and a dedicated service identity with access limited to those buckets, and confirms the endpoint is reachable from the cluster network. If the environment is air-gapped, confirm the storage endpoint is internal and that no step depends on public internet access. Done when a test upload and download succeed with the GitLab credentials.
Install the GitLab Operator
The cluster administrator installs the GitLab Operator through OpenShift's operator mechanism, in the namespace planned for the platform, and sets the channel or version that matches the target release. Keep the Operator and the GitLab version aligned, and record which one was installed. Done when the Operator reports a successful installation and its controller pod is running without restarts.
Define the GitLab custom resource
The platform engineer writes the GitLab custom resource that points the Operator at the external PostgreSQL, Redis and object storage, and sets the hostname, TLS and the sizing that matches the user count. Store secrets in the cluster's secret mechanism rather than in the manifest, and review each key against the current Operator documentation. Validate the manifest with a dry run before applying it. Done when the dry run passes and the reviewed manifest is stored in version control.
Configure security context constraints for GitLab service accounts
OpenShift restricts the user IDs and volumes that pods can use through security context constraints, so the GitLab service accounts need an explicit, reviewed binding. The cluster administrator grants the minimum constraint that lets GitLab components run and write to their volumes, and avoids broad privileged grants. Confirm which constraint each component needs in the current GitLab Operator guidance. Done when all GitLab pods are admitted and no pod is stuck in a rejected state with a constraint error.
Deploy and verify health checks and sign-in
After the custom resource is applied, the platform team waits for all components to reach a ready state, then checks the health endpoints GitLab exposes and signs in with an initial administrator account. Confirm that a test project can be created, a repository pushed to, and a pipeline job scheduled, which exercises the database, Redis and object storage together. Record the initial administrator access and rotate it according to policy. Done when health checks pass, sign-in works and the test pipeline completes.
Run a backup and restore test
Before the instance takes real work, the operations team runs a backup and restores it into a separate target to prove the procedure works. Backups must cover the database, repositories and object storage, and the GitLab secrets needed to decrypt stored data, so confirm which components the backup procedure captures for this deployment. Compare restored projects and a sample of artifacts against the source. Done when the restored instance signs in and the compared data matches.
Security context constraints and hardening on OpenShift
On OpenShift, the GitLab Operator's pods have to fit the cluster's admission policy before anything else works. The cards below cover the decisions that connect that policy to the rest of the deployment: pod identity and volumes, secrets and encryption keys, traffic to external databases, runner placement, staged hardening and the signals you watch after go-live.
Agree pod UIDs and volumes with SCCs
OpenShift assigns pods a UID range and restricts volume types through security context constraints (SCCs). GitLab components expect specific users, group IDs and writable paths, so a default restricted SCC can block pods from starting. Before installation, ask your platform team which SCC applies to the GitLab namespace, which UID range it grants, and whether a dedicated SCC is needed for the components that write to persistent volumes. Confirm this against the Operator's current documentation for your OpenShift release, since the required settings change between versions.
Keep secrets out of values files
The Operator replaces the single gitlab.rb file with custom resource settings and Kubernetes Secrets, including the keys GitLab uses to encrypt database columns and CI variables. Losing those keys makes stored data unreadable, so they need a backup separate from the cluster. Decide where the root password, the database credentials and the encryption keys live, who can read them, and how they are rotated. Restrict list and watch access to these Secrets with least-privilege RBAC, and consider encryption at rest for etcd or an external store.
Restrict traffic to external databases
GitLab's reference architectures recommend keeping stateful services such as PostgreSQL and Redis outside Kubernetes, so the cluster connects to managed or VM-hosted databases over the network. Write NetworkPolicy rules that allow only the GitLab pods to reach the database ports, and only from the namespace and labels you specify. Confirm the egress path for object storage, the container registry and any Gitaly node, because a blocked route typically surfaces as a failed job or a stuck upgrade rather than a clear error.
Isolate runners from the GitLab control plane
CI jobs execute arbitrary code, so the runner fleet is the highest-risk part of the deployment. Decide whether runners run on the same OpenShift cluster or on separate nodes, and whether they use the Kubernetes executor or a separate VM-based fleet. Give runner pods their own namespace, avoid privileged containers and host paths, and keep the runner's manager token and registration settings out of shared repositories. Keep runner major and minor versions aligned with GitLab, as the Runner documentation advises.
Apply hardening guidance in stages
GitLab's hardening documentation covers application settings, CI/CD, configuration, the operating system and NIST SP 800-53 alignment, and states that the guidance is a work in progress to roll out gradually. Treat it as a backlog rather than a single change window. Start with sign-up, visibility and SSH key settings, then move to CI/CD and secrets controls. Record each change in your change management system so the security team can show what was applied and when, and retest after each Operator upgrade because defaults can shift.
Monitor logs and health after go-live
Once GitLab is running, the cluster's audit logs, pod events and GitLab's own health endpoints are the first signals of a misconfigured SCC, a rejected admission request or a database connection that has dropped. Decide which logs are forwarded to your central platform, who receives alerts on restarts and failed migrations, and how Prometheus metrics are scraped from the GitLab components. Test these alerts during the first upgrade so you know they fire before a stop is missed.
How Operator-driven upgrades must respect required upgrade stops
Every GitLab upgrade on OpenShift has to land on a required upgrade stop before it moves forward. Since GitLab 17.5, those stops fall at versions x.2, x.5, x.8 and x.11, so 18.2, 18.5, 18.8, 18.11, 19.2, 19.5, 19.8 and 19.11 are the points where a team can safely pause. The GitLab Operator does not remove this requirement. Before any change, map the currently running version to the next stop in the GitLab upgrade paths documentation, and write the hop sequence into the change record. A team on an older release may need several hops, and each one is a separate, testable change.
Plan the hops around the release cadence. GitLab ships a minor release on the third Thursday of each month and patch releases twice a month, but its maintenance policy backports bug fixes only to the current stable release. Security fixes also reach the previous two monthly releases. A cluster that lags behind will therefore receive fewer fixes than it expects, and the gap is an operational risk to record. For each hop, test in a staging namespace that mirrors the production Operator, the GitLab custom resource and the external PostgreSQL, Redis and object storage settings. Confirm the Operator version matches the GitLab target in the same change, and back up the database, object storage and secrets before every hop using the GitLab backup and restore documentation. Use the planned major release, GitLab 20.0, expected in May 2027, as a planning date for the next major upgrade, and confirm its scope with GitLab when the release notes are published.
Questions teams ask before running GitLab on OpenShift
What does GitLab on OpenShift cost, and does DeployOpen quote a fixed scope?
DeployOpen does not publish a price list. A quote follows from a written scope, and most engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts. The main cost components are the implementation itself, the external PostgreSQL, Redis and object storage you choose, the OpenShift capacity the instance consumes, and GitLab licensing. The implementation is one-time, while cluster capacity, managed services, licenses and any retainer for upgrades or support recur. Ask for the quote to list the GitLab edition, the number of users, the stateful services in scope, the upgrade and backup procedures, and what is excluded.
How long does a GitLab on OpenShift build take, and what drives the duration?
The duration depends on the scope agreed in writing, so DeployOpen gives a timeline with the quote rather than a generic figure. The biggest drivers are whether PostgreSQL, Redis and object storage already exist and are reachable from the cluster, the number of users and CI load that set the reference architecture, how many security context and network decisions your OpenShift policies require, and how long your approvals and change windows take. Integrations with identity, runners and backup targets add work. Ask for the timeline to be split into discovery, build, verification, handover and upgrade rehearsal.
What does our team need to provide before the build starts?
Plan to provide access and decisions before the build begins. The list usually includes a target OpenShift project and cluster access with the rights needed to install the Operator and grant security context constraints, DNS names and the hostnames GitLab will use, certificates from your certificate authority, network paths and credentials for the external PostgreSQL and object storage services, a backup target, and named approvers for architecture, security and change control. Confirm each item against your own environment and your OpenShift administration model before scheduling work.
Can our internal team run GitLab on OpenShift without a partner?
Yes, if the team has the skills to operate both OpenShift and GitLab. The work needs people who can manage Operator-based installs, write security context constraints that match the GitLab pods, run external stateful services with tested backups, and plan upgrades through GitLab's required upgrade stops. Engineers also need to understand the GitLab Runner fleet and identity integration. Teams that already run OpenShift and GitLab in production often handle this in-house. Teams new to one of the two platforms usually benefit from a written plan, a rehearsed upgrade and documented runbooks, whoever delivers them.
Which GitLab licensing tier do we need for an OpenShift deployment?
The tier decides which features you can use, not whether the Operator install works. GitLab Free costs 0 US dollars, Premium costs 29 US dollars per user per month billed annually, and Ultimate is custom priced, and all three are available for self-managed installations. The GitLab pricing page lists advanced CI/CD and priority support for Premium, and application security testing, software supply chain security, vulnerability management and compliance features for Ultimate. Decide the tier before the architecture is fixed, because security scanning, compliance reporting and Geo depend on it. Confirm the current tier details on the pricing page at the time of purchase.
Is Geo part of a GitLab on OpenShift install?
No, Geo is not included in a standard install. GitLab Geo is available in the Premium and Ultimate tiers for self-managed GitLab and provides a warm-standby secondary site in another region that is continuously synchronized for disaster recovery. Adding it means a second site, replication of the database and repositories, and a tested failover procedure, which changes the architecture and the budget. Decide early whether disaster recovery needs Geo or whether backups and a restore procedure meet your recovery targets. If Geo is in scope, record it in the written scope so it is priced and tested.
What should engineers check after the Operator install and before go-live?
Check that the Operator reconciles the GitLab custom resource without errors, that all pods reach a ready state under the security context constraints you set, and that the external PostgreSQL and object storage connections work from inside the cluster. Then confirm login through your identity provider, a test backup and a restore into a separate environment, and a runner that registers and runs a job. Document the GitLab version, the Operator version and the upgrade stops GitLab requires, so the next upgrade follows a planned path.
Limits to confirm in your OpenShift environment
GitLab on OpenShift with the GitLab Operator depends on several version and policy limits that sit outside GitLab itself. The cards below cover the checks that most often decide whether a plan holds, and each one should be confirmed in your own cluster before sizing or scheduling the work.
Operator and GitLab version fit
Confirm that the GitLab Operator release you plan to use supports your OpenShift release, and that the target GitLab version is reachable from your current version through the required upgrade stops. Pin both versions in writing before the install, because a mismatch found after deployment forces a rebuild of the plan. Check the GitLab maintenance policy for which minor releases are currently maintained, since the newest supported line is the one you should target.
Security context constraint allowance
Ask your platform team which security context constraints apply to the namespace and service accounts GitLab will use. OpenShift restricts UIDs and volume types by default, and GitLab components expect specific settings. Confirm the policy in a test namespace first, and record any exception the security team must approve. Review the Pod Security Standards alongside your own SCC rules so the expected baseline is clear.
External PostgreSQL and Redis support
If PostgreSQL and Redis run outside the cluster, confirm their versions against the GitLab release you plan to install. GitLab's reference architectures do not support running stateful components such as PostgreSQL and Redis inside Kubernetes, so these services must sit on VMs or managed platforms. Check the version matrix for the exact target release and confirm that your database team can provide the required roles and extensions.
Object storage provider support
Confirm that your object storage platform, whether S3-compatible on-premises storage or a cloud service, is supported for each GitLab data type you need. Some providers are tested by GitLab while others are community-documented, and several data types may need separate settings. Ask whether the storage team can provide the required buckets, credentials and lifecycle rules before the install begins.
Air-gapped mirroring requirements
If the cluster has no internet access, plan how container images, Operator bundles, Helm charts and GitLab security scanner data reach it. GitLab documents offline environments and separate guidance for security scanners and self-hosted AI features, so each one needs its own mirror plan. Confirm which registries and update channels your network can reach and who approves transfers of new images for each upgrade.
Reference architecture size fit
Compare your expected user count, API request rate and CI load against GitLab's published reference architectures, which start at 1,000 users and reach 50,000 users. GitLab generally recommends a high availability strategy at 3,000 or more users, which affects how many nodes and how much stateful infrastructure you must provide. Size against peak CI concurrency, not only named users, and ask your platform team whether the cluster can hold the required replicas.
What DeployOpen delivers on an OpenShift GitLab engagement
An OpenShift GitLab engagement starts with a written scope and a deliverables list agreed before any work begins. The scope names the target OpenShift cluster, the cloud account or data center it runs in, the GitLab edition and tier, the external PostgreSQL, Redis and object storage services, and the upgrade target. DeployOpen installs GitLab inside your cluster and your infrastructure, so your team keeps ownership of the cluster, the registry, the network path and the data. Confirm early which cluster administrators will grant the Operator install rights, because that decision shapes the rest of the build.
The handover includes documented security context constraints for each GitLab workload, so your security team can see which service accounts receive which SCC, why, and what would break if the grant were widened. It also includes an upgrade runbook built around the Operator, covering the required upgrade stops listed in the GitLab upgrade paths documentation, a pre-upgrade backup step, and a rollback decision point. Backup and restore are verified by an actual restore into a separate target, not only by a successful backup job, and the result is recorded in the handover pack.
DeployOpen prepares systems, configuration records, test results and runbooks that your auditors or certification bodies can review, but it does not issue audit reports, attestations or certifications. Ask for the evidence list in writing so you know which artifacts will exist at handover. Ongoing upgrades, patch rounds, backup restore tests and support can be covered by an optional retainer after the fixed-scope work closes, and whether you need one depends on how much of the operation stays in your team.
How DeployOpen scopes, delivers and supports GitLab on OpenShift
DeployOpen plans, implements, hardens, documents and supports self-hosted open-source platforms inside your own infrastructure, and that includes GitLab on OpenShift installed through the GitLab Operator. Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.
How we scope
- Written scope names the OpenShift cluster version, the GitLab release line and the Operator version to be installed.
- Scope records which stateful services stay outside the cluster, such as PostgreSQL, Redis and object storage, and who owns each.
- Scope lists the security context constraints, network policies, ingress and certificate decisions that the cluster team must approve.
How we build
- We configure the GitLab custom resource, external service connections and storage classes in a non-production cluster first.
- We validate security context constraint bindings and pod permissions against the planned runner and GitLab workloads before go-live.
- We test a backup and restore of the GitLab data and secrets, and rehearse an Operator-driven upgrade across a required upgrade stop.
How we hand over
- Deliverables include the deployed configuration as code, a runbook for install, upgrade and rollback, and a record of design decisions.
- We document the upgrade path, including required upgrade stops, the Operator version pairing and the order of component changes.
- Your operations team receives a walkthrough and a verification checklist so they can run routine maintenance without us.
How we support
- Ongoing support, upgrades and continuous testing are available as retainers, scoped in writing separately from the build.
- Retainer work can cover planned GitLab and Operator upgrades, backup restore tests and review of security context constraint changes.
- Ask any provider which Operator and GitLab versions they have deployed before, and how they test an upgrade before running it in production.

