努力
加油

Ubuntu服务器如何安全安装并初始化MySQL服务?

在 Ubuntu 上部署 MySQL,很多新手容易犯两个极端错误:要么直接用 apt install mysql-server 装完就跑,完全忽略安全配置;要么被网上各种“硬核”教程搞晕,改了一堆配置文件导致服务起不来。

作为在云环境摸爬滚打多年的运维/开发,我推荐一种平衡了安全性、可维护性和标准化的安装初始化流程。这里以目前主流的云厂商(如阿里云 ECS、腾讯云 CVM)推荐的 Ubuntu 20.04/22.04 LTS 为例。

核心原则

  1. 最小权限原则:不要给 root 密码远程登录,不要用 root 连接业务数据库。
  2. 网络隔离:生产环境严禁绑定 0.0.0.0,必须通过内网 IP 或特定公网 IP 访问。
  3. 自动更新与补丁:利用系统自带的包管理器管理版本,避免手动编译带来的依赖地狱。

第一步:系统准备与源清理

不要急着装 MySQL,先确保系统是干净的。

# 1. 更新系统基础包
sudo apt update && sudo apt upgrade -y

# 2. 安装必要的依赖(部分镜像可能预装,但显式安装更稳妥)
sudo apt install -y curl gnupg lsb-release

# 3. 检查是否残留旧版 MySQL/MariaDB(重要!防止冲突)
dpkg -l | grep mysql
dpkg -l | grep mariadb

# 如果有残留,建议彻底清除
# sudo apt purge mysql* mariadb*
# sudo apt autoremove

注意:Ubuntu 默认源里现在通常提供的是 MySQL 8.0。如果你需要特定版本(如 5.7),需要添加官方 APT 仓库。但对于大多数新项目,直接拥抱 MySQL 8.0 是更好的选择,因为它对 JSON 支持更好,安全性更强(默认密码插件 caching_sha2_password)。


第二步:安装 MySQL Server

使用官方源安装是最省心的方式。

# 1. 下载并导入 MySQL 官方的 GPG 密钥和仓库配置
wget https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.29-1_all.deb

# 在执行过程中,屏幕会弹出一个菜单:
# - Select "MySQL Server & Cluster" -> Choose "mysql-8.0" (默认通常是这个)
# - Select "Tools & Utils" -> 保持默认
# - 确定后,它会更新 apt 源。

# 如果不想交互,也可以直接添加源(针对 Ubuntu 20.04/22.04):
# wget https://repo.mysql.com/apt/ubuntu/pool/main/m/mysql-community/mysql-apt-config_0.8.29-1_all.deb
# sudo dpkg -i mysql-apt-config_0.8.29-1_all.deb
# sudo apt update

# 2. 正式安装
sudo apt install mysql-server -y

安装完成后,MySQL 服务通常会自动启动。你可以检查状态:

sudo systemctl status mysql

如果没启动,执行 sudo systemctl start mysql 并设置开机自启 sudo systemctl enable mysql。


第三步:安全初始化(关键步骤)

这是大多数人忽略但决定服务器生死的一步。绝对不要跳过!

运行安全脚本:

sudo mysql_secure_installation

脚本会引导你完成以下操作,请仔细回答:

  1. Validate Password Component(密码验证组件):

    • 提示:Press y|Y for Yes, any other key for No:
    • 建议选 Y。这会强制要求密码复杂度(长度、大小写、特殊字符、数字)。虽然有点烦,但在云上这是底线。
    • 级别选择:通常选 2 (STRONG)。
  2. Change the root password?

    • 建议选 N。因为 MySQL 8.0 默认使用 auth_socket 插件进行本地 root 认证,不需要密码也能通过 sudo 登录。如果你非要设密码,选 Y 并设置一个强密码。
    • 专家建议:保留默认的 socket 认证更安全,因为这意味着只有拥有服务器 sudo 权限的人才能以 root 身份进入数据库,防止了远程暴力破解 root 密码的风险。
  3. Remove anonymous users?

    • 必须选 Y。删除匿名账户,防止未授权访问。
  4. Disallow root login remotely?

    • 必须选 Y。禁止 root 用户从远程(非 localhost)登录。这是防止黑客撞库的第一道防线。
  5. Remove test database and access to it?

    • 必须选 Y。删除测试库,防止信息泄露。
  6. Reload privilege tables now?

    • 必须选 Y。立即重新加载权限表,使更改生效。

第四步:创建专用数据库用户(最佳实践)

永远不要用 root 账号连接你的应用程序。创建一个具有最小权限的业务用户。

  1. 进入 MySQL 命令行:

    sudo mysql
  2. 创建数据库和用户(示例):

    -- 创建数据库,指定 utf8mb4 编码(支持 emoji 和多语言)
    CREATE DATABASE myapp_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    
    -- 创建用户,仅限特定 IP 访问(假设应用服务器 IP 为 192.168.1.100)
    -- 如果应用和数据库在同一台机器,可以用 'localhost' 或 '127.0.0.1'
    CREATE USER 'myapp_user'@'192.168.1.100' IDENTIFIED BY 'Your_Strong_Passw0rd!';
    
    -- 授予权限(只给该数据库的 CRUD 权限,不给 FILE, SUPER, GRANT 等高危权限)
    GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON myapp_db.* TO 'myapp_user'@'192.168.1.100';
    
    -- 刷新权限
    FLUSH PRIVILEGES;
    
    -- 退出
    EXIT;

为什么不用 ALL PRIVILEGES? 万一应用代码有 SQL 注入漏洞,攻击者只能操作 myapp_db,无法删除其他库或读取系统文件。


第五步:网络与安全组配置(云服务器特有)

这一步决定了你的数据库是否会被扫到。

  1. 修改 MySQL 监听地址(可选但推荐):
    编辑 /etc/mysql/mysql.conf.d/mysqld.cnf:

    [mysqld]
    # 将 bind-address 改为你的内网 IP,或者注释掉这行(默认是 127.0.0.1)
    # 如果是单机部署,保持 127.0.0.1 即可,外部通过 SSH 隧道或内网访问
    bind-address = 127.0.0.1

    注意:如果你希望从其他服务器通过内网连接,这里要改成服务器的内网 IP,而不是 0.0.0.0。

  2. 重启 MySQL:

    sudo systemctl restart mysql
  3. 防火墙与安全组:

    • UFW(Ubuntu 自带防火墙):如果开启了 UFW,确保 3306 端口只对可信 IP 开放。
      sudo ufw allow from 192.168.1.100 to any port 3306
    • 云厂商安全组(重中之重):
      • 在阿里云/腾讯云的 ECS/CVM 控制台,找到“安全组”。
      • 入方向规则:添加一条规则,协议 TCP,端口 3306,来源 IP 填应用服务器的内网 IP(如果是同一可用区)或应用服务器的公网 IP(如果跨地域且无专线)。
      • 绝对不要将来源设为 0.0.0.0/0,除非你在做开发调试且知道风险。

第六步:验证与监控

  1. 验证连接:
    从应用服务器尝试连接:

    mysql -h <数据库服务器内网IP> -u myapp_user -p

    输入密码,如果能进入命令行,说明网络、权限、用户都配置正确。

  2. 查看日志:
    如果出现奇怪的问题,第一时间看日志:

    sudo tail -f /var/log/mysql/error.log

常见坑点总结

  1. 时区问题:MySQL 8.0 默认不加载系统时区,可能导致时间查询偏差。可以在 mysqld.cnf 中加上 default-time-zone = '+08:00'(中国标准时间)。
  2. 客户端兼容性问题:如果你的应用程序非常老(如某些 PHP 5.x + PDO 的老项目),可能不支持 MySQL 8.0 默认的 caching_sha2_password 认证插件。这种情况下,需要将用户认证方式改回 mysql_native_password:
    ALTER USER 'myapp_user'@'%' IDENTIFIED WITH mysql_native_password BY 'Your_Password';
  3. 内存溢出:MySQL 默认配置可能占用过多内存。对于小内存云服务器(如 2G/4G),建议安装后调整 /etc/mysql/my.cnf 中的 innodb_buffer_pool_size,一般设置为物理内存的 50%-70%。

按照这套流程走下来,你的 MySQL 实例不仅安装成功,而且在安全基线上达到了生产环境的基本要求。