Od
Databases AWS

Oracle Database 21c SE2 on AWS User Guide

| Product: Oracle Database 21c SE2 on Oracle Linux 8 on AWS

Overview

This guide covers launching and using the Oracle Database 21c SE2 on Oracle Linux 8 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg Oracle Database Standard Edition 2 listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.

Oracle Database 21c desupports the traditional non container architecture, so the starter database is a multitenant container database (CDB) named ORCL with one pluggable database (PDB) named ORCLPDB. Applications connect to the ORCLPDB service; the ORCL container root is used for administration. Standard Edition 2 permits up to three pluggable databases without the multitenant option.

Bring Your Own License. No Oracle Database licence is included. You need your own Oracle Database Standard Edition 2 licence for the instance, and Oracle licenses Standard Edition 2 on AWS only on instances of up to 8 vCPUs.

Base release only. Oracle Database is installed from Oracle's 21c base release media, version 21.3.0.0.0, with no Release Update, OJVM patch or other Oracle patch applied. Release Updates are support content that Oracle provides to customers with an Oracle support contract, so you apply them yourself (see step 12). The Oracle Linux 8 packages are fully patched when the image is built.

The cloudimg image adds:

  • No usable password in the image. On the first boot of your instance a one shot service, oracle-db-21c-firstboot.service, runs before the database is reachable. With no listener running, it sets a unique random password on SYS, SYSTEM and PDBADMIN (the administrator of ORCLPDB) and re-keys every other password account, such as DBSNMP and the sample schemas, with a random value and leaves it locked and expired. It then starts the listener on 127.0.0.1 only, proves that each new password works and that the historic and default passwords are refused, and checks that no plaintext password reached the audit trail or the trace files. Only then does it write the passwords to /root/oracle-db-credentials.txt, a file only root can read, followed by the ready marker /var/lib/cloudimg/oracle-db-21c-firstboot.done.
  • Fail closed. oracle-db.service starts the database only after that ready marker exists. If any first boot step fails, the database and the listener are stopped and /root/oracle-db-FIRSTBOOT-FAILED.txt explains why.
  • Listener on localhost. The Oracle listener on port 1521 is bound to 127.0.0.1, and the listing's default security group opens SSH (port 22) only. You connect through an SSH tunnel; opening 1521 is a deliberate step that first requires network encryption (step 9).
  • No instance metadata for the database. The database, its listener and every session they spawn are blocked from the EC2 instance metadata service, so a database feature that fetches a URL (for example UTL_HTTP, once a DBA grants it network access) cannot read the instance role's credentials (step 13).
  • Separate data volume. The Oracle home, the datafiles, the redo logs and the recovery area live on a dedicated 30 GiB EBS volume mounted at /opt/oracle.

This is a headless image. Oracle Database has no web interface here; you administer it over SSH with sqlplus, and connect graphical tools such as Oracle SQL Developer through an SSH tunnel.

Default user: ec2-user · Architecture: x86_64 · Recommended instance type: m5.large

Prerequisites

  • An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route you use for management.
  • A security group that allows TCP 22 (SSH) from your own networks only. Port 1521 does not need to be open.
  • Your own Oracle Database Standard Edition 2 licence (Bring Your Own License).
  • The AWS CLI version 2 if you plan to launch from the command line.

Instance type: m5.large (2 vCPU, 8 GiB) runs the starter database, which is sized for it. For production choose m5.xlarge (4 vCPU) or m5.2xlarge (8 vCPU) and raise the database memory as described in step 11. Oracle licenses Standard Edition 2 on AWS only on instances of up to 8 vCPUs, so larger shapes such as m5.4xlarge are not within the SE2 rules.

Step 1: Launch from AWS Marketplace

Open the listing on AWS Marketplace, choose View purchase options and Subscribe. When the subscription is active choose Launch your software, then in Version pick Oracle Database 21c SE2 on Oracle Linux 8. Choose your Region, an instance type of m5.large or larger (up to 8 vCPUs), your key pair and a security group that opens port 22 from your own networks only, then launch.

First boot sets and then proves the per instance passwords before the database is allowed to start. It finishes a few minutes after the instance passes its status checks.

Step 2: Launch from the AWS CLI

Replace <ami-id> with the AMI ID of this version in your Region, and the other placeholders with your own values. The command requires IMDSv2 and sets a metadata hop limit of 1:

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> \
  --metadata-options HttpTokens=required,HttpEndpoint=enabled,HttpPutResponseHopLimit=1 \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=oracle-db-21c-se2}]'

The /opt/oracle data volume is created from the image automatically. Retrieve the public address once the instance is running:

aws ec2 describe-instances --instance-ids <instance-id> --query "Reservations[].Instances[].PublicIpAddress" --output text

Step 3: Connect over SSH

Version SSH user
Oracle Database 21c SE2 on Oracle Linux 8 ec2-user
ssh -i <your-key.pem> ec2-user@<public-ip>

SSH can become available before first boot has finished. The ready marker exists only after every password has been set and proven:

sudo test -f /var/lib/cloudimg/oracle-db-21c-firstboot.done && echo "first boot complete"

If the command prints nothing, first boot is still running; follow it with sudo journalctl -u oracle-db-21c-firstboot.service -b -f.

Step 4: Retrieve the Generated Credentials

First boot writes the SYS, SYSTEM and PDBADMIN passwords for this instance, with the connection details, to /root/oracle-db-credentials.txt, readable only by root:

sudo cat /root/oracle-db-credentials.txt

The file looks like this, with unique passwords on your instance:

# Oracle Database 21c Standard Edition 2 - per-instance credentials (cloudimg)
# Generated Mon Oct 19 14:12:04 UTC 2026 on i-0123456789abcdef0. Root-only (0600). Unique to this instance.

SYS_PASSWORD=<your generated SYS password>
SYSTEM_PASSWORD=<your generated SYSTEM password>
PDBADMIN_PASSWORD=<your generated PDBADMIN password>

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

Use SYSTEM for application and administrative connections, SYS for SYSDBA operations, and PDBADMIN to administer ORCLPDB. To read one password into a shell variable without printing it:

SYSPWD=$(sudo awk -F'= *' '/^SYSTEM_PASSWORD=/{print $2}' /root/oracle-db-credentials.txt)
test -n "$SYSPWD" && echo "SYSTEM password read (${#SYSPWD} characters)"

Every other account is locked

Only SYS, SYSTEM and PDBADMIN can log in. To use another account, set your own password and unlock it as SYSDBA, in the container that owns the account:

ALTER USER <name> IDENTIFIED BY "<new-strong-password>" ACCOUNT UNLOCK;

If first boot fails

First boot fails closed: it stops the database and the listener, writes no credentials file and leaves a notice. Read the notice and the journal, then reboot once to retry; first boot runs again on every boot until it succeeds:

sudo cat /root/oracle-db-FIRSTBOOT-FAILED.txt
sudo journalctl -u oracle-db-21c-firstboot.service -b
sudo reboot

If it fails again, contact cloudimg support with the journal output.

Run the security self-test

The self-test re-proves the security state of the instance: each password in the credentials file works and the historic and default passwords are refused, every other account is locked, the listener is bound to 127.0.0.1 only, no listener started before the passwords were set, and the database cannot reach the instance metadata service:

sudo /usr/local/sbin/cloudimg-oracle-selftest

Each check prints a PASS line and the run ends with SELFTEST_OK. The self-test checks the instance as delivered: after you rotate a password, open port 1521 or raise the database memory, the matching checks report FAIL by design.

Step 5: Confirm the Database Service and the Listener

oracle-db.service starts the database and the listener on every boot with Oracle's dbstart, and only after first boot has written its ready marker:

systemctl is-enabled oracle-db.service oracle-db-21c-firstboot.service
systemctl is-active oracle-db.service

Both units print enabled, and the database service prints active. The listener binds to the loopback address only:

sudo ss -tlnp | grep ':1521 '

You see one listening socket on 127.0.0.1:1521 owned by tnslsnr, and no other address on port 1521.

Step 6: Confirm the Edition and the Base Release

Connect to the container root with operating system authentication as the oracle user and query the version views:

sudo su - oracle -c 'sqlplus -S -L / as sysdba' <<'SQL'
SET PAGESIZE 50 LINESIZE 120 FEEDBACK OFF
COLUMN banner FORMAT a80
COLUMN version_full FORMAT a12
SELECT banner FROM v$version WHERE banner LIKE 'Oracle%';
SELECT instance_name, version_full, status FROM v$instance;
EXIT;
SQL

The banner reads Oracle Database 21c Standard Edition 2 Release 21.0.0.0.0 - Production, and the instance ORCL reports VERSION_FULL 21.3.0.0.0, the base release, with status OPEN.

Step 7: The Container Database and the Pluggable Database

Your application schemas live in the pluggable database ORCLPDB. Confirm it is open read write:

sudo su - oracle -c 'sqlplus -S -L / as sysdba' <<'SQL'
SET PAGESIZE 50 LINESIZE 120 FEEDBACK OFF
COLUMN name FORMAT a12
COLUMN open_mode FORMAT a12
SELECT name, open_mode FROM v$pdbs WHERE name = 'ORCLPDB';
EXIT;
SQL

ORCLPDB reports READ WRITE. Its state is saved, so it opens whenever the container database starts.

Step 8: Connect with SQL*Plus

Connect to the ORCLPDB service as SYSTEM. Switch to the oracle user, then start SQL*Plus without a password on the command line and enter it at the prompt, so it never appears in the process list or your shell history:

sudo su - oracle
. ~/setEnv.sh
sqlplus /nolog
SQL> CONNECT system@//localhost:1521/ORCLPDB
Enter password: <SYSTEM_PASSWORD>

At the SQL> prompt you can create schemas, tables and data:

CREATE TABLE products (
  id    NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  name  VARCHAR2(100),
  price NUMBER(10,2)
);
INSERT INTO products (name, price) VALUES ('Mechanical Keyboard', 89.00);
COMMIT;
SELECT name, price FROM products;

For the container root use sqlplus / as sysdba as the oracle user, or CONNECT sys@//localhost:1521/ORCL AS SYSDBA with the SYS password. To administer the pluggable database as its own administrator, CONNECT pdbadmin@//localhost:1521/ORCLPDB.

Step 9: Connect Remotely with SQL Developer or JDBC

Through an SSH tunnel (recommended)

The listener is bound to 127.0.0.1 and the security group opens port 22 only. On your workstation, open a tunnel that forwards local port 1521 to the listener and leave it running:

ssh -i <your-key.pem> -N -L 1521:127.0.0.1:1521 ec2-user@<public-ip>

While the tunnel is open, localhost:1521 on your workstation reaches the database:

Host:            localhost (through the SSH tunnel)
Port:            1521
Service name:    ORCLPDB
Username:        SYSTEM
Password:        <your generated SYSTEM password>
JDBC URL:        jdbc:oracle:thin:@//localhost:1521/ORCLPDB

In SQL Developer create a connection of type Basic with these values, then Test and Connect. For the container root use the ORCL service name and connect as SYS with the SYSDBA role.

Opening port 1521 deliberately

If applications must connect directly, open the listener in three steps, and only to your own networks.

1. Require Oracle native network encryption and integrity. As the oracle user, append to $ORACLE_HOME/network/admin/sqlnet.ora:

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

Oracle documents these settings in "Configuring Oracle Database Network Encryption and Data Integrity" (https://docs.oracle.com/en/database/oracle/oracle-database/21/dbseg/configuring-network-data-encryption-and-integrity.html). To use TLS (TCPS) with an Oracle wallet instead, follow the Transport Layer Security chapters of the Oracle Database 21c Security Guide (https://docs.oracle.com/en/database/oracle/oracle-database/21/dbseg/index.html).

2. Bind the listener to all interfaces and restart the database service, which restarts the listener:

sudo sed -i 's/(HOST = 127.0.0.1)/(HOST = 0.0.0.0)/' /opt/oracle/product/21.0.0/dbhome_1/network/admin/listener.ora
sudo systemctl restart oracle-db.service

3. Allow TCP 1521 from your own network only. Never use 0.0.0.0/0:

aws ec2 authorize-security-group-ingress --group-id <security-group-id> --protocol tcp --port 1521 --cidr <your-network-cidr>

Clients then connect to <public-ip>:1521/ORCLPDB (or the private IP inside the VPC) and negotiate encryption automatically; the JDBC thin driver and SQL Developer do so when the server requires it.

Step 10: The Oracle Data Volume

The Oracle home, datafiles, redo logs and recovery area are on a dedicated EBS volume at /opt/oracle:

findmnt /opt/oracle
df -h /opt/oracle

/opt/oracle is its own ext4 filesystem on a separate device, so you can snapshot it on its own schedule and grow it independently of the root volume.

Step 11: Managing the Database Service

Manage the database through systemd. Stopping the service runs Oracle's dbshut to close the database cleanly; starting it runs dbstart:

systemctl status oracle-db.service --no-pager
sudo systemctl stop oracle-db.service
sudo systemctl start oracle-db.service
sudo systemctl restart oracle-db.service

Prefer the service to sqlplus startup or lsnrctl start from a shell: the service applies both metadata walls of step 13 (a database started by hand keeps the nftables wall only) and waits for the first boot ready marker.

Database memory and instance size

The starter database uses 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, sized for an m5.large. On m5.xlarge or larger, raise it as SYSDBA in the container root, for example:

ALTER SYSTEM SET sga_max_size=6G SCOPE=SPFILE;
ALTER SYSTEM SET sga_target=6G SCOPE=SPFILE;
ALTER SYSTEM SET pga_aggregate_target=2G SCOPE=BOTH;

Then sudo systemctl restart oracle-db.service. Leave at least 2 GiB of the instance memory for the operating system.

Logs

The alert log and the listener log are under /opt/oracle/diag:

sudo su - oracle -c 'find /opt/oracle/diag -name alert_ORCL.log'

Step 12: Patching Oracle Database

This image ships the 21.3.0.0.0 base release. cloudimg does not apply or redistribute Oracle Release Updates, OJVM patches or other Oracle patches: they are available to customers with an Oracle support contract through My Oracle Support. Plan to apply the current Release Update before production use, with your own Oracle support entitlement:

  • Oracle's Critical Patch Update advisories, which list the security fixes in each quarterly update: https://www.oracle.com/security-alerts/
  • Patching with AutoUpgrade, which automates downloading and applying Release Updates: https://docs.oracle.com/en/database/oracle/oracle-database/21/upgrd/autoupgrade-patching.html

Take an EBS snapshot of /opt/oracle before you patch. The Oracle Linux packages can be updated at any time with sudo dnf upgrade.

Step 13: Instance Metadata Protection

The database is blocked from the EC2 instance metadata service (169.254.169.254). This stops a database session that can fetch URLs, for example through UTL_HTTP or UTL_TCP after a DBA grants a network access control entry, from reading the credentials of an IAM role attached to the instance. Two independent walls enforce it:

  • A systemd drop-in on oracle-db.service sets IPAddressDeny= for the metadata addresses, so no process of the database service, including the listener and every session it spawns, can connect to them. On Oracle Linux 8 systemd enforces this only with a cgroup2 tree, so the image boots with the kernel argument systemd.legacy_systemd_cgroup_controller=0 (the hybrid hierarchy: every cgroup v1 controller is unchanged).
  • An nftables rule for the oracle user, loaded at boot by cloudimg-oracle-imds-egress.service, rejects the same addresses for any socket the oracle user owns, so a database or listener started by hand from a shell is blocked too. oracle-db.service requires this unit, so the database does not start without it.
cat /etc/systemd/system/oracle-db.service.d/cloudimg-imds-egress.conf
systemctl is-active cloudimg-oracle-imds-egress.service
sudo nft list table inet cloudimg_oracle_imds

The drop-in lists IPAddressDeny=169.254.169.254 168.63.129.16 fd00:ec2::254, the unit is active, and the table holds reject rules for the oracle user's uid (54321) to those addresses. The security self-test in step 4 proves both walls on your instance: it connects to 169.254.169.254 from inside the running oracle-db.service and as the oracle user from a shell, expects both to be refused while a loopback connection from the same place succeeds, and checks that root can still reach the metadata service. Your own administration over SSH, the AWS CLI and the AWS Systems Manager agent are not affected.

Launch instances with IMDSv2 required and a hop limit of 1 (step 2).

Step 14: Backups

Recovery Manager (RMAN) takes consistent online backups. As the oracle user:

sudo su - oracle
. ~/setEnv.sh
rman target / <<'RMAN'
BACKUP DATABASE PLUS ARCHIVELOG;
RMAN

BACKUP ... PLUS ARCHIVELOG needs the database in ARCHIVELOG mode; the starter database runs in NOARCHIVELOG mode, so enable archiving first (see the Oracle Database Backup and Recovery User's Guide) or take a cold backup with the database shut down. For logical, schema level exports use Oracle Data Pump against ORCLPDB, entering the password at the prompt:

expdp system@//localhost:1521/ORCLPDB schemas=APPUSER directory=DATA_PUMP_DIR dumpfile=appuser.dmp

You can also take an EBS snapshot of the /opt/oracle volume; shut the database down cleanly first for a consistent copy.

Support and licensing

This image is Bring Your Own License: you need your own Oracle Database Standard Edition 2 licence, and Oracle support for Release Updates. The AMI price covers cloudimg's hardening, first boot setup and support for the image.

For Oracle Database administration, see the Oracle Database 21c documentation at https://docs.oracle.com/en/database/oracle/oracle-database/21/.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. cloudimg is not affiliated with or endorsed by Oracle.