Database Hosting: PostgreSQL, MySQL, and MongoDB on Bare Metal
Managed database services charge $15–$200+/mo for what you can run on your own server in ten minutes. AWS RDS, PlanetScale, MongoDB Atlas — they all add a 5–10x markup over the actual compute cost. Here is how to install, secure, back up, and replicate the three most popular databases on bare metal.
PostgreSQL
Install and Configure
# Deploy a RAW server and SSH in
npx rawhq deploy
ssh root@your-server-ip
# Install PostgreSQL 16
apt update && apt install -y postgresql-16
# Verify
systemctl status postgresql
sudo -u postgres psql -c "SELECT version();"Tune for NVMe storage and available RAM. Edit /etc/postgresql/16/main/postgresql.conf:
# Memory (adjust for your server size)
shared_buffers = 1GB
effective_cache_size = 3GB
work_mem = 64MB
maintenance_work_mem = 256MB
# NVMe write performance
wal_buffers = 64MB
checkpoint_completion_target = 0.9
random_page_cost = 1.1Security Hardening
- Change the default password —
ALTER USER postgres PASSWORD 'strong-random-password'; - Restrict connections — edit
pg_hba.confto allow only localhost and specific IPs - Disable remote root — set
listen_addresses = 'localhost'unless replication is needed - Enable SSL — set
ssl = onwith a valid certificate for any remote connections
Backup Strategy
# Daily logical backup (cron job)
pg_dump -U postgres -Fc mydb > /backups/mydb-$(date +%F).dump
# Point-in-time recovery with WAL archiving
archive_mode = on
archive_command = 'cp %p /backups/wal/%f'
# Restore from backup
pg_restore -U postgres -d mydb /backups/mydb-2026-04-06.dumpMySQL
Install and Configure
# Install MySQL 8
apt install -y mysql-server
# Secure the installation
mysql_secure_installation
# Set root password, remove anonymous users,
# disable remote root, remove test databaseTune InnoDB for your hardware in /etc/mysql/mysql.conf.d/mysqld.cnf:
[mysqld]
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
max_connections = 200Security Hardening
- Run mysql_secure_installation — removes test databases and anonymous users
- Create app-specific users — never use root for application connections
- Bind to localhost — set
bind-address = 127.0.0.1in the config - Enable audit logging — track who queries what for compliance
Backup Strategy
# Logical backup
mysqldump -u root -p --all-databases --single-transaction \
> /backups/mysql-all-$(date +%F).sql
# Binary backup with xtrabackup (faster for large DBs)
xtrabackup --backup --target-dir=/backups/mysql-full/
# Automated daily cron
0 2 * * * mysqldump -u backup -p'pass' mydb | gzip > /backups/mydb-$(date +\%F).sql.gzMongoDB
Install and Configure
# Add MongoDB 7 repo and install
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
gpg --dearmor -o /usr/share/keyrings/mongodb-server-7.0.gpg
apt update && apt install -y mongodb-org
# Start MongoDB
systemctl enable mongod
systemctl start mongod
# Verify
mongosh --eval "db.runCommand({ ping: 1 })"Configure WiredTiger storage engine in /etc/mongod.conf:
storage:
dbPath: /var/lib/mongodb
wiredTiger:
engineConfig:
cacheSizeGB: 1.5
net:
bindIp: 127.0.0.1
port: 27017
security:
authorization: enabledSecurity Hardening
- Enable authentication — MongoDB ships with auth disabled by default. Always enable it.
- Create admin user —
db.createUserwithuserAdminAnyDatabaserole - Bind to localhost only — unless you have a replica set on separate machines
- Disable HTTP interface — set
net.http.enabled: false
Backup Strategy
# Full database dump
mongodump --out /backups/mongo-$(date +%F)
# Restore
mongorestore /backups/mongo-2026-04-06/
# Compressed backup for cron
mongodump --archive=/backups/mongo-$(date +%F).gz --gzipReplication Basics
Each database handles replication differently, but the concept is the same: a primary server writes data and one or more replicas receive copies for redundancy and read scaling.
- PostgreSQL — streaming replication with
pg_basebackup. Primary writes WAL, replicas stream it in real time. - MySQL — binary log replication. Primary logs all changes, replicas apply them. GTID mode simplifies failover.
- MongoDB — replica sets with automatic failover. Minimum 3 nodes (or 2 data + 1 arbiter). Built-in election protocol.
For most startups and side projects, a single bare metal server with automated backups is sufficient. Add replication when you need high availability or read scaling — deploy a second RAW server and configure streaming replication.
Cost Comparison: Self-Hosted vs Managed
Self-hosting on bare metal saves 85–90% versus managed database services. You trade managed backups and dashboards for full control, better performance (no network hop between app and DB), and dramatically lower cost.
Universal Security Checklist
- Firewall — only expose ports 22, 80, and 443. Database ports should never be public.
- Strong passwords — use randomly generated credentials, not defaults
- Automatic backups — daily dumps to a separate location. Test restores monthly.
- Updates — enable unattended security updates for the database packages
- Monitoring — track connections, query latency, disk usage, and replication lag
Get Started
npx rawhq deploy7-day free trial. Dedicated bare metal in 13 seconds. Run PostgreSQL, MySQL, and MongoDB on the same server as your app for $0 extra.