Migration Guide: Production/Pro (External PostgreSQL)📜
This guide covers migrating from the legacy Big Bang nexus-repository-manager chart to the new nxrm-ha chart in production environments with external PostgreSQL. This is primarily a Helm chart architecture change - your data stays the same.
ℹ️ NOTE: This guide assumes you already have an external PostgreSQL database. If you’re migrating from H2 (embedded database), see the OSS/Development Migration Guide instead.
Overview📜
What’s Changing:
- Deployment → StatefulSet
- Direct values → Passthrough pattern (values nested under upstream key)
- Single container → Multi-container pod (main app + log sidecars)
What Stays the Same: - External PostgreSQL database (same connection, same data) - External blob storage (S3/Azure/NFS - same buckets/containers) - All repositories, artifacts, users, and configurations
Prerequisites📜
- Access to the Kubernetes cluster
kubectlCLI tool installedhelmCLI tool installedfluxCLI tool installed (if using GitOps)- Admin access to the existing Nexus instance
- External PostgreSQL database already configured
- External blob storage (S3/Azure/NFS) already configured
- Backups of database and blob storage
Estimated Downtime: 30 - 45 minutes
Values Migration: Passthrough Pattern📜
The main change is restructuring your values file. Big Bang additions stay at root level, upstream chart values move under upstream:.
Values Mapping Reference📜
| Configuration | Old Chart Location | New Chart Location |
|---|---|---|
| Hostname/Domain | hostname, domain |
hostname, domain (unchanged) |
| Admin Password | custom_admin_password |
custom_admin_password (unchanged - MUST match existing password during migration) |
| Database Config | Env vars + secrets | nexus.database.host, nexus.database.user, nexus.database.password (chart auto-creates secret) |
| Istio | istio.* |
istio.* (unchanged) |
| Network Policies | networkPolicies.* |
networkPolicies.* (unchanged) |
| Monitoring | monitoring.* |
monitoring.* (unchanged) |
| SSO/SAML | sso.* |
sso.* (unchanged) |
| Blob Stores | nexus.blobstores.* |
nexus.blobstores.* (unchanged) |
| Image | image.repository, image.tag |
upstream.statefulset.container.image.repository, upstream.statefulset.container.image.nexusTag |
| Resources | resources.* |
upstream.statefulset.container.resources.* |
| Service Account | serviceAccount.* |
upstream.serviceAccount.* |
| Environment Vars | env.* |
upstream.statefulset.container.env.* |
| Probes | livenessProbe.*, readinessProbe.* |
upstream.statefulset.livenessProbe.*, upstream.statefulset.readinessProbe.* |
Example Values File📜
addons:
nxrm-ha:
enabled: true
values:
# Big Bang-specific configurations
hostname: nexus
domain: example.com
istio:
enabled: true
injection: enabled
networkPolicies:
enabled: true
monitoring:
enabled: true
sso:
enabled: false # Configure if needed
# Custom admin password (MUST match existing if migrating)
custom_admin_password: "SomeSecurePassword123!"
# Security realms configuration
realms:
- NexusAuthenticatingRealm
- LdapRealm
- NpmToken
nexus:
# External database configuration - chart will auto-create "nexus-postgresql" secret
database:
host: "postgres.example.com" # YOUR external PostgreSQL host
user: "nexus" # YOUR database user
password: "your-password" # YOUR database password
# Docker registry configuration (optional)
docker:
enabled: true
registries:
- host: containers.dev.bigbang.mil
port: 5000
# Repository configuration (optional)
repository:
enabled: true
repo:
- name: "containers"
format: "docker"
type: "hosted"
repo_data:
name: "containers"
online: true
storage:
blobStoreName: "your-nexus-blobstore"
strictContentTypeValidation: true
writePolicy: "allow_once"
docker:
v1Enabled: false
forceBasicAuth: true
httpPort: 5000
# Blobstore configuration (optional - configure if using S3/Azure)
blobstores:
enabled: true
blobstore:
- name: "your-nexus-blobstore"
type: "s3"
blobstore_data:
name: "your-nexus-blobstore"
bucketConfiguration:
bucket:
region: "your-region"
name: "your-nexus-blobstore"
prefix: ""
expiration: 3
bucketSecurity:
accessKeyId: "your-accessKeyId"
secretAccessKey: "your-secretAccessKey"
sessionToken: "your-sessionToken"
# Disable internal PostgreSQL for production (use external RDS/managed database)
postgresql:
install: false
#=============================================================================
# Upstream Chart Values (Nested under 'upstream')
#=============================================================================
upstream:
nameOverride: nxrm-ha
fullnameOverride: nxrm-ha
serviceAccount:
enabled: true
name: nexus-repository-deployment-sa
# For AWS IRSA (S3 access):
# annotations:
# eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/nexus-role
statefulset:
replicaCount: 1 # OSS mode (use 3 for HA/Pro)
clustered: false # Set to true for HA/Pro
container:
image:
repository: registry1.dso.mil/ironbank/sonatype/nexus/nexus
nexusTag: 3.84.0-03
resources:
requests:
cpu: "4"
memory: "4Gi"
limits:
cpu: "4"
memory: "4Gi"
env:
install4jAddVmParams: "-Xms2048m -Xmx2048m -Dnexus.loadAsOSS=true"
# For HA/Pro mode: "-Xms2703m -Xmx2703m -Dnexus.datastore.nexus.maximumPoolSize=80"
jdbcUrlParams: null # Must start with a '?' e.g. "?foo=bar&baz=foo"
imagePullSecrets:
existingSecret:
enabled: true
name: "private-registry"
service:
nexus:
enabled: true
type: ClusterIP
port: 8081
secret:
existingDbSecret:
enabled: true
nexusAdminSecret:
enabled: false
# For HA/Pro with license:
# license:
# licenseSecret:
# enabled: true
# fileContentsBase64: <nexus-license>
What happens automatically:
- Chart creates nexus-postgresql secret from your nexus.database.* values
- Both init container and main container reference this secret
- No manual secret creation or additional overrides needed!
Step-by-Step Migration Process📜
This process has been tested and successfully preserves: - Repository configurations - Component data and artifacts metadata - User accounts and passwords - System settings
Step 1: Prepare for Migration📜
Backup your current configuration and prepare the environment:
export NEXUS_NAMESPACE="nexus-repository-manager"
# Backup current configuration (if not using GitOps)
kubectl get all,secrets,cm -n $NEXUS_NAMESPACE -o yaml > backup.yaml
helm get values nexus-repository-manager -n bigbang > old-values.yaml
# Create your new nxrm-ha-values.yaml using the example above
Step 2: Suspend Old Flux HelmRelease (If Using GitOps)📜
Important: If using Flux/GitOps, suspend the OLD HelmRelease to prevent Flux from reconciling it back during migration. The new nxrm-ha chart will be managed by a separate HelmRelease.
# Suspend OLD Flux HelmRelease (prevents auto-reconciliation during migration)
flux suspend hr nexus-repository-manager -n bigbang
# Verify suspension
flux get hr nexus-repository-manager -n bigbang
# Expected: SUSPENDED should be True
Note:
- Skip this step if not using Flux/GitOps
- The old HelmRelease will remain suspended - the new nxrm-ha HelmRelease manages the new deployment
- You can delete the old HelmRelease after successful migration
Step 3: Scale Down Old Nexus Deployment and Clean Up Resources📜
Important: Scale down the old deployment BEFORE deploying the new chart to prevent both from accessing the same PostgreSQL database simultaneously.
# Scale down old deployment
kubectl scale deployment nexus-repository-manager -n $NEXUS_NAMESPACE --replicas=0
# Wait for termination
kubectl wait --for=delete pod -l app=nexus-repository-manager \
-n $NEXUS_NAMESPACE --timeout=300s
# Delete old Istio VirtualServices to prevent conflicts with new chart
kubectl delete virtualservice -n $NEXUS_NAMESPACE --all
Step 4: Deploy NXRM-HA Chart📜
Configure the nxrm-ha addon in your Big Bang values. Important: Ensure database credentials, custom admin password, and blobstore settings match your existing nexusRepositoryManager deployment.
# nxrm-ha-migration.yaml
addons:
nexusRepositoryManager:
enabled: true # Keep old one running during migration
nxrm-ha:
enabled: true
values:
custom_admin_password: "SomeSecurePassword123!" # MUST match existing admin password
realms:
- NexusAuthenticatingRealm
- LdapRealm
- NpmToken
nexus:
hostname: nxrm-ha
docker:
enabled: true
registries:
- host: containers.dev.bigbang.mil
port: 5000
repository:
enabled: true
repo:
- name: "containers"
format: "docker"
type: "hosted"
repo_data:
name: "containers"
online: true
storage:
blobStoreName: "your-nexus-blobstore"
strictContentTypeValidation: true
writePolicy: "allow_once"
cleanup:
policyNames:
- "string"
component:
proprietaryComponents: true
docker:
v1Enabled: false
forceBasicAuth: true
httpPort: 5000
blobstores:
enabled: true
blobstore:
- name: "your-nexus-blobstore"
type: "s3"
blobstore_data:
name: "your-nexus-blobstore"
bucketConfiguration:
bucket:
region: "your-region"
name: "your-nexus-blobstore"
prefix: ""
expiration: 3
bucketSecurity:
accessKeyId: "your-accessKeyId"
secretAccessKey: "your-secretAccessKey"
sessionToken: "your-sessionToken"
# External PostgreSQL database configuration for production
# MUST match your existing nexusRepositoryManager database settings
database:
host: "postgres.example.com" # Replace with your RDS endpoint
user: "nexus" # Database username
password: "your-password" # Use sealed secrets in production!
# Disable internal PostgreSQL for production (use external RDS/managed database)
postgresql:
install: false
# HA configuration with Pro license and external PostgreSQL
# Production-ready setup with:
# - 3 replicas for high availability
# - External PostgreSQL database (see nexus.database config above)
# - S3 blob storage for shared artifact storage
# - Pro license for HA features
#
upstream:
statefulset:
replicaCount: 3
clustered: true
container:
env:
nexusDBName: nexus
nexusDBPort: 5432
install4jAddVmParams: "-Xms2703m -Xmx2703m -Dnexus.datastore.nexus.maximumPoolSize=80"
jdbcUrlParams: null # Must start with a '?' e.g. "?foo=bar&baz=foo"
zeroDowntimeEnabled: false
# Override default additionalEnv to remove empty LICENSE_FILE (OSS default)
# Keep DB vars but omit LICENSE_FILE - chart sets it automatically from license secret
additionalEnv:
- name: DB_NAME
value: "nexus"
- name: DB_HOST
valueFrom:
secretKeyRef:
name: nexus-postgresql
key: DB_HOST
- name: DB_USER
valueFrom:
secretKeyRef:
name: nexus-postgresql
key: DB_USER
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: nexus-postgresql
key: DB_PASSWORD
secret:
license:
licenseSecret:
enabled: true
fileContentsBase64: <nexus-license>
Critical Migration Requirements:
-
Database credentials MUST match your existing
nexusRepositoryManagerdeployment:database: host: "postgres.example.com" user: "nexus" password: "your-password" -
Admin password MUST match your existing Nexus admin password (stored in the database):
First, retrieve your current admin password from the old deployment:
# Get existing admin password from old secret
kubectl get secret nexus-repository-manager-secret -n nexus-repository-manager \
-o jsonpath='{.data.admin-password}' | base64 -d; echo
Then set it in your nxrm-ha values at the root level:
custom_admin_password: "SomeSecurePassword123!" # Use the password from above
Important: This password is stored in the migrated database. If the Kubernetes secret password doesn’t match the database password, authentication will fail for automation (EULA job, scripts, etc.).
-
Blobstore configuration MUST match your existing blob storage setup (if using S3/Azure):
blobstores: enabled: true blobstore: - name: "your-nexus-blobstore" type: "s3" -
Other upstream settings should mirror your existing deployment (image, resources, service account, etc.)
After configuring, deploy via GitOps or Helm:
# If using GitOps: commit the configuration and let Flux deploy
# OR manually with Helm:
helm upgrade -i bigbang chart/ -n bigbang --create-namespace -f nxrm-ha-migration.yaml
# Wait for HelmRelease to be ready
kubectl wait helmrelease/nxrm-ha -n bigbang --for=condition=Ready --timeout=300s
Step 5: Verify Deployment📜
After deployment, verify these critical checks:
# 1. Verify HelmRelease was successful
flux get hr nxrm-ha -n bigbang
# Expected: READY should be True, MESSAGE should show "Helm install succeeded" or "Helm upgrade succeeded"
# Example output:
# NAME REVISION SUSPENDED READY MESSAGE
# nxrm-ha 84.0.0-bb.3 False True Helm install succeeded for release nxrm-ha/nxrm-ha.v1 with chart nxrm-ha@84.0.0-bb.3
# 2. Verify NXRM-HA pod is running
kubectl get pods -n nxrm-ha -l app.kubernetes.io/name=nxrm-ha
# Expected: 5/5 Running (main app + sidecars)
# Example output:
# NAME READY STATUS RESTARTS AGE
# nxrm-ha-0 5/5 Running 0 2m
# 3. Get admin password
kubectl get secret nxrm-ha-adminsecret \
-n nxrm-ha -o jsonpath='{.data.nexus-admin-password}' | base64 -d; echo
# 4. Verify Nexus UI access
# Navigate to https://nexus.example.com (URL remains unchanged)
# Login with admin and the password from above
# Verify repositories and blob stores are accessible
# Check that existing artifacts are available
Important: Do not proceed to the next step until: - HelmRelease shows READY=True - NXRM-HA pod shows 5/5 Running
Step 6: Post-Migration Tasks📜
These tasks are critical to the proper functioning of the repository after the migration process. Some tasks may take a notable amount of time to complete.
⚠️ WARNING: Do not restart your instance while the post-migration tasks are running to avoid damaging your browse and search index.
Run these repair tasks manually via the Nexus UI:
-
Navigate to Administration → System → Tasks
-
First: Create and run Repair - Rebuild repository browse
- Task name:
Rebuild repository browse - Repository:
(All Repositories) - Task frequency:
Manual -
Click Create task, then click Run
-
Second: Create and run Repair - Rebuild repository search
- Task name:
Rebuild repository search - Repository:
(All Repositories) - Task frequency:
Manual -
Click Create task, then click Run
-
Third: Create and run Repair - Reconcile component database from blob store
- Task name:
Reconcile blob store - Blob store:
default(or your blob store name) - Task frequency:
Manual - Click Create task, then click Run
- Wait for this task to complete before proceeding (check task status)
-
This scans the blob store directory and updates the database with blob metadata
-
Fourth: Create and run Repair - Recalculate blob store storage
- Task name:
Recalculate blob store metrics - Blob store:
default(or your blob store name) - Task frequency:
Manual - Click Create task, then click Run
-
This updates the Blob Count and Total Size metrics displayed in the UI
-
(If using Helm repositories): Create and run Repair - Rebuild Helm metadata
-
Verify Scheduled Tasks: Navigate to Administration → System → Tasks and verify your previously configured scheduled tasks are present. Recreate any missing tasks (e.g., cleanup policies, repository health checks, compact blob store).
Important Notes: - The Reconcile task is essential - it syncs the blob store files with the database - The Recalculate task updates UI metrics - without it, Blob Store page shows 0 blobs - All tasks must complete successfully before the migration is considered complete - Monitor task progress in the Tasks UI before proceeding
Step 7: Disable Old Addon (GitOps)📜
After confirming the migration is successful and stable, disable the old nexusRepositoryManager addon in your Big Bang values:
addons:
nexusRepositoryManager:
enabled: false
Note: Only do this after you’re confident the migration is successful and you won’t need to rollback.
Rollback Procedure📜
If issues occur during or after migration, you can rollback to the old deployment:
Option 1: Using GitOps/Flux📜
# 1. Disable nxrm-ha addon in Big Bang values
addons:
nxrm-ha:
enabled: false
# 2. Re-enable old nexusRepositoryManager addon
addons:
nexusRepositoryManager:
enabled: true
# ... your previous values
Commit and let Flux reconcile.
Option 2: Manual Rollback📜
# Scale down nxrm-ha StatefulSet
kubectl scale statefulset nxrm-ha -n nxrm-ha --replicas=0
# Wait for pods to terminate
kubectl wait --for=delete pod -l app.kubernetes.io/name=nxrm-ha -n nxrm-ha --timeout=300s
# Resume old Flux HelmRelease (if it was suspended in Step 2)
flux resume hr nexus-repository-manager -n bigbang 2>/dev/null || echo "Not using Flux"
# Scale up old deployment
kubectl scale deployment nexus-repository-manager -n nexus-repository-manager --replicas=1
# Verify old deployment is running
kubectl get pods -n nexus-repository-manager
Important: - Since both deployments use the same external PostgreSQL database, data changes made in NXRM-HA will persist after rollback - Ensure you have backups before attempting rollback
What Gets Migrated📜
The migration successfully preserves: - ✅ All repository configurations (Maven, Docker, NPM, PyPI, etc.) - ✅ Component data and artifacts metadata - ✅ User accounts and passwords - ✅ Roles and permissions - ✅ System configuration - ⚠️ Scheduled tasks (may need to be recreated - verify after migration) - ✅ Security settings - ✅ Blob store configurations
Key Differences After Migration📜
| Feature | Legacy Chart | NXRM-HA |
|---|---|---|
| Database | External PostgreSQL | External PostgreSQL (unchanged) |
| Namespace | nexus-repository-manager | nxrm-ha |
| Pod Name | nexus-repository-manager-* | nxrm-ha-* |
| Admin Secret | nexus-repository-manager-secret | nxrm-ha-adminsecret |
| Service Name | nexus-repository-manager | nxrm-ha |
| Service Account | nexus-repository-manager | nexus-repository-deployment-sa |
| Log Access | kubectl logs deploy/nexus-repository-manager |
kubectl logs statefulset/nxrm-ha -c nxrm-app |
| Values Structure | Direct | Nested under upstream: |
| High Availability | Not supported | Supported (Pro only) |