This guide outlines the process of migrating a Nexus Docker instance from OrientDB (deprecated since version 3.71) to PostgreSQL, with an intermediate step through H2. Follow the instructions step by step to ensure proper execution of the migration.
I decided to create this guide because the official documentation is incomplete and not always reliable. I've consolidated information from Stack Overflow, Reddit, GitHub issues, and the official documentation to provide a more comprehensive solution.
This guide is also suitable for migrating from H2 to Postgres, just skip the first part.
- If you haven't done so, update the Nexus3 Docker image to version 3.70.3 (the latest available for OrientDB).
-
Backup the
nexus.propertiesfile:docker cp nexus_container_name:/opt/sonatype/sonatype-work/nexus3/etc/nexus.properties . -
Stop the container:
docker-compose down
-
Backup the Nexus database folder
-
Modify the
docker-compose.ymlfile: Add the mapping for thenexus.propertiesfile:volumes: - ./nexus.properties:/opt/sonatype/sonatype-work/nexus3/etc/nexus.properties
-
Start the container again:
docker-compose up -d
Why not migrate directly to Postgres? Because before version 3.77, you can only do it with the Pro version. :)
-
Access the container:
docker exec -ti nexus_container_name bash -
From the Nexus web interface, in the Tasks section, perform the backup and store the last 4
.bakfiles in a folder. -
Enter the backup folder and download the Nexus database migrator:
curl -s -L -O https://download.sonatype.com/nexus/nxrm3-migrator/nexus-db-migrator-3.70.1-03.jar
-
Run the H2 database migration:
java -Xmx2G -Xms2G -XX:+UseG1GC -XX:MaxDirectMemorySize=28672M -jar nexus-db-migrator-3.70.1-03.jar --migration_type=h2
-
Stop Nexus:
/opt/sonatype/nexus/bin/nexus stop
-
If the
nexus.mv.dbfile exists, copy it to the/nexus-data/dbfolder:cp nexus.mv.db /nexus-data/db
-
Exit the container
-
Stop the container again:
docker-compose down
-
Add the following configuration in the
nexus.propertiesfile:nexus.datastore.enabled=true -
Start the containers:
docker-compose up -d
-
Check the logs to verify that the database was correctly migrated:
docker logs nexus_container_name | grep H2
The database is now perfectly migrated to H2.
Now, you could update to the latest version and it would work, but then you wouldn't be able to migrate to Postgres (I have no idea why they don't mention it in the docs). So, you need to use version 3.77, the version from which it's possible to migrate to Postgres without the Pro version.
-
Update the Nexus version to
3.77.1and remove the mapping for thenexus.propertiesfile. -
Start the container:
docker-compose up -d
If you don't have the default encryption key error, skip the following steps.
-
Create a
secret.jsonfile with the following structure:{ "active": "key", "keys": [ { "id": "key", "key": "very secure and long password string" } ] } -
Add the following environment variables in the
docker-compose.ymlfile:environment: - NEXUS_SECRETS_KEY_FILE=/opt/sonatype/secret.json volumes: - ./secret.json:/opt/sonatype/secret.json
-
Restart the container:
docker-compose down && docker-compose up -d -
Re-encrypt the secret key using the REST API (you have to change only password and hostname):
curl -u admin:<password> -X 'PUT' \ 'http(s)://your.repo.com/service/rest/v1/secrets/encryption/re-encrypt' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -H 'NX-ANTI-CSRF-TOKEN: token' \ -H 'X-Nexus-UI: true' \ -d '{ "secretKeyId": "key" }'
-
Add PostgreSQL to the
docker-compose.ymlfile:postgres: image: postgres:17.4 hostname: db restart: on-failure volumes: - ./postgresql_data:/var/lib/postgresql/data environment: POSTGRES_DB: nexus POSTGRES_USER: nexus POSTGRES_PASSWORD: nexus PGDATA: /var/lib/postgresql/data/pgdata PGOPTIONS: -c max_connections=200 healthcheck: test: ["CMD-SHELL", "sh -c 'pg_isready -U nexus -d nexus'"] interval: 30s timeout: 10s retries: 5
Change the password of course...
PGOPTIONS: -c max_connections=200It's not required, but it's recommended. -
Add this to nexus service in the
docker-compose.ymlfile:depends_on: postgres: condition: service_healthy restart: true
-
Start the containers:
docker-compose up -d
-
Clean the backup directory
-
From the Nexus web interface, in the Tasks section, perform the backup and store the .zip file in a folder
-
Access the container:
docker exec -ti nexus_container_name bash -
Cd into the zip folder
-
Stop Nexus:
/opt/sonatype/nexus/bin/nexus stop
-
Copy the Nexus database:
cp /nexus-data/db/nexus.mv.db . -
Download the Nexus database migrator:
curl -s -L -O https://download.sonatype.com/nexus/nxrm3-migrator/nexus-db-migrator-3.77.1-01.jar
-
Run the migration from H2 to PostgreSQL:
java -Xmx16G -Xms16G -XX:+UseG1GC -XX:MaxDirectMemorySize=28672M -jar nexus-db-migrator-*.jar --migration_type=h2_to_postgres --db_url="jdbc:postgresql://db:5432/nexus?user=nexus&password=nexus¤tSchema=public"
-
Exit the container
-
Access the postgres container:
docker exec -ti postgres_container_name bash -
Access PostgreSQL:
psql -U nexus
-
Run the
VACUUMcommand to optimize the database:VACUUM(FULL,ANALYZE,VERBOSE);
-
Check the
max_connectionsconfiguration:SHOW max_connections;
If it's not set to 200, set
max_connectionsto 200 and delete the PGOPTIONS env variable fromdocker-compose.yml:ALTER SYSTEM SET max_connections = 200;
-
Exit the container
-
Stop the containers:
docker-compose down
-
Modify the
docker-compose.ymlfile by removing the mappings fornexus-dataandbackupfolder (if any), and adding the following environment variables:environment: - NEXUS_DATASTORE_NEXUS_JDBCURL: jdbc:postgresql://db:5432/nexus?currentSchema=public - NEXUS_DATASTORE_NEXUS_USERNAME: nexus - NEXUS_DATASTORE_NEXUS_PASSWORD: nexus - NEXUS_DATASTORE_NEXUS_ADVANCED: maximumPoolSize=190
190 is arbitrary, the important thing is that it's not 200. If you've left the default value in Postgres (100), set a number lower than one hundred. Otherwise, in Postgres, you'll get "FATAL: sorry, too many clients already."
-
Start the containers:
docker-compose up -d
You may need to run
docker-compose downanddocker-compose up -dagain.
- If you encounter errors in the Java command, try removing the options
-Xmx2G -Xms2G -XX:+UseG1GC -XX:MaxDirectMemorySize=28672M.
It took me a lot of time, study, swearing, and more to create this guide. I want to donate the result of my efforts to the community, but if you feel like thanking me, buy me a coffee! : paypal.me/mirawara