Preparing Internal Ansible Roles for Public GitHub Publication
Bottom line
Publishing internal Ansible roles on GitHub is a well-trodden path with mature tooling, but success requires more than pushing code. A structured 4-phase approach - sanitize, restructure, quality-gate, and promote - separates roles that languish at zero stars from those that gain adoption. The technical path is straightforward (ansible-lint + molecule + Galaxy import), but the social path (documentation, community engagement, launch timing) determines whether anyone finds and uses your work. Standalone roles remain the lower-friction starting point despite the community's gradual shift toward collections. Plan for a 30-day launch effort with at least a week of pre-launch quality hardening.
Key findings
-
Security sanitization is the critical first gate: Every fetched source that covers open-sourcing internal code emphasizes removing hardcoded credentials, internal hostnames, and proprietary references before going public. Red Hat's guidance (Source 9) shows externalizing all secrets to environment variables -
ANSIBLE_GALAXY_SERVER_<NAME>_TOKENpattern - and never storing tokens inansible.cfg. Real-world CVEs (SolarWinds CVE-2024-28987 CVSS 9.1, tj-actions supply chain attack affecting 23K repos) underscore the stakes. Agrepfor patterns likepassword:, internal FQDNs, and IP addresses should be run before any push. -
Galaxy quality scoring directly impacts discoverability: Galaxy scores roles based on
yamllint+ansible-lintoutput plus community surveys (Source 10). Penalties range from -1.0 (VERY_HIGH severity) to -0.075 (VERY_LOW). Incompletemeta/main.ymlcauses Galaxy to display "No platforms" - a signal that discourages users (Source 2). A role passingansible-lint --profile productionwith explicit platform declarations and descriptive galaxy_tags (max 20) will score higher and rank better in search results. -
Molecule + Docker + CI matrix is the testing standard: The current best practice (Sources 3, 11) uses geerlingguy's pre-built Docker images spanning 7 platforms (Ubuntu 20.04/22.04, Debian 11/12, Rocky 8/9, Amazon Linux 2023), run in parallel via GitHub Actions matrix builds with
fail-fast: false. Linting runs as a separate fast-feedback CI job (ansible-lint+yamllint) that completes in seconds. Pre-commit hooks catch issues before they reach CI. -
README quality and launch timing matter more than code quality for initial traction: The 30-day launch playbook (Source 5) emphasizes: launch Tuesday–Thursday 8–10 AM PT. A "Show HN" post with a founder's comment within 5 minutes; platform-tailored messaging; and responding to all comments within 2 hours. Repository polish - a demo GIF, one-line description, comparison table, and "good first issue" labels - determines whether visitors convert to stargazers. The first 30–60 minutes on Hacker News are the critical window for visibility.
-
Standalone roles vs. Collections: publish standalone now, plan migration later: The community is moving toward collections (Source 13 - Ansible docs officially document the migration path). Standalone roles remain fully supported and are lower friction for initial publishing. Adfinis (Source 15) notes "we generally recommend collections over single-role repositories" while acknowledging no official deprecation of standalone roles. The migration path (
ansible-galaxy collection init+ copy role toroles/) is well-documented, making it safe to start with standalone roles.
Background
Ansible Galaxy (galaxy.Ansible.Com) is the community hub for sharing Ansible roles and collections. Roles are standardized directory structures that encapsulate reusable automation tasks, handlers, variables, templates, and files. Publishing a role to Galaxy makes it installable with a single command (ansible-galaxy role install namespace.role_name). Galaxy imports roles directly from public GitHub repositories and uses Git tags matching SemVer as version numbers.
The ecosystem has been evolving since ~2020 from standalone roles toward collections - packages that bundle multiple roles, modules, and plugins under a namespace. But standalone roles remain the primary format for single-purpose automation sharing and are the recommended starting point for new publishers.
Current state (2026)
- Ansible Galaxy is actively maintained on the galaxy NG platform
ansible-galaxy role importand GitHub Actions auto-import are the standard publishing workflow- Community infrastructure includes Ansible Forum (forum.Ansible.Com), Ansible Bullhorn newsletter (200+ editions), Meetup Pro for global events, and an active subreddit ecosystem
- Galaxy content scoring uses yamllint + ansible-lint + import-time checks; community surveys augment scores after 3+ responses
- Molecule 5+ removed built-in lint; linting is now run directly (yamllint + ansible-lint) before molecule test
Technical and implementation details
Phase 1: Security sanitization
- Remove hardcoded credentials: Replace any inline passwords, tokens, or API keys with variables that default to empty/placeholder values
- Remove internal references: Search for internal hostnames, IPs, URLs, LDAP paths, and company-specific paths; replace with variables or remove
- Audit
defaults/main.yml: Ensure default values are safe for public exposure - no real credentials, no internal server names - Check
files/andtemplates/: Binary files and templates may contain embedded internal configuration; review all - Git history audit: Consider whether any previous commits contain sensitive data; use
git filter-branchor start fresh if needed - Run secrets scanners:
gitleaksortruffleHogagainst the full Git history
Phase 2: Structural cleanup
Target the community-standard structure (Source 14 - Adfinis):
ansible-role-<name>/
├── defaults/main.yml # Safe public defaults
├── handlers/main.yml # Service restarts via notify
├── meta/main.yml # Galaxy metadata (critical)
├── tasks/
│ ├── main.yml # Imports only + tags
│ ├── install.yml # Package installation
│ └── config.yml # Configuration rendering
├── templates/ # Mirror target filesystem paths
├── vars/
│ ├── Debian.yml # OS-specific static vars
│ └── RedHat.yml
├── molecule/default/ # Docker-based tests
├── .ansible-lint # Lint configuration
├── .yamllint # YAML style rules
├── .github/workflows/ # CI pipelines
├── README.md
├── LICENSE
├── CONTRIBUTING.md
└── CHANGELOG.md
Key conventions:
- Role tagging:
role::<rolename>:<subtask>(enables--tags role::nginx:install) - OS-specific vars loaded via
with_first_found:{{ ansible_distribution }}_{{ ansible_distribution_major_version }}.yml→{{ ansible_distribution }}.yml→{{ ansible_os_family }}.yml - Templates include
{{ ansible_managed | comment }}header - Service restarts via handlers, not conditional task logic
- Use
ansible.builtin.FQCN for all modules
Phase 3: Quality gates
Linting (runs first, takes seconds):
# .ansible-lint
profile: moderate # Start here, graduate to production
exclude_paths: [.cache/, .github/, molecule/, .venv/]
# .yamllint
extends: default
rules:
line-length: {max: 160, level: warning}
truthy: {allowed-values: ['true', 'false', 'yes', 'no']}
indentation: {spaces: 2, indent-sequences: true}
Pre-commit hooks (catches before commit):
# .pre-commit-config.yaml
repos:
- repo: https://github.com/ansible/ansible-lint
rev: v24.10.0
hooks:
- id: ansible-lint
- repo: https://github.com/adrienverge/yamllint
rev: v1.38.0
hooks:
- id: yamllint
CI workflow (GitHub Actions):
# .github/workflows/ci.yml
name: Molecule Test
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ansible/ansible-lint@main
molecule:
needs: lint
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
distro: [ubuntu2204, debian12, rocky9]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: {python-version: "3.11"}
- run: pip install ansible-core molecule molecule-plugins[docker]
- run: molecule test -- --limit ${{ matrix.distro }}
Galaxy auto-import on tag:
# .github/workflows/galaxy-import.yml
name: Import to Galaxy
on:
push:
tags: ['v*']
jobs:
import:
runs-on: ubuntu-latest
steps:
- run: pip install ansible
- run: ansible-galaxy role import --token "${{ secrets.GALAXY_API_KEY }}" <github-user> <repo-name>
Phase 4: Galaxy metadata
The meta/main.yml file is what Galaxy reads. Complete every field:
| Field | Requirement |
|---|---|
role_name |
Name users install (lowercase, underscores) |
author |
Your Galaxy username |
description |
Shows in search results |
license |
MIT or Apache 2.0 recommended |
min_ansible_version |
e.g., "2.14" |
platforms |
List OS + versions you've tested |
galaxy_tags |
Max 20, used for search/categorization |
dependencies |
List or [] |
Evidence, comparisons, and related context
Standalone roles vs. Collections: Collections are the community direction and required for Red Hat Certified Content. But standalone roles remain easier to publish, discover, and install. Recommendation: publish standalone roles now, migrate to a collection when you have 3+ related roles or custom modules (Sources 2, 13, 15).
Ansible vs. Other IaC tools: Ansible occupies the configuration management + application deployment niche. Terraform/Pulumi focus on infrastructure provisioning. In practice, Ansible roles complement rather than compete with Terraform modules - many teams use both. Position your roles accordingly.
Quality comparison: Roles with CI badges (passing tests) and Galaxy quality scores ≥4.0 signal reliability. Sources 2 and 10 confirm users check these indicators before installing. A role without CI badges will be compared unfavorably to roles that have them.
Limitations and critiques
- Galaxy scoring documentation gap: The only documented scoring system (Source 10) is from the old Galaxy platform. Current Galaxy NG scoring appears similar but lacks official public documentation. This is a source gap.
- No internal-to-public case studies found: Despite extensive search, no team has publicly documented their experience open-sourcing internal Ansible roles. The Supabase Ansible stack (Source 13 search result) is the closest example but not a detailed case study.
- Promotion advice is generic: The 30-day launch plan and growth strategies (Sources 5, 6) are general open-source advice. Ansible-specific promotion metrics are absent.
- Molecule Docker images from geerlingguy: While these are community standard, they depend on one maintainer. Consider the bus factor.
- The Galaxy ecosystem is consolidating toward collections: Publishing standalone roles in 2026 is valid but may require eventual migration. This should be factored into long-term maintenance planning.
Open questions
- What is the current Galaxy NG content scoring algorithm? (Old docs may be outdated)
- Do Ansible Bullhorn newsletter features drive measurable role adoption?
- Are there any teams that have documented their experience open-sourcing internal Ansible roles, including metrics before/after?
- What is the typical conversion rate from Galaxy views to
ansible-galaxy installfor a new role? - How much does the
ansible-role-prefix in repo names help or hurt GitHub search discoverability vs. Galaxy normalization?
Practical takeaways
-
Run the security grep first. Before any refactoring, scan for credentials, internal IPs, and company hostnames. This is the #1 risk when open-sourcing internal code. Use
gitleakson the full Git history. -
Start with
ansible-galaxy role initandansible-lint --fix. Generate a fresh skeleton, then port your logic into it rather than trying to clean the existing structure incrementally. Runansible-lint --fix .to auto-correct formatting issues. -
Use the cookiecutter-ansible-role template (idealista) or
ansible-galaxy role initto generate a standards-compliant skeleton with molecule tests, CI config, and pre-commit hooks already wired up. -
The
meta/main.ymlis your storefront - fill every field. Galaxy displays "No platforms" and "Empty description" for incomplete metadata, which directly reduces installs. Spend 15 minutes getting this right. -
CI badges build trust. A green CI badge and a Galaxy quality score ≥4.0 are the signals users look for before installing an unfamiliar role. Set up GitHub Actions with lint + molecule matrix before your first public push.
-
Launch on a Tuesday or Wednesday morning (PT). Post a "Show HN" on Hacker News, follow within 5 minutes with a detailed founder's comment. Respond to all feedback within hours. The first 60 minutes determine algorithmic visibility.
-
Plan for 30 days of sustained effort. Week -1: polish repo and build pre-launch buzz. Launch day: coordinated multi-platform push. Weeks 1-4: respond to feedback, publish weekly tutorials, engage community. Target: 500+ stars, 20+ contributors by day 30.
-
Consider the collection migration path early. Even if you start with standalone roles, structure them so migration to a collection is straightforward - use FQCN for modules, avoid hyphens in role names, and keep plugins separate from role logic.
Sources used
- Galaxy User Guide - Ansible Community Documentation - https://docs.ansible.com/projects/ansible/latest/galaxy/user_guide.html
- How to Publish Ansible Roles to Galaxy - oneuptime.Com - https://oneuptime.com/blog/post/2026-02-21-how-to-publish-ansible-roles-to-galaxy/view
- Molecule CI in GitHub Actions - Phil's Blog - https://philnewm.github.io/molecule-gh-action/
- Cookiecutter-ansible-role - idealista (GitHub) - https://github.com/idealista/cookiecutter-ansible-role
- Promote Your Open Source Project: 30-Day Launch Guide - daily.Dev - https://business.daily.dev/resources/promote-open-source-project-step-by-step-launch-guide/
- Open Source Fame: 0 to 10,000 GitHub Stars - markaicode.Com - https://markaicode.com/grow-github-repository-stars/
- Secure Code Audits in 2025 - codeant.Ai - https://www.codeant.ai/blogs/source-code-audit-checklist-best-practices-for-secure-code
- Guide for Publishing Open Source Code - Gov. Of Canada - https://github.com/canada-ca/open-source-logiciel-libre/blob/master/en/guides/publishing-open-source-code.md
- Strategies for Eliminating Ansible Hardcoded Credentials - Red Hat Developer - https://developers.redhat.com/articles/2025/01/23/strategies-eliminating-ansible-hardcoded-credentials
- Content Scoring - Ansible Documentation (old Galaxy) - https://old-galaxy.ansible.com/docs/contributing/content_scoring.html
- Testing Ansible Roles Across Multiple OS Versions - oneuptime.Com - https://oneuptime.com/blog/post/2026-02-21-how-to-test-ansible-roles-across-multiple-os-versions/view
- Improving Ansible Meetups - Ansible Forum - https://forum.ansible.com/t/improving-ansible-meetups/43491
- Migrating Roles to Roles in Collections - Ansible Docs - https://docs.ansible.com/projects/ansible/latest/dev_guide/migrating_roles.html
- Roles & Collections - Adfinis Ansible Guide - https://docs.adfinis.com/ansible-guide/roles_collections.html
- Ansible-Lint Rule Analysis and Best Practices - ansiblebyexample.Com - https://www.ansiblebyexample.com/articles/ansible-lint-best-practices-and-automation
- How to Use Molecule Lint - oneuptime.Com - https://oneuptime.com/blog/post/2026-02-21-how-to-use-molecule-lint-to-check-ansible-syntax/view