ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Ubuntu从零搭建MySQL、Redis、Nginx与自动备份完整指南

Ubuntu从零搭建MySQL、Redis、Nginx与自动备份完整指南 刚拿到一台崭新的 Ubuntu 服务器时很多人的第一反应是赶紧把 MySQL、Redis、Nginx 装起来再把项目扔上去跑通。但真到动手才发现环境配置这东西坑全藏在细节里MySQL 装完密码策略折腾半天、Redis 裸奔着就对外服务、Nginx 转发规则反复试错、备份脚本写完一次没恢复过……等哪天数据库真出问题才发现备份根本没法用。这篇文章我会把 Ubuntu 从零搭建 MySQL Redis Nginx 三件套外加一套靠谱的自动备份方案完整走一遍。里面的命令、配置、踩坑点都是我实际部署中反复验证过的不是那种抄官方文档的流水账。不管你是在自己的 VPS 上折腾还是给公司搭测试环境照着这份指南一步步来基本能少走两个月的弯路。这套组合是当下中小型后端服务的基础标配。MySQL 撑业务数据Redis 扛缓存和临时数据Nginx 负责接入流量和反向代理自动备份保证出事能恢复。四个组件凑齐一个最小可用、可长期运行的 Web 后端环境就算是立起来了。1. 环境准备与系统初始化部署之前先把底子打好。很多莫名其妙的安装失败归根结底是系统源、依赖库、防火墙这几样没弄利索。这块多花十分钟后面能省下十个小时的排查时间。1.1 版本选择与基础依赖安装Ubuntu 版本优先选 LTS长期支持版我这边实际用的是 Ubuntu 22.04 LTS这套流程在 20.04 和 24.04 上也都验证过命令基本通用。内核版本和 apt 源的差异可能会让个别包的版本号不一样但整体步骤不会有大的偏差。登录服务器后第一件事是把系统包里已有的软件更新到最新避免因为源索引过期安装到有已知问题的旧版本sudo apt update sudo apt upgrade -y然后装上后续编译、安装过程中会用到的工具链和基础库。这里我习惯一次性装齐全省得后面装某个组件时突然报错缺依赖再回头补装打断思路sudo apt install -y build-essential libssl-dev libncurses5-dev \ libncursesw5-dev zlib1g-dev gcc g make cmake \ curl wget git pkg-config顺便提一句很多人在 Ubuntu 上装 GCC 失败十有八九是build-essential没装全或者 apt 源没配置好。别绕弯子先把这一步的依赖装完再说。1.2 配置防火墙与开放端口Ubuntu 默认不带图形防火墙界面一般用 UFWUncomplicated Firewall来管理。这个工具名字起得好用起来也确实简单。先把默认策略设为拒绝外部访问然后只放行需要的端口这是服务器安全的基础操作sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable这里有个细节22 端口SSH千万别忘了放行不然一开防火墙你的远程连接立刻断掉服务器只能去机房物理操作。MySQL 的 3306 端口和 Redis 的 6379 端口我默认不对外开放。如果业务确实需要远程连接建议只对特定 IP 放行比如sudo ufw allow from 192.168.1.100 to any port 3306/tcp注意有的云厂商还有一层安全组策略服务器内部 UFW 和云控制台安全组要同时配置两边是独立的只放行一边仍然连不上。很多新手在这里卡住半天排查到最后才发现是安全组没加规则。2. MySQL 8.0 部署全流程MySQL 是这套环境里最重要的组件数据安全全指望它。安装方式我推荐直接用 MySQL 官方 apt 源而不是 Ubuntu 自带的发行版源。官方源版本更新及时补丁跟进也快生产环境用省心得多。2.1 添加官方源并安装先下载并安装 MySQL 官方源配置包wget https://dev.mysql.com/get/mysql-apt-config_0.8.24-1_all.deb sudo dpkg -i mysql-apt-config_0.8.24-1_all.deb安装过程中会有交互界面问你要装哪个版本的 MySQL选择mysql-8.0即可。如果手速快没看清就跳过了也没关系默认选项就是 8.0直接回车就行。然后更新源并安装sudo apt update sudo apt install -y mysql-server安装完先看下版本和运行状态确认服务已经拉起来mysql --version sudo systemctl status mysql如果状态显示active (running)说明安装成功。这一步卡住的话多半是官方源下载速度太慢可以换个国内镜像源再apt update。2.2 初始化安全配置MySQL 8.0 安装完成后默认自带一个安全初始化脚本在 root 密码为空的情况下运行它会设置密码、删除匿名用户、禁用 root 远程登录一步步引导你完成基础加固。直接用下面命令跑起来sudo mysql_secure_installation这个脚本会依次询问几个问题我的推荐选项是这样的设置密码强度校验选2最强校验如果只是内网开发环境可以选0不校验看自己需求。设置 root 密码输入你想用的强密码长度建议不低于 12 位。删除匿名用户选y禁止 root 远程登录选y删除 test 数据库并重新加载权限表选y跑完之后测试一下本地登录sudo mysql -u root -p能进入 MySQL 命令行就说明配置成功。2.3 创建业务账号并设置远程访问生产环境千万别用 root 去连业务正确做法是创建一个专用账号只授予需要的库的权限。这种最小权限原则能极大降低账号泄露时的破坏面。CREATE USER app_userlocalhost IDENTIFIED BY YourStrongPassword_2024; CREATE DATABASE app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; GRANT ALL PRIVILEGES ON app_db.* TO app_userlocalhost; GRANT ALL PRIVILEGES ON app_db.* TO app_user%; FLUSH PRIVILEGES;字符集选utf8mb4而不是老旧的utf8因为utf8mb4支持完整 Unicode 编码包括 emoji 和生僻字这是 8.0 时代的标准写法。app_userlocalhost是本地连接用app_user%是外部连接用。如果只在服务器本机连数据库第二个%账号可以不创建。需要远程连接时还要确认 MySQL 配置文件里监听了所有网卡。编辑 MySQL 配置文件sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf确认或修改bind-address 0.0.0.0改完重启 MySQLsudo systemctl restart mysql这时从另一台机器用客户端工具连接试试如果能连上远程访问就打通了。2.4 关键性能参数调优MySQL 默认配置偏保守是为了在低配机器上也能跑起来。生产环境按照机器的内存大小把几个关键参数调整一下性能提升非常明显。我常用的模板如下以 8G 内存为例[mysqld] # 缓存池大小MySQL 内存占用大头设为物理内存的 60%-70% innodb_buffer_pool_size 5G # 日志缓冲区 innodb_log_buffer_size 16M # 并发连接数上限 max_connections 500 # 默认存储引擎 default_storage_engine InnoDB # 字符集 character-set-server utf8mb4 collation-server utf8mb4_unicode_ci # 每线程排序缓冲 sort_buffer_size 2M join_buffer_size 2M改完配置同样要重启sudo systemctl restart mysql怎么看调优是否生效进 MySQL 命令行执行SHOW VARIABLES LIKE innodb_buffer_pool_size; SHOW VARIABLES LIKE max_connections;数值和配置一致说明生效了。实操心得innodb_buffer_pool_size不是越大越好。如果机器上还跑着 Redis、Nginx 和业务程序缓存池太大容易导致内存互相争抢触发 OOM内存溢出进程被系统直接杀掉。最好先看看你当前业务实际用多少再留出 30% 余量给系统和缓存。比如 8G 机器只跑 MySQL给 5G 没问题如果同时跑 Java 后端4G 就够了。3. Redis 部署与配置Redis 做缓存和临时存储非常好用但它的默认配置是“裸奔”状态——没有密码、绑定所有网卡、任何机器都能连。这个隐患我在很多生产环境里见过轻则数据被删重则服务器被挖矿程序利用。3.1 安装 RedisUbuntu 官方源里就有 Redis版本虽然不是最新但稳定性和 apt 的管理便利性是最好的适合绝大多数场景sudo apt install -y redis-server装完检查状态sudo systemctl status redis-server redis-cli pingredis-cli ping返回PONG服务就正常了。3.2 修改绑定地址与密码Redis 的配置文件在/etc/redis/redis.conf。不管是不是要开放远程有两个配置项必须改sudo vim /etc/redis/redis.conf关键修改如下# 默认是 127.0.0.1只允许本地访问 # 如果业务网络需要多个机器连 Redis改成服务器内网 IP bind 127.0.0.1 # 设置访问密码 requirepass YourRedis_StrongPassword_2024 # 关闭危险命令防止误操作和数据被篡改 rename-command FLUSHALL rename-command FLUSHDB 这里解释一下为什么要关FLUSHALL和FLUSHDB。这两条命令可以瞬间清空 Redis 全部数据如果密码泄露或者被漏洞利用攻击者一条命令就能把你的缓存数据全部毁掉。开发环境如果确实需要清空缓存开个临时窗口改配置启用就行生产环境建议保持禁用。改完重启 Redis 生效sudo systemctl restart redis-server以后本地连接需要带密码redis-cli -a YourRedis_StrongPassword_2024 ping注意用-a传密码命令行的连接密码可能会留在 shell 历史记录里可以改用环境变量方式REDISCLI_AUTH密码 redis-cli ping。这样密码不会直接出现在ps或历史命令中安全得多。3.3 配置持久化策略Redis 是内存数据库掉电就是丢数据所以持久化配置是必须的。Redis 官方提供两种方案RDB快照持久化和 AOF追加文件持久化。生产环境我建议两个都开RDB 负责快速恢复AOF 负责精确记录每次写操作。在配置文件里加上# RDB 快照策略满足条件自动触发 save 900 1 save 300 10 save 60 10000 # 开启 AOF appendonly yes appendfsync everysecappendfsync everysec表示每秒钟把 AOF 缓冲区刷到磁盘丢了最多一秒钟的数据性能影响也能接受。改完确认生效redis-cli -a YourRedis_StrongPassword_2024 CONFIG GET appendonly返回yes就配置成功了。4. Nginx 站点配置与反向代理Nginx 在这套环境里承担两个角色一是托管静态网站文件二是反向代理转发到后端的应用程序。它本身就带编译依赖直接从 apt 装就行。4.1 安装与基础配置sudo apt install -y nginx sudo systemctl status nginx装好后浏览器访问服务器 IP看到 Nginx 默认欢迎页就说明安装成功。Nginx 的主配置文件是/etc/nginx/nginx.conf站点配置一般放在/etc/nginx/sites-available/目录下然后软链接到/etc/nginx/sites-enabled/。这种“可用”和“启用”分离的结构多站点管理时特别清晰。4.2 配置站点和反向代理我直接给一个生产环境可用的站点配置模板# /etc/nginx/sites-available/myapp.conf server { listen 80; server_name api.example.com; # 静态文件访问日志格式 access_log /var/log/nginx/myapp_access.log; error_log /var/log/nginx/myapp_error.log; # 静态资源直接走文件系统 location /static/ { alias /var/www/myapp/static/; expires 30d; add_header Cache-Control public, immutable; } # 其余请求后端处理 location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }启用站点sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginxnginx -t这一步必须做它能帮你检查配置文件语法是否正确。配置语法错了直接 reloadNginx 会拒绝加载新配置反而保持旧配置运行。4.3 SSL 证书配置现在正规站点都要求 HTTPS证书推荐用 Let‘s Encrypt 的免费证书。先用 certbot 获取证书sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d api.example.com这种验证方式会自动修改 Nginx 配置把 80 端口服务加上 443 的 SSL 配置并设置自动续期证书的定时任务。如果你的证书是别的方式比如云厂商申请的需要手动配置。在 Nginx 的 server 块里加上listen 443 ssl; ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;很多人在替换 SSL 证书后抱怨“不生效”排查思路很简单看进程是否重新加载了配置再看证书路径有没有权限问题。用nginx -t检查语法用sudo systemctl reload nginx重载配置用openssl x509 -in /path/to/fullchain.pem -noout -dates看证书有效期。实操心得Nginx 的日志是排查问题最好的线索。访问异常时第一时间打开/var/log/nginx/error.log看有没有权限错误、proxy 连接失败这类关键信息。很多 502 Bad Gateway 都是后端服务没启动、端口监听错位导致的日志里会直接写出来。5. 全自动备份脚本设计与实现上面的三个组件都部署完了业务跑起来最后一件事也是最重要的一件事备份。很多人以为备份就是把数据库导出一份放服务器上就行其实远远不够。真正的备份系统要满足三个条件能定时跑、能安全存放、能恢复验证。备份不仅是数据库还要把 Redis 的持久化文件、Nginx 的配置文件一起背起来。哪天真出事靠的是一整套环境可复原而不只是数据库里有数据。5.1 编写核心备份脚本我写的是一个既能备份、又能滚动清理的 Shell 脚本统一放在/usr/local/bin/backup_all.sh。脚本内容如下#!/bin/bash set -euo pipefail # 配置区 BACKUP_ROOT/data/backups MYSQL_USERbackup_user MYSQL_PASSWORDYourBackupUser_Password REDIS_PASSWORDYourRedis_StrongPassword REMOTE_BACKUP_DIR/remote/backup RETENTION_DAYS7 DATE$(date %Y%m%d_%H%M%S) # # 创建当天备份目录 mkdir -p ${BACKUP_ROOT}/${DATE} # 1. MySQL 全量备份 mysqldump -u${MYSQL_USER} -p${MYSQL_PASSWORD} \ --single-transaction --routines --triggers \ --all-databases | gzip ${BACKUP_ROOT}/${DATE}/mysql_all.sql.gz # 2. Redis RDB 文件备份需要先执行 SAVE 强制生成最新快照 redis-cli -a ${REDIS_PASSWORD} SAVE # 用 CONFIG GET 拿到 RDB 文件实际路径 RDB_PATH$(redis-cli -a ${REDIS_PASSWORD} --no-raw CONFIG GET dir | tail -1) RDB_FILE$(redis-cli -a ${REDIS_PASSWORD} --no-raw CONFIG GET dbfilename | tail -1) cp ${RDB_PATH}/${RDB_FILE} ${BACKUP_ROOT}/${DATE}/ # 3. Nginx 配置备份 tar czf ${BACKUP_ROOT}/${DATE}/nginx_conf.tar.gz -C /etc nginx/ # 4. 同步到远程服务器 rsync -avz --delete ${BACKUP_ROOT}/${DATE}/ backupremote_host:${REMOTE_BACKUP_DIR}/ # 5. 清理本机超过保留天数的旧备份 find ${BACKUP_ROOT} -type d -mtime ${RETENTION_DAYS} -exec rm -rf {} \; find ${BACKUP_ROOT} -type f -mtime ${RETENTION_DAYS} -delete echo [$(date %Y-%m-%d %H:%M:%S)] Backup complete: ${BACKUP_ROOT}/${DATE}来说几个关键细节mysqldump加上--single-transaction是在不锁表的情况下做一致性备份对正在运行的业务几乎无感知。加上--routines和--triggers是因为默认情况下存储过程和触发器不会被导出来少了它们恢复出来的数据库功能不完整。脚本里备份前先执行 Redis 的SAVE是为了确保 RDB 文件是最新的。Redis 的 RDB 默认是按时点自动落盘的直接拷贝磁盘上的文件可能丢失最近一段时间的数据。rsync同步到远程服务器的好处是增量传输每次只传变化的文件带宽占用小。异地备份的最大意义是防“机器级故障”——服务器硬盘坏了、机房出事了本机备份跟着一起完蛋唯独异地上还有一份。5.2 创建专用备份账号细心的你可能注意到了脚本里用的 MySQL 账号是backup_user。我建议单独建一个只有备份权限的账号避免脚本里使用 root 高权限账号CREATE USER backup_userlocalhost IDENTIFIED BY YourBackupUser_Password; GRANT SELECT, SHOW VIEW, TRIGGER ON *.* TO backup_userlocalhost; GRANT LOCK TABLES ON *.* TO backup_userlocalhost; FLUSH PRIVILEGES;这样即使备份脚本文件泄露攻击者也拿不到一个能删数据的账号算是个低成本高回报的安全习惯。5.3 定时任务 crontab 配置脚本写好了还需要让系统按计划自动执行。用 crontab 添加定时任务crontab -e加入下面一行代表每天凌晨 2 点执行备份脚本0 2 * * * /usr/local/bin/backup_all.sh /var/log/backup_all.log 21关于执行时间的选择凌晨 2 点通常是业务低峰期mysqldump对 IO 的影响最小避开其他定时任务日志轮转、证书续期等的集中时间点脚本里的日志输出重定向到文件是为了出错时有迹可查。不过我不会只依赖这一点而是让定时任务配合外部监控工具执行失败时脚本返回非零退出码监控工具检测到后会自动告警这样哪天备份坏了你能第一时间知道。5.4 备份验证与恢复演练备份算是搭起来了但我必须说实话没验证过的备份等于没备份。有多少人备份脚本跑了一年真出事恢复时才发现导出的文件是坏的默认的概率不低。我的做法是每月至少做一次恢复演练。找个测试环境执行以下步骤# 1. 解压备份文件 gunzip -c mysql_all.sql.gz mysql_all.sql # 2. 重建数据库 mysql -u root -p mysql_all.sql # 3. 验证关键表数据 mysql -u root -p -e SELECT COUNT(*) FROM app_db.users;恢复成功后还会检查 Nginx 配置备份能不能正常解析sudo mkdir -p /tmp/nginx_test sudo tar xzf nginx_conf.tar.gz -C /tmp/nginx_test sudo nginx -t -c /tmp/nginx_test/etc/nginx/nginx.conf把这几条命令写进一个restore_test.sh脚本里每月手动执行一次。恢复演练虽然麻烦但能确保真出事时手不慌。一个可正常恢复的备份才配叫备份无法恢复的只是给硬盘白白占空间的死数据。6. 常见问题与排错速查这套流程跑下来大概率会碰到一些问题。我把自己部署和帮别人排查过程中遇到的高频问题列成一张速查表直接按图索骥就好。现象可能原因排查命令/方法MySQL 远程连接超时UFW 或云安全组未放行 3306sudo ufw status云控制台检查安全组MySQL 本地登录失败密码策略太强不符合规则sudo mysql -u root用 auth_socket 方式登录后重设Redis 连接被拒绝bind 配置仍为 127.0.0.1检查/etc/redis/redis.conf的 bind 行Redis 需要密码才能访问requirepass 已设置连接时加-a参数Nginx 返回 502后端服务未启动或端口不对systemctl status 你的服务ss -tlnpNginx 配置重载失败语法错误sudo nginx -t定位具体错误行备份脚本运行失败mysql 密码包含特殊字符被 shell 解析脚本中用单引号包裹密码或改用配置文件传参crontab 执行了但没生成备份脚本权限或 PATH 问题bash /usr/local/bin/backup_all.sh手动跑一遍看报错其中两个我单独多说两句。第一个是 MySQL 密码策略。MySQL 8.0 默认的密码校验强度要求比较高如果你设的密码不够复杂会直接报错。开发环境不想折腾密码复杂度的话可以临时调低策略SET GLOBAL validate_password.policy LOW; SET GLOBAL validate_password.length 8;第二个是 Nginx 替换 SSL 证书不生效。很多人改完证书文件页面还是旧的这通常不是 Nginx 的问题而是证书链文件本身过期了或者更新后没有彻底重载 worker 进程。用curl -vI https://你的域名查看实际返回的证书内容用sudo systemctl reload nginx重载再不行就sudo systemctl restart nginx完全重启。注意线上环境能用reload就不要用restart。reload是平滑重载不影响正在处理的请求restart会中断所有连接极端情况下会造成请求丢失。7. 部署完成后的检查清单环境全部搭完别急着跑路。最后按下面这份清单逐项打勾确认每个环节没问题再交付[ ] MySQL 能本地登录业务账号权限正常3306 端口仅对需要的 IP 开放[ ] Redis 设置了密码FLUSHALL已禁用6379 端口未对外网开放[ ] Nginx 配置无语法错误SSL 证书未过期站点能正常访问[ ] 备份脚本手动执行成功/data/backups/下有当天的新备份文件[ ] crontab 任务已生效crontab -l能看到[ ] 备份文件已同步到远程服务器远程目录内容不空[ ] 在测试库上至少做了一次恢复演练业务数据能完整恢复这套组合拳打下来一套“能干活、难搞坏、坏了能恢复”的 Ubuntu 后端环境就落地了。中间的花样不多每一步都是生产环境验证过的稳妥选择——官方源、最小权限、持久化开启、异地备份目的就一个让你在业务壮大的路上底层的这些基础设施别成为短板。最后再分享一个小经验脚本里所有的密码和密钥不要直接写在脚本文件里用环境变量或者单独的配置文件加载权限设为 600。服务器上的密码泄露往往不是被暴力破解而是文件权限太宽松被顺手看了去这点真不是小事。
返回列表