Connecting Git Repositories
Configure Magos Workspaces to clone Terraform modules using built-in Git transports or remote helpers.
Every Magos Workspace reconciles a Terraform module that lives in Git. The magos-job image performs a shallow clone of spec.source.repoURL at spec.source.targetRevision, checks out the resolved commit, and runs terraform init against the directory under spec.source.path. This page covers the built-in authentication shapes and extending Git transport support with remote helpers.
Public repositories
For a public repository, no credentials are needed. Magos clones over HTTPS without authentication.
spec:
source:
repoURL: https://github.com/magosproject/demo.git
targetRevision: main
path: .
The RefWatcher controller polls the remote ref on its interval (default 30 seconds, configurable via the magosproject.io/git-poll-interval annotation) and writes the resolved SHA back to the Workspace when the branch moves. A push to main results in a fresh plan and apply cycle without operator intervention.
Private HTTPS repositories
For HTTPS with a personal access token or password, store the credentials in a Kubernetes Secret with a specific label and shape, and let Magos discover it automatically based on the repository URL.
Create the Secret:
apiVersion: v1
kind: Secret
metadata:
name: github-prod-readonly
namespace: default
labels:
magosproject.io/secret-type: repository
type: Opaque
stringData:
repoURL: https://github.com/your-org/private-infra.git
username: git
password: ghp_xxxxxxxxxxxxxxxxxxxxxxxx
Three rules:
- The
magosproject.io/secret-type: repositorylabel is how the workspace controller finds credential Secrets in the namespace. - The
repoURLdata key must match the Workspace'sspec.source.repoURLexactly. The workspace controller looks up the matching Secret by URL, so multiple Secrets can coexist for different repositories. - For HTTPS authentication, set
usernameandpassword. With personal access tokens,usernameis typicallygit(or your provider's recommended placeholder) andpasswordholds the token.
Then point the Workspace at the same URL:
spec:
source:
repoURL: https://github.com/your-org/private-infra.git
targetRevision: main
path: .
The workspace controller injects the username and password into the plan and apply Pods through valueFrom.secretKeyRef, so the credentials never traverse the controller process and never appear on the Workspace CR.
Private SSH repositories
For SSH, the Secret shape is the same except sshPrivateKey replaces username and password:
apiVersion: v1
kind: Secret
metadata:
name: gitlab-prod-readonly
namespace: default
labels:
magosproject.io/secret-type: repository
type: Opaque
stringData:
repoURL: [email protected]:your-org/private-infra.git
sshPrivateKey: |
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
Then point the Workspace at the same URL:
spec:
source:
repoURL: [email protected]:your-org/private-infra.git
targetRevision: main
path: .
SSH host-key verification is intentionally disabled inside the runner Pod. The Pod is throwaway, there is no persisted known_hosts to compare against, and shipping a known_hosts bundle inside the image would be brittle. Clusters that need stricter SSH verification should layer that in through the Pod spec (init container, mounted known_hosts, custom service account) rather than relying on the runner image.
If a Secret has both sshPrivateKey and username/password, the SSH key wins. This matches the precedence Git itself applies.
Git remote helpers
Magos uses go-git for HTTP, HTTPS, SSH, the Git protocol, file://, local paths, and SCP-like SSH URLs. Repository URLs with another scheme are delegated to the native Git CLI, so a standard git-remote-<scheme> executable can provide the transport without changing the Workspace API.
For example, this URL causes Git to invoke git-remote-codecommit:
spec:
source:
repoURL: codecommit://profile@example
targetRevision: main
The default controller and job images include Git but do not include remote helpers. Build derivative versions of both images and install the helper under its canonical executable name. The controller image needs it for RefWatcher to run git ls-remote; the job image needs it to clone the repository.
FROM ghcr.io/magosproject/magos/controller:VERSION
USER 0
COPY git-remote-codecommit /usr/local/bin/git-remote-codecommit
USER 65532:65532
Create the corresponding job image from ghcr.io/magosproject/magos/job:VERSION. That image already runs as root, so it does not need the final USER directives. Select both derivative images with Helm values:
image:
repository: registry.example.com/magos/controller-with-codecommit
tag: VERSION
jobImage:
repository: registry.example.com/magos/job-with-codecommit
tag: VERSION
Remote helpers inherit the environment and Kubernetes ServiceAccount of the process invoking them. Configure RefWatcher with controllers.refwatcher.serviceAccount, controllers.refwatcher.env, and controllers.refwatcher.envFrom. Configure plan-job cloud identity with the Workspace's spec.serviceAccountName.
Repository credentials injected into a plan job are also visible to its helper, but interpreting those variables is helper-specific. RefWatcher does not resolve per-Workspace repository credential Secrets, so any credentials it needs must come from its own ServiceAccount, environment, or referenced configuration.
Rotation
Rotating a credential Secret triggers an immediate refresh: the workspace controller watches Secret resources labelled magosproject.io/secret-type=repository and re-reconciles every Workspace whose repoURL matches the rotated Secret. The next Plan Job will pick up the new credentials.
There is no in-controller credential cache to worry about. The kubelet reads the Secret at Pod start, so a rotation that happens between the controller writing the Job spec and the Pod actually scheduling will be picked up on the next Job creation, not silently retained.
Where credentials live
Magos never copies repository credentials onto a Workspace CR. The credential flow is:
- The credential lives in a Secret in the same namespace as the Workspace.
- The workspace controller refers to that Secret through
valueFrom.secretKeyRefin the Job spec. - The kubelet resolves the env vars (
GIT_USERNAME,GIT_PASSWORD, orGIT_SSH_PRIVATE_KEY) at Pod start. - The
magos-jobbinary reads those env vars and makes them available to the selected Git transport. For built-in transports, it hands them to go-git; remote helpers inherit them as environment variables.
The controller process holds the Secret in its watch cache (because it needs to match repoURL to find the right Secret) but never writes credentials to status or logs. The cache for the workspace controller is restricted by label, so only magosproject.io/secret-type=repository Secrets are loaded; other Secrets in the namespace (including Variable-Set-referenced ones) are never read by the workspace controller.