When working with Git providers that use custom or self-signed TLS certificates (such as self-hosted GitLab, GitHub Enterprise, or Bitbucket), you need to configure Pipelines as Code to trust these certificates.
Overview
Pipelines as Code components make HTTPS connections to:
- Git provider APIs (GitHub, GitLab, Bitbucket)
- Git repositories for cloning
- Webhook endpoints
- Custom catalog hubs
If any of these endpoints use certificates not signed by a well-known Certificate Authority (CA), you must expose the custom CA certificate to Pipelines as Code.
OpenShift Configuration
On OpenShift, if Pipelines as Code is installed through the OpenShift Pipelines Operator, the process is simplified.
Add Certificate via Proxy Object
OpenShift allows you to add custom certificates cluster-wide using the Proxy object. The OpenShift Pipelines Operator automatically exposes these certificates to all Pipelines components, including Pipelines as Code.
-
Follow the OpenShift documentation for configuring custom PKI
-
The certificate will be automatically mounted in:
pipelines-as-code-controller
pipelines-as-code-watcher
pipelines-as-code-webhook
- All PipelineRun pods
No additional configuration is needed. The operator handles certificate distribution automatically.
Kubernetes Configuration
On standard Kubernetes clusters, you need to manually configure custom certificates.
Step 1: Create ConfigMap with Certificate
Create a ConfigMap containing your custom CA certificate:
kubectl -n pipelines-as-code create configmap git-repo-cert \
--from-file=git.crt=/path/to/ca.crt
Parameters:
git-repo-cert - ConfigMap name (you can use any name)
git.crt - Key name in ConfigMap (you can use any name)
/path/to/ca.crt - Path to your CA certificate file
Example:
# For a self-hosted GitLab instance
kubectl -n pipelines-as-code create configmap gitlab-ca-cert \
--from-file=gitlab.crt=/home/user/certs/gitlab-ca.crt
Step 2: Mount ConfigMap in Deployments
You need to mount the ConfigMap in both the controller and watcher deployments.
Option 1: Edit Deployment YAML
Edit the deployment to add the ConfigMap volume:
kubectl edit deployment pipelines-as-code-controller -n pipelines-as-code
Add the volume and volumeMount:
apiVersion: apps/v1
kind: Deployment
metadata:
name: pipelines-as-code-controller
namespace: pipelines-as-code
spec:
template:
spec:
containers:
- name: pac-controller
# ... other config
volumeMounts:
- name: git-certs
mountPath: /pac-custom-certs
readOnly: true
volumes:
- name: git-certs
configMap:
name: git-repo-cert
Repeat for the watcher deployment:
kubectl edit deployment pipelines-as-code-watcher -n pipelines-as-code
Option 2: Use kubectl patch
Patch both deployments using kubectl:
# Patch controller
kubectl patch deployment pipelines-as-code-controller \
-n pipelines-as-code \
--type=json \
-p='[
{
"op": "add",
"path": "/spec/template/spec/volumes/-",
"value": {
"name": "git-certs",
"configMap": {"name": "git-repo-cert"}
}
},
{
"op": "add",
"path": "/spec/template/spec/containers/0/volumeMounts/-",
"value": {
"name": "git-certs",
"mountPath": "/pac-custom-certs",
"readOnly": true
}
}
]'
# Patch watcher
kubectl patch deployment pipelines-as-code-watcher \
-n pipelines-as-code \
--type=json \
-p='[
{
"op": "add",
"path": "/spec/template/spec/volumes/-",
"value": {
"name": "git-certs",
"configMap": {"name": "git-repo-cert"}
}
},
{
"op": "add",
"path": "/spec/template/spec/containers/0/volumeMounts/-",
"value": {
"name": "git-certs",
"mountPath": "/pac-custom-certs",
"readOnly": true
}
}
]'
After mounting the certificates, configure the SSL_CERT_DIR environment variable to include your custom certificate directory.
The SSL_CERT_DIR environment variable tells Go applications where to look for CA certificates. You must include:
- Your custom certificate path (
/pac-custom-certs)
- Standard system certificate paths
kubectl set env deployment pipelines-as-code-controller \
pipelines-as-code-watcher \
-n pipelines-as-code \
SSL_CERT_DIR=/pac-custom-certs:/etc/ssl/certs:/etc/pki/tls/certs:/system/etc/security/cacerts
Certificate search paths:
/pac-custom-certs - Your custom certificates
/etc/ssl/certs - Debian/Ubuntu system certificates
/etc/pki/tls/certs - RHEL/CentOS system certificates
/system/etc/security/cacerts - Android system certificates
Always include standard system certificate paths in SSL_CERT_DIR. Omitting them will break connections to public services (like artifacthub.io, GitHub.com, etc.).
Step 4: Verify Configuration
Verify the deployments have been updated:
# Check controller deployment
kubectl get deployment pipelines-as-code-controller -n pipelines-as-code -o yaml | grep SSL_CERT_DIR
# Check watcher deployment
kubectl get deployment pipelines-as-code-watcher -n pipelines-as-code -o yaml | grep SSL_CERT_DIR
# Verify pods restarted
kubectl get pods -n pipelines-as-code
Check logs for certificate-related errors:
kubectl logs -n pipelines-as-code deployment/pipelines-as-code-controller | grep -i cert
kubectl logs -n pipelines-as-code deployment/pipelines-as-code-watcher | grep -i cert
Multiple Certificates
If you need to trust multiple custom certificates:
Option 1: Multiple Files in One ConfigMap
kubectl -n pipelines-as-code create configmap git-repo-certs \
--from-file=gitlab.crt=/path/to/gitlab-ca.crt \
--from-file=github.crt=/path/to/github-ca.crt \
--from-file=bitbucket.crt=/path/to/bitbucket-ca.crt
All certificate files will be mounted in the same directory.
Option 2: Bundle Certificates
Combine multiple certificates into a single file:
cat gitlab-ca.crt github-enterprise-ca.crt > combined-ca.crt
kubectl -n pipelines-as-code create configmap git-repo-cert \
--from-file=git.crt=combined-ca.crt
PipelineRun Pods
Custom certificates mounted in controller and watcher deployments only affect Pipelines as Code components. To use custom certificates in PipelineRun pods (for git-clone tasks, etc.), you need additional configuration.
Option 1: ConfigMap in PipelineRun Namespace
Create the same ConfigMap in each namespace where PipelineRuns execute:
kubectl -n my-repo-namespace create configmap git-repo-cert \
--from-file=git.crt=/path/to/ca.crt
Then mount it in your git-clone task:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: my-pipeline
spec:
pipelineSpec:
tasks:
- name: git-clone
taskRef:
name: git-clone
params:
- name: url
value: https://gitlab.company.com/repo.git
workspaces:
- name: ssl-ca-directory
configMap:
name: git-repo-cert
Option 2: Cluster-wide Certificate Distribution
For cluster-wide certificate distribution, consider:
- OpenShift Proxy object (OpenShift only)
- Tekton Pipelines ConfigMap - Configure
ssl-cert-dir in config-defaults
- Custom init container - Copy certificates to shared workspace in each PipelineRun
Troubleshooting
Certificate Verification Errors
If you see errors like:
x509: certificate signed by unknown authority
This indicates the certificate is not trusted. Verify:
- ConfigMap exists and contains certificate:
kubectl get configmap git-repo-cert -n pipelines-as-code
kubectl describe configmap git-repo-cert -n pipelines-as-code
- ConfigMap is mounted in pods:
kubectl describe pod <controller-pod> -n pipelines-as-code | grep -A5 Mounts
- SSL_CERT_DIR is set:
kubectl exec -n pipelines-as-code deployment/pipelines-as-code-controller -- env | grep SSL_CERT_DIR
- Certificate file is readable:
kubectl exec -n pipelines-as-code deployment/pipelines-as-code-controller -- ls -l /pac-custom-certs/
kubectl exec -n pipelines-as-code deployment/pipelines-as-code-controller -- cat /pac-custom-certs/git.crt
Certificates must be in PEM format:
-----BEGIN CERTIFICATE-----
MIID...
-----END CERTIFICATE-----
If your certificate is in DER format, convert it:
openssl x509 -inform DER -in cert.der -out cert.pem
Certificate Expired
Check certificate validity:
openssl x509 -in /path/to/ca.crt -noout -dates
Testing Certificate Trust
Test from inside a pod:
# Test HTTPS connection
kubectl exec -n pipelines-as-code deployment/pipelines-as-code-controller -- \
curl -v https://gitlab.company.com
# Check certificate chain
kubectl exec -n pipelines-as-code deployment/pipelines-as-code-controller -- \
openssl s_client -connect gitlab.company.com:443 -CApath /pac-custom-certs
Best Practices
Certificate Management:
- Use descriptive ConfigMap names (e.g.,
gitlab-ca-cert, not cert)
- Document certificate source and expiration in ConfigMap annotations
- Set up monitoring for certificate expiration
- Automate certificate rotation when possible
- Use the same ConfigMap name across all namespaces for consistency
Always verify certificates are from trusted sources. Using certificates from untrusted sources can expose your cluster to man-in-the-middle attacks.
Example: Complete Setup for GitLab
Complete example for self-hosted GitLab with custom certificate:
# 1. Create ConfigMap with GitLab CA certificate
kubectl -n pipelines-as-code create configmap gitlab-ca \
--from-file=gitlab.crt=/etc/ssl/certs/gitlab-ca.crt
# 2. Patch controller deployment
kubectl patch deployment pipelines-as-code-controller -n pipelines-as-code \
--type=json -p='[
{"op":"add","path":"/spec/template/spec/volumes/-","value":{"name":"gitlab-certs","configMap":{"name":"gitlab-ca"}}},
{"op":"add","path":"/spec/template/spec/containers/0/volumeMounts/-","value":{"name":"gitlab-certs","mountPath":"/pac-certs","readOnly":true}}
]'
# 3. Patch watcher deployment
kubectl patch deployment pipelines-as-code-watcher -n pipelines-as-code \
--type=json -p='[
{"op":"add","path":"/spec/template/spec/volumes/-","value":{"name":"gitlab-certs","configMap":{"name":"gitlab-ca"}}},
{"op":"add","path":"/spec/template/spec/containers/0/volumeMounts/-","value":{"name":"gitlab-certs","mountPath":"/pac-certs","readOnly":true}}
]'
# 4. Set SSL_CERT_DIR
kubectl set env deployment/pipelines-as-code-controller \
deployment/pipelines-as-code-watcher \
-n pipelines-as-code \
SSL_CERT_DIR=/pac-certs:/etc/ssl/certs:/etc/pki/tls/certs
# 5. Verify
kubectl rollout status deployment/pipelines-as-code-controller -n pipelines-as-code
kubectl rollout status deployment/pipelines-as-code-watcher -n pipelines-as-code
# 6. Test connection
kubectl exec -n pipelines-as-code deployment/pipelines-as-code-controller -- \
curl -v https://gitlab.company.com/api/v4/version
See Also