Transport Layer Security (TLS) encrypts traffic between your app and database, protecting credentials and data in transit. This guide shows how to enable and verify TLS for a CodeIgniter 4 app using the MySQLi driver against Amazon RDS/Aurora MySQL—whether you have root on the host or not. It also covers enforcing TLS at the database and common pitfalls.
What you’ll do
- Download the Amazon RDS CA bundle
- Point CodeIgniter’s MySQLi connection at that CA
- Verify the connection is encrypted (with either MySQL or MariaDB clients)
- Optionally require TLS at the DB parameter group level
1) Get the Amazon RDS CA bundle
Use either the global bundle (works for all commercial regions) or a region-specific bundle (e.g., us-east-1).
- Global (covers any commercial region):
https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem - Regional example (N. Virginia):
https://truststore.pki.rds.amazonaws.com/us-east-1/us-east-1-bundle.pem
With root (system-wide location)
|
1 2 3 4 5 |
sudo install -d -m 0755 /etc/ssl/certs sudo curl -fSLo /etc/ssl/certs/rds-combined-ca-bundle.pem \ https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem sudo chmod 0644 /etc/ssl/certs/rds-combined-ca-bundle.pem |
Without root (per-site location, safe for Plesk)
|
1 2 3 4 5 |
mkdir -p /var/www/vhosts/example.com/private/ssl/rds curl -fSLo /var/www/vhosts/example.com/private/ssl/rds/rds-combined-ca-bundle.pem \ https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem chmod 0644 /var/www/vhosts/example.com/private/ssl/rds/rds-combined-ca-bundle.pem |
Sanity checks:
|
1 2 3 4 |
grep -c "BEGIN CERTIFICATE" /path/to/rds-combined-ca-bundle.pem openssl crl2pkcs7 -nocrl -certfile /path/to/rds-combined-ca-bundle.pem \ | openssl pkcs7 -print_certs -noout | head |
Plesk note: if PHP has
open_basedirrestrictions, include the chosen path under the domain’s PHP settings.
2) Configure CodeIgniter 4 (MySQLi) for TLS
CodeIgniter’s MySQLi driver supports TLS via the encrypt option. Provide the CA bundle path and enable verification.
Option A — app/Config/Database.php
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public array $default = [ 'DSN' => '', 'hostname' => 'your-rds-endpoint.rds.amazonaws.com', 'username' => 'db_user', 'password' => '***', 'database' => 'db_name', 'DBDriver' => 'MySQLi', 'pConnect' => false, 'DBDebug' => (ENVIRONMENT !== 'production'), 'charset' => 'utf8mb4', 'DBCollat' => 'utf8mb4_general_ci', 'encrypt' => [ 'ssl_ca' => '/var/www/vhosts/example.com/private/ssl/rds/rds-combined-ca-bundle.pem', 'ssl_verify' => true, // 'ssl_cipher' => 'TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256', // optional pinning ], 'compress' => false, 'strictOn' => false, 'failover' => [], 'port' => 3306, ]; |
Option B — via .env (recommended for secrets)
|
1 2 3 4 5 6 7 |
database.default.hostname = your-rds-endpoint.rds.amazonaws.com database.default.username = db_user database.default.password = *** database.default.database = db_name database.default.DBDriver = MySQLi database.default.encrypt = {"ssl_ca":"/var/www/vhosts/example.com/private/ssl/rds/rds-combined-ca-bundle.pem","ssl_verify":true} |
In app/Config/Database.php, decode if present:
|
1 2 3 4 5 6 7 8 9 |
public function __construct() { parent::__construct(); $arr = json_decode($this->default['encrypt'] ?? '', true); if (is_array($arr)) { $this->default['encrypt'] = $arr; } } |
3) Verify the connection is encrypted
A) Using the Oracle MySQL client (supports --ssl-mode)
|
1 2 3 4 5 6 |
mysql -h your-rds-endpoint.rds.amazonaws.com \ -u db_user -p \ --ssl-mode=VERIFY_CA \ --ssl-ca=/var/www/vhosts/example.com/private/ssl/rds/rds-combined-ca-bundle.pem \ -e "SHOW SESSION STATUS LIKE 'Ssl_cipher';" |
B) Using the MariaDB client (no --ssl-mode)
If mysql --version shows “MariaDB”, use:
|
1 2 3 4 5 6 7 |
mysql -h your-rds-endpoint.rds.amazonaws.com \ -u db_user -p \ --ssl \ --ssl-ca=/var/www/vhosts/example.com/private/ssl/rds/rds-combined-ca-bundle.pem \ --ssl-verify-server-cert \ -e "SHOW SESSION STATUS LIKE 'Ssl_cipher';" |
Which client do I have?
|
1 2 3 4 5 6 |
mysql --version # Example outputs: # mysql Ver 8.0.x for Linux on x86_64 (MySQL Community Server - GPL) # or # mysql Ver 15.1 Distrib 10.xx-MariaDB, for Linux (x86_64) using readline 5.1 |
From inside your app (works the same regardless of client):
|
1 2 3 4 |
$db = \Config\Database::connect(); $row = $db->query('SHOW SESSION STATUS LIKE "Ssl_cipher"')->getRow(); log_message('info', 'MySQL SSL cipher: ' . ($row->Value ?? '')); |
A non-empty Ssl_cipher confirms TLS is active.
4) Enforce TLS on the database (recommended)
Set require_secure_transport = ON in your RDS (MySQL) DB parameter group (or Aurora MySQL cluster parameter group) to reject plaintext connections.
Troubleshooting
mysql: unknown variable 'ssl-mode=VERIFY_CA'
You’re using the MariaDB client. Use--ssl+--ssl-verify-server-certinstead (see 3B).- “AccessDenied” when downloading the bundle
Use the exact paths shown above (/global/global-bundle.pemor/<region>/<region>-bundle.pem). - “Certificate verify failed”
Ensure the CA path is correct and readable by the PHP-FPM user; verify withls -land checkopen_basedir. - RDS Proxy
When connecting through RDS Proxy, it uses ACM-managed certificates; clients normally don’t need to fetch a separate trust store.
Security checklist
- Enforce verification (
--ssl-mode=VERIFY_CAor--ssl-verify-server-cert/ssl_verify: true). - Store credentials in
.env, not in the repository. - Keep the CA bundle out of web root (e.g.,
private/ssl/rds/). - Consider pinning TLS versions/ciphers if your policy requires it.
Appendix: Copy-paste blocks
Global bundle to a per-site path (non-root):
|
1 2 3 4 5 |
mkdir -p /var/www/vhosts/example.com/private/ssl/rds curl -fSLo /var/www/vhosts/example.com/private/ssl/rds/rds-combined-ca-bundle.pem \ https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem chmod 0644 /var/www/vhosts/example.com/private/ssl/rds/rds-combined-ca-bundle.pem |
MySQL client verification (Oracle client):
|
1 2 3 4 5 6 |
mysql -h your-rds-endpoint.rds.amazonaws.com \ -u db_user -p \ --ssl-mode=VERIFY_CA \ --ssl-ca=/var/www/vhosts/example.com/private/ssl/rds/rds-combined-ca-bundle.pem \ -e "SHOW SESSION STATUS LIKE 'Ssl_cipher';" |
MariaDB client verification:
|
1 2 3 4 5 6 7 |
mysql -h your-rds-endpoint.rds.amazonaws.com \ -u db_user -p \ --ssl \ --ssl-ca=/var/www/vhosts/example.com/private/ssl/rds/rds-combined-ca-bundle.pem \ --ssl-verify-server-cert \ -e "SHOW SESSION STATUS LIKE 'Ssl_cipher';" |




