Ansible实战:LNMP一键部署指南
文章目录第一步控制机环境准备安装 Ansible 与配置 SSH第二步创建基于 Roles 标准目录结构的项目第三步编写主机清单 (Inventory) 和各个 Roles 代码1. 创建主机清单 hosts.ini2. 编写 Nginx 角色拉取 Nginx 官方源并配置反向代理到 PHP3. 编写 PHP 角色从 Remi 源拉取 PHP 8.1配置参数与截图一致4. 编写 MySQL 角色拉取 MySQL 8.0 官方源第四步编写主入口 Playbook (site.yml)第五步执行部署与自主检测第六步浏览器可视化验证错误显示有错误再进行下列操作1、页面显示默认首页1.1 为什么主机名匹配不上1.2 解决步骤请按顺序执行第一步恢复带有链接的首页第二步检查 PHP 是否安装并启动关键第三步确认 PHP 测试文件是否存在第四步确认 Nginx 配置正确且已重启第五步在浏览器验证第一步控制机环境准备安装 Ansible 与配置 SSH1. 在192.168.30.198机器上安装 Ansible# 1. 安装 EPEL 源Ansible 依赖此源dnfinstallepel-release-y# 2. 安装 Ansiblednfinstallansible-y# 3. 检测安装是否成功自主检测命令ansible--version# 预期输出ansible [core 2.x.x] ...2. 配置 SSH 免密登录到目标机器192.168.30.199# 1. 生成 SSH 密钥一路回车即可ssh-keygen-trsa-b4096-f~/.ssh/id_rsa-N# 2. 将公钥发送到 199 主机需要输入一次 199 机器的 root 密码ssh-copy-id root192.168.30.199# 3. 修改目标机器主机名可选匹配后续 Playbook 的模板sshroot192.168.30.199hostnamectl set-hostname gaoxf199# 4. 测试 SSH 连通性自主检测命令sshroot192.168.30.199hostname# 预期输出gaoxf199第二步创建基于 Roles 标准目录结构的项目在192.168.30.198控制机上执行# 创建 LNMP 项目文件夹及 Roles 各级目录mkdir-p~/lnmp-roles/{roles/{nginx,mysql,php}/{tasks,templates,vars,handlers},group_vars}cd~/lnmp-roles第三步编写主机清单 (Inventory) 和各个 Roles 代码这里我们直接使用cat生成文件。请在~/lnmp-roles目录下逐条复制以下命令并执行1. 创建主机清单hosts.inicathosts.iniEOF [webserver] 192.168.30.199 ansible_userroot ansible_python_interpreter/usr/bin/python3 EOF2. 编写 Nginx 角色拉取 Nginx 官方源并配置反向代理到 PHP# 2.1 任务文件catroles/nginx/tasks/main.ymlEOF --- - name: 安装依赖包 yum: name: epel-release state: present - name: 添加 Nginx 官方 Yum 源 (Rocky 9) yum_repository: name: nginx description: Nginx Official YUM Repository baseurl: http://nginx.org/packages/centos/9/$basearch/ gpgcheck: yes gpgkey: https://nginx.org/keys/nginx_signing.key enabled: yes - name: 从官方源安装 Nginx (会自动导入 GPG 密钥) yum: name: nginx state: present - name: 部署优化版 Nginx 主配置 template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf notify: restart nginx - name: 部署虚拟主机模板 (支持PHP解析) template: src: vhost.conf.j2 dest: /etc/nginx/conf.d/www.conf notify: restart nginx - name: 启动 Nginx 并设置开机自启 systemd: name: nginx state: started enabled: yes EOF# 2.2 Nginx 主配置模板catroles/nginx/templates/nginx.conf.j2EOF user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 4096; include /etc/nginx/mime.types; default_type application/octet-stream; include /etc/nginx/conf.d/*.conf; } EOF# 2.3 Nginx 虚拟主机模板catroles/nginx/templates/vhost.conf.j2EOF server { listen 80 default_server; server_name _; root /usr/share/nginx/html; index index.php index.html index.htm; charset utf-8; # --- 关键加上这一行强制浏览器使用UTF-8 location / { } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } EOF# 2.4 Nginx 处理器catroles/nginx/handlers/main.ymlEOF --- - name: restart nginx systemd: name: nginx state: restarted EOF3. 编写 PHP 角色从 Remi 源拉取 PHP 8.1配置参数与截图一致# 3.1 PHP 任务文件catroles/php/tasks/main.ymlEOF --- - name: 安装 Remi 源 (针对 PHP 8.1) - 首次安装跳过 GPG 检查 yum: name: https://rpms.remirepo.net/enterprise/remi-release-9.rpm state: present disable_gpg_check: yes - name: 重置 PHP 模块流 command: dnf module reset php -y - name: 启用 PHP 8.1 模块流 command: dnf module enable php:8.1 -y - name: 安装 PHP 8.1 及 FPM 和相关扩展 yum: name: - php-fpm - php-cli - php-mysqlnd - php-gd - php-xml - php-mbstring - php-opcache state: present - name: 部署优化版 php.ini (修改内存、上传限制等) template: src: php.ini.j2 dest: /etc/php.ini notify: restart php-fpm - name: 部署优化版 www.conf (修改 max_children20 等) template: src: www.conf.j2 dest: /etc/php-fpm.d/www.conf notify: restart php-fpm - name: 创建 phpinfo 测试页 copy: content: ?php phpinfo(); ? dest: /usr/share/nginx/html/info.php - name: 启动 PHP-FPM 并设置开机自启 systemd: name: php-fpm state: started enabled: yes - name: SELinux 放行 Nginx 网络连接 (防止403/502错误) ansible.posix.seboolean: name: httpd_can_network_connect state: yes persistent: yes when: ansible_selinux.status enabled EOF# 3.2 PHP 配置模板 php.ini.j2catroles/php/templates/php.ini.j2EOF ; 优化核心参数 memory_limit 256M upload_max_filesize 50M post_max_size 50M date.timezone Asia/Shanghai EOF# 3.3 PHP-FPM 进程池模板 www.conf.j2catroles/php/templates/www.conf.j2EOF [www] user apache group apache listen 127.0.0.1:9000 pm dynamic pm.max_children 20 pm.start_servers 5 pm.min_spare_servers 5 pm.max_spare_servers 10 EOF# 3.4 PHP 处理器catroles/php/handlers/main.ymlEOF --- - name: restart php-fpm systemd: name: php-fpm state: restarted EOF4. 编写 MySQL 角色拉取 MySQL 8.0 官方源# 4.1 MySQL 任务文件catroles/mysql/tasks/main.ymlEOF --- - name: 强制导入 MySQL 官方 GPG 公钥 (解决安装包时的签名验证失败问题) shell: rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql changed_when: false ignore_errors: yes # 即使下载公钥失败也继续往下走因为有下一步的跳过 gpg 检查兜底。 - name: 配置 MySQL 8.0 官方 Yum 源 (清华镜像加速) yum_repository: name: mysql80-community description: MySQL 8.0 Community Server YUM Repo baseurl: https://mirrors.tuna.tsinghua.edu.cn/mysql/yum/mysql-8.0-community-el9-$basearch/ gpgcheck: yes gpgkey: https://repo.mysql.com/RPM-GPG-KEY-mysql enabled: yes sslverify: no - name: 从配置好的 Yum 源安装 MySQL Server (强制跳过 GPG 校验) yum: name: mysql-community-server state: present disable_gpg_check: yes # 关键这一行将彻底解决拦截问题 - name: 启动 MySQL 并设置开机自启 systemd: name: mysqld state: started enabled: yes - name: 获取 MySQL 初始临时 root 密码 shell: grep temporary password /var/log/mysqld.log | awk {print $NF} register: mysql_temp_pass changed_when: false EOF第四步编写主入口 Playbook (site.yml)catsite.ymlEOF --- - name: 部署 LNMP 生产环境至 199 服务器 hosts: webserver gather_facts: yes roles: - role: nginx - role: php - role: mysql post_tasks: - name: 端口连通性健康检查 (Nginx 80, PHP-FPM 9000) wait_for: port: {{ item }} host: 127.0.0.1 timeout: 5 loop: - 80 - 9000 - name: 输出部署成功结果Web测试地址 debug: msg: - - LNMP 部署完成 - 目标主机: gaoxf199 (192.168.30.199) - PHP 测试页: http://192.168.30.199/info.php - Nginx 主页: http://192.168.30.199 - EOF第五步执行部署与自主检测现在所有 Roles 和 Playbook 已经就绪。在~/lnmp-roles目录下执行1. 运行主 Playbook自动拉取依赖、软件源并安装ansible-playbook-ihosts.ini site.yml(执行过程中控制台会显示绿色的ok,changed等状态和您提供的截图中一样其中 PHP 会重置模块流这就是截图里的TASK [重置 PHP 模块])2. 在控制机上验证服务是否成功运行自主检测命令# 1. 检测 Ping 连通性ansible all-ihosts.ini-mping# 2. 远程在目标机查看端口监听状态 (检测 Nginx, PHP-FPM 是否正常)ansible192.168.30.199-ihosts.ini-mshell-ass -tlnp | grep -E :(80|9000|3306)# 预期输出包含 LISTEN 状态的 80, 9000, 3306# 3. 远程在目标机测试 PHP-FPM 和 Nginx 是否连接正常ansible192.168.30.199-ihosts.ini-mshell-acurl -I http://127.0.0.1/info.php# 预期输出HTTP/1.1 200 OK第六步浏览器可视化验证在您的本地电脑或任何与 198/199 网络互通的主机的浏览器地址栏输入http://192.168.30.199预期结果将显示类似您提供的图 6、7、8 中的“Welcome to gaoxf199”以及“Nginx deployed by Ansible”并带有「PHP Info」超链接。点击「PHP Info」或直接访问http://192.168.30.199/info.php预期结果显示紫色的PHP Version 8.1.32信息大表格与您的图9完全一致。在此页面搜索memory_limit能看到值为256M搜索upload_max_filesize能看到值为50M表明您的优化模板已经成功生效。错误显示有错误再进行下列操作1、页面显示默认首页建议执行完下面的操作且修改完服务器上的文件后再去控制机重新跑一遍ansible-playbook -i hosts.ini site.yml这次 MySQL 已修复应该能完全接管并推送修改的模板了。看到这个默认的 Nginx 欢迎页说明Nginx 进程已经成功启动了但是自定义虚拟主机配置文件没有生效。因为系统中原本自带了一个默认的配置文件default.conf它抢占了 IP 的访问请求。1.1 为什么主机名匹配不上在 Ansiblevhost.conf.j2模板中配置的是server_name {{ ansible_fqdn }}; # 这里是 第二台机器的主机名但在浏览器中直接输入的是 IP192.168.30.199。在 Nginx 中默认配置文件default.conf通常设置了server_name _;通配符。Nginx 只会将 IP 请求匹配给通配符配置而不会匹配给主机名配置所以默认页面就被“抢”到了。1.2 解决步骤请按顺序执行在目标机192.168.30.199上操作即可完成sshroot192.168.30.199第一步恢复带有链接的首页在目标机上执行cat/usr/share/nginx/html/index.htmlEOF h1Welcome to gaoxf199/h1 pNginx deployed by Ansible/p a href/info.phpPHP Info/a EOF第二步检查 PHP 是否安装并启动关键如果 PHP 没起来点链接会报 404 或 502 错误。请执行# 查看 PHP-FPM 状态systemctl status php-fpm# 如果显示 inactive (dead)请启动它systemctl start php-fpm systemctlenablephp-fpm第三步确认 PHP 测试文件是否存在ls-l/usr/share/nginx/html/info.php如果不存在手动创建echo?php phpinfo(); ?/usr/share/nginx/html/info.php第四步确认 Nginx 配置正确且已重启# 测试配置文件是否有语法错误nginx-t# 如果没问题重启 Nginx 让 PHP 解析生效systemctl restart nginx# 确认 PHP 转发地址匹配grepfastcgi_pass/etc/nginx/conf.d/www.conf# 必须输出fastcgi_pass 127.0.0.1:9000;第五步在浏览器验证现在访问http://192.168.30.199就能看到PHP Info的超链接了。点击进去就会显示紫色的PHP Version 8.1.32页面。如果打开了 PHP 页面说明 Nginx 到 PHP 的桥接已经彻底打通。

相关新闻

Dify调用本地API服务报错403?一篇文章帮你彻底排查网络与代理问题

Dify调用本地API服务报错403?一篇文章帮你彻底排查网络与代理问题

背景最近在Dify平台搭建工作流时,需要调用同服务器上的一个本地API服务。本来以为在同一台机器上,用localhost或127.0.0.1就能轻松搞定,结果却遇到了一连串的网络问题,从403 Forbidden到Connection refused,再到Tempor…

2026/8/27 21:12:37 阅读更多 →
Havenlon | 杂谈:AI 为什么越来越像人?因为它正在经历一次“厚积薄发“

Havenlon | 杂谈:AI 为什么越来越像人?因为它正在经历一次“厚积薄发“

小时候,大人常对我们说一句话:书读多了,人会越来越聪明。这句话在当时几乎无法被验证。一本书读完,人不会立刻变得不同;十本书读完,一个孩子与同龄人之间也看不出明显差距。它更像一句安慰,而不…

2026/8/26 15:45:12 阅读更多 →
Logs 的原理

Logs 的原理

目录 第一部分 Logs 第二部分 操作 第三部分 AI 要点(只建框架) 第一部分 Logs 1. 一条日志本质上是什么 一条日志 带时间戳的事件记录。最小形态:时间 谁说的 严重程度 说了什么 可观测性里还希望有:服务名、实…

2026/8/25 14:07:01 阅读更多 →

最新新闻

AI飞行救生机器人:自主导航与目标检测技术拆解

AI飞行救生机器人:自主导航与目标检测技术拆解

会飞的救生圈来了!国产AI飞行救生机器人可自主导航搜救 水域救援最难的环节,从来不是“把人救上来”,而是在宽阔、昏暗、波涛起伏的水面上,快速发现落水者并准确抵达他身边。 传统搜救依赖目视观察、望远镜、岸上指挥&#xff0…

2026/8/27 21:13:26 阅读更多 →
本地媒体脱敏实战:人脸打码、EXIF清理与视频抽帧

本地媒体脱敏实战:人脸打码、EXIF清理与视频抽帧

一则外媒报道里,有人被形容成“几乎像个蝙蝠侠式的人物”,又被比作“复仇的Mother Courage”。这种标签通常会在社交平台快速完成符号化传播:一个普通人的故事被压缩成几个关键词,配合一张图片或者一段短视频,瞬间跨平…

2026/8/27 21:13:26 阅读更多 →
三维可视化的性能检查方法

三维可视化的性能检查方法

三维可视化的性能检查方法三维页面的瓶颈可能在资源、绘制调用或着色器。先用浏览器与图形调试工具分开观察加载时间、帧时间和显存占用,不把卡顿都归因于模型数量。 控制资源生命周期 离开场景时释放纹理、几何体和渲染目标;共享资源要有明确所有者。压…

2026/8/27 21:13:26 阅读更多 →
数据可视化工具的选型与验证

数据可视化工具的选型与验证

数据可视化工具的选型与验证可视化选型先看数据规模、交互需求和无障碍要求。图表库提供的默认样式并不保证读者能正确理解数据,口径和缺失值处理仍需说明。 用任务检验表达 准备几项真实阅读任务,例如比较趋势、定位异常和查看明细。检查颜色、标签和交…

2026/8/27 21:13:26 阅读更多 →
高级组件模式的边界设计

高级组件模式的边界设计

高级组件模式的边界设计组件抽象先处理状态归属,再讨论复用。字段值、校验状态和展示文案应各有来源;组件只渲染并派发事件,提交策略留给业务层。 检查可替换性 当组件需要依赖路由、接口或全局状态时,先明确这些依赖如何注入。为…

2026/8/27 21:13:26 阅读更多 →
Agent任务拆解:从Prompt到可校验可追踪的稳定工程流程

Agent任务拆解:从Prompt到可校验可追踪的稳定工程流程

很多开发者在搭完第一个 Agent 的时候,都会经历一个类似的心路历程:Demo 阶段一切都很丝滑,让大模型查资料、写代码、调工具,每一步都像模像样;一旦把真实业务接进系统,Agent 就开始花式翻车。要么漏掉关键…

2026/8/27 21:12:25 阅读更多 →

日新闻

Go语言构建企业级AI服务网关:统一管理英伟达等AI接口调用

Go语言构建企业级AI服务网关:统一管理英伟达等AI接口调用

1. 项目概述:从零构建一个企业级的AI服务网关 最近在帮一个做内容审核的团队做技术架构升级,他们原来的业务里,每天有几十万张图片和短视频需要过审,最初是接了几个开源的AI模型自己部署,但效果和性能一直不太稳定。后…

2026/8/27 0:00:51 阅读更多 →
网盘直链下载助手5分钟解析八大网盘真实地址

网盘直链下载助手5分钟解析八大网盘真实地址

网盘直链下载助手5分钟解析八大网盘真实地址 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / 迅雷云盘 / 夸…

2026/8/27 1:06:27 阅读更多 →
从零点亮 ESP32:Arduino ESP32 开发环境搭建与首次烧录完整指南

从零点亮 ESP32:Arduino ESP32 开发环境搭建与首次烧录完整指南

从零点亮 ESP32:Arduino ESP32 开发环境搭建与首次烧录完整指南 【免费下载链接】arduino-esp32 Arduino core for the ESP32 family of SoCs 项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32 Arduino ESP32 是乐鑫官方的 ESP32 系列 Ardui…

2026/8/27 1:06:27 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/26 14:45:33 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/26 17:46:43 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/26 14:46:37 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/27 17:46:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/26 17:46:39 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/27 20:00:17 阅读更多 →