How Argo CD reads GitLab repositories and reacts to pushes
Argo CD reads manifests from a GitLab repository over Git, using credentials you register with it, and it can react to pushes through a webhook that GitLab sends to Argo CD. For a platform team whose manifests live in GitLab, the integration is therefore Git repository access with credentials, plus webhooks for faster refresh and the GitLab Pull Request generator for preview environments. This is a documented path in Argo CD, not a custom connector you would need to build or maintain.
The split of responsibilities matters for the design. GitLab Runner handles continuous integration: it builds images, runs tests and, if you choose, commits a new image tag or manifest change to the GitOps repository. Argo CD handles continuous delivery: it compares the desired state in Git with the live cluster and applies the difference. Keep the CI job's write access to the deployment repository narrow, and make Argo CD the only component that applies to the cluster. Your first decisions are which credential type to use (a deploy token or an SSH key, registered through a repository credential template) and whether the webhook secret in argocd-secret is set so that GitLab's push events are verified before Argo CD acts on them.
GitLab Free, Premium and Ultimate all run on self-managed installations, so the tier you hold does not decide whether this integration works. Confirm with your GitLab account team which features your organization already licenses, because the pricing page ties advanced CI/CD and compliance features to paid tiers, and those features may shape your pipeline but are not required to sync from a repository. Before you start, confirm your GitLab version and the Argo CD version you plan to run against the Argo CD webhook guide, since webhook settings and credential handling change between releases.
What you need before connecting GitLab to Argo CD
Connecting Argo CD to GitLab touches the Argo CD version, the GitLab edition and version, the network path between the two, the certificate trust chain and the credentials Argo CD uses to read repositories. Confirm each item before you create repository secrets or register a webhook, because a mismatch in any one of them usually shows up later as a failed sync or a webhook that never fires.
Argo CD patch line
Confirm which Argo CD minor version you run and whether it is still on the patch line. Only the three most recent minor versions receive patch releases, so an older install will stop getting security fixes for its GitLab-facing code paths. Check the release process page before you choose a target version, and plan the next minor upgrade as a separate change with its own test window.
GitLab edition and upgrade stops
Record whether you run GitLab.com or a self-managed instance, the exact version, and the edition. Self-managed GitLab must move through required upgrade stops, which since GitLab 17.5 fall at x.2, x.5, x.8 and x.11. Argo CD only talks to GitLab over Git and webhooks, so a GitLab upgrade can change clone behavior or API responses. Confirm the upgrade path before you rely on a token or webhook for production syncs.
Network reachability
Map two paths. The repo-server must reach the GitLab Git endpoint over HTTPS or SSH to fetch manifests. GitLab must reach the Argo CD API endpoint to deliver webhooks. For self-managed GitLab inside a segmented network, confirm the firewall rules, proxies and DNS names for both directions. Webhook delivery fails silently when the receiver is behind a private address that GitLab cannot resolve, so test with a real push.
TLS trust for a private CA
If GitLab or the Argo CD API uses certificates issued by a private certificate authority, the repo-server and the webhook sender both need that CA in their trust store. Without it, repository fetches fail with certificate errors and webhook deliveries are rejected. Confirm the chain of every hostname involved, including intermediates, and record who owns renewal, since expired certificates break GitOps delivery across all applications at once.
Scoped GitLab credentials
Decide which credential Argo CD will use: a deploy token, a deploy key over SSH, or a group or project access token with read scope. Use the narrowest scope that can clone the manifest repositories. Argo CD needs read access only, so avoid tokens with write or API scope. Plan a rotation date for each credential and record which owner, group or project it belongs to, since personal tokens leave when the person does.
Repository secrets in Kubernetes
Since Argo CD 3.0, repository configuration no longer lives in the argocd-cm ConfigMap, so every GitLab repository must be defined as a Kubernetes Secret. Confirm which namespace holds Argo CD, who can read and write those Secrets, and how credential templates will cover groups of repositories. Treat the Secrets as sensitive, because they hold the tokens or private keys Argo CD uses against GitLab.
Deploy tokens or SSH keys: which credential fits your repositories
When Argo CD reads one GitLab project, a repository-scoped credential is the simplest fit. A deploy token is limited to read access on the repository and is not tied to a person's account, so it survives staff changes. An SSH deploy key grants read access to one project with a key pair that Argo CD holds in a repository Secret. Either way, the credential exposes only the repository Argo CD is configured to read, which keeps the blast radius small.
- Deploy token: Created on the project and stored in a repository Secret with the username and token fields Argo CD expects. Scopes are set when the token is created.
- Deploy key: An SSH key pair where the public key is added to the project and the private key is stored in the Secret. Keys can be read-only.
- Rotation: Create the new credential, update the Secret, confirm a sync succeeds, then revoke the old one. Schedule this as a recurring task rather than an incident response.
- Ownership: Record who owns each token or key and which application uses it, so revocation does not break unrelated deployments.
- Expiry: Deploy tokens can carry an expiry date, so track it alongside the rotation calendar.
Confirm token scopes, expiry behavior and deploy key options against the current GitLab authentication documentation for your version before you standardize on either method.
When many repositories sit under one GitLab group, repeating a Secret for each project multiplies the credentials you must rotate. Argo CD credential templates solve this by matching a URL prefix, such as a group path, and applying one credential to every repository beneath it. The credential is defined once and new projects in the group inherit access without a new Secret, provided the underlying token or key covers them.
- Template match: A credential template keyed to the group URL prefix supplies the credential for any repository Argo CD reads under that path.
- Group-level token: Use a token issued for the group with read access to the projects Argo CD needs. Confirm whether it can read subgroups and archived projects.
- Blast radius: One leaked token now exposes every matching repository, so limit the scope to read and review who can create projects in the group.
- Rotation: Rotating one template replaces the credential for the whole group, which lowers recurring effort but requires coordinated timing.
- Exceptions: Projects that need a different credential need an explicit repository Secret, which takes precedence for that exact URL.
Test the template against a newly created project in the group to confirm inheritance works as you expect.
Pipelines, bots and other automation that read or write repositories should not borrow a developer's personal access token. A dedicated automation account, often called a service or bot user, gives the automation its own identity, its own audit trail and its own removal path when a project changes hands. The account's permissions should match the job: read access for Argo CD, and write access only where a pipeline must commit back to Git.
- Dedicated identity: Create a separate account for each automation purpose so audit logs show which system acted.
- Least privilege: Grant the minimum role on the required projects and avoid group owner roles.
- Personal tokens: Avoid personal access tokens for automation, since they end when the person leaves or changes role.
- Rotation and expiry: Set an expiry on tokens for the account and record the renewal owner in your change calendar.
- Separation: Keep the read credential Argo CD uses separate from any write credential a CI job holds.
Confirm how your GitLab version handles service accounts, token expiry and role assignment in the current authentication documentation, since these settings vary by license tier and installation.
Configure GitLab repository access and webhooks in order
This sequence gives Argo CD read-only access to a GitLab repository, a verified first sync, and then webhook-driven refresh and ApplicationSet generation. Each step closes with a check so problems surface before automation is layered on top.
Create a read-only GitLab credential
The GitLab administrator or project owner creates a deploy token scoped to read_repository, or a dedicated SSH key with read-only access, for the project or group that holds the manifests. Use a service identity rather than a personal account so access survives staff changes. Confirm the scope against your GitLab version in your own instance, since token scopes and key handling are set in the GitLab interface. The output is a credential that can clone the repository and nothing else, recorded in your secrets vault rather than in Git.
Store the repository as a Kubernetes Secret
The platform engineer creates a Kubernetes Secret in the Argo CD namespace with the label argocd.argoproj.io/secret-type set to repository, containing the repository URL and the deploy token or SSH private key. Argo CD 3.0 removed repository definitions from the argocd-cm ConfigMap, so this Secret is the only supported place to declare the repository. Apply it with your normal deployment path. The check is that the repository appears under Settings and then Repositories in the Argo CD UI with a Successful connection status.
Verify a manual sync before automating
Create one Argo CD Application that points at a known path in the repository and run a manual sync from the UI or the argocd CLI. Confirm that the manifests render, the target resources reach the expected health status, and the sync history records the Git revision. Do this before any webhook or generator exists, so that credential, path and rendering problems are isolated from automation problems. The check is a Synced and Healthy Application with the expected commit shown in its history.
Generate the webhook shared secret
Generate a long random value with a cryptographic random generator, then add it to argocd-secret under the key webhook.gitlab.secret. Keep the value in your secrets management process, because the same value must be typed into the GitLab webhook form in the next step. Restart or let the Argo CD API server reload as your installation requires, and confirm the change with the environment's configuration review. Argo CD uses this value to verify that incoming GitLab webhook requests are authentic.
Add the webhook in GitLab
A GitLab project or group maintainer adds a webhook under Settings and then Webhooks, pointing at the Argo CD webhook endpoint on your own domain and pasting the shared secret into the secret token field. Enable push events, and enable merge request events if the Pull Request generator will use them. Scope the webhook to the narrowest group or project that needs it. The check is a test delivery from GitLab that returns a 2xx response, and an Argo CD log line showing that the repository was refreshed.
Confirm the webhook triggers a refresh
Push a harmless commit to the monitored branch and watch the Application in the Argo CD UI. The Application should move to OutOfSync or update its revision within a short time without a manual refresh, which shows the webhook is reaching the repo-server path. If the change does not appear, check the GitLab delivery log for the response code before changing Argo CD settings. The check is the new commit revision visible on the Application without pressing refresh.
Enable the SCM Provider or Pull Request generator
The platform engineer adds an ApplicationSet with either the SCM Provider generator, to discover repositories in a GitLab group, or the Pull Request generator, to create preview Applications for open merge requests. Set a label filter so only intentionally labeled repositories or merge requests produce Applications, and confirm the GitLab token used by the generator has the narrowest scope that works. Review the generated Application template for project boundaries before applying it. The check is a generated Application appearing in the UI for the labeled project or merge request, and nothing appearing for an unlabeled one.
Hand off from CI to GitOps
Agree with the application team that CI builds and tests the artifact and then commits the new image tag or Helm value to the GitOps repository, while Argo CD performs the deployment. The CI job should use its own limited credential and should not run kubectl against the cluster. Confirm the handoff with one pipeline run: the CI job completes, the GitOps commit appears, the webhook refreshes the Application, and the sync finishes. The check is a single traceable path from commit to deployed revision.
When the Pull Request generator fits and when polling is enough
The ApplicationSet Pull Request generator fits best when you want an Argo CD Application per open GitLab merge request, typically so reviewers can inspect a preview environment built from the proposed change. The generator supports GitLab, can filter merge requests by label, and can regenerate on webhook events rather than waiting for a poll cycle. If your preview environments are a review requirement, this is the native way to produce them. If you only need to deploy the default branch after merge, a plain Application or ApplicationSet pointed at that branch is simpler and needs far less access. Confirm in the generator guide for your exact Argo CD version which GitLab options (token, base URL, project, label and webhook behavior) are supported, because these fields have changed across releases.
The costs are operational, not just technical. Each generation cycle calls the GitLab API to list merge requests, so a busy project with frequent polling multiplies API traffic, and the token used by the generator needs read access to every project it covers. Scope that token to the smallest set of projects and use a dedicated service account rather than a personal token. Label filters are the main guardrail: without them, every branch with an open merge request can become an Application, which quickly exhausts cluster capacity and clutters the Argo CD UI. Decide the label convention with your developers before you enable the generator, and test it against a non-production project first.
Cleanup is where preview setups most often fail. When a merge request closes or merges, the generator stops producing its parameters, and the matching Application is removed only if the ApplicationSet's prune and deletion behavior is set correctly for that template. Verify this in a test project by closing a merge request and confirming that the Application, its namespace and any preview resources disappear as expected. Also plan for stale resources after a controller or webhook outage, since polling will catch up but webhook-only designs may not. If your team can accept a short delay, a periodic poll with a longer interval can be enough, and it keeps the token scope and API load easier to justify to security reviewers.
Mapping GitLab objects to Argo CD repositories, webhooks and generators
This table maps each GitLab object to the Argo CD setting that consumes it, the Kubernetes object that stores it, and the failure you are likely to see when the pairing is wrong. Read the first four rows when you connect a repository, then the last rows when you enable merge request previews. Most GitLab-side mistakes surface as repository or generator errors in Argo CD, so check the Argo CD object named in each row first.
| GitLab object | Argo CD counterpart | Where it is stored | What breaks if it is wrong |
|---|---|---|---|
| Project or group | Repository URL, or the scope of an SCM Provider or Pull Request generator | Repository Secret (required since Argo CD 3.0); ApplicationSet generator spec | Repo-server cannot clone, or the generator returns the wrong set of projects or none |
| Deploy token or access token | Username and password credential for HTTPS repository access | Repository Secret; confirm the required token scopes in GitLab | Expired or under-scoped token leaves applications showing repository fetch errors |
| SSH deploy key | SSH private key credential for SSH repository URLs | Private key field in the repository Secret; public key registered on the GitLab project | Clone fails if the key is missing from the project or the host key is not trusted |
| Merge request event | Webhook-triggered generation for the Pull Request generator | ApplicationSet with a Pull Request generator; GitLab webhook delivery | Without the event, new or closed merge requests are handled only on the next generator refresh |
| Shared webhook secret | Token that Argo CD uses to verify incoming GitLab webhook requests | webhook.gitlab.secret key in argocd-secret | Mismatched values cause deliveries to be rejected, so Argo CD falls back to regular refresh |
| Label filter | Labels option on the GitLab Pull Request generator | ApplicationSet generator spec | No filter creates an application for every open merge request; a wrong label skips reviews that need previews |
Controls that keep GitLab credentials and webhooks from becoming a deployment path
A GitLab connection gives Argo CD three things it can act on: repository credentials, webhook deliveries and the content it renders. Each one can push changes toward a cluster, so the controls below limit what a stolen token, a forged request or a hostile manifest can do. Check each one in your environment before the first application syncs.
Verify webhooks with a shared secret
Argo CD checks GitLab webhook deliveries against a shared secret stored under webhook.gitlab.secret in argocd-secret. Without that check, anyone who can reach the webhook endpoint can ask Argo CD to refresh applications, which costs capacity even when no change is deployed. Generate a long random value, set the same value in the GitLab webhook configuration, and test that a delivery with a wrong token is rejected. Confirm the endpoint is reachable only from the networks GitLab uses.
Scope Git credentials to read-only access
Use a deploy token or SSH deploy key that can read only the manifest repositories Argo CD needs. Write access is not required for sync, and a write-capable credential in Argo CD turns a compromised cluster component into a way to change source code. Register credentials as repository secrets or credential templates so one scoped identity covers a group of repositories. Ask GitLab which token scopes and project roles your version supports before you create them.
Redact credentials in responses and logs
Argo CD removes cluster, Git and OAuth2 credentials from API responses and logs. Your own tooling can still leak them, for example through CI job output, exported manifests or copied kubectl get secret output. Review what your dashboards, log shippers and support tickets capture, and rotate any credential that appears outside its secret. Keep repository credentials in Kubernetes Secrets, as the 3.0 upgrade requires, and restrict who can read those Secrets.
Encrypt traffic between components
Argo CD uses TLS for traffic, including between its own components, and this protects credentials and manifests in transit. Verify that the GitLab connection, the webhook endpoint and the Argo CD API all use certificates your internal certificate authority issues and that clients validate them. Do not disable certificate checks to get a connection working. Record which certificate authority and renewal process applies, because an expired certificate stops webhooks and syncs.
Treat repo-server rendering as code execution
The repo-server runs Helm and Kustomize against repository content, so a chart, a Kustomize plugin or a file reference that reaches outside the repository can read or change what the server sees. Limit which repositories an Application can use, keep Helm charts and remote bases pinned to reviewed versions, and avoid enabling out-of-tree file access unless the design needs it. Ask who can merge to each repository, since that person can change the rendered output.
Separate manifests from untrusted forks
PR-based Applications deploy code from proposed changes, so a fork from an outside contributor should never reach a cluster. Keep deployable manifest repositories in a group that only maintainers can write to, and use the Pull Request generator only for repositories where merge requests from forks are disabled or blocked from deployment. Confirm the generator's filters match your own project and branch rules, and check that a fork cannot supply a branch name that matches a deployment filter.
Limit which projects trigger PR-based Applications
The Pull Request generator and webhook-driven refresh let a GitLab project cause new Applications to appear. Restrict generation with label filters and with Argo CD Projects, so each project can deploy only to its own namespaces and clusters. Review who can add labels or open merge requests in those projects, because a label change can widen what the generator picks up. Test a merge request from a non-production project before enabling generation on production clusters.
Common GitLab and Argo CD failures and how to fix them
This table lists the failures teams most often hit when Argo CD reads GitLab repositories or receives GitLab webhooks, with the likely cause and the fix for each. Read each row by matching the symptom you see, then check the log source named in the last column before changing configuration. Most of these problems trace back to credentials, the webhook secret, network reachability or label filters.
| Symptom | Likely cause | Fix | Where to read logs |
|---|---|---|---|
| Repository authentication fails after a token expires | The GitLab deploy token or access token stored in the repository Secret has expired, been revoked or lost its read scope | Issue a new token with read_repository scope, update the repository Secret or credential template, then refresh the application. Plan a rotation date and owner for every token. | argocd-repo-server logs, and the repository connection status in the Argo CD UI or CLI |
| Repository access fails with a host key verification error | The SSH host key for your self-managed GitLab changed after an upgrade, certificate rotation or server rebuild, or the known_hosts entry was never added | Confirm the new host key fingerprint with your GitLab administrator through a trusted channel, then update the known hosts entry in argocd-ssh-known-hosts-cm. Do not disable host key checking to clear the error. | argocd-repo-server logs |
| Webhook returns 403 Forbidden | The token in the GitLab webhook does not match webhook.gitlab.secret in argocd-secret, or the secret was rotated on one side only | Set the same value in the GitLab webhook configuration and in argocd-secret, then redeliver a test event from GitLab. Restart the API server if the change does not take effect. | GitLab project webhook delivery history, and argocd-server logs |
| Webhook never fires or never reaches Argo CD | GitLab cannot reach the Argo CD webhook endpoint, because of DNS, firewall rules, a private network address or a proxy that drops POST requests | Confirm the webhook URL resolves and accepts HTTPS from GitLab's network path, that the endpoint is reachable from GitLab itself, and that the URL path is /api/webhook. Check that GitLab does not block outbound requests to local addresses in its settings. | GitLab webhook delivery history for response codes, then argocd-server logs for received events |
| Pull Request generator returns no applications | Label filters on the generator exclude every merge request, or the generator points at the wrong project or group path | Remove the label filter and confirm the generated list, then add labels back one at a time. Check the GitLab token scope and the project path in the generator spec. | applicationset-controller logs |
| Self-signed certificate errors on clone or API calls | The GitLab instance uses an internal CA that Argo CD does not trust, or the chain is incomplete | Add the CA certificate to Argo CD's trusted TLS configuration for the repository host, and confirm the full chain is served. Avoid skipping verification in production. | argocd-repo-server logs and argocd-server logs for TLS handshake errors |
| Rate limits and slow refresh from frequent polling | Many applications poll the same repository at short intervals, or webhooks are missing so Argo CD falls back to polling | Restore webhook delivery so polling can be reduced, and review how many applications share one repository. Ask GitLab administrators about API rate limits for your token type before changing intervals. | argocd-repo-server logs, and GitLab API rate limit responses in the same window |
Questions teams ask before connecting GitLab to Argo CD
How much effort does connecting GitLab to Argo CD take, and what drives it?
The effort depends mostly on how many repositories Argo CD must read, which GitLab edition and hosting model you run, how the network between GitLab, Argo CD and your clusters is designed, and whether you want pull request preview environments. A single repository with one credential and no previews is a small, bounded task. Dozens of repositories across several teams add work in credential templates, project boundaries and access reviews. Self-managed GitLab behind a private network adds routing and certificate work that GitLab.com does not. Ask any partner for a quote that lists each repository group, the credential method for each, the webhook design, the ApplicationSet generators in scope and the clusters that receive changes. A quote without those inputs is not comparable.
Can our own team connect GitLab to Argo CD without outside help?
Yes, a team with Kubernetes and GitLab administration experience can do the core wiring itself. The steps are documented: register repositories with deploy tokens or SSH keys through credential templates, store the webhook secret, and configure the Pull Request generator where needed. The risks lie in the details that are easy to get wrong: scoping tokens to the minimum read access, keeping repository secrets out of Git, restricting which projects each Argo CD project can deploy from, and confirming that the repo-server does not read files it should not. Teams without a named owner for these decisions often find the setup works but the access model drifts. An outside review of the finished design can be useful even when your team builds it.
What do we need to provide before the integration work starts?
You need four things in place before work starts. First, GitLab administrator or group owner access sufficient to create deploy tokens or service accounts and to add webhooks at the group or project level. Second, administrative access to the Argo CD instance and to every target cluster it deploys to. Third, a named owner for credentials who approves token scopes, rotation dates and who may read the Argo CD repository secrets. Fourth, a list of repositories, branches and environments that are in scope. Ask for these inputs in writing as part of the scope. The owner should also agree how credentials are rotated, because the integration depends on them remaining valid after staff changes.
Do we need webhooks, or is polling enough for GitLab?
Polling is enough for correctness, but webhooks make change detection faster and reduce repeated requests to GitLab. Argo CD can refresh applications on a schedule, and webhooks let GitLab notify Argo CD when a push or merge request event occurs. The webhook secret is set in the webhook.gitlab.secret key in argocd-secret, and Argo CD uses it to verify that incoming requests came from GitLab. Webhooks matter more for pull request generators, where event-driven generation keeps preview environments current. If your network blocks inbound traffic from GitLab to Argo CD, polling is the practical choice, and that decision should be recorded with the reason. Confirm the webhook configuration against the current Argo CD webhook guide for your version.
How do GitLab upgrade stops affect the Argo CD integration?
GitLab requires upgrades to pass through required upgrade stops, and since GitLab 17.5 these fall at versions x.2, x.5, x.8 and x.11. Examples include 18.2, 18.5, 18.8, 18.11, 19.2, 19.5, 19.8 and 19.11. The Argo CD integration depends on the GitLab API, token behavior and webhook payloads, so a GitLab upgrade can change any of them. Plan each GitLab upgrade as a change that includes a test of repository access, webhook delivery and the Pull Request generator in a non-production Argo CD instance. Keep the upgrade path in your change calendar, and ask any partner how they will verify the integration after each stop. GitLab also maintains only its current and recent stable releases, so an older GitLab version may need to move forward sooner than your schedule expects.
Does GitLab edition or licensing change how we connect Argo CD?
The core integration works with GitLab's Free tier in principle, since Argo CD reads repositories through standard Git access and webhooks. What changes is the feature set around your delivery process. The GitLab pricing page lists Premium at 29 US dollars per user per month billed annually, with Ultimate custom priced, and both are available for self-managed installations. Those tiers add CI/CD and security features that affect how your pipelines hand off to GitOps, not how Argo CD authenticates. Confirm with GitLab which features your pipelines need, because licensing is a separate cost from the Argo CD work. The GitLab source is open core, with content under the ee/ directory under the GitLab Enterprise Edition license and the rest under the MIT Expat license.
Who pays for what when GitLab and Argo CD are both self-managed?
Three cost lines usually appear. GitLab subscription fees, if you choose a paid tier, are paid to GitLab. Infrastructure for GitLab, Argo CD and the clusters is paid to your cloud or data center provider. Implementation and any ongoing support are paid to a partner or met by your own staff. Argo CD itself is Apache-2.0 licensed and has no paid edition from the project. The one-time costs are the design, credential setup, webhook configuration and testing. The recurring costs are token rotation, GitLab and Argo CD upgrades, and the review of access as teams change. Ask a quote to separate these lines and to state which upgrades and reviews are included in the first year and which are retainer work.
Handing off from GitLab CI to GitOps without giving CI cluster access
The pipeline should build, test and publish, then change Git. It should never run kubectl or helm against a production cluster. In this pattern GitLab CI produces a container image, runs its tests and scans, and then commits a small change to a separate configuration repository, typically the image tag or digest in a Kustomize overlay or Helm values file. Argo CD watches that repository, sees the new desired state and applies it. The CI job needs write access to one Git repository and read access to whatever registry it pushes to. It holds no kubeconfig, no service account token for the cluster and no Argo CD API credentials. If a job is compromised, the damage is limited to what the pipeline can push to Git, which is a narrower and more reviewable blast radius than cluster-admin. The token deserves the most attention. A project access token or a dedicated bot account scoped to the configuration repository, with the Developer role and only the branch permissions the flow needs, is the usual choice. Avoid a personal access token tied to an engineer who may leave. Store the token as a masked and protected CI/CD variable so it is available only on protected branches, and confirm in your GitLab version how protected variables and push rules interact with the bot. Where the config repository should be changed only through review, have the job open a merge request instead of pushing to the default branch, and let a human or a policy approve it. Confirm with your security team whether merge requests opened by automation meet your change approval rules, because that decision defines what counts as the change record.
Keeping Argo CD as the only path to production means controlling who else can change the cluster. The Argo CD sync must be the sole writer, so restrict direct kubectl access for deployment identities and make the Argo CD AppProject destination and source rules match the repositories and namespaces your pipeline is allowed to touch. Within Argo CD, disable automatic sync for production applications if your change process requires a human to press sync, or keep auto-sync on and rely on merge approval, but do not run both an automated CI deploy stage and an Argo CD sync against the same resources. The Argo CD Git webhook guide explains how GitLab push events shorten the time to sync; the webhook is a trigger, not a gate, so approval belongs in GitLab.
GitLab Runner is documented separately, and where runners sit is a design choice you should confirm for your environment. A runner that can reach the Git host and the registry, but not the cluster API, keeps the separation clean. Runners on the cluster network, or shared runners used for other projects, widen what a job can reach. Ask your platform team whether the runner that builds images can also reach internal registries and the config repository, whether runner tags restrict which projects use it, and whether job logs can expose the bot token. The GitLab Runner documentation is the starting point for those checks.
How DeployOpen scopes and delivers the GitLab integration
DeployOpen is a Chainscore Labs company that plans, implements, hardens, documents and supports self-hosted open-source platforms inside your own cloud accounts, data centers or air-gapped networks. For Argo CD with GitLab repositories and webhooks, we agree the repositories, credential method, webhook path and handoff from CI in writing before any build starts.
How we scope
- Inventory which GitLab instance hosts each repository, self-managed or GitLab.com, and who owns it.
- Choose the credential method per repository, deploy token or SSH key, and document who rotates it.
- Define webhook scope, shared secret ownership and whether the Pull Request generator is in scope.
- Confirm the CI-to-GitOps handoff, including which pipeline jobs commit image tags and which do not.
How we build
- Create repository credentials as Kubernetes Secrets or credential templates, with no secrets committed to Git.
- Configure the webhook with a shared secret stored in argocd-secret and test delivery on each source repository.
- Set up the SCM Provider and Pull Request generators with label filters, then verify generated Applications in a non-production cluster.
- Test repo-server behavior with untrusted content and out-of-tree file access restrictions before go-live.
How we hand over
- Provide a written runbook covering credential rotation, webhook secret rotation and generator troubleshooting.
- Document the repository map, project boundaries and the CI jobs that hand off to Argo CD.
- Walk your platform and security teams through failed-sync and failed-webhook scenarios on your own systems.
- Deliver configuration as code so your team can review and change the integration through Git.
How we support
- Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.
- Ongoing support, upgrades and continuous testing are available as retainers after handover.
- Ask any partner for the GitLab version and upgrade stop plan your instance will follow, and confirm it against the official upgrade paths.
- Confirm with your GitLab administrators which Argo CD versions and GitLab features your environment supports before the quote is final.

