Installing and Configuring MySQL
July 20, 2026
Most self-hosted web applications need a relational database. MySQL is the standard choice, though Debian ships MariaDB as its default MySQL-compatible server. The installation and hardening steps differ between distributions, but the end result is the same: a running database server with a secured root account, no anonymous users, no test database, and no remote root access.
Choosing Between MySQL and MariaDB
On Gentoo, you install MySQL directly from the dev-db/mysql package. On Debian, the default MySQL-compatible server is MariaDB (mariadb-server). MariaDB is a fork of MySQL that maintains wire-level compatibility — applications that work with MySQL work with MariaDB without changes.
Alpine Linux can run either. This post covers Gentoo (MySQL) and Debian (MariaDB). The SQL commands and client tools are identical between the two.
Installing the Database Server
On Gentoo
emerge -av dev-db/mysql
This installs the MySQL server and client. Gentoo's MySQL package includes the mysql command-line client, mysqld server binary, and init scripts.
On Debian
apt install -y mariadb-server
Debian's package includes the server, client, and systemd unit files. MariaDB starts automatically after installation.
On Alpine
apk add mysql mysql-client
Alpine's MySQL package is actually MariaDB under the hood.
Initializing the Data Directory
On Gentoo
After installing MySQL on Gentoo, the data directory at /var/lib/mysql needs to be initialized before the server can start. This creates the system tables that MySQL needs internally.
mysqld --initialize-insecure --user=mysql --datadir=/var/lib/mysql
The --initialize-insecure flag creates the root account without a password. This is intentional — you'll set a password in the next step. The alternative --initialize generates a random root password and prints it to the error log, which is harder to automate.
If the data directory already contains files (from a previous installation), this command does nothing.
On Debian
Debian's MariaDB package initializes the data directory automatically during installation. No manual step is needed.
On Alpine
mysql_install_db --user=mysql --datadir=/var/lib/mysql
Starting and Enabling the Service
On Gentoo
rc-update add mysql default
rc-service mysql start
On Debian
systemctl enable mariadb
systemctl start mariadb
MariaDB may already be running after installation. systemctl start is a no-op if it's already active.
On Alpine
rc-update add mariadb default
rc-service mariadb start
Verify the service is listening:
ss -lnt sport = :3306
You should see MySQL/MariaDB listening on port 3306:
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 80 0.0.0.0:3306 0.0.0.0:*
Setting the Root Password
On a fresh installation, the MySQL root account has no password. Set one immediately.
On Gentoo
Connect to MySQL via the unix socket (no password needed on a fresh install):
mysql -u root
Set the root password:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'your-secure-password-here';
FLUSH PRIVILEGES;
EXIT;
On Debian
Debian's MariaDB uses unix socket authentication for root by default — the root OS user can connect without a password via the socket. To set a traditional password:
mysql -u root
ALTER USER 'root'@'localhost' IDENTIFIED BY 'your-secure-password-here';
FLUSH PRIVILEGES;
EXIT;
Alternatively, if you want to keep unix socket auth (root OS user connects without a password, but non-root users need the password):
mysql -u root -e "SET PASSWORD FOR 'root'@'localhost' = PASSWORD('your-secure-password-here');"
Creating the Root Credential File
To avoid typing the root password on every mysql command, create a credentials file at /root/.my.cnf:
cat > /root/.my.cnf << 'EOF'
[client]
user=root
password=your-secure-password-here
EOF
chmod 600 /root/.my.cnf
The chmod 600 is critical — this file contains the root database password in plaintext. Only the root user should be able to read it.
Test that it works:
mysql -e "SELECT 1"
If this returns a result without prompting for a password, the credential file is working.
Securing the Installation
A default MySQL installation includes components that should be removed on a production server. The mysql_secure_installation script handles this interactively, but you can do it manually with SQL statements for reproducibility.
Removing Anonymous Users
Anonymous users allow anyone to connect to MySQL without a username. Remove them:
mysql -e "DELETE FROM mysql.user WHERE User='';"
mysql -e "FLUSH PRIVILEGES;"
Disabling Remote Root Login
The root account should only be accessible from localhost. Remove any root entries that allow remote connections:
mysql -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');"
mysql -e "FLUSH PRIVILEGES;"
Removing the Test Database
MySQL ships with a test database that any user can access. Remove it:
mysql -e "DROP DATABASE IF EXISTS test;"
mysql -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';"
mysql -e "FLUSH PRIVILEGES;"
All-in-One Script
For convenience, here's the full secure-installation equivalent as a single script:
mysql << 'EOF'
DELETE FROM mysql.user WHERE User='';
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%';
FLUSH PRIVILEGES;
EOF
Creating Application Databases and Users
With the server secured, create databases and users for your applications. The pattern is always the same: create the database, create a user with a strong password, and grant privileges only on that specific database.
mysql << 'EOF'
CREATE DATABASE IF NOT EXISTS myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'myapp'@'localhost' IDENTIFIED BY 'app-password-here';
GRANT ALL PRIVILEGES ON myapp.* TO 'myapp'@'localhost';
FLUSH PRIVILEGES;
EOF
Key points:
utf8mb4— use this instead ofutf8. MySQL'sutf8encoding only supports 3-byte characters, which breaks on emoji and some CJK characters.utf8mb4is the real UTF-8.'myapp'@'localhost'— restricts the user to local connections only. If the application connects from a different host, replacelocalhostwith that IP address.GRANT ALL ON myapp.*— grants full access to themyappdatabase only, not to other databases. Never grantALL ON *.*to application users.
Checking the Socket Path
Different distributions put the MySQL socket in different locations. Knowing where it is matters for application configuration files that need to specify the socket path.
mysql -e "SHOW VARIABLES LIKE 'socket';"
Typical paths:
| Distribution | Socket Path |
|---|---|
| Gentoo | /var/run/mysqld/mysqld.sock |
| Debian | /run/mysqld/mysqld.sock |
| Alpine | /run/mysqld/mysqld.sock |
Applications like PHP, Python, and Ruby can connect via this socket instead of TCP when running on the same host. Socket connections are faster and skip the TCP stack entirely.
Verifying the Installation
Run through these checks to confirm everything is working:
# Service is running
ss -lnt sport = :3306
# Root can connect
mysql -e "SELECT 1"
# No anonymous users
mysql -e "SELECT User, Host FROM mysql.user WHERE User='';"
# Should return an empty set
# No remote root
mysql -e "SELECT User, Host FROM mysql.user WHERE User='root';"
# Should only show localhost entries
# No test database
mysql -e "SHOW DATABASES;"
# Should not include 'test'
# Character set is correct
mysql -e "SHOW VARIABLES LIKE 'character_set_server';"
# Should show utf8mb4 (or latin1 on older defaults)
Setting the Default Character Set
If the server defaults to latin1 instead of utf8mb4, set the default globally. On Gentoo, create /etc/mysql/conf.d/charset.cnf:
mkdir -p /etc/mysql/conf.d
cat > /etc/mysql/conf.d/charset.cnf << 'EOF'
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
[client]
default-character-set = utf8mb4
EOF
On Debian, create /etc/mysql/mariadb.conf.d/99-charset.cnf:
cat > /etc/mysql/mariadb.conf.d/99-charset.cnf << 'EOF'
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
[client]
default-character-set = utf8mb4
EOF
Restart the service after changing the character set:
# Gentoo/Alpine
rc-service mysql restart
# Debian
systemctl restart mariadb
Summary
After completing these steps:
- MySQL (Gentoo) or MariaDB (Debian) is installed and running
- The data directory is initialized
- Root has a strong password stored in
/root/.my.cnf - Anonymous users, remote root access, and the test database are removed
- Application databases use
utf8mb4for proper Unicode support - The server listens on port 3306 and accepts connections via unix socket
This database server is now ready for applications like PostfixAdmin, Roundcube, Nextcloud, and Matomo.