Oracle Database 19c SE2 on AWS User Guide
Overview
This guide covers launching and using the Oracle Database 19c 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 19c is Oracle's Long Term Release. The starter database is a single non container database named ORCL, and applications connect to the ORCL service.
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 19c base release media, version 19.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 11). The Oracle Linux 8 packages are fully patched when the image is built.
The cloudimg image adds:
- No database and no password in the image. The image ships the Oracle home only. On the first boot of your instance a one shot service,
oracle-db-19c-firstboot.service, creates theORCLdatabase on your instance with Oracle's Database Configuration Assistant (dbca), so every instance has its own database and its own passwords. With no listener running, it then sets a unique random password onSYSandSYSTEMand re-keys every other password account, such asDBSNMP, with a random value and leaves it locked and expired. It then starts the listener on127.0.0.1only, 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-19c-firstboot.done. - Fail closed.
oracle-db.servicestarts 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.txtexplains 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 8). - No instance metadata for the database. The database, its listener and every session they spawn, and the
dbcarun that creates the database at first boot, are blocked from the EC2 instance metadata service, so a database feature that fetches a URL (for exampleUTL_HTTP, once a DBA grants it network access) cannot read the instance role's credentials (step 12). - 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 10. 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 19c 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 creates the database, then sets and proves the per instance passwords before the database is allowed to start. Allow about 15 minutes from launch on an m5.large; creating the database with dbca is most of that time (11 to 13 minutes measured on a 2 vCPU, 8 GiB instance), and larger instance types finish sooner.
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-19c-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 and Watch First Boot
| Version | SSH user |
|---|---|
| Oracle Database 19c SE2 on Oracle Linux 8 | ec2-user |
ssh -i <your-key.pem> ec2-user@<public-ip>
SSH is available before first boot has finished. The ready marker exists only after the database has been created and every password has been set and proven:
sudo test -f /var/lib/cloudimg/oracle-db-19c-firstboot.done && echo "first boot complete"
If the command prints nothing, first boot is still running; follow it with sudo journalctl -u oracle-db-19c-firstboot.service -b -f (the dbca progress lines start with [dbca], ending with 100% complete). Each first boot step is also recorded, with the seconds since boot, in a root only event log:
sudo cat /var/log/cloudimg/oracle-db-firstboot.events
On a completed first boot the steps read, in this order, start, db-create-start, db-created (with the dbca run time), rotated, listener-started 127.0.0.1:1521, verified and ready, for example:
41.76 c5aaa117-0be8-48fb-94e3-13b5e52b5eb2 start
47.97 c5aaa117-0be8-48fb-94e3-13b5e52b5eb2 db-create-start
721.57 c5aaa117-0be8-48fb-94e3-13b5e52b5eb2 db-created 674s
725.16 c5aaa117-0be8-48fb-94e3-13b5e52b5eb2 rotated
726.06 c5aaa117-0be8-48fb-94e3-13b5e52b5eb2 listener-started 127.0.0.1:1521
742.18 c5aaa117-0be8-48fb-94e3-13b5e52b5eb2 verified
801.53 c5aaa117-0be8-48fb-94e3-13b5e52b5eb2 ready
Step 4: Retrieve the Generated Credentials
First boot writes the SYS and SYSTEM 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 19c Standard Edition 2 - per-instance credentials (cloudimg)
# Generated Wed Oct 21 01:11:15 UTC 2026 on i-0123456789abcdef0. Root-only (0600). Unique to this instance.
SYS_PASSWORD=<your generated SYS password>
SYSTEM_PASSWORD=<your generated SYSTEM password>
ORACLE_SID=ORCL
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 (the login profile sets ORACLE_HOME) ; sqlplus /nolog ; then CONNECT system@//localhost:1521/ORCL
Use SYSTEM for application and administrative connections, and SYS for SYSDBA operations. 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 and SYSTEM can log in. To use another account, set your own password and unlock it as SYSDBA:
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:
sudo cat /root/oracle-db-FIRSTBOOT-FAILED.txt
sudo journalctl -u oracle-db-19c-firstboot.service -b
If the event log shows db-create-start without db-created, the database creation itself failed (for example on an instance with too little memory); a partly created database is not repaired by a reboot, so terminate the instance and launch a new one on a supported instance type (m5.large or larger). If the database was created and a later step failed, reboot once to retry; first boot runs again on every boot until it succeeds. 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, the database was created by this instance's own first boot, 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-19c-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 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;
SELECT cdb FROM v$database;
EXIT;
SQL
The banner reads Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production, the instance ORCL reports VERSION_FULL 19.3.0.0.0, the base release, with status OPEN, and CDB is NO: ORCL is a non container database.
Step 7: Connect with SQL*Plus
Connect to the ORCL 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
sqlplus /nolog
SQL> CONNECT system@//localhost:1521/ORCL
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 SYSDBA work use sqlplus / as sysdba as the oracle user, or CONNECT sys@//localhost:1521/ORCL AS SYSDBA with the SYS password.
Step 8: 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: ORCL
Username: SYSTEM
Password: <your generated SYSTEM password>
JDBC URL: jdbc:oracle:thin:@//localhost:1521/ORCL
In SQL Developer create a connection of type Basic with these values, then Test and Connect. For SYSDBA work 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
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/19/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 19c Security Guide (https://docs.oracle.com/en/database/oracle/oracle-database/19/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/19.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/ORCL (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 9: 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 10: 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 12 (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, 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 11: Patching Oracle Database
This image ships the 19.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/19/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 12: 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.servicesetsIPAddressDeny=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 argumentsystemd.legacy_systemd_cgroup_controller=0(the hybrid hierarchy: every cgroup v1 controller is unchanged). - An nftables rule for the
oracleuser, loaded at boot bycloudimg-oracle-imds-egress.service, rejects the same addresses for any socket theoracleuser owns, wherever it runs: thedbcarun that creates the database at first boot, a database or listener started by hand from a shell, and the database service itself.oracle-db.serviceand the first boot service require this unit, so neither starts 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 13: Backups
Recovery Manager (RMAN) takes consistent online backups. As the oracle user:
sudo su - oracle
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, entering the password at the prompt:
expdp system@//localhost:1521/ORCL 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.
Several instances in one RMAN recovery catalog
Oracle derives the database identifier (DBID) of the new ORCL database from its name and the second it is created, so instances launched at the same moment, for example several at once from one launch request, can be given the same DBID. A recovery catalog registers each database by its DBID, so before you register more than one of them in the same catalog, give each its own DBID with Oracle's DBNEWID utility. As the oracle user, with the database mounted and not open:
sudo systemctl stop oracle-db.service
sudo su - oracle
sqlplus / as sysdba <<'SQL'
STARTUP MOUNT
SQL
nid TARGET=/ LOGFILE=/tmp/nid.log
sqlplus / as sysdba <<'SQL'
STARTUP MOUNT
ALTER DATABASE OPEN RESETLOGS;
SHUTDOWN IMMEDIATE
SQL
exit
sudo systemctl start oracle-db.service
nid changes the DBID of the database and leaves it shut down; opening with RESETLOGS starts a new incarnation, so take a fresh full backup afterwards. Run the instances' nid at different times: the new DBID is also derived from the time. Check the result with SELECT dbid FROM v$database;.
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.
- Email: support@cloudimg.co.uk
- Website: https://www.cloudimg.co.uk
- Support: 24/7, with a 24 hour response SLA
- Every version in this listing: Oracle Database Standard Edition 2 on AWS
For Oracle Database administration, see the Oracle Database 19c documentation at https://docs.oracle.com/en/database/oracle/oracle-database/19/.
Oracle and Java are registered trademarks of Oracle and/or its affiliates. cloudimg is not affiliated with or endorsed by Oracle.