Configuring TLS-Encrypted MySQL Connections: Server, Client, and Certificates
AI generated
InnoDB
SQL
MySQL / Security
Configuring TLS-Encrypted MySQL Connections
how server, client, and certificate management fit together

Unencrypted connections between an application server and a database are an underestimated risk in production Magento environments: anyone with access to the network segment between the web server and the database server can read customer data, sessions, and credentials in plain text. This article shows how to consistently secure MySQL connections with TLS on both the server and client side, manage certificates cleanly, and avoid the typical pitfalls that show up in multi-store setups with several application servers.

15 min read TLS / SSL Certificate Management

1. Why TLS matters for MySQL connections in a Magento context

MySQL connections already run opportunistically encrypted by default, but without any enforced check: a client that does not offer TLS, or an attacker who actively downgrades a connection, can still establish the session unencrypted. In a typical Magento setup with a separate database server, several web and cron servers, and possibly a cloud environment spanning multiple availability zones, the network path between application and database is no longer a closed system but crosses switches, load balancers, and sometimes even shared network segments.

Anyone reading along on that path sees not only orders and customer data but potentially the database password itself, if authentication details are ever transmitted over an unencrypted channel. For stores handling payment data, personal data under the GDPR, or PCI-DSS obligations, consistently enforced TLS encryption is therefore not optional polish but a basic safeguard that can be set up with manageable effort and that audits routinely ask about explicitly.

2. Server-side TLS configuration: require_secure_transport and SSL variables

For several years now MySQL has automatically generated self-signed certificates in the data directory on first start, so TLS is technically available right away. That is not enough for an enforced, production-grade configuration, though: actual enforcement happens through the global system variable require_secure_transport, which, since MySQL 8.0.21, prevents clients from connecting over TCP without encryption. Unix socket connections on the same host are unaffected, since they never travel over the network in the first place.

In addition, dedicated certificates should replace the automatically generated default ones as soon as multiple servers are involved, since the automatic generation happens independently per instance and does not fit a company-wide certificate chain. The relevant variables ssl_ca, ssl_cert, and ssl_key are set in the [mysqld] section of the configuration file and point to the dedicated certificate authority, the server certificate, and the private key.


# /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
ssl_ca   = /etc/mysql/tls/ca.pem
ssl_cert = /etc/mysql/tls/server-cert.pem
ssl_key  = /etc/mysql/tls/server-key.pem

# since MySQL 8.0.21: reject any TCP connection without TLS
require_secure_transport = ON
tls_version = TLSv1.2,TLSv1.3

3. Generating and managing certificates: a dedicated CA instead of ad hoc certificates

For smaller setups, MySQL ships the mysql_ssl_rsa_setup command line tool, which generates a minimal certificate authority along with server and client certificates in a few seconds. For production environments with several database servers and application servers, it pays off instead to build a dedicated, documented PKI structure where a central internal CA signs the certificates for every database instance, so clients only need to trust a single, consistent certificate chain.

It matters that the server certificate carries a Subject Alternative Name covering every relevant hostname and, where applicable, the internal IP address, since modern clients no longer check only the Common Name. The server's private key needs restrictive file permissions (0600, owned by the mysql user) and must never leave the database server, not even inside a backup, without additional encryption of its own.


# Building a minimal own CA with openssl (short version)
openssl genrsa -out ca-key.pem 4096
openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca.pem -subj "/CN=Mironsoft Internal DB CA"

# Generate a server certificate and sign it with the CA
openssl genrsa -out server-key.pem 2048
openssl req -new -key server-key.pem -out server-req.pem -subj "/CN=db-primary.internal"
openssl x509 -req -in server-req.pem -days 825 -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile server-ext.cnf

# server-ext.cnf contains: subjectAltName=DNS:db-primary.internal,DNS:db.internal,IP:10.0.1.10

4. Client-side configuration: REQUIRE SSL and REQUIRE X509 per user

Besides the global enforcement through require_secure_transport, TLS can also be mandated per database user for staggered security requirements. The REQUIRE SSL clause in CREATE USER or ALTER USER forces an encrypted connection without requiring a client certificate. Higher requirements are met by REQUIRE X509, which additionally demands a valid client certificate signed by the known CA and thereby enables genuine mutual authentication.

On the client side, the ssl-mode parameter controls connection behavior, with values ranging from DISABLED through PREFERRED and REQUIRED up to VERIFY_CA and VERIFY_IDENTITY. Only the latter two modes actually check whether the certificate presented by the server originates from the expected CA and, in the case of VERIFY_IDENTITY, whether the connection's hostname matches the certificate, which effectively prevents man-in-the-middle attacks.


-- Application user that must always use TLS
CREATE USER 'magento_app'@'10.0.2.%' IDENTIFIED BY 'a-strong-password' REQUIRE SSL;

-- Migration user with mutual certificate verification
CREATE USER 'ci_migration'@'10.0.3.%' IDENTIFIED BY 'another-password' REQUIRE X509;

-- Retrofit an existing user to require TLS
ALTER USER 'reporting'@'%' REQUIRE SSL;

5. Magento integration: setting the right SSL options in env.php

For Magento itself to use TLS on the database connection, the corresponding PDO options need to be set in the db section of app/etc/env.php. Magento passes the driver_options defined there straight through to the PDO MySQL driver, so the same constants used in any other PHP PDO application apply, such as PDO::MYSQL_ATTR_SSL_CA for the path to the CA file and PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT to enable hostname verification equivalent to VERIFY_IDENTITY.

A common mistake in multi-server deployments is updating the CA file on only one application server while others still reference an expired certificate, causing sporadic, hard-to-reproduce connection failures. env.php should therefore be distributed consistently through the deployment process, and the path to the CA file should be identical across every server, ideally driven by central configuration management rather than manual copies.


// app/etc/env.php (excerpt)
'db' => [
    'connection' => [
        'default' => [
            'host' => 'db-primary.internal',
            'dbname' => 'magento',
            'username' => 'magento_app',
            'password' => 'a-strong-password',
            'driver_options' => [
                PDO::MYSQL_ATTR_SSL_CA => '/etc/magento/tls/ca.pem',
                PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => true,
            ],
        ],
    ],
],

6. Certificate rotation: expiry monitoring and rollover without downtime

Certificates have a limited lifetime, and an unnoticed expired server certificate can, in the worst case, take down every application connection at once as soon as clients use VERIFY_CA or VERIFY_IDENTITY. A simple daily check with openssl x509 -enddate -noout against every certificate in use, combined with a warning threshold of about thirty days before expiry, reliably prevents that outage and should feed into an existing monitoring system.

For the actual rollover, the database server no longer needs a restart since MySQL 8.0.16: the command ALTER INSTANCE RELOAD TLS reloads new certificate and key files from the configured paths without interrupting existing connections. In practice that means copying the new certificate to disk, running ALTER INSTANCE RELOAD TLS, and only then removing the old files, so an invalid certificate is never active at any point.

7. Practical pitfalls in multi-store setups with several application servers

As soon as several application servers, or several Magento websites behind a load balancer, access the same database, typical configuration mistakes surface. The most common one is a server certificate whose Subject Alternative Name lists only a single internal hostname, while some application servers connect through a different DNS name or an IP address. Under VERIFY_IDENTITY that results in rejected connections that show up on some servers and not others, which makes troubleshooting considerably harder.

A second typical pitfall is diverging CA bundle versions across application servers after a certificate rotation, for instance because a new server was provisioned during a scaling event using an older deployment snapshot. Central certificate distribution through configuration management tools, or a shared, versioned artifact in the deployment process, prevents this drift and ensures every server uses the same certificate chain at any given time.


# Test the connection from a single application server explicitly
mysql --host=db-primary.internal --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/magento/tls/ca.pem -u magento_app -p -e "SHOW STATUS LIKE 'Ssl_cipher';"

# Compare the CA fingerprint across every application server
md5sum /etc/magento/tls/ca.pem

8. Monitoring and troubleshooting: status variables and common error codes

Whether a specific connection is actually encrypted is shown by the session variable Ssl_cipher, which stays empty for an unencrypted connection and reports the cipher suite in use for a successful TLS connection. For an ongoing overview, a periodic query against performance_schema.status_by_thread or performance_schema.status_by_account shows which accounts actually connect encrypted and which still do not.

The most common client-side error code for TLS problems is errno 2026, which shows up both for a genuine certificate problem and for a simply wrong CA file path, making it fairly uninformative on its own. In that case, a manual connection attempt using the CLI client with ssl-mode explicitly set helps, since the error message it returns is usually far more detailed than the one surfaced through the PDO driver in the application.


-- Check whether the current connection uses TLS
SHOW STATUS LIKE 'Ssl_cipher';

-- Server-wide overview of encrypted vs. unencrypted sessions
SELECT VARIABLE_VALUE AS current_cipher
FROM performance_schema.session_status
WHERE VARIABLE_NAME = 'Ssl_cipher';

9. Performance impact of TLS and justified exceptions

The computational cost of TLS is essentially limited to the initial handshake, while the actual data transfer causes practically no measurable overhead anymore thanks to modern CPU acceleration for AES. With short-lived connections and no connection pooling, the repeated handshake can still become noticeable, which is one more reason connection pooling on the application side is advisable regardless, as it further reduces the TLS overhead by making the handshake happen less often.

One justified exception to the encryption requirement is a pure Unix socket connection between application and database on the same host, since there is no network path there that could be eavesdropped on. For every connection over TCP, especially between separate servers or across a cloud VPC, consistently enforced TLS encryption remains the standard, one that current compliance frameworks such as PCI-DSS 4.0 explicitly expect.

ssl-mode Encryption Enforced Certificate Verification Recommended Use
DISABLED No None Local testing only, never in production
PREFERRED (default) No (opportunistic) None Not suitable for production Magento environments
REQUIRED Yes None Minimum requirement for every TCP connection
VERIFY_CA Yes CA chain checked When hostnames vary (e.g. behind a load balancer)
VERIFY_IDENTITY Yes CA chain and hostname checked Recommended default for application servers

Mironsoft

Database performance, index tuning, and Magento DB optimization

A Magento shop suffering from slow database queries?

We analyze MySQL databases for performance bottlenecks, optimize indexes and queries with purpose, and set up backup and replication strategies that actually work when it counts.

Performance Audit

Systematically investigate the slow query log and explain plans for bottlenecks.

Index Optimization

Build indexes with purpose for the shop's actual query load.

Backup Strategy

Set up reliable backup and restore processes for production Magento databases.

10. Summary

TLS-Encrypted MySQL Connections at a Glance

Server enforcement

require_secure_transport = ON blocks unencrypted TCP connections since MySQL 8.0.21.

User level

REQUIRE SSL or REQUIRE X509 enforces encryption and, optionally, client certificates per account.

Rotation

ALTER INSTANCE RELOAD TLS loads new certificates without a restart and without dropping connections.

Multi-server

SAN entries and centrally distributed CA files prevent server-dependent connection failures.

11. FAQ: TLS-Encrypted MySQL Connections at a Glance

1Is MySQL's automatically generated SSL configuration enough for production?
It is enough to get started, but a production multi-server environment should use a dedicated, documented CA with proper Subject Alternative Names, since automatically generated certificates are independent per instance and cannot be distributed consistently.
2What exactly does require_secure_transport do?
This global system variable has, since MySQL 8.0.21, prevented clients from connecting over TCP without TLS. Unix socket connections on the same host are exempt since they never travel over the network.
3What is the difference between REQUIRE SSL and REQUIRE X509?
REQUIRE SSL only forces an encrypted connection without a client certificate. REQUIRE X509 additionally demands a valid client certificate signed by the known CA, enabling mutual authentication.
4Which ssl-mode is recommended for Magento application servers?
VERIFY_IDENTITY is the recommended default, since it checks both the certificate chain and the hostname. VERIFY_CA is suitable when hostnames vary behind a load balancer and an exact match is not possible.
5How do you set TLS options in Magento's env.php?
Through driver_options in the db section, such as PDO::MYSQL_ATTR_SSL_CA for the CA file path and PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT for hostname verification. Magento passes these options straight through to the PDO MySQL driver.
6Does the database server need a restart for certificate rotation?
No, since MySQL 8.0.16 the command ALTER INSTANCE RELOAD TLS reloads new certificate and key files from the configured paths without interrupting existing connections.
7Which error code typically points to a TLS problem?
Errno 2026 signals a failed SSL connection but is fairly uninformative, since it appears both for genuine certificate problems and for a simply wrong CA path. A manual connection attempt with the CLI client usually returns a more detailed error.
8Why do TLS errors often only occur on individual application servers?
Usually because of diverging or outdated CA files on individual servers, often after a certificate rotation or after adding a new server built from an older deployment snapshot. Centrally distributed, versioned certificates prevent this drift.
9Does TLS cause a noticeable performance overhead?
The actual data transfer causes practically no measurable overhead anymore thanks to CPU acceleration for AES. With short-lived connections and no connection pooling, the repeated handshake can become noticeable, which is another reason to use connection pooling.
10Is there a justified exception to the TLS requirement?
Yes, pure Unix socket connections between application and database on the same host, since there is no eavesdroppable network path there. For every connection over TCP, TLS remains mandatory.