Skip to content

Nexus Service Accounts

All Nexus CI/CD authentication is managed through Vault. Credentials are never stored as GitLab CI/CD variables or in source code.


Account Overview

Three service accounts cover all automated Nexus operations:

Account Vault Path Permissions Used By
svc-orchestrator secret/nexus/svc-orchestrator Docker + RPM + Raw + PyPI (read/write) Platform CI/CD builds, deployments
svc-executor secret/nexus/svc-executor RPM + Raw (read/write) Executor CLI CI/CD builds
svc-deployer secret/nexus/svc-deployer Docker pull only (read) Kubernetes deployments, EC2 deployments

When to Use Each Account

  • svc-orchestrator — Default for all platform services (server, ui, iam-api, notification-api, etc.). Handles Docker push on build, Docker pull on deploy, and PyPI publish for cwiq-common.
  • svc-executor — Exclusive to the executor project. Has write access only to RPM and raw artifact repositories. Cannot push Docker images.
  • svc-deployer — Pull-only. Used by Kubernetes pods and EC2 deployment scripts that need to pull images from Nexus without build privileges.

Do not create new service accounts for individual services

All platform services share svc-orchestrator. Only create a new account if you genuinely need a different permission scope — for example, a service that should only be able to pull, not push. Coordinate with the infrastructure team to add the account to Vault and Nexus.


Authentication Flow in CI/CD

Nexus credentials are never injected as static GitLab CI/CD variables. Every pipeline fetches them at runtime from Vault using GitLab's JWT token:

sequenceDiagram
    participant Job as CI/CD Job
    participant Vault as HashiCorp Vault
    participant Nexus as Nexus Registry

    Job->>Vault: POST /v1/auth/jwt/login<br/>(CI_JOB_JWT_V2 token, role=nexus-ci)
    Vault-->>Job: Vault client token
    Job->>Vault: GET /v1/secret/nexus/svc-orchestrator<br/>(with Vault token)
    Vault-->>Job: { username, password }
    Job->>Nexus: docker login nexus.shared.cwiq.io:8443<br/>(username + password)
    Job->>Nexus: docker push orchestrator-server:main-abc123

The shared CI templates in .gitlab-ci-common.yml implement this flow. Individual project pipelines do not need to replicate it — they inherit it by extending the template jobs.

See Vault JWT Auth for the complete authentication pattern, Vault role configuration, and how to add Vault access for a new service.


Human Access (Web UI)

The Nexus Web UI (nexus.shared.cwiq.io) uses Authentik SSO for human access. Log in with your Authentik credentials — the same ones you use for GitLab, Vault, and Grafana.

Human accounts can:

  • Browse repositories and artifacts
  • Download artifacts manually
  • View storage usage and repository metadata

Human accounts cannot push artifacts. All artifact publishing is done by CI/CD service accounts.


Adding a New Service That Needs Nexus Access

For a new platform service that needs to push Docker images:

  1. The service uses the existing svc-orchestrator account — no new account needed
  2. Include the standard CI templates in the service's .gitlab-ci.yml (see CI/CD Pipeline Overview)
  3. The template's .build-push job handles Docker login and push automatically

For a new service that needs only pull access (e.g., a deployment script):

  1. Use the svc-deployer account
  2. Retrieve credentials from secret/nexus/svc-deployer in Vault
  3. Run docker login nexus.shared.cwiq.io:8444 before pulling

For a new service that needs a distinct permission scope:

  1. Contact the infrastructure team to create the account in Nexus
  2. The infrastructure team adds the credentials to Vault at secret/nexus/svc-{name}
  3. Update the Vault JWT role policy to grant the new service access to that path

Vault Secret Structure

Each service account secret in Vault contains:

{
  "username": "svc-orchestrator",
  "password": "<redacted>"
}

Fetching in a shell script:

# Authenticate to Vault (CI/CD — JWT flow)
VAULT_TOKEN=$(curl -s \
  --request POST \
  --data "{\"jwt\": \"${CI_JOB_JWT_V2}\", \"role\": \"nexus-ci\"}" \
  "${VAULT_ADDR}/v1/auth/jwt/login" | jq -r '.auth.client_token')

# Read credentials
NEXUS_USER=$(curl -s \
  --header "X-Vault-Token: ${VAULT_TOKEN}" \
  "${VAULT_ADDR}/v1/secret/nexus/svc-orchestrator" | jq -r '.data.username')

NEXUS_PASSWORD=$(curl -s \
  --header "X-Vault-Token: ${VAULT_TOKEN}" \
  "${VAULT_ADDR}/v1/secret/nexus/svc-orchestrator" | jq -r '.data.password')

The shared CI template abstracts this into a reusable before-script block. Individual jobs do not call these endpoints directly.