Laravel + MySQL + SSL-Mode - SQLSTATE[HY000] [3159]

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Solving the SSL Nightmare: Laravel, MySQL, and SQLSTATE[HY000] [3159]

As a senior developer working with modern stacks like Laravel and MySQL, dealing with database connectivity and security protocols is a daily reality. Recently, I encountered a frustrating scenario involving an SSL connection setup on a Linode server where a seemingly correct command-line connection worked, but the application layer—specifically php artisan migrate—failed with a cryptic SQLSTATE error.

This post dives deep into the root cause of this conflict and provides a practical solution for ensuring secure, reliable database interactions within your Laravel application.

Understanding the Error: SQLSTATE[HY000] [3159]

The error you are seeing, SQLSTATE[HY000] [3159] Connections using insecure transport are prohibited while --require_secure_transport=ON, is a clear security measure being enforced by the MySQL server. When you use --ssl-mode=required with the client (like mysqlclient), you are explicitly demanding an encrypted connection.

The core conflict arises because:

  1. Client Success: Your direct command-line client successfully established the SSL connection, likely because it is configured to handle certificate verification directly at the OS/client level.
  2. Application Failure: The underlying PHP MySQL driver used by Laravel's Eloquent or migration tools encounters a stricter security check enforced by the environment (perhaps due to specific PHP extensions or configuration settings) that prohibits insecure transport when secure mode is active, resulting in the QueryException.

Essentially, the application layer is failing to properly negotiate the required secure transport channel demanded by the MySQL server.

The Laravel Configuration Fix: Bridging the Gap

Since you are running this within a Laravel context, we need to ensure that the connection defined in your .env file aligns with the security requirements and the actual SSL setup on your server. While the error originates at the driver level, configuring the database connection explicitly helps Laravel manage the session securely.

The fix often involves ensuring that the necessary connection parameters are correctly passed, especially when dealing with custom hostnames or stricter modes. Although you mentioned you haven't set up PEM files, we must configure the intent of the connection correctly.

1. Reviewing .env and config/database.php

The configuration for Laravel resides primarily in your environment variables and the database configuration file. While the error points to a transport issue, ensuring the host and credentials are rock-solid is the first step.

In your .env file:

DB_CONNECTION=mysql
DB_HOST=lin-xxx-mysql-primary-private.servers.linodedb.net
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME=your_user
DB_PASSWORD=your_password
# Note: SSL settings are often implicitly handled by the driver negotiation, 
# but ensure all connection details are correct for secure access.

In your config/database.php, verify that the connection configuration supports the required security context. For MySQL connections, Laravel relies on the underlying PDO driver to handle the SSL handshake. If you are using a modern setup, ensure your PHP environment has the necessary SSL libraries compiled in (e.g., OpenSSL support).

// config/database.php
'mysql' => [
    'driver' => 'mysql',
    'host' => env('DB_HOST', '127.0.0.1'),
    'port' => env('DB_PORT', '3306'),
    'database' => env('DB_DATABASE', 'laravel'),
    'username' => env('DB_USERNAME', 'root'),
    'password' => env('DB_PASSWORD', ''),
    // Ensure SSL is handled correctly if the driver supports it directly, 
    // though usually this is managed by host settings and client negotiation.
    'ssl_mode' => 'required', // Explicitly setting the required mode here can sometimes help Laravel contextually.
],

Best Practices for Secure Database Access

The discrepancy between the CLI success and the application failure highlights a common pitfall: the gap between shell utilities and high-level framework abstraction. When dealing with production applications, security protocols must be consistent across all layers.

Key Takeaway: Always treat database connections as secured endpoints. If you are using cloud providers like Linode, ensure that the SSL certificates are correctly installed on the server and properly trusted by the operating system and PHP environment so that all processes—from mysqlclient to Laravel's Artisan commands—can negotiate a secure tunnel without error.

For robust security in your Laravel projects, always prioritize configuration integrity. As we build scalable applications, ensuring that our data layer is not just functional but fundamentally secure is paramount. For more insights into building resilient systems with PHP and frameworks, I highly recommend exploring resources from laravelcompany.com.

Conclusion

The SQLSTATE[HY000] [3159] error in Laravel migrations stems from a mismatch in how the application layer negotiates the SSL connection compared to the raw client connection. By meticulously reviewing your .env settings, ensuring correct host configuration, and verifying the underlying PHP/MySQL environment setup, you can resolve this conflict. Remember, consistency is key: what works on the command line must work within the framework context. Secure development starts with secure configurations!