Install MySQL on Fedora, start it, and every local account on the machine can log in as the MySQL root user. No password, no sudo, nothing in the log about a temporary password. That is the first thing to fix, and most guides get the reason wrong.
This guide installs MySQL Server from the Fedora repositories, locks down root, creates an application database and user, opens remote access through firewalld, tunes the server, and sets up mysqldump backups that restore cleanly. Fedora 45 moved the default from the 8.4 LTS line to MySQL 9.7, so the second half covers the 8.4 to 9.7 upgrade: what a Fedora 44 to 45 system upgrade does to a running database, the settings that stop 9.7 from starting, and how to run 8.4 on a fresh Fedora 45 install if you need to. All of it was tested in October 2026 on Fedora 45 with MySQL 9.7 and Fedora 44 with MySQL 8.4, including a real Fedora 44 to 45 upgrade with data in place.
Which MySQL version does Fedora ship?
Fedora 45 installs MySQL 9.7 when you ask for mysql-server. Fedora 44 installs MySQL 8.4. Each release also carries the other line under a versioned package name, which is the part that trips people up:
| Package | Fedora 45 | Fedora 44 |
|---|---|---|
mysql-server (default) | 9.7.2 | 8.4.10 |
| Versioned alternative | mysql8.4-server 8.4.11 | mysql9.7-server 9.7.1 |
| Older line | none | mysql8.0-server 8.0.46 |
| MariaDB | 12.3.2 | 11.8.8 |
| Config file | /etc/my.cnf.d/mysql-server.cnf | |
| Error log | /var/log/mysql/mysqld.log | |
| Service | mysqld | |
Both lines are long-term support releases. Fedora moved to 9.7 to ship the latest LTS; the reasoning is in the Fedora change proposal for MySQL 9.7. The packages conflict with each other, so one machine runs one MySQL. MariaDB is a separate fork with its own MariaDB on Fedora guide; it conflicts with MySQL too.
Install MySQL Server
Workstation, Server and Cloud editions all use the same command:
sudo dnf -y install mysql-server
Ten packages on Fedora 45, including the client, the error message files and mysql-selinux, which keeps the daemon working with SELinux in enforcing mode:
Package Arch Version Repository Size
Installing:
mysql-server x86_64 0:9.7.2-1.fc45 fedora 125.5 MiB
Installing dependencies:
mariadb-connector-c-config noarch 0:3.4.9-3.fc45 fedora 26.4 KiB
mecab x86_64 0:0.996-12.fc45 fedora 1.2 MiB
mysql x86_64 0:9.7.2-1.fc45 fedora 52.0 MiB
mysql-common noarch 0:9.7.2-1.fc45 fedora 452.0 KiB
mysql-errmsg noarch 0:9.7.2-1.fc45 fedora 11.2 MiB
mysql-selinux noarch 0:1.0.18-2.fc45 fedora 50.1 KiB
policycoreutils-python-utils noarch 0:3.11-2.fc45 fedora 94.5 KiB
protobuf-cpp x86_64 0:6.33.5-7.fc45 fedora 4.4 MiB
protobuf-lite x86_64 0:6.33.5-7.fc45 fedora 890.3 KiB
Transaction Summary:
Installing: 10 packages
Total size of inbound packages is 27 MiB. Need to download 27 MiB.
Enable the service and start it now:
sudo systemctl enable --now mysqld
The first start runs mysql-prepare-db-dir, which initializes /var/lib/mysql. Check the result:
systemctl status mysqld --no-pager
Look for Server is operational in the status line:
● mysqld.service - MySQL 9.7 database server
Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; preset: disabled)
Drop-In: /usr/lib/systemd/system/service.d
└─10-timeout-abort.conf
Active: active (running) since Mon 2026-10-12 10:43:28 UTC; 255ms ago
Invocation: 1a9f40cbd4ce45378e7dc1bb3a1c0aaf
Process: 11374 ExecStartPre=/usr/libexec/mysql-check-socket (code=exited, status=0/SUCCESS)
Process: 11396 ExecStartPre=/usr/libexec/mysql-prepare-db-dir mysqld.service (code=exited, status=0/SUCCESS)
Main PID: 11466 (mysqld)
Status: "Server is operational"
Tasks: 36 (limit: 4593)
Memory: 468.9M (peak: 484M)
CPU: 2.139s
CGroup: /system.slice/mysqld.service
└─11466 /usr/libexec/mysqld --basedir=/usr
Oct 12 10:43:23 f45-01 systemd[1]: Starting mysqld.service - MySQL 9.7 database server...
Oct 12 10:43:23 f45-01 mysql-prepare-db-dir[11396]: Initializing MySQL database
Oct 12 10:43:28 f45-01 systemd[1]: Started mysqld.service - MySQL 9.7 database server.
Client and server report the same build:
mysql --version; mysqld --version
“Source distribution” means Fedora built it from the upstream source rather than repackaging the Oracle RPM:
mysql Ver 9.7.2 for Linux on x86_64 (Source distribution)
/usr/libexec/mysqld Ver 9.7.2 for Linux on x86_64 (Source distribution)
Root starts with an empty password
The Fedora package does not generate a temporary password and does not set up socket authentication for root. The root account uses caching_sha2_password with an empty password:
sudo mysql -e "SELECT user, host, plugin, authentication_string = \"\" AS empty_pw FROM mysql.user"
The 1 in the last column is the problem:
user host plugin empty_pw
mysql.infoschema localhost caching_sha2_password 0
mysql.session localhost caching_sha2_password 0
mysql.sys localhost caching_sha2_password 0
root localhost caching_sha2_password 1
So sudo isn’t what lets you in. Any local user can connect as root, over the socket or over TCP to 127.0.0.1. Here an ordinary account with no special rights does exactly that on Fedora 45:

Fedora 44 with MySQL 8.4 behaves the same way. Two other things are missing that older guides assume: there is no validate_password component loaded, so MySQL accepts any password you give it, and there is no test database or anonymous user to clean up. The fresh server holds only the system schemas:
sudo mysql -e "SHOW DATABASES"
Four schemas, all internal. This one is a fresh install on Fedora 45 Workstation:
Database
information_schema
mysql
performance_schema
sys
Set the root password
Put the values the rest of this guide reuses into shell variables. read -s keeps the passwords out of your shell history and off the screen:
export APP_DB=appdb APP_USER=appuser APP_NET="10.0.1.%"
read -rsp "MySQL root password: " MYSQL_ROOT_PW; echo
read -rsp "App user password: " APP_USER_PW; echo
Pick strong passwords anyway. Nothing on the server will reject a weak one. Now set the root password:
sudo mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PW}'"
From this point a password is required for root, and that includes sudo mysql, which is refused now:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
Typing -p every time gets old, and putting the password on the command line triggers a warning and lands in ps output. Store it once with mysql_config_editor, which writes an obfuscated ~/.mylogin.cnf readable only by you:
mysql_config_editor set --login-path=root --user=root --password
It prompts for the password once. Check what it stored, which never shows the password itself:
mysql_config_editor print --all
The [root] login path holds the user and a masked password:
[root]
user = "root"
password = *****
Every admin command below uses --login-path=root instead of a password:
mysql --login-path=root -e "SELECT CURRENT_USER()"
No prompt and no warning:
CURRENT_USER()
root@localhost
Optional: a passwordless admin account tied to your Linux login
The auth_socket plugin ships in the Fedora build but is not loaded. It authenticates a MySQL account by the Linux user on the other end of the socket, the way Ubuntu and Debian handle root. Load it and create an admin account matching your login name. The example uses josphat; replace it with the output of whoami:
mysql --login-path=root -e "INSTALL PLUGIN auth_socket SONAME 'auth_socket.so'; CREATE USER 'josphat'@'localhost' IDENTIFIED WITH auth_socket; GRANT ALL PRIVILEGES ON *.* TO 'josphat'@'localhost' WITH GRANT OPTION"
Logged in as josphat, a bare mysql now works:
USER() CURRENT_USER()
josphat@localhost josphat@localhost
Any other Linux account asking for that MySQL user is turned away with error 1698, password or not:
deploy
ERROR 1698 (28000): Access denied for user 'josphat'@'localhost'
INSTALL PLUGIN is persistent, so the plugin survives restarts.
Create a database and an application user
Applications should never connect as root. The server default character set is already utf8mb4 with the utf8mb4_0900_ai_ci collation, so a plain CREATE DATABASE is correct; older guides that force utf8mb4_unicode_ci pick an older, less accurate collation:
mysql --login-path=root -e "CREATE DATABASE ${APP_DB}; CREATE USER '${APP_USER}'@'localhost' IDENTIFIED BY '${APP_USER_PW}'; GRANT ALL PRIVILEGES ON ${APP_DB}.* TO '${APP_USER}'@'localhost'"
Connect as the new user and write some data to prove the grant:
mysql -u"${APP_USER}" -p"${APP_USER_PW}" "${APP_DB}" -e "CREATE TABLE notes (id INT AUTO_INCREMENT PRIMARY KEY, body VARCHAR(200), created TIMESTAMP DEFAULT CURRENT_TIMESTAMP); INSERT INTO notes (body) VALUES (\"first row\"), (\"second row\"); SELECT id, body FROM notes"
The warning about a password on the command line is expected in a test like this; applications pass it through their own config:
mysql: [Warning] Using a password on the command line interface can be insecure.
id body
1 first row
2 second row
To manage databases from a GUI instead, MySQL Workbench and DBeaver both run on Fedora and connect with the same accounts.
Allow remote connections
MySQL listens on all interfaces by default, on 3306 for the classic protocol and 33060 for the X Protocol:
sudo ss -tlnp | grep mysqld
Both sockets belong to mysqld:
LISTEN 0 4096 *:3306 *:* users:(("mysqld",pid=11466,fd=22))
LISTEN 0 70 *:33060 *:* users:(("mysqld",pid=11466,fd=19))
MySQL accounts are keyed on user and host, so a remote client needs its own account. APP_NET holds a wildcard for the application subnet:
mysql --login-path=root -e "CREATE USER '${APP_USER}'@'${APP_NET}' IDENTIFIED BY '${APP_USER_PW}'; GRANT ALL PRIVILEGES ON ${APP_DB}.* TO '${APP_USER}'@'${APP_NET}'; SELECT user, host FROM mysql.user WHERE user = '${APP_USER}'"
The same user now exists twice, once per allowed origin:
user host
appuser 10.0.1.%
appuser localhost
Check which firewalld zone you are in before adding anything. A Workstation installed from the ISO uses the FedoraWorkstation zone, which already opens TCP and UDP ports 1025 to 65535. On that zone MySQL is reachable from the whole network the moment it starts, and a rule for 3306 restricts nothing. We confirmed it from a second VM: under FedoraWorkstation the connection to 3306 opened, under public it was rejected with No route to host:
firewall-cmd --get-default-zone; sudo firewall-cmd --list-ports
This is the output that should worry you on a database host:
FedoraWorkstation
1025-65535/tcp 1025-65535/udp
Move the machine to the public zone, which allows only ssh, mdns and dhcpv6-client and no port ranges, then open MySQL deliberately. On a machine you also use as a desktop, this closes the high port range for tools such as KDE Connect too, so re-add what you need by service:
sudo firewall-cmd --set-default-zone=public
Fedora Server uses the FedoraServer zone, which allows ssh, cockpit and dhcpv6-client and no port ranges. Cloud images do not ship firewalld at all, so the lab installed it first. Then allow MySQL from the application subnet only, rather than the whole network:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.1.0/24" service name="mysql" accept'
sudo firewall-cmd --reload
Confirm the rule is active:
sudo firewall-cmd --list-rich-rules
One rule, scoped to the subnet:
rule family="ipv4" source address="10.0.1.0/24" service name="mysql" accept
Zones and rich rules are covered in more depth in the firewalld guide for Fedora.
Tune the server
The defaults suit a laptop, not a database host. Check them first:
mysql --login-path=root -e "SELECT @@log_bin, @@binlog_expire_logs_seconds, @@innodb_buffer_pool_size, @@innodb_redo_log_capacity, @@max_connections"
A 128 MiB buffer pool, a 100 MiB redo log, binary logging on, and binlogs kept for 30 days:
@@log_bin @@binlog_expire_logs_seconds @@innodb_buffer_pool_size @@innodb_redo_log_capacity @@max_connections
1 2592000 134217728 104857600 151
Keep your changes in their own drop-in file. /etc/my.cnf.d/mysql-server.cnf belongs to the package, and a separate file is easier to carry between servers:
sudo vim /etc/my.cnf.d/99-tuning.cnf
This is the file used on the 4 GB test VM. Size innodb_buffer_pool_size to 50 to 70 percent of RAM on a dedicated database host:
[mysqld]
innodb_buffer_pool_size = 2G
innodb_redo_log_capacity = 1G
max_connections = 200
binlog_expire_logs_seconds = 604800
Watch the option names. Configs copied from older guides use innodb_log_file_size and expire_logs_days. expire_logs_days was already removed in 8.4 and innodb_log_file_size is gone in 9.7. An unknown option is fatal: mysqld refuses to start at all. This is what the old config did on Fedora 45:

The replacements are innodb_redo_log_capacity and binlog_expire_logs_seconds, as in the file above. Restart and check the values took:
sudo systemctl restart mysqld
mysql --login-path=root -e "SELECT @@log_bin, @@binlog_expire_logs_seconds, @@innodb_buffer_pool_size/1024/1024/1024 AS pool_gib, @@innodb_redo_log_capacity/1024/1024/1024 AS redo_gib, @@max_connections"
2 GiB pool, 1 GiB redo, seven days of binlogs:
@@log_bin @@binlog_expire_logs_seconds pool_gib redo_gib @@max_connections
1 604800 2.000000000000 1.000000000000 200
Back up with mysqldump
MySQL 9.7 turns GTIDs on by default, and the Fedora config does not change that. It matters for backups:
mysql --login-path=root -e "SELECT @@gtid_mode, @@enforce_gtid_consistency"
Both are ON:
@@gtid_mode @@enforce_gtid_consistency
ON ON
A single-database dump taken the usual way embeds the GTID set of the server. Restoring it into another database on the same server then fails with error 3546, because those GTIDs were already executed there. For single-database dumps you plan to restore anywhere other than a fresh replica, add --set-gtid-purged=OFF:
mysqldump --login-path=root --single-transaction --routines --triggers --events --set-gtid-purged=OFF "${APP_DB}" | gzip > "${APP_DB}-$(date +%F).sql.gz"
Test the restore into a scratch database. A backup you have never restored is a guess:
mysql --login-path=root -e "CREATE DATABASE appdb_restore"
gunzip < "${APP_DB}-$(date +%F).sql.gz" | mysql --login-path=root appdb_restore
mysql --login-path=root -e "SELECT id, body FROM appdb_restore.notes"
Both rows came back:
id body
1 first row
2 second row
For a full-server backup that can seed a replica or a point-in-time recovery, dump everything and record the binlog position:
mysqldump --login-path=root --all-databases --single-transaction --source-data=2 --routines --events --triggers | gzip > all-$(date +%F).sql.gz
mysqlpump, which older guides recommend for big databases, is no longer shipped. MySQL Shell, with its parallel dump utilities, is not in the Fedora repositories either, so large datasets need the MySQL Shell build from Oracle or a physical backup tool.
Upgrade MySQL 8.4 to 9.7
A Fedora 44 machine running mysql-server gets MySQL 9.7 the moment it upgrades to Fedora 45. The package name stays the same, so the release upgrade replaces 8.4 with 9.7 like any other package. This is from the real Fedora 44 to 45 upgrade transaction on the test server:
mysql x86_64 0:9.7.2-1.fc45 fedora 52.0 MiB
replacing mysql x86_64 0:8.4.10-1.fc44 updates 51.9 MiB
mysql-common noarch 0:9.7.2-1.fc45 fedora 452.0 KiB
replacing mysql-common noarch 0:8.4.10-1.fc44 updates 444.8 KiB
mysql-errmsg noarch 0:9.7.2-1.fc45 fedora 11.2 MiB
replacing mysql-errmsg noarch 0:8.4.10-1.fc44 updates 10.5 MiB
mysql-selinux noarch 0:1.0.18-2.fc45 fedora 50.1 KiB
replacing mysql-selinux noarch 0:1.0.14-3.fc44 fedora 49.9 KiB
mysql-server x86_64 0:9.7.2-1.fc45 fedora 125.5 MiB
replacing mysql-server x86_64 0:8.4.10-1.fc44 updates 114.5 MiB
MySQL supports a direct upgrade from one LTS line to the next, and the server upgrades the data dictionary itself on first start. There is no mysql_upgrade step anymore. What can stop it are settings and accounts that 9.7 no longer supports. Check two things on 8.4 before you upgrade.
First, accounts still on the old mysql_native_password plugin. The server side of that plugin was removed in the 9.x series, so those accounts can’t log in after the upgrade:
mysql --login-path=root -e "SELECT user, host, plugin FROM mysql.user WHERE plugin = 'mysql_native_password'"
The test server had one, created for a legacy client:
user host plugin
legacy localhost mysql_native_password
Second, config files that still reference options 9.7 rejects. That covers the legacy plugin switch and the InnoDB and binlog options older guides, including earlier versions of this one, told people to set. expire_logs_days is already fatal on 8.4; innodb_log_file_size is only deprecated there and becomes fatal on 9.7:
grep -rnE "mysql_native_password|innodb_log_file_size|innodb_log_files_in_group|expire_logs_days|replica_parallel_type" /etc/my.cnf /etc/my.cnf.d/
On the test server it turned up the drop-in that enabled the legacy plugin:
/etc/my.cnf.d/legacy.cnf:2:mysql_native_password = ON
Skip these checks and the upgrade half succeeds, which is the worst outcome. On a copy of the same server, a straight package swap to 9.7 upgraded the data dictionary and system tables, then hit the leftover option and aborted. The data is now in 9.7 format, so going back to 8.4 means restoring from a dump:

Fix both before the upgrade. Move each account to caching_sha2_password; ALTER USER needs the password in plain text, so supply the one the client already uses, or the client will stop working. Then remove or correct the flagged config lines and restart 8.4 to confirm it still starts. On the test server that meant the legacy account and legacy.cnf:
mysql --login-path=root -e "ALTER USER 'legacy'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'the-existing-client-password'"
sudo rm /etc/my.cnf.d/legacy.cnf
sudo systemctl restart mysqld
Old clients that only speak mysql_native_password need updating; every current connector supports caching_sha2_password. Then take a full dump, since it is the only way back to 8.4:
mysqldump --login-path=root --all-databases --single-transaction --routines --events --triggers | gzip > pre-upgrade-$(date +%F).sql.gz
With that done, the Fedora upgrade went through cleanly. On the first boot into Fedora 45, mysqld upgraded the data to 9.7 on its own and came up running with the 8.4 data intact. The prompt still says f44-01 because that was the hostname before the upgrade; the converted legacy account also logged in afterwards:

Note gtid_mode in that output. It ran with GTIDs off on 8.4 and came up with them on after the upgrade, because 9.7 changed the default. enforce_gtid_consistency flips to ON as well, and it rejects statements that are unsafe for GTID-based replication. If you replicate by binlog file and position, or want 8.4 behaviour, set both explicitly in your drop-in before upgrading. To stay on Fedora 44 but move to 9.7 now, the same checks apply. The swap removes the old package’s service enablement, so enable mysqld again afterwards:
sudo dnf -y swap mysql-server mysql9.7-server
sudo systemctl enable --now mysqld
The swap transaction prints Removed '/etc/systemd/system/multi-user.target.wants/mysqld.service'; skip the enable and the server keeps working until the next reboot, then stays down.
Stay on MySQL 8.4 on Fedora 45
On a fresh Fedora 45 machine, install the versioned package instead of mysql-server:
sudo dnf install mysql8.4-server
It resolves to the 8.4 packages from the main Fedora repository:
Package Arch Version Repository Size
Installing:
mysql8.4-server x86_64 0:8.4.11-1.fc45 fedora 114.4 MiB
Installing dependencies:
mecab x86_64 0:0.996-12.fc45 fedora 1.2 MiB
mysql-selinux noarch 0:1.0.18-2.fc45 fedora 50.1 KiB
mysql8.4 x86_64 0:8.4.11-1.fc45 fedora 51.9 MiB
mysql8.4-common noarch 0:8.4.11-1.fc45 fedora 444.8 KiB
mysql8.4-errmsg noarch 0:8.4.11-1.fc45 fedora 10.5 MiB
protobuf-lite x86_64 0:6.33.5-7.fc45 fedora 890.3 KiB
Where 9.7 is already installed, the two conflict and dnf stops. MySQL does not support downgrading a data directory, so a server that has started on 9.7 stays on 9.7 unless you restore an 8.4 dump into a fresh 8.4 install.
MySQL errors seen in testing
ERROR 1045 (28000): Access denied for user ‘root’@’localhost’ (using password: NO)
Root has a password now and the client sent none. On Fedora this includes sudo mysql, because root never used socket authentication. Use mysql --login-path=root or mysql -uroot -p.
ERROR 1524 (HY000): Plugin ‘mysql_native_password’ is not loaded
Seen in two places on MySQL 9.7: when creating an account IDENTIFIED WITH mysql_native_password, and when an account carried over from 8.4 tries to log in. The error log also flags the second case at startup with Nobody can currently login using this account. Fix the account with ALTER USER ... IDENTIFIED WITH caching_sha2_password BY '...'.
[ERROR] [MY-000067] [Server] unknown variable
An option in /etc/my.cnf or /etc/my.cnf.d/ no longer exists. In testing that meant innodb_log_file_size, expire_logs_days and mysql_native_password=ON. systemctl only says the control process failed, so read the last lines of /var/log/mysql/mysqld.log, which name the option.
ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed
A dump taken with GTIDs on is being restored into the same server, or one that already executed those transactions. This is the exact error from the first restore test:
ERROR 3546 (HY000) at line 24: @@GLOBAL.GTID_PURGED cannot be changed: the added gtid set must not overlap with @@GLOBAL.GTID_EXECUTED
Re-take the dump with --set-gtid-purged=OFF.
ERROR 1698 (28000): Access denied for user ‘josphat’@’localhost’
The account uses auth_socket and the connecting Linux user is a different one. That is the plugin doing its job. Connect from the matching login, or give that person their own account. For a full PHP and web stack on top of this server, the LAMP stack on Fedora and phpMyAdmin on Fedora guides pick up from here.
sudo firewall-cmd –permanent –add-rich-rule ‘rule family=”ipv4″ service name=”mysql” source address=”10.1.1.0/24″ accept’
can i also set “source address=”0.0.0.0/0” here..??
or is this Dangerous?
installing is not a issue, but actually connecting to a MySQL database is a different story, nor matter what you do, you will always get “Access denied for user@localhost using password (YES)” …
This could be password issue. We’ve tested and it works