Run a ZDM migration job interactively and it will stop repeatedly to ask for passwords — source admin, target admin, GoldenGate admin, TDE keystore, and more, depending on the migration type. That’s fine for a one-off manual run, but it breaks entirely once ZDM is kicked off from a scheduler, a CI/CD pipeline, or an unattended runbook. The fix is wallet-based credential storage: ZDM reads passwords from an Oracle wallet instead of prompting for them.
What ZDM Prompts For
Logical migration (Data Pump/GoldenGate-based) typically prompts for:
Enter source database administrative user "SYSTEM" password:
Enter source database administrative user "GGADMIN" password:
Enter source container database administrative user "SYSTEM" password:
Enter source container database administrative user "C##GGADMIN" password:
Enter target database administrative user "SYSTEM" password:
Enter target database administrative user "GGADMIN" password:
Enter Oracle GoldenGate hub administrative user "oggadmin" password:
Physical migration (Data Guard-based) typically prompts for:
Enter source database DBNAME SYS password:
Enter user "opc" password:
Enter source database DBNAME TDE keystore password:
Each of these can be sourced from a wallet instead.
Prerequisites
- A running ZDM install (see the installation guide) with
ZDM_HOMEandZDM_BASEset for the account running the wallet setup. - The
orapkiandmkstoreutilities, both bundled with$ZDM_HOME/bin— no separate install needed.
Logical Migration Wallets
1. Create Wallet Directories
One wallet per credential keeps rotation simple later — updating one user’s password doesn’t require touching any other wallet:
mkdir -p $ZDM_BASE/wallets/src_admin
mkdir -p $ZDM_BASE/wallets/src_ggadmin
mkdir -p $ZDM_BASE/wallets/src_admin_cdb
mkdir -p $ZDM_BASE/wallets/src_ggadmin_cdb
mkdir -p $ZDM_BASE/wallets/tgt_admin
mkdir -p $ZDM_BASE/wallets/tgt_ggadmin
mkdir -p $ZDM_BASE/wallets/ogg_oggadmin
2. Create the Wallet Files
-auto_login_only is what makes these readable by the ZDM process without a wallet password prompt of its own — without it, you’ve just moved the password prompt problem one layer down instead of solving it:
for w in src_admin src_ggadmin src_admin_cdb src_ggadmin_cdb tgt_admin tgt_ggadmin ogg_oggadmin; do
$ZDM_HOME/bin/orapki wallet create -wallet $ZDM_BASE/wallets/$w -auto_login_only
done
Oracle PKI Tool Release 21.0.0.0.0 - Production
Version 21.0.0.0.0
Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved.
Operation is successfully completed.
3. Store the Credentials
Each mkstore call prompts for the password interactively once — this is the one place a human still has to type a password, and it happens exactly once per credential, not once per migration run:
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/src_admin -createCredential store system
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/src_ggadmin -createCredential store ggadmin
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/src_admin_cdb -createCredential store system
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/src_ggadmin_cdb -createCredential store c##ggadmin
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/tgt_admin -createCredential store system
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/tgt_ggadmin -createCredential store ggadmin
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/ogg_oggadmin -createCredential store oggadmin
Oracle Secret Store Tool Release 21.0.0.0.0 - Production
Version 21.0.0.0.0
Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved.
Your secret/Password is missing in the command line
Enter your secret/Password:
Re-enter your secret/Password:
4. Confirm the Credentials Are Stored
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/src_admin -listCredential | grep '^1'
A 1 entry with the expected username confirms the credential landed correctly — an empty result here means the wallet was created but the credential step silently failed or targeted the wrong wallet path.
5. Point ZDM at the Wallets
Add these to the ZDM response file used for the logical migration job. <ZDM_BASE> must be the full absolute path — a relative path here fails at job submission time, not at wallet creation time, which makes it a confusing error to trace back if you don’t already know to check this:
WALLET_SOURCEADMIN=<ZDM_BASE>/wallets/src_admin
WALLET_SOURCEGGADMIN=<ZDM_BASE>/wallets/src_ggadmin
WALLET_SOURCECONTAINER=<ZDM_BASE>/wallets/src_admin_cdb
WALLET_SOURCECGGADMIN=<ZDM_BASE>/wallets/src_ggadmin_cdb
WALLET_TARGETADMIN=<ZDM_BASE>/wallets/tgt_admin
WALLET_TARGETGGADMIN=<ZDM_BASE>/wallets/tgt_ggadmin
WALLET_OGGADMIN=<ZDM_BASE>/wallets/ogg_oggadmin
Physical Migration Wallets
Physical migration needs a smaller, different set of credentials — no GoldenGate admin users, but a TDE keystore password if the source is encrypted.
1. Create Directories and Wallets
mkdir -p $ZDM_BASE/wallets/src_sys
mkdir -p $ZDM_BASE/wallets/oss_user
mkdir -p $ZDM_BASE/wallets/src_tde
for w in src_sys oss_user src_tde; do
$ZDM_HOME/bin/orapki wallet create -wallet $ZDM_BASE/wallets/$w -auto_login_only
done
2. Store the Credentials
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/src_sys -createCredential store sysuser
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/oss_user -createCredential store ossuser
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/src_tde -createCredential store tdeuser
3. Point ZDM at the Wallets
These are passed as response-file parameters (not WALLET_ prefixed variables) for physical migrations:
-sourcesyswallet <ZDM_BASE>/wallets/src_sys
-osswallet <ZDM_BASE>/wallets/oss_user
-tdekeystorewallet <ZDM_BASE>/wallets/src_tde
For example:
-sourcesyswallet /u01/zdm/zdmbase/wallets/src_sys
-osswallet /u01/zdm/zdmbase/wallets/oss_user
-tdekeystorewallet /u01/zdm/zdmbase/wallets/src_tde
A Note on Wallet Rotation
When a source or target password changes, the wallet needs updating too — ZDM has no awareness that a database password rotated unless the wallet is refreshed to match:
$ZDM_HOME/bin/mkstore -wrl $ZDM_BASE/wallets/src_admin -modifyCredential store system
Build password rotation into whatever process changes these database passwords in the first place; a stale wallet fails a migration job exactly the way a stale token fails a git push — quietly, and usually at the least convenient moment.