Setting Up MySQL on a Remote Server and Connecting via PHP

Introduction
Deploying MySQL on a remote server unlocks scalable application architecture but introduces security and configuration challenges. This guide walks through:
Secure MySQL installation
Remote access configuration
Database migration strategies
PHP connectivity
Production hardening
Performance tuning
Tested on Ubuntu 22.04 LTS | MySQL 8.0 | PHP 8.1
๐ Prerequisites
Server Specifications:
Ubuntu 22.04 LTS (2+ vCPU, 4GB RAM recommended)
Public IP address (
139.1.1.101
in this example)
Local Environment:
MySQL Workbench or
mysqldump
SSH client (OpenSSH)
Security Essentials:
Firewall (UFW) enabled
SSH key authentication
๐ Step-by-Step Implementation
๐ 1. Secure Server Initialization
# SSH with key authentication (recommended)
ssh -i ~/.ssh/your_key.pem karimtrd@139.1.1.101
# Create sudo user (if not exists)
sudo adduser deploy --gecos "" && sudo usermod -aG sudo deploy
Security Tip: Disable root SSH in /etc/ssh/sshd_config
๐ ๏ธ 2. MySQL Installation & Hardening
Install with TLS Support:
sudo apt update && sudo apt install mysql-server -y
sudo systemctl enable --now mysql
Configure Security:
sudo mysql_secure_installation
Follow these choices:
VALIDATE PASSWORD COMPONENT โ Strong
Root password: Hello@Unlock!24Mysql
Remove anonymous users? โ Yes
Disallow root login remotely? โ Yes
Remove test database? โ Yes
Reload privileges? โ Yes
Verify Installation:
sudo mysql -u root -p
SHOW VARIABLES LIKE '%tls%'; # Confirm TLS active
๐ 3. Remote Access Configuration
Update MySQL Config:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
bind-address = 0.0.0.0
# Enable binary logging for point-in-time recovery
log-bin = /var/log/mysql/mysql-bin.log
server-id = 1
Firewall Rules:
sudo ufw allow proto tcp from 192.168.1.0/24 to any port 3306 # Limit to your network
sudo ufw limit 22/tcp # Protect SSH from brute-force
sudo ufw enable
Restart Service:
sudo systemctl restart mysql
๐ค 4. Database User & Privileges
CREATE DATABASE postech22_karimtraders
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
CREATE USER 'vm_karimtraders'@'192.168.1.%'
IDENTIFIED WITH mysql_native_password BY 'Unlock!24Mysql@Do'
REQUIRE SSL; # Enforce TLS
GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE
ON postech22_karimtraders.*
TO 'vm_karimtraders'@'192.168.1.%';
USE postech22_karimtraders;
FLUSH PRIVILEGES;
Note: Avoid GRANT ALL
and '%'
wildcards in production
๐ Database Migration Strategies
# Local export with compression
mysqldump -u root -p --single-transaction --routines \
--triggers postech22_karimtraders | gzip > db_$(date +%F).sql.gz
# Secure transfer
scp -i ~/.ssh/key.pem db_2023-10-05.sql.gz karimtrd@139.1.1.101:~
# Remote import
gunzip < db_2023-10-05.sql.gz | mysql -u vm_karimtraders -p postech22_karimtraders
Method 2: MySQL Replication (Large Databases)
Configure master-slave replication
Promote the slave to primary after cutover
Update application connection strings
๐ PHP Connectivity & Best Practices
PDO Connection with Error Handling:
<?php
$servername = "139.1.1.101";
$username = "vm_karimtraders";
$password = "Unlock!24Mysql@Do";
$dbname = "postech22_karimtraders";
$ssl = [
PDO::MYSQL_ATTR_SSL_CA => '/etc/ssl/certs/ca-certificates.crt',
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => true
];
try {
$conn = new PDO(
"mysql:host=$servername;dbname=$dbname;charset=utf8mb4",
$username,
$password,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_PERSISTENT => true
] + $ssl
);
echo "Connected successfully with TLS encryption";
} catch (PDOException $e) {
error_log("Connection failed: " . $e->getMessage());
http_response_code(503);
exit("Database maintenance in progress");
}
?>
Key Features:
TLS encryption enforcement
Prepared statements
Persistent connections
Graceful error handling
๐ฅ Production Hardening Checklist
Encryption:
ALTER DATABASE postech22_karimtraders ENCRYPTION = 'Y'; # InnoDB tablespace encryption
Auditing:
sudo apt install mysql-audit-plugin
Backup Automation:
# Daily compressed backups with retention 0 2 * * * /usr/bin/mysqldump -u bkpuser -p[Password] --single-transaction \ --routines postech22_karimtraders | gzip > /backups/db_$(date +\%F).sql.gz \ && find /backups -type f -mtime +30 -delete
Monitoring:
Enable Performance Schema:
SET GLOBAL performance_schema=ON;
Install Percona Monitoring Plugins
โก Performance Tuning
my.cnf Optimizations:
[mysqld]
innodb_buffer_pool_size = 2G # 70-80% of RAM
innodb_log_file_size = 256M
max_connections = 200
thread_cache_size = 50
query_cache_type = 0 # Disable on MySQL 8+
Connection Pooling in PHP:
$conn->setAttribute(PDO::ATTR_PERSISTENT, true); # Reuse connections
Index Optimization:
EXPLAIN SELECT * FROM orders WHERE status = 'processing';
CREATE INDEX idx_orders_status ON orders(status);
๐จ Troubleshooting Guide
Issue | Diagnosis Command | Solution |
Connection timeout | telnet 139.1.1.101 3306 | Check UFW rules and bind-address |
"Access Denied" errors | SELECT host FROM mysql.user WHERE user='vm_karimtraders'; | Verify user privileges |
High CPU usage | SHOW PROCESSLIST; | Optimize slow queries |
Replication lag | SHOW SLAVE STATUS\G | Increase innodb_buffer_pool_size |
Can't connect via PHP | `php -m | grep mysql` |
โ Deployment Validation Checklist
Test local โ remote connection:
mysql -h 139.1.1.101 -u vm_karimtraders -p
Verify TLS:
\s
in MySQL client shows "SSL: Cipher in use"Load test with
sysbench
Validate backups: Restore to test instance
Test failover procedure (if replicated)
๐ Conclusion
You've now deployed a production-grade MySQL server with:
Encrypted network connections
Least-privilege access control
Automated backups
Performance monitoring
PHP connectivity best practices
Next Steps:
Implement read replicas for high-traffic apps
Set up automated failover with ProxySQL
Enable slow query logging for optimization
โจ Pro Tip: Use infrastructure-as-code tools like Ansible to automate this setup!
Enjoyed this guide?
โ
Follow me for more DevOps tutorials
๐ Share with your engineering team
๐ฌ Comment your deployment challenges!
Subscribe to my newsletter
Read articles from KUMAR BISHOJIT directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
