Claude-skill-registry ansible-roles
Use when structuring and reusing code with Ansible roles for modular, maintainable automation and configuration management.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/ansible-roles" ~/.claude/skills/majiayu000-claude-skill-registry-ansible-roles && rm -rf "$T"
manifest:
skills/data/ansible-roles/SKILL.mdsafety · automated scan (low risk)
This is a pattern-based risk scan, not a security review. Our crawler flagged:
- makes HTTP requests (curl)
- downloads files (wget)
Always read a skill's source content before installing. Patterns alone don't mean the skill is malicious — but they warrant attention.
source content
Ansible Roles
Structure and reuse automation code with Ansible roles for modular, maintainable infrastructure.
Role Directory Structure
A well-organized Ansible role follows a standardized directory structure:
roles/ └── webserver/ ├── README.md ├── defaults/ │ └── main.yml ├── files/ │ ├── nginx.conf │ └── ssl/ │ ├── cert.pem │ └── key.pem ├── handlers/ │ └── main.yml ├── meta/ │ └── main.yml ├── tasks/ │ ├── main.yml │ ├── install.yml │ ├── configure.yml │ └── security.yml ├── templates/ │ ├── nginx.conf.j2 │ └── site.conf.j2 ├── tests/ │ ├── inventory │ └── test.yml └── vars/ └── main.yml
Basic Role Example
tasks/main.yml
--- # Main task file for webserver role - name: Include OS-specific variables include_vars: "{{ ansible_os_family }}.yml" - name: Import installation tasks import_tasks: install.yml tags: - install - webserver - name: Import configuration tasks import_tasks: configure.yml tags: - configure - webserver - name: Import security tasks import_tasks: security.yml tags: - security - webserver - name: Ensure nginx is running service: name: "{{ nginx_service_name }}" state: started enabled: yes tags: - service - webserver
tasks/install.yml
--- # Installation tasks for webserver role - name: Install nginx and dependencies (Debian/Ubuntu) apt: name: - nginx - nginx-extras - python3-passlib state: present update_cache: yes cache_valid_time: 3600 when: ansible_os_family == "Debian" - name: Install nginx and dependencies (RedHat/CentOS) yum: name: - nginx - nginx-mod-stream - python3-passlib state: present update_cache: yes when: ansible_os_family == "RedHat" - name: Create nginx directories file: path: "{{ item }}" state: directory owner: "{{ nginx_user }}" group: "{{ nginx_group }}" mode: '0755' loop: - "{{ nginx_conf_dir }}/sites-available" - "{{ nginx_conf_dir }}/sites-enabled" - "{{ nginx_log_dir }}" - "{{ nginx_cache_dir }}" - /var/www/html - name: Install certbot for SSL apt: name: certbot state: present when: - nginx_ssl_enabled - ansible_os_family == "Debian"
tasks/configure.yml
--- # Configuration tasks for webserver role - name: Deploy main nginx configuration template: src: nginx.conf.j2 dest: "{{ nginx_conf_dir }}/nginx.conf" owner: root group: root mode: '0644' validate: 'nginx -t -c %s' backup: yes notify: - Reload nginx tags: - config - name: Deploy site configurations template: src: site.conf.j2 dest: "{{ nginx_conf_dir }}/sites-available/{{ item.name }}.conf" owner: root group: root mode: '0644' validate: 'nginx -t -c {{ nginx_conf_dir }}/nginx.conf' loop: "{{ nginx_sites }}" when: nginx_sites is defined notify: - Reload nginx - name: Enable sites file: src: "{{ nginx_conf_dir }}/sites-available/{{ item.name }}.conf" dest: "{{ nginx_conf_dir }}/sites-enabled/{{ item.name }}.conf" state: link loop: "{{ nginx_sites }}" when: - nginx_sites is defined - item.enabled | default(true) notify: - Reload nginx - name: Disable default site file: path: "{{ nginx_conf_dir }}/sites-enabled/default" state: absent when: nginx_disable_default_site notify: - Reload nginx - name: Configure log rotation template: src: logrotate.j2 dest: /etc/logrotate.d/nginx owner: root group: root mode: '0644'
tasks/security.yml
--- # Security tasks for webserver role - name: Generate dhparam file command: openssl dhparam -out {{ nginx_conf_dir }}/dhparam.pem 2048 args: creates: "{{ nginx_conf_dir }}/dhparam.pem" when: nginx_ssl_enabled - name: Set secure permissions on dhparam file: path: "{{ nginx_conf_dir }}/dhparam.pem" owner: root group: root mode: '0600' when: nginx_ssl_enabled - name: Configure firewall rules (ufw) ufw: rule: allow port: "{{ item }}" proto: tcp loop: - "80" - "443" when: - nginx_configure_firewall - ansible_os_family == "Debian" - name: Configure firewall rules (firewalld) firewalld: service: "{{ item }}" permanent: yes state: enabled immediate: yes loop: - http - https when: - nginx_configure_firewall - ansible_os_family == "RedHat" - name: Create basic auth file htpasswd: path: "{{ nginx_conf_dir }}/.htpasswd" name: "{{ item.username }}" password: "{{ item.password }}" owner: root group: "{{ nginx_group }}" mode: '0640' loop: "{{ nginx_basic_auth_users }}" when: nginx_basic_auth_users is defined no_log: yes
Role Variables
defaults/main.yml
--- # Default variables for webserver role # These can be overridden in playbooks or inventory # Package and service names nginx_package_name: nginx nginx_service_name: nginx # User and group nginx_user: www-data nginx_group: www-data # Directories nginx_conf_dir: /etc/nginx nginx_log_dir: /var/log/nginx nginx_cache_dir: /var/cache/nginx nginx_pid_file: /var/run/nginx.pid # Main configuration nginx_worker_processes: auto nginx_worker_connections: 1024 nginx_keepalive_timeout: 65 nginx_client_max_body_size: 10m # Performance tuning nginx_sendfile: on nginx_tcp_nopush: on nginx_tcp_nodelay: on nginx_gzip: on nginx_gzip_types: - text/plain - text/css - application/json - application/javascript - text/xml - application/xml # Security nginx_ssl_enabled: no nginx_ssl_protocols: "TLSv1.2 TLSv1.3" nginx_ssl_ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256" nginx_ssl_prefer_server_ciphers: on nginx_disable_default_site: yes nginx_configure_firewall: yes nginx_server_tokens: off # Sites configuration nginx_sites: [] # Example: # nginx_sites: # - name: example.com # server_name: example.com www.example.com # root: /var/www/example.com # enabled: yes # ssl: yes # Basic authentication # nginx_basic_auth_users: # - username: admin # password: secretpassword
vars/main.yml
--- # Variables that should not be overridden nginx_conf_path: "{{ nginx_conf_dir }}/nginx.conf" nginx_error_log: "{{ nginx_log_dir }}/error.log" nginx_access_log: "{{ nginx_log_dir }}/access.log" # OS-specific overrides loaded via include_vars
vars/Debian.yml
--- nginx_user: www-data nginx_group: www-data nginx_conf_dir: /etc/nginx nginx_service_name: nginx
vars/RedHat.yml
--- nginx_user: nginx nginx_group: nginx nginx_conf_dir: /etc/nginx nginx_service_name: nginx
Role Handlers
handlers/main.yml
--- # Handlers for webserver role - name: Reload nginx service: name: "{{ nginx_service_name }}" state: reloaded listen: "reload nginx" - name: Restart nginx service: name: "{{ nginx_service_name }}" state: restarted listen: "restart nginx" - name: Validate nginx config command: nginx -t changed_when: false listen: "validate nginx" - name: Reload firewall service: name: ufw state: reloaded when: ansible_os_family == "Debian" listen: "reload firewall"
Role Templates
templates/nginx.conf.j2
# {{ ansible_managed }} user {{ nginx_user }}; worker_processes {{ nginx_worker_processes }}; pid {{ nginx_pid_file }}; events { worker_connections {{ nginx_worker_connections }}; use epoll; multi_accept on; } http { ## # Basic Settings ## sendfile {{ nginx_sendfile | ternary('on', 'off') }}; tcp_nopush {{ nginx_tcp_nopush | ternary('on', 'off') }}; tcp_nodelay {{ nginx_tcp_nodelay | ternary('on', 'off') }}; keepalive_timeout {{ nginx_keepalive_timeout }}; types_hash_max_size 2048; server_tokens {{ nginx_server_tokens | ternary('on', 'off') }}; client_max_body_size {{ nginx_client_max_body_size }}; include {{ nginx_conf_dir }}/mime.types; default_type application/octet-stream; ## # SSL Settings ## {% if nginx_ssl_enabled %} ssl_protocols {{ nginx_ssl_protocols }}; ssl_ciphers {{ nginx_ssl_ciphers }}; ssl_prefer_server_ciphers {{ nginx_ssl_prefer_server_ciphers | ternary('on', 'off') }}; ssl_dhparam {{ nginx_conf_dir }}/dhparam.pem; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; {% endif %} ## # Logging Settings ## access_log {{ nginx_access_log }}; error_log {{ nginx_error_log }}; ## # Gzip Settings ## gzip {{ nginx_gzip | ternary('on', 'off') }}; {% if nginx_gzip %} gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types {{ nginx_gzip_types | join(' ') }}; {% endif %} ## # Virtual Host Configs ## include {{ nginx_conf_dir }}/sites-enabled/*; }
templates/site.conf.j2
# {{ ansible_managed }} # Site: {{ item.name }} {% if item.ssl | default(false) %} # Redirect HTTP to HTTPS server { listen 80; listen [::]:80; server_name {{ item.server_name }}; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name {{ item.server_name }}; ssl_certificate {{ item.ssl_cert | default('/etc/letsencrypt/live/' + item.name + '/fullchain.pem') }}; ssl_certificate_key {{ item.ssl_key | default('/etc/letsencrypt/live/' + item.name + '/privkey.pem') }}; {% else %} server { listen 80; listen [::]:80; server_name {{ item.server_name }}; {% endif %} root {{ item.root | default('/var/www/' + item.name) }}; index {{ item.index | default('index.html index.htm') }}; {% if item.access_log is defined %} access_log {{ item.access_log }}; {% endif %} {% if item.error_log is defined %} error_log {{ item.error_log }}; {% endif %} {% if item.basic_auth | default(false) %} auth_basic "Restricted Access"; auth_basic_user_file {{ nginx_conf_dir }}/.htpasswd; {% endif %} location / { {% if item.proxy_pass is defined %} proxy_pass {{ item.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; proxy_set_header X-Forwarded-Proto $scheme; {% else %} try_files $uri $uri/ =404; {% endif %} } {% if item.locations is defined %} {% for location in item.locations %} location {{ location.path }} { {% if location.proxy_pass is defined %} proxy_pass {{ location.proxy_pass }}; {% endif %} {% if location.alias is defined %} alias {{ location.alias }}; {% endif %} {% if location.return is defined %} return {{ location.return }}; {% endif %} } {% endfor %} {% endif %} # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; }
Role Dependencies
meta/main.yml
--- galaxy_info: role_name: webserver author: Your Organization description: Install and configure nginx web server company: Your Company license: MIT min_ansible_version: 2.9 platforms: - name: Ubuntu versions: - focal - jammy - name: Debian versions: - buster - bullseye - name: EL versions: - 7 - 8 - 9 galaxy_tags: - web - nginx - webserver - http dependencies: - role: common vars: common_packages: - curl - wget - role: firewall when: nginx_configure_firewall allow_duplicates: no
Using Roles in Playbooks
Simple Role Usage
--- - name: Configure web servers hosts: webservers become: yes roles: - webserver
Role with Variables
--- - name: Configure web servers with custom settings hosts: webservers become: yes roles: - role: webserver vars: nginx_worker_processes: 4 nginx_ssl_enabled: yes nginx_sites: - name: example.com server_name: example.com www.example.com root: /var/www/example.com ssl: yes ssl_cert: /etc/ssl/certs/example.com.crt ssl_key: /etc/ssl/private/example.com.key
Role with Tags
--- - name: Configure infrastructure hosts: all become: yes roles: - role: webserver tags: - web - nginx - role: database tags: - db - postgres
Pre and Post Tasks
--- - name: Deploy web application hosts: webservers become: yes pre_tasks: - name: Announce deployment debug: msg: "Starting deployment to {{ inventory_hostname }}" - name: Check disk space command: df -h / register: disk_space changed_when: false roles: - webserver - monitoring post_tasks: - name: Verify nginx is responding uri: url: http://localhost status_code: 200 retries: 3 delay: 5 - name: Notify completion debug: msg: "Deployment completed successfully"
Role Inclusion Methods
Static Import
--- - name: Configure servers hosts: all tasks: - name: Import webserver role import_role: name: webserver vars: nginx_worker_processes: 2 tags: - webserver
Dynamic Include
--- - name: Configure servers based on conditions hosts: all tasks: - name: Include webserver role for web servers include_role: name: webserver when: "'webservers' in group_names" - name: Include database role for db servers include_role: name: database when: "'databases' in group_names"
Import with Task Files
--- - name: Custom installation workflow hosts: webservers tasks: - name: Run pre-installation checks import_role: name: webserver tasks_from: preflight - name: Install nginx import_role: name: webserver tasks_from: install - name: Configure nginx import_role: name: webserver tasks_from: configure
Creating Roles with Ansible Galaxy
Initialize a New Role
# Create role structure ansible-galaxy init roles/myapp # Create role with custom template ansible-galaxy init --init-path roles/ myapp # List role files tree roles/myapp
Install Roles from Galaxy
# Install a role ansible-galaxy install geerlingguy.nginx # Install specific version ansible-galaxy install geerlingguy.nginx,2.8.0 # Install from requirements file ansible-galaxy install -r requirements.yml
requirements.yml
--- # Install from Ansible Galaxy - name: geerlingguy.nginx version: 2.8.0 - name: geerlingguy.postgresql version: 3.4.0 # Install from Git repository - name: custom-app src: https://github.com/yourorg/ansible-role-custom-app.git scm: git version: main # Install from local path - name: internal-role src: /path/to/roles/internal-role
Advanced Role Patterns
Role with Multiple Entry Points
# roles/webserver/tasks/main.yml --- - name: Default task flow import_tasks: "{{ webserver_task_flow | default('standard') }}.yml"
# roles/webserver/tasks/standard.yml --- - import_tasks: install.yml - import_tasks: configure.yml - import_tasks: security.yml
# roles/webserver/tasks/minimal.yml --- - import_tasks: install.yml - import_tasks: configure.yml
Conditional Role Execution
--- - name: Configure servers with conditional roles hosts: all become: yes roles: - role: webserver when: - ansible_os_family == "Debian" - inventory_hostname in groups['webservers'] - role: webserver-nginx when: webserver_type == "nginx" - role: webserver-apache when: webserver_type == "apache"
Nested Role Dependencies
# roles/application/meta/main.yml --- dependencies: - role: webserver vars: nginx_sites: - name: "{{ app_name }}" server_name: "{{ app_domain }}" proxy_pass: "http://localhost:{{ app_port }}" - role: database vars: db_name: "{{ app_db_name }}" db_user: "{{ app_db_user }}" - role: monitoring vars: monitor_services: - nginx - "{{ app_name }}"
When to Use This Skill
Use the ansible-roles skill when you need to:
- Structure reusable automation code across multiple playbooks and projects
- Implement modular infrastructure as code with clear separation of concerns
- Share automation logic between teams or projects
- Create distributable automation packages for common infrastructure patterns
- Organize complex playbooks into manageable, testable components
- Implement role-based configuration management with variable precedence
- Build layered infrastructure with role dependencies
- Version control automation logic independently from playbooks
- Create standardized infrastructure components for consistency
- Implement security and compliance requirements through reusable roles
- Build internal automation libraries for your organization
- Contribute to or consume community automation from Ansible Galaxy
- Test infrastructure components in isolation before integration
- Implement different configurations for development, staging, and production
- Create self-documenting infrastructure through role metadata
Best Practices
- Follow standard directory structure - Use ansible-galaxy init to create roles with proper organization
- Use defaults wisely - Place overridable variables in defaults/main.yml, non-overridable in vars/main.yml
- Document thoroughly - Include comprehensive README.md with usage examples and variable documentation
- Keep roles focused - Each role should have a single, well-defined purpose
- Use role dependencies - Declare dependencies in meta/main.yml rather than in playbooks
- Tag appropriately - Apply meaningful tags to tasks for selective execution
- Implement idempotency - Ensure roles can be run multiple times safely
- Version your roles - Use semantic versioning for role releases
- Test roles independently - Include test playbooks in tests/ directory
- Use templates for configuration - Prefer Jinja2 templates over static files for flexibility
- Implement OS detection - Use ansible_os_family for cross-platform compatibility
- Secure sensitive data - Use ansible-vault for passwords and secrets in role variables
- Use handlers correctly - Only notify handlers when configuration changes
- Validate configurations - Use validate parameter in template/copy modules
- Name tasks clearly - Use descriptive names that explain what each task does
Common Pitfalls
- Overly complex roles - Trying to make one role do too many things
- Poor variable naming - Using generic names that conflict with other roles
- Missing role prefix - Not prefixing role variables with role name
- Ignoring variable precedence - Not understanding how Ansible resolves variable conflicts
- Hard-coded values - Embedding environment-specific values instead of using variables
- Missing dependencies - Not declaring role dependencies in meta/main.yml
- No validation - Deploying configurations without validation checks
- Skipping tests - Not including test playbooks or scenarios
- Poor handler design - Restarting services unnecessarily or not at all
- Missing OS support - Assuming all target systems are the same
- No backup strategy - Not backing up configurations before changes
- Ignoring idempotency - Using command/shell modules without proper guards
- Missing tags - Not tagging tasks for selective execution
- Poor template practices - Complex logic in templates instead of variables
- No version control - Not versioning roles or tracking changes