mcpField
A
ansible-coder

ansible-coder

github.com/majesticlabs-dev云与 DevOps5072 次安装7 周前更新
代码仓库

关于 ansible-coder

ansible-coder 是面向服务器配置与维护的 Ansible 编写技能,适用于从少量服务器到复杂基础设施的配置任务。它默认采用扁平、简洁的结构,并说明何时使用 Cloud-Init 或 Ansible。

主要功能

  1. 01优先采用单一扁平 Playbook
  2. 02提供静态及 Terraform 动态 Inventory 示例
  3. 03涵盖软件包、安全与系统配置
  4. 04支持 Galaxy 依赖管理
  5. 05提供检查模式和主机范围执行

适用场景

  1. 01配置少量 Web 或数据库服务器
  2. 02为现有服务器重复运行配置
  3. 03设置 Docker、SSH、Fail2ban 和防火墙
  4. 04通过 Terraform 输出生成 Inventory

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/majesticlabs-dev/majestic-marketplace --skill ansible-coder

安装后在 Claude Code 中输入/ansible-coder确认已加载。

附带文件references/kamal-playbook.mdreferences/provision-script.md

详细介绍

Ansible 编码器

⚠️ 简单至上——默认采用扁平结构

始终从最简单的方案开始。只有明确提出要求时,才增加复杂性。

简单(默认)与过度设计
方面✅ 简单(默认)❌ 过度设计
Playbook1 个包含内联任务的 playbook多个 playbook + 自定义角色
角色使用 Galaxy 角色(geerlingguy.*)为简单任务编写自定义角色
清单单个 hosts.ini多个清单 + group_vars 层级结构
变量内联在 playbook 中或放在单个变量文件中分散在 group_vars/host_vars 中
文件数量总计约 3-5 个文件嵌套目录中有 20 多个文件
适合采用简单方案的情况(90% 的情况)
  • 设置 1-5 台服务器
  • 标准技术栈(Docker、nginx、fail2ban、ufw)
  • 单一环境或配置相同的服务器
  • 每台主机都没有复杂的条件逻辑
适合采用复杂方案的情况(10% 的情况)
  • 配置差异较大的大型服务器集群
  • 需要隔离角色的多团队协作
  • 带有依赖项的复杂编排
  • 用户明确要求模块化结构

规则:如果所有内容都能放进一个 200 行的 playbook,就这样做。

何时使用 Ansible 与 Cloud-Init

使用 Cloud-Init 的情况使用 Ansible 的情况
仅限首次启动在现有服务器上重新运行配置
安装简单的软件包复杂的多步骤配置
创建基本用户基于角色的配置
不可变基础设施需要更新的可变服务器

**经验法则:**使用 Cloud-Init 进行初始配置,使用 Ansible 进行持续管理。

目录结构

简单结构(默认)
infra/ansible/
├── playbook.yml          # Single playbook with all tasks inline
├── requirements.yml      # Galaxy dependencies (geerlingguy.*, etc.)
├── hosts.ini             # Inventory (git-ignored)
└── hosts.ini.example     # Inventory template
复杂结构(仅在确有必要时使用)
infra/ansible/
├── playbook.yml          # Main playbook
├── requirements.yml      # Galaxy dependencies
├── hosts.ini             # Inventory (git-ignored)
├── hosts.ini.example     # Inventory template
├── group_vars/
│   └── all.yml           # Shared variables
└── roles/
    └── custom_role/
        ├── tasks/main.yml
        ├── handlers/main.yml
        └── templates/

清单

静态清单
# hosts.ini
[web]
192.168.1.1 ansible_user=root

[db]
192.168.1.2 ansible_user=root

[all:vars]
ansible_python_interpreter=/usr/bin/python3
从 Terraform 动态生成
# Generate inventory from Terraform output
SERVER_IP=$(cd infra && tofu output -raw server_ip)
cat > infra/ansible/hosts.ini << EOF
[web]
$SERVER_IP ansible_user=root
EOF

Playbook 结构

基本 Playbook
---
- name: Configure web servers
  hosts: web
  become: true

  vars:
    timezone: "UTC"
    swap_size_mb: "2048"

  tasks:
    - name: Update apt cache
      ansible.builtin.apt:
        update_cache: true
        cache_valid_time: 3600

    - name: Install packages
      ansible.builtin.apt:
        name:
          - docker.io
          - fail2ban
          - ufw
        state: present
使用角色
---
- name: Configure web servers
  hosts: web
  become: true

  vars:
    security_autoupdate_reboot: true
    security_autoupdate_reboot_time: "03:00"

  roles:
    - role: geerlingguy.swap
      when: ansible_swaptotal_mb < 1
    - role: geerlingguy.docker
    - role: security

常见任务

软件包管理
- name: Install required packages
  ansible.builtin.apt:
    name:
      - curl
      - ca-certificates
      - gnupg
      - fail2ban
      - ufw
      - ntp
    state: present
    update_cache: true
Docker 安装
- name: Check if Docker is installed
  ansible.builtin.command: docker --version
  register: docker_installed
  ignore_errors: true
  changed_when: false

- name: Install Docker via convenience script
  ansible.builtin.shell: curl -fsSL https://get.docker.com | sh
  when: docker_installed.rc != 0
  args:
    creates: /usr/bin/docker

- name: Ensure Docker is running
  ansible.builtin.systemd:
    name: docker
    state: started
    enabled: true
SSH 加固
- name: Disable SSH password authentication
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: "^#?PasswordAuthentication"
    line: "PasswordAuthentication no"
  notify: Restart ssh

- name: Disable SSH root login with password
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: "^#?PermitRootLogin"
    line: "PermitRootLogin prohibit-password"
  notify: Restart ssh

handlers:
  - name: Restart ssh
    ansible.builtin.systemd:
      name: ssh  # Ubuntu uses 'ssh', not 'sshd'
      state: restarted
Fail2ban
- name: Configure fail2ban for SSH
  ansible.builtin.copy:
    dest: /etc/fail2ban/jail.local
    content: |
      [sshd]
      enabled = true
      port = ssh
      filter = sshd
      logpath = /var/log/auth.log
      maxretry = 5
      bantime = 3600
      findtime = 600
    mode: "0644"
  notify: Restart fail2ban

- name: Ensure fail2ban is running
  ansible.builtin.systemd:
    name: fail2ban
    state: started
    enabled: true

handlers:
  - name: Restart fail2ban
    ansible.builtin.systemd:
      name: fail2ban
      state: restarted
UFW 防火墙
- name: Set UFW default policies
  community.general.ufw:
    direction: "{{ item.direction }}"
    policy: "{{ item.policy }}"
  loop:
    - { direction: incoming, policy: deny }
    - { direction: outgoing, policy: allow }

- name: Allow specified ports through UFW
  community.general.ufw:
    rule: allow
    port: "{{ item }}"
    proto: tcp
  loop:
    - 22   # SSH
    - 80   # HTTP
    - 443  # HTTPS

- name: Enable UFW
  community.general.ufw:
    state: enabled
内核调优
- name: Configure sysctl for performance
  ansible.posix.sysctl:
    name: "{{ item.name }}"
    value: "{{ item.value }}"
    state: present
    reload: true
  loop:
    - { name: vm.swappiness, value: "10" }
    - { name: net.core.somaxconn, value: "65535" }
时区
- name: Set timezone
  community.general.timezone:
    name: "{{ timezone }}"
移除 Snap(精简 Ubuntu)
- name: Remove snapd
  ansible.builtin.apt:
    name: snapd
    state: absent
    purge: true
  ignore_errors: true

- name: Remove snap directories
  ansible.builtin.file:
    path: "{{ item }}"
    state: absent
  loop:
    - /snap
    - /var/snap
    - /var/lib/snapd

Galaxy 依赖项

requirements.yml
---
roles:
  - name: geerlingguy.swap
    version: 2.0.0
  - name: geerlingguy.docker
    version: 7.4.1

collections:
  - name: community.general
  - name: ansible.posix
安装
ansible-galaxy install -r requirements.yml --force

运行 Playbook

基本执行
ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i hosts.ini playbook.yml
使用变量
ansible-playbook -i hosts.ini playbook.yml \
  -e "timezone=Europe/Berlin" \
  -e "swap_size_mb=4096"
试运行
ansible-playbook -i hosts.ini playbook.yml --check --diff
限定特定主机
ansible-playbook -i hosts.ini playbook.yml --limit web

请参阅 Kamal 服务器准备,了解完整的 Kamal 部署服务器 playbook。

请参阅 与 Terraform 集成,了解 Terraform-Ansible-Kamal 配置流程。

故障排除

问题原因修复方法
ssh: connect refused服务器尚未就绪等待或检查防火墙
Permission deniedSSH 密钥错误使用 -i 指定
sudo: password required用户需要 NOPASSWD使用 become_method: sudo
处理程序未运行任务未产生变更使用 changed_when: true
找不到模块缺少集合从 requirements.yml 安装

评论

支持 Markdown