Skip to content

Database Hosting — MySQL, PostgreSQL & MongoDB Guide

DodaTech Updated 2026-06-20 12 min read

In this tutorial, you'll learn about Database Hosting. We cover key concepts, practical examples, and best practices.

Database hosting deploys MySQL, PostgreSQL, and MongoDB on servers or cloud platforms to store, query, and protect application data reliably.

In this tutorial, you will learn how to install and configure MySQL, PostgreSQL, and MongoDB on Linux servers, create databases and users with proper permissions, set up automated backups, configure replication for high availability, tune performance, and secure your databases against common attacks. DodaTech uses these databases to power Doda Browser user accounts and Durga Antivirus Pro threat intelligence storage.

What You'll Learn

By the end of this guide, you will deploy MySQL, PostgreSQL, and MongoDB databases on a Linux server or cloud instance, create users with least-privilege access, configure automated backups and replication, and apply production security hardening.

Why Database Hosting Matters

Every web application depends on a database. A misconfigured database leads to data loss, security breaches, and downtime. Understanding how to host databases properly is essential for any developer deploying production applications — whether on bare-metal servers, Docker containers, or CDN-protected cloud infrastructure.

Database Hosting Learning Path

flowchart LR
  A[MySQL Setup] --> B[PostgreSQL Setup]
  B --> C[MongoDB Setup]
  C --> D[Backups & Replication]
  D --> E[Performance Tuning]
  E --> F[Security Hardening]
  F --> G{You Are Here}
  style G fill:#f90,color:#fff

MySQL — Installation and Configuration

MySQL is the world's most popular open-source relational database. It excels at structured data with complex joins and transactions.

Install MySQL on Ubuntu

# Update package list and install MySQL
sudo apt update
sudo apt install mysql-server -y

# Secure the installation
sudo mysql_secure_installation

The mysql_secure_installation script prompts you to:

  1. Set a root password (choose a strong 20+ character password)
  2. Remove anonymous users
  3. Disallow remote root login
  4. Remove the test database
  5. Reload privilege tables

Create a Database and User

This follows the least-privilege principle used in security-hardened Linux and Docker deployments.

-- Log into MySQL as root
sudo mysql

-- Create a database for your application
CREATE DATABASE app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- Create a user with a strong password
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'Str0ng!Passw0rd#2026';

-- Grant privileges on the application database only
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX ON app_db.* TO 'app_user'@'localhost';

-- Apply changes
FLUSH PRIVILEGES;

-- Verify access
SHOW GRANTS FOR 'app_user'@'localhost';

Expected output

+--------------------------------------------------------------+
| Grants for app_user@localhost                                 |
+--------------------------------------------------------------+
| GRANT USAGE ON *.* TO `app_user`@`localhost`                 |
| GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX          |
|   ON `app_db`.* TO `app_user`@`localhost`                    |
+--------------------------------------------------------------+

Configure Remote Access

Edit MySQL's config file (/etc/mysql/mysql.conf.d/mysqld.cnf):

# Change bind-address from 127.0.0.1 to the server's IP
bind-address = 0.0.0.0

# Optionally restrict to a specific IP for security
# bind-address = 203.0.113.10
sudo systemctl restart mysql

PostgreSQL — Installation and Configuration

PostgreSQL is an advanced open-source relational database known for ACID compliance, extensibility, and support for advanced data types like JSONB and arrays.

Install PostgreSQL on Ubuntu

# Install PostgreSQL
sudo apt update
sudo apt install postgresql postgresql-contrib -y

# Switch to the postgres system user
sudo -i -u postgres

Create a Database and User

# Create a new user (replace 'dbuser' with your username)
createuser --interactive
# Enter name: dbuser
# Shall the new role be a superuser? n
# Shall the new role be allowed to create databases? y

# Create a database owned by the new user
createdb app_db --owner=dbuser

# Set a password for the user
psql -c "ALTER USER dbuser WITH PASSWORD 'Str0ng!Passw0rd#2026';"

Expected output

# Connect as the new user
psql -h localhost -U dbuser -d app_db

# List databases
\l
#                                    List of databases
#    Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
# -----------+----------+----------+-------------+-------------+-----------------------
#  app_db    | dbuser   | UTF8     | en_US.UTF-8 | en_US.UTF-8 |

Configure pg_hba.conf for Remote Access

Edit /etc/<a href="/databases/postgresql/">postgresql</a>/16/main/pg_hba.conf:

# Add this line for remote access (replace 203.0.113.0/24 with your subnet)
host    app_db          dbuser          203.0.113.0/24         scram-sha-256

# Or allow from any IP (not recommended for production)
# host    app_db          dbuser          0.0.0.0/0             scram-sha-256

Then edit <a href="/databases/postgresql/">postgresql</a>.conf:

listen_addresses = 'localhost,203.0.113.10'
sudo systemctl restart postgresql

MongoDB — Installation and Configuration

MongoDB is a leading NoSQL document database that stores data in flexible, JSON-like documents. It excels at unstructured data and rapid prototyping.

Install MongoDB 7 on Ubuntu

# Import MongoDB GPG key
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
  sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor

# Add repository
echo "deb [ signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] \
  https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | \
  sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list

# Install MongoDB
sudo apt update
sudo apt install mongodb-org -y

# Start MongoDB
sudo systemctl start mongod
sudo systemctl enable mongod

Create a Database and User

// Connect to MongoDB shell
mongosh

// Switch to (or create) a database
use app_db

// Create a user with readWrite access
db.createUser({
  user: "app_user",
  pwd: "Str0ng!Passw0rd#2026",
  roles: [
    { role: "readWrite", db: "app_db" },
    { role: "dbAdmin", db: "app_db" }
  ]
});

// Verify the user can authenticate
db.auth("app_user", "Str0ng!Passw0rd#2026")

Expected output

// After creating user
{ ok: 1 }
// User "app_user" created with roles: readWrite, dbAdmin on app_db

// After authentication
1  // (1 = success, 0 = failure)

Backups and Replication

MySQL Backup with mysqldump

# Full database backup
mysqldump -u app_user -p app_db > backup-2026-06-20.sql

# Compress to save space
gzip backup-2026-06-20.sql

# Restore
gunzip < backup-2026-06-20.sql.gz | mysql -u app_user -p app_db

PostgreSQL Backup with pg_dump

# Full database backup
pg_dump -U dbuser -h localhost app_db > backup-2026-06-20.sql

# Compress with custom format (faster restore)
pg_dump -U dbuser -h localhost -Fc app_db > backup-2026-06-20.dump

# Restore from custom format
pg_restore -U dbuser -h localhost -d app_db backup-2026-06-20.dump

MongoDB Backup with mongodump

# Full database backup
mongodump --username app_user --password 'Str0ng!Passw0rd#2026' \
  --db app_db --out backup-2026-06-20/

# Restore
mongorestore --username app_user --password 'Str0ng!Passw0rd#2026' \
  --db app_db backup-2026-06-20/app_db/

Backup Comparison

Feature MySQL (mysqldump) PostgreSQL (pg_dump) MongoDB (mongodump)
Output format SQL text SQL text or custom BSON (binary JSON)
Compression Manual (gzip) Built-in (-Fc) Built-in (--gzip)
Parallel backup No Yes (-j 4) Yes (--numParallelCollections)
Selective restore File-level Table-level Collection-level

Performance Tuning

MySQL Performance Config

# /etc/mysql/mysql.conf.d/tuning.cnf
innodb_buffer_pool_size = 1G    # 70-80% of available RAM
innodb_log_file_size = 256M     # Redo log size
query_cache_type = 0            # Disable query cache (deprecated in 8.0)
max_connections = 150           # Adjust based on app needs
tmp_table_size = 64M            # Temp table size before using disk

PostgreSQL Performance Config

# /etc/postgresql/16/main/postgresql.conf
shared_buffers = 256MB          # 25% of available RAM
effective_cache_size = 1GB      # OS file cache estimation
work_mem = 16MB                  # Per-operation sort memory
maintenance_work_mem = 256MB    # VACUUM, CREATE INDEX memory
wal_buffers = 16MB              # WAL write buffer
random_page_cost = 1.1          # SSD-optimized (default 4.0 for HDD)

Expected impact

-- Before tuning: slow query
EXPLAIN ANALYZE SELECT * FROM orders WHERE status = 'pending';
-- Execution time: 8500.123 ms (Seq Scan on orders)

-- After adding index
CREATE INDEX idx_orders_status ON orders(status);

-- After tuning
EXPLAIN ANALYZE SELECT * FROM orders WHERE status = 'pending';
-- Execution time: 12.456 ms (Bitmap Index Scan on orders)

Security Hardening

Common Security Measures

Measure MySQL PostgreSQL MongoDB
Change default port port = 3307 port = 5433 port = 27018
Disable remote root Remove root remote grants Comment out local trust Remove default admin user
Enable TLS require_secure_transport = ON ssl = on net.tls.mode = requireTLS
Audit logging Audit plugin log_statement = 'ddl' Auditing (Enterprise)
Regular updates apt upgrade mysql-server apt upgrade <a href="/databases/postgresql/">postgresql</a> apt upgrade <a href="/databases/mongodb/">mongodb</a>-org

MySQL Security Script

-- Remove anonymous users
DELETE FROM mysql.user WHERE User = '';

-- Disallow root login remotely
DELETE FROM mysql.user WHERE User = 'root' AND Host != 'localhost';

-- Remove test database
DROP DATABASE IF EXISTS test;

-- Apply changes
FLUSH PRIVILEGES;

Common Errors

1. "Access denied for user 'app_user'@'localhost'"

The user does not exist or the password is incorrect. Verify with SELECT user, host FROM mysql.user; in MySQL, or \du in PostgreSQL. Recreate the user if needed.

2. "Can't connect to MySQL server on 'x.x.x.x' (111 Connection refused)"

The MySQL server is not running, or bind-address is set to 127.0.0.1. Check status with systemctl status mysql and verify bind-address in the config file.

3. PostgreSQL "FATAL: no pg_hba.conf entry for host"

The pg_hba.conf file does not have a rule allowing connections from the client's IP. Add a line like host all all 203.0.113.0/24 scram-sha-256 and reload: sudo systemctl reload <a href="/databases/postgresql/">postgresql</a>.

4. MongoDB "Authentication failed" on replica set

MongoDB requires a keyfile for replica set authentication. Generate a keyfile: openssl rand -base64 756 > /etc/<a href="/databases/mongodb/">mongodb</a>-keyfile and copy it to all replica set members with chmod 400.

5. MySQL "Table 'table_name' is marked as crashed"

The table's data file is corrupted. Repair it: REPAIR TABLE table_name; or via command line mysqlcheck -r app_db table_name. Check for disk errors if this recurs.

6. Disk Space Exhausted by Database Logs

MySQL binary logs and PostgreSQL WAL files accumulate. Set a retention policy: MySQL expire_logs_days = 7, PostgreSQL wal_keep_size = 1GB and regular pg_archivecleanup.

7. Slow Queries After Database Growth

Missing indexes cause full table scans. Use EXPLAIN to find slow queries, SHOW PROCESSLIST in MySQL or pg_stat_activity in PostgreSQL to identify running queries, and add appropriate indexes.

Practice Questions

1. What is the difference between MySQL and PostgreSQL?

MySQL is simpler and faster for basic read-heavy workloads. PostgreSQL offers more advanced features: JSONB indexing, full-text search built-in, custom data types, and better concurrency control. Choose MySQL for simplicity, PostgreSQL for data integrity and advanced features.

2. When should you use MongoDB instead of a relational database?

Use MongoDB when your data model is unstructured or evolving, you need fast prototyping, or you're storing document-like data (user profiles, blog posts, product catalogs) that doesn't require complex joins.

3. What is the purpose of a database index?

An index is a data structure (usually a B-tree) that speeds up data retrieval at the cost of slower writes. Without an index, the database must scan every row. With an index, it can jump directly to matching rows — often 100-1000x faster.

4. How do you restore a MySQL database from a backup?

Use mysql -u username -p database_name < backup.sql. For compressed backups: gunzip < backup.sql.gz | mysql -u username -p database_name.

5. Challenge: Set up streaming replication

Configure PostgreSQL streaming replication: set up a primary server with wal_level = replica, create a replication user, take a base backup with pg_basebackup, and configure a standby server with standby_mode = on and primary_conninfo pointing to the primary.

Mini Project: Production Database Hosting Setup

Deploy a database server following production best practices:

  1. Install MySQL, PostgreSQL, and MongoDB on a Linux server
  2. For each database, create a dedicated database and user for an application
  3. Configure remote access (restrict to app server IP only)
  4. Set up automated daily backups with a cron job
  5. Create a performance baseline by running sample queries before and after adding indexes
  6. Apply all security hardening measures (change ports, disable remote root, enable TLS)
  7. Test failover by stopping the database and verifying backup restore

Test each database:

# MySQL test
mysql -h localhost -u app_user -p app_db -e "SELECT 1 AS test;"
# Expected: +------+ | test | +------+ |    1 | +------+

# PostgreSQL test
psql -h localhost -U dbuser -d app_db -c "SELECT 1 AS test;"
# Expected: test  ------ 1 (1 row)

# MongoDB test
mongosh --username app_user --password 'Str0ng!Passw0rd#2026' \
  --eval "db.runCommand({ ping: 1 })"
# Expected: { ok: 1 }

# Backup test
ls -lh /backups/
# Expected: backup files exist and are non-empty

This setup mirrors how DodaTech manages Doda Browser user data in PostgreSQL and Durga Antivirus Pro threat intelligence in MongoDB.

FAQ

What is the best database for a web application?

For most web applications, PostgreSQL is the best default choice. It handles structured and semi-structured data, supports JSONB, has excellent concurrency, and is ACID-compliant. Use MySQL for WordPress or Laravel apps. Use MongoDB when you need flexible schemas and fast iteration.

How do I choose between SQL and NoSQL?

SQL databases (MySQL, PostgreSQL) enforce schemas and support complex joins and transactions. NoSQL databases (MongoDB) offer flexibility, horizontal scaling, and faster writes. Start with SQL unless your data model is inherently document-based or you need to scale writes across many servers.

What is database replication and why is it important?

Replication copies data from one database server to another. It provides high availability (if the primary fails, a replica takes over), read scaling (distribute read queries across replicas), and disaster recovery (replicas in different data centers).

How do I secure a production database?

Use strong passwords, limit network access (bind to specific IPs), disable remote root login, enable TLS for encrypted connections, create users with least-privilege access, enable audit logging, keep software updated, and take regular encrypted backups.

Should I host my own database or use a cloud service?

Self-hosted databases give you full control and lower cost at small scale. Cloud services (Amazon RDS, Cloud SQL, MongoDB Atlas) handle backups, patching, replication, and monitoring — reducing operational overhead. Start self-hosted to learn, move to managed services for production.

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro