Oracle Database 21c EE with ASM on AWS User Guide
Overview
This image runs Oracle Database 21c Enterprise Edition on Oracle Linux 8 with its datafiles on Oracle Automatic Storage Management (ASM) rather than on a conventional filesystem. ASM is the storage layer that Oracle recommends for the database, and it is what most enterprises standardise on for production Oracle estates on premises. Shipping an image whose storage already mirrors that layout gives you operational parity with your existing ASM deployments: the same asmcmd tooling, the same disk group model, and the same Grid Infrastructure stack that your DBAs already operate.
Oracle Database 21c is an Innovation Release. It is where Oracle first shipped many of the features that were later consolidated into the long term 23ai release — blockchain tables, native JSON, immutable tables, in database JavaScript, and automatic in memory enhancements among them — so it is the right choice when you want to evaluate or build on the newest Oracle capabilities. 21c is also a fully multitenant release: the traditional non container architecture is desupported, so the database is always a container database (CDB) with one or more pluggable databases (PDBs) inside it. This image is preconfigured with a CDB named ORCL and a single user pluggable database named ORCLPDB. Your applications connect to the ORCLPDB service and see an ordinary database; the CDB root (ORCL) is the administrative container that holds the Oracle supplied metadata and the shared background processes. The PDB$SEED template is also present — Oracle uses it to clone new PDBs.
ASM is delivered here through single instance Grid Infrastructure, also known as Oracle Restart. The Grid Infrastructure stack (ohasd, Cluster Synchronization Services, and the ASM instance +ASM) is installed in its own home, mounts the ASM disk groups at boot, and then automatically starts the ASM instance, the TNS listener, and the ORCL database — no systemd database unit is needed, because Oracle Restart itself is the high availability framework that brings the database up and keeps it up. The pluggable database ORCLPDB has its own Oracle Restart resource and is configured to open automatically every time the CDB starts.
Two ASM disk groups are configured. +DATA holds the datafiles, the current control file, the online redo logs, and the server parameter file. +RECO is the Fast Recovery Area: it holds the archived redo logs, the multiplexed copy of the control file, and the second members of the redo log groups. Both disk groups use EXTERNAL redundancy. This is deliberate: every EBS volume is already synchronously replicated across the storage fleet within its Availability Zone, so layering ASM mirroring on top would double or triple the storage cost for no additional durability. The value ASM adds on AWS is multi volume IOPS aggregation, online storage management, and parity with your on premises tooling — not extra copies of already replicated blocks.
This image ships Oracle Database 21c at the base 21.3.0.0.0 release. Oracle publishes Release Updates for 21c on My Oracle Support, and the security section at the end of this guide explains how to apply the latest one with OPatch and datapatch for production use. A starter container database named ORCL with the pluggable database ORCLPDB is preconfigured, the SQL*Plus command line client is available in the Oracle home, and the Oracle listener on port 1521 is bound to the loopback address 127.0.0.1 only. The default security group opens SSH (port 22) and nothing else, so the database is not reachable from the network until you decide it should be: SQL Developer and JDBC clients on your workstation connect through an SSH tunnel, and Step 9 also shows how to open port 1521 deliberately, with network encryption, to your own network only. The Grid Infrastructure home and the Database home live on a dedicated 50 GiB EBS gp3 volume mounted at /u01, separate from the operating system disk, while the datafiles live on raw EBS volumes managed directly by ASM.
The image ships with no usable credentials. The Grid Infrastructure listener resource ships disabled, so at boot Oracle Restart opens ASM and the database with no listener running. On the first boot of every launched instance, a one shot service named oracle-db-21c-firstboot.service then sets a unique random 24 character password on the database SYS, SYSTEM and PDBADMIN accounts and on the ASM SYS and ASMSNMP accounts, gives every other password account in the database a random password and leaves it locked and expired, and only then enables and starts the listener on 127.0.0.1. It proves that each new password works and that each historic or default password is refused, checks that no plaintext password reached the audit trail or the trace files, and writes the passwords to /root/oracle-db-credentials.txt with mode 0600 so that only the root user can read them. Two instances launched from the same image never share credentials. If you run an instance launched from an image released before October 2026, read Instances launched from earlier images in Step 19.
Prerequisites
Before you deploy this image you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network (port 1521 does not need to be open; you reach the listener through an SSH tunnel)
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Step 1: Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images choose AWS Marketplace AMIs and search for Oracle Database. Select the cloudimg listing for Oracle Database 21c EE with ASM on Oracle Linux 8 and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or larger. m5.large (2 vCPUs / 8 GiB RAM) is the smallest size Grid Infrastructure supports, and the starter database is sized to fit it: dbca automatic shared memory management with 3072 MB in total (an sga_target of about 2.3 GiB and a pga_aggregate_target of about 768 MiB), alongside about 1 GiB for the ASM instance and about 1 GiB for the Oracle Restart daemons. That is a sensible size for development and test. For production choose m5.xlarge (4 vCPUs / 16 GiB RAM) or larger, such as m5.2xlarge, m5.4xlarge or the memory optimised R5 and R6i families, and give the database the extra memory as shown in Step 10. Enterprise Edition has no socket cap, so the M5, M6i, R5, R6i, C5 and C6i families are all valid. Choose your EC2 key pair under Key pair (login). Under Network settings select your VPC and subnet, and either create or select a security group that allows inbound port 22 from your management network only. Do not add a rule for port 1521: the listener is bound to 127.0.0.1, and Step 9 explains how to reach it through an SSH tunnel or, if you need to, how to open it deliberately.
Leave the root volume at the default size. The image automatically adds three more EBS volumes, and you should keep all three:
| Volume | Device | Size | Filesystem | Holds |
|---|---|---|---|---|
/u01 |
/dev/sdf |
50 GiB | ext4 | Grid Infrastructure home, Database home, Oracle inventory |
+DATA |
/dev/sdg |
40 GiB | raw (ASM) | datafiles, control file, online redo, spfile |
+RECO |
/dev/sdh |
20 GiB | raw (ASM) | Fast Recovery Area, archive logs, control file copy |
The two ASM volumes are presented to the instance as raw block devices — they are not formatted with a filesystem, because ASM manages them directly. A udev rule in the image re applies the correct grid:asmadmin ownership to those devices on every boot, matched by their block device mapping position rather than by volume id, so ASM finds its disks again even though AWS Nitro renumbers the underlying /dev/nvmeXn1 names on each launch.
Select Launch instance. First boot initialisation takes approximately three to four minutes after the instance state becomes Running and the status checks pass, because the firstboot service waits for Oracle Restart to open the database and the pluggable database before rotating credentials. The listener only starts once every account has its own password.
Step 2: Launch the Instance from the AWS CLI
The following block launches an instance from the cloudimg Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens port 22 from your management network only, as described above. Note that the block device mapping recreates all four volumes — the root disk, the ext4 /u01 binaries disk, and the two raw ASM disks.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--block-device-mappings '[
{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":50,"VolumeType":"gp3"}},
{"DeviceName":"/dev/sdf","Ebs":{"VolumeSize":50,"VolumeType":"gp3"}},
{"DeviceName":"/dev/sdg","Ebs":{"VolumeSize":40,"VolumeType":"gp3"}},
{"DeviceName":"/dev/sdh","Ebs":{"VolumeSize":20,"VolumeType":"gp3"}}]' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=oracle-db-21c-ee-asm-01}]'
The command prints a JSON document on success. Note the instance ID, then retrieve its public address once it is running with aws ec2 describe-instances --instance-ids <instance-id> --query "Reservations[].Instances[].PublicIpAddress" --output text.
Step 3: Connect over SSH and Retrieve the Credentials
Wait for the EC2 instance to reach 2/2 status checks and for first boot to complete. Connect over SSH with the key pair you selected, using the ec2-user login name:
ssh -i <your-key.pem> ec2-user@<public-ip>
Once you are on the instance, read the credentials file with sudo:
sudo cat /root/oracle-db-credentials.txt
The file holds one KEY=value line per account, the Oracle SID (ORCL), the pluggable database service (PDB_SERVICE=ORCLPDB) and the listener address. Sample contents (the passwords on your instance are unique):
# Oracle Database 21c Enterprise Edition with ASM - per-instance credentials (cloudimg)
# Generated Sun Oct 18 10:12:31 UTC 2026 on i-0123456789abcdef0. Root-only (0600). Unique to this instance.
SYS_PASSWORD=CkEr8JYt1calXfxPIwb1Ecj4
SYSTEM_PASSWORD=DwRDQ3aBfQ7Ufam4DGNWrEh1
PDBADMIN_PASSWORD=PI7mBxUIZCxRIWVZYUfz69u2
ASM_PASSWORD=UkrMLja2LC2wRGlXrun6iur0
ASMSNMP_PASSWORD=Cc4NyCLW0nhPkfXjtmDT6Jn7
ORACLE_SID=ORCL
PDB_SERVICE=ORCLPDB
LISTENER=127.0.0.1:1521 (localhost only - use an SSH tunnel, or see the guide to open it deliberately with encryption)
Every other database account is locked and expired with a random password.
Connect: sudo su - oracle ; . ~/setEnv.sh ; sqlplus /nolog ; then CONNECT system@//localhost:1521/ORCLPDB
| Key | Account |
|---|---|
SYS_PASSWORD |
Database SYS; connect AS SYSDBA |
SYSTEM_PASSWORD |
Database SYSTEM, a common user valid in the CDB root and in ORCLPDB |
PDBADMIN_PASSWORD |
PDBADMIN, the local administrator of the pluggable database ORCLPDB |
ASM_PASSWORD |
SYS of the ASM instance +ASM; connect AS SYSASM |
ASMSNMP_PASSWORD |
ASMSNMP, the ASM monitoring account; it has its own password and does not share the ASM SYS password |
Every other password account in the database, such as DBSNMP and the other Oracle supplied accounts, was given a random password that nobody knows and is locked and expired. To use one of them, give it a new password and unlock it as SYSDBA (sudo su - oracle, . ~/setEnv.sh, sqlplus / as sysdba), for example:
ALTER USER DBSNMP IDENTIFIED BY "<new-strong-password>" ACCOUNT UNLOCK;
Run it in the container that owns the account: from the CDB root for a common account, or after ALTER SESSION SET CONTAINER = ORCLPDB; for an account local to the pluggable database.
Copy the passwords somewhere secure such as a password manager or an encrypted vault, and do not commit them to source control. Every command block in this guide that connects as SYSTEM reads the password from this file into a SYSPWD shell variable with awk -F'= *', which also tolerates a space after the =, so every block is self contained.
The image provisions two Oracle operating system users: oracle owns the database home and runs the ORCL instance, and grid owns the Grid Infrastructure home and runs the +ASM instance. Each has a setEnv.sh helper in its home directory that exports the correct ORACLE_HOME, ORACLE_SID, and library path, so you do not have to remember them.
Confirm First Boot with the Security Self Test
First boot writes the credentials file and then, last of all, its ready marker /var/lib/cloudimg/oracle-db-21c-firstboot.done. The image includes a self test that re-proves the security state of the instance: that every password in the credentials file works and every historic or default password is refused, that every other account is locked, that no plaintext password reached the audit trail, and that the listener and every database socket are bound to 127.0.0.1 only:
sudo /usr/local/sbin/cloudimg-oracle-selftest
It prints one PASS line per check and finishes with SELFTEST_OK (abridged sample):
PASS: ready marker present
PASS: no first-boot error notice
PASS: /root/oracle-db-credentials.txt is 0600 root:root
PASS: SYS@ORCL refuses a historic/default password
PASS: SYS@ORCL accepts its per-instance password
PASS: SYSTEM@ORCL accepts its per-instance password
PASS: PDBADMIN@ORCLPDB accepts its per-instance password
PASS: SYS@+ASM accepts its per-instance password
PASS: ASMSNMP@+ASM accepts its per-instance password
PASS: every other password account is locked
PASS: no literal IDENTIFIED BY password in v$sql or the unified audit trail
PASS: listener.ora binds 127.0.0.1 only
PASS: no database socket on a non-loopback address
PASS: first boot ordered after Oracle Restart
PASS: memory fits m5.large: sga_target 2304M, pga_aggregate_target 768M
PASS: first boot order: rotated -> listener (loopback) -> verified -> ready
PASS: no build secrets or response files left in the image
SELFTEST_OK
The self test checks the passwords recorded in the credentials file and the image's starter configuration, so after you rotate passwords (Step 15), raise the database memory (Step 10) or open the listener to the network (Step 9), the matching lines report a difference. That is expected.
If First Boot Did Not Complete
First boot is fail closed. If any step cannot be completed or proven, the service stops and disables the listener, stops the database, writes no credentials file, and explains what happened in /root/oracle-db-FIRSTBOOT-FAILED.txt. The instance never accepts database connections until every account has its own random password. To investigate:
sudo cat /root/oracle-db-FIRSTBOOT-FAILED.txt
sudo journalctl -u oracle-db-21c-firstboot.service -b
sudo reboot
A reboot retries first boot, which runs again on every boot until it succeeds. If it fails a second time, contact cloudimg support with the journal output.
Step 4: Verify Oracle Restart is Running
Oracle Restart (single instance Grid Infrastructure) is the framework that mounts the ASM disk groups and starts the ASM instance, the listener, the ORCL container database, and the ORCLPDB pluggable database at boot. Confirm the High Availability Services daemon is online and inspect the resource tree as the grid user:
sudo -u grid bash <<'OUTER'
. ~/setEnv.sh
crsctl check has
crsctl stat res -t
OUTER
The expected response confirms the stack is online and every resource — the two disk groups, the ASM instance, the listener, the ORCL database, and the orclpdb pluggable database — is in service:
CRS-4638: Oracle High Availability Services is online
--------------------------------------------------------------------------------
Name Target State Server State details
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.DATA.dg
ONLINE ONLINE oracle-asm STABLE
ora.LISTENER.lsnr
ONLINE ONLINE oracle-asm STABLE
ora.RECO.dg
ONLINE ONLINE oracle-asm STABLE
ora.asm
ONLINE ONLINE oracle-asm Started,STABLE
ora.ons
OFFLINE OFFLINE oracle-asm STABLE
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.cssd
1 ONLINE ONLINE oracle-asm STABLE
ora.diskmon
1 OFFLINE OFFLINE STABLE
ora.evmd
1 ONLINE ONLINE oracle-asm STABLE
ora.orcl.db
1 ONLINE ONLINE oracle-asm Open,HOME=/u01/app/o
racle/product/21.0.0
/dbhome_1,STABLE
ora.orcl.orclpdb.pdb
1 ONLINE ONLINE oracle-asm STABLE
--------------------------------------------------------------------------------
Three of these states are normal and expected and do not indicate a problem:
ora.orcl.orclpdb.pdbisONLINE— the pluggable databaseORCLPDBhas its own Oracle Restart resource, separate from theora.orcl.dbcontainer resource. It opens automatically whenever the CDB starts, because its open state is saved (confirmed in Step 14).ora.LISTENER.lsnris the listener, bound to127.0.0.1:1521only — the image ships this resource disabled, and first boot enables it only after every account has its own password; from then on Oracle Restart starts it with the rest of the stack on every boot. If Grid Infrastructure ever reports it asINTERMEDIATEwith "Not All Endpoints Registered", the listener is still fully functional: Step 6 confirms that it is serving every database service.ora.onsandora.diskmonareOFFLINE— Oracle Notification Service and the disk monitor are only used in a full RAC cluster (and on Exadata fordiskmon). They are inactive by design on a single instance Oracle Restart configuration and their state does not affect the database.
Step 5: Verify the ASM Disk Groups
The ASM disk groups are the storage that the database sits on. List them with asmcmd as the grid user:
sudo -u grid bash <<'OUTER'
. ~/setEnv.sh
asmcmd lsdg
OUTER
The expected response shows both disk groups MOUNTED with EXTERN (external) redundancy and reports the free space in each:
State Type Rebal Sector Logical_Sector Block AU Total_MB Free_MB Req_mir_free_MB Usable_file_MB Offline_disks Voting_files Name
MOUNTED EXTERN N 512 512 4096 4194304 40960 36324 0 36324 0 N DATA/
MOUNTED EXTERN N 512 512 4096 4194304 20480 19740 0 19740 0 N RECO/
Usable_file_MB equals Free_MB because external redundancy keeps no mirror reserve — every free megabyte is usable for data. You can also see the raw devices that back the disk groups; the image symlinks them under /dev/oracleasm/ with stable names, owned by grid:asmadmin:
ls -l /dev/oracleasm/
Returns the two ASM disks, each pointing at the underlying NVMe device that AWS attached this boot:
total 0
lrwxrwxrwx 1 root root 10 May 31 15:56 DATA1 -> ../nvme2n1
lrwxrwxrwx 1 root root 10 May 31 15:56 RECO1 -> ../nvme3n1
Step 6: Verify the Listener is Running
Oracle's TNS listener is the network endpoint for all client connections. It is owned by the Grid Infrastructure home and managed by Oracle Restart. Its configuration file, /u01/app/21.0.0/grid/network/admin/listener.ora, binds it to 127.0.0.1 only, with a static entry for the ASM instance and no dynamic endpoints, so it never listens on the instance's private or public address. Confirm it is up and serving the database services as the grid user:
sudo -u grid bash <<'OUTER'
. ~/setEnv.sh
lsnrctl status
OUTER
The expected response confirms the listener is listening on 127.0.0.1 port 1521 and that the ORCL container service, the orclpdb pluggable database service, and the +ASM services have registered with it. The +ASM service is listed twice: once from the static entry (status UNKNOWN) and once from the ASM instance's own registration (status READY):
LSNRCTL for Linux: Version 21.0.0.0.0 - Production on 18-OCT-2026 10:20:33
Copyright (c) 1991, 2021, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias LISTENER
Version TNSLSNR for Linux: Version 21.0.0.0.0 - Production
Start Date 18-OCT-2026 10:12:02
Uptime 0 days 0 hr. 8 min. 31 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Listener Parameter File /u01/app/21.0.0/grid/network/admin/listener.ora
Listener Log File /u01/app/grid/diag/tnslsnr/oracle-asm/listener/alert/log.xml
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
Services Summary...
Service "+ASM" has 2 instance(s).
Instance "+ASM", status UNKNOWN, has 1 handler(s) for this service...
Instance "+ASM", status READY, has 1 handler(s) for this service...
Service "+ASM_DATA" has 1 instance(s).
Instance "+ASM", status READY, has 1 handler(s) for this service...
Service "+ASM_RECO" has 1 instance(s).
Instance "+ASM", status READY, has 1 handler(s) for this service...
Service "ORCL" has 1 instance(s).
Instance "ORCL", status READY, has 1 handler(s) for this service...
Service "ORCLXDB" has 1 instance(s).
Instance "ORCL", status READY, has 1 handler(s) for this service...
Service "orclpdb" has 1 instance(s).
Instance "ORCL", status READY, has 1 handler(s) for this service...
The command completed successfully
The orclpdb service is the one your applications use — it routes connections into the pluggable database. ORCL is the CDB root service, used for administration. The kernel level confirmation that port 1521 is bound to the loopback address only:
sudo ss -Hltn 'sport = :1521' | awk '{print $4}'
Returns a single local address:
127.0.0.1:1521
Nothing listens on port 1521 on the instance's network interfaces, so the database is reachable only from the instance itself or through an SSH tunnel until you open it deliberately (Step 9).
Step 7: Connect Locally with SQL*Plus
The simplest way to talk to the database from the instance is the SQL*Plus client that ships with the Oracle Database installation. In 21c your application schemas live inside the pluggable database, so connect to the ORCLPDB service. Read the SYSTEM password from the credentials file, then connect over the listener:
SYSPWD=$(sudo awk -F'= *' '/^SYSTEM_PASSWORD=/{print $2}' /root/oracle-db-credentials.txt | head -1)
sudo -u oracle env SYSPWD="$SYSPWD" bash <<'OUTER'
. ~/setEnv.sh
sqlplus -S system/"$SYSPWD"@localhost:1521/ORCLPDB <<'SQL'
SET PAGESIZE 50 LINESIZE 200
SELECT banner FROM v$version WHERE banner LIKE 'Oracle%';
EXIT;
SQL
OUTER
The expected response confirms the installed Oracle Database release:
BANNER
--------------------------------------------------------------------------------
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
You can also connect interactively with operating system authentication, which needs no password. Switch to the oracle OS user, source its environment, and run sqlplus. Operating system authentication lands you in the CDB root; switch into the pluggable database with ALTER SESSION SET CONTAINER:
sudo su - oracle
. ~/setEnv.sh
sqlplus / as sysdba
ALTER SESSION SET CONTAINER = ORCLPDB;
In an interactive session, type EXIT; to leave SQL*Plus.
Step 8: Run a Sample Query
Create a small table in the pluggable database, insert two rows, read them back, then drop the table. This exercise confirms that the database is writable on ASM and that the SYSTEM user has the standard DDL grants inside ORCLPDB:
SYSPWD=$(sudo awk -F'= *' '/^SYSTEM_PASSWORD=/{print $2}' /root/oracle-db-credentials.txt | head -1)
sudo -u oracle env SYSPWD="$SYSPWD" bash <<'OUTER'
. ~/setEnv.sh
sqlplus -S system/"$SYSPWD"@localhost:1521/ORCLPDB <<'SQL'
SET PAGESIZE 50 LINESIZE 200
CREATE TABLE demo_users (id NUMBER, name VARCHAR2(50), created_at DATE);
INSERT INTO demo_users VALUES (1, 'Alice', SYSDATE);
INSERT INTO demo_users VALUES (2, 'Bob', SYSDATE);
COMMIT;
SELECT id, name, TO_CHAR(created_at,'YYYY-MM-DD') AS created_at FROM demo_users ORDER BY id;
DROP TABLE demo_users;
EXIT;
SQL
OUTER
Expected response:
Table created.
1 row created.
1 row created.
Commit complete.
ID NAME CREATED_AT
---------- -------------------------------------------------- ----------
1 Alice 2026-05-31
2 Bob 2026-05-31
Table dropped.
Step 9: Connect from a Remote Machine
The listener accepts connections on 127.0.0.1 only, and the default security group opens port 22 only. The recommended way to connect from your workstation is an SSH tunnel: it reuses the SSH access you already have, encrypts the database traffic inside SSH, and needs no extra security group rule. Open the tunnel from your workstation and leave it running while you work:
ssh -i <your-key.pem> -N -L 1521:127.0.0.1:1521 ec2-user@<public-ip>
Port 1521 on your workstation now forwards to the listener on the instance. If port 1521 is already in use on your workstation, forward a different local port, for example -L 1522:127.0.0.1:1521, and connect to localhost:1522.
From a host with sqlplus installed (the Oracle Instant Client tarball contains it), connect through the tunnel with Oracle's "Easy Connect" syntax and enter the SYSTEM_PASSWORD value from /root/oracle-db-credentials.txt when prompted:
sqlplus system@//localhost:1521/ORCLPDB
The connection string localhost:1521/ORCLPDB is equivalent to the following TNS descriptor, which you would use from an application that reads a tnsnames.ora file, and to the JDBC URL below it:
ORCLPDB =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ORCLPDB)
)
)
jdbc:oracle:thin:@//localhost:1521/ORCLPDB
To perform CDB level administration instead, use the ORCL service in the same way. Day to day application traffic should always target ORCLPDB.
Or use SQL Developer
Oracle SQL Developer is a free graphical client published by Oracle. With the SSH tunnel running, create a new connection in SQL Developer with the values below:
| Setting | Value |
|---|---|
| Connection Name | cloudimg-oracle-21c-ee-asm (or any name you choose) |
| Authentication | Default |
| Username | SYSTEM |
| Password | Value of SYSTEM_PASSWORD from /root/oracle-db-credentials.txt |
| Connection Type | Basic |
| Role | default |
| Hostname | localhost (through the SSH tunnel) |
| Port | 1521 |
| Service Name | ORCLPDB |
Click Test, and with the tunnel running the status bar reports Success. Click Connect to open a SQL Worksheet. Set the Service Name to ORCLPDB for application work, or to ORCL for CDB administration.
Opening Port 1521 Deliberately
Only open the listener to the network if a tunnel does not suit your architecture, for example when application servers in the same VPC must connect directly, and only to the networks that need it. Make all three changes, in this order.
1. Require network encryption. As the oracle user, append the following lines to $ORACLE_HOME/network/admin/sqlnet.ora in the database home (the file the database server processes read; it is created if it does not exist), so that every network session is encrypted and integrity checked:
sudo su - oracle
. ~/setEnv.sh
cat >> $ORACLE_HOME/network/admin/sqlnet.ora <<'EOF'
SQLNET.ENCRYPTION_SERVER = required
SQLNET.ENCRYPTION_TYPES_SERVER = (AES256)
SQLNET.CRYPTO_CHECKSUM_SERVER = required
SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER = (SHA256)
EOF
exit
Alternatively, use Transport Layer Security: a TCPS listener endpoint with a wallet, as described in the "Configuring Transport Layer Security Encryption" chapter of the Oracle Database Security Guide at https://docs.oracle.com/en/database/oracle/oracle-database/21/dbseg/.
2. Bind the listener to all interfaces. As the grid user, edit $GRID_HOME/network/admin/listener.ora (/u01/app/21.0.0/grid/network/admin/listener.ora), change (HOST = 127.0.0.1) to (HOST = 0.0.0.0) on the TCP address line, then restart the listener:
sudo su - grid
. ~/setEnv.sh
sed -i 's/(HOST = 127.0.0.1)/(HOST = 0.0.0.0)/' /u01/app/21.0.0/grid/network/admin/listener.ora
srvctl stop listener
srvctl start listener
exit
3. Allow port 1521 from your own network only. From your workstation, add an inbound rule to the instance's security group for your management or application CIDR:
aws ec2 authorize-security-group-ingress \
--group-id <security-group-id> \
--protocol tcp --port 1521 \
--cidr <your-mgmt-cidr>
Never use 0.0.0.0/0 for port 1521. Clients then connect to the instance's private or public address on port 1521 with the ORCLPDB service name, and their Oracle client negotiates the required encryption automatically.
Step 10: Manage the Database with Oracle Restart
Because ASM is managed by Grid Infrastructure, the database is not controlled by a systemd unit. Instead, Oracle Restart starts and stops the database, and you manage it with the srvctl utility as the oracle user. Check its registration and current status:
sudo -u oracle bash <<'OUTER'
. ~/setEnv.sh
srvctl status database -d ORCL
srvctl config database -d ORCL
OUTER
The expected response confirms the database is running, that Oracle Restart will start it automatically (Management policy: AUTOMATIC), and that it depends on both disk groups:
Database is running.
Database unique name: ORCL
Database name: ORCL
Oracle home: /u01/app/oracle/product/21.0.0/dbhome_1
Oracle user: oracle
Spfile: +DATA/ORCL/PARAMETERFILE/spfile.270.1234711423
Password file:
Domain:
Start options: open
Stop options: immediate
Database role: PRIMARY
Management policy: AUTOMATIC
Disk Groups: DATA,RECO
Services:
Database instance: ORCL
srvctl manages the container database ORCL. When the CDB opens, the pluggable database ORCLPDB opens with it automatically because its open state is saved (Step 14 verifies this). To stop the database cleanly (the ASM instance and listener stay up):
sudo -u oracle bash -c '. ~/setEnv.sh; srvctl stop database -d ORCL'
To start it again:
sudo -u oracle bash -c '. ~/setEnv.sh; srvctl start database -d ORCL'
To stop or start the entire Grid Infrastructure stack — ASM, listener, and database together — use crsctl as root: crsctl stop has and crsctl start has. The High Availability Services daemon is itself started at boot by the systemd unit oracle-ohasd.service, which is the only Oracle related systemd unit on the image besides the one shot firstboot service.
There is also a one shot unit oracle-db-21c-firstboot.service whose only job is to set the per instance passwords on the very first boot and then enable the loopback listener. It is gated on its sentinel file /var/lib/cloudimg/oracle-db-21c-firstboot.done and exits immediately on every subsequent boot.
Give the Database More Memory
The starter database is sized for the recommended m5.large (8 GiB): a total memory target of 3072 MB, about 2.3 GiB of sga_target and about 768 MiB of pga_aggregate_target, leaving room for the ASM instance (about 1 GiB), the Oracle Restart daemons (about 1 GiB) and the operating system. After you move to m5.xlarge (16 GiB) or larger (stop the instance, change its instance type, start it again), raise the targets as SYSDBA and restart the database through Oracle Restart. The values below suit an m5.xlarge; scale them to your instance size:
sudo su - oracle
. ~/setEnv.sh
sqlplus / as sysdba
ALTER SYSTEM SET sga_max_size=8G SCOPE=SPFILE;
ALTER SYSTEM SET sga_target=8G SCOPE=SPFILE;
ALTER SYSTEM SET pga_aggregate_target=2G SCOPE=BOTH;
EXIT;
srvctl stop database -db ORCL
srvctl start database -db ORCL
The SGA settings take effect when the database restarts; the PGA target changes immediately. After resizing, the self test's memory check reports the new values against the m5.large starter sizing, which is expected.
Step 11: Storage Layout
The binaries live on the ext4 /u01 volume; the database data lives on the ASM disk groups. Confirm the binaries volume:
df -h /u01
Returns the dedicated 50 GiB gp3 volume that holds both Oracle homes and the inventory:
Filesystem Size Used Avail Use% Mounted on
/dev/nvme1n1 49G 19G 31G 38% /u01
The main directories on /u01:
/u01/app/21.0.0/grid— the Grid Infrastructure (Oracle Restart / ASM) home, owned by thegriduser/u01/app/oracle/product/21.0.0/dbhome_1— the Oracle Database 21c home, owned by theoracleuser/u01/app/oracle— the databaseORACLE_BASEwith the diagnostic repository under/u01/app/oracle/diag/u01/app/oraInventory— the Oracle Universal Installer inventory/root/oracle-db-credentials.txt— per instance passwords, mode 0600 root only
The datafiles themselves are not on /u01 — they are inside ASM. Confirm where each file lives by querying the data dictionary as SYSDBA. Run this from the CDB root so you see the datafiles for every container at once:
sudo -u oracle bash <<'OUTER'
. ~/setEnv.sh
sqlplus -S / as sysdba <<'SQL'
SET PAGESIZE 100 LINESIZE 200
COLUMN name FORMAT A80
COLUMN member FORMAT A80
SELECT name FROM v$datafile ORDER BY file#;
SELECT name FROM v$controlfile;
SELECT member FROM v$logfile ORDER BY group#, member;
EXIT;
SQL
OUTER
Every datafile is on +DATA, the control file is multiplexed across +DATA and +RECO, and each online redo log group has one member on +DATA and one on +RECO — so the loss of a single disk group does not lose both copies of the control file or the redo. In a 21c multitenant database the datafiles are grouped by container: the files directly under +DATA/ORCL/DATAFILE/ belong to the CDB root, and each pluggable database (the PDB$SEED template and your ORCLPDB) gets its own GUID named subdirectory:
NAME
--------------------------------------------------------------------------------
+DATA/ORCL/DATAFILE/system.257.1234711125
+DATA/ORCL/DATAFILE/sysaux.258.1234711171
+DATA/ORCL/DATAFILE/undotbs1.259.1234711195
+DATA/ORCL/C8209F27C6B26005E053362EE80AE60E/DATAFILE/system.266.1234711223
+DATA/ORCL/C8209F27C6B26005E053362EE80AE60E/DATAFILE/sysaux.267.1234711223
+DATA/ORCL/DATAFILE/users.260.1234711197
+DATA/ORCL/C8209F27C6B26005E053362EE80AE60E/DATAFILE/undotbs1.268.1234711223
+DATA/ORCL/53230A5D054484F0E06312521FAC83D9/DATAFILE/system.272.1234711529
+DATA/ORCL/53230A5D054484F0E06312521FAC83D9/DATAFILE/sysaux.273.1234711529
+DATA/ORCL/53230A5D054484F0E06312521FAC83D9/DATAFILE/undotbs1.271.1234711529
+DATA/ORCL/53230A5D054484F0E06312521FAC83D9/DATAFILE/users.275.1234711551
11 rows selected.
NAME
--------------------------------------------------------------------------------
+DATA/ORCL/CONTROLFILE/current.261.1234711205
+RECO/ORCL/CONTROLFILE/current.256.1234711205
MEMBER
--------------------------------------------------------------------------------
+DATA/ORCL/ONLINELOG/group_1.262.1234711207
+RECO/ORCL/ONLINELOG/group_1.257.1234711211
+DATA/ORCL/ONLINELOG/group_2.263.1234711207
+RECO/ORCL/ONLINELOG/group_2.259.1234711211
+DATA/ORCL/ONLINELOG/group_3.264.1234711207
+RECO/ORCL/ONLINELOG/group_3.258.1234711211
6 rows selected.
You can browse the same files from the ASM side with asmcmd as the grid user:
sudo -u grid bash <<'OUTER'
. ~/setEnv.sh
echo "--- +DATA/ORCL/DATAFILE/ (CDB root) ---"
asmcmd ls +DATA/ORCL/DATAFILE/
echo "--- +DATA/ORCL/ (containers + structure) ---"
asmcmd ls +DATA/ORCL/
OUTER
The CDB root datafiles appear directly under DATAFILE/, and the container GUID directories (one per pluggable database) sit alongside the CONTROLFILE, ONLINELOG, PARAMETERFILE and TEMPFILE directories:
--- +DATA/ORCL/DATAFILE/ (CDB root) ---
SYSAUX.258.1234711171
SYSTEM.257.1234711125
UNDOTBS1.259.1234711195
USERS.260.1234711197
--- +DATA/ORCL/ (containers + structure) ---
5322F931C6987D1BE06312521FACA5A9/
53230A5D054484F0E06312521FAC83D9/
C8209F27C6B26005E053362EE80AE60E/
CONTROLFILE/
DATAFILE/
ONLINELOG/
PARAMETERFILE/
TEMPFILE/
Step 12: Enterprise Edition Options
Enterprise Edition unlocks the full Oracle option catalogue. The licensable options shipped with this image are:
| Option | Status | Purpose |
|---|---|---|
| Partitioning | enabled | Range, list, hash, and composite partitioning on tables and indexes |
| Advanced Compression | enabled | Compress tablespaces, LOBs, backups, and Data Pump exports |
| Advanced Security | enabled | Transparent Data Encryption, Network Encryption, Data Redaction |
| Diagnostics Pack | enabled | AWR snapshots, ASH reports, SQL Monitor, Real Time SQL Monitoring |
| Tuning Pack | enabled | SQL Tuning Advisor, SQL Access Advisor, SQL Profiles |
| Data Guard | enabled | Active Standby, Far Sync, role transitions |
| Database Vault | available | Realms, command rules, factor based access control |
| Label Security | available | Row level labels and mediation policies |
| Real Application Testing | available | Database Replay, SQL Performance Analyzer |
| Spatial | available | SDO_GEOMETRY, network and property graph |
| OLAP | available | Multidimensional analytic workspaces |
Confirm that Enterprise Edition options are visible in the running database by querying V$OPTION:
sudo -u oracle bash <<'OUTER'
. ~/setEnv.sh
sqlplus -S / as sysdba <<'SQL'
SET PAGESIZE 100 LINESIZE 200
COLUMN parameter FORMAT A40
SELECT parameter, value FROM v$option
WHERE parameter IN ('Partitioning','Advanced Compression','Advanced replication','Real Application Clusters','Data Mining')
ORDER BY parameter;
EXIT;
SQL
OUTER
Returns:
PARAMETER VALUE
---------------------------------------- ----------------------------------------
Advanced Compression TRUE
Advanced replication TRUE
Data Mining TRUE
Partitioning TRUE
Real Application Clusters FALSE
TRUE means the option is linked into the running binary and licensed under Enterprise Edition. Real Application Clusters reports FALSE because this is a single instance Oracle Restart configuration — ASM and Oracle Restart give you the production storage stack without the multi node RAC option, which is the right shape for a single EC2 instance. Note that licensing of paid options (Advanced Compression, Diagnostics + Tuning Packs, Advanced Security, Partitioning) is separate from technical availability in the binary, and you must hold appropriate Oracle licensing before using a chargeable option in production.
Step 13: Use Partitioning
Partitioning is an Enterprise Edition option. Create a range partitioned table in the pluggable database, insert rows that land in different partitions, and count the rows in each:
SYSPWD=$(sudo awk -F'= *' '/^SYSTEM_PASSWORD=/{print $2}' /root/oracle-db-credentials.txt | head -1)
sudo -u oracle env SYSPWD="$SYSPWD" bash <<'OUTER'
. ~/setEnv.sh
sqlplus -S system/"$SYSPWD"@localhost:1521/ORCLPDB <<'SQL'
SET PAGESIZE 100 LINESIZE 200
CREATE TABLE sales_by_year (id NUMBER, region VARCHAR2(20), amount NUMBER, sale_date DATE)
PARTITION BY RANGE (sale_date) (
PARTITION p2024 VALUES LESS THAN (TO_DATE('2025-01-01','YYYY-MM-DD')),
PARTITION p2025 VALUES LESS THAN (TO_DATE('2026-01-01','YYYY-MM-DD')),
PARTITION p2026 VALUES LESS THAN (MAXVALUE)
);
INSERT INTO sales_by_year VALUES (1,'EU',100,TO_DATE('2024-06-01','YYYY-MM-DD'));
INSERT INTO sales_by_year VALUES (2,'NA',200,TO_DATE('2025-06-01','YYYY-MM-DD'));
INSERT INTO sales_by_year VALUES (3,'AP',300,TO_DATE('2026-06-01','YYYY-MM-DD'));
COMMIT;
SELECT 'p2024' AS partition_name, COUNT(*) AS rows_in_part FROM sales_by_year PARTITION (p2024)
UNION ALL SELECT 'p2025', COUNT(*) FROM sales_by_year PARTITION (p2025)
UNION ALL SELECT 'p2026', COUNT(*) FROM sales_by_year PARTITION (p2026);
DROP TABLE sales_by_year PURGE;
EXIT;
SQL
OUTER
Expected response shows each of the three partitions holding the one row that falls in its date range:
PARTI ROWS_IN_PART
----- ------------
p2024 1
p2025 1
p2026 1
Step 14: Confirm the Release and the Pluggable Database
This image ships Oracle Database 21c at the base 21.3.0.0.0 release. List the interim patches applied to the Oracle home with the OPatch utility:
sudo -u oracle bash <<'OUTER'
. ~/setEnv.sh
$ORACLE_HOME/OPatch/opatch lspatches
OUTER
A base release reports no interim patches:
There are no Interim patches installed in this Oracle Home "/u01/app/oracle/product/21.0.0/dbhome_1".
OPatch succeeded.
The running instance reports its release through V$INSTANCE:
sudo -u oracle bash <<'OUTER'
. ~/setEnv.sh
sqlplus -S / as sysdba <<'SQL'
SET HEADING OFF FEEDBACK OFF PAGESIZE 0
SELECT version_full FROM v$instance;
EXIT;
SQL
OUTER
Returns the base 21c release identifier:
21.3.0.0.0
Oracle publishes quarterly Release Updates for 21c on My Oracle Support; the security section below explains how to apply the latest one for a production deployment. Finally, confirm the multitenant layout — that the pluggable database is open and that its open state is saved, which is what makes it re open automatically every time the CDB restarts:
sudo -u oracle bash <<'OUTER'
. ~/setEnv.sh
sqlplus -S / as sysdba <<'SQL'
SET PAGESIZE 100 LINESIZE 120
COLUMN name FORMAT A12
COLUMN con_name FORMAT A12
COLUMN state FORMAT A8
SELECT con_id, name, open_mode FROM v$pdbs ORDER BY con_id;
SELECT con_name, state FROM dba_pdb_saved_states;
EXIT;
SQL
OUTER
PDB$SEED is the read only template Oracle clones new PDBs from, and ORCLPDB is your application database, open read write. The saved state row confirms ORCLPDB will auto open on restart:
CON_ID NAME OPEN_MODE
---------- ------------ ----------
2 PDB$SEED READ ONLY
3 ORCLPDB READ WRITE
CON_NAME STATE
------------ --------
ORCLPDB OPEN
Step 15: Rotate the SYSTEM and SYS Passwords
For a production deployment, rotate the SYSTEM, SYS and PDBADMIN passwords that the firstboot service generated. SYSTEM and SYS are common users, so connect as SYSDBA with operating system authentication at the CDB root and issue ALTER USER — the change applies across the container and its PDBs. PDBADMIN is local to ORCLPDB, so switch into the pluggable database to rotate it:
sudo -u oracle bash -c '
. ~/setEnv.sh
sqlplus -S / as sysdba <<SQL
ALTER USER SYSTEM IDENTIFIED BY "<new-system-password>";
ALTER USER SYS IDENTIFIED BY "<new-sys-password>";
ALTER SESSION SET CONTAINER = ORCLPDB;
ALTER USER PDBADMIN IDENTIFIED BY "<new-pdbadmin-password>";
EXIT;
SQL'
The ASM SYS and ASMSNMP accounts each have their own password; rotate them as the grid user connecting as sysasm:
sudo -u grid bash -c '
. ~/setEnv.sh
sqlplus -S / as sysasm <<SQL
ALTER USER SYS IDENTIFIED BY "<new-asm-sys-password>";
ALTER USER ASMSNMP IDENTIFIED BY "<new-asmsnmp-password>";
EXIT;
SQL'
Use a different strong password for each account. Store the new values in your secrets manager immediately. The file /root/oracle-db-credentials.txt is the per instance bootstrap record and should not be considered your source of truth after the first rotation.
Step 16: Grow ASM Storage Online
One of the operational advantages of ASM is online storage management: you can add capacity to a disk group without downtime. To grow +DATA, attach a new EBS volume to the instance, apply the same grid:asmadmin ownership the image already applies to its ASM disks, and add it to the disk group. ASM automatically rebalances existing data across the new disk.
# 1. Attach a new gp3 volume to the instance from the AWS console or CLI, e.g. as /dev/sdi.
# 2. On the instance, set ASM ownership on the raw device (replace <device> with the new NVMe name):
sudo chown grid:asmadmin /dev/<device>
sudo chmod 0660 /dev/<device>
# 3. Add it to +DATA as the grid user:
sudo -u grid bash -c '. ~/setEnv.sh; asmcmd lsdg'
sudo -u grid bash -c '. ~/setEnv.sh; sqlplus -S / as sysasm <<SQL
ALTER DISKGROUP DATA ADD DISK "/dev/<device>";
SQL'
ASM begins a rebalance as soon as the disk is added; monitor it with asmcmd lsop. To make the new ownership survive reboots, add the device to the image's udev rule. For most workloads it is simpler to grow the existing EBS volume in place from the AWS console and then run ALTER DISKGROUP DATA RESIZE ALL; so ASM picks up the larger device.
Step 17: Server Components
| Component | Version | Source |
|---|---|---|
| Oracle Grid Infrastructure (Oracle Restart + ASM) | 21c (21.3.0.0.0 base release) | Oracle 21.3.0.0.0 GI media |
| Oracle Database | 21c Innovation Release, Enterprise Edition (21.3.0.0.0 base release) | Oracle 21.3.0.0.0 DB media |
| Oracle Linux | 8 | cloudimg golden base image |
| SQL*Plus / asmcmd | 21c | bundled in the Oracle homes |
| Oracle Restart daemon | oracle-ohasd.service |
baked into the image |
| Firstboot unit | oracle-db-21c-firstboot.service |
baked into the image |
Step 18: Backup Recommendations
The key difference from a filesystem based image is that the datafiles are inside ASM, so a single filesystem snapshot of /u01 does not capture your data — /u01 holds only the binaries. Use one of the following:
- Oracle Recovery Manager (RMAN) is the recommended approach, because it understands ASM and the multitenant architecture natively. Put the database in archivelog mode and back up to the
+RECOdisk group or to an external destination. RMAN can back up the whole container database in one command, or an individual pluggable database withBACKUP PLUGGABLE DATABASE ORCLPDB;. It integrates with the Fast Recovery Area already configured on+RECOand supports incremental backups. - Crash consistent EBS snapshots require snapshotting the
+DATAand+RECOvolumes together and at the same moment, because the control file and redo are split across both. The safest way to get a consistent set is to stop the database first, snapshot all data volumes, then start it again:
sudo -u oracle bash -c '. ~/setEnv.sh; srvctl stop database -d ORCL'
# snapshot the +DATA and +RECO EBS volumes (and optionally /u01) here, e.g.:
aws ec2 create-snapshot --volume-id <vol-id-of-+DATA> --description "orcl-data $(date +%F)"
aws ec2 create-snapshot --volume-id <vol-id-of-+RECO> --description "orcl-reco $(date +%F)"
sudo -u oracle bash -c '. ~/setEnv.sh; srvctl start database -d ORCL'
For production, prefer RMAN with archivelog mode so you can take hot backups without stopping the database.
Step 19: Security Recommendations
Oracle Database 21c is an Innovation Release. Apply the following recommendations on a production deployment:
- Keep port 1521 closed in the EC2 security group and reach the database through an SSH tunnel (Step 9). If application servers must connect directly, follow Opening Port 1521 Deliberately in Step 9: network encryption first, then the listener binding, then a security group rule for your own network only. Never open the listener to the public internet.
- Rotate the SYSTEM, SYS, PDBADMIN, ASM SYS and ASMSNMP passwords using the rotation step above, and store the new values in your secrets manager.
- Leave the locked accounts locked. Unlock only an account you actually need, with a new strong password (Step 3).
- Create per-application schema users inside
ORCLPDBwith only the grants the application needs, instead of usingSYSTEMfor application traffic. Keep application objects in the pluggable database, not the CDB root. - Enable Transparent Data Encryption (TDE) on application tablespaces. TDE is bundled with Enterprise Edition's Advanced Security option and is the recommended path for data at rest encryption; it composes cleanly with ASM and with the multitenant keystore model.
- Apply the latest Oracle Database Release Update for 21c, by downloading the RU bundle from My Oracle Support and applying it with OPatch and datapatch to both the Grid and Database homes. Oracle publishes a new RU on a quarterly cadence; this image ships at the 21.3.0.0.0 base release.
- Enable Oracle Unified Auditing if your compliance regime requires it.
- Require network encryption (native network encryption or TLS) before any client traffic leaves the instance other than through the SSH tunnel; Step 9 shows the
sqlnet.orasettings. - Apply OS security patches by running
sudo dnf update -yon a regular maintenance schedule. Reboot the instance after a kernel update — Oracle Restart re mounts the ASM disk groups, reopens the database, and re opens theORCLPDBpluggable database automatically on the way back up. - Take regular RMAN backups (or consistent EBS snapshots of both ASM volumes) and store them in a separate account or Region.
- Limit SSH access to a small management CIDR; do not leave port 22 open to the whole internet in production.
Instances Launched from Earlier Images
Instances launched from images released before October 2026 ran the Grid Infrastructure listener on all interfaces (0.0.0.0:1521) with ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER=ON in listener.ora, and the security group created by default with those images opened port 1521 to the internet. On 21c images the PDBADMIN account also kept its build time password, and ASMSNMP shared the ASM SYS password. If you run such an instance, make these changes. You can recognise one by running sudo ss -Hltn 'sport = :1521' on it: a local address of 0.0.0.0:1521 or *:1521 means it needs them.
Remove the world open rule from the security group, from your workstation:
aws ec2 revoke-security-group-ingress \
--group-id <security-group-id> \
--protocol tcp --port 1521 \
--cidr 0.0.0.0/0
As the grid user, set the listener address in /u01/app/21.0.0/grid/network/admin/listener.ora back to (HOST = 127.0.0.1), delete the ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER=ON line, and restart the listener:
sudo su - grid
. ~/setEnv.sh
cp /u01/app/21.0.0/grid/network/admin/listener.ora /u01/app/21.0.0/grid/network/admin/listener.ora.bak
sed -i -E -e 's/\(HOST *= *0\.0\.0\.0\)/(HOST = 127.0.0.1)/' \
-e '/ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER/d' /u01/app/21.0.0/grid/network/admin/listener.ora
srvctl stop listener
srvctl start listener
exit
Make sure the database registers with the listener on the loopback address, as SYSDBA:
sudo su - oracle
. ~/setEnv.sh
sqlplus / as sysdba
ALTER SYSTEM SET local_listener='(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))' SCOPE=BOTH;
ALTER SYSTEM REGISTER;
EXIT;
exit
Rotate the PDBADMIN password as SYSDBA:
sudo su - oracle
. ~/setEnv.sh
sqlplus / as sysdba
ALTER SESSION SET CONTAINER=ORCLPDB;
ALTER USER PDBADMIN IDENTIFIED BY "<new-strong-password>";
EXIT;
exit
Give ASMSNMP its own password, as the grid user:
sudo su - grid
. ~/setEnv.sh
sqlplus / as sysasm
ALTER USER ASMSNMP IDENTIFIED BY "<new-strong-password>";
EXIT;
exit
Use a different strong password for each account and store them in your secrets manager. Because the listener was reachable from the internet, also consider rotating SYS and SYSTEM (Step 15) and reviewing the listener log for connections you do not recognise. Then reach the database through an SSH tunnel as described in Step 9, or open it deliberately as described there. If the credentials file on such an instance puts a space after the =, the awk extraction used throughout this guide still reads it.
Screenshots
The following screenshots are taken from a running Oracle Database 21c EE with ASM instance launched from this image.



Support
cloudimg provides 24/7/365 expert technical support for this image. Guaranteed response within 24 hours, one hour average for critical issues. Contact support@cloudimg.co.uk.
For general Oracle Database and ASM questions, performance tuning, and migration help, consult the official Oracle Database 21c documentation set at https://docs.oracle.com/en/database/oracle/oracle-database/21/index.html and the Oracle Automatic Storage Management Administrator's Guide.
Oracle, Oracle Database, Oracle ASM, and related marks are trademarks or registered trademarks of Oracle Corporation. Use of them does not imply any affiliation with or endorsement by Oracle Corporation.