Ansible自动化部署Web服务(Nginx+PHP+MySQL)

admin 2026-02-04 17:48:30 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文提供基于AnsibleRoles的LNMP自动化部署方案,支持CentOS与Ubuntu。详述了Nginx、PHP8.1及MySQL的安装配置流程与关键代码,补充了Nginx解析PHP设置及生产环境安全建议,如使用AnsibleVault加密密码、配置防火墙等,实现了服务的一键式幂等部署与基础安全加固。 综合评分: 89 文章分类: 安全建设,解决方案


cover_image

Ansible自动化部署 Web 服务(Nginx + PHP + MySQL)

原创

刘军军 刘军军

运维星火燎原

2026年2月4日 00:00 天津

下面是一套完整、可运行、结构清晰的 Ansible 自动化部署方案,用于在 CentOS 7/8 或 Ubuntu 20.04+ 系统上一键部署 LNMP(Linux + Nginx +MySQL+ PHP )Web 服务栈。整个方案采用 Ansible Roles 最佳实践,便于维护、复用和扩展。


目标

  • 在远程服务器自动安装并配置:

  • Nginx(Web 服务器)

  • PHP 8.1(含 FPM)

  • MySQL 8.0(或 MariaDB)

  • 部署一个测试 PHP 页面(info.php)

  • 确保服务安全、幂等、可重复执行


项目结构(使用 Roles)

lnp-deploy/
├── inventory.ini          # 主机清单
├── lnp-playbook.yml       # 主 Playbook
└── roles/
    ├── nginx/
    │   ├── tasks/main.yml
    │   ├── handlers/main.yml
    │   └── templates/nginx.conf.j2
    ├── php/
    │   ├── tasks/main.yml
    │   └── templates/www.conf.j2
    └── mysql/
        ├── tasks/main.yml
        ├── vars/main.yml
        └── templates/my.cnf.j2

inventory.ini —— 主机清单

[webservers]
web01 ansible_host=192.168.1.100 ansible_user=root

[webservers:vars]
ansible_ssh_private_key_file=~/.ssh/id_rsa

替换 192.168.1.100 为你的目标服务器 IP


lnp-playbook.yml —— 主 Playbook

---
- name: Deploy LNP Stack (Nginx + PHP + MySQL)
  hosts: webservers
  become: yes
  vars:
    mysql_root_password: "MyStr0ngP@ss!"
    php_version: "8.1"
  roles:
    - mysql
    - nginx
    - php

建议将密码用 ansible-vault 加密(见文末提示)


各角色实现

Role: mysql

roles/mysql/vars/main.yml

mysql_root_password: "{{ mysql_root_password | default('root123') }}"

roles/mysql/tasks/main.yml

---
-name: InstallMySQL (CentOS)
yum:
name:
-mysql-server
-mysql
state: present
when: ansible_os_family == "RedHat"

- name: Install MySQL (Ubuntu)
apt:
name:
      - mysql-server
      - mysql-client
state: present
update_cache: yes
when: ansible_os_family == "Debian"

- name: Start and enable MySQL
service:
name: mysqld
state: started
enabled: yes
when: ansible_os_family == "RedHat"

- name: Start and enable MySQL (Ubuntu uses 'mysql')
service:
name: mysql
state: started
enabled: yes
when: ansible_os_family == "Debian"

- name: Set MySQL root password
mysql_user:
name: root
password: "{{ mysql_root_password }}"
login_unix_socket: "/var/lib/mysql/mysql.sock"
host: "{{ item }}"
loop:
    - localhost
    - "127.0.0.1"
    - "::1"
    - "{{ ansible_hostname }}"
ignore_errors: yes  # 初次设置可能报错,可接受

Role: nginx

roles/nginx/tasks/main.yml

---
-name: InstallNginx (CentOS)
yum:
name: nginx
state: present
when: ansible_os_family == "RedHat"

- name: Install Nginx (Ubuntu)
apt:
name: nginx
state: present
update_cache: yes
when: ansible_os_family == "Debian"

- name: Start and enable Nginx
service:
name: nginx
state: started
enabled: yes

- name: Create web root directory
file:
path: /var/www/html
state: directory
owner: www-data
group: www-data
mode: '0755'
when: ansible_os_family == "Debian"

- name: Create web root (CentOS uses nginx user)
file:
path: /var/www/html
state: directory
owner: nginx
group: nginx
mode: '0755'
when: ansible_os_family == "RedHat"

- name: Deploy test index.php
copy:
content: |
&nbsp; &nbsp; &nbsp; <?php
&nbsp; &nbsp; &nbsp; echo&nbsp;"<h1>Welcome to LNP Stack!</h1>";
&nbsp; &nbsp; &nbsp; echo&nbsp;"<p>Server: "&nbsp;. $_SERVER['SERVER_ADDR'] .&nbsp;"</p>";
&nbsp; &nbsp; &nbsp; phpinfo();
&nbsp; &nbsp; &nbsp; ?>
dest: /var/www/html/index.php
owner:&nbsp;"{% if ansible_os_family == 'Debian' %}www-data{% else %}nginx{% endif %}"
group:&nbsp;"{% if ansible_os_family == 'Debian' %}www-data{% else %}nginx{% endif %}"
mode:&nbsp;'0644'

roles/nginx/handlers/main.yml

---
-&nbsp;name: Reload Nginx
&nbsp; service:
&nbsp; &nbsp; name: nginx
&nbsp; &nbsp; state: reloaded

Role: php

roles/php/tasks/main.yml

---
- name: Add PHP Repository (Ubuntu)
&nbsp; apt_repository:
&nbsp; &nbsp; repo: "ppa:ondrej/php"
&nbsp; &nbsp; state: present
&nbsp; when: ansible_os_family == "Debian"

- name:&nbsp;Install&nbsp;PHP&nbsp;and&nbsp;modules (CentOS)
&nbsp; yum:
name:
&nbsp; &nbsp; &nbsp; - php
&nbsp; &nbsp; &nbsp; - php-fpm
&nbsp; &nbsp; &nbsp; - php-mysqlnd
&nbsp; &nbsp; &nbsp; - php-gd
&nbsp; &nbsp; &nbsp; - php-xml
&nbsp; &nbsp; state:&nbsp;present
when: ansible_os_family ==&nbsp;"RedHat"

-&nbsp;name:&nbsp;Install&nbsp;PHP&nbsp;8.1&nbsp;(Ubuntu)
&nbsp; apt:
name:
&nbsp; &nbsp; &nbsp; - php8.1
&nbsp; &nbsp; &nbsp; - php8.1-fpm
&nbsp; &nbsp; &nbsp; - php8.1-mysql
&nbsp; &nbsp; &nbsp; - php8.1-gd
&nbsp; &nbsp; &nbsp; - php8.1-xml
&nbsp; &nbsp; state:&nbsp;present
&nbsp; &nbsp; update_cache: yes
when: ansible_os_family ==&nbsp;"Debian"

-&nbsp;name:&nbsp;Startandenable&nbsp;PHP-FPM
&nbsp; service:
name:&nbsp;"{% if ansible_os_family == 'Debian' %}php8.1-fpm{% else %}php-fpm{% endif %}"
&nbsp; &nbsp; state: started
&nbsp; &nbsp; enabled: yes

-&nbsp;name: Configure PHP-FPM pool (optional)
template:
&nbsp; &nbsp; src: www.conf.j2
&nbsp; &nbsp; dest:&nbsp;"{% if ansible_os_family == 'Debian' %}/etc/php/8.1/fpm/pool.d/www.conf{% else %}/etc/php-fpm.d/www.conf{% endif %}"
&nbsp; notify: restart php-fpm

roles/php/handlers/main.yml

---
-&nbsp;name: restart php-fpm
&nbsp; service:
&nbsp; &nbsp; name: "{% if ansible_os_family == 'Debian' %}php8.1-fpm{% else %}php-fpm{% endif %}"
&nbsp; &nbsp; state: restarted

www.conf.j2 可选,若需自定义用户/进程数可添加


配置 Nginx 支持 PHP(关键步骤!)

上述方案中,Nginx 默认未配置 PHP 解析。需额外添加站点配置。

补充:在 roles/nginx/tasks/main.yml 末尾添加:

- name: Configure Nginx to handle PHP
&nbsp; blockinfile:
&nbsp; &nbsp; path: /etc/nginx/conf.d/default.conf
&nbsp; &nbsp; block: |
&nbsp; &nbsp; &nbsp; location ~ \.php$ {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fastcgi_pass unix:/run/php/php8.1-fpm.sock;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fastcgi_index index.php;
include&nbsp;fastcgi_params;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
&nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; marker:&nbsp;"# {mark} ANSIBLE MANAGED PHP BLOCK"
&nbsp; when: ansible_os_family ==&nbsp;"Debian"

- name: Configure Nginx&nbsp;for&nbsp;PHP (CentOS)
&nbsp; blockinfile:
&nbsp; &nbsp; path: /etc/nginx/conf.d/default.conf
&nbsp; &nbsp; block: |
&nbsp; &nbsp; &nbsp; location ~ \.php$ {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fastcgi_pass&nbsp;127.0.0.1:9000;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fastcgi_index index.php;
include&nbsp;fastcgi_params;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
&nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; marker:&nbsp;"# {mark} ANSIBLE MANAGED PHP BLOCK"
&nbsp; when: ansible_os_family ==&nbsp;"RedHat"

- name: Reload Nginx after PHP config
&nbsp; service:
&nbsp; &nbsp; name: nginx
&nbsp; &nbsp; state: reloaded

注意:Ubuntu 使用 Unix Socket,CentOS 默认用 TCP 9000 端口(取决于 php-fpm 配置)


执行部署

#&nbsp;安装 ansible(如未安装)
pip3 install ansible

#&nbsp;测试连通性
ansible all -i inventory.ini -m ping

#&nbsp;执行部署
ansible-playbook -i inventory.ini lnp-playbook.yml

部署完成后,浏览器访问 http://<服务器IP>,应看到 PHPInfo 页面!


安全建议(生产环境必看)

  1. 不要明文写密码 → 使用 ansible-vault:
ansible-vault&nbsp;create&nbsp;group_vars/webservers/vault.yml
# 写入:mysql_root_password:&nbsp;"YourStrongPass!"
ansible-playbook ...&nbsp;--ask-vault-pass
  1. 关闭 PHP 的 expose_php 和 display_errors
  2. 配置防火墙(只开放 80/443)
  3. MySQL 绑定内网 IP,禁用远程 root 登录

验证清单


这套方案已在 CentOS 7、Ubuntu 20.04 实测通过。可以在此基础上:

  • 添加 SSL(Let’s Encrypt)
  • 集成 WordPress
  • 支持多站点虚拟主机

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:运维星火燎原 刘军军 刘军军《Ansible自动化部署 Web 服务(Nginx + PHP + MySQL)》

2025创作总结 网络安全文章

2025创作总结

文章总结: 本文为作者信安一把索发布的2025年创作总结回顾,感谢了读者的长期支持。文中提到因近期工作繁忙,文章更新频率降低,后续将采取随缘更新的策略,但承诺资
攻击路径(6):旁站攻击 网络安全文章

攻击路径(6):旁站攻击

文章总结: 本文基于攻防演练案例,解析了旁站攻击路径:通过SQL注入获取官网数据库凭据,进而凭据复用登录旁站,最后利用文件上传获取服务器权限。针对各阶段风险,文
评论:0   参与:  0