Od
Databases AWS

Oracle Database Client 26ai on AWS User Guide

| Product: Oracle Database Client 26ai on Oracle Linux 9 on AWS

Overview

This guide covers launching and using the Oracle Database Client 26ai on Oracle Linux 9 AMI from cloudimg on Amazon EC2. It is the newest 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 26ai is the client of Oracle AI Database 26ai, the current long term support release of Oracle Database (release 23.26, the 23ai family). 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. A 26ai client connects to Oracle AI Database 26ai and to the earlier releases Oracle supports for it (Oracle publishes the client and server interoperability matrix on My Oracle Support). The image is the Administrator install type, which includes:

  • SQL*Plus, SQLcl (sql), SQL*Loader (sqlldr), tnsping, the Data Pump clients (expdp, impdp), the original export and import clients (exp, imp), the Workload Replay client (wrc), adrci, orapki and mkstore
  • The Pro*C/C++ precompiler (proc)
  • The OCI client library (libclntsh.so.23.1), the OCCI C++ library (libocci.so.23.1), the JDBC drivers (ojdbc17.jar, ojdbc11.jar and ojdbc8.jar) and the ODBC driver (libsqora.so.23.1, with the unixODBC driver manager installed) for your own applications
  • Oracle Net, configured through sqlnet.ora and tnsnames.ora

Base release only. The client is installed from Oracle's 26ai base release media, LINUX.X64_2326100_client.zip, release 23.26.1.0.0, with no Oracle patch applied. cloudimg checks the media against the size and SHA-256 checksum Oracle publishes for it before installing it. Oracle Release Updates for the client are support content that Oracle provides to customers with an Oracle support contract, so you apply them yourself (step 11). The Oracle Linux 9 packages are fully patched when the image is built.

Oracle Linux 9. Oracle certifies the 26ai client on Oracle Linux 9 with the Unbreakable Enterprise Kernel 7 (UEK 5.15), which is the kernel this image boots. The installer runs its own prerequisite checks with no check skipped or overridden. cloudimg installs the prerequisite libraries on Oracle's list and sets the Oracle Net kernel parameters Oracle asks for (/etc/sysctl.d/97-oracle-client.conf). Three packages on the same list, which Oracle marks as optional, are deliberately not installed because they bring services a client image does not run: nfs-utils (an RPC listener), smartmontools (a disk monitoring daemon) and sysstat (statistics collection timers). The 26ai client links its programs during installation with the Oracle Linux 9 C and C++ compilers, and that link runs cleanly. The compilers are used for that link only: the build removes gcc, gcc-c++ and make afterwards, so no compiler ships (install them before you relink, step 11).

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 23.26.1.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 database, no credentials, no listening service but SSH. The image carries no database and no password, wallet or credentials file, and 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 9. Key-only SSH, SELinux enforcing, the host firewall allowing SSH only, no password on any account, no compiler, the IMDSv2-only instance metadata service, UTC with the Amazon Time Sync Service as the preferred clock source, 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 8).

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, or 2484 for TLS), 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 and SQLcl 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 26ai on Oracle Linux 9. 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-26ai}]'

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 26ai on Oracle Linux 9 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; preset: disabled)
     Active: active (exited) since Thu 2026-10-22 04:47:48 UTC; 40s ago
    Process: 14613 ExecStart=/usr/local/sbin/cloudimg-oracle-client-firstboot (code=exited, status=0/SUCCESS)
   Main PID: 14613 (code=exited, status=0/SUCCESS)
2026-10-22T04:47:46Z first boot verification started
2026-10-22T04:47:48Z verified 382 files of the Oracle home; SQL*Plus 23.26.1.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|sql|sqlldr|tnsping|exp|imp|expdp|impdp|adrci|orapki|mkstore|proc|wrc' | tr '\n' ' '; echo
ORACLE_HOME=/u01/app/oracle/product/23.0.0/client_1
TNS_ADMIN=/u01/app/oracle/product/23.0.0/client_1/network/admin

SQL*Plus: Release 23.26.1.0.0 - Production
Version 23.26.1.0.0

adrci exp expdp imp impdp mkstore orapki proc sql sqlldr sqlplus tnsping wrc

The release line is the exact release: 23.26.1.0.0 is the 26ai base release on Oracle's installation media, with no Oracle patch applied. The Oracle home sits in Oracle's 23.0.0 version directory, so the path stays the same after you apply Release Updates.

SQLcl, Oracle's modern command line for SQL and PL/SQL (command history, tab completion, DDL and INFO commands, CSV and JSON output, Liquibase), is sql and runs on the Java runtime inside the Oracle home:

. /etc/profile.d/oracle-client.sh
sql -V
SQLcl: Release 25.4.0.0 Production Build: 25.4.0.344.0019

SQLcl keeps its command history in ~/.dbtools of the user who runs it.

Path Purpose
/u01/app/oracle/product/23.0.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/ojdbc17.jar JDBC driver for Java 17 and later (ojdbc11.jar for Java 11, ojdbc8.jar for Java 8)
$ORACLE_HOME/lib/libclntsh.so.23.1 OCI client library (C, C++, Python python-oracledb thick mode, Node.js node-oracledb thick mode, Perl, PHP OCI8)
$ORACLE_HOME/lib/libocci.so.23.1 OCCI C++ client library
$ORACLE_HOME/lib/libsqora.so.23.1 ODBC driver
/u01/app/oraInventory Oracle central inventory
/usr/share/doc/cloudimg/oracle-client-26ai/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, the firewall, the accounts, the absence of a compiler 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 (382 files)
PASS: login shell: sqlplus -V = 23.26.1.0.0
PASS: wrapper (empty environment): sqlplus -V = 23.26.1.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: firewalld public: dhcpv6-client ssh
PASS: no account carries a password hash (locked or not)
PASS: no compiler (gcc, cc, c++, g++, make) on the PATH
PASS: sshd -T PasswordAuthentication no
PASS: sshd -T KbdInteractiveAuthentication no
PASS: sshd -T PermitEmptyPasswords no
PASS: sshd -T PermitRootLogin no
PASS: sshd -T PubkeyAuthentication yes
PASS: sshd -T X11Forwarding 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 26ai - 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 = FREEPDB1))
#   )

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/23.0.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 or SQLcl

Connect with the alias, or directly with EZCONNECT. SQL*Plus and SQLcl prompt 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>
sql <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). For an Oracle Autonomous Database, download its wallet, unzip it into a directory only your account can read, set TNS_ADMIN to that directory and connect with one of the service names in its tnsnames.ora. 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 (step 8).

Step 8: Encrypt the Connection and Store Credentials Safely

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 (often 2484) 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. A TLS wallet for an RDS CA bundle, created in a directory of your own (the commands prompt for the wallet password):

mkdir -m 700 ~/wallet
orapki wallet create -wallet ~/wallet -auto_login_only
orapki wallet add -wallet ~/wallet -trusted_cert -cert <rds-ca-bundle.pem> -auto_login_only

For unattended scripts, store the database password in a wallet as a secure external password store: create it with mkstore -wrl <wallet-dir> -create in a directory only your account can read, add the credential with mkstore -wrl <wallet-dir> -createCredential MYDB <db-user> (it prompts for the password), add WALLET_LOCATION and SQLNET.WALLET_OVERRIDE = TRUE to the sqlnet.ora your script uses, and connect with sqlplus /@MYDB. The image ships no wallet; every wallet you create is your instance's own.

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 and Cron

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 26ai 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/23.0.0/client_1
export TNS_ADMIN=${TNS_ADMIN:-/u01/app/oracle/product/23.0.0/client_1/network/admin}
export NLS_LANG=${NLS_LANG:-AMERICAN_AMERICA.AL32UTF8}
export LD_LIBRARY_PATH=/u01/app/oracle/product/23.0.0/client_1/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
exec /u01/app/oracle/product/23.0.0/client_1/bin/sqlplus "$@"

SQL*Plus: Release 23.26.1.0.0 - Production
Version 23.26.1.0.0

For other Oracle tools in a script (SQLcl, Data Pump, exp/imp), source the profile first (. /etc/profile.d/oracle-client.sh).

Step 10: Connect Your Applications

Applications use the libraries in the Oracle home directly:

  • Java: add $ORACLE_HOME/jdbc/lib/ojdbc17.jar (Java 17 and later; ojdbc11.jar for Java 11, ojdbc8.jar for Java 8) 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 and OCCI (C, C++, Pro*C, python-oracledb and node-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. With python-oracledb, call oracledb.init_oracle_client(lib_dir="/u01/app/oracle/product/23.0.0/client_1/lib") to use thick mode.
  • ODBC: the unixODBC driver manager is installed. Register the Oracle driver in /etc/odbcinst.ini, for example a section [Oracle 26ai ODBC driver] with Driver = /u01/app/oracle/product/23.0.0/client_1/lib/libsqora.so.23.1, then define your data sources in /etc/odbc.ini or ~/.odbc.ini:
odbcinst -j | head -3
unixODBC 2.3.12
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini

Step 11: Patching

This image ships the 23.26.1.0.0 base release. cloudimg does not apply or redistribute Oracle patches: Release Updates are available to customers with an Oracle support contract through My Oracle Support. Apply the current client Release Update 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/
  • Patching an Oracle home with AutoUpgrade and OPatch, from the Oracle AI Database 26ai documentation: https://docs.oracle.com/en/database/oracle/oracle-database/26/upgrd/autoupgrade-patching.html

Run OPatch as the oracle software owner (OPatch refuses to run as root), for example sudo -iu oracle $ORACLE_HOME/OPatch/opatch lspatches. Oracle's relink, which patches run, needs the C and C++ compilers and make, which the image does not ship. Install them first with sudo dnf install gcc gcc-c++ make (from the Oracle Linux 9 repositories; with them the link and relink all run cleanly on this image), and remove them afterwards if you like with sudo dnf remove gcc gcc-c++ make.

The Oracle home includes Oracle's own Java runtime (Java 11.0.30) and Perl 5.38 ($ORACLE_HOME/jdk and $ORACLE_HOME/perl), which SQLcl, the installer and other Oracle tools use; they are updated by Oracle's patches, not by dnf. Use your own current Java runtime for your applications rather than the Oracle home's.

The Oracle Linux packages update themselves: dnf-automatic applies Oracle Linux security errata every day. Check it 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 12: 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=672,fd=7))
LISTEN 0      128             [::]:22           [::]:*    users:(("sshd",pid=672,fd=8))
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. It carries no database and no credentials file.
  • The SSH settings live in /etc/ssh/sshd_config.d/00-cloudimg.conf, which sshd_config reads first, ahead of the distribution's own drop-ins. 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).
  • The image changes these kernel parameters for Oracle Net, as Oracle's client prerequisites ask (/etc/sysctl.d/97-oracle-client.conf): fs.aio-max-nr = 1048576, net.core.rmem_default = 262144, net.core.rmem_max = 4194304, net.core.wmem_default = 262144 and net.core.wmem_max = 1048576.
  • The fwupd-refresh timer is masked: EC2 instances have no firmware that the Linux Vendor Firmware Service can update.

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 Release Updates. 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 AI Database 26ai documentation at https://docs.oracle.com/en/database/oracle/oracle-database/26/, in particular the SQL*Plus User's Guide, the SQLcl 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.