Changing the MySQL or MariaDB bind address lets you keep TCP access limited to the networks that actually need it, whether that means localhost only, a private service IP, or a small set of database-facing interfaces. Tight listener scope reduces accidental exposure and makes remote-access rules easier to reason about.

The mysqld-compatible server reads startup options from one or more option files, then opens its TCP listener according to the effective bind-address setting under [mysqld]. If no loaded file sets that option, current MySQL uses a wildcard listener by default, while many packaged MariaDB and distro installs still ship a localhost-focused file that overrides broader listening.

Use a real host IP address for targeted listening, not an interface name such as eth0. A listener change does not grant remote access by itself, and a missing listener can also be caused by skip-networking, so confirm the effective option chain, restart the service, and then verify both the listening socket and a real TCP client connection.

Steps to change MySQL or MariaDB bind address:

  1. Select the installed server binary so later discovery commands query the correct product.
    $ server_bin=$(command -v mariadbd || command -v mysqld)
    $ echo "$server_bin"
    /usr/sbin/mariadbd

    Current MariaDB packages usually return mariadbd, while MySQL packages usually return mysqld.

  2. Print the option-file search order used by the running server binary.
    $ "$server_bin" --verbose --help 2>/dev/null | sed -n '/Default options are read from the following files in the given order:/,+3p'
    Default options are read from the following files in the given order:
    /etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf
    ##### snipped #####

    The local host is authoritative here. Current MySQL also reports /usr/etc/my.cnf in its upstream binary help output.

  3. Inspect the base option file for include directories before choosing where to place the change.
    $ sudo grep -nE '^(\\!include|\\!includedir)' /etc/my.cnf /etc/mysql/my.cnf /etc/mysql/mariadb.cnf 2>/dev/null
    /etc/mysql/my.cnf:28:!includedir /etc/mysql/mariadb.conf.d/
    /etc/mysql/my.cnf:29:!includedir /etc/mysql/conf.d/

    On MariaDB package installs for Debian and Ubuntu, the active server file is often /etc/mysql/mariadb.conf.d/50-server.cnf. MySQL packages commonly use /etc/mysql/mysql.conf.d/ or /etc/mysql/conf.d/ for server overrides.

  4. Check the effective bind-address value already loaded for [mysqld].
    $ my_print_defaults mysqld | grep -- '^--bind-address='
    --bind-address=127.0.0.1

    No output usually means no loaded option file is setting bind-address explicitly. Current upstream MySQL defaults to a wildcard listener when unset, but packaged installs often override that with a more restrictive file.

  5. Search the discovered config tree for every bind-address or skip-networking line before editing.
    $ sudo grep -RniE '^[[:space:]]*(bind-address|skip-networking)' /etc/mysql /etc/my.cnf 2>/dev/null
    /etc/mysql/mariadb.conf.d/50-server.cnf:27:bind-address            = 127.0.0.1

    If multiple matching lines appear, the last-loaded file wins. If skip-networking is enabled, the server will not accept TCP connections until that option is removed or disabled.

  6. Create or edit a dedicated server override file in the last included server directory that the host actually loads.
    $ sudoedit /etc/mysql/mariadb.conf.d/z-custom-bind.cnf

    Use the last server include directory discovered on the host. On MySQL packages, that may be /etc/mysql/mysql.conf.d/z-custom-bind.cnf or /etc/mysql/conf.d/z-custom-bind.cnf instead.

  7. Set bind-address under [mysqld] to the address that should accept TCP connections.
    [mysqld]
    bind-address = 192.0.2.40

    Use 127.0.0.1 for local-only TCP access, or a specific private service IP for controlled remote access. Current MySQL 8.0.13+ and MariaDB 10.11+ also support comma-separated non-wildcard addresses when the server must listen on more than one specific address.

    Setting bind-address to 0.0.0.0 exposes the database on all IPv4 interfaces. Use that only when firewall rules and database account host restrictions already limit who can connect.

  8. Confirm the edited file is being read before restarting the service.
    $ my_print_defaults mysqld | grep -- '^--bind-address='
    --bind-address=192.0.2.40

    If the expected value does not appear, the file is in the wrong path, under the wrong option group, or overridden later in the include chain.

  9. Identify the actual database service unit name before restarting it.
    $ systemctl list-unit-files --type=service | grep --extended-regexp '^(mysql|mariadb|mysqld)\.service'
    mariadb.service                              enabled         enabled

    Depending on packaging, the unit may be mysql.service, mariadb.service, or mysqld.service.

  10. Restart the database service to apply the new listener.
    $ sudo systemctl restart mariadb

    Restarting drops active database connections, so schedule the change when connected applications can tolerate a short interruption.

    Replace mariadb with the unit name discovered on the host.

  11. Confirm the service came back cleanly after the restart.
    $ systemctl is-active mariadb
    active

    If the service does not return active, inspect the recent journal before editing again.

    $ sudo journalctl --unit=mariadb.service --no-pager --lines=50
    ##### snipped #####
  12. Check that mysqld is listening on the intended address and port.
    $ ss --listening --numeric --tcp | grep ':3306 '
    LISTEN 0      80      192.0.2.40:3306      0.0.0.0:*

    If no listener appears, recheck bind-address, skip-networking, and the service logs from the failed or restarted unit.

  13. Test a real TCP connection to the new listener from an allowed client.
    $ client_bin=$(command -v mariadb || command -v mysql)
    $ "$client_bin" --host=192.0.2.40 --port=3306 --protocol=TCP --user=appuser --password --execute="SELECT CURRENT_USER(), @@hostname, @@port;"
    CURRENT_USER()        @@hostname    @@port
    appuser@192.0.2.%     dbhost        3306

    If the TCP socket opens but login fails, review the database account host value such as 'appuser'@'192.0.2.%' and any host firewall or security-group rules that still restrict the client.