EQVPS
PanelZacznij

Jak zainstalować MySQL na VPS: użytkownicy, bezpieczny dostęp zdalny, mniej RAM i kopie zapasowe

Instalujemy MySQL 8.0 na VPS z Ubuntu 24.04, tworzymy bazę i użytkownika dla aplikacji, łączymy się z własnego komputera bez otwierania portu 3306, zmniejszamy pamięć w spoczynku z 383 MB do 165 MB i co noc robimy kopię skryptem, który głośno zgłasza błąd.

Instalacja MySQL to jedno polecenie. Większość pracy zaczyna się potem: użytkownik dla aplikacji, sposób na dostęp do bazy z własnego komputera bez wystawiania portu 3306 do internetu, ustawienia pamięci dla małego serwera i kopie zapasowe, które robią się bez ciebie. Ten poradnik obejmuje wszystkie cztery na Ubuntu 24.04. Każdy krok wykonaliśmy na naszym obrazie Ubuntu 24.04, a poniższe liczby pochodzą z tego serwera.

Wykonuj polecenia jako użytkownik z sudo. Tworzy go poradnik konfiguracji Ubuntu.

1. Zainstaluj

sudo apt update
sudo apt install -y mysql-server
mysql --version

Na naszym serwerze instalacja trwała 51 sekund i dała MySQL 8.0.46. Uruchamia się od razu, startuje przy każdym uruchomieniu systemu i nasłuchuje tylko na samym serwerze: 127.0.0.1:3306 dla zwykłych połączeń i 127.0.0.1:33060 dla nowszego protokołu X. Z zewnątrz nic jeszcze nie jest dostępne.

2. Utwórz bazę i użytkownika

Konto root w MySQL używa w Ubuntu uwierzytelniania przez gniazdo, więc sudo mysql loguje cię bez hasła. Utwórz bazę i użytkownika dla aplikacji:

sudo mysql
CREATE DATABASE app CHARACTER SET utf8mb4;
CREATE USER 'app'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'localhost';
EXIT;

Sprawdź to tak, jak będzie łączyć się aplikacja:

mysql -u app -p app -e "SELECT CURRENT_USER();"

Powinno wypisać app@localhost. Złe hasło kończy się ERROR 1045 (28000): Access denied for user 'app'@'localhost'. Użytkownik może wszystko wewnątrz app i nic poza nią.

3. Połączenie z własnego komputera: tunel SSH

Aby używać klienta desktopowego, takiego jak DBeaver, MySQL Workbench czy konsolowy mysql na swoim komputerze, nie otwieraj portu. Przekieruj go przez SSH:

ssh -L 3307:127.0.0.1:3306 deploy@YOUR.SERVER.IP

Na planie z NAT dodaj -p i osobisty port SSH z panelu. Dopóki to okno jest otwarte, skieruj klienta na host 127.0.0.1, port 3307, użytkownik app. Po stronie lokalnej użyliśmy 3307, żeby nie kolidować z MySQL, który może działać na twoim komputerze. W naszym teście serwer od razu odpowiedział przez tunel, a bezpośrednie połączenie z jego adresem na 3306 zostało odrzucone.

4. Bezpośredni dostęp dla jednego innego serwera

Czasem aplikacja działa na drugim serwerze i musi łączyć się bezpośrednio. Baza potrzebuje wtedy planu z własnym IPv4, bo plan z NAT przekierowuje tylko twój port SSH. Trzy zmiany, wszystkie ograniczone do adresu serwera aplikacji (tu 203.0.113.20):

sudo sed -i 's/^bind-address.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
sudo systemctl restart mysql
sudo ufw allow from 203.0.113.20 to any port 3306 proto tcp
CREATE USER 'app'@'203.0.113.20' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'203.0.113.20';

Jeśli ufw nie jest jeszcze włączony, najpierw dopuść SSH (sudo ufw allow OpenSSH), a potem uruchom sudo ufw enable. Szczegóły są w poradniku ufw.

Sprawdziliśmy oba zamki osobno. Z regułą w zaporze, ale bez pasującego użytkownika MySQL, serwer odmówił z error 1130: Host '…' is not allowed to connect to this MySQL server. Po dodaniu użytkownika połączenie przeszło. Bez reguły w zaporze połączenie po prostu kończyło się przekroczeniem czasu. Każdy inny adres w internecie dostaje to samo przekroczenie czasu.

5. Mniej RAM

W spoczynku, bez własnych danych, MySQL 8.0 zajmował na naszym serwerze 383 MB. Większość to Performance Schema, funkcja diagnostyczna rezerwująca pamięć z góry. Na małym VPS wyłącz ją i sam ustaw rozmiar głównej pamięci podręcznej:

sudo tee /etc/mysql/mysql.conf.d/zz-small-vps.cnf >/dev/null <<'EOF'
[mysqld]
performance_schema = OFF
innodb_buffer_pool_size = 256M
max_connections = 50
EOF
sudo systemctl restart mysql
ps -o rss= -C mysqld

Po restarcie zajmował 165 MB. Buffer pool przechowuje w pamięci dane i indeksy, a 256 MB pasuje do serwera z 2 GB, na którym działa też aplikacja. Zwiększ go, jeśli baza jest najważniejszą rzeczą na serwerze i urosła ponad rozmiar cache. max_connections = 50 w zupełności wystarcza jednej aplikacji z pulą połączeń. Tracisz statystyki performance_schema. Włącz je z powrotem, jeśli kiedyś trzeba będzie dokładnie zbadać wolne zapytania.

6. Nocne kopie zapasowe

mysqldump --single-transaction robi spójną kopię tabel InnoDB bez blokowania aplikacji. Zamknij to w małym skrypcie:

sudo tee /usr/local/bin/mysql-backup >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
umask 077
mkdir -p /var/backups/mysql
mysqldump --single-transaction --routines --triggers app | gzip > /var/backups/mysql/app-$(date +%F).sql.gz
find /var/backups/mysql -name 'app-*.sql.gz' -mtime +14 -delete
EOF
sudo chmod 755 /usr/local/bin/mysql-backup
echo '0 3 * * * root /usr/local/bin/mysql-backup' | sudo tee /etc/cron.d/mysql-backup
sudo /usr/local/bin/mysql-backup && sudo ls -l /var/backups/mysql

Każdy wiersz ma swój powód:

  • umask 077 sprawia, że zrzut może czytać tylko root (-rw-------), bo zawiera wszystkie twoje dane.
  • pipefail sprawia, że cały skrypt kończy się błędem, gdy zawiedzie mysqldump. Bez tego gzip zapisałby maleńkie puste archiwum i zgłosił sukces. Celowo zepsuliśmy polecenie i skrypt zakończył się kodem 2, tak jak powinien.
  • find … -mtime +14 -delete trzyma kopie z dwóch tygodni.
  • Skrypt działa jako root, więc mysqldump loguje się przez gniazdo i hasło nie leży w żadnym pliku.

Kopia, której nigdy nie odtworzyłeś, jeszcze się nie liczy. Odtwórz ją do tymczasowej bazy i obejrzyj dane:

sudo mysql -e "CREATE DATABASE app_restore"
gunzip -c /var/backups/mysql/app-2026-10-25.sql.gz | sudo mysql app_restore
sudo mysql -e "SHOW TABLES FROM app_restore"
sudo mysql -e "DROP DATABASE app_restore"

W naszym teście odtworzona tabela miała te same wiersze co oryginał. Kopie na tym samym dysku nie chronią przed utratą serwera, więc co jakiś czas przenoś je na inną maszynę przez scp albo restic. Managed Backups dokładają do tego codzienne punkty przywracania całego serwera.

Jaki plan

Micro (2 vCPU, 2 GB, 25 GB, $5/mies.) utrzyma MySQL z takim strojeniem plus aplikację webową. Jeśli sama baza urośnie powyżej kilku gigabajtów, Small z 4 GB i 35 GB za $8/mies. pozwoli dać buffer poolowi 1 GB lub więcej. Oba plany są z NAT, a tunel SSH z kroku 3 na nich działa. Krok 4 wymaga własnego IPv4: Micro-IP kosztuje $10/mies.

Wolisz PostgreSQL? Poradnik PostgreSQL ma ten sam plan. Wszystkie plany są w dziale VPS, a płatność w USDT, USDC lub ETH w sieciach Base, Ethereum lub Polygon.

FAQ

MySQL czy MariaDB?

Obie są we własnych repozytoriach Ubuntu 24.04: mysql-server instaluje MySQL 8.0, a mariadb-server instaluje MariaDB 10.11. Większość aplikacji, które wymagają „MySQL”, działa z każdą z nich. Użyj tej, którą wskazuje dokumentacja twojej aplikacji, a jeśli jej to obojętne — MySQL 8.0. Ten poradnik używa MySQL.

Jakie jest hasło roota w MySQL?

Nie ma żadnego. W Ubuntu konto root w MySQL używa uwierzytelniania przez gniazdo: sudo mysql loguje cię jako root, a przez sieć nikt nie zaloguje się jako root. Zostaw to tak i twórz osobnych użytkowników dla aplikacji.

Czy otwierać port 3306 do internetu?

Nie. Otwarte porty baz danych są stale skanowane i atakowane zgadywaniem haseł. Ze swojego komputera łącz się przez tunel SSH. Jeśli inny serwer musi łączyć się bezpośrednio, dopuść tylko jego IP, zarówno w MySQL, jak i w zaporze.

Ile RAM potrzebuje MySQL?

Zaraz po instalacji MySQL 8.0 zajmował na naszym serwerze testowym 383 MB, bez własnych baz. Po wyłączeniu Performance Schema i ustawieniu skromnego buffer poola zszedł do 165 MB. Plan Micro z 2 GB spokojnie uciągnie MySQL i aplikację; po takim strojeniu 1 GB wystarczy na małą stronę.

Czy muszę uruchamiać mysql_secure_installation?

W Ubuntu 24.04 większość jego pracy jest już zrobiona. Nasza świeża instalacja nie miała anonimowych użytkowników ani testowej bazy, a root może logować się tylko przez lokalne gniazdo. Uruchom go, jeśli chcesz komponent sprawdzania siły haseł, który oferuje; w przeciwnym razie możesz go pominąć.

Komentarze

Brak komentarzy. Bądź pierwszy.

Zostaw komentarz

Komentarze są moderowane przed pojawieniem się.