Zum Inhalt

MySQL

Inhalt

  • MySQL 8.0 über databases/mysql80-server
  • aktueller Portstand: 8.0.44 auf 2026Q1, 8.0.45 auf latest
  • InnoDB als primäre Engine
  • Basishärtung mit mysql_secure_installation
  • Zugangsdaten mit mysql_config_editor
  • logische Backups mit mysqldump
  • optionale GTID-/Binlog-Basis für spätere Replikation

Einleitung

Dieses HowTo beschreibt die Installation und Konfiguration von MySQL auf FreeBSD 15+.

Dieses HowTo verwendet bewusst databases/mysql80-server für bestehende 8.0-Bestandsumgebungen. Stand heute liegt der Port im FreeBSD-Quarterly-Zweig 2026Q1 bei 8.0.44 und im latest-Zweig bei 8.0.45. Gleichzeitig ist wichtig: MySQL 8.0 erreicht im April 2026 EoL. Für neue Installationen solltest du deshalb prüfen, ob MySQL 8.4 LTS die bessere Wahl ist. (freshports.org)

Dieses HowTo konzentriert sich auf InnoDB als primäre Engine. GTID ist hier bewusst nicht standardmäßig aktiv, sondern wird weiter unten als optionale Produktionsfunktion getrennt behandelt. Das ist Absicht, weil GTID in MySQL explizit konfiguriert werden muss und nicht zur Standardinstallation gehört. (dev.mysql.com)


Voraussetzungen

Zu den Voraussetzungen für dieses HowTo siehe bitte: Hosting System


Vorbereitungen

DNS Records

Für dieses HowTo sind keine zusätzlichen DNS-Records erforderlich.

Gruppen / Benutzer / Passwörter

Für dieses HowTo müssen keine zusätzlichen Systemgruppen oder Systembenutzer manuell angelegt werden.

Der Dienst verwendet den Systembenutzer mysql. (GitHub)

Verzeichnisse / Dateien

Für dieses HowTo müssen vor der Installation keine zusätzlichen Verzeichnisse oder Dateien manuell angelegt werden.

Der Port bringt bereits die Beispieldatei my.cnf.sample unter /usr/local/etc/mysql/ sowie das FreeBSD-Service-Skript mysql-server mit. (freshports.org)


Installation

Wir installieren databases/mysql80-server und dessen Abhängigkeiten.

Bash
mkdir -p /var/db/ports/comms_hidapi
cat <<'EOF' > /var/db/ports/comms_hidapi/options
_OPTIONS_READ=hidapi-0.15.0
_FILE_COMPLETE_OPTIONS_LIST=DOCS
OPTIONS_FILE_UNSET+=DOCS

EOF

mkdir -p /var/db/ports/security_libfido2
cat <<'EOF' > /var/db/ports/security_libfido2/options
_OPTIONS_READ=libfido2-1.16.0
_FILE_COMPLETE_OPTIONS_LIST=DOCS
OPTIONS_FILE_UNSET+=DOCS

EOF

mkdir -p /var/db/ports/textproc_groff
cat <<'EOF' > /var/db/ports/textproc_groff/options
_OPTIONS_READ=groff-1.24.1
_FILE_COMPLETE_OPTIONS_LIST=DOCS EXAMPLES UCHARDET
OPTIONS_FILE_UNSET+=DOCS
OPTIONS_FILE_UNSET+=EXAMPLES
OPTIONS_FILE_SET+=UCHARDET

EOF

mkdir -p /var/db/ports/print_gsfonts
cat <<'EOF' > /var/db/ports/print_gsfonts/options
_OPTIONS_READ=gsfonts-8.11
_FILE_COMPLETE_OPTIONS_LIST=DOCS
OPTIONS_FILE_UNSET+=DOCS

EOF

mkdir -p /var/db/ports/databases_mysql80-client
cat <<'EOF' > /var/db/ports/databases_mysql80-client/options
_OPTIONS_READ=mysql80-client-8.0.45
_FILE_COMPLETE_OPTIONS_LIST= SASLCLIENT
OPTIONS_FILE_UNSET+=SASLCLIENT

EOF

mkdir -p /var/db/ports/databases_mysql80-server
cat <<'EOF' > /var/db/ports/databases_mysql80-server/options
_OPTIONS_READ=mysql80-server-8.0.45
_FILE_COMPLETE_OPTIONS_LIST= ARCHIVE BLACKHOLE EXAMPLE FEDERATED INNOBASE PARTITION PERFSCHEMA PERFSCHM
OPTIONS_FILE_UNSET+=ARCHIVE
OPTIONS_FILE_UNSET+=BLACKHOLE
OPTIONS_FILE_UNSET+=EXAMPLE
OPTIONS_FILE_UNSET+=FEDERATED
OPTIONS_FILE_UNSET+=INNOBASE
OPTIONS_FILE_UNSET+=PARTITION
OPTIONS_FILE_UNSET+=PERFSCHEMA
OPTIONS_FILE_SET+=PERFSCHM

EOF

portmaster -w -B -g -U --force-config databases/mysql80-server -n

Dienst in rc.conf eintragen

Der Dienst wird mittels sysrc in der rc.conf eingetragen und dadurch beim Systemstart automatisch gestartet.

Das FreeBSD-rc-Skript unterstützt hier unter anderem mysql_enable, mysql_dbdir und mysql_optfile. Es initialisiert ein noch leeres Datenverzeichnis beim ersten Start außerdem automatisch mit mysqld --initialize-insecure. (GitHub)

Bash
sysrc mysql_enable=YES

Konfiguration

Verzeichnisse anlegen

Für Passwortdateien und Backups legen wir die benötigten Verzeichnisse jetzt an.

Bash
install -d -m 0750 -o mysql -g mysql /var/db/backups/mysql

Konfigurationsdatei

MySQL sollte dauerhaft über eine Option-Datei konfiguriert werden. Das rc-Skript verwendet standardmäßig /usr/local/etc/mysql/my.cnf, wenn dort eine Datei vorhanden ist; alternativ sucht es im Datenverzeichnis. Der Port liefert dafür bereits my.cnf.sample mit. (GitHub)

Bash
cat <<'EOF' > /usr/local/etc/mysql/my.cnf
[client]
port                            = 3306
socket                          = /tmp/mysql.sock

[mysqld]
user                            = mysql
port                            = 3306
socket                          = /tmp/mysql.sock
bind_address                    = 127.0.0.1,::1

basedir                         = /usr/local
datadir                         = /var/db/mysql
tmpdir                          = /var/db/mysql_tmpdir
replica-load-tmpdir             = /var/db/mysql_tmpdir
secure_file_priv                = /var/db/mysql_secure

default_password_lifetime       = 0
explicit-defaults-for-timestamp = 1

log_bin                         = mysql-bin
server_id                       = 1
sync_binlog                     = 1
binlog_cache_size               = 256K
binlog_expire_logs_seconds      = 604800
binlog_stmt_cache_size          = 256K

log_output                      = FILE
slow_query_log                  = OFF
slow_query_log_file             = slow-query.log
long_query_time                 = 0.05
# log_queries_not_using_indexes   = ON

max_connections                 = 101
net_retry_count                 = 16384
open_files_limit                = 32768
table_open_cache                = 8192
table_definition_cache          = 4096

key_buffer_size                 = 256M
join_buffer_size                = 512K
sort_buffer_size                = 2M
read_buffer_size                = 256K
read_rnd_buffer_size            = 512K
max_heap_table_size             = 256M
tmp_table_size                  = 256M

innodb_thread_concurrency       = 8
innodb_buffer_pool_size         = 2G
innodb_buffer_pool_instances    = 2
innodb_data_home_dir            = /var/db/mysql
innodb_log_group_home_dir       = /var/db/mysql
innodb_data_file_path           = ibdata1:1G;ibdata2:1G;ibdata3:128M:autoextend
innodb_temp_data_file_path      = ibtmp1:128M:autoextend
innodb_flush_method             = O_DIRECT
innodb_redo_log_capacity        = 512M
innodb_sort_buffer_size         = 2M
# innodb_force_recovery           = 1

lower_case_table_names          = 1

# myisam_recover_options          = FORCE,BACKUP

# relay_log_recovery              = ON
# sync_relay_log                  = 1
# enforce_gtid_consistency        = ON
# gtid_mode                       = ON

mysqlx                          = OFF
mysqlx_port                     = 33060
mysqlx_socket                   = /tmp/mysqlx.sock
mysqlx_bind_address             = 127.0.0.1,::1
EOF

Falls deine my.cnf selbst eine datadir-Direktive enthält, muss sie zur rc.conf-Einstellung mysql_dbdir="/var/db/mysql" passen. Das rc-Skript übergibt den Datenpfad explizit an mysqld_safe. (GitHub)

Server zum ersten Mal starten

Wenn das Datenverzeichnis noch nicht initialisiert ist, erzeugt das FreeBSD-rc-Skript es beim ersten Start mit --initialize-insecure. Danach existiert der initiale root-Account ohne Passwort, bis du es selbst setzt. Genau dafür ist der erste Start hier absichtlich getrennt vom nächsten Schritt. (GitHub)

Bash
service mysql-server start

Erster Funktionstest:

Bash
mysql --protocol=socket -u root --skip-password -e "SELECT VERSION();"

Root-Passwort sauber setzen

Nach einer Initialisierung mit --initialize-insecure setzt du das Root-Passwort sauber mit ALTER USER. Für MySQL 8.0 ist caching_sha2_password der moderne Standard-Mechanismus; Legacy-Authentifizierung mit mysql_native_password solltest du nur noch für nachweislich alte Clients überhaupt in Betracht ziehen. In MySQL 8.4 ist mysql_native_password bereits nicht mehr standardmäßig aktiviert. (dev.mysql.com)

Bash
# Passwort für den MySQL-Superuser "root" erzeugen und
# in /var/db/passwords/mysql_superuser_root speichern
install -b -m 0600 -o mysql -g mysql /dev/null /var/db/passwords/mysql_superuser_root
openssl rand -hex 64 | openssl passwd -5 -stdin | tr -cd '[[:print:]]' | \
  cut -c 2-17 | tee /var/db/passwords/mysql_superuser_root | xargs -I % \
  mysql --protocol=socket --user=root --skip-password -e "ALTER USER 'root'@'localhost' IDENTIFIED BY \"%\";"

cat /var/db/passwords/mysql_superuser_root

Zusätzliche Basishärtung

mysql_secure_installation ist im Port enthalten und hilft bei den üblichen Basishärtungen. Für dieses Setup ist sinnvoll:

  • optional validate_password aktivieren
  • anonyme Benutzer entfernen
  • Remote-Login für root verbieten
  • Test-Datenbank entfernen
  • Privilegien neu laden
Bash
mysql_secure_installation

Das Root-Passwort ist in diesem HowTo bereits gesetzt. In mysql_secure_installation überspringst du die Passwortänderung deshalb an dieser Stelle und nutzt das Tool nur noch für die restlichen Härtungsschritte. (freshports.org)

Zugangsdaten mit mysql_config_editor speichern

Ein Login-Path in .mylogin.cnf kann nur einen Satz aus host, user, password, port und socket speichern. Genau diese Felder schreibt mysql_config_editor. Auf Unix verwendet localhost ohne explizites TCP-Protokoll standardmäßig den Unix-Socket. Für lokale Root-Administration reicht deshalb zuerst ein einzelner Socket-Login-Path. (dev.mysql.com)

Bash
mysql_config_editor set \
  --login-path=root-local \
  --socket=/tmp/mysql.sock \
  --user=root \
  --password

Falls dein my.cnf einen anderen Socket-Pfad setzt, musst du hier denselben Pfad verwenden. (dev.mysql.com)

Konfiguration prüfen

Eine klassische configtest-Funktion wie bei manchen anderen Diensten gibt es hier nicht. Für die Prüfung ist deshalb sinnvoll, sich zuerst die aus Option-Dateien gelesenen Werte anzeigen zu lassen und anschließend die Erreichbarkeit des laufenden Dienstes zu testen. my_print_defaults ist genau für das Auslesen solcher Optionen vorgesehen. (dev.mysql.com)

Bash
my_print_defaults mysqld
mysqladmin --login-path=root-local ping

Optionale Produktionsfunktion: Binärlog und GTID

GTID ist in dieser Anleitung absichtlich nicht standardmäßig aktiv. Für GTID-basierte Replikation muss die Konfiguration bewusst vorbereitet werden. Oracle dokumentiert dafür insbesondere: Binary Logging muss aktiv sein, enforce_gtid_consistency muss gesetzt werden und gtid_mode=ON ist nicht der Default. Das hier ist nur die Grundrichtung, keine vollständige Replikationsanleitung. (dev.mysql.com)

INI
[mysqld]
# log_bin                     = mysql-bin
# server_id                   = 1
# binlog_expire_logs_seconds  = 604800
# enforce_gtid_consistency    = ON
# gtid_mode                   = ON

Datenbanken

MySQL-Benutzer admin anlegen

MySQL-Konten sind immer an Benutzer + Host gebunden. Für dieses HowTo legen wir deshalb drei lokale Administrationskonten an: für Socket, IPv4 und IPv6. Das passt sauber zu den späteren Login-Paths. (dev.mysql.com)

Bash
# Passwort für den MySQL-Benutzer "admin" erzeugen und
# in /var/db/passwords/mysql_user_admin speichern
install -b -m 0600 -o mysql -g mysql /dev/null /var/db/passwords/mysql_user_admin
openssl rand -hex 64 | openssl passwd -5 -stdin | tr -cd '[[:print:]]' | \
  cut -c 2-17 | tee /var/db/passwords/mysql_user_admin | xargs -I % \
  mysql --login-path=root-local -e "\
DROP USER IF EXISTS 'admin'@'localhost'; \
DROP USER IF EXISTS 'admin'@'127.0.0.1'; \
DROP USER IF EXISTS 'admin'@'::1'; \
CREATE USER 'admin'@'localhost' IDENTIFIED BY '%'; \
CREATE USER 'admin'@'127.0.0.1' IDENTIFIED BY '%'; \
CREATE USER 'admin'@'::1' IDENTIFIED BY '%'; \
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' WITH GRANT OPTION; \
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'127.0.0.1' WITH GRANT OPTION; \
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'::1' WITH GRANT OPTION; \
FLUSH PRIVILEGES;"

cat /var/db/passwords/mysql_user_admin

Passende Login-Paths:

Bash
mysql_config_editor set \
  --login-path=admin-local \
  --socket=/tmp/mysql.sock \
  --user=admin \
  --password

mysql_config_editor set \
  --login-path=admin-tcp4 \
  --host=127.0.0.1 \
  --port=3306 \
  --user=admin \
  --password

mysql_config_editor set \
  --login-path=admin-tcp6 \
  --host=::1 \
  --port=3306 \
  --user=admin \
  --password

MySQL-Datenbank test_db für admin anlegen

MySQL 8.0 verwendet utf8mb4 als Standardzeichensatzlinie. Für neue Datenbanken ist das die richtige Basis. Dieses Beispiel bleibt bewusst bei InnoDB. (dev.mysql.com)

Bash
cat <<'EOF' > /tmp/test_db.sql
DROP DATABASE IF EXISTS test_db;
CREATE DATABASE test_db CHARACTER SET utf8mb4;
GRANT ALL PRIVILEGES ON test_db.* TO 'admin'@'localhost';
GRANT ALL PRIVILEGES ON test_db.* TO 'admin'@'127.0.0.1';
GRANT ALL PRIVILEGES ON test_db.* TO 'admin'@'::1';
FLUSH PRIVILEGES;
USE test_db;
CREATE TABLE kunden (
    id          BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    name        VARCHAR(255) NOT NULL,
    email       VARCHAR(255) NULL,
    created_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE KEY uq_kunden_email (email)
) ENGINE=InnoDB;
EOF

mysql --login-path=admin-local < /tmp/test_db.sql

Einfacher Funktionstest:

Bash
mysql --login-path=admin-local -e "SHOW DATABASES;"
mysql --login-path=admin-local -e "USE test_db; SHOW TABLES;"
mysql --login-path=admin-tcp4 -e "SELECT CURRENT_USER(), @@hostname;"

Einzelne Datenbank sichern

Für InnoDB ist mysqldump --single-transaction die richtige logische Backup-Basis, weil dabei ein konsistenter Snapshot für transaktionale Tabellen erzeugt wird, ohne normale Lese-/Schreibvorgänge unnötig hart zu blockieren. mysqlpump solltest du für neue Setups nicht mehr einplanen; es ist seit 8.0.34 deprecated. (dev.mysql.com)

Bash
mysqldump \
  --login-path=admin-local \
  --single-transaction \
  --routines \
  --events \
  --triggers \
  test_db > /var/db/backups/mysql/test_db-$(date +%F).sql

Wiederherstellung:

Bash
mysql --login-path=admin-local -e "CREATE DATABASE test_db_restore CHARACTER SET utf8mb4;"
mysql --login-path=admin-local test_db_restore < /var/db/backups/mysql/test_db-2026-03-21.sql

Einzelne Tabelle sichern

Bash
mysqldump \
  --login-path=admin-local \
  --single-transaction \
  test_db kunden > /var/db/backups/mysql/test_db-kunden-$(date +%F).sql

Wiederherstellung:

Bash
mysql --login-path=admin-local test_db_restore < /var/db/backups/mysql/test_db-kunden-2026-03-21.sql

Alle Datenbanken logisch sichern

Bash
mysqldump \
  --login-path=admin-local \
  --single-transaction \
  --routines \
  --events \
  --triggers \
  --all-databases > /var/db/backups/mysql/all-databases-$(date +%F).sql

Wiederherstellung:

Bash
mysql --login-path=admin-local < /var/db/backups/mysql/all-databases-2026-03-21.sql

Zusatzsoftware

Mögliche Zusatzsoftware wird hier installiert und konfiguriert.

Für dieses HowTo ist keine zusätzliche Software erforderlich.


Aufräumen

Überflüssige oder temporäre Verzeichnisse und Dateien entsorgen.

Zusatzsoftware Installation

Nicht erforderlich.

Zusatzsoftware Konfiguration

Nicht erforderlich.

Temporäre Testdatei entfernen:

Bash
rm -f /tmp/test_db.sql

Abschluss

Abschließend den Dienst einmal sauber neu starten und die Erreichbarkeit prüfen:

Bash
service mysql-server restart
mysql --login-path=admin-local -e "SELECT VERSION();"

Für spätere Änderungen:

Bash
service mysql-server restart
mysqladmin --login-path=root-local ping

Für Updates gilt: erst Backup, dann Update. Seit MySQL 8.0.16 übernimmt der Server die Upgrade-Arbeiten, die früher mysql_upgrade erledigt hat; das Tool ist deshalb deprecated und in 8.4 bereits entfernt. Bei Major-Upgrades, insbesondere 8.0 → 8.4, solltest du dem dokumentierten Upgrade-Pfad folgen und nicht blind nur den Port austauschen. (freshports.org)


Referenzen

  • FreeBSD Handbook: Ports und Diensteverwaltung
  • FreshPorts: databases/mysql80-server
  • MySQL Reference Manual: Initializing the Data Directory
  • MySQL Reference Manual: Securing the Initial MySQL Account
  • MySQL Reference Manual: mysql_secure_installation
  • MySQL Reference Manual: mysql_config_editor
  • MySQL Reference Manual: Connection Transport Protocols
  • MySQL Reference Manual: mysqldump
  • MySQL Reference Manual: GTID / Replication
  • MySQL Product Support EOL Announcements