TLS protects MySQL and MariaDB logins, queries, and result sets from passive capture on any network path between the client and the server. That matters as soon as connections leave the local Unix socket, because plain TCP exposes database credentials and application data to anyone who can observe the traffic.

The server side of a TLS-enabled database connection is controlled by the ssl_ca, ssl_cert, and ssl_key settings. Those files provide the certificate authority chain, the server certificate, and the matching private key that the database process loads during startup, while require_secure_transport blocks plain TCP sessions that do not negotiate TLS first.

Current releases add some shortcuts, but those shortcuts do not remove the need for deliberate certificate management. MySQL can auto-generate certificate files in the data directory when no TLS options are set, and MariaDB 11.4+ can enable verified zero-configuration TLS between current MariaDB clients and servers; a CA-managed certificate with the correct subjectAltName is still the safer choice when clients need predictable host validation, mixed MySQL/MariaDB fleets, or mutual TLS later. Examples below use the common Debian and Ubuntu layout under /etc/mysql/.

Steps to configure MySQL or MariaDB server SSL/TLS:

  1. Open a terminal session with an account that can use sudo.
  2. Check the current server TLS state before changing files.
    $ mysql -u root -p -e "SHOW GLOBAL VARIABLES LIKE 'have_ssl'; SHOW GLOBAL VARIABLES WHERE Variable_name IN ('ssl_ca','ssl_cert','ssl_key','require_secure_transport');"

    Use mariadb instead of mysql on MariaDB packages that do not ship the compatibility client name. Non-empty ssl_ca, ssl_cert, or ssl_key values mean the server already has a configured TLS context.

    MySQL can auto-discover ca.pem, server-cert.pem, and server-key.pem in the data directory. Replace those defaults when clients need VERIFY_IDENTITY against a real host name, because the auto-generated MySQL certificates do not carry a host-specific identity for that check.

  3. Create a directory for CA-managed TLS files.
    $ sudo install -d -m 0750 -o mysql -g mysql /etc/mysql/ssl
  4. Create a local certificate authority and a server certificate with a matching subjectAltName.
    $ sudo openssl genrsa -out /etc/mysql/ssl/ca-key.pem 4096
    $ sudo openssl req -x509 -new -nodes -key /etc/mysql/ssl/ca-key.pem -sha256 -days 3650 -out /etc/mysql/ssl/ca-cert.pem -subj "/CN=Example Database CA"
    $ sudo openssl genrsa -out /etc/mysql/ssl/server-key.pem 2048
    $ sudo openssl req -new -key /etc/mysql/ssl/server-key.pem -out /etc/mysql/ssl/server-req.pem -subj "/CN=db.example.net"
    $ sudo tee /etc/mysql/ssl/server-ext.cnf >/dev/null <<'EOF'
    subjectAltName=DNS:db.example.net,IP:192.0.2.15
    extendedKeyUsage=serverAuth
    EOF
    $ sudo openssl x509 -req -in /etc/mysql/ssl/server-req.pem -CA /etc/mysql/ssl/ca-cert.pem -CAkey /etc/mysql/ssl/ca-key.pem -CAcreateserial -out /etc/mysql/ssl/server-cert.pem -days 3650 -sha256 -extfile /etc/mysql/ssl/server-ext.cnf
    Certificate request self-signature ok
    subject=CN = db.example.net

    Replace db.example.net and 192.0.2.15 with the DNS name and IP address that clients really use. Use a certificate from an internal or public CA instead of a self-signed CA when the environment already has a trusted PKI.

    Hostname validation depends on the subjectAltName extension. A Common Name alone is not enough for current TLS client verification.

  5. Set file ownership and permissions so the database service can read the server key and certificate.
    $ sudo chown mysql:mysql /etc/mysql/ssl/server-key.pem /etc/mysql/ssl/server-cert.pem
    $ sudo chmod 600 /etc/mysql/ssl/server-key.pem
    $ sudo chmod 644 /etc/mysql/ssl/ca-cert.pem /etc/mysql/ssl/server-cert.pem

    Protect the CA private key carefully. Move it off the database host after signing if the server does not also act as the certificate authority.

  6. Create a custom TLS include file for the server.
    /etc/mysql/conf.d/ssl.cnf
    [mysqld]
    ssl_ca=/etc/mysql/ssl/ca-cert.pem
    ssl_cert=/etc/mysql/ssl/server-cert.pem
    ssl_key=/etc/mysql/ssl/server-key.pem
    require_secure_transport=ON

    On MariaDB packages for Debian and Ubuntu, create /etc/mysql/mariadb.conf.d/z-custom-my.cnf instead and use a [mariadb] or [server] section. Keep custom TLS settings in a separate include file instead of editing the bundled 50-server.cnf directly.

    require_secure_transport=ON rejects unencrypted TCP connections while still allowing secure local transports such as the Unix socket.

  7. Restart the database service so the new TLS context loads.
    $ sudo systemctl restart mysql

    Use sudo systemctl restart mariadb on MariaDB packages whose unit name is mariadb.

    If the restart fails, inspect sudo journalctl -u mysql -b --no-pager or the MariaDB unit name before retrying. A wrong certificate path or unreadable key file usually prevents startup.

  8. Confirm that the server is active and that it loaded the TLS files.
    $ mysql -u root -p -e "SHOW GLOBAL VARIABLES LIKE 'have_ssl'; SHOW GLOBAL VARIABLES WHERE Variable_name IN ('ssl_ca','ssl_cert','ssl_key','require_secure_transport');"
    Variable_name	Value
    have_ssl	YES
    Variable_name	Value
    require_secure_transport	ON
    ssl_ca	/etc/mysql/ssl/ca-cert.pem
    ssl_cert	/etc/mysql/ssl/server-cert.pem
    ssl_key	/etc/mysql/ssl/server-key.pem

    have_ssl=YES confirms that the server initialized TLS support. The file paths should match the include file that was just added.

  9. Create a temporary account that must use TLS, then verify a TCP connection negotiates a cipher.
    $ mysql -u root -p -e "CREATE USER 'tlscheck'@'%' IDENTIFIED BY 'StrongPass123' REQUIRE SSL;"
    $ mysql --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/mysql/ssl/ca-cert.pem -h db.example.net -u tlscheck -p -e "SHOW STATUS LIKE 'Ssl_cipher';"
    Enter password:
    +---------------+------------------------+
    | Variable_name | Value                  |
    +---------------+------------------------+
    | Ssl_cipher    | TLS_AES_256_GCM_SHA384 |
    +---------------+------------------------+

    On current MariaDB clients, the equivalent check is typically mariadb --ssl-ca=/etc/mysql/ssl/ca-cert.pem --ssl-verify-server-cert -h db.example.net -u tlscheck -p -e "SHOW STATUS LIKE 'Ssl_cipher';".

    Replace StrongPass123 with a unique temporary password.

    If Ssl_cipher is empty, the connection is not using TLS. Re-check the certificate paths, the server restart, and whether the client connected over TCP instead of the local socket.

  10. Remove the temporary account when the test is complete.
    $ mysql -u root -p -e "DROP USER 'tlscheck'@'%';"

    To keep encryption mandatory for a real application account, use ALTER USER 'app'@'%' REQUIRE SSL; or stronger certificate-based requirements such as REQUIRE X509.