Encrypted SSL/TLS sessions protect MySQL and MariaDB traffic from passive capture, keeping credentials and query results confidential on untrusted networks.

When a client connects over TCP, the database server negotiates TLS during the initial handshake. The server presents a certificate, the client validates it against a trusted CA, and the session keys encrypt all subsequent protocol packets.

Many modern packages ship with TLS support and sometimes auto-generated certificates, but encryption without certificate validation still permits silent interception by an attacker with network position. Certificate files must be readable by the database service, private keys must remain tightly permissioned, and an incorrect ssl-key or ssl-cert path can prevent mysqld from starting.

Steps to enable SSL/TLS on MariaDB or MySQL server:

  1. Open a terminal with sudo privileges.
  2. Create a directory for TLS material at /etc/mysql/ssl.
    $ sudo install -d -m 0750 -o mysql -g mysql /etc/mysql/ssl
  3. Generate a private key for a local certificate authority at /etc/mysql/ssl/ca-key.pem.
    $ sudo openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out /etc/mysql/ssl/ca-key.pem
    .....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*+++++
    .....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*+++++

    Store the CA private key offline when certificate signing is complete.

  4. Create a self-signed CA certificate at /etc/mysql/ssl/ca-cert.pem.
    $ sudo openssl req -x509 -new -key /etc/mysql/ssl/ca-key.pem -sha256 -days 3650 -out /etc/mysql/ssl/ca-cert.pem
    Country Name (2 letter code) [AU]: US
    State or Province Name (full name) [Some-State]: California
    Locality Name (eg, city) []: SanFrancisco
    Organization Name (eg, company) [Internet Widgits Pty Ltd]: ExampleOrg
    Organizational Unit Name (eg, section) []: Database
    Common Name (e.g. server FQDN or YOUR name) []: ExampleOrg MySQL CA
    Email Address []:

    Only the CA certificate (not the CA private key) belongs on client hosts for server validation.

  5. Generate a private key for the database server at /etc/mysql/ssl/server-key.pem.
    $ sudo openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out /etc/mysql/ssl/server-key.pem
    .....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*+++++
    .....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*+++++
  6. Create a server certificate signing request at /etc/mysql/ssl/server-req.pem.
    $ sudo openssl req -new -key /etc/mysql/ssl/server-key.pem -out /etc/mysql/ssl/server-req.pem
    Country Name (2 letter code) [AU]: US
    State or Province Name (full name) [Some-State]: California
    Locality Name (eg, city) []: SanFrancisco
    Organization Name (eg, company) [Internet Widgits Pty Ltd]: ExampleOrg
    Organizational Unit Name (eg, section) []: Database
    Common Name (e.g. server FQDN or YOUR name) []: db.example.net
    Email Address []:

    Hostname validation requires a subjectAltName; a Common Name alone is insufficient for VERIFY_IDENTITY in many TLS stacks.

  7. Create an OpenSSL extension file for the server certificate at /etc/mysql/ssl/server-ext.cnf.
    $ sudo tee /etc/mysql/ssl/server-ext.cnf >/dev/null <<'EOF'
    [v3_server]
    basicConstraints=CA:FALSE
    keyUsage=digitalSignature,keyEncipherment
    extendedKeyUsage=serverAuth
    subjectAltName=DNS:db.example.net,IP:10.0.0.10
    EOF

    Replace the DNS and IP values with real database host details.

  8. Sign the server request to create /etc/mysql/ssl/server-cert.pem.
    $ 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 -extensions v3_server
    Certificate request self-signature ok
    subject=CN = db.example.net
  9. Generate a private key for an optional client certificate at /etc/mysql/ssl/client-key.pem.
    $ sudo openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out /etc/mysql/ssl/client-key.pem
    .....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*+++++
    .....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*+++++

    Client certificates are optional unless accounts enforce REQUIRE X509 or specific certificate attributes.

  10. Create a client certificate signing request at /etc/mysql/ssl/client-req.pem.
    $ sudo openssl req -new -key /etc/mysql/ssl/client-key.pem -out /etc/mysql/ssl/client-req.pem
    Country Name (2 letter code) [AU]: US
    State or Province Name (full name) [Some-State]: California
    Locality Name (eg, city) []: SanFrancisco
    Organization Name (eg, company) [Internet Widgits Pty Ltd]: ExampleOrg
    Organizational Unit Name (eg, section) []: Database
    Common Name (e.g. server FQDN or YOUR name) []: mysql-client
    Email Address []:
  11. Create an OpenSSL extension file for the client certificate at /etc/mysql/ssl/client-ext.cnf.
    $ sudo tee /etc/mysql/ssl/client-ext.cnf >/dev/null <<'EOF'
    [v3_client]
    basicConstraints=CA:FALSE
    keyUsage=digitalSignature
    extendedKeyUsage=clientAuth
    EOF
  12. Sign the client request to create /etc/mysql/ssl/client-cert.pem.
    $ sudo openssl x509 -req -in /etc/mysql/ssl/client-req.pem -CA /etc/mysql/ssl/ca-cert.pem -CAkey /etc/mysql/ssl/ca-key.pem -CAcreateserial -out /etc/mysql/ssl/client-cert.pem -days 3650 -sha256 -extfile /etc/mysql/ssl/client-ext.cnf -extensions v3_client
    Certificate request self-signature ok
    subject=CN = mysql-client
  13. Set ownership of the server key/certificate to the mysql user.
    $ sudo chown mysql:mysql /etc/mysql/ssl/server-key.pem /etc/mysql/ssl/server-cert.pem

    Keep client key material root-owned on the server, or copy it off-host for client use.

  14. Restrict permissions on private keys.
    $ sudo chmod 600 /etc/mysql/ssl/ca-key.pem /etc/mysql/ssl/server-key.pem /etc/mysql/ssl/client-key.pem
  15. Set read permissions on certificate-related files.
    $ sudo chmod 644 /etc/mysql/ssl/ca-cert.pem /etc/mysql/ssl/server-cert.pem /etc/mysql/ssl/client-cert.pem /etc/mysql/ssl/server-req.pem /etc/mysql/ssl/client-req.pem
  16. Add the TLS paths under the mysqld section in /etc/mysql/mysql.conf.d/mysqld.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

    MariaDB commonly uses /etc/mysql/mariadb.conf.d/50-server.cnf for server settings.

    An incorrect ssl-key path or unreadable key file can prevent the database service from starting.

  17. Restart the mysql service.
    $ sudo systemctl restart mysql

    The service name is often mariadb on MariaDB packages.

  18. Check the service status for an active state.
    $ sudo systemctl status mysql
    ● mysql.service - MySQL Community Server
         Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
         Active: active (running) since Mon 2025-12-08 09:41:12 UTC; 12s ago
    ##### snipped #####

    Use journalctl for startup errors: sudo journalctl -u mysql -b --no-pager.

  19. Confirm the server loaded the configured TLS files.
    $ sudo mysql -e "SHOW VARIABLES WHERE Variable_name IN ('ssl_ca','ssl_cert','ssl_key');"
    +---------------+------------------------------+
    | Variable_name | Value                        |
    +---------------+------------------------------+
    | ssl_ca        | /etc/mysql/ssl/ca-cert.pem   |
    | ssl_cert      | /etc/mysql/ssl/server-cert.pem |
    | ssl_key       | /etc/mysql/ssl/server-key.pem |
    +---------------+------------------------------+

    A non-empty Ssl_cipher value confirms an encrypted session.

  20. Create a minimal test account that requires SSL.
    $ sudo mysql -e "CREATE USER 'tlscheck'@'127.0.0.1' IDENTIFIED BY 'STRONG_PASSWORD_HERE' REQUIRE SSL;"
    Query OK, 0 rows affected

    Replace STRONG_PASSWORD_HERE with a unique password.

  21. Verify a TLS cipher is negotiated for a TCP connection.
    $ sudo mysql -h 127.0.0.1 --ssl-ca=/etc/mysql/ssl/ca-cert.pem -u tlscheck -p -e "SHOW STATUS LIKE 'Ssl_cipher';"
    Enter password:
    +---------------+-------------------------+
    | Variable_name | Value                   |
    +---------------+-------------------------+
    | Ssl_cipher    | TLS_AES_256_GCM_SHA384  |
    +---------------+-------------------------+

    Mutual TLS uses --ssl-cert plus --ssl-key with an account that enforces REQUIRE X509.

    Account-level enforcement uses ALTER USER 'app'@'%' REQUIRE SSL;.

  22. Remove the test account.
    $ sudo mysql -e "DROP USER 'tlscheck'@'127.0.0.1';"
    Query OK, 0 rows affected
Discuss the article:

Comment anonymously. Login not required.