Introduction

Ansible Lint Rule 106 (role-name) enforces naming conventions for Ansible roles. Role names must use only lowercase alphanumeric characters and underscores, and must start with a letter. This prevents issues with Galaxy imports, cross-platform compatibility, and playbook readability. This article covers the rule, common violations, how to rename roles, and Galaxy namespace requirements.

The Rule

Role names must follow these requirements:

  1. Start with a letter (a-z)
  2. Contain only lowercase letters (a-z), digits (0-9), and underscores (_)
  3. No uppercase, hyphens, dots, spaces, or special characters

Valid Role Names

webserver
my_app
database_backup
nginx_proxy_v2
role42
load_balancer_ha

Invalid Role Names

1myrole        # starts with a digit
my-role        # contains hyphen
myRole         # contains uppercase
my.role        # contains dot
web server     # contains space
rôle_config    # contains non-ASCII character

The Error

Problematic Code

---
- name: Example playbook
  hosts: all
  roles:
    - My-WebServer       # uppercase + hyphen
    - 1st_database       # starts with digit
    - cache.server       # contains dot

Lint Output

$ ansible-lint playbook.yml
WARNING  Listing 3 violation(s) that are fatal
role-name[non-lowercase]: Role name 'My-WebServer' is not valid.
playbook.yml:5

role-name[non-alphanumeric]: Role name '1st_database' does not start with alphabetic character.
playbook.yml:6

role-name[non-alphanumeric]: Role name 'cache.server' contains invalid characters.
playbook.yml:7

Failed: 3 failure(s), 0 warning(s) on 1 files.

Fixed Code

---
- name: Example playbook
  hosts: all
  roles:
    - my_webserver
    - first_database
    - cache_server

Why These Rules Exist

1. Ansible Galaxy Compatibility

Galaxy enforces the same naming rules. Roles with invalid names cannot be published:

# This fails on Galaxy upload
$ ansible-galaxy role import my-org My-WebServer
ERROR! Invalid role name 'My-WebServer'

# This works
$ ansible-galaxy role import my_org my_webserver

2. Cross-Platform File Systems

Some operating systems are case-insensitive (macOS, Windows). A role named WebServer and webserver would collide:

roles/
├── WebServer/    # On case-insensitive FS, these
├── webserver/    # are the SAME directory

3. Python Module Compatibility

When roles are part of collections, they map to Python namespaces. Python modules must follow the same naming rules:

# Valid Python module name
from ansible_collections.my_namespace.my_collection.roles import webserver

# Invalid — hyphens aren't allowed in Python identifiers
from ansible_collections.my_namespace.my_collection.roles import web-server  # SyntaxError

4. URL and Path Safety

Role names appear in URLs (Galaxy), file paths, and variable names. Special characters cause issues:

# Galaxy URL — clean
https://galaxy.ansible.com/ui/standalone/roles/geerlingguy/docker/

# Broken if role had dots or spaces
https://galaxy.ansible.com/ui/standalone/roles/my org/web.server/  # broken URL

Renaming Existing Roles

Step 1: Rename the Directory

# Old name
mv roles/My-WebServer roles/my_webserver

Step 2: Update meta/main.yml

# roles/my_webserver/meta/main.yml
galaxy_info:
  role_name: my_webserver
  author: your_name
  description: Install and configure nginx web server
  company: example
  license: MIT
  min_ansible_version: "2.14"
  platforms:
    - name: Ubuntu
      versions:
        - jammy
        - noble
    - name: EL
      versions:
        - "8"
        - "9"
  galaxy_tags:
    - webserver
    - nginx

Step 3: Update All References

# Find all references to the old name
grep -r "My-WebServer" --include="*.yml" --include="*.yaml" .

# Update playbooks
sed -i 's/My-WebServer/my_webserver/g' site.yml deploy.yml

Step 4: Update Dependencies

# roles/my_app/meta/main.yml
dependencies:
  - role: my_webserver    # was: My-WebServer
    vars:
      http_port: 8080

Role Name in Different Contexts

In Playbooks

# Direct reference
roles:
  - my_webserver

# With variables
roles:
  - role: my_webserver
    vars:
      http_port: 443

# Using include_role
tasks:
  - name: Include webserver role
    ansible.builtin.include_role:
      name: my_webserver

In requirements.yml

# Galaxy role
- name: geerlingguy.docker
  version: "7.1.0"

# Git source — src can have hyphens, name must not
- src: https://github.com/example/ansible-role-webserver.git
  name: my_webserver
  version: main

In Collections

Collection roles follow the same rules, with the namespace prefix:

my_namespace.my_collection.my_role    # valid
my_namespace.my_collection.My-Role    # invalid

Common Patterns for Converting Names

Old NameNew NameIssue
My-WebServermy_webserverUppercase + hyphen
1st-deployfirst_deployStarts with digit + hyphen
app.server.v2app_server_v2Dots
Load-Balancerload_balancerUppercase + hyphen
DB Backupdb_backupSpace
CacheLayercache_layerCamelCase

Automated Conversion Script

#!/bin/bash
# Convert role directory names to valid format
for dir in roles/*/; do
  old_name=$(basename "$dir")
  # Convert to lowercase, replace hyphens/dots/spaces with underscores
  new_name=$(echo "$old_name" | tr '[:upper:]' '[:lower:]' | sed 's/[-. ]/_/g')
  # Remove leading digits
  new_name=$(echo "$new_name" | sed 's/^[0-9]*//')
  if [ "$old_name" != "$new_name" ]; then
    echo "Renaming: $old_name → $new_name"
    mv "roles/$old_name" "roles/$new_name"
  fi
done

Galaxy Namespace Rules

Galaxy namespaces have similar but slightly different rules:

ComponentAllowed CharactersExample
Namespacea-z, 0-9, _ (start with letter)geerlingguy
Role namea-z, 0-9, _ (start with letter)docker
Collectionnamespace.nameansible.builtin
# Valid Galaxy references
$ ansible-galaxy role install geerlingguy.docker
$ ansible-galaxy collection install community.general

# Invalid — hyphens not allowed in namespace
$ ansible-galaxy role install my-org.my-role  # ERROR

Auto-Fix with ansible-lint

# ansible-lint cannot auto-fix role names (requires directory rename)
# But it clearly reports what needs changing:
$ ansible-lint roles/
role-name: Role name 'My-WebServer' does not comply with requirements.

Best Practices

  1. Use snake_case — my_webserver, not myWebServer or my-webserver
  2. Be descriptive — nginx_reverse_proxy over role1
  3. Prefix with purpose — deploy_app, configure_database, install_monitoring
  4. Match Galaxy convention — author.role_name (e.g., geerlingguy.docker)
  5. Avoid version numbers in names — use Galaxy versioning instead of my_role_v2
  6. Set role_name in meta — explicitly declare the name in meta/main.yml
  7. Check before creating — run ansible-lint on new roles immediately

Conclusion

Ansible Lint Rule 106 (role-name) ensures role names use only lowercase alphanumeric characters and underscores, starting with a letter. This prevents Galaxy import failures, cross-platform path collisions, and Python namespace issues. Use snake_case for all role names, update meta/main.yml with the role_name field, and run ansible-lint to catch violations early.