package services
// PlaybookTemplate Playbook模板定义
type PlaybookTemplate struct {
ID string `json:"id"`
Name string `json:"name"`
Category string `json:"category"`
Description string `json:"description"`
Icon string `json:"icon"`
Content string `json:"content"`
Tags []string `json:"tags"`
}
// TemplateCategory 模板分类
type TemplateCategory struct {
ID string `json:"id"`
Name string `json:"name"`
Icon string `json:"icon"`
Count int `json:"count"`
}
// GetTemplateCategories 获取所有模板分类
func GetTemplateCategories() []TemplateCategory {
cats := map[string]TemplateCategory{}
for _, t := range GetPlaybookTemplates() {
c, ok := cats[t.Category]
if !ok {
c = TemplateCategory{ID: t.Category, Name: categoryNames[t.Category], Icon: categoryIcons[t.Category]}
}
c.Count++
cats[t.Category] = c
}
var result []TemplateCategory
// 按固定顺序输出
order := []string{"system", "web", "database", "container", "devops", "security", "monitoring"}
for _, id := range order {
if c, ok := cats[id]; ok {
result = append(result, c)
}
}
return result
}
var categoryNames = map[string]string{
"system": "系统管理",
"web": "Web服务",
"database": "数据库",
"container": "容器化",
"devops": "DevOps",
"security": "安全加固",
"monitoring": "监控告警",
}
var categoryIcons = map[string]string{
"system": "🖥️",
"web": "🌐",
"database": "🗄️",
"container": "🐳",
"devops": "🔧",
"security": "🔒",
"monitoring": "📊",
}
// GetPlaybookTemplates 获取所有Playbook模板
func GetPlaybookTemplates() []PlaybookTemplate {
return []PlaybookTemplate{
// ===== 系统管理 =====
{
ID: "update-packages", Name: "系统包更新", Category: "system",
Description: "自动更新系统软件包,支持Debian/RedHat系列",
Icon: "📦", Tags: []string{"update", "apt", "yum"},
Content: `---
- name: 系统包更新
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
update_cache: yes
upgrade_type: dist # dist(完整升级) 或 safe(安全升级)
tasks:
- name: 更新apt缓存
apt:
update_cache: yes
when: ansible_os_family == "Debian"
- name: 升级所有包(Debian)
apt:
upgrade: "{{ upgrade_type }}"
autoremove: yes
autoclean: yes
when: ansible_os_family == "Debian"
- name: 更新yum缓存
yum:
update_cache: yes
when: ansible_os_family == "RedHat"
- name: 升级所有包(RedHat)
yum:
name: "*"
state: latest
when: ansible_os_family == "RedHat"
- name: 检查是否需要重启
stat:
path: /var/run/reboot-required
register: reboot_required
when: ansible_os_family == "Debian"
- name: 提示重启
debug:
msg: "⚠️ 系统需要重启以完成更新"
when: ansible_os_family == "Debian" and reboot_required.stat.exists
`,
},
{
ID: "check-system", Name: "系统信息采集", Category: "system",
Description: "采集操作系统、硬件、网络等详细信息",
Icon: "🔍", Tags: []string{"info", "facts", "inventory"},
Content: `---
- name: 系统信息采集
hosts: "{{ target_hosts | default('all') }}"
gather_facts: yes
tasks:
- name: 操作系统信息
debug:
msg: |
══════════ 系统信息 ══════════
主机名: {{ ansible_facts['hostname'] }}
系统: {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }}
内核: {{ ansible_facts['kernel'] }}
架构: {{ ansible_facts['architecture'] }}
CPU: {{ ansible_facts['processor_vcpus'] }} vCPUs
内存: {{ (ansible_facts['memtotal_mb'] / 1024) | round(2) }} GB
IP: {{ ansible_facts['default_ipv4']['address'] | default('N/A') }}
═══════════════════════════════
- name: 磁盘使用
shell: df -h | grep -E '^/dev/'
register: disk_info
- name: 显示磁盘
debug:
msg: "{{ disk_info.stdout_lines }}"
- name: 运行时间
shell: uptime -p
register: uptime_info
- name: 显示运行时间
debug:
msg: "运行时间: {{ uptime_info.stdout }}"
`,
},
{
ID: "check-resources", Name: "资源监控检查", Category: "system",
Description: "检查CPU/内存/磁盘使用率,超阈值告警",
Icon: "📈", Tags: []string{"monitor", "cpu", "memory", "disk"},
Content: `---
- name: 资源监控检查
hosts: "{{ target_hosts | default('all') }}"
gather_facts: yes
vars:
warn_threshold: 80
crit_threshold: 90
tasks:
- name: 获取CPU使用率
shell: top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1
register: cpu_result
changed_when: false
- name: 获取内存使用率
shell: free | grep Mem | awk '{printf "%.0f", $3/$2*100}'
register: mem_result
changed_when: false
- name: 获取磁盘使用率
shell: df -h / | tail -1 | awk '{print $5}' | tr -d '%'
register: disk_result
changed_when: false
- name: 显示资源报告
debug:
msg: |
═══════ {{ inventory_hostname }} 资源报告 ═══════
CPU 使用率: {{ cpu_result.stdout }}%
内存使用率: {{ mem_result.stdout }}%
磁盘使用率: {{ disk_result.stdout }}%
告警阈值: {{ warn_threshold }}% / 严重: {{ crit_threshold }}%
═══════════════════════════════════════
- name: 严重告警
fail:
msg: "🚨 严重: {{ inventory_hostname }} 资源使用率超过 {{ crit_threshold }}%"
when: >
(cpu_result.stdout | int >= crit_threshold) or
(mem_result.stdout | int >= crit_threshold) or
(disk_result.stdout | int >= crit_threshold)
`,
},
{
ID: "log-cleanup", Name: "日志清理", Category: "system",
Description: "清理系统日志、临时文件,释放磁盘空间",
Icon: "🧹", Tags: []string{"cleanup", "log", "disk"},
Content: `---
- name: 日志清理
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
log_retention_days: 30
tmp_retention_days: 7
tasks:
- name: 清理journal日志
shell: journalctl --vacuum-time={{ log_retention_days }}d
register: journal_result
changed_when: "'Vacuuming' in journal_result.stdout"
- name: 清理旧日志文件
find:
paths: /var/log
patterns: "*.gz,*.old,*.[0-9]"
age: "{{ log_retention_days }}d"
register: old_logs
- name: 删除旧日志
file:
path: "{{ item.path }}"
state: absent
loop: "{{ old_logs.files }}"
- name: 清理临时文件
find:
paths: /tmp
age: "{{ tmp_retention_days }}d"
register: tmp_files
- name: 删除临时文件
file:
path: "{{ item.path }}"
state: absent
loop: "{{ tmp_files.files }}"
ignore_errors: yes
- name: 清理apt缓存
apt:
autoclean: yes
when: ansible_os_family == "Debian"
- name: 显示磁盘空间
shell: df -h /
register: disk_after
- name: 清理完成
debug:
msg: "{{ disk_after.stdout_lines }}"
`,
},
{
ID: "time-sync", Name: "时间同步(NTP)", Category: "system",
Description: "配置NTP时间同步,确保集群时间一致",
Icon: "⏰", Tags: []string{"ntp", "time", "chrony"},
Content: `---
- name: 时间同步配置
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
ntp_servers:
- ntp.aliyun.com
- ntp1.aliyun.com
- pool.ntp.org
tasks:
- name: 安装chrony
package:
name: chrony
state: present
- name: 配置NTP服务器
lineinfile:
path: /etc/chrony.conf
regexp: "^server "
line: "server {{ item }} iburst"
create: yes
loop: "{{ ntp_servers }}"
- name: 启动chrony
service:
name: chronyd
state: started
enabled: yes
- name: 验证时间同步
shell: chronyc tracking
register: chrony_status
changed_when: false
- name: 显示同步状态
debug:
msg: "{{ chrony_status.stdout_lines }}"
`,
},
// ===== Web服务 =====
{
ID: "deploy-nginx", Name: "部署Nginx", Category: "web",
Description: "安装配置Nginx,支持自定义站点和反向代理",
Icon: "🌐", Tags: []string{"nginx", "web", "proxy"},
Content: `---
- name: 部署Nginx
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
nginx_worker_processes: auto
nginx_worker_connections: 1024
server_name: localhost
listen_port: 80
proxy_pass: ""
root_dir: /var/www/html
tasks:
- name: 安装Nginx
package:
name: nginx
state: present
- name: 创建网站目录
file:
path: "{{ root_dir }}"
state: directory
owner: www-data
group: www-data
mode: '0755'
when: ansible_os_family == "Debian"
- name: 创建网站目录(RedHat)
file:
path: "{{ root_dir }}"
state: directory
owner: nginx
group: nginx
mode: '0755'
when: ansible_os_family == "RedHat"
- name: 部署默认页面
copy:
content: |
{{ server_name }}
Deployed by Ansible Deploy
Server: {{ inventory_hostname }}
dest: "{{ root_dir }}/index.html"
when: proxy_pass == ""
- name: 配置Nginx站点
copy:
content: |
server {
listen {{ listen_port }};
server_name {{ server_name }};
{% if proxy_pass != "" %}
location / {
proxy_pass {{ proxy_pass }};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
{% else %}
root {{ root_dir }};
index index.html;
location / {
try_files $uri $uri/ =404;
}
{% endif %}
}
dest: /etc/nginx/conf.d/{{ server_name }}.conf
notify: Reload Nginx
- name: 启动Nginx
service:
name: nginx
state: started
enabled: yes
handlers:
- name: Reload Nginx
service:
name: nginx
state: reloaded
`,
},
{
ID: "deploy-apache", Name: "部署Apache", Category: "web",
Description: "安装配置Apache HTTP Server",
Icon: "🪶", Tags: []string{"apache", "httpd", "web"},
Content: `---
- name: 部署Apache
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
server_name: localhost
listen_port: 80
document_root: /var/www/html
tasks:
- name: 安装Apache(Debian)
apt:
name: apache2
state: present
when: ansible_os_family == "Debian"
- name: 安装Apache(RedHat)
yum:
name: httpd
state: present
when: ansible_os_family == "RedHat"
- name: 创建网站目录
file:
path: "{{ document_root }}"
state: directory
mode: '0755'
- name: 部署测试页面
copy:
content: "Apache on {{ inventory_hostname }}
"
dest: "{{ document_root }}/index.html"
- name: 启动Apache(Debian)
service:
name: apache2
state: started
enabled: yes
when: ansible_os_family == "Debian"
- name: 启动Apache(RedHat)
service:
name: httpd
state: started
enabled: yes
when: ansible_os_family == "RedHat"
`,
},
// ===== 数据库 =====
{
ID: "deploy-mysql", Name: "部署MySQL", Category: "database",
Description: "安装MySQL/MariaDB,配置root密码和基础优化",
Icon: "🐬", Tags: []string{"mysql", "mariadb", "database"},
Content: `---
- name: 部署MySQL
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
mysql_root_password: "ChangeMe@2024"
mysql_port: 3306
mysql_max_connections: 500
mysql_datadir: /var/lib/mysql
tasks:
- name: 安装MySQL(Debian)
apt:
name:
- mysql-server
- mysql-client
- python3-pymysql
state: present
when: ansible_os_family == "Debian"
- name: 安装MariaDB(RedHat)
yum:
name:
- mariadb-server
- mariadb
- python3-PyMySQL
state: present
when: ansible_os_family == "RedHat"
- name: 启动MySQL
service:
name: "{{ 'mysql' if ansible_os_family == 'Debian' else 'mariadb' }}"
state: started
enabled: yes
- name: 设置root密码
shell: |
mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '{{ mysql_root_password }}'; FLUSH PRIVILEGES;"
ignore_errors: yes
no_log: true
- name: 优化配置
copy:
content: |
[mysqld]
port = {{ mysql_port }}
max_connections = {{ mysql_max_connections }}
datadir = {{ mysql_datadir }}
innodb_buffer_pool_size = 256M
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
dest: /etc/mysql/conf.d/optimize.cnf
when: ansible_os_family == "Debian"
notify: Restart MySQL
- name: 验证MySQL
shell: mysql -u root -p{{ mysql_root_password }} -e "SELECT VERSION();"
register: mysql_version
changed_when: false
no_log: true
- name: 显示版本
debug:
msg: "MySQL版本: {{ mysql_version.stdout_lines[-1] | default('unknown') }}"
handlers:
- name: Restart MySQL
service:
name: "{{ 'mysql' if ansible_os_family == 'Debian' else 'mariadb' }}"
state: restarted
`,
},
{
ID: "deploy-redis", Name: "部署Redis", Category: "database",
Description: "安装Redis,配置密码、内存限制和持久化",
Icon: "🔴", Tags: []string{"redis", "cache", "database"},
Content: `---
- name: 部署Redis
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
redis_port: 6379
redis_password: "ChangeMe@2024"
redis_maxmemory: "512mb"
redis_maxmemory_policy: allkeys-lru
redis_bind: "0.0.0.0"
tasks:
- name: 安装Redis
package:
name: redis-server
state: present
when: ansible_os_family == "Debian"
- name: 安装Redis(RedHat)
yum:
name: redis
state: present
when: ansible_os_family == "RedHat"
- name: 配置Redis
lineinfile:
path: /etc/redis/redis.conf
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
loop:
- { regexp: '^bind ', line: 'bind {{ redis_bind }}' }
- { regexp: '^port ', line: 'port {{ redis_port }}' }
- { regexp: '^requirepass ', line: 'requirepass {{ redis_password }}' }
- { regexp: '^maxmemory ', line: 'maxmemory {{ redis_maxmemory }}' }
- { regexp: '^maxmemory-policy ', line: 'maxmemory-policy {{ redis_maxmemory_policy }}' }
notify: Restart Redis
- name: 启动Redis
service:
name: "{{ 'redis-server' if ansible_os_family == 'Debian' else 'redis' }}"
state: started
enabled: yes
- name: 验证Redis
shell: redis-cli -a {{ redis_password }} ping
register: redis_ping
changed_when: false
no_log: true
- name: 显示状态
debug:
msg: "Redis状态: {{ redis_ping.stdout }}"
handlers:
- name: Restart Redis
service:
name: "{{ 'redis-server' if ansible_os_family == 'Debian' else 'redis' }}"
state: restarted
`,
},
{
ID: "deploy-postgresql", Name: "部署PostgreSQL", Category: "database",
Description: "安装PostgreSQL,配置用户和基础优化",
Icon: "🐘", Tags: []string{"postgresql", "postgres", "database"},
Content: `---
- name: 部署PostgreSQL
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
postgres_version: "15"
postgres_password: "ChangeMe@2024"
postgres_port: 5432
postgres_max_connections: 200
tasks:
- name: 安装PostgreSQL(Debian)
apt:
name:
- postgresql
- postgresql-contrib
- python3-psycopg2
state: present
when: ansible_os_family == "Debian"
- name: 安装PostgreSQL(RedHat)
yum:
name:
- postgresql-server
- postgresql-contrib
- python3-psycopg2
state: present
when: ansible_os_family == "RedHat"
- name: 初始化数据库(RedHat)
shell: postgresql-setup --initdb
when: ansible_os_family == "RedHat"
ignore_errors: yes
- name: 启动PostgreSQL
service:
name: postgresql
state: started
enabled: yes
- name: 设置postgres密码
become_user: postgres
shell: psql -c "ALTER USER postgres PASSWORD '{{ postgres_password }}';"
no_log: true
- name: 验证安装
become_user: postgres
shell: psql -c "SELECT version();"
register: pg_version
changed_when: false
- name: 显示版本
debug:
msg: "{{ pg_version.stdout_lines[0] | default('PostgreSQL installed') }}"
`,
},
// ===== 容器化 =====
{
ID: "deploy-docker", Name: "部署Docker", Category: "container",
Description: "安装Docker CE + Docker Compose,配置镜像加速",
Icon: "🐳", Tags: []string{"docker", "container", "compose"},
Content: `---
- name: 部署Docker
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
docker_mirror: "https://mirror.ccs.tencentyun.com"
docker_data_root: /var/lib/docker
docker_log_max_size: "100m"
docker_log_max_file: "3"
tasks:
- name: 安装依赖(Debian)
apt:
name:
- apt-transport-https
- ca-certificates
- curl
- gnupg
- lsb-release
state: present
when: ansible_os_family == "Debian"
- name: 添加Docker GPG密钥
shell: |
curl -fsSL https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
when: ansible_os_family == "Debian"
ignore_errors: yes
- name: 添加Docker仓库
shell: |
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable" > /etc/apt/sources.list.d/docker.list
when: ansible_os_family == "Debian"
- name: 安装Docker(Debian)
apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin
state: present
update_cache: yes
when: ansible_os_family == "Debian"
- name: 安装Docker(RedHat)
yum:
name:
- docker
- docker-compose-plugin
state: present
when: ansible_os_family == "RedHat"
- name: 配置Docker
copy:
content: |
{
"data-root": "{{ docker_data_root }}",
"registry-mirrors": ["{{ docker_mirror }}"],
"log-driver": "json-file",
"log-opts": {
"max-size": "{{ docker_log_max_size }}",
"max-file": "{{ docker_log_max_file }}"
},
"storage-driver": "overlay2",
"live-restore": true
}
dest: /etc/docker/daemon.json
notify: Restart Docker
- name: 启动Docker
service:
name: docker
state: started
enabled: yes
- name: 添加用户到docker组
user:
name: "{{ ansible_user }}"
groups: docker
append: yes
ignore_errors: yes
- name: 验证Docker
shell: docker version --format '{{.Server.Version}}'
register: docker_ver
changed_when: false
- name: 显示版本
debug:
msg: "Docker版本: {{ docker_ver.stdout }}"
handlers:
- name: Restart Docker
service:
name: docker
state: restarted
`,
},
{
ID: "deploy-portainer", Name: "部署Portainer", Category: "container",
Description: "部署Portainer CE容器管理面板",
Icon: "🎛️", Tags: []string{"portainer", "docker", "ui"},
Content: `---
- name: 部署Portainer
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
portainer_port: 9443
portainer_data: /opt/portainer
tasks:
- name: 创建数据目录
file:
path: "{{ portainer_data }}"
state: directory
- name: 拉取并启动Portainer
shell: |
docker volume create portainer_data
docker run -d \
-p 8000:8000 \
-p {{ portainer_port }}:9443 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
register: portainer_result
ignore_errors: yes
- name: 显示访问地址
debug:
msg: "Portainer已部署: https://{{ ansible_host | default(inventory_hostname) }}:{{ portainer_port }}"
`,
},
// ===== DevOps =====
{
ID: "deploy-nodejs", Name: "部署Node.js", Category: "devops",
Description: "安装Node.js + PM2进程管理器",
Icon: "💚", Tags: []string{"nodejs", "npm", "pm2"},
Content: `---
- name: 部署Node.js
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
node_version: "20"
install_pm2: true
tasks:
- name: 安装NodeSource仓库
shell: |
curl -fsSL https://deb.nodesource.com/setup_{{ node_version }}.x | bash -
when: ansible_os_family == "Debian"
- name: 安装Node.js(Debian)
apt:
name: nodejs
state: present
update_cache: yes
when: ansible_os_family == "Debian"
- name: 安装Node.js(RedHat)
yum:
name: nodejs
state: present
when: ansible_os_family == "RedHat"
- name: 安装PM2
npm:
name: pm2
global: yes
when: install_pm2
- name: 设置PM2开机启动
shell: pm2 startup systemd -u {{ ansible_user }} --hp /home/{{ ansible_user }}
when: install_pm2
ignore_errors: yes
- name: 验证安装
shell: node --version && npm --version
register: node_ver
changed_when: false
- name: 显示版本
debug:
msg: "{{ node_ver.stdout_lines }}"
`,
},
{
ID: "deploy-python-app", Name: "部署Python应用", Category: "devops",
Description: "配置Python环境 + Gunicorn + Systemd服务",
Icon: "🐍", Tags: []string{"python", "gunicorn", "flask", "django"},
Content: `---
- name: 部署Python应用
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
app_name: myapp
app_dir: /opt/myapp
python_version: python3
venv_dir: /opt/myapp/venv
gunicorn_port: 8000
gunicorn_workers: 4
app_user: www-data
tasks:
- name: 安装Python和依赖
package:
name:
- "{{ python_version }}"
- "{{ python_version }}-venv"
- python3-pip
state: present
- name: 创建应用目录
file:
path: "{{ app_dir }}"
state: directory
owner: "{{ app_user }}"
mode: '0755'
- name: 创建虚拟环境
shell: "{{ python_version }} -m venv {{ venv_dir }}"
args:
creates: "{{ venv_dir }}/bin/activate"
- name: 安装Gunicorn
pip:
name: gunicorn
virtualenv: "{{ venv_dir }}"
- name: 创建Systemd服务
copy:
content: |
[Unit]
Description={{ app_name }} Gunicorn Service
After=network.target
[Service]
User={{ app_user }}
WorkingDirectory={{ app_dir }}
ExecStart={{ venv_dir }}/bin/gunicorn --workers {{ gunicorn_workers }} --bind 0.0.0.0:{{ gunicorn_port }} app:app
Restart=always
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/{{ app_name }}.service
notify: Restart App
- name: 启动服务
systemd:
name: "{{ app_name }}"
state: started
enabled: yes
daemon_reload: yes
handlers:
- name: Restart App
systemd:
name: "{{ app_name }}"
state: restarted
daemon_reload: yes
`,
},
{
ID: "backup-data", Name: "数据备份", Category: "devops",
Description: "定时备份指定目录到本地或远程",
Icon: "💾", Tags: []string{"backup", "cron", "archive"},
Content: `---
- name: 数据备份
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
backup_source: /data
backup_dest: /backup
backup_retention_days: 7
backup_hour: "2"
backup_minute: "0"
tasks:
- name: 创建备份目录
file:
path: "{{ backup_dest }}"
state: directory
mode: '0700'
- name: 创建备份脚本
copy:
content: |
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="{{ backup_dest }}/backup_${DATE}.tar.gz"
tar -czf "$BACKUP_FILE" {{ backup_source }} 2>/dev/null
find {{ backup_dest }} -name "backup_*.tar.gz" -mtime +{{ backup_retention_days }} -delete
echo "Backup completed: $BACKUP_FILE"
dest: /usr/local/bin/backup.sh
mode: '0755'
- name: 配置定时任务
cron:
name: "daily-backup"
hour: "{{ backup_hour }}"
minute: "{{ backup_minute }}"
job: "/usr/local/bin/backup.sh >> /var/log/backup.log 2>&1"
- name: 立即执行一次备份
shell: /usr/local/bin/backup.sh
register: backup_result
- name: 备份结果
debug:
msg: "{{ backup_result.stdout }}"
`,
},
// ===== 安全加固 =====
{
ID: "security-hardening", Name: "安全加固", Category: "security",
Description: "SSH加固、防火墙配置、禁用root远程登录",
Icon: "🔒", Tags: []string{"security", "ssh", "firewall", "hardening"},
Content: `---
- name: 安全加固
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
ssh_port: 22
disable_root_login: true
enable_firewall: true
allowed_ssh_users: []
tasks:
- name: 修改SSH端口
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?Port "
line: "Port {{ ssh_port }}"
notify: Restart SSH
- name: 禁用root登录
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?PermitRootLogin "
line: "PermitRootLogin no"
when: disable_root_login
notify: Restart SSH
- name: 禁用密码认证(仅密钥)
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?PasswordAuthentication "
line: "PasswordAuthentication no"
notify: Restart SSH
- name: 设置SSH超时
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?ClientAliveInterval "
line: "ClientAliveInterval 300"
notify: Restart SSH
- name: 安装UFW(Debian)
apt:
name: ufw
state: present
when: ansible_os_family == "Debian" and enable_firewall
- name: 配置UFW规则
shell: |
ufw allow {{ ssh_port }}/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
when: ansible_os_family == "Debian" and enable_firewall
- name: 安装fail2ban
package:
name: fail2ban
state: present
ignore_errors: yes
- name: 启动fail2ban
service:
name: fail2ban
state: started
enabled: yes
ignore_errors: yes
- name: 加固完成
debug:
msg: "✅ 安全加固完成 - SSH端口: {{ ssh_port }}, Root登录: {{ '禁用' if disable_root_login else '允许' }}"
handlers:
- name: Restart SSH
service:
name: "{{ 'ssh' if ansible_os_family == 'Debian' else 'sshd' }}"
state: restarted
`,
},
{
ID: "ssl-cert", Name: "SSL证书部署", Category: "security",
Description: "使用Certbot自动申请Let's Encrypt证书",
Icon: "📜", Tags: []string{"ssl", "https", "certbot", "letsencrypt"},
Content: `---
- name: SSL证书部署
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
domain: example.com
email: admin@example.com
webroot: /var/www/html
tasks:
- name: 安装Certbot
package:
name:
- certbot
- python3-certbot-nginx
state: present
- name: 申请证书
shell: |
certbot certonly --webroot -w {{ webroot }} \
-d {{ domain }} \
--email {{ email }} \
--agree-tos --non-interactive
args:
creates: /etc/letsencrypt/live/{{ domain }}/fullchain.pem
- name: 配置自动续期
cron:
name: "certbot-renew"
hour: "3"
minute: "30"
job: "certbot renew --quiet --post-hook 'systemctl reload nginx'"
- name: 证书信息
shell: openssl x509 -in /etc/letsencrypt/live/{{ domain }}/fullchain.pem -noout -dates
register: cert_info
changed_when: false
ignore_errors: yes
- name: 显示证书
debug:
msg: "{{ cert_info.stdout_lines | default(['证书已申请']) }}"
`,
},
// ===== 监控告警 =====
{
ID: "deploy-node-exporter", Name: "部署Node Exporter", Category: "monitoring",
Description: "部署Prometheus Node Exporter采集主机指标",
Icon: "📡", Tags: []string{"prometheus", "monitoring", "exporter"},
Content: `---
- name: 部署Node Exporter
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
exporter_version: "1.7.0"
exporter_port: 9100
tasks:
- name: 创建用户
user:
name: node_exporter
system: yes
shell: /usr/sbin/nologin
create_home: no
- name: 下载Node Exporter
get_url:
url: "https://github.com/prometheus/node_exporter/releases/download/v{{ exporter_version }}/node_exporter-{{ exporter_version }}.linux-amd64.tar.gz"
dest: /tmp/node_exporter.tar.gz
- name: 解压
unarchive:
src: /tmp/node_exporter.tar.gz
dest: /tmp
remote_src: yes
- name: 安装二进制
copy:
src: "/tmp/node_exporter-{{ exporter_version }}.linux-amd64/node_exporter"
dest: /usr/local/bin/node_exporter
mode: '0755'
remote_src: yes
- name: 创建Systemd服务
copy:
content: |
[Unit]
Description=Node Exporter
After=network.target
[Service]
User=node_exporter
ExecStart=/usr/local/bin/node_exporter --web.listen-address=:{{ exporter_port }}
Restart=always
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/node_exporter.service
- name: 启动服务
systemd:
name: node_exporter
state: started
enabled: yes
daemon_reload: yes
- name: 验证
shell: curl -s http://localhost:{{ exporter_port }}/metrics | head -5
register: metrics
changed_when: false
- name: 显示状态
debug:
msg: "Node Exporter运行在端口 {{ exporter_port }}"
`,
},
{
ID: "deploy-grafana", Name: "部署Grafana", Category: "monitoring",
Description: "部署Grafana可视化监控面板",
Icon: "📊", Tags: []string{"grafana", "dashboard", "visualization"},
Content: `---
- name: 部署Grafana
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
grafana_port: 3000
grafana_admin_password: "admin123"
tasks:
- name: 安装依赖
apt:
name:
- apt-transport-https
- software-properties-common
state: present
when: ansible_os_family == "Debian"
- name: 添加Grafana仓库
shell: |
curl -fsSL https://apt.grafana.com/gpg.key | gpg --dearmor -o /usr/share/keyrings/grafana.gpg
echo "deb [signed-by=/usr/share/keyrings/grafana.gpg] https://apt.grafana.com stable main" > /etc/apt/sources.list.d/grafana.list
when: ansible_os_family == "Debian"
- name: 安装Grafana
apt:
name: grafana
state: present
update_cache: yes
when: ansible_os_family == "Debian"
- name: 配置端口
lineinfile:
path: /etc/grafana/grafana.ini
regexp: "^;?http_port"
line: "http_port = {{ grafana_port }}"
- name: 启动Grafana
service:
name: grafana-server
state: started
enabled: yes
- name: 显示访问信息
debug:
msg: "Grafana: http://{{ ansible_host | default(inventory_hostname) }}:{{ grafana_port }} (admin/{{ grafana_admin_password }})"
`,
},
// ===== 系统管理(新增) =====
{
ID: "host-connectivity", Name: "主机连通性测试", Category: "system",
Description: "批量检测主机SSH连通性、DNS解析、端口可达性",
Icon: "🔗", Tags: []string{"ping", "connectivity", "network", "check"},
Content: `---
- name: 主机连通性测试
hosts: "{{ target_hosts | default('all') }}"
gather_facts: no
tasks:
- name: Ansible Ping 测试
ping:
register: ping_result
ignore_errors: yes
- name: 检测SSH端口
wait_for:
host: "{{ ansible_host | default(inventory_hostname) }}"
port: "{{ ansible_port | default(22) }}"
timeout: 5
delegate_to: localhost
register: ssh_port
ignore_errors: yes
- name: 检测DNS解析
shell: nslookup {{ inventory_hostname }} 2>/dev/null || host {{ inventory_hostname }} 2>/dev/null || echo "DNS解析失败"
delegate_to: localhost
register: dns_result
changed_when: false
ignore_errors: yes
- name: 检测常用端口
wait_for:
host: "{{ ansible_host | default(inventory_hostname) }}"
port: "{{ item }}"
timeout: 3
delegate_to: localhost
loop: [80, 443]
register: port_scan
ignore_errors: yes
- name: 输出连通性报告
debug:
msg: |
═══════ {{ inventory_hostname }} 连通性报告 ═══════
SSH Ping: {{ '✅ 成功' if ping_result is succeeded else '❌ 失败' }}
SSH 端口: {{ '✅ 开放' if ssh_port is succeeded else '❌ 不可达' }}
DNS 解析: {{ dns_result.stdout | default('N/A') }}
HTTP(80): {{ '✅ 开放' if port_scan.results[0] is succeeded else '❌ 关闭' }}
HTTPS(443): {{ '✅ 开放' if port_scan.results[1] is succeeded else '❌ 关闭' }}
═══════════════════════════════════════
`,
},
{
ID: "ubuntu-multi-ip", Name: "Ubuntu 22.04 多IP配置", Category: "system",
Description: "通过Netplan为Ubuntu 22.04配置多IP地址(主IP+辅助IP)",
Icon: "🌐", Tags: []string{"ubuntu", "netplan", "network", "multi-ip"},
Content: `---
- name: Ubuntu 22.04 多IP地址配置
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
# 主网卡名称(根据实际修改)
primary_nic: ens192
# 主IP配置
primary_ip: "192.168.1.100/24"
primary_gateway: "192.168.1.1"
primary_dns:
- 223.5.5.5
- 119.29.29.29
# 辅助IP列表(可添加多个)
secondary_ips:
- "192.168.1.101/24"
- "10.0.0.100/16"
tasks:
- name: 确认系统版本
assert:
that:
- ansible_distribution == "Ubuntu"
- ansible_distribution_version is version('22.04', '>=')
fail_msg: "此模板仅适用于 Ubuntu 22.04+"
success_msg: "系统版本: {{ ansible_distribution }} {{ ansible_distribution_version }}"
- name: 备份现有Netplan配置
shell: |
mkdir -p /etc/netplan/backup
cp /etc/netplan/*.yaml /etc/netplan/backup/ 2>/dev/null || true
args:
creates: /etc/netplan/backup
- name: 生成Netplan配置
copy:
content: |
network:
version: 2
ethernets:
{{ primary_nic }}:
addresses:
- {{ primary_ip }}
{% for ip in secondary_ips %}
- {{ ip }}
{% endfor %}
routes:
- to: default
via: {{ primary_gateway }}
nameservers:
addresses:
{% for dns in primary_dns %}
- {{ dns }}
{% endfor %}
dest: /etc/netplan/01-multi-ip.yaml
mode: '0600'
register: netplan_config
- name: 验证Netplan配置语法
shell: netplan try --timeout=10
environment:
NETPLAN_TRY_TIMEOUT: "10"
ignore_errors: yes
register: netplan_try
- name: 应用Netplan配置
shell: netplan apply
when: netplan_config is changed
- name: 等待网络恢复
wait_for:
host: "{{ primary_ip | ansible.utils.ipaddr('address') }}"
port: 22
timeout: 30
delegate_to: localhost
when: netplan_config is changed
ignore_errors: yes
- name: 验证IP配置
shell: ip addr show {{ primary_nic }} | grep "inet "
register: ip_verify
changed_when: false
- name: 显示配置结果
debug:
msg: |
═══════ 多IP配置完成 ═══════
网卡: {{ primary_nic }}
主IP: {{ primary_ip }}
网关: {{ primary_gateway }}
辅助IP:
{% for ip in secondary_ips %}
- {{ ip }}
{% endfor %}
当前IP列表:
{{ ip_verify.stdout }}
═══════════════════════════
`,
},
{
ID: "ipmitool-bmc", Name: "IPMI配置BMC地址", Category: "system",
Description: "使用ipmitool配置服务器BMC/IPMI管理口IP地址",
Icon: "🔧", Tags: []string{"ipmi", "bmc", "ipmitool", "hardware"},
Content: `---
- name: IPMI配置BMC地址
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
# BMC网络配置
bmc_ip: "10.10.10.100"
bmc_netmask: "255.255.255.0"
bmc_gateway: "10.10.10.1"
# BMC用户配置
bmc_user: "admin"
bmc_password: "Admin@123"
bmc_channel: 1
# 是否启用DHCP(设为true则忽略上面的静态IP配置)
bmc_dhcp: false
tasks:
- name: 安装ipmitool
package:
name: ipmitool
state: present
- name: 加载IPMI内核模块
modprobe:
name: "{{ item }}"
state: present
loop:
- ipmi_devintf
- ipmi_si
ignore_errors: yes
- name: 查看当前BMC配置
shell: ipmitool lan print {{ bmc_channel }}
register: bmc_current
changed_when: false
ignore_errors: yes
- name: 显示当前BMC信息
debug:
msg: "{{ bmc_current.stdout_lines | default(['无法读取BMC信息']) }}"
- name: 设置BMC为静态IP
shell: ipmitool lan set {{ bmc_channel }} ipsrc static
when: not bmc_dhcp
- name: 配置BMC IP地址
shell: ipmitool lan set {{ bmc_channel }} ipaddr {{ bmc_ip }}
when: not bmc_dhcp
- name: 配置BMC子网掩码
shell: ipmitool lan set {{ bmc_channel }} netmask {{ bmc_netmask }}
when: not bmc_dhcp
- name: 配置BMC默认网关
shell: ipmitool lan set {{ bmc_channel }} defgw ipaddr {{ bmc_gateway }}
when: not bmc_dhcp
- name: 设置BMC为DHCP模式
shell: ipmitool lan set {{ bmc_channel }} ipsrc dhcp
when: bmc_dhcp
- name: 配置BMC用户密码
shell: |
ipmitool user set name {{ bmc_channel }} 2 {{ bmc_user }} 2>/dev/null || true
ipmitool user set password 2 {{ bmc_password }}
ipmitool user enable 2
ipmitool channel setaccess {{ bmc_channel }} 2 privilege=4
no_log: true
ignore_errors: yes
- name: 验证BMC配置
shell: ipmitool lan print {{ bmc_channel }}
register: bmc_verify
changed_when: false
- name: 显示最终配置
debug:
msg: |
═══════ BMC配置完成 ═══════
模式: {{ 'DHCP' if bmc_dhcp else '静态IP' }}
IP: {{ bmc_ip }}
掩码: {{ bmc_netmask }}
网关: {{ bmc_gateway }}
用户: {{ bmc_user }}
═══════════════════════════
{{ bmc_verify.stdout }}
`,
},
{
ID: "apt-install", Name: "APT软件安装", Category: "system",
Description: "通过apt批量安装/卸载软件包,支持指定版本和仓库",
Icon: "📦", Tags: []string{"apt", "install", "package", "debian"},
Content: `---
- name: APT软件安装
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
# 要安装的软件包列表
packages_install:
- vim
- curl
- wget
- htop
- net-tools
- tree
- unzip
- git
# 要卸载的软件包列表
packages_remove: []
# 是否更新缓存
update_cache: yes
# 是否自动清理
autoremove: yes
# 安装推荐包
install_recommends: no
# 指定版本(可选,格式: "package=version")
# 例: packages_install: ["nginx=1.18.0-0ubuntu1"]
tasks:
- name: 确认Debian系统
assert:
that: ansible_os_family == "Debian"
fail_msg: "此模板仅适用于 Debian/Ubuntu 系统"
- name: 更新APT缓存
apt:
update_cache: yes
cache_valid_time: 3600
when: update_cache
- name: 安装软件包
apt:
name: "{{ packages_install }}"
state: present
install_recommends: "{{ install_recommends }}"
register: install_result
when: packages_install | length > 0
- name: 卸载软件包
apt:
name: "{{ packages_remove }}"
state: absent
purge: yes
when: packages_remove | length > 0
- name: 自动清理
apt:
autoremove: yes
autoclean: yes
when: autoremove
- name: 验证安装结果
shell: dpkg -l {{ packages_install | join(' ') }} 2>/dev/null | grep "^ii" | awk '{print $2, $3}'
register: verify_result
changed_when: false
when: packages_install | length > 0
- name: 显示安装报告
debug:
msg: |
═══════ APT安装报告 ═══════
已安装: {{ packages_install | length }} 个包
已卸载: {{ packages_remove | length }} 个包
变更: {{ install_result.changed | default(false) }}
{% if verify_result is defined and verify_result.stdout_lines is defined %}
已确认:
{% for line in verify_result.stdout_lines %}
✓ {{ line }}
{% endfor %}
{% endif %}
═══════════════════════════
`,
},
{
ID: "dpkg-install", Name: "DPKG软件安装", Category: "system",
Description: "通过dpkg安装本地.deb包,支持URL下载和依赖修复",
Icon: "📥", Tags: []string{"dpkg", "deb", "install", "offline"},
Content: `---
- name: DPKG软件安装
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
# 本地deb包路径列表(服务器上的路径)
local_deb_files: []
# 远程URL列表(会自动下载后安装)
remote_deb_urls: []
# 下载临时目录
download_dir: /tmp/dpkg_install
# 安装后是否修复依赖
fix_dependencies: yes
# 是否保留下载的deb文件
keep_deb_files: no
tasks:
- name: 确认Debian系统
assert:
that: ansible_os_family == "Debian"
fail_msg: "此模板仅适用于 Debian/Ubuntu 系统"
- name: 创建下载目录
file:
path: "{{ download_dir }}"
state: directory
mode: '0755'
when: remote_deb_urls | length > 0
- name: 下载远程deb包
get_url:
url: "{{ item }}"
dest: "{{ download_dir }}/{{ item | basename }}"
mode: '0644'
loop: "{{ remote_deb_urls }}"
register: download_result
when: remote_deb_urls | length > 0
- name: 安装本地deb包
apt:
deb: "{{ item }}"
state: present
loop: "{{ local_deb_files }}"
register: local_install
when: local_deb_files | length > 0
- name: 安装下载的deb包
apt:
deb: "{{ download_dir }}/{{ item | basename }}"
state: present
loop: "{{ remote_deb_urls }}"
register: remote_install
when: remote_deb_urls | length > 0
- name: 修复依赖关系
apt:
update_cache: yes
force_apt_get: yes
shell: apt-get install -f -y
when: fix_dependencies
ignore_errors: yes
- name: 清理下载文件
file:
path: "{{ download_dir }}"
state: absent
when: not keep_deb_files and remote_deb_urls | length > 0
- name: 显示安装报告
debug:
msg: |
═══════ DPKG安装报告 ═══════
本地包: {{ local_deb_files | length }} 个
远程包: {{ remote_deb_urls | length }} 个
{% if local_deb_files | length > 0 %}
本地安装:
{% for f in local_deb_files %}
✓ {{ f }}
{% endfor %}
{% endif %}
{% if remote_deb_urls | length > 0 %}
远程安装:
{% for u in remote_deb_urls %}
✓ {{ u | basename }}
{% endfor %}
{% endif %}
依赖修复: {{ '是' if fix_dependencies else '否' }}
═══════════════════════════
`,
},
}
}