Remote Database Access and Security
Bind to localhost by default; when remote access is truly needed, use a least-privilege account plus a firewall allowlist and an encrypted channel — never expose a database port to the open internet.
Your database holds the most sensitive data you own. Most breaches don't come from exotic exploits — they come from someone opening 3306, 5432, or 6379 straight to the internet, then pairing it with a weak password or a default account. This article covers the safe default and how to open things up carefully when you have to.
Default: listen on 127.0.0.1 only
If the database and the application run on the same server, keep the database bound to the loopback address so nothing outside the box can reach it.
MySQL/MariaDB (/etc/mysql/mysql.conf.d/mysqld.cnf):
[mysqld]
bind-address = 127.0.0.1
PostgreSQL (/etc/postgresql//main/postgresql.conf):
listen_addresses = 'localhost'
Redis is especially risky — always bind to localhost and require a password (/etc/redis/redis.conf):
bind 127.0.0.1
requirepass your-strong-password
Restart the service, then confirm with ss -tlnp that the port listens on 127.0.0.1 and not on 0.0.0.0.
When you genuinely need remote access: four layers
1. Widen bind-address cautiously
Only when necessary, change the listen address to a private IP (for example 10.0.0.5). Avoid 0.0.0.0 whenever you can.
2. Let the firewall allow trusted IPs only
Use ufw to restrict the port to known sources instead of opening it to everyone:
sudo ufw allow from 203.0.113.10 to any port 5432 proto tcp
sudo ufw deny 5432
3. Create a dedicated least-privilege account — not root
Give the remote application its own account with access to just the database and rights it needs:
CREATE USER 'app'@'10.0.0.%' IDENTIFIED BY 'strong-password';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app'@'10.0.0.%';
4. Turn on SSL or use an SSH tunnel
The simplest robust option is an SSH tunnel, which keeps the database port private:
ssh -L 5432:127.0.0.1:5432 user@your-server
# then connect locally to 127.0.0.1:5432
Same private network? Prefer internal traffic
If the app and the database sit on the same private network (the same VPC or a datacenter LAN), have them talk over their internal addresses. The database never needs a public face, and the connection is both faster and safer.
Summary
- Bind to 127.0.0.1 by default, and double-check the listen address with ss -tlnp.
- Never expose 6379/3306/5432 to the public internet — Redis, MySQL, and PostgreSQL alike.
- When remote access is required: widen bind-address, allowlist source IPs in the firewall, create a dedicated least-privilege account, and wrap it in SSL or an SSH tunnel.
- Keep same-network traffic internal. Shrinking your attack surface is the cheapest, highest-return investment in database security.