Od
Databases AWS

Oracle Database Client 19c on AWS User Guide

| Product: Oracle Database Client 19c on Oracle Linux 8 on AWS

Overview

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

Oracle Database Client 19c is the client side of Oracle's Long Term Release. It gives an EC2 instance the tools and libraries to connect to Oracle databases that run somewhere else: on Amazon RDS for Oracle, on another EC2 instance, on premises over a VPN or AWS Direct Connect, or in Oracle Cloud. The image is the Administrator install type, which includes:

  • SQL*Plus, SQL*Loader (sqlldr), tnsping, the Data Pump clients (expdp, impdp), the original export and import clients (exp, imp), adrci, orapki and mkstore
  • The OCI client library (libclntsh.so), the JDBC drivers (ojdbc8.jar) and the ODBC driver (libsqora.so.19.1) for your own applications
  • Oracle Net, configured through sqlnet.ora and tnsnames.ora

Base release only. The client is installed from Oracle's 19c base release media, version 19.3.0.0.0, with no Oracle patch applied. cloudimg checks the media against the SHA-256 checksum Oracle publishes before installing it. Oracle patches for the client are support content that Oracle provides to customers with an Oracle support contract, so you apply them yourself (step 10). The Oracle Linux 8 packages are fully patched when the image is built.

Bring your own licence. This image includes no Oracle licence. The Oracle Database Client is used under Oracle's license terms for it, and you need your own Oracle Database licence for every database you connect to.

The cloudimg image adds:

  • A verified Oracle home. When the image is built, cloudimg records the SHA-256 checksum of every file in the Oracle home's bin and lib directories. On the first boot of your instance, cloudimg-oracle-client-firstboot.service checks every file against that record and checks that SQL*Plus is release 19.3.0.0.0. If anything differs the unit fails, so the instance reports a degraded boot, and /root/oracle-client-FIRSTBOOT-FAILED.txt explains why.
  • The environment set for you. Every login shell gets ORACLE_HOME, TNS_ADMIN, PATH, LD_LIBRARY_PATH and NLS_LANG from /etc/profile.d/oracle-client.sh, and sqlplus, sqlldr and tnsping also work from scripts and cron through small wrappers in /usr/local/bin. The Oracle library directory is never added to the system library path, so an Oracle library can never replace a system one.
  • No listening service but SSH. The image runs no Oracle listener and no other network service: only SSH listens on port 22. The client only makes outbound connections to your databases.
  • Hardened Oracle Linux 8. Key-only SSH, SELinux enforcing, the host firewall allowing SSH only, no password on any account, the IMDSv2-only instance metadata service, and daily automatic Oracle Linux security updates.
  • No shared identity. Each instance generates its own SSH host keys and machine identity on first boot, and no build credential, log or key is left in the image. The client needs no secret of its own, so the image creates none; Oracle wallets are yours to create (step 7).

This is a headless image with no web interface; you work over SSH.

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.
  • A security group that allows TCP 22 (SSH) from your own networks only. No other inbound port is needed.
  • Outbound network access from the instance to each database's listener port (usually TCP 1521), through the security groups, network ACLs and routes between them.
  • The host name or address, port and service name of each database you want to reach, and a database account.
  • Your own Oracle Database licence for the databases you connect to.

Instance type: m5.large (2 vCPU, 8 GiB) suits interactive SQL*Plus work and most batch loads; choose a larger type for heavy SQL*Loader or Data Pump work.

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 Client 19c on Oracle Linux 8. Choose your Region, an instance type (m5.large is recommended), your key pair and a security group that opens port 22 from your own networks only, then launch.

The instance is ready about two minutes after launch.

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:

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 \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=oracle-client-19c}]'

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 Check First Boot

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

Check that the first boot verification has run:

systemctl status cloudimg-oracle-client-firstboot.service --no-pager | head -5
sudo cat /var/log/cloudimg/oracle-client-firstboot.log

The unit is active (exited) with status=0/SUCCESS, and the log records how many files of the Oracle home were checked:

● cloudimg-oracle-client-firstboot.service - cloudimg: verify the Oracle Database Client home on first boot
   Loaded: loaded (/etc/systemd/system/cloudimg-oracle-client-firstboot.service; enabled; vendor preset: disabled)
   Active: active (exited) since Wed 2026-10-21 03:13:11 EDT; 2min 7s ago
  Process: 5673 ExecStart=/usr/local/sbin/cloudimg-oracle-client-firstboot (code=exited, status=0/SUCCESS)
 Main PID: 5673 (code=exited, status=0/SUCCESS)
2026-10-21T07:13:08Z first boot verification started
2026-10-21T07:13:11Z verified 480 files of the Oracle home; SQL*Plus 19.3.0.0.0

If the unit failed, read /root/oracle-client-FIRSTBOOT-FAILED.txt and contact support.

Step 4: Confirm the Client Release and Tools

Your login shell already has the Oracle environment. The blocks in this guide also source /etc/profile.d/oracle-client.sh first, so they work the same in a non-login shell:

. /etc/profile.d/oracle-client.sh
echo "ORACLE_HOME=$ORACLE_HOME"
echo "TNS_ADMIN=$TNS_ADMIN"
sqlplus -V
ls "$ORACLE_HOME/bin" | grep -xE 'sqlplus|sqlldr|tnsping|exp|imp|expdp|impdp|adrci|orapki|mkstore' | tr '\n' ' '; echo
ORACLE_HOME=/u01/app/oracle/product/19.3.0/client_1
TNS_ADMIN=/u01/app/oracle/product/19.3.0/client_1/network/admin

SQL*Plus: Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

adrci exp expdp imp impdp mkstore orapki sqlldr sqlplus tnsping

Oracle names every 19c release "Release 19.0.0.0.0"; the Version line is the exact release, here the 19.3.0.0.0 base release.

Path Purpose
/u01/app/oracle/product/19.3.0/client_1 ORACLE_HOME
/u01/app/oracle ORACLE_BASE
$ORACLE_HOME/network/admin TNS_ADMIN: sqlnet.ora and tnsnames.ora
$ORACLE_HOME/jdbc/lib/ojdbc8.jar JDBC Thin driver (Java 8 and later)
$ORACLE_HOME/lib/libclntsh.so OCI client library (C, C++, Python python-oracledb thick mode, Perl, PHP OCI8)
$ORACLE_HOME/lib/libsqora.so.19.1 ODBC driver
/u01/app/oraInventory Oracle central inventory
/usr/share/doc/cloudimg/oracle-client-19c/README.txt A summary of this image

Step 5: Run the Self-Test

The image carries a self-test that repeats the first boot checks and proves the client works end to end without a database: Oracle Net name resolution, a connection attempt that reaches the network layer, the exact listening ports, SELinux and every SSH setting:

sudo /usr/local/sbin/cloudimg-oracle-client-selftest
PASS: first-boot verification marker present
PASS: no first-boot failure note
PASS: Oracle home matches the build manifest (480 files)
PASS: login shell: sqlplus -V = 19.3.0.0.0
PASS: wrapper (non-login): sqlplus -V = 19.3.0.0.0
PASS: tnsping: unknown alias refused (TNS-03505)
PASS: sqlplus: no listener on this instance (ORA-12541)
PASS: only TCP 22 listens
PASS: no Oracle listener process
PASS: SELinux enforcing
PASS: sshd -T passwordauthentication no
PASS: sshd -T permitrootlogin no
PASS: sshd -T pubkeyauthentication yes
PASS: sshd -T x11forwarding no
PASS: sshd -T kbdinteractiveauthentication no
PASS: sshd -T challengeresponseauthentication no
PASS: sshd -T permitemptypasswords no
PASS: sshd -T allowtcpforwarding yes
PASS: sshd -T maxauthtries 4
PASS: sshd -T clientaliveinterval 300
PASS: sshd -T clientalivecountmax 3
PASS: sshd -T logingracetime 60
PASS: no core dump or crash report
ORACLE_CLIENT_SELFTEST_OK

TNS-03505 and ORA-12541 are the expected answers here: the self-test asks for an alias that does not exist and connects to port 1521 on the instance itself, where no listener runs.

Step 6: Add Your Databases to tnsnames.ora

sqlnet.ora resolves names through tnsnames.ora first and then EZCONNECT (host:port/service), so you can connect without any configuration, or give each database a short alias. Look at the shipped files:

. /etc/profile.d/oracle-client.sh
grep -v '^#' "$TNS_ADMIN/sqlnet.ora"
cat "$TNS_ADMIN/tnsnames.ora"
NAMES.DIRECTORY_PATH = (TNSNAMES, EZCONNECT)
SQLNET.EXPIRE_TIME = 10
SQLNET.OUTBOUND_CONNECT_TIMEOUT = 60
# cloudimg Oracle Database Client 19c - Oracle Net service names.
# Add one entry per database, for example:
#
# MYDB =
#   (DESCRIPTION =
#     (ADDRESS = (PROTOCOL = TCP)(HOST = db.example.com)(PORT = 1521))
#     (CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = ORCLPDB1))
#   )

The files belong to the oracle software owner, so edit them with sudo. To add an alias, append an entry with your database's host, port and service name:

sudo tee -a /u01/app/oracle/product/19.3.0/client_1/network/admin/tnsnames.ora > /dev/null <<'TNS'

MYDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = <db-host>)(PORT = 1521))
    (CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = <service-name>))
  )
TNS
tnsping MYDB

tnsping resolves the alias and contacts the database listener; it ends with OK (<n> msec) when the listener answers. If it reports TNS-12535 or times out, the network path to the database (security groups, network ACLs, routes) does not allow the connection. To keep your own tnsnames.ora elsewhere, set TNS_ADMIN to that directory in your shell profile.

Step 7: Connect with SQL*Plus

Connect with the alias, or directly with EZCONNECT. SQL*Plus prompts for the password, which keeps it out of your shell history and the process list:

sqlplus <db-user>@MYDB
sqlplus <db-user>@//<db-host>:1521/<service-name>

For Amazon RDS for Oracle, <db-host> is the DB instance endpoint shown in the RDS console and <service-name> is the database name (ORCL by default). Once connected:

SELECT banner_full FROM v$version;
SELECT sys_context('USERENV', 'SERVICE_NAME') FROM dual;

Never put a password on the command line (sqlplus user/password@db): it is visible to every user of the instance in the process list. For unattended scripts, use an Oracle wallet (a secure external password store) instead: create it with mkstore in a directory only your account can read, add WALLET_LOCATION and SQLNET.WALLET_OVERRIDE = TRUE to your own sqlnet.ora, and connect with sqlplus /@MYDB. The image ships no wallet; every wallet you create is your instance's own.

Step 8: Encrypt the Connection to the Database

Oracle Net traffic is not encrypted unless the client and the server agree to encrypt it. sqlnet.ora carries commented settings for both methods:

  • Oracle Native Network Encryption. Uncomment the SQLNET.ENCRYPTION_CLIENT and SQLNET.CRYPTO_CHECKSUM_CLIENT lines (REQUIRED, AES256 and SHA256) to refuse any unencrypted session. The database must accept encryption; Amazon RDS for Oracle enables it with the NATIVE_NETWORK_ENCRYPTION option.
  • TLS (TCPS). Create a wallet holding your database's CA certificate with orapki, point WALLET_LOCATION at it and use (PROTOCOL = TCPS) and the database's TLS port in the alias. Amazon RDS for Oracle provides TLS with its SSL option and publishes its CA certificates.
. /etc/profile.d/oracle-client.sh
grep -n 'ENCRYPTION\|CRYPTO\|WALLET' "$TNS_ADMIN/sqlnet.ora"
9:# SQLNET.ENCRYPTION_CLIENT = REQUIRED
10:# SQLNET.ENCRYPTION_TYPES_CLIENT = (AES256)
11:# SQLNET.CRYPTO_CHECKSUM_CLIENT = REQUIRED
12:# SQLNET.CRYPTO_CHECKSUM_TYPES_CLIENT = (SHA256)
14:# WALLET_LOCATION = (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = /path/to/your/wallet)))

Edit sqlnet.ora with sudo, as in step 6. If the database is only reachable through a bastion, an SSH tunnel also works: ssh -N -L 1521:<db-host>:1521 ec2-user@<bastion> and connect to //localhost:1521/<service-name>.

Step 9: Use the Client from Scripts, Cron and Applications

A login shell has the environment from /etc/profile.d/oracle-client.sh. Scripts and cron jobs do not read it, so sqlplus, sqlldr and tnsping are also installed as wrappers in /usr/local/bin that set the environment for that one command:

cat /usr/local/bin/sqlplus
env -i PATH=/usr/local/bin:/usr/bin:/bin sqlplus -V
#!/bin/bash
# cloudimg Oracle Database Client 19c wrapper: sqlplus from any shell (scripts, cron), environment scoped to this call
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=/u01/app/oracle/product/19.3.0/client_1
export TNS_ADMIN=${TNS_ADMIN:-/u01/app/oracle/product/19.3.0/client_1/network/admin}
export NLS_LANG=${NLS_LANG:-AMERICAN_AMERICA.AL32UTF8}
export LD_LIBRARY_PATH=/u01/app/oracle/product/19.3.0/client_1/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
exec /u01/app/oracle/product/19.3.0/client_1/bin/sqlplus "$@"

SQL*Plus: Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

For other Oracle tools in a script, source the profile first (. /etc/profile.d/oracle-client.sh). Applications use the libraries directly:

  • Java: add $ORACLE_HOME/jdbc/lib/ojdbc8.jar to the classpath and connect with jdbc:oracle:thin:@//<db-host>:1521/<service-name> or jdbc:oracle:thin:@MYDB with -Doracle.net.tns_admin=$TNS_ADMIN.
  • OCI (C, C++, python-oracledb thick mode, PHP OCI8, Perl DBD::Oracle): set ORACLE_HOME and LD_LIBRARY_PATH=$ORACLE_HOME/lib for the application, as the wrappers do, rather than adding the directory to the system library path.
  • ODBC: register $ORACLE_HOME/lib/libsqora.so.19.1 as the driver in your unixODBC odbcinst.ini (install unixODBC with sudo dnf install unixODBC).

Step 10: Patching

This image ships the 19.3.0.0.0 base release. cloudimg does not apply or redistribute Oracle patches: they are available to customers with an Oracle support contract through My Oracle Support. Apply the current client patches with your own Oracle support entitlement before production use:

  • Oracle's Critical Patch Update advisories, which list the security fixes in each quarterly update: https://www.oracle.com/security-alerts/
  • The Oracle Database 19c documentation, including patching and upgrading: https://docs.oracle.com/en/database/oracle/oracle-database/19/

The Oracle home includes Oracle's own Java runtime and Perl ($ORACLE_HOME/jdk and $ORACLE_HOME/perl), which the Oracle installer and tools use; they are updated by Oracle's patches, not by dnf.

The Oracle Linux packages update themselves: dnf-automatic applies Oracle Linux security errata every day. Check it and the pending updates with:

grep -E '^(upgrade_type|apply_updates)' /etc/dnf/automatic.conf
systemctl is-enabled dnf-automatic.timer
upgrade_type = security
apply_updates = yes
enabled

To apply every available update now, run sudo dnf upgrade and reboot if a new kernel was installed.

Step 11: Security Defaults

sudo ss -tlnp
sudo firewall-cmd --list-services
getenforce
sudo sshd -T | grep -E '^(passwordauthentication|permitrootlogin|x11forwarding|pubkeyauthentication) '
State  Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0      128          0.0.0.0:22        0.0.0.0:*    users:(("sshd",pid=966,fd=3))
LISTEN 0      128             [::]:22           [::]:*    users:(("sshd",pid=966,fd=4))
dhcpv6-client ssh
Enforcing
permitrootlogin no
pubkeyauthentication yes
passwordauthentication no
x11forwarding no
  • Only SSH listens. The image never needs an inbound port beyond 22; keep port 1521 closed on this instance.
  • The SSH settings live in /etc/ssh/sshd_config.d/00-cloudimg.conf, which sshd_config reads first. Your EC2 key pair is the only way in; root login and passwords are refused.
  • SELinux is enforcing and the host firewall (firewalld) allows SSH only, alongside your security group.
  • The instance metadata service accepts IMDSv2 requests only (the AMI requires a session token).

Support and licensing

This image is bring your own licence: it includes no Oracle licence. The Oracle Database Client is used under Oracle's license terms, you need your own Oracle Database licence for every database you connect to, and Oracle support for Oracle patches. The AMI price covers cloudimg's hardening, first boot verification 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 Client on AWS

For the client tools, see the Oracle Database 19c documentation at https://docs.oracle.com/en/database/oracle/oracle-database/19/, in particular the SQL*Plus User's Guide, the Database Utilities guide (SQL*Loader and Data Pump) and the Net Services Administrator's Guide.

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