How to Install MySQL 8.0 on Debian 12 and 11

Commands to Install MySQL 8.0 on Debian 12 and 11 Linux using the command line terminal with the MySQL official APT repository.

Last updatedAuthorJoshua JamesRead time8 minGuide typeDebian

MySQL 8.0 on Debian is now a legacy installation path: Oracle’s MySQL 8.0 release notes mark 8.0.46 as the end-of-life release in April 2026, but the MySQL APT repository still publishes 8.0 packages for Debian 12 (Bookworm) and Debian 11 (Bullseye). Use these steps when an application still requires the 8.0 branch, and plan a tested move to MySQL 8.4 LTS or MariaDB for new deployments.

Debian 13 (Trixie) does not have a mysql-8.0 component in Oracle’s Debian repository. Trixie users should install Oracle’s MySQL 8.4 LTS packages or use Debian’s default MariaDB packages instead. The 8.0 commands stay scoped to Debian 12 and Debian 11 so APT does not silently resolve a different branch.

Install MySQL 8.0 on Debian 12 or 11

Start by matching your Debian release to the package source. Oracle’s current supported-platform list points new Debian 13 and Debian 12 users toward current MySQL LTS releases, while MySQL 8.0 remains useful only for compatibility-bound systems that cannot move yet.

Debian ReleaseMySQL 8.0 Repository StateValidated CandidateRecommendation
Debian 13 (Trixie)No mysql-8.0 componentNot availableUse MySQL 8.4 LTS or MariaDB
Debian 12 (Bookworm)Oracle mysql-8.0 component available8.0.46-1debian12Use only for MySQL 8.0 compatibility
Debian 11 (Bullseye)Oracle mysql-8.0 component available8.0.37-1debian11Legacy maintenance path only

Do not install MySQL 8.0 on a server that already runs MariaDB or another MySQL-compatible fork unless you have a tested migration plan and verified backups. Oracle’s MySQL packages conflict with MariaDB packages, and replacing a live database server is a maintenance-window task, not a routine package install.

Oracle documents the repository family in the MySQL APT repository guide, and the current platform matrix is listed on Oracle’s MySQL supported platforms page. Debian’s default package sources do not ship Oracle MySQL; they ship MariaDB as the default MySQL-compatible server.

Use one Oracle MySQL source path. Do not configure both extrepo and the manual source on the same system, because duplicate MySQL APT sources can create confusing candidates or signature-path conflicts. The manual DEB822 source keeps the Debian release and MySQL branch guard visible before APT refreshes metadata.

Refresh Debian Packages

Refresh APT before adding a new vendor source so dependency resolution uses current Debian metadata.

sudo apt update
sudo apt upgrade

These commands use sudo. If your user cannot run administrative commands, configure sudo access before continuing.

Install Repository Prerequisites

Install the tools needed to download the signing key, convert it into an APT keyring, and create the repository file. Minimal Debian systems often lack curl and gpg, so install them explicitly.

sudo apt install -y ca-certificates curl gpg

Import the MySQL APT Signing Key

Import MySQL’s current APT signing key and store it as a dedicated keyring. The curl command guide explains the download flags if you want a deeper look at the command.

curl -fsSL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xb7b3b788a8d3785c" | sudo gpg --dearmor --yes -o /usr/share/keyrings/mysql.gpg

Verify the key identity before trusting packages from the repository.

gpg --show-keys --with-fingerprint /usr/share/keyrings/mysql.gpg

Expected key identity:

pub   rsa4096 2023-10-23 [SC] [expires: 2027-10-23]
      BCA4 3417 C3B4 85DD 128E  C6D4 B7B3 B788 A8D3 785C
uid                      MySQL Release Engineering <mysql-build@oss.oracle.com>

Create the MySQL 8.0 APT Source

Create a DEB822 source file that only enables the MySQL 8.0 and tools components for standard amd64 Debian systems. The release guard stops the command on Debian 13 and any other unsupported codename before it writes a source file.

(
  . /etc/os-release
  arch=$(dpkg --print-architecture)
  case "$VERSION_CODENAME" in
    bookworm|bullseye) ;;
    *)
      printf 'Oracle does not publish MySQL 8.0 packages for Debian %s. Use MySQL 8.4 LTS or MariaDB instead.\n' "$VERSION_CODENAME"
      exit 1
      ;;
  esac
  case "$arch" in
    amd64) ;;
    *)
      printf 'This MySQL 8.0 source block was validated for amd64, not %s.\n' "$arch"
      exit 1
      ;;
  esac

  printf '%s\n' \
    'Types: deb' \
    'URIs: https://repo.mysql.com/apt/debian' \
    "Suites: $VERSION_CODENAME" \
    'Components: mysql-8.0 mysql-tools' \
    "Architectures: $arch" \
    'Signed-By: /usr/share/keyrings/mysql.gpg' | sudo tee /etc/apt/sources.list.d/mysql.sources > /dev/null
)

Confirm that the source file uses your Debian codename and the mysql-8.0 component.

cat /etc/apt/sources.list.d/mysql.sources

Debian 12 example:

Types: deb
URIs: https://repo.mysql.com/apt/debian
Suites: bookworm
Components: mysql-8.0 mysql-tools
Architectures: amd64
Signed-By: /usr/share/keyrings/mysql.gpg

Debian 11 should show Suites: bullseye. If a file shows Suites: trixie, remove it and use a current MySQL 8.4 or MariaDB path instead.

Confirm the MySQL 8.0 Candidate

Refresh APT, then check which package source owns mysql-server. With the MySQL 8.0 source enabled, APT resolves mysql-server to Oracle’s MySQL Community packages.

sudo apt update
apt-cache policy mysql-server

Relevant Debian 12 output:

mysql-server:
  Installed: (none)
  Candidate: 8.0.46-1debian12
  Version table:
     8.0.46-1debian12 500
        500 https://repo.mysql.com/apt/debian bookworm/mysql-8.0 amd64 Packages

Debian 11 should show 8.0.37-1debian11 from bullseye/mysql-8.0. If APT shows MariaDB, Debian’s default-mysql-server, or no candidate, fix the repository file before installing.

Install MySQL 8.0 Server

Install the standard mysql-server package after the candidate points to Oracle’s mysql-8.0 component.

sudo apt install mysql-server

The MySQL Community package can prompt for a root password and an authentication plugin. Choose a strong root password and keep caching_sha2_password unless a legacy application is known to require mysql_native_password. Store the password in your normal secrets workflow.

Verify and Start Using MySQL 8.0

Check the MySQL Service and Version

The Oracle package installs a mysql systemd service and normally starts it automatically. Check the installed client version and service state.

mysql --version
systemctl is-active mysql
systemctl is-enabled mysql

Expected output pattern:

mysql  Ver 8.0.x for Linux on x86_64 (MySQL Community Server - GPL)
active
enabled

If the service is not running, start it and enable it at boot.

sudo systemctl enable --now mysql

Connect to MySQL Locally

Use the root password created during installation to run a simple version query.

mysql -u root -p -e "SELECT VERSION();"

Expected output pattern:

VERSION()
8.0.x

Create a Database and Application User

A normal application should not connect as the MySQL root account. Create a database and a dedicated local user, then grant that user access only to the database it needs.

mysql -u root -p
CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'replace_with_a_strong_password';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Replace the database name, user name, and password with values that match your application. Test the new account before wiring it into an application config file.

mysql -u appuser -p appdb -e "SHOW TABLES;"

Secure MySQL 8.0 After Installation

Run the MySQL Security Helper

Run MySQL’s bundled security helper after the service starts. It reviews common weak defaults such as anonymous users, remote root login, the test database, and privilege-table reloads.

sudo mysql_secure_installation

For a new server, the usual secure choices are to keep or set a strong root password, remove anonymous users, disallow remote root login, remove the test database, and reload privilege tables. The helper is interactive, so read each prompt instead of pasting a fixed answer sequence from an old tutorial.

Keep MySQL Local Unless Remote Access Is Required

MySQL should stay reachable only from localhost unless an application on another host must connect directly. For many web stacks, the safer design is to keep the database local to the application server or connect through a private network, VPN, or SSH tunnel.

sudo ss -ltnp | grep ':3306' || echo 'No MySQL TCP listener found on port 3306.'

A localhost-only listener commonly appears as 127.0.0.1:3306 or [::1]:3306. Do not expose 3306/tcp to the internet.

Allow Remote Application Access When Needed

If a separate application server must connect, change MySQL’s bind address deliberately, restrict the firewall to the application server IP, and create a MySQL account scoped to that host. Use 0.0.0.0 only when a firewall or private network limits who can reach port 3306/tcp.

printf '%s\n' '[mysqld]' 'bind-address = 0.0.0.0' | sudo tee /etc/mysql/mysql.conf.d/99-remote-bind.cnf > /dev/null
sudo systemctl restart mysql
sudo ss -ltnp | grep ':3306'

If you use UFW on Debian, allow only the trusted application host. Replace 192.0.2.50 with the real private IP address of your application server.

sudo ufw allow from 192.0.2.50 to any port 3306 proto tcp

Create a MySQL user that matches the remote host instead of allowing broad host patterns.

CREATE USER 'appuser'@'192.0.2.50' IDENTIFIED BY 'replace_with_a_strong_password';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'192.0.2.50';
FLUSH PRIVILEGES;

Rollback remote access by removing /etc/mysql/mysql.conf.d/99-remote-bind.cnf, restarting MySQL, and deleting the UFW rule created for port 3306/tcp. Keep the database closed until a specific application host needs direct access.

Update MySQL 8.0 Packages

APT manages MySQL packages after the Oracle source is configured. Because MySQL 8.0 is past its support window, updates should be treated as final branch maintenance only, not ongoing feature or long-term security coverage. Schedule package updates for a maintenance window because MySQL server package upgrades can restart the service.

sudo apt update
sudo apt install mysql-server

Run the candidate check again when planning a branch change. A MySQL 8.0-to-8.4 move is a database upgrade and needs backups, application compatibility checks, and a maintenance window.

apt-cache policy mysql-server

Remove MySQL 8.0 from Debian

Back Up Databases Before Removal

Export databases before removing server packages. The command prompts for the MySQL root password and writes a dated SQL dump in your home directory.

mysqldump --all-databases --single-transaction --routines --triggers -u root -p > ~/mysql-8-0-backup-$(date +%F).sql

Stop and Purge MySQL Packages

Stop the service, then purge the Oracle MySQL packages installed by the repository path.

sudo systemctl stop mysql
sudo apt purge mysql-server mysql-client mysql-community-server mysql-community-client mysql-community-server-core mysql-community-client-core mysql-community-client-plugins mysql-common

Check for remaining installed MySQL packages before cleaning dependencies or data directories.

dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n' 'mysql*' 2>/dev/null | grep '^ii' || echo 'No installed MySQL packages remain.'

Preview autoremovable packages before deleting dependencies on a reused server.

sudo apt autoremove --purge --dry-run

If the preview lists only MySQL-related packages you no longer need, run the cleanup.

sudo apt autoremove --purge

Remove the Oracle MySQL APT Source

Remove the source file created during installation, then remove the keyring only when no remaining APT source references it. Refresh APT afterward so Oracle’s repository no longer contributes candidates.

sudo rm -f /etc/apt/sources.list.d/mysql.sources
remaining_mysql_key_refs=$(find /etc/apt/sources.list /etc/apt/sources.list.d -type f -print 2>/dev/null | xargs -r grep -lF '/usr/share/keyrings/mysql.gpg' 2>/dev/null || true)
if [ -z "$remaining_mysql_key_refs" ]; then
  sudo rm -f /usr/share/keyrings/mysql.gpg
else
  printf 'Keeping /usr/share/keyrings/mysql.gpg because another APT source still references it:\n%s\n' "$remaining_mysql_key_refs"
fi
sudo apt update
apt-cache policy mysql-server

After source cleanup, apt-cache policy should no longer list repo.mysql.com. If an older extrepo-based setup is still present, remove that source as well before rechecking.

if command -v extrepo >/dev/null 2>&1; then
  sudo extrepo disable mysql-8.0 || true
fi
sudo rm -f /etc/apt/sources.list.d/extrepo_mysql-8.0.sources /var/lib/extrepo/keys/mysql-8.0.*
sudo apt update

Delete MySQL Data Files Only When Intended

The cleanup command permanently deletes MySQL databases, logs, and configuration. Do not run it unless your backup is verified and no remaining MySQL-compatible server uses these paths.

sudo rm -rf /var/lib/mysql /var/log/mysql /etc/mysql

Troubleshoot MySQL 8.0 on Debian

Fix NO_PUBKEY or EXPKEYSIG for B7B3B788A8D3785C

If sudo apt update reports NO_PUBKEY, EXPKEYSIG, or an invalid signature for B7B3B788A8D3785C, refresh the MySQL keyring and run APT again.

curl -fsSL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xb7b3b788a8d3785c" | sudo gpg --dearmor --yes -o /usr/share/keyrings/mysql.gpg
sudo apt update

If the error continues, confirm that Signed-By: /usr/share/keyrings/mysql.gpg appears in /etc/apt/sources.list.d/mysql.sources and that the fingerprint matches the expected MySQL key identity.

Fix Package Not Found or the Wrong MySQL Branch

Check the Debian codename, repository file, and final candidate when APT cannot find MySQL 8.0 or resolves a different branch.

. /etc/os-release
printf '%s\n' "$VERSION_CODENAME"
cat /etc/apt/sources.list.d/mysql.sources
apt-cache policy mysql-server

Debian 12 must use Suites: bookworm, and Debian 11 must use Suites: bullseye. Debian 13 cannot use mysql-8.0; Oracle’s Trixie repository publishes MySQL 8.4 LTS and newer branches instead.

Fix mysql_secure_installation Command Not Found

Oracle’s MySQL 8.0 packages provide mysql_secure_installation through mysql-community-server-core. If the command is missing, verify that the Oracle server package is installed from the intended source. On Debian 13 (Trixie), use a supported MySQL 8.4 LTS or MariaDB path first; Oracle does not publish a Trixie mysql-8.0 component.

dpkg -l 'mysql-server*' 'mysql-community-server*' | grep '^ii'
dpkg -L mysql-community-server-core | grep '/mysql_secure_installation$'

If those checks fail, repair the repository source, refresh APT, and reinstall the server metapackage.

sudo apt update
sudo apt install mysql-server

Handle MariaDB or Other MySQL-Compatible Conflicts

APT may refuse the transaction or plan removals if MariaDB is already installed. Inspect the installed package set and simulate the MySQL install before making changes.

dpkg -l 'mariadb*' | grep '^ii' || echo 'No installed MariaDB packages found.'
apt-get -s install mysql-server

If the simulation lists MariaDB removals, held packages, or dependency conflicts, stop and plan a migration. Export databases, test restores, and confirm application compatibility before replacing server packages.

Fix Access Denied or Authentication Plugin Errors

Access denied errors usually mean the wrong user, password, host match, or authentication plugin was used. Start by checking the exact account and host entries from an administrative session.

mysql -u root -p -e "SELECT user, host, plugin FROM mysql.user ORDER BY user, host;"

For new applications, keep caching_sha2_password and update the application connector if it cannot authenticate. Use mysql_native_password only for a verified legacy application that cannot support the default plugin.

ALTER USER 'appuser'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'replace_with_a_strong_password';
FLUSH PRIVILEGES;

If a legacy application truly requires the old plugin, change only that application user.

ALTER USER 'appuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'replace_with_a_strong_password';
FLUSH PRIVILEGES;

Diagnose a MySQL Service That Will Not Start

Check service status, recent journal entries, MySQL’s error log, and port ownership before changing data-directory permissions or deleting files.

sudo systemctl status mysql --no-pager
sudo journalctl -u mysql -n 80 --no-pager
sudo tail -n 80 /var/log/mysql/error.log
sudo ss -ltnp | grep ':3306' || echo 'No MySQL listener found on port 3306.'

Common causes include another service already using port 3306/tcp, a bad option in a file under /etc/mysql/, a failed remote-bind change, or data files copied with the wrong ownership. Avoid broad recursive ownership changes on /var/lib/mysql unless the error log specifically identifies a permissions problem.

Conclusion

MySQL 8.0 is installed on Debian 12 or 11 from Oracle’s legacy 8.0 repository, with the service verified, the security helper available, and application-user setup ready for local workloads. Keep the server on a restricted listener, back up before package changes, and treat any move to MySQL 8.4 LTS as a planned database upgrade rather than a routine refresh.

Share this guide

Help another Linux user troubleshoot faster

Share this guide with someone troubleshooting Linux systems or saving it for later.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Verify before posting: