diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 00000000..27105069 --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,6 @@ +--- +offline: true +exclude_paths: + - .github/ +skip_list: + - yaml[line-length] diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..17232369 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,9 @@ +##################### +# Main global owner # +##################### +* @nginx/ansible + +################################################ +# Enable auto merge on GitHub Action workflows # +################################################ +/.github/workflows diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 12c0b3ec..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' ---- -### Describe the bug - -A clear and concise description of what the bug is. - -### To reproduce - -Steps to reproduce the behavior: - -1. Deploy NGINX Config role using playbook.yml -2. View output/logs/configuration on '...' -3. See error - -### Expected behavior - -A clear and concise description of what you expected to happen. - -### Your environment - -- Version of the NGINX Config role or specific commit -- Version of Ansible -- Version of Jinja2 (if you are using any templating capability) -- Target deployment platform - -### Additional context - -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..3d8455f4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,71 @@ +--- +name: ๐Ÿ› Bug report +description: Create a report to help us improve +labels: bug +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + + Before you continue filling out this report, please take a moment to check that your bug has not been [already reported on GitHub][issue search] ๐Ÿ™Œ + + Remember to redact any sensitive information such as authentication credentials and/or license keys! + + **Note:** If you are seeking community support or have a question, please consider starting a new thread via [GitHub discussions][discussions] or the [NGINX Community forum][forum]. + + [issue search]: https://github.com/nginx/ansible-role-nginx-config/issues + [discussions]: https://github.com/nginx/ansible-role-nginx-config/discussions + [forum]: https://community.nginx.org + + - type: textarea + id: overview + attributes: + label: Bug Overview + description: A clear and concise overview of the bug. + placeholder: When I do "X" with the NGINX config Ansible role, "Y" happens instead of "Z". + validations: + required: true + + - type: textarea + id: behavior + attributes: + label: Expected Behavior + description: A clear and concise description of what you expected to happen. + placeholder: When I do "X" with the NGINX config Ansible role, I expect "Z" to happen. + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to Reproduce the Bug + description: Detail the series of steps required to reproduce the bug. + value: | + 1. I have deployed/run the NGINX config Ansible role using the following `playbook.yml`... + 2. I have seen the following error(s) on my terminal/logs... + validations: + required: true + + - type: textarea + id: environment + attributes: + label: Environment Details + description: Please provide details about your environment. + value: | + - Target deployment platforms: [e.g. AWS/GCP/local cluster/etc...] + - Target OSs: [e.g. RHEL 9/Ubuntu 24.04/etc...] + - Host OS (where you are running Ansible from): [e.g. RHEL 9/Ubuntu 24.04/etc...] + - Version of the NGINX Ansible role (or specific commit): [e.g. 0.25.0/commit hash] + - Version of Ansible: [e.g. 2.16.5] + - How is Ansible being managed: [e.g. CLI/pipeline/Automation Hub/etc...] + - Version of Jinja2 (if you are using any templating capability): [e.g. 3.1.1] + validations: + required: true + + - type: textarea + id: context + attributes: + label: Additional Context + description: Add any other context about the problem here. + placeholder: Feel free to add any other context/information/screenshots/etc... that you think might be relevant to this issue in here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..3f7850f7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,12 @@ +--- +blank_issues_enabled: false +contact_links: + - name: ๐Ÿ’ฌ Talk to the NGINX community! + url: https://community.nginx.org + about: A community forum for NGINX users, developers, and contributors + - name: ๐Ÿ“ Code of Conduct + url: https://www.contributor-covenant.org/version/2/1/code_of_conduct + about: NGINX follows the Contributor Covenant Code of Conduct to ensure a safe and inclusive community + - name: ๐Ÿ’ผ For commercial & enterprise users + url: https://www.f5.com/products/nginx + about: F5 offers a wide range of NGINX products for commercial & enterprise users diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index d27aba8e..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' ---- -### Is your feature request related to a problem? Please describe - -A clear and concise description of what the problem is. Ex. I'm always frustrated when ... - -### Describe the solution you'd like - -A clear and concise description of what you want to happen. - -### Describe alternatives you've considered - -A clear and concise description of any alternative solutions or features you've considered. - -### Additional context - -Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..04e60aaa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,40 @@ +--- +name: โœจ Feature request +description: Suggest an idea for this project +labels: enhancement +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this feature request! + + Before you continue filling out this request, please take a moment to check that your feature has not been [already requested on GitHub][issue search] ๐Ÿ™Œ + + **Note:** If you are seeking community support or have a question, please consider starting a new thread via [GitHub discussions][discussions] or the [NGINX Community forum][forum]. + + [issue search]: https://github.com/nginx/ansible-role-nginx-config/issues + [discussions]: https://github.com/nginx/ansible-role-nginx-config/discussions + [forum]: https://community.nginx.org + + - type: textarea + id: overview + attributes: + label: Feature Overview + description: A clear and concise description of what the feature request is. + placeholder: I would like the NGINX config Ansible role to be able to do "X". + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: Detail any potential alternative solutions/workarounds you've used or considered. + placeholder: I have done/might be able to do "X" in the NGINX config Ansible role by doing "Y". + + - type: textarea + id: context + attributes: + label: Additional Context + description: Add any other context about the problem here. + placeholder: Feel free to add any other context/information/screenshots/etc... that you think might be relevant to this feature request here. diff --git a/.github/SECURITY.md b/.github/SECURITY.md deleted file mode 100644 index b11b8e47..00000000 --- a/.github/SECURITY.md +++ /dev/null @@ -1,9 +0,0 @@ -# Security Policy - -## Supported Versions - -This role mainly consists of Ansible tasks. Ansible applies security fixes to the most recent three releases. Please find more information in [the Ansible docs](https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html#release-status). - -## Reporting a Vulnerability - -If you find a security vulnerability that affects Ansible, we encourage you to report it according to the [Ansible guidelines](https://docs.ansible.com/ansible/devel/community/reporting_bugs_and_features.html#reporting-a-bug). diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index d8636089..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -version: 2 -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - - package-ecosystem: "pip" - directory: "/.github/workflows/requirements" - schedule: - interval: "weekly" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 3a96a0b8..3c1b1f03 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,12 +1,13 @@ ### Proposed changes -Describe the use case and detail of the change. If this PR addresses an issue on GitHub, make sure to include a link to that issue using one of the [supported keywords](https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) here in this description (not in the title of the PR). +Describe the use case and detail of the change. If this PR addresses an issue on GitHub, make sure to include a link to that issue using one of the [supported keywords](https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) in this PR's description or commit message. ### Checklist -Before creating a PR, run through this checklist and mark each as complete. +Before creating a PR, run through this checklist and mark each as complete: -- [ ] I have read the [CONTRIBUTING](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/CONTRIBUTING.md) document -- [ ] I have added Molecule tests that prove my fix is effective or that my feature works -- [ ] I have checked that any relevant Molecule tests pass after adding my changes -- [ ] I have updated any relevant documentation (`defaults/main/*.yml`, `README.md` and `CHANGELOG.md`) +- [ ] I have read the [contributing guidelines](/CONTRIBUTING.md). +- [ ] I have signed the [F5 Contributor License Agreement (CLA)](https://github.com/f5/f5-cla/blob/main/docs/f5_cla.md). +- [ ] If applicable, I have added Molecule tests that prove my fix is effective or that my feature works. +- [ ] If applicable, I have checked that any relevant Molecule tests pass after adding my changes. +- [ ] I have updated any relevant documentation ([`defaults/main/*.yml`](/defaults/main/), [`README.md`](/README.md) and [`CHANGELOG.md`](/CHANGELOG.md)). diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 92e753fa..ec310454 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,84 +1,117 @@ --- name-template: "$RESOLVED_VERSION" tag-template: "$RESOLVED_VERSION" +include-pre-releases: true categories: - - title: "๐Ÿ’ฃ Breaking Changes" + - title: ๐Ÿ’ฃ Breaking Changes labels: - - "breaking change" - - title: "๐Ÿ”” Deprecation Warnings" + - breaking change + - title: ๐Ÿ”” Deprecation Warnings labels: - - "deprecation" - - title: "๐Ÿš€ Features" + - deprecation + - title: ๐Ÿš€ Features labels: - - "feature" - - title: "๐ŸŽ‰ Enhancements" + - enhancement + - title: ๐Ÿ› Bug Fixes labels: - - "enhancement" - - title: "๐Ÿ› Bug Fixes" + - bug + - title: ๐Ÿงช Tests labels: - - "bug" - - title: "๐Ÿ“ Documentation" + - tests + - title: ๐Ÿ”จ Maintenance labels: - - "documentation" - - title: "โฌ†๏ธ Dependencies" + - chore + - title: ๐Ÿ‘ท CI/CD labels: - - "dependencies" + - ci + - title: โฌ†๏ธ Dependencies + collapse-after: 15 + labels: + - dependencies + - title: ๐Ÿ“ Documentation + labels: + - documentation + - title: Other Changes + labels: + - "*" exclude-labels: - - "skip-changelog" + - skip changelog version-resolver: minor: labels: - - "breaking change" - - "deprecation" + - breaking change + - deprecation patch: labels: - - "bug" - - "dependencies" - - "documentation" - - "feature" - - "enhancement" + - bug + - ci + - chore + - dependencies + - documentation + - enhancement + - tests default: patch autolabeler: - - label: "breaking change" + - label: breaking change body: - "/breaking/i" - - label: "deprecation" + title: + - "/breaking/i" + - "/^\\w+!/i" + - label: deprecation branch: - "/deprecate\/.+/" title: - "/deprecate/i" - - label: "feature" + - label: enhancement branch: - "/feat\/.+/" - "/feature\/.+/" - - "/implement\/.+/" title: - "/feat/i" - "/feature/i" - - "/implement/i" - - label: "enhancement" - branch: - - "/add\/.+/" - - "/enhancement\/.+/" - title: - - "/add/i" - - "/enhancement/i" - - label: "bug" + - label: bug branch: - "/fix\/.+/" + - "/bug\/.+/" + - "/bugfix\/.+/" title: - "/fix/i" - - label: "documentation" + - "/bug/i" + - "/bugfix/i" + - label: tests branch: - - "/docs\/.+/" + - "/tests{0,1}\/.+/" files: - - "**/!(changelog).md" + - "/tests/**" title: - - "/docs/i" - - "/documentation/i" - - label: "dependencies" + - "/tests{0,1}\/.+/i" + - label: documentation + branch: + - "/docs{0,1}\/.+/" + - "/documentation\/.+/" files: - - ".github/workflows/requirements/*" + - "docs/**" + title: + - "/docs{0,1}\/.+/i" + - "/documentation/i" + - label: ci + branch: + - "/ci\/.+/" + title: + - "/ci/i" + - label: chore + branch: + - "/chore\/.+/" + - "/refactor\/.+/" + - "/style\/.+/" + title: + - "/chore/i" + - "/refactor/i" + - "/style/i" +replacers: + - search: "/(\\w+)(\\(\\w+\\))?!?: /g" + replace: "" template: | ๐Ÿ‘พ *Help make the NGINX config Ansible role better by participating in our [survey](https://forms.office.com/Pages/ResponsePage.aspx?id=L_093Ttq0UCb4L-DJ9gcUKLQ7uTJaE1PitM_37KR881UM0NCWkY5UlE5MUYyWU1aTUcxV0NRUllJSC4u)!* ๐Ÿ‘พ @@ -88,13 +121,13 @@ template: | ## Install & Upgrade - * To install the Ansible NGINX config role on a fresh environment, run `ansible-galaxy install nginxinc.nginx_config`. - * To upgrade the Ansible NGINX config role to the latest release, run `ansible-galaxy install -f nginxinc.nginx_config`. - * To install or upgrade to this specific Ansible NGINX config role release ($RESOLVED_VERSION), run `ansible-galaxy install -f nginxinc.nginx_config,v$RESOLVED_VERSION`. + - To install the Ansible NGINX config role on a fresh environment, run `ansible-galaxy install nginxinc.nginx_config`. + - To upgrade the Ansible NGINX config role to the latest release, run `ansible-galaxy install -f nginxinc.nginx_config`. + - To install or upgrade to this specific Ansible NGINX config role release ($RESOLVED_VERSION), run `ansible-galaxy install -f nginxinc.nginx_config,v$RESOLVED_VERSION`. ## Resources - * Functional configuration examples (check `converge.yml` under each `molecule` scenario) -- [github.com/nginxinc/ansible-role-nginx-config/tree/$RESOLVED_VERSION/molecule](https://github.com/nginxinc/ansible-role-nginx-config/tree/$RESOLVED_VERSION/molecule). - * Ansible Galaxy repository -- [galaxy.ansible.com/nginxinc/nginx_config](https://galaxy.ansible.com/nginxinc/nginx_config). - * NGINX Ansible role & collection introductory blog -- [nginx.com/blog/announcing-nginx-core-collection-ansible](https://www.nginx.com/blog/announcing-nginx-core-collection-ansible). - * NGINX: Better with Ansible demo -- [github.com/alessfg/nginx-ansible-demo](https://github.com/alessfg/nginx-ansible-demo). + - Functional configuration examples (check `converge.yml` under each `molecule` scenario) -- [github.com/nginx/ansible-role-nginx-config/tree/$RESOLVED_VERSION/molecule](https://github.com/nginx/ansible-role-nginx-config/tree/$RESOLVED_VERSION/molecule). + - Ansible Galaxy repository -- [galaxy.ansible.com/nginxinc/nginx_config](https://galaxy.ansible.com/nginxinc/nginx_config). + - NGINX Ansible role & collection introductory blog -- [nginx.com/blog/announcing-nginx-core-collection-ansible](https://www.f5.com/blog/announcing-nginx-core-collection-ansible). + - NGINX: Better with Ansible demo -- [github.com/alessfg/nginx-ansible-demo](https://github.com/alessfg/nginx-ansible-demo). diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 00000000..f09f6db8 --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,126 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ], + "commitMessageLowerCase": "never", + "labels": [ + "dependencies" + ], + "prConcurrentLimit": 0, + "prHourlyLimit": 0, + "schedule": [ + "* 0-7 * * 1" + ], + "packageRules": [ + { + "groupName": "Ansible collections", + "matchManagers": [ + "ansible-galaxy", + "custom.regex" + ], + "automerge": true, + "matchCurrentVersion": "!/^0/", + "matchUpdateTypes": [ + "minor", + "patch" + ] + } + ], + "ansible-galaxy": { + "fileMatch": [ + "(^|/)[\\w-]*requirements([_.]\\w+)?\\.ya?ml$" + ] + }, + "customManagers": [ + { + "customType": "regex", + "datasourceTemplate": "galaxy-collection", + "fileMatch": [ + "README.md" + ], + "matchStrings": [ + "- name: (?\\w+\\.\\w+)(?:\\s+#.*)?\\s+version: (?\\d+\\.\\d+\\.\\d+)" + ], + "versioningTemplate": "semver" + } + ], + "dockerfile": { + "ignorePaths": [ + "molecule/**/Dockerfile.j2" + ] + }, + "github-actions": { + "addLabels": [ + "skip changelog" + ], + "packageRules": [ + { + "groupName": "GitHub Actions", + "matchPackageNames": [ + "actions/**", + "github/**" + ] + }, + { + "groupName": "Docker Actions", + "matchPackageNames": [ + "docker/**" + ] + }, + { + "enabled": false, + "matchUpdateTypes": [ + "digest" + ] + }, + { + "automerge": true, + "matchUpdateTypes": [ + "minor", + "patch" + ], + "matchCurrentVersion": "!/^0/" + } + ] + }, + "pip_requirements": { + "fileMatch": [ + "(^|/)[\\w-]*requirements([_.]\\w+)?\\.(txt|pip)$" + ], + "packageRules": [ + { + "groupName": "Python dependencies", + "matchPackageNames": [ + "*" + ] + }, + { + "groupName": "Ansible core", + "matchPackageNames": [ + "ansible-core" + ], + "separateMinorPatch": true, + "separateMultipleMinor": true + }, + { + "groupName": "Ansible devtools", + "matchPackageNames": [ + "ansible-compat", + "ansible-lint", + "molecule", + "molecule-plugins" + ], + "separateMajorMinor": false, + "separateMinorPatch": true + }, + { + "automerge": true, + "matchUpdateTypes": [ + "patch" + ], + "matchCurrentVersion": "!/^0/" + } + ] + } +} diff --git a/.github/scorecard.yml b/.github/scorecard.yml new file mode 100644 index 00000000..00d6ade6 --- /dev/null +++ b/.github/scorecard.yml @@ -0,0 +1,10 @@ +--- +annotations: + - checks: + - fuzzing + - packaging + - pinned-dependencies + - sast + - signed-releases + reasons: + - reason: not-applicable diff --git a/.github/workflows/f5_cla.yml b/.github/workflows/f5_cla.yml new file mode 100644 index 00000000..43e473ea --- /dev/null +++ b/.github/workflows/f5_cla.yml @@ -0,0 +1,41 @@ +--- +name: F5 CLA +on: + issue_comment: + types: [created] + pull_request_target: + types: [opened, closed, synchronize] +permissions: read-all +jobs: + f5-cla: + name: F5 CLA + runs-on: ubuntu-24.04 + permissions: + actions: write + pull-requests: write + statuses: write + steps: + - name: Run F5 Contributor License Agreement (CLA) assistant + if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have hereby read the F5 CLA and agree to its terms') || github.event_name == 'pull_request_target' + uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1 + with: + # Path to the CLA document. + path-to-document: https://github.com/f5/f5-cla/blob/main/docs/f5_cla.md + # Custom CLA messages. + custom-notsigned-prcomment: '๐ŸŽ‰ Thank you for your contribution! It appears you have not yet signed the [F5 Contributor License Agreement (CLA)](https://github.com/f5/f5-cla/blob/main/docs/f5_cla.md), which is required for your changes to be incorporated into an F5 Open Source Software (OSS) project. Please kindly read the [F5 CLA](https://github.com/f5/f5-cla/blob/main/docs/f5_cla.md) and reply on a new comment with the following text to agree:' + custom-pr-sign-comment: 'I have hereby read the F5 CLA and agree to its terms' + custom-allsigned-prcomment: 'โœ… All required contributors have signed the F5 CLA for this PR. Thank you!' + # Remote repository storing CLA signatures. + remote-organization-name: f5 + remote-repository-name: f5-cla-data + # Branch where CLA signatures are stored. + branch: main + path-to-signatures: signatures/signatures.json + # Comma separated list of usernames for maintainers or any other individuals who should not be prompted for a CLA. + # NOTE: You will want to edit the usernames to suit your project needs. + allowlist: bot* + # Do not lock PRs after a merge. + lock-pullrequest-aftermerge: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PERSONAL_ACCESS_TOKEN: ${{ secrets.F5_CLA_TOKEN }} diff --git a/.github/workflows/galaxy.yml b/.github/workflows/galaxy.yml index 600aac03..69b9b473 100644 --- a/.github/workflows/galaxy.yml +++ b/.github/workflows/galaxy.yml @@ -1,24 +1,25 @@ --- -name: Ansible Galaxy import -"on": +name: Ansible Galaxy Role Import +on: release: - types: - - published + types: [published] + workflow_dispatch: +permissions: read-all jobs: - galaxy: - name: Galaxy - runs-on: ubuntu-20.04 + ansible-galaxy: + name: Import role to Ansible Galaxy + runs-on: ubuntu-24.04 steps: - name: Check out the codebase - uses: actions/checkout@v2.3.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Python 3 - uses: actions/setup-python@v2.2.2 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: 3.x - - name: Install Ansible - run: pip3 install -r .github/workflows/requirements/requirements_galaxy.txt + - name: Install Ansible core + run: pip3 install -r .github/workflows/requirements/requirements_ansible.txt - - name: Import release to Ansible Galaxy + - name: Import role releases to Ansible Galaxy run: ansible-galaxy role import --api-key ${{ secrets.GALAXY_API_KEY }} $(echo ${{ github.repository }} | cut -d/ -f1) $(echo ${{ github.repository }} | cut -d/ -f2) diff --git a/.github/workflows/milestone-pr.yml b/.github/workflows/milestone-pr.yml new file mode 100644 index 00000000..3e704664 --- /dev/null +++ b/.github/workflows/milestone-pr.yml @@ -0,0 +1,42 @@ +--- +name: Milestone & Project PR Automation +on: + pull_request: + branches: [main] + workflow_dispatch: +permissions: read-all +jobs: + milestone: + name: Add milestone to GitHub PR + if: github.actor == 'renovate[bot]' + runs-on: ubuntu-24.04 + permissions: + issues: write + pull-requests: write + steps: + - name: Find current milestone and add it to GitHub PR + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const { data: [milestone] } = await github.rest.issues.listMilestones({ + owner: context.repo.owner, + repo: context.repo.repo, + }); + + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + milestone: milestone.number, + }); + + project: + name: Add project to GitHub PR + if: github.actor == 'renovate[bot]' + runs-on: ubuntu-24.04 + steps: + - name: Add Project + uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v.1.0.2 + with: + project-url: https://github.com/orgs/nginx/projects/30/views/1 + github-token: ${{ secrets.ADD_TO_PROJECT_TOKEN }} diff --git a/.github/workflows/molecule.yml b/.github/workflows/molecule.yml index 12d20c97..d627a48a 100644 --- a/.github/workflows/molecule.yml +++ b/.github/workflows/molecule.yml @@ -1,52 +1,82 @@ --- name: Molecule CI/CD -"on": +on: pull_request: - branches: - - main + branches: [main] push: - branches: - - main - ignore-tags: - - "*" + branches: [main] + tags-ignore: ["**"] + merge_group: schedule: - cron: "0 0 1 * *" workflow_dispatch: +permissions: read-all jobs: + ansible-lint: + name: Ansible Lint + runs-on: ubuntu-24.04 + steps: + - name: Check out the codebase + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up Python 3 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: 3.x + + - name: Install Ansible core and Ansible Lint + run: pip3 install -r .github/workflows/requirements/requirements_ansible_lint.txt + + - name: Install Ansible core collection dependencies + run: ansible-galaxy install -r .github/workflows/requirements/requirements_collections.yml + + - name: Run Ansible Lint + run: ansible-lint --force-color + molecule: name: Molecule - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 + env: + NGINX_CRT: ${{ secrets.NGINX_CRT }} + NGINX_KEY: ${{ secrets.NGINX_KEY }} + NGINX_JWT: ${{ secrets.NGINX_JWT }} strategy: + fail-fast: false matrix: scenario: - - cleanup_module + - api_plus + - cleanup_config + - complete + - complete_plus - default - - plus - - stable_push + - entitlement_plus + - push_config + - reverse_proxy + - stub_status + - web_server + needs: ansible-lint steps: - name: Check out the codebase - if: "!(contains(matrix.scenario, 'plus') && github.event.pull_request.head.repo.full_name != github.repository)" - uses: actions/checkout@v2.3.5 + if: ${{ !(contains(matrix.scenario, 'plus')) || (env.NGINX_CRT != 0 && env.NGINX_KEY != 0) }} + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Python 3 - if: "!(contains(matrix.scenario, 'plus') && github.event.pull_request.head.repo.full_name != github.repository)" - uses: actions/setup-python@v2.2.2 + if: ${{ !(contains(matrix.scenario, 'plus')) || (env.NGINX_CRT != 0 && env.NGINX_KEY != 0) }} + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: 3.x - - name: Install Molecule dependencies - if: "!(contains(matrix.scenario, 'plus') && github.event.pull_request.head.repo.full_name != github.repository)" + - name: Install Ansible core and Molecule + if: ${{ !(contains(matrix.scenario, 'plus')) || (env.NGINX_CRT != 0 && env.NGINX_KEY != 0) }} run: pip3 install -r .github/workflows/requirements/requirements_molecule.txt - - name: Install Ansible base dependencies - if: "!(contains(matrix.scenario, 'plus') && github.event.pull_request.head.repo.full_name != github.repository)" - run: ansible-galaxy install -r .github/workflows/requirements/requirements_ansible.yml + - name: Install Ansible core collection dependencies + if: ${{ !(contains(matrix.scenario, 'plus')) || (env.NGINX_CRT != 0 && env.NGINX_KEY != 0) }} + run: ansible-galaxy install -r .github/workflows/requirements/requirements_collections.yml - name: Run Molecule tests - if: "!(contains(matrix.scenario, 'plus') && github.event.pull_request.head.repo.full_name != github.repository)" + if: ${{ !(contains(matrix.scenario, 'plus')) || (env.NGINX_CRT != 0 && env.NGINX_KEY != 0) }} run: molecule test -s ${{ matrix.scenario }} env: PY_COLORS: 1 ANSIBLE_FORCE_COLOR: 1 - NGINX_CRT: ${{ secrets.NGINX_CRT }} - NGINX_KEY: ${{ secrets.NGINX_KEY }} diff --git a/.github/workflows/ossf_scorecard.yml b/.github/workflows/ossf_scorecard.yml new file mode 100644 index 00000000..2d996de4 --- /dev/null +++ b/.github/workflows/ossf_scorecard.yml @@ -0,0 +1,50 @@ +--- +# This workflow uses actions that are not certified by GitHub. They are provided by a third-party and are governed by separate terms of service, privacy policy, and support documentation. +name: OSSF Scorecard +on: + # For Branch-Protection check. Only the default branch is supported. See https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection. + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained. + schedule: + - cron: "0 0 * * 1" + push: + branches: [main] + workflow_dispatch: +# Declare default permissions as read only. +permissions: read-all +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-24.04 + permissions: + # Needed if using Code Scanning alerts. + security-events: write + # Needed for GitHub OIDC token if publish_results is true. + id-token: write + steps: + - name: Check out the codebase + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - name: Run analysis + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 + with: + results_file: results.sarif + results_format: sarif + # Publish the results for public repositories to enable scorecard badges. For more details, see https://github.com/ossf/scorecard-action#publishing-results. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF format to the repository Actions tab. + - name: Upload artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: Upload SARIF results to code scanning + uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2 + with: + sarif_file: results.sarif diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml deleted file mode 100644 index df48be6d..00000000 --- a/.github/workflows/release-drafter.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Release Drafter -"on": - pull_request: - types: - - opened - - reopened - - synchronize - push: - branches: - - main -jobs: - update_release_draft: - name: Update release draft - runs-on: ubuntu-20.04 - steps: - - uses: release-drafter/release-drafter@v5 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..e6f2d05a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,23 @@ +--- +name: Release Drafter +on: + push: + branches: [main] + pull_request_target: + types: [opened, reopened, synchronize] + workflow_dispatch: +permissions: read-all +jobs: + update-release-draft: + name: Update release draft + runs-on: ubuntu-24.04 + permissions: + contents: write + pull-requests: write + steps: + - name: Run Release Drafter + uses: release-drafter/release-drafter@b1476f6e6eb133afa41ed8589daba6dc69b4d3f5 # v6.1.0 + with: + disable-autolabeler: ${{ github.actor == 'renovate[bot]' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/requirements/requirements_ansible_lint.txt b/.github/workflows/requirements/requirements_ansible_lint.txt new file mode 100644 index 00000000..aae950c3 --- /dev/null +++ b/.github/workflows/requirements/requirements_ansible_lint.txt @@ -0,0 +1,4 @@ +ansible-core==2.16.14 +ansible-compat==25.6.0 +yamllint==1.37.1 +ansible-lint==25.6.1 \ No newline at end of file diff --git a/.github/workflows/requirements/requirements_ansible.yml b/.github/workflows/requirements/requirements_collections.yml similarity index 57% rename from .github/workflows/requirements/requirements_ansible.yml rename to .github/workflows/requirements/requirements_collections.yml index 9fef21cf..a19037a6 100644 --- a/.github/workflows/requirements/requirements_ansible.yml +++ b/.github/workflows/requirements/requirements_collections.yml @@ -1,8 +1,10 @@ --- collections: - - name: community.general - version: 3.8.0 - name: ansible.posix - version: 1.3.0 - - name: community.docker version: 2.0.0 + - name: community.general + version: 11.0.0 + - name: community.crypto + version: 3.0.0 + - name: community.docker + version: 4.6.1 diff --git a/.github/workflows/requirements/requirements_galaxy.txt b/.github/workflows/requirements/requirements_galaxy.txt index 084ae80b..36e5effd 100644 --- a/.github/workflows/requirements/requirements_galaxy.txt +++ b/.github/workflows/requirements/requirements_galaxy.txt @@ -1 +1,2 @@ -ansible-core==2.11.6 +ansible-core==2.16.14 +jinja2==3.1.6 diff --git a/.github/workflows/requirements/requirements_molecule.txt b/.github/workflows/requirements/requirements_molecule.txt index a0cca878..a27f3527 100644 --- a/.github/workflows/requirements/requirements_molecule.txt +++ b/.github/workflows/requirements/requirements_molecule.txt @@ -1,6 +1,6 @@ -ansible-core==2.11.6 -Jinja2==3.0.2 -ansible-lint==5.2.1 -yamllint==1.26.3 -molecule[docker]==3.5.2 -docker==5.0.3 +ansible-core==2.16.14 +jinja2==3.1.6 +ansible-compat==25.6.0 +molecule==25.6.0 +molecule-plugins[docker]==23.7.0 +docker==7.1.0 diff --git a/.gitignore b/.gitignore index 4e78f821..bcfa7fe1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,27 +1,44 @@ -# Any private crt and keys # -############################ +######################## +# Any crt/keys/license # +######################## *.crt *.key -*~ -\#* +*.jwt !molecule.crt !molecule.key +!rand.key + +########################## +# Backup/temporary files # +########################## +*~ +\#* -# OS Specific # -############### +################## +# MacOS specific # +################## Thumbs.db .DS_Store .vscode +######################## +# Code editor specific # +######################## +.idea +.vscode + +#################### # Ansible specific # #################### .cache *.retry +################### # Python specific # ################### __pycache__ +######## # Logs # ######## *.log diff --git a/.yamllint b/.yamllint deleted file mode 100644 index ff6d5ce9..00000000 --- a/.yamllint +++ /dev/null @@ -1,12 +0,0 @@ ---- -extends: default - -rules: - braces: - max-spaces-inside: 1 - level: error - brackets: - max-spaces-inside: 1 - level: error - comments-indentation: disable - line-length: disable diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d90d830..0dd5a1d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,21 +1,213 @@ # Changelog +## 0.7.2 (Unreleased) + +FEATURES: + +- Add validation tasks to check the Ansible version, the Jinja2 version, and whether the required Ansible collections for this role are installed. +- Bump the Ansible `community.general` collection to `9.2.0`, `community.crypto` collection to `2.21.1` and `community.docker` collection to `3.11.0`. +- Add templating support for the `ngx_mgmt_module`, `ngx_http_gzip_static_module`, and `ngx_stream_map_module` NGINX modules. + +BUG FIXES: + +- Fix the default path for the stream template deployment location. +- Fix incompatibility when using the `listen` directive and setting both the `quic` and `so_keepalive` parameters. +- Correct cleanup error when `nginx_config_cleanup_paths` is not defined. +- Disable check_mode for `jinja2_version` and Ansible collections validation tasks. +- The default PID path has changed as of NGINX 1.27.5 and 1.28.0. +- Properly wrap `http_version` number in quotes in both the template defaults and Molecule tests. +- NGINX `set_real_ip_from` directive template parameter should be a list. +- Fix backup parameter for stream templates. + +TESTS: + +- Add Molecule tests covering common NGINX use cases (web server, reverse proxy), enabling the NGINX stub status metrics, and NGINX Plus API and live metrics dashboard. +- Update the platforms used in the various Molecule scenarios. +- Use the local role name (`ansible-role-nginx-config`) instead of the fully qualified role name (`nginxinc.nginx_config`) in Molecule to ensure tests always work as intended in environments where the role has been already installed beforehand. +- Update RHEL UBI images to UBI 9.4. +- Update Molecule NGINX Plus tests to work with R33 by introducing the new license JWT. + +DOCUMENTATION: + +- Update community docs & required workflows per the latest [NGINX template repository](https://github.com/nginx/template-repository) guidelines. +- Update and tweak the README. In order to make the installation instructions easier, some file names used by the various GitHub Actions workflows have been renamed. + +CI/CD: + +- Bump the minimum version of Ansible supported on Ansible Galaxy to `2.16`. +- Update GitHub Actions to Ubuntu 24.04. +- Switch GitHub Actions from using tags to release hashes. +- Remove platform metadata from the Ansible Galaxy role metadata since platforms are no longer supported in Ansible Galaxy NG. +- Implement OSSF Scorecard. +- Implement Renovate and replace Dependabot. +- Automatically add milestone and project data to Renovate Bot PRs. + +MAINTENANCE: + +- Remove CentOS 7 related artifacts, tests, and metadata since RHEL 7 related distributions are no longer tested nor supported. +- Tweak Release Drafter to work better with conventional commits. + +## 0.7.1 (October 3rd, 2023) + +ENHANCEMENTS: + +- Implement directives for the `http_v3` module. + +BUG FIXES: + +- Add handler to reload NGINX when SSL cert or key is changed. + +CI/CD: + +- Uncomment the `ansible-compat` version from the CI/CD pipeline. +- Implement F5 CLA. + +## 0.7.0 (July 6, 2023) + +BREAKING CHANGES: + +- Two parameters have been removed from the `listen` dictionary: + - `spdy` -> This parameter is no longer supported. + - `http2` -> This parameter has been replaced by the `http2` directive. To enable HTTP2, use the `enable` parameter in the newly implemented `http2` module/dictionary: + + ```yaml + http2: + enable: true + ``` + +ENHANCEMENTS: + +- Initial pass at implementing directives for the `http2` (officially named `http_v2`) module. +- Bump the Ansible `community.general` collection to `7.1.0`, `ansible.posix` collection to `1.5.4`, `community.crypto` collection to `2.14.0`, and `community.docker` collection to `3.4.7`. + +BUG FIXES: + +- The default template now has a proper example value and comment for the `map.mappings` directive. + +CI/CD: + +- Split Ansible Lint into its own GitHub Actions job since Molecule no longer runs linters natively. +- Remove the "stable" part of the `stable_push` Molecule scenario since installing the NGINX stable branch is already tested by the core NGINX Ansible role. +- Replace `molecule[docker]` with `molecule` and `molecule-plugins[docker]`. +- Explicitly set the `ansible-compat` version (commented out for the time being whilst waiting for a new release of Molecule). +- Add pre-releases to Release Drafter. + +## 0.6.0 (January 29, 2023) + +ENHANCEMENTS: + +- Standardize code from dot to array notation to keep in with the standards set by the other roles in the Ansible NGINX core collection. +- Bump the minimum version of Ansible core required to run the role to `2.12` (`2.11` is no longer supported by Ansible). +- Support the `include` directive in the main NGINX context. +- Bump the Ansible `community.general` collection to `6.2.0` and `community.docker` collection to `3.4.0`. + +BUG FIXES: + +- GitHub Actions should now correctly skip \*plus\* scenarios only when the NGINX Plus license secrets are not present. +- The `ignore-tags` GitHub Actions key does not exist. Replace it with the correct key, `tags-ignore`. + +TESTS: + +- Update GitHub Actions to run on Ubuntu 22.04 (and thus support `cgroups` v2). +- Explicitly specify `amd64` as the platform used in NGINX Plus Molecule tests. This will ensure that tests involving NGINX App Protect will work as expected when run on different host architectures (e.g. newer Macbooks with `arm` processors). +- Update the versions of the Ansible NGINX and NGINX App Protect roles used by Molecule. + +## 0.5.2 (October 17, 2022) + +ENHANCEMENTS: + +- Bump the Ansible `community.general` collection to `5.5.0`, `ansible.posix` collection to `1.4.0` and `community.docker` collection to `3.1.0`. +- Add support for the latest NGINX Plus R26 directives: + - `auth_jwt_require` now allows you to optionally set the `error` code you wish to return. + - `health_check` now lets you set a `keepalive_time`. +- Add support for the latest NGINX App Protect DoS directives (`app_protect_dos_arb_fqdn`, `app_protect_dos_api`, and `app_protect_dos_accelerated_mitigation`). + +BUG FIXES: + +Improve the NGINX main config defaults to bring them closer to the standard NGINX defaults on a fresh NGINX install. + +TESTS: + +- Update GitHub Actions to only skip \*plus\* scenarios when the NGINX Plus license secrets are not present (it used to only run the NGINX Plus test scenarios during internal PRs). +- Remove Yamllint (Ansible Lint now incorporates Yamllint). +- Skip Ansible Lint line length rules. Slightly refactor code to incorporate changes added to Ansible Lint 6.7.0. + +## 0.5.1 (April 6, 2022) + +FEATURES: + +Rename all modules to use the fully qualified collection name (FQCN) per Ansible guidelines. + +ENHANCEMENTS: + +- Bump the Ansible `community.general` collection to `4.7.0` and `community.docker` collection to `2.3.0`. +- Add labels to loops in `tasks/config/template-config.yml` to reduce amount of output data. +- Implement `gunzip`, `map`, `mirror`, `realip` and `split_clients` modules into `http` templates. +- Streamline configuring SELinux. +- Update Dependabot to trigger updates at the same time across all NGINX core roles at the same time and to avoid triggering release drafter on GitHub Actions dependency updates. + +BUG FIXES: + +Ansible check mode runs will no longer fail if NGINX has not yet been installed. + +## 0.5.0 (February 17, 2022) + +BREAKING CHANGES: + +- Remove parameters deprecated in release `0.4.0`. To recap, these are `nginx_config_main_upload_*`, `nginx_config_upload_html_*`, and `nginx_config_stream_upload_*`. Use `nginx_config_upload` instead. +- Refactor all the `stream` Jinja2 templates!: + - Each NGINX module is now contained within its own templating file. Macros are then used, in turn, to import each respective module template into a top level template file. + - This avoids confusing and unnecessary code duplication, as well as hard to maintain code. + - You will notice that the overall structure of your NGINX config now follows a very simple dictionary structure where each top level key corresponds to an NGINX module. Top level lists are used when dealing with `servers`: + + ```yaml + core: + root: /usr/share/nginx/html + proxy: + set_header: [] + servers: + - core: {} + proxy: {} + ``` + + - Check [`defaults/main/template.yml`](https://github.com/nginx/ansible-role-nginx-config/blob/main/defaults/main/template.yml) and [`molecule/default/converge.yml`](https://github.com/nginx/ansible-role-nginx-config/blob/main/molecule/default/converge.yml) for examples! + - These changes follow in the footsteps of the `http` Jinja2 refactor introduced in the `0.4.0` release. If you want more information on how to port your `stream` configurations, the release notes/changelog for `0.4.0` are a good place to start. +- Replace `conf_file_name` and `conf_file_location` with `deployment_location` inside `nginx_config_stream_template`. +- Replace `html_file_name` and `html_file_location` with `deployment_location` inside `nginx_config_html_demo_template`. + +FEATURES: + +- Add `backup` variable to template and upload parameters. Set to `false` if you don't want to keep backups of your previous NGINX config files. +- Automatically create a NGINX `client_body_temp_path` directory if your NGINX config uses the directive. + +ENHANCEMENTS: + +Bump the Ansible `community.general` collection to `4.4.0` and `community.docker` collection to `2.1.1`. + +BUG FIXES: + +- Fix a bug when using a single `custom_directives` entry and the http template. +- Fix check mode issue when running with SELinux enabled. Role no longer reports a change in check mode when setting the host to permissive mode. +- Fix typo in the REST API template. +- Fix incorrect REST API and status log variable names in [`defaults/main/template.yml`](https://github.com/nginx/ansible-role-nginx-config/blob/main/defaults/main/template.yml). +- Fix bugged conditional check in the `http/ssl.j2` Jinja2 template. + ## 0.4.2 (October 28, 2021) BUG FIXES: -* Dictionaries are a sequence per Jinja2 contrary to Python's defaults (dictionaries are not a sequence in Python). The template conditionals assumed the latter. -* NAP DoS monitor directive would fail if some variables were commented out. -* NGINX listen `so_keepalive` parameter was not working as intended when setting specific values. -* Make sure all template objects are properly transformed into strings before doing Jinja2 operations. -* Remove unnecessary parentheses. +- Dictionaries are a sequence per Jinja2 contrary to Python's defaults (dictionaries are not a sequence in Python). The template conditionals assumed the latter. +- NAP DoS monitor directive would fail if some variables were commented out. +- NGINX listen `so_keepalive` parameter was not working as intended when setting specific values. +- Make sure all template objects are properly transformed into strings before doing Jinja2 operations. +- Remove unnecessary parentheses. ## 0.4.1 (October 25, 2021) BUG FIXES: -* Fix issue where your `deployment_location` directory would not be properly created due to an outdated variable. -* Remove duplicated brace in `http/auth.j2`. +- Fix issue where your `deployment_location` directory would not be properly created due to an outdated variable. +- Remove duplicated brace in `http/auth.j2`. ## 0.4.0 (October 19, 2021) @@ -25,24 +217,24 @@ Efforts have been made to thoroughly test all these changes and make sure they w DEPRECATION WARNINGS: -The `nginx_config_main_upload_*`, `nginx_config_upload_html_*`, and `nginx_config_stream_upload_*` parameters have been deprecated in favor of a newly introduced parameter, `nginx_config_upload_*` (previously `nginx_config_snippet_upload_*`). The new parameter provides greater flexibility in configuring your upload settings in addition to simplifying the upload Ansible tasks. The deprecated parameters will be removed in the next major release (0.5.0), due December 2021. +The `nginx_config_main_upload_*`, `nginx_config_upload_html_*`, and `nginx_config_stream_upload_*` parameters have been deprecated in favor of a newly introduced parameter, `nginx_config_upload` (previously `nginx_config_snippet_upload_*`). The new parameter provides greater flexibility in configuring your upload settings in addition to simplifying the upload Ansible tasks. The deprecated parameters will be removed in the next major release (0.5.0), due December 2021. BREAKING CHANGES: General updates: -* Rename upload related variables: - * Rename the `nginx_config_snippet_upload_*` parameters to `nginx_config_upload_*` (check `defaults/main/upload.yml` for an example). - * Rename the `nginx_config_html_upload_*` parameters to `nginx_config_upload_html_*`. - * Rename the `nginx_config_ssl_upload_*` parameters to `nginx_config_upload_ssl_*`. -* Tweak the `nginx_config_html_upload` and `nginx_config_ssl_upload` parameters to use a list instead of a single `src` and `dest` value (check `defaults/main/upload.yml` for an example). +- Rename upload related variables: + - Rename the `nginx_config_snippet_upload_*` parameters to `nginx_config_upload_*` (check `defaults/main/upload.yml` for an example). + - Rename the `nginx_config_html_upload_*` parameters to `nginx_config_upload_html_*`. + - Rename the `nginx_config_ssl_upload_*` parameters to `nginx_config_upload_ssl_*`. +- Tweak the `nginx_config_html_upload` and `nginx_config_ssl_upload` parameters to use a list instead of a single `src` and `dest` value (check `defaults/main/upload.yml` for an example). Template engine updates: -* Refactor all the Jinja2 templates!: - * Each NGINX module is now contained within its own templating file. Macros are then used, in turn, to import each respective module template into a top level template file. - * This avoids confusing and unnecessary code duplication, as well as hard to maintain code. - * You will notice that the overall structure of your NGINX config now follows a very simple dictionary structure where each top level key corresponds to an NGINX module. Top level lists are used when dealing with `servers` and `locations`: +- Refactor all the `http` Jinja2 templates!: + - Each NGINX module is now contained within its own templating file. Macros are then used, in turn, to import each respective module template into a top level template file. + - This avoids confusing and unnecessary code duplication, as well as hard to maintain code. + - You will notice that the overall structure of your NGINX config now follows a very simple dictionary structure where each top level key corresponds to an NGINX module. Top level lists are used when dealing with `servers` and `locations`: ```yaml core: @@ -57,35 +249,35 @@ Template engine updates: proxy: {} ``` - * Check [`defaults/main/template.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/defaults/main/template.yml) and [`molecule/default/converge.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/molecule/default/converge.yml) for examples! -* Refactor the base config templates to simplify the creation of templates as well as development and maintenance moving forward: - * Modify `servers`, `servers.listen`, `server.locations`, `upstream` and `upstream.servers` from nested dictionaries in the `http` and `stream` configuration templates to lists. - * Remove/merge the `web_server` and `reverse_proxy` nested dictionary keys from the HTTP templates. These often lead to confusing and unnecessary code duplication and hard to maintain code. To update your templates, remove both keys and adjust your spacing accordingly. - * Replaced `conf_file_name` and `conf_file_location` with a single variable, `deployment_location`. - * All config related parameters now live under the `config` key in both the core/main and HTTP templates. - * Modify the `nginx_config_html_demo_template` variable from a nested dictionary to a list. -* Refactor the `nginx_config_main_template` to now include all the respective `core` and `events` directives. The following variables have changed: - * `http_enable` no longer exists, neither does `http_settings`. You can still use `http.include` to include files within the `http` context. - * `stream_enable` no longer exists, neither does `stream_settings`. You can still use `stream.include` to include files within the `stream` context. -* Refactor the `upstream` HTTP config template into its own separate file. All the `upstream` module directives are now included. The following variables have changed: - * `port` is no longer supported. Instead, include the port as part of your `address`. - * `lb_method` is no longer supported. Instead, you will have to specifically set the method you want to use. - * `zone_name` and `zone_size` have been modified into a dictionary. - * `sticky_cookie` is no longer supported as is. You will now have to configure the respective `sticky_cookie` values. - * The `health_check` parameter within the `server` dictionary is no longer supported. Instead, manually set `max_fails` and `fail_timeout`. -* Refactor various individual variables into the `core` HTTP config template. All the `core` module directives are now included. The following variables are now included in the `core` dictionary: - * `alias`, `client_max_body_size`, `error_log`, `error_page`, `include`, `index`, `keepalive_timeout`, `listen`, `root`, `send_file`, `server_name`, `server_names_hash_bucket_size`, `server_names_hash_max_size`, `server_tokens`, `tcp_nodelay`, `tcp_nopush`, `try_files` - * `listen.port` is now `listen.address`, and `listen.opts` no longer exists (there are now individual keys for each `listen` parameter). -* Refactor the `ssl` HTTP config template into its own separate file. All the `ssl` module directives are now included. Almost all variables have changed: - * All `ssl` variables still live within an `ssl` dictionary, but the names have changed to reflect the official NGINX directive names. - * `ssl` configs are now supported within both the `http` and `server` contexts. -* Refactor both the `app_protect_waf` and `app_protect_dos` modules into a single file: - * The `app_protect` dictionary now has the `app_protect_waf` key. - * `app_protect_global` directives are now found inside the `app_protect_waf` dictionary too. -* Refactor the `proxy` HTTP config template into its own separate file. All the `proxy` module directives are now included. All variables have changed: - * All `proxy_*` related variables now live under the `proxy` dictionary key. You can specify the `proxy` dictionary key inside the `http`, `server`, and `location` contexts. - * Removed the `nginx_config_main_template.http_settings.cache` dictionary variable. Use `nginx_config_http_template.*.proxy.cache_path` instead. - * Removed the `location.websocket` variable. Use `location.proxy.set_header` instead: + - Check [`defaults/main/template.yml`](https://github.com/nginx/ansible-role-nginx-config/blob/main/defaults/main/template.yml) and [`molecule/default/converge.yml`](https://github.com/nginx/ansible-role-nginx-config/blob/main/molecule/default/converge.yml) for examples! +- Refactor the base config templates to simplify the creation of templates as well as development and maintenance moving forward: + - Modify `servers`, `servers.listen`, `server.locations`, `upstream` and `upstream.servers` from nested dictionaries in the `http` and `stream` configuration templates to lists. + - Remove/merge the `web_server` and `reverse_proxy` nested dictionary keys from the HTTP templates. These often lead to confusing and unnecessary code duplication and hard to maintain code. To update your templates, remove both keys and adjust your spacing accordingly. + - Replaced `conf_file_name` and `conf_file_location` with a single variable, `deployment_location`. + - All config related parameters now live under the `config` key in both the core/main and HTTP templates. + - Modify the `nginx_config_html_demo_template` variable from a nested dictionary to a list. +- Refactor the `nginx_config_main_template` to now include all the respective `core` and `events` directives. The following variables have changed: + - `http_enable` no longer exists, neither does `http_settings`. You can still use `http.include` to include files within the `http` context. + - `stream_enable` no longer exists, neither does `stream_settings`. You can still use `stream.include` to include files within the `stream` context. +- Refactor the `upstream` HTTP config template into its own separate file. All the `upstream` module directives are now included. The following variables have changed: + - `port` is no longer supported. Instead, include the port as part of your `address`. + - `lb_method` is no longer supported. Instead, you will have to specifically set the method you want to use. + - `zone_name` and `zone_size` have been modified into a dictionary. + - `sticky_cookie` is no longer supported as is. You will now have to configure the respective `sticky_cookie` values. + - The `health_check` parameter within the `server` dictionary is no longer supported. Instead, manually set `max_fails` and `fail_timeout`. +- Refactor various individual variables into the `core` HTTP config template. All the `core` module directives are now included. The following variables are now included in the `core` dictionary: + - `alias`, `client_max_body_size`, `error_log`, `error_page`, `include`, `index`, `keepalive_timeout`, `listen`, `root`, `send_file`, `server_name`, `server_names_hash_bucket_size`, `server_names_hash_max_size`, `server_tokens`, `tcp_nodelay`, `tcp_nopush`, `try_files` + - `listen.port` is now `listen.address`, and `listen.opts` no longer exists (there are now individual keys for each `listen` parameter). +- Refactor the `ssl` HTTP config template into its own separate file. All the `ssl` module directives are now included. Almost all variables have changed: + - All `ssl` variables still live within an `ssl` dictionary, but the names have changed to reflect the official NGINX directive names. + - `ssl` configs are now supported within both the `http` and `server` contexts. +- Refactor both the `app_protect_waf` and `app_protect_dos` modules into a single file: + - The `app_protect` dictionary now has the `app_protect_waf` key. + - `app_protect_global` directives are now found inside the `app_protect_waf` dictionary too. +- Refactor the `proxy` HTTP config template into its own separate file. All the `proxy` module directives are now included. All variables have changed: + - All `proxy_*` related variables now live under the `proxy` dictionary key. You can specify the `proxy` dictionary key inside the `http`, `server`, and `location` contexts. + - Removed the `nginx_config_main_template.http_settings.cache` dictionary variable. Use `nginx_config_http_template.*.proxy.cache_path` instead. + - Removed the `location.websocket` variable. Use `location.proxy.set_header` instead: ```yaml proxy: @@ -96,27 +288,27 @@ Template engine updates: value: Upgrade ``` -* Combine the `grpc_global` directives with the `grpc` directives. -* Refactor the `auth` HTTP config template into its own separate `auth` modules file. All the various `auth` related module directives including all `auth_jwt` directives are now available. All variables have changed: - * All the various `auth` variables now live within their respective `auth` dictionaries. - * `auth` configs are now supported within the `http`, `server`, and `location` contexts. -* Refactor the `autoindex` HTTP config template into its own separate file `modules` file and added missing `autoindex` module directives. All variables have changed: - * The `autoindex` directives now live within the `autoindex` dictionary. - * The `autoindex` dictionary now lives in the HTTP template config instead of the Main template config. -* Refactor the `add_headers` dictionary into a `headers` dictionary that now includes all the `headers` HTTP config directives: - * The `add_headers` directive now lives within the `headers` dictionary. -* Refactor the `keyval` directives into its own template config that now includes all the `keyval` HTTP module directives: - * Both `keyval` directives now live within the `keyval` dictionary. - * The `keyval` dictionary now lives in the HTTP template config instead of the Main template config. -* Refactor `server.health_check_plus` into its own dictionary that now includes all the `health_check` module directives (check [`defaults/main/template.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/defaults/main/template.yml) for examples). -* Refactor the `limit_req` directive into its own dictionary: - * The `limit_req` directives now live within the `limit_req` dictionary. - * The `limit_req` dictionary now lives in the HTTP template config instead of the Main template config. -* Refactor the `access_log` and `log_format` directives into a `log` dictionary that now includes all the `log` module directives: - * An `access` and `format` directive now lives within the `log` dictionary. - * The `log` dictionary HTTP context now lives in the HTTP template config instead of the Main template config. -* Refactor the `return` and `rewrite` directives into their own dictionary that now includes all the `rewrite` HTTP module directives: - * The `rewrites` directive has transitioned from a list of one liners +- Combine the `grpc_global` directives with the `grpc` directives. +- Refactor the `auth` HTTP config template into its own separate `auth` modules file. All the various `auth` related module directives including all `auth_jwt` directives are now available. All variables have changed: + - All the various `auth` variables now live within their respective `auth` dictionaries. + - `auth` configs are now supported within the `http`, `server`, and `location` contexts. +- Refactor the `autoindex` HTTP config template into its own separate file `modules` file and added missing `autoindex` module directives. All variables have changed: + - The `autoindex` directives now live within the `autoindex` dictionary. + - The `autoindex` dictionary now lives in the HTTP template config instead of the Main template config. +- Refactor the `add_headers` dictionary into a `headers` dictionary that now includes all the `headers` HTTP config directives: + - The `add_headers` directive now lives within the `headers` dictionary. +- Refactor the `keyval` directives into its own template config that now includes all the `keyval` HTTP module directives: + - Both `keyval` directives now live within the `keyval` dictionary. + - The `keyval` dictionary now lives in the HTTP template config instead of the Main template config. +- Refactor `server.health_check_plus` into its own dictionary that now includes all the `health_check` module directives (check [`defaults/main/template.yml`](https://github.com/nginx/ansible-role-nginx-config/blob/main/defaults/main/template.yml) for examples). +- Refactor the `limit_req` directive into its own dictionary: + - The `limit_req` directives now live within the `limit_req` dictionary. + - The `limit_req` dictionary now lives in the HTTP template config instead of the Main template config. +- Refactor the `access_log` and `log_format` directives into a `log` dictionary that now includes all the `log` module directives: + - An `access` and `format` directive now lives within the `log` dictionary. + - The `log` dictionary HTTP context now lives in the HTTP template config instead of the Main template config. +- Refactor the `return` and `rewrite` directives into their own dictionary that now includes all the `rewrite` HTTP module directives: + - The `rewrites` directive has transitioned from a list of one liners ```yaml rewrites: @@ -131,7 +323,7 @@ Template engine updates: replacement: $1$2 ``` - * The `return` directive has transitioned from a slightly complex dictionary structure (wherein the `location` variable didn't necessarily have any effect) + - The `return` directive has transitioned from a slightly complex dictionary structure (wherein the `location` variable didn't necessarily have any effect) ```yaml returns: @@ -149,8 +341,8 @@ Template engine updates: text: nginx ``` -* Refactor the `sub_filter` directives into their own `sub_filter` dictionary that includes all the `sub_filter` HTTP module directives: - * The only major difference is that one liners under the `sub_filters` dictionary key have changed from +- Refactor the `sub_filter` directives into their own `sub_filter` dictionary that includes all the `sub_filter` HTTP module directives: + - The only major difference is that one liners under the `sub_filters` dictionary key have changed from ```yaml sub_filters: @@ -165,7 +357,7 @@ Template engine updates: replacement: $hostname ``` - * Removed the `server.http_demo_conf` dictionary. Use `server.sub_filters` instead: + - Removed the `server.http_demo_conf` dictionary. Use `server.sub_filters` instead: ```yaml sub_filter: @@ -192,16 +384,16 @@ Template engine updates: replacement: $http_x_forwarded_for ``` - * The `sub_filter` dictionary HTTP context now lives in the HTTP template config instead of the Main template config. -* Rename some NGINX template config parameters to align with NGINX directive names: - * Rename `html_file_location` to `root`. - * Rename `html_file_name` to `index`. -* NGINX App Protect 3.2 supports multiple log destinations per scope. Changing the `security_log` variable from a dictionary to a list of objects in order to support this. -* NGINX App Protect 3.5 supports a new timeout directive which allows the user to configure the period of time between reconnect retries of the module to the web application firewall (WAF) engine. Added this as a supported directive. + - The `sub_filter` dictionary HTTP context now lives in the HTTP template config instead of the Main template config. +- Rename some NGINX template config parameters to align with NGINX directive names: + - Rename `html_file_location` to `root`. + - Rename `html_file_name` to `index`. +- NGINX App Protect 3.2 supports multiple log destinations per scope. Changing the `security_log` variable from a dictionary to a list of objects in order to support this. +- NGINX App Protect 3.5 supports a new timeout directive which allows the user to configure the period of time between reconnect retries of the module to the web application firewall (WAF) engine. Added this as a supported directive. FEATURES: -* Replace Ansible community distribution with Ansible base and add the necessary extra collections as a dependency requirement. For reference, these are: +- Replace Ansible community distribution with Ansible base and add the necessary extra collections as a dependency requirement. For reference, these are: ```yaml --- @@ -214,102 +406,102 @@ FEATURES: version: 1.10.0 ``` -* Explicitly list Jinja2 `2.11.3` as a requirement, as well as detail the minimum supported version (`2.11.x`). -* Implement Release Drafter. -* Add support for configuring NGINX App Protect DoS (Denial of Service) module and directives. -* Add support for configuring the NGINX Rest API module and the NGINX stub status module. +- Explicitly list Jinja2 `2.11.3` as a requirement, as well as detail the minimum supported version (`2.11.x`). +- Implement Release Drafter. +- Add support for configuring NGINX App Protect DoS (Denial of Service) module and directives. +- Add support for configuring the NGINX Rest API module and the NGINX stub status module. ENHANCEMENTS: -* Move the `gzip` HTTP config template into the `modules` file. It's a small module and did not warrant being in its own individual file. -* Update Ansible Lint to `5.1.3`, Molecule to `3.4.0`, yamllint to `1.26.3` and Docker Python SDK to `5.0.2`. -* Consolidate Molecule testing scenarios to address changes introduced in Ansible Lint `5.*`. -* Specify GitHub actions Ubuntu release. -* Minor GitHub template tweaks, including the creation of a SECURITY doc. -* Replace Molecule tests using Debian stretch with Debian buster (stretch has reached its EoL), and update list of supported platforms. -* Replace Ansible base with Ansible core. Ansible core will be the "core" Ansible release moving forward from Ansible `2.11`. -* Update GitHub actions to add a workflow dispatch option. -* Update GitHub actions `if` conditionals to use the `contains` function instead of checking for exact names. -* Remove Debian Buster from the `plus` Molecule scenario since it often fails in the GitHub Actions CI/CD pipeline. -* Replace "yes"/"no" boolean values with "true"/"false" to comply with YAML spec `1.2`. -* Ensure the default values for the `nginx.conf` template match the default values found on a fresh NGINX installation. -* Change Dependabot frequency from daily to weekly. -* Minor touch-up of GitHub actions workflows. +- Move the `gzip` HTTP config template into the `modules` file. It's a small module and did not warrant being in its own individual file. +- Update Ansible Lint to `5.1.3`, Molecule to `3.4.0`, Yamllint to `1.26.3` and Docker Python SDK to `5.0.2`. +- Consolidate Molecule testing scenarios to address changes introduced in Ansible Lint `5.*`. +- Specify GitHub Actions Ubuntu release. +- Minor GitHub template tweaks, including the creation of a SECURITY doc. +- Replace Molecule tests using Debian stretch with Debian buster (stretch has reached its EoL), and update list of supported platforms. +- Replace Ansible base with Ansible core. Ansible core will be the "core" Ansible release moving forward from Ansible `2.11`. +- Update GitHub Actions to add a workflow dispatch option. +- Update GitHub Actions `if` conditionals to use the `contains` function instead of checking for exact names. +- Remove Debian Buster from the `plus` Molecule scenario since it often fails in the GitHub Actions CI/CD pipeline. +- Replace "yes"/"no" boolean values with "true"/"false" to comply with YAML spec `1.2`. +- Ensure the default values for the `nginx.conf` template match the default values found on a fresh NGINX installation. +- Change Dependabot frequency from daily to weekly. +- Minor touch-up of GitHub Actions workflows. BUG FIXES: -* Add `state` parameter to package module in Molecule verification tests. -* In NGINX App Protect environments on SELinux enforced systems, the `nginx -t` handler fails when run from a directory that the NGINX process' user does not have access to. -* Fix missing GRPC boolean check in GRPC template. -* Fix `nginx_config_cleanup_paths` not working as intended. -* Fix issue with the `app_protect.j2` template that was causing the default values for `nginx.conf` to fail. +- Add `state` parameter to package module in Molecule verification tests. +- In NGINX App Protect environments on SELinux enforced systems, the `nginx -t` handler fails when run from a directory that the NGINX process' user does not have access to. +- Fix missing GRPC boolean check in GRPC template. +- Fix `nginx_config_cleanup_paths` not working as intended. +- Fix issue with the `app_protect.j2` template that was causing the default values for `nginx.conf` to fail. ## 0.3.3 (January 28, 2021) FEATURES: -* Add support for configuration snippets (use the `nginx_config_snippet_upload_*` parameters to configure it). -* Add support for Dependabot. +- Add support for configuration snippets (use the `nginx_config_snippet_upload_*` parameters to configure it). +- Add support for Dependabot. ENHANCEMENTS: -* Add support for NGINX GRPC directives. -* Add support for NGINX GZIP directives. -* Add support for upstream server `backup` parameter in http and stream template. -* Only run GitHub actions Galaxy CI/CD workflow when a new release is published. -* Update list of supported platforms. -* Update Ansible base to `2.10.5` and Ansible to `2.10.6`. +- Add support for NGINX GRPC directives. +- Add support for NGINX GZIP directives. +- Add support for upstream server `backup` parameter in http and stream template. +- Only run GitHub Actions Galaxy CI/CD workflow when a new release is published. +- Update list of supported platforms. +- Update Ansible base to `2.10.5` and Ansible to `2.10.6`. BUG FIXES: -* Address inconsistent types within Jinja templates. -* Add Jinja2 checks to all config template parameters to ensure that they are only included when appropriately defined. -* Fix edge case where `proxy_pass` is still required when using `grpc_pass`. +- Address inconsistent types within Jinja templates. +- Add Jinja2 checks to all config template parameters to ensure that they are only included when appropriately defined. +- Fix edge case where `proxy_pass` is still required when using `grpc_pass`. ## 0.3.2 (January 11, 2021) ENHANCEMENTS: -* The GitHub actions Molecule CI/CD workflow is no longer run on a new release (this is not necessary since it already runs on every push). -* The GitHub actions Molecule CI/CD workflow should now correctly avoid running 'Plus' related tests on external PRs. -* The `cleanup-config.yml` playbook has been slightly refactored and simplified. -* Update Ansible base to `2.10.4`, Ansible to `2.10.5`, Molecule to `3.2.2` and Docker Python SDK to `4.4.1`. -* Update copyright notice. +- The GitHub Actions Molecule CI/CD workflow is no longer run on a new release (this is not necessary since it already runs on every push). +- The GitHub Actions Molecule CI/CD workflow should now correctly avoid running 'Plus' related tests on external PRs. +- The `cleanup-config.yml` playbook has been slightly refactored and simplified. +- Update Ansible base to `2.10.4`, Ansible to `2.10.5`, Molecule to `3.2.2` and Docker Python SDK to `4.4.1`. +- Update copyright notice. ## 0.3.1 (December 22, 2020) ENHANCEMENTS: -* Update Molecule to `3.2.1` and Docker Python SDK to `4.4.0`. -* Replace TravisCI with GitHub actions. +- Update Molecule to `3.2.1` and Docker Python SDK to `4.4.0`. +- Replace TravisCI with GitHub Actions. BUG FIXES: -* Switch to explicit boolean values in `sub_filter` defaults for `last_modified` and `since` in `nginx_config_main_template`. `"on"` and `"off"` values are treated as true instead of true/false when surrounded by double quotes. By always resorting to true/false we avoid unaccounted edge cases. -* Fix issue whereas SELinux state would not be correctly set back to `enforcing` when `nginx_config_selinux: true`. +- Switch to explicit boolean values in `sub_filter` defaults for `last_modified` and `since` in `nginx_config_main_template`. `"on"` and `"off"` values are treated as true instead of true/false when surrounded by double quotes. By always resorting to true/false we avoid unaccounted edge cases. +- Fix issue whereas SELinux state would not be correctly set back to `enforcing` when `nginx_config_selinux: true`. ## 0.3.0 (November 17, 2020) BREAKING CHANGES: -* The default port of the status and REST API config is now `8080` and matches the CI Molecule test which already uses it. You can set `nginx_config_status_port` to another value if desired. -* The allow/deny directives for `nginx_config_status` and `nginx_config_rest_api` now take a list instead of a single value. -* The default `nginx_config_*_log` values have changed to `nginx_config_*_access_log` and no longer have a default value of `off`. Set the respective variables to `false` to preserve the previous behaviour. +- The default port of the status and REST API config is now `8080` and matches the CI Molecule test which already uses it. You can set `nginx_config_status_port` to another value if desired. +- The allow/deny directives for `nginx_config_status` and `nginx_config_rest_api` now take a list instead of a single value. +- The default `nginx_config_*_log` values have changed to `nginx_config_*_access_log` and no longer have a default value of `off`. Set the respective variables to `false` to preserve the previous behaviour. ENHANCEMENTS: -* Add survey to README. -* Improve README structure and use tables where relevant. -* Update Ansible (now Ansible base) to `2.10.3`, Ansible (now Ansible Community Distribution) to `2.10.3`, Ansible Lint to `4.3.7`, Molecule to `3.1.5`, and yamllint to `1.25.0`. -* Improve templating of stub status and REST API config. +- Add survey to README. +- Improve README structure and use tables where relevant. +- Update Ansible (now Ansible base) to `2.10.3`, Ansible (now Ansible Community Distribution) to `2.10.3`, Ansible Lint to `4.3.7`, Molecule to `3.1.5`, and Yamllint to `1.25.0`. +- Improve templating of stub status and REST API config. BUG FIXES: -* Prevent TravisCI from trying to build (and failing) NGINX Plus images on external PRs. -* Fix naming for SELinux facts dictionary. -* Correctly import `app_protect` global directives in template. -* Role now runs correctly when using Ansible's check mode. -* Fix issue with access log in stub status and REST API config template not being properly parsed. +- Prevent TravisCI from trying to build (and failing) NGINX Plus images on external PRs. +- Fix naming for SELinux facts dictionary. +- Correctly import `app_protect` global directives in template. +- Role now runs correctly when using Ansible's check mode. +- Fix issue with access log in stub status and REST API config template not being properly parsed. ## 0.2.0 (September 24, 2020) @@ -317,28 +509,28 @@ BREAKING CHANGES: The process to configure modules has changed. Instead of manually setting the modules you want to install to `true` or `false`, you will now have to use either: -* A newly introduced top level list variable, `nginx_config_modules`. -* A newly introduced list variable within your main NGINX config template, `nginx_config_main_template.modules`. +- A newly introduced top level list variable, `nginx_config_modules`. +- A newly introduced list variable within your main NGINX config template, `nginx_config_main_template.modules`. Make sure you only use one variable or the other, since they will overwrite each other. This change will simplify adding future supported modules to this role, and allows you to include any external modules you may wish in your NGINX config. FEATURES: -* Support for all NGINX App Protect directives has been added. You can find details on the supported directives on `defaults/main/template.yml`. This is the first module to be included using J2 macros. Expect to slowly see a refactor of various modules to use macros where possible. -* Add Alpine `3.12` to the list of supported platforms. -* Remove Alpine `3.8` from the list of supported platforms . -* Add NGINX Plus tests to TravisCI +- Support for all NGINX App Protect directives has been added. You can find details on the supported directives on `defaults/main/template.yml`. This is the first module to be included using J2 macros. Expect to slowly see a refactor of various modules to use macros where possible. +- Add Alpine `3.12` to the list of supported platforms. +- Remove Alpine `3.8` from the list of supported platforms . +- Add NGINX Plus tests to TravisCI ENHANCEMENTS: -* Added handlers to check for NGINX syntax validity and fail if any errors are detected. -* Switch to using `ansible_facts` wherever possible. -* Improved tasks naming conventions. -* Update Ansible to `2.9.13` and Ansible Lint to `4.3.5`. -* Explicitly defined `mode` in relevant tasks. -* Improve configuration templating capabilities: - * Allow setting `access_log`/`access_log_location` to `off`. - * Add IP restriction for web servers +- Added handlers to check for NGINX syntax validity and fail if any errors are detected. +- Switch to using `ansible_facts` wherever possible. +- Improved tasks naming conventions. +- Update Ansible to `2.9.13` and Ansible Lint to `4.3.5`. +- Explicitly defined `mode` in relevant tasks. +- Improve configuration templating capabilities: + - Allow setting `access_log`/`access_log_location` to `off`. + - Add IP restriction for web servers BUG FIXES: @@ -346,4 +538,4 @@ An empty `nginx_config_cleanup_files` will no longer cause `nginx_config_cleanup ## 0.1.0 (August 19, 2020) -Initial release of the NGINX Config role. Contains all NGINX Config related features previously available on the [NGINX Ansible role](https://github.com/nginxinc/ansible-role-nginx). +Initial release of the NGINX Config role. Contains all NGINX Config related features previously available on the [NGINX Ansible role](https://github.com/nginx/ansible-role-nginx). diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 1cbfc7ab..e18d3706 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -2,73 +2,77 @@ ## Our Pledge -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards -Examples of behavior that contributes to creating a positive environment -include: +Examples of behavior that contributes to a positive environment for our community include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Demonstrating empathy and kindness toward other people. +- Being respectful of differing opinions, viewpoints, and experiences. +- Giving and gracefully accepting constructive feedback. +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience. +- Focusing on what is best not just for us as individuals, but for the overall community. -Examples of unacceptable behavior by participants include: +Examples of unacceptable behavior include: -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting +- The use of sexualized language or imagery, and sexual attention or advances of any kind. +- Trolling, insulting or derogatory comments, and personal or political attacks. +- Public or private harassment. +- Publishing others' private information, such as a physical or email address, without their explicit permission. +- Other conduct which could reasonably be considered inappropriate in a professional setting. -## Our Responsibilities +## Enforcement Responsibilities -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. +Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. +Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official email address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at nginx@nginx.org. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at . All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. + +### 2. Warning -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. +**Community Impact**: A violation through a single incident or series of actions. + +**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, -available at +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1, available at . + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/inclusion). -For answers to common questions about this code of conduct, see - +For answers to common questions about this code of conduct, see the FAQ at . Translations are available at . diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b34507c7..e526b1ae 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,71 +4,65 @@ The following is a set of guidelines for contributing to the NGINX config Ansibl #### Table Of Contents -[Ask a Question](#ask-a-question) - [Getting Started](#getting-started) - [Contributing](#contributing) - [Code Guidelines](#code-guidelines) - -* [Git Guidelines](#git-guidelines) -* [Ansible Guidelines](#ansible-guidelines) - -[Code of Conduct](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/CODE_OF_CONDUCT.md) - -## Ask a Question - -Don't know how something works? Curious if the role can achieve your desired functionality? Please open an Issue on GitHub with the label `question`. +[Code of Conduct](/CODE_OF_CONDUCT.md) ## Getting Started -Follow our [Installation Guide](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/README.md#Installation) to install Ansible and Molecule and get ready to use the NGINX config Ansible role. +Follow the role's [installation guide](/README.md#Installation) to install Ansible, Ansible Lint, and Molecule and get ready to develop and test the NGINX config Ansible role. -### Project Structure +### Project Overview & Structure -* The NGINX config Ansible role is written in `yaml` and supports NGINX Open Source and NGINX Plus. -* The project follows the standard [Ansible role directory structure](https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html): - * The main code is found in [`tasks/`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/tasks/). - * Variables can be found in [`defaults/main/`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/defaults/main/). - * "Constant" variables can be found in [`vars/main.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/vars/main.yml). - * Configuration templates for NGINX can be found in [`templates/`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/templates/). - * [Molecule](https://molecule.readthedocs.io/) tests can be found in [`molecule/`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/molecule/). - * CI/CD is done via GitHub actions using the workflow files found in [`.github/workflows/`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/.github/workflows/). +- The NGINX config Ansible role is written in [`yaml`](https://yaml.org) and supports NGINX Open Source and NGINX Plus. +- The project follows the standard [Ansible role directory structure](https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html): + - The main "codebase" is found in the [`tasks/`](/tasks/) directory. + - Variables can be found in [`defaults/main/`](/defaults/main/). The filenames in this directory highlight which variables are contained in each file. + - "Constant/hardcoded" variables can be found in [`vars/main.yml`](/vars/main.yml). Use this file if you want to create a variable that should not be tweaked by users except in exceptional circumstances. + - Configuration templates for NGINX can be found in the [`templates/`](/templates/) directory. + - [Molecule](https://molecule.readthedocs.io/) tests can be found in the [`molecule/`](/molecule/) directory. Tweak or add new scenarios as necessary. Read the [Molecule docs](https://molecule.readthedocs.io/) and check out the [`default`](/molecule/default/) Molecule scenario to get an idea of how Molecule works in action. + - CI/CD is done via GitHub Actions using the workflow files found in the [`.github/workflows/`](/.github/workflows/) directory. If you create a new Molecule scenario, you will also need to update the [Molecule workflow](/.github/workflows/molecule.yml). ## Contributing ### Report a Bug -To report a bug, open an issue on GitHub with the label `bug` using the available bug report issue template. Please ensure the issue has not already been reported. +To report a bug, open an issue on GitHub with the label `bug` using the available [bug report issue form](/.github/ISSUE_TEMPLATE/bug_report.yml). Please ensure the bug has not already been reported. **If the bug is a potential security vulnerability, please report it using our [security policy](/SECURITY.md).** + +### Suggest a Feature or Enhancement + +To suggest a feature or enhancement, please create an issue on GitHub with the label `enhancement` using the available [feature request issue form](/.github/ISSUE_TEMPLATE/feature_request.yml). Please ensure the feature or enhancement has not already been suggested. + +### Open a Pull Request (PR) -### Suggest an Enhancement +- Fork the repo, create a branch, implement your changes, add any relevant tests, and submit a PR when your changes are **tested** (using Molecule) and ready for review. +- Fill in the [PR template](/.github/pull_request_template.md). -To suggest an enhancement, please create an issue on GitHub with the label `enhancement` using the available feature issue template. +> [!NOTE] +> If you'd like to implement a new feature, please consider creating a [feature request issue](/.github/ISSUE_TEMPLATE/feature_request.yml) first to start a discussion about the feature. -### Open a Pull Request +#### F5 Contributor License Agreement (CLA) -* Fork the repo, create a branch, implement your changes, add any relevant Molecule tests, submit a PR when your changes are **tested** (using Molecule) and ready for review. -* Fill in [our pull request template](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/.github/pull_request_template.md). +F5 requires all contributors to agree to the terms of the F5 CLA (available [here](https://github.com/f5/f5-cla/blob/main/docs/f5_cla.md)) before any of their changes can be incorporated into an F5 Open Source repository (even contributions to the F5 CLA itself!). -Note: if you'd like to implement a new feature, please consider creating a feature request issue first to start a discussion about the feature. +If you have not yet agreed to the F5 CLA terms and submit a PR to this repository, a bot will prompt you to view and agree to the F5 CLA. You will have to agree to the F5 CLA terms through a comment in the PR before any of your changes can be merged. Your agreement signature will be safely stored by F5 and no longer be required in future PRs. ## Code Guidelines ### Ansible Guidelines -* Run `molecule lint` over your code to automatically resolve a lot of `yaml` and Ansible style issues. -* Run `molecule test` on your code before you submit a PR to catch any potential issues. If you are testing a specific molecule scenario, run `molecule test -s `. If you are testing the NGINX Plus scenario (`plus`), you will need to procure an NGINX Plus license (check out the [NGINX Plus developer license FAQ](https://www.nginx.com/developer-license-faqs/) to find out how to request one). -* Follow these guides on some good practices for Ansible: - * - * +- Run `ansible lint` over your code to automatically resolve a lot of `yaml`, `jinja2`, and Ansible style issues. +- Run `molecule test` on your code before you submit a PR to catch any potential issues. If you are testing a specific Molecule scenario, run `molecule test -s `. If you are testing any of the NGINX Plus scenarios (`...-plus`), you will need to procure an NGINX Plus license (check out the [F5 Trials](https://www.f5.com/trials) site to find out how to request one). +- Check out [Ansible's official tips and tricks](https://docs.ansible.com/ansible/latest/tips_tricks/ansible_tips_tricks.html) site for more best practices. ### Git Guidelines -* Keep a clean, concise and meaningful git commit history on your branch (within reason), rebasing locally and squashing before submitting a PR. -* Follow the guidelines of writing a good commit message as described here and summarised in the next few points: - * In the subject line, use the present tense ("Add feature" not "Added feature"). - * In the subject line, use the imperative mood ("Move cursor to..." not "Moves cursor to..."). - * Limit the subject line to 72 characters or less. - * Reference issues and pull requests liberally after the subject line. - * Add more detailed description in the body of the git message (`git commit -a` to give you more space and time in your text editor to write a good message instead of `git commit -am`). +- Keep a clean, concise and meaningful git commit history on your branch (within reason), rebasing locally and squashing before submitting a PR. +- If possible and/or relevant, use the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format when writing a commit message, so that changelogs can be automatically generated. +- Follow the guidelines of writing a good commit message as described here and summarized in the next few points: + - In the subject line, use the present tense ("Add feature" not "Added feature"). + - In the subject line, use the imperative mood ("Move cursor to..." not "Moves cursor to..."). + - Limit the subject line to 72 characters or less. + - Reference issues and pull requests liberally after the subject line. + - Add more detailed description in the body of the git message (`git commit -a` to give you more space and time in your text editor to write a good message instead of `git commit -am`). diff --git a/README.md b/README.md index ce093cd4..f21ecd8f 100644 --- a/README.md +++ b/README.md @@ -1,173 +1,202 @@ [![Ansible Galaxy](https://img.shields.io/badge/galaxy-nginxinc.nginx__config-5bbdbf.svg)](https://galaxy.ansible.com/nginxinc/nginx_config) -[![Molecule CI/CD](https://github.com/nginxinc/ansible-role-nginx-config/workflows/Molecule%20CI/CD/badge.svg)](https://github.com/nginxinc/ansible-role-nginx-config/actions) +[![Molecule CI/CD](https://github.com/nginx/ansible-role-nginx-config/actions/workflows/molecule.yml/badge.svg)](https://github.com/nginx/ansible-role-nginx-config/actions/workflows/molecule.yml) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/nginx/ansible-role-nginx-config/badge)](https://securityscorecards.dev/viewer/?uri=github.com/nginx/ansible-role-nginx-config) +[![Project Status: Active โ€“ The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) +[![Community Support](https://badgen.net/badge/support/community/cyan?icon=awesome)](/SUPPORT.md) +[![Community Forum](https://img.shields.io/badge/community-forum-009639?logo=discourse&link=https%3A%2F%2Fcommunity.nginx.org)](https://community.nginx.org) [![License](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](/CODE_OF_CONDUCT.md) -# ๐Ÿ‘พ *Help make the NGINX config Ansible role better by participating in our [survey](https://forms.office.com/Pages/ResponsePage.aspx?id=L_093Ttq0UCb4L-DJ9gcUKLQ7uTJaE1PitM_37KR881UM0NCWkY5UlE5MUYyWU1aTUcxV0NRUllJSC4u)!* ๐Ÿ‘พ +# ๐Ÿ‘พ *Help make the NGINX config Ansible role better by participating in our [survey](https://forms.office.com/r/tyWCe7GkpT)!* ๐Ÿ‘พ # Ansible NGINX Configuration Role This role configures NGINX Open Source and NGINX Plus on your target host. -**Note:** This role is still in active development. There may be unidentified issues and the role variables may change as development continues. +> [!IMPORTANT] +> This role is still in active development. There may be unidentified issues and the role variables may change as development continues. -**Note 2:** The role is being currently refactored to use a long term sustainable templating structure (these changes are expected to go live with the role's `0.4.0` release). As such, the documentation found here (on main) reflects the most up to date templates. However, if you are using the latest release available on Ansible Galaxy, please check the `0.3.3` documentation available [here](https://github.com/nginxinc/ansible-role-nginx-config/tree/0.3.3). - -## Requirements +## Role Requirements ### Ansible -* This role is developed and tested with [maintained](https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html) versions of Ansible core (above `2.11`). -* When using Ansible core, you will also need to install the following collections: +If you want to use this role, you will need to use a supported version of Ansible core and Jinja2 as well as a few Ansible collections. + +For ease of use, you can install and/or upgrade Ansible core, Jinja2, and the aforementioned Ansible collections by running the following four commands on your Ansible host: + +```bash +pip install --upgrade -r https://raw.githubusercontent.com/nginx/ansible-role-nginx-config/main/.github/workflows/requirements/requirements_ansible.txt +curl -O https://raw.githubusercontent.com/nginx/ansible-role-nginx-config/main/.github/workflows/requirements/requirements_collections.yml +ansible-galaxy install --force -r requirements_collections.yml +rm -f requirements_collections.yml +``` + +This will also ensure you are deploying/running this role with a fully tested version of the aforementioned packages/collections. + +#### Ansible core + +- This role is developed and tested with [maintained](https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html) versions of Ansible core and Python. +- When using Ansible core, you will also need to install the following Ansible collections: - ```yaml - --- - collections: - - name: community.general - version: 3.8.0 - - name: ansible.posix - version: 1.3.0 - - name: community.docker # Only required if you plan to use Molecule (see below) - version: 2.0.0 - ``` + ```yaml + --- + collections: + - name: ansible.posix + version: 2.0.0 + - name: community.general + version: 11.0.0 + - name: community.crypto # Only required if you plan to to test the NGINX Plus Molecule scenario + version: 3.0.0 + - name: community.docker # Only required if you plan to use Molecule + version: 4.6.1 + ``` - **Note:** You can alternatively install the Ansible community distribution (what is known as the "old" Ansible) if you don't want to manage individual collections. -* Instructions on how to install Ansible can be found in the [Ansible website](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#upgrading-ansible-from-version-2-9-and-older-to-version-2-10-or-later). +- Instructions on how to install Ansible core can be found in the [Ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#upgrading-ansible-from-version-2-9-and-older-to-version-2-10-or-later) docs. +- Instructions on how to install Ansible collections can be found in the [Ansible collections](https://docs.ansible.com/ansible/latest/collections_guide/collections_installing.html) guide. + +> [!TIP] +> You can alternatively install the [Ansible community distribution](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#selecting-an-ansible-package-and-version-to-install) (what is still known Ansible -- instead of Ansible core) if you don't want to manage individual collections. ### Jinja2 -* This role uses Jinja2 templates. Ansible core installs Jinja2 by default, but depending on your install and/or upgrade path, you might be running an outdated version of Jinja2. The minimum version of Jinja2 required for the role to properly function is `2.11`. -* Instructions on how to install Jinja2 can be found in the [Jinja2 website](https://jinja.palletsprojects.com/en/2.11.x/intro/#installation). +- This role uses Jinja2 templates. Ansible core installs Jinja2 by default, but depending on your install and/or upgrade path, you might be running an outdated version of Jinja2. The minimum version of Jinja2 required for the role to properly function is `3.1`. +- Instructions on how to install Jinja2 can be found in the [Jinja2 website](https://jinja.palletsprojects.com/en/3.1.x/intro/#installation). -### Molecule (Optional) +### Testing suite (Optional) -* Molecule is used to test the various functionalities of the role. The recommended version of Molecule to test this role is `3.3`. -* Instructions on how to install Molecule can be found in the [Molecule website](https://molecule.readthedocs.io/en/latest/installation.html). _You will also need to install the Molecule Docker driver._ -* To run the NGINX Plus/App Protect config Molecule tests, you must copy your NGINX Plus/App Protect license to the role's [`files/license`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/files/license/) folder. +If you want to contribute to this role, you will also need to install Ansible Lint and Molecule. -You can alternatively add your NGINX Plus/App Protect repository certificate and key to the local environment. Run the following commands to export these files as base64-encoded variables and execute the Molecule tests: +#### Ansible Lint (Optional) -```bash -export NGINX_CRT=$( cat | base64 ) -export NGINX_KEY=$( cat | base64 ) -molecule test -s plus -``` +- Ansible Lint is used to lint the role for both Ansible best practices and potential Ansible/YAML issues. +- Instructions on how to install Ansible Lint can be found in the [Ansible Lint website](https://ansible.readthedocs.io/projects/lint/installing/). +- Once installed, using Ansible Lint is as easy as running: -## Installation + ```bash + ansible-lint + ``` -### Ansible Galaxy +- For ease of use, you can install and/or upgrade Ansible Lint by running the following command on your Ansible host: -Use `ansible-galaxy install nginxinc.nginx_config` to install the latest stable release of the role on your system. + ```bash + pip install -r https://raw.githubusercontent.com/nginx/ansible-role-nginx-config/main/.github/workflows/requirements/requirements_ansible_lint.txt + ``` -### Git +#### Molecule (Optional) -Use `git clone https://github.com/nginxinc/ansible-role-nginx-config.git` to pull the latest edge commit of the role from GitHub. +- Molecule is used to test the various functionalities of the role. +- Instructions on how to install Molecule can be found in the [Molecule website](https://molecule.readthedocs.io/en/latest/installation.html). *You will also need to install the Molecule plugins package and the Docker Python SDK.* +- To run the NGINX Plus/App Protect config Molecule tests, you must copy your NGINX Plus/App Protect license to the role's Molecule [`common/files/license`](/molecule/common/files/license/) directory. -## Platforms + You can alternatively add your NGINX Plus/App Protect repository certificate and key to the local environment. Run the following commands to export these files as base64-encoded variables and execute the Molecule tests: + + ```bash + export NGINX_CRT=$( cat | base64 ) + export NGINX_KEY=$( cat | base64 ) + molecule test -s plus + ``` + +- For ease of use, you can install and/or upgrade Molecule, the Molecule plugins package, and the Docker Python SDK by running the following command on your Ansible host: + + ```bash + pip install --upgrade -r https://raw.githubusercontent.com/nginx/ansible-role-nginx-config/main/.github/workflows/requirements/requirements_molecule.txt + ``` + +## Role Installation + +This role can be installed via either Ansible Galaxy (the Ansible community marketplace) or by cloning this repo. Once installed, you will need to include the role in your Ansible playbook using [the `roles` keyword, the `import_role` module, or the `include_role` module](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html#using-roles). + +### Ansible Galaxy + +To install the latest stable release of the role on your system, use: + +```bash +ansible-galaxy install nginxinc.nginx_config +``` -The NGINX config Ansible role supports all platforms supported by [NGINX Open Source](https://nginx.org/en/linux_packages.html#mainline) and [NGINX Plus](https://www.nginx.com/products/technical-specs/): +Alternatively, if you have already installed the role, you can update the role to the latest release by using: -### NGINX Open Source +```bash +ansible-galaxy install -f nginxinc.nginx_config +``` + +To use the role, include the following task in your playbook: ```yaml -Alpine: - - 3.11 - - 3.12 - - 3.13 - - 3.14 -Amazon Linux: - - 2 -CentOS: - - 7.4+ - - 8 -Debian: - - buster (10) - - bullseye (11) -Red Hat: - - 7.4+ - - 8 -SUSE/SLES: - - 12 - - 15 -Ubuntu: - - bionic (18.04) - - focal (20.04) - - hirsute (21.04) +- name: Configure NGINX + ansible.builtin.include_role: + name: nginxinc.nginx_config +``` + +### Git + +To pull the latest edge commit of the role from GitHub, use: + +```bash +git clone https://github.com/nginx/ansible-role-nginx-config.git ``` -### NGINX Plus +To use the role, include the following task in your playbook: ```yaml -Alpine: - - 3.11 - - 3.12 - - 3.13 - - 3.14 -Amazon Linux 2: - - any -CentOS: - - 7.4+ - - 8 -Debian: - - buster (10) - - bullseye (11) -FreeBSD: - - 12.1+ - - 13 -Oracle Linux: - - 7.4+ -Red Hat: - - 7.4+ - - 8 -SUSE/SLES: - - 12 - - 15 -Ubuntu: - - bionic (18.04) - - focal (20.04) +- name: Configure NGINX + ansible.builtin.include_role: + name: # e.g. if you clone the repo inside your project's roles directory ``` +## Platforms + +The NGINX config Ansible role supports all platforms supported by [NGINX Open Source](https://nginx.org/en/linux_packages.html#mainline) and [NGINX Plus](https://www.nginx.com/products/technical-specs/). + +> [!NOTE] +> You should be able to use this role to configure any NGINX installation -- wherever/however it's been installed -- at your own risk. Any potential bugs with the role involving unsupported installation methods/platforms will be addressed in a best effort manner and might be outright dismissed.* + ## Role Variables -This role has multiple variables. The descriptions and defaults for all these variables can be found in the **[`defaults/main/`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/defaults/main/)** folder in the following files: +This role has multiple variables. The descriptions and defaults for all these variables can be found in the **[`defaults/main/`](/defaults/main/)** directory in the following files: | Name | Description | | ---- | ----------- | -| **[`main.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/defaults/main/main.yml)** | NGINX simple config variables | -| **[`selinux.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/defaults/main/selinux.yml)** | Set up SELinux to allow the necessary connections to your NGINX setup | -| **[`template.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/defaults/main/template.yml)** | NGINX config template variables | -| **[`upload.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/defaults/main/upload.yml)** | NGINX config/HTML/SSL upload variables | +| **[`main.yml`](/defaults/main/main.yml)** | NGINX simple config variables | +| **[`selinux.yml`](/defaults/main/selinux.yml)** | Set up SELinux to allow the necessary connections to your NGINX setup | +| **[`template.yml`](/defaults/main/template.yml)** | NGINX config template variables | +| **[`upload.yml`](/defaults/main/upload.yml)** | NGINX config/HTML/SSL upload variables | ## Example Playbooks -Working functional playbook examples can be found in the **[`molecule/`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/molecule/)** folder in the following files: +Working functional playbook examples can be found in the **[`molecule/`](/molecule/)** directory in the following files: | Name | Description | | ---- | ----------- | -| **[`cleanup_module/converge.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/molecule/cleanup_module/converge.yml)** | Cleanup an NGINX config and configure NGINX supported modules | -| **[`default/converge.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/molecule/default/converge.yml)** | Use the NGINX config templating variables to create an NGINX config | -| **[`plus/converge.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/molecule/plus/converge.yml)** | Use the NGINX config templating variables to create an NGINX Plus config | -| **[`stable_push/converge.yml`](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/molecule/stable_push/converge.yml)** | Install NGINX using the stable branch and push a preexisting config from your system to your NGINX instance | - -Do note that if you install this repository via Ansible Galaxy, you will have to replace the role variable in the sample playbooks from `ansible-role-nginx-config` to `nginxinc.nginx_config`. +| **[`api/converge.yml`](/molecule/api/converge.yml)** | Configure the NGINX Plus API and live metrics dashboard | +| **[`cleanup_config/converge.yml`](/molecule/cleanup_config/converge.yml)** | Cleanup an NGINX config | +| **[`complete/converge.yml`](/molecule/complete/converge.yml)** | Test all NGINX directives are correctly templated | +| **[`complete_plus/converge.yml`](/molecule/complete_plus/converge.yml)** | Test all NGINX Plus specific directives are correctly templated | +| **[`default/converge.yml`](/molecule/default/converge.yml)** | Configure NGINX with a config as close as possible to the default config | +| **[`push_config/converge.yml`](/molecule/push_config/converge.yml)** | Push a preexisting NGINX config from your system to your NGINX instance | +| **[`reverse_proxy/converge.yml`](/molecule/reverse_proxy/converge.yml)** | Configure NGINX as a reverse proxy between two web servers | +| **[`stub_status/converge.yml`](/molecule/stub_status/converge.yml)** | Configure the NGINX Open Source stub status metrics | +| **[`web_server/converge.yml`](/molecule/web_server/converge.yml)** | Configure NGINX as a web server | + +> [!NOTE] +> If you install this repository via Ansible Galaxy, you will need to replace the `include_role` variable in the example playbooks from `ansible-role-nginx-config` to `nginxinc.nginx_config`. ## Other NGINX Ansible Collections and Roles You can find the Ansible NGINX Core collection of roles to install and configure NGINX Open Source, NGINX Plus, and NGINX App Protect [here](https://github.com/nginxinc/ansible-collection-nginx). -You can find the Ansible NGINX role to install NGINX OSS and NGINX Plus [here](https://github.com/nginxinc/ansible-role-nginx). +You can find the Ansible NGINX role to install NGINX OSS and NGINX Plus [here](https://github.com/nginx/ansible-role-nginx). You can find the Ansible NGINX App Protect role to install and configure NGINX App Protect WAF and NGINX App Protect DoS [here](https://github.com/nginxinc/ansible-role-nginx-app-protect). -You can find the Ansible NGINX Controller collection of roles to install and configure NGINX Controller [here](https://github.com/nginxinc/ansible-collection-nginx_controller). - You can find the Ansible NGINX Unit role to install NGINX Unit [here](https://github.com/nginxinc/ansible-role-nginx-unit). ## License -[Apache License, Version 2.0](https://github.com/nginxinc/ansible-role-nginx-config/blob/main/LICENSE) +[Apache License, Version 2.0](/LICENSE) ## Author Information [Alessandro Fael Garcia](https://github.com/alessfg) -© [F5 Networks, Inc.](https://www.f5.com/) 2020 - 2021 +© [F5, Inc.](https://www.f5.com/) 2020 - 2025 diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..4ddf287c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,26 @@ +# Security Policy + +## Versions + +### Latest Versions + +We advise users to run or update to the most recent release of this project. Older versions of this project may not have all enhancements and/or bug fixes applied to them. + +### Supported Versions + +This codebase mainly consists of an Ansible role, sprinkled with a dose of GitHub actions for CI/CD. Ansible applies security fixes to the most recent three releases. Please find more information in [the Ansible docs](https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html#release-status). + +## Reporting a Vulnerability + +### Ansible + +If you find a security vulnerability that directly affects Ansible, we encourage you to report it according to the [Ansible guidelines](https://docs.ansible.com/ansible/devel/community/reporting_bugs_and_features.html#reporting-a-bug). + +### Codebase + +The F5 Security Incident Response Team (F5 SIRT) offers two methods to easily report potential security vulnerabilities: + +- If youโ€™re an F5 customer with an active support contract, please contact [F5 Technical Support](https://www.f5.com/support). +- If you arenโ€™t an F5 customer, please report any potential or current instances of security vulnerabilities in any F5 product to the F5 Security Incident Response Team at . + +For more information, please read the F5 SIRT vulnerability reporting guidelines available at [https://www.f5.com/support/report-a-vulnerability](https://www.f5.com/support/report-a-vulnerability). diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 00000000..94f7a717 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,33 @@ +# Support + +## Ask a Question + +We use GitHub for tracking bugs and feature requests related to all NGINX Ansible roles. + +Don't know how something in this project works? Curious if this project can achieve your desired functionality? Please open an issue on GitHub with the label `question`. Alternatively, start a GitHub discussion! + +## NGINX Specific Questions and/or Issues + +This isn't the right place to get support for NGINX specific questions, but the following resources are available below. Thanks for your understanding! + +### Community Slack + +We have a community [forum](https://community.nginx.org/)! If you have any questions and/or issues, try checking out the [`Troubleshooting`](https://community.nginx.org/c/troubleshooting/8) and [`How do I...?`](https://community.nginx.org/c/how-do-i/9) categories. Both fellow community members and NGINXers might be able to help you! :) + +### Documentation + +For a comprehensive list of all NGINX directives, check out . + +For a comprehensive list of administration and deployment guides for all NGINX products, check out . + +### Mailing List + +Want to get in touch with the NGINX development team directly? Try using the relevant mailing list found at ! + +## Contributing + +Please see the [contributing guide](/CONTRIBUTING.md) for guidelines on how to best contribute to this project. + +## Community Support + +This project does **not** offer commercial support. Community support is offered on a best effort basis through either GitHub issues/PRs/discussions or through any of our active communities. diff --git a/defaults/main/selinux.yml b/defaults/main/selinux.yml index 195e6f5d..d594c979 100644 --- a/defaults/main/selinux.yml +++ b/defaults/main/selinux.yml @@ -1,12 +1,15 @@ --- -# Set SELinux enforcing for NGINX (Centos/Redhat only) - you may need to open ports on your own +# Set SELinux enforcing for NGINX (Redhat only) - you may need to open ports on your own nginx_config_selinux: false + # Enable enforcing mode if true. Permissive if false (audit only, no enforcing) globally (only works with nginx_config_selinux: true) nginx_config_selinux_enforcing: true + # List of TCP ports to add to http_port_t type (80 and 443 have this type already) # nginx_config_selinux_tcp_ports: # - 80 # - 443 + # List of UDP ports to add to http_port_t type # nginx_config_selinux_udp_ports: # - 80 diff --git a/defaults/main/template.yml b/defaults/main/template.yml index 41ec95b8..32581693 100644 --- a/defaults/main/template.yml +++ b/defaults/main/template.yml @@ -3,9 +3,9 @@ nginx_config_html_demo_template_enable: false nginx_config_html_demo_template: - template_file: www/index.html.j2 - html_file_name: index.html - html_file_location: /usr/share/nginx/html + deployment_location: /usr/share/nginx/html/index.html web_server_name: Default + backup: true # Enable creating dynamic templated NGINX configuration files. # Defaults are the values found in a fresh NGINX installation. @@ -14,13 +14,14 @@ nginx_config_main_template_enable: false nginx_config_main_template: template_file: nginx.conf.j2 deployment_location: /etc/nginx/nginx.conf + backup: true config: main: # Configure NGINX main core directives - load_module: modules/ngx_http_js_module.so # String or a list of strings - # - modules/ngx_http_js_module.so + # load_module: modules/ngx_http_js_module.so # String or a list of strings + # - modules/ngx_http_js_module.so user: # nginx # Can alternatively be set to a 'username' string username: nginx # Required - group: nginx + # group: nginx # worker_cpu_affinity: # auto: true # Optional boolean # cpumask: 0101 1010 # Optional if 'auto' is set to 'true' @@ -35,8 +36,8 @@ nginx_config_main_template: # - /var/log/nginx/error.log # - file: /var/log/nginx/error.log # Required # level: notice - pid: /var/run/nginx.pid - daemon: true # Boolean + pid: /run/nginx.pid + # daemon: true # Boolean # debug_points: abort # Can be set to 'abort' or 'stop' # env: # MALLOC_OPTIONS # String, a list of strings, a dictionary, or a list of dictionaries. The 'variable' variable is only required when setting a 'value'. # variable: PERL5LIB # Required @@ -63,11 +64,35 @@ nginx_config_main_template: # use: epoll # worker_aio_requests: 32 # Number worker_connections: 1024 # Number + # include: # String or a list of strings + # - /etc/nginx/modules.conf + mgmt: # Configure NGINX management directives. Only required when using NGINX Plus >R33. + enforce_initial_report: true # Boolean + license_token: license.jwt + # proxy: 123.456.789:8353 + # proxy_username: username + # proxy_password: password + resolver: + address: 127.0.0.1 # Required -- String or a list of strings + valid: 30s + ipv4: true # Boolean + ipv6: true # Boolean + status_zone: mgmt_mem_zone + # ssl_crl: /path/to/file + # ssl_trusted_certificate: /path/to/file + ssl_verify: false # Boolean + state_path: /var/lib/nginx/state + usage_report: + endpoint: product.connect.nginx.com + interval: 30m http: - include: /etc/nginx/conf.d/*.conf # String or a list of strings - stream: include: # String or a list of strings - - /etc/nginx/conf.d/stream/*.conf + - /etc/nginx/mime.types + - /etc/nginx/conf.d/*.conf + # stream: + # include: /etc/nginx/conf.d/stream/*.conf # String or a list of strings + # quic: + # bpf: false # Boolean # Enable creating dynamic templated NGINX HTTP configuration files. # Defaults will not produce a valid configuration. Instead they are meant to showcase @@ -78,8 +103,9 @@ nginx_config_http_template_enable: false nginx_config_http_template: - template_file: http/default.conf.j2 deployment_location: /etc/nginx/conf.d/default.conf + backup: true config: - upstreams: # Configure NGINX upstreams + upstreams: # Configure upstreams - name: backend # Required servers: # Cannot be used if 'state' directive is defined - address: localhost # Required -- You can use an IP address, a Unix socket, or a domain -- include port details inline if necessary @@ -122,7 +148,7 @@ nginx_config_http_template: valid: 30s ipv6: false # Boolean status_zone: backend_mem_zone - resolver_timeout: 30s + resolver_timeout: 30s # Available only in NGINX Plus sticky_cookie: # You can only set one type of sticky session affinity name: cookie # Required expires: 1d @@ -199,8 +225,7 @@ nginx_config_http_template: port: 80 default_server: true # Boolean ssl: false # Boolean - http2: false # Boolean - spdy: false # Boolean + quic: false # Boolean # Incompatible with the 'so_keepalive' parameter proxy_protocol: false # Boolean fastopen: 12 # Number backlog: 511 # Number @@ -210,7 +235,7 @@ nginx_config_http_template: bind: false # Boolean ipv6only: false # Boolean reuseport: false # Boolean - so_keepalive: # false # Can alternatively be set to a 'boolean' + so_keepalive: # false # Can alternatively be set to a 'boolean' -- Incompatible with theย 'quic' parameter keepidle: 30m keepintvl: 5 keepcnt: 10 @@ -239,7 +264,7 @@ nginx_config_http_template: address: 127.0.0.1 # Required -- String or a list of strings valid: 60s ipv6: false # Boolean - status_zone: zone # Only available in NGINX Plus + status_zone: zone # Available only in NGINX Plus resolver_timeout: 30s root: html index: path # Note -- This directive originally belongs to the NGINX index module, but we are making an exception here. @@ -268,7 +293,24 @@ nginx_config_http_template: underscores_in_headers: false # Boolean -- Not available in the 'location' context variables_hash_bucket_size: 64 # Available only in the 'http' context variables_hash_max_size: 1024 # Available only in the 'http' context - ssl: + http2: # Configure HTTP2 + enable: false # Boolean -- Not available in the 'location' context + body_preread_size: 64k # Not available in the 'location' context + chunk_size: 8k + max_concurrent_streams: 128 # Number -- Not available in the 'location' context + recv_buffer_size: 256k # Only available in the 'http' context + recv_timeout: 20s # Not available in the 'location' context + http3: + enable: false # Boolean + hq: false # Boolean + max_concurrent_streams: 128 # Number + stream_buffer_size: 64k + quic: + active_connection_id_limit: 2 + gso: false # Boolean + host_key: /path/to/file + retry: false # Boolean + ssl: # Configure SSL buffer_size: 16k certificate: /path/to/file # String or a list of strings certificate_key: /path/to/file # String or a list of strings @@ -344,7 +386,10 @@ nginx_config_http_template: enable: true # Required uri: example.com port: 80 - proxy: # Configure Proxy + arb_fqdn: 192.168.1.10 # Available only in the 'http' context + api: false # Available only in the 'location' context + accelerated_mitigation: false # Available only in the 'http' context + proxy: # Configure proxy settings bind: # Set to 'false' and remove/comment nested variables to disable proxy_bind address: 0.0.0.0 # Required transparent: false # Boolean @@ -410,7 +455,7 @@ nginx_config_http_template: headers_hash_bucket_size: 64 headers_hash_max_size: 512 hide_header: Date # String or a list of strings - http_version: 1.1 # Can be set to '1.0' or '1.1' + http_version: '1.1' # Can be set to '1.0' or '1.1' ignore_client_abort: false # Boolean ignore_headers: X-Accel-Redirect # String or a list of strings -- Can be set to 'X-Accel-Redirect', 'X-Accel-Expires', 'X-Accel-Limit-Rate', 'X-Accel-Buffering', 'X-Accel-Charset', 'Expires', 'Cache-Control', 'Set-Cookie' or 'Vary' intercept_errors: false # Boolean @@ -499,7 +544,7 @@ nginx_config_http_template: ssl_trusted_certificate: /path/to/file ssl_verify: false # Boolean ssl_verify_depth: 1 - access: # Configure HTTP access + access: # Configure access settings allow: localhost # String or a list of strings deny: 192.168.1.100 # String or a list of strings auth_basic: # Configure basic auth @@ -525,8 +570,10 @@ nginx_config_http_template: key_request: /path/to/file leeway: 0s type: signed # Can be set to 'signed', 'encrypted' or 'nested' - require: $valid_jwt_iss # String or a list of strings - api: # Available only in NGINX Plus -- Configure NGINX Plus HTTP API + require: + values: $valid_jwt_iss # Required -- String or a list of strings + error: 401 # Can be set to '401' or '403' + api: # Available only in NGINX Plus -- Configure HTTP API enable: # true # Set to Boolean directly to simply enable the 'api' directive -- Available only in the 'location' context write: true # Boolean status_zone: one # Not available in the 'http' context @@ -536,6 +583,11 @@ nginx_config_http_template: exact_size: true # Boolean format: html localtime: false # Boolean + gunzip: # Configure GUNZIP + enable: true # Boolean + buffers: + number: 32 # Required + size: 4k # Required gzip: # Configure GZIP enable: true # Boolean buffers: @@ -546,6 +598,7 @@ nginx_config_http_template: http_version: 1.1 # Can be set to '1.0' or '1.1' min_length: 20 proxied: [] # String or a list of strings -- Can alternatively be set to 'false' + static: false # Boolean or 'always' types: [] # String or a list of strings vary: false # Boolean headers: # Configure headers @@ -560,7 +613,7 @@ nginx_config_http_template: expires: # false # Can alternatively be set to 'false' modified: true # Boolean time: "12h" - health_check: # Available only in NGINX Plus -- Configure NGINX Plus health checks + health_check: # Available only in NGINX Plus -- Configure active health checks health_checks: # Available only in the 'location' context - interval: 5s jitter: 0 @@ -573,10 +626,11 @@ nginx_config_http_template: port: 80 grpc_service: service grpc_status: 12 + keepalive_time: 0 match: # Available only in the 'http' context - name: name # Required conditions: [] - keyval: # Available only in NGINX Plus -- Configure NGINX Plus key value store + keyval: # Available only in NGINX Plus -- Configure key value store keyvals: # Available only in the 'http' context - key: key # Required variable: $var # Required @@ -628,7 +682,25 @@ nginx_config_http_template: inactive: 20s min_uses: 2 # Number valid: 1m - rewrite: # Configure rewrite directives + map: # Configure maps -- Available only in the 'http' context + hash_bucket_size: 64 + hash_max_size: 2048 + mappings: # List of dictionaries + - string: $remote_addr # Required + variable: $upstream # Required + hostnames: false # Boolean + volatile: false # Boolean + content: # Dictionary or list of dictionaries + - value: default + new_value: 0 + mirror: # Configure mirrors + request_body: true # Boolean + uri: false # String or a list of strings -- Can alternatively be set to 'false' + realip: # Configure RealIP + set_real_ip_from: 0.0.0.0 + real_ip_header: X-Real-IP + real_ip_recursive: false # Boolean + rewrite: # Configure rewrites return: # Can also be set to a return URL or code directly -- Not available in the 'http' context code: 200 # Required -- You have to set either 'code' or 'url' text: text # Only available when using 'code' @@ -642,16 +714,25 @@ nginx_config_http_template: - variable: $var # Required value: var # Required uninitialized_variable_warn: true # Boolean - sub_filter: # Configure sub_filter directives + split_clients: # Configure split_clients -- Available only in the 'http' context + string: $remote_addr # Required + variable: $upstream # Required + content: # List of dictionaries -- Percentages must add up to 100% + - percentage: 20% # Required + value: appv2 # Required + - percentage: "*" # Required + value: app # Required + sub_filter: # Configure sub filters sub_filters: # Dictionary or a list of dictionaries - string: server_hostname # Required replacement: $hostname # Required last_modified: false # Boolean once: true # Boolean types: text/html # String or a list of strings - custom_directives: # String or a list of strings. Custom directive for specific use cases not covered by templates. Note: You need to add a semi-colon at the end of each directive. + custom_directives: # String or a list of strings. Custom directive for specific use cases not covered by templates. Note: You need to include each directive in its full form. Make sure you add a semi-colon or closing curly bracket at the end of each directive. - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:/run/php/php7.2-fpm.sock; + # - if ($request_method = POST) { return 405; } servers: # All previous modules are also available (when allowed) in the 'servers' and 'locations' contexts. - core: proxy: @@ -672,10 +753,11 @@ nginx_config_http_template: nginx_config_status_enable: false nginx_config_status_template_file: http/status.conf.j2 nginx_config_status_file_location: /etc/nginx/conf.d/status.conf +nginx_config_status_backup: true nginx_config_status_port: 8080 # Optional -- Defaults to 8080 nginx_config_status_access_log: # Optional -- Set to 'false' and remove/comment nested variables to disable access log - location: /var/log/nginx/access.log # Required - name: main # Required + path: /var/log/nginx/access.log # Required + format: main # Required nginx_config_status_allow: # Optional - 127.0.0.1 nginx_config_status_deny: # Optional @@ -687,11 +769,12 @@ nginx_config_status_deny: # Optional nginx_config_rest_api_enable: false nginx_config_rest_api_template_file: http/api.conf.j2 nginx_config_rest_api_file_location: /etc/nginx/conf.d/api.conf +nginx_config_rest_api_backup: true nginx_config_rest_api_port: 8080 # Optional-- Defaults to 8080 nginx_config_rest_api_write: false # Optional nginx_config_rest_api_access_log: # Optional -- Set to 'false' and remove/comment nested variables to disable access log - location: /var/log/nginx/access.log # Required - name: main # Required + path: /var/log/nginx/access.log # Required + format: main # Required nginx_config_rest_api_allow: # Optional - 127.0.0.1 nginx_config_rest_api_deny: # Optional @@ -704,56 +787,214 @@ nginx_config_rest_api_dashboard_deny: # Optional # Enable creating dynamic templated NGINX stream configuration files. # Defaults will not produce a valid configuration. Instead they are meant to showcase -# the options available for templating. Each key represents a new configuration file. +# the options available for templating. Each dictionary in the top level list/array represents a new configuration file. +# Unless otherwise noted, all variables are *strings* and *optional* (*required* values inside a dictionary are only required if the top level variable is defined). +# Most (not all) of these directives can also be used under the 'server' context, as briefly seen at the end of the below dictionary. nginx_config_stream_template_enable: false nginx_config_stream_template: - template_file: stream/default.conf.j2 - conf_file_name: default.conf - conf_file_location: /etc/nginx/conf.d/stream/ - network_streams: - - listen: - - ip: 0.0.0.0 # Wrap in square brackets for IPv6 addresses + deployment_location: /etc/nginx/conf.d/streams/stream_default.conf + backup: true + config: + upstreams: # Configure upstreams + - name: stream_upstream # Required + servers: + - address: 0.0.0.0:9091 # Required + weight: 1 # Number + max_conns: 100 # Number + max_fails: 3 # Number + fail_timeout: 5s + backup: false # Boolean + down: false # Boolean + resolve: false # Boolean + service: http + slow_start: 0s + zone: + name: stream_zone # Required + size: 64k + state: /var/lib/nginx/state/servers.conf # Available only in NGINX Plus -- Cannot be used if 'servers' directive is defined + hash: # You can only set one load balancing method -- 'round_robin' is used if no method is specified + key: key # Required + consistent: false # Boolean + least_conn: false # Boolean -- You can only set one load balancing method + least_time: # You can only set one load balancing method + response: last_byte # Required -- Can be set to 'header' or 'last_byte' + inflight: false # Boolean + random: # You can only set one load balancing method + two: true # Boolean + method: least_time=last_byte # Requires two to be set to 'true' + resolver: # Available only in NGINX Plus + address: [] # Required -- String or a list of strings + valid: 30s + ipv6: false # Boolean + status_zone: backend_mem_zone + resolver_timeout: 30s # Available only in NGINX Plus + core: # Configure NGINX Stream core directives + include: path # String or a list of strings. Note -- This directive originally belongs to the NGINX core module, but we are making an exception here. + listen: # Available only in the 'server' context + - address: 0.0.0.0 # Can also be a unix path + port: 80 + ssl: false # Boolean + udp: false # Boolean + proxy_protocol: false # Boolean + fastopen: 12 # Number + backlog: 511 # Number + rcvbuf: 512 + sndbuf: 512 + bind: false # Boolean + ipv6only: false # Boolean + reuseport: false # Boolean + so_keepalive: # false # Can alternatively be set to a 'boolean' + keepidle: 30m + keepintvl: 5 + keepcnt: 10 + preread_buffer_size: 16k + preread_timeout: 30s + proxy_protocol_timeout: 30s + resolver: + address: 127.0.0.1 # Required -- String or a list of strings + valid: 60s + ipv6: false # Boolean + status_zone: zone # Available only in NGINX Plus + resolver_timeout: 30s + tcp_nodelay: true # Boolean + variables_hash_bucket_size: 64 + variables_hash_max_size: 1024 + ssl: # Configure SSL + alpn: http/1.1 # String or a list of strings + certificate: /etc/ssl/certs/molecule.crt # String or a list of strings + certificate_key: /etc/ssl/private/molecule.key # String or a list of strings + ciphers: # String or a list of strings + - HIGH + - "!aNull" + - "!MD5" + client_certificate: /path/to/file + conf_command: Protocol TLSv1.2 # String or a list of strings + crl: /path/to/file + dhparam: /path/to/file + ecdh_curve: auto # String or a list of strings + handshake_timeout: 60s + password_file: /path/to/file + prefer_server_ciphers: false # Boolean + protocols: # String or a list of strings + - TLSv1 + - TLSv1.1 + - TLSv1.2 + session_cache: # none # Can be set to 'false', 'none', 'builtin' (uses the 'enable' and 'size' dict), or 'shared' (uses the 'name' and 'size' dict) + builtin: + enable: false # Required + size: 16k + # shared: + # name: cache # Required + # size: 16k # Required + session_ticket_key: /path/to/file # String or a list of strings + session_tickets: true # Boolean + session_timeout: 5m + trusted_certificate: /path/to/file + verify_client: false # Boolean -- Can also be set to 'optional' or 'optional_no_ca' + verify_depth: 1 # Number + proxy: # Configure proxy settings + bind: # Set to 'false' and remove/comment nested variables to disable proxy_bind + address: 0.0.0.0 # Required + transparent: false # Boolean + buffer_size: 4k + connect_timeout: 60s + download_rate: 0 + half_close: false # Boolean + next_upstream: true # Boolean + next_upstream_timeout: 0 + next_upstream_tries: 0 # Number + pass: 127.0.0.1 # Available only in the 'server' context + protocol: false # Boolean + requests: 0 # Number + responses: 0 # Number + session_drop: false # Available only in NGINX Plus -- Boolean + socket_keepalive: false # Boolean + ssl: false + ssl_certificate: /path/to/file + ssl_certificate_key: /path/to/file + ssl_ciphers: HIGH # String or a list of strings + ssl_conf_command: # String or a list of strings + - Protocol TLSv1.2 + ssl_crl: /path/to/file + ssl_name: $hostname + ssl_password_file: /path/to/file + ssl_protocols: TLSv1.2 # String or a list of strings + ssl_server_name: false # Boolean + ssl_session_reuse: true # Boolean + ssl_trusted_certificate: /path/to/file + ssl_verify: false # Boolean + ssl_verify_depth: 1 # Number + timeout: 10m + upload_rate: 0 + health_check: # Available only in NGINX Plus -- Configure active health checks + health_checks: # Available only in the 'server' context + - interval: 5s + jitter: 0 + fails: 1 # Number + passes: 1 # Number + uri: / + mandatory: false # Boolean + persistent: false # Boolean + match: match port: 80 - ssl: false - opts: [] # Listen opts like udp which will be added (ssl is automatically added if you specify 'ssl:'). - ssl: - cert: /etc/ssl/certs/default.crt - key: /etc/ssl/private/default.key - dhparam: /etc/ssl/private/dh_param.pem - protocols: TLSv1 TLSv1.1 TLSv1.2 - ciphers: HIGH:!aNULL:!MD5 - prefer_server_ciphers: true - session_cache: none - session_timeout: 5m - disable_session_tickets: false - trusted_cert: /etc/ssl/certs/root_CA_cert_plus_intermediates.crt - ecdh_curve: auto - include_files: [] - proxy_pass: backend - proxy_timeout: 3s - proxy_connect_timeout: 1s - proxy_protocol: false - proxy_ssl: - cert: /etc/ssl/certs/proxy_default.crt - key: /etc/ssl/private/proxy_default.key - trusted_cert: /etc/ssl/certs/proxy_ca.crt - protocols: TLSv1 TLSv1.1 TLSv1.2 - ciphers: HIGH:!aNULL:!MD5 - verify: false - verify_depth: 1 - session_reuse: true - health_check_plus: false - # custom_options: [] - upstreams: - - name: backend - lb_method: least_conn - zone_name: backend - zone_size: 64k - sticky_cookie: false - servers: - - address: localhost - port: 8080 - weight: 1 - health_check: max_fails=1 fail_timeout=10s - # custom_options: [] - # custom_options: [] + udp: false + match: + - name: nginx_stream + conditions: + - status 200 + timeout: 60s + keyval: # Available only in NGINX Plus -- Configure key value store + keyvals: # Available only in the 'stream' context + - key: key # Required + variable: $var # Required + zone: one # Required + zones: # Available only in the 'stream' context + - name: one # Required + size: 32k # Required + state: /var/lib/nginx/state/one.keyval + timeout: 60m + type: string # Can be set to 'string', 'ip' or 'prefix' + sync: false # Boolean + log: # Configure logs + format: # Available only in the 'stream' context + - name: main # Required + escape: default # Can be set to 'default', 'json' or 'none' + format: | # Required + '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"' + access: # false # Can alternatively be set to 'false' + - path: /var/log/nginx/access.log # Required + format: main + buffer: 1m + gzip: 5 # Number -- Can alternatively be set to 'true' + flush: 10h + if: $loggable + error: # /var/log/nginx/error.log # String, a list of strings, a dictionary, or a list of dictionaries. The 'file' variable is only required when setting a 'level'. This directive originally belongs to the NGINX core module, but we are making an exception. + file: /var/log/nginx/error.log # Required + level: notice + # - /var/log/nginx/error.log + # - file: /var/log/nginx/error.log # Required + # level: notice + open_log_file_cache: # Set to 'false' to set to 'off' + max: 1000 # Required + inactive: 20s + min_uses: 2 # Number + valid: 1m + map: # Configure maps -- Available only in the 'stream' context + hash_bucket_size: 64 + hash_max_size: 2048 + mappings: # List of dictionaries + - string: $remote_addr # Required + variable: $upstream # Required + hostnames: false # Boolean + volatile: false # Boolean + content: # Dictionary or list of dictionaries + - value: default + new_value: 0 + custom_directives: # String or a list of strings. Custom directive for specific use cases not covered by templates. Note: You need to include each directive in its full form. Make sure you add a semi-colon or closing curly bracket at the end of each directive. + - server {}; + servers: # All previous modules are also available (when allowed) in the 'servers' context. + - core: + proxy: diff --git a/defaults/main/upload.yml b/defaults/main/upload.yml index 5c66b221..7a249f42 100644 --- a/defaults/main/upload.yml +++ b/defaults/main/upload.yml @@ -2,33 +2,25 @@ # Enable uploading NGINX related files to your system. # Default for uploading files is false. # Default location of files is the files folder within the NGINX Config Ansible role. -# (DEPRECATED) Upload the main NGINX configuration file. -nginx_config_main_upload_enable: false -nginx_config_main_upload_src: config/nginx.conf -nginx_config_main_upload_dest: /etc/nginx/ -# (DEPRECATED) Upload HTTP NGINX configuration files. -nginx_config_http_upload_enable: false -nginx_config_http_upload_src: config/http/*.conf -nginx_config_http_upload_dest: /etc/nginx/conf.d/ -# (DEPRECATED) Upload Stream NGINX configuration files. -nginx_config_stream_upload_enable: false -nginx_config_stream_upload_src: config/stream/*.conf -nginx_config_stream_upload_dest: /etc/nginx/conf.d/ # Upload NGINX config files/snippets. nginx_config_upload_enable: false nginx_config_upload: - - src: config/snippets/ # You can optionally also include the specific file name - dest: /etc/nginx/snippets # You can optionally also include the specific desired file name + - src: config/snippets/ # You can optionally also include the specific file name + dest: /etc/nginx/snippets # You can optionally also include the specific desired file name + backup: true # Upload HTML files. nginx_config_upload_html_enable: false nginx_config_upload_html: - src: www/index.html dest: /usr/share/nginx/html + backup: true # Upload SSL certificates and keys. nginx_config_upload_ssl_enable: false nginx_config_upload_ssl_crt: - src: ssl/certs/ dest: /etc/ssl/certs + backup: true nginx_config_upload_ssl_key: - src: ssl/private/ dest: /etc/ssl/private + backup: true diff --git a/handlers/main.yml b/handlers/main.yml index 0a607e43..c9a57aa3 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,6 +1,6 @@ --- - name: (Handler - NGINX Config) Check NGINX - command: nginx -t + ansible.builtin.command: nginx -t args: chdir: /etc/nginx/ register: config_check @@ -10,18 +10,20 @@ listen: (Handler - NGINX Config) Run NGINX - name: (Handler - NGINX Config) Print NGINX error if syntax check fails - debug: - var: config_check.stderr_lines - failed_when: config_check.rc != 0 + ansible.builtin.debug: + var: config_check['stderr_lines'] + failed_when: config_check['rc'] != 0 when: - - config_check.stderr_lines is defined - - config_check.rc != 0 + - config_check['stderr_lines'] is defined + - config_check['stderr_lines'] != [] + - config_check['rc'] != 0 listen: (Handler - NGINX Config) Run NGINX - name: (Handler - NGINX Config) Start/reload NGINX - service: + ansible.builtin.service: name: nginx state: reloaded + enabled: true when: - nginx_config_start | bool - not ansible_check_mode | bool diff --git a/meta/main.yml b/meta/main.yml index 499e1ffa..658c5450 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,42 +1,13 @@ --- galaxy_info: - author: Alessandro Fael Garcia + author: nginxinc description: Official Ansible role for configuring NGINX role_name: nginx_config - namespace: nginxinc # Ansible Lint requirement - company: F5 Networks, Inc. + company: F5, Inc. license: Apache License, Version 2.0 - min_ansible_version: 2.11 - - platforms: - - name: Alpine - versions: - - any - - name: Amazon Linux 2 - versions: - - any - - name: Debian - versions: - - buster - - bullseye - - name: EL - versions: - - 7 - - 8 - - name: FreeBSD - versions: - - 12.1 - - name: Ubuntu - versions: - - bionic - - focal - - hirsute - - name: SLES - versions: - - 12 - - 15 + min_ansible_version: '2.16' galaxy_tags: - nginx @@ -47,3 +18,7 @@ galaxy_info: - server - development - configuration + +collections: + - ansible.posix + - community.general diff --git a/molecule/api_plus/converge.yml b/molecule/api_plus/converge.yml new file mode 100644 index 00000000..9dcbb94f --- /dev/null +++ b/molecule/api_plus/converge.yml @@ -0,0 +1,20 @@ +--- +- name: Converge + hosts: all + tasks: + - name: Configure NGINX + ansible.builtin.include_role: + name: ansible-role-nginx-config + vars: + nginx_config_debug_output: true + + nginx_config_rest_api_enable: true + nginx_config_rest_api_template_file: http/api.conf.j2 + nginx_config_rest_api_file_location: /etc/nginx/conf.d/api.conf + nginx_config_rest_api_backup: true + nginx_config_rest_api_port: 8080 + nginx_config_rest_api_write: true + nginx_config_rest_api_access_log: + path: /var/log/nginx/access.log + format: main + nginx_config_rest_api_dashboard: true diff --git a/molecule/api_plus/molecule.yml b/molecule/api_plus/molecule.yml new file mode 100644 index 00000000..813c8240 --- /dev/null +++ b/molecule/api_plus/molecule.yml @@ -0,0 +1,51 @@ +--- +dependency: + name: galaxy + options: + role-file: molecule/common/requirements/oss_requirements.yml +driver: + name: docker +lint: | + set -e + ansible-lint --force-color +platforms: + - name: alpine-3.19 + image: alpine:3.19 + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /sbin/init + - name: debian-bullseye + image: debian:bullseye-slim + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /sbin/init + - name: rhel-9 + image: redhat/ubi9:9.4 + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /usr/sbin/init + - name: ubuntu-jammy + image: ubuntu:jammy + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /sbin/init +provisioner: + name: ansible + playbooks: + prepare: prepare.yml + converge: converge.yml + verify: verify.yml + env: + ANSIBLE_ROLES_PATH: ~/.cache/molecule/ansible-role-nginx-config/${MOLECULE_SCENARIO_NAME}/roles:${MOLECULE_PROJECT_DIRECTORY}/..:~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles diff --git a/molecule/plus/prepare.yml b/molecule/api_plus/prepare.yml similarity index 50% rename from molecule/plus/prepare.yml rename to molecule/api_plus/prepare.yml index e41e1399..d962353a 100644 --- a/molecule/plus/prepare.yml +++ b/molecule/api_plus/prepare.yml @@ -4,39 +4,36 @@ gather_facts: false tasks: - name: Create ephemeral license certificate file from b64 decoded env var - copy: - content: "{{ lookup('env','NGINX_CRT') | b64decode }}" + ansible.builtin.copy: + content: "{{ lookup('env', 'NGINX_CRT') | b64decode }}" dest: ../common/files/license/nginx-repo.crt force: false - mode: 0444 + mode: "0444" - name: Create ephemeral license key file from b64 decoded env var - copy: - content: "{{ lookup('env','NGINX_KEY') | b64decode }}" + ansible.builtin.copy: + content: "{{ lookup('env', 'NGINX_KEY') | b64decode }}" dest: ../common/files/license/nginx-repo.key force: false - mode: 0444 + mode: "0444" + + - name: Create ephemeral license JWT file from b64 encoded env var + ansible.builtin.copy: + content: "{{ lookup('env', 'NGINX_JWT') }}" + dest: ../common/files/license/license.jwt + force: false + mode: "0444" - name: Install NGINX Plus hosts: all tasks: - - name: Install NGINX - include_role: + - name: Install NGINX Plus + ansible.builtin.include_role: name: nginxinc.nginx vars: nginx_type: plus nginx_license: certificate: ../common/files/license/nginx-repo.crt key: ../common/files/license/nginx-repo.key + jwt: ../common/files/license/license.jwt nginx_remove_license: false - - - name: Install NGINX App Protect WAF - include_role: - name: nginxinc.nginx_app_protect - vars: - nginx_app_protect_waf_enable: true - nginx_app_protect_dos_enable: true - nginx_app_protect_setup_license: false - nginx_app_protect_remove_license: false - nginx_app_protect_install_signatures: false - nginx_app_protect_install_threat_campaigns: false diff --git a/molecule/api_plus/verify.yml b/molecule/api_plus/verify.yml new file mode 100644 index 00000000..17308d48 --- /dev/null +++ b/molecule/api_plus/verify.yml @@ -0,0 +1,20 @@ +--- +- name: Verify + hosts: all + tasks: + - name: Check if NGINX Plus is installed + ansible.builtin.package: + name: nginx-plus + state: present + check_mode: true + register: install + failed_when: (install is changed) or (install is failed) + + - name: Check if NGINX service is running + ansible.builtin.service: + name: nginx + state: started + enabled: true + check_mode: true + register: service + failed_when: (service is changed) or (service is failed) diff --git a/molecule/cleanup_module/converge.yml b/molecule/cleanup_config/converge.yml similarity index 81% rename from molecule/cleanup_module/converge.yml rename to molecule/cleanup_config/converge.yml index ae5b52fa..f7eb920d 100644 --- a/molecule/cleanup_module/converge.yml +++ b/molecule/cleanup_config/converge.yml @@ -3,7 +3,7 @@ hosts: all tasks: - name: Configure NGINX - include_role: + ansible.builtin.include_role: name: ansible-role-nginx-config vars: nginx_config_debug_output: true @@ -15,6 +15,3 @@ recurse: false nginx_config_cleanup_files: - /etc/nginx/conf.d/default.conf - - nginx_config_modules: - - modules/ngx_http_js_module.so diff --git a/molecule/cleanup_config/molecule.yml b/molecule/cleanup_config/molecule.yml new file mode 100644 index 00000000..813c8240 --- /dev/null +++ b/molecule/cleanup_config/molecule.yml @@ -0,0 +1,51 @@ +--- +dependency: + name: galaxy + options: + role-file: molecule/common/requirements/oss_requirements.yml +driver: + name: docker +lint: | + set -e + ansible-lint --force-color +platforms: + - name: alpine-3.19 + image: alpine:3.19 + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /sbin/init + - name: debian-bullseye + image: debian:bullseye-slim + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /sbin/init + - name: rhel-9 + image: redhat/ubi9:9.4 + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /usr/sbin/init + - name: ubuntu-jammy + image: ubuntu:jammy + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /sbin/init +provisioner: + name: ansible + playbooks: + prepare: prepare.yml + converge: converge.yml + verify: verify.yml + env: + ANSIBLE_ROLES_PATH: ~/.cache/molecule/ansible-role-nginx-config/${MOLECULE_SCENARIO_NAME}/roles:${MOLECULE_PROJECT_DIRECTORY}/..:~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles diff --git a/molecule/cleanup_module/prepare.yml b/molecule/cleanup_config/prepare.yml similarity index 75% rename from molecule/cleanup_module/prepare.yml rename to molecule/cleanup_config/prepare.yml index 485619d6..3966ff25 100644 --- a/molecule/cleanup_module/prepare.yml +++ b/molecule/cleanup_config/prepare.yml @@ -3,14 +3,14 @@ hosts: all tasks: - name: Install NGINX - include_role: + ansible.builtin.include_role: name: nginxinc.nginx vars: nginx_modules: - njs - name: Create mock NGINX configuration file - file: + ansible.builtin.file: path: /etc/nginx/conf.d/mock.conf state: touch - mode: 0644 + mode: "0644" diff --git a/molecule/cleanup_module/verify.yml b/molecule/cleanup_config/verify.yml similarity index 76% rename from molecule/cleanup_module/verify.yml rename to molecule/cleanup_config/verify.yml index 7b2066fa..3b9d84b5 100644 --- a/molecule/cleanup_module/verify.yml +++ b/molecule/cleanup_config/verify.yml @@ -3,7 +3,7 @@ hosts: all tasks: - name: Check if NGINX is installed - package: + ansible.builtin.package: name: nginx state: present check_mode: true @@ -11,7 +11,7 @@ failed_when: (install is changed) or (install is failed) - name: Check if NGINX service is running - service: + ansible.builtin.service: name: nginx state: started enabled: true @@ -20,15 +20,15 @@ failed_when: (service is changed) or (service is failed) - name: Check default.conf does not exist - stat: + ansible.builtin.stat: path: /etc/nginx/conf.d/default.conf check_mode: true register: stat_result - failed_when: stat_result.stat.exists + failed_when: stat_result['stat']['exists'] | bool - name: Check mock.conf does not exist - stat: + ansible.builtin.stat: path: /etc/nginx/conf.d/mock.conf check_mode: true register: stat_result - failed_when: stat_result.stat.exists + failed_when: stat_result['stat']['exists'] | bool diff --git a/molecule/cleanup_module/molecule.yml b/molecule/cleanup_module/molecule.yml deleted file mode 100644 index a1080a48..00000000 --- a/molecule/cleanup_module/molecule.yml +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependency: - name: galaxy - options: - role-file: molecule/common/requirements/oss_requirements.yml -driver: - name: docker -lint: | - set -e - yamllint . - ansible-lint --force-color -platforms: - - name: alpine-3.13 - image: alpine:3.13 - dockerfile: ../common/Dockerfile.j2 - privileged: true - volumes: - - "/sys/fs/cgroup:/sys/fs/cgroup:rw" - command: "/sbin/init" - - name: centos-7 - image: centos:7 - dockerfile: ../common/Dockerfile.j2 - privileged: true - volumes: - - "/sys/fs/cgroup:/sys/fs/cgroup:rw" - command: "/usr/sbin/init" - - name: debian-buster - image: debian:buster-slim - dockerfile: ../common/Dockerfile.j2 - privileged: true - volumes: - - "/sys/fs/cgroup:/sys/fs/cgroup:rw" - command: "/sbin/init" - - name: ubuntu-bionic - image: ubuntu:bionic - dockerfile: ../common/Dockerfile.j2 - privileged: true - volumes: - - "/sys/fs/cgroup:/sys/fs/cgroup:rw" - command: "/sbin/init" -provisioner: - name: ansible - playbooks: - prepare: prepare.yml - converge: converge.yml - verify: verify.yml diff --git a/molecule/common/Dockerfile.j2 b/molecule/common/Dockerfile.j2 index fc2cfd35..5442227b 100644 --- a/molecule/common/Dockerfile.j2 +++ b/molecule/common/Dockerfile.j2 @@ -25,12 +25,14 @@ RUN \ && dnf clean all; \ elif [ $(command -v yum) ]; then \ yum makecache fast \ - && yum install -y bash iproute initscripts sudo /usr/bin/python /usr/bin/python2-config vim yum-plugin-ovl \ + && yum install -y bash iproute initscripts sudo /usr/bin/python /usr/bin/python2-config vim yum-plugin-copr yum-plugin-ovl \ + && yum copr enable -y jsynacek/systemd-backports-for-centos-7 \ + && yum update --disableplugin=priorities -y systemd \ && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf \ && yum clean all; \ elif [ $(command -v zypper) ]; then \ zypper refresh \ - && zypper install -y bash iproute2 python3 sudo vim \ + && zypper install -y bash iproute2 python3 sudo systemd systemd-sysvinit vim \ && zypper clean -a; \ elif [ $(command -v apk) ]; then \ apk update \ diff --git a/molecule/common/files/nginx.conf b/molecule/common/files/nginx.conf index 07e8d3d8..16112b1f 100644 --- a/molecule/common/files/nginx.conf +++ b/molecule/common/files/nginx.conf @@ -2,7 +2,7 @@ user nginx; worker_processes 4; error_log /var/log/nginx/error.log warn; -pid /var/run/nginx.pid; +pid /run/nginx.pid; events { worker_connections 1024; diff --git a/molecule/common/files/snippets/modules.conf b/molecule/common/files/snippets/modules.conf new file mode 100644 index 00000000..ab3d02ac --- /dev/null +++ b/molecule/common/files/snippets/modules.conf @@ -0,0 +1 @@ +load_module modules/ngx_http_perl_module.so; diff --git a/molecule/common/files/ssl/rand.key b/molecule/common/files/ssl/rand.key new file mode 100644 index 00000000..93009070 --- /dev/null +++ b/molecule/common/files/ssl/rand.key @@ -0,0 +1 @@ + Eว4๚hน’ถ4ใึšYโ &i"/mั{๗7ฑฎ<%…J%fท๊^ั์`RฟPระ[ ฤ,6=!ช>Zๅ ปo้KฮcG่ \ No newline at end of file diff --git a/molecule/common/requirements/oss_requirements.yml b/molecule/common/requirements/oss_requirements.yml index 8c86ac9d..e1f75bcb 100644 --- a/molecule/common/requirements/oss_requirements.yml +++ b/molecule/common/requirements/oss_requirements.yml @@ -1,4 +1,4 @@ --- roles: - name: nginxinc.nginx - version: 0.21.3 + version: 0.25.0 diff --git a/molecule/common/requirements/plus_requirements.yml b/molecule/common/requirements/plus_requirements.yml index ae7018f1..d8ff981d 100644 --- a/molecule/common/requirements/plus_requirements.yml +++ b/molecule/common/requirements/plus_requirements.yml @@ -1,6 +1,7 @@ --- roles: - name: nginxinc.nginx - version: 0.21.3 - - name: nginxinc.nginx_app_protect - version: 0.7.0 + version: 0.25.0 + # - name: nginxinc.nginx_app_protect + # src: https://github.com/nginxinc/ansible-role-nginx-app-protect + # version: main diff --git a/molecule/complete/converge.yml b/molecule/complete/converge.yml new file mode 100644 index 00000000..69b198ca --- /dev/null +++ b/molecule/complete/converge.yml @@ -0,0 +1,893 @@ +--- +- name: Converge + hosts: all + tasks: + - name: Configure NGINX + ansible.builtin.include_role: + name: ansible-role-nginx-config + vars: + nginx_config_debug_output: true + + nginx_config_selinux: true + nginx_config_selinux_tcp_ports: + - 80 + + nginx_config_upload_enable: true + nginx_config_upload: + - src: ../common/files/snippets/modules.conf + dest: /etc/nginx/modules.conf + + nginx_config_upload_ssl_enable: true + nginx_config_upload_ssl_crt: + - src: ../common/files/ssl/molecule.crt + dest: /etc/ssl/certs + backup: true + nginx_config_upload_ssl_key: + - src: ../common/files/ssl/molecule.key + dest: /etc/ssl/private + backup: true + - src: ../common/files/ssl/rand.key + dest: /etc/ssl/private + backup: true + + nginx_config_main_template_enable: true + nginx_config_main_template: + template_file: nginx.conf.j2 + deployment_location: /etc/nginx/nginx.conf + backup: true + config: + main: + load_module: + - modules/ngx_http_js_module.so + user: + username: nginx + worker_cpu_affinity: + auto: true + worker_priority: 0 + worker_processes: auto + worker_rlimit_core: 10000 + worker_rlimit_nofile: 10000 + worker_shutdown_timeout: 30m + error_log: + - /var/log/nginx/ansible.log + - file: /var/log/nginx/molecule.log + - file: /var/log/nginx/error.log + level: notice + pid: /run/nginx.pid + daemon: true + debug_points: abort + env: + variable: PERL5LIB + value: /data/site/modules + lock_file: logs/nginx.lock + master_process: true + pcre_jit: false + thread_pool: + - name: default + threads: 32 + max_queue: 65536 + - name: molecule + threads: 32 + timer_resolution: 1s + working_directory: /etc/nginx + quic: + bpf: false + events: + accept_mutex: false + accept_mutex_delay: 500ms + multi_accept: false + use: epoll + worker_aio_requests: 32 + worker_connections: 512 + include: + - /etc/nginx/modules.conf + http: + include: + - /etc/nginx/conf.d/*.conf + - /etc/nginx/conf.d/backend/*.conf + stream: + include: + - /etc/nginx/conf.d/streams/*.conf + + nginx_config_status_enable: true + nginx_config_status_backup: true + nginx_config_status_port: 8080 + nginx_config_status_access_log: + path: /var/log/nginx/access.log + format: main + + nginx_config_http_template_enable: true + nginx_config_http_template: + - backup: true + config: + upstreams: + - name: frontend_servers + zone: + name: frontend_mem_zone + size: 64k + least_conn: true + keepalive: 32 + keepalive_requests: 100 + keepalive_timeout: 60s + servers: + - address: 0.0.0.0:8081 + weight: 1 + max_conns: 100 + max_fails: 3 + fail_timeout: 5s + backup: false + down: false + resolve: false + - name: backend_servers + zone: + name: backend_mem_zone + size: 64k + least_conn: true + servers: + - address: 0.0.0.0:8082 + weight: 1 + max_fails: 3 + fail_timeout: 5s + - address: unix:/var/run/control.unit.sock + weight: 1 + max_fails: 3 + fail_timeout: 5s + - address: 0.0.0.0:8083 + down: true + - address: 0.0.0.0:8084 + backup: true + core: + absolute_redirect: true + aio: + threads: true + aio_write: false + auth_delay: 0s + chunked_transfer_encoding: true + client_body_buffer_size: 8k + client_body_in_file_only: false + client_body_in_single_buffer: false + client_body_temp_path: + path: /var/cache/nginx/client + level: 2 + client_body_timeout: 60s + client_header_buffer_size: 1k + client_header_timeout: 60s + client_max_body_size: 1m + connection_pool_size: 256 + default_type: text/plain + directio: false + directio_alignment: 512 + disable_symlinks: + check: "on" + from: $document_root + error_page: + - code: + - 404 + response: 404 + uri: /404.html + etag: true + if_modified_since: exact + ignore_invalid_headers: true + internal: false + keepalive_disable: msie6 + keepalive_requests: 1000 + keepalive_time: 1h + keepalive_timeout: + timeout: 75s + header_timeout: 75s + large_client_header_buffers: + number: 4 + size: 8k + limit_rate: 0 + limit_rate_after: 0 + lingering_close: true + lingering_time: 30s + lingering_timeout: 5s + log_not_found: true + log_subrequest: false + max_ranges: 0 + merge_slashes: true + msie_padding: true + msie_refresh: false + open_file_cache: + max: 10 + inactive: 60s + open_file_cache_errors: false + open_file_cache_min_uses: 1 + open_file_cache_valid: 60s + output_buffers: + number: 2 + size: 32k + port_in_redirect: true + postpone_output: 1460 + read_ahead: 0 + recursive_error_pages: false + request_pool_size: 4k + reset_timedout_connection: false + resolver: + address: 127.0.0.1 + valid: 60s + ipv6: false + resolver_timeout: 30s + root: html + satisfy: all + send_timeout: 60s + sendfile: false + sendfile_max_chunk: 0 + server_name_in_redirect: false + server_names_hash_bucket_size: 32 + server_names_hash_max_size: 512 + server_tokens: true + subrequest_output_buffer_size: 4k + tcp_nodelay: true + tcp_nopush: false + types: + - mime: text/html + extensions: html + - mime: application/octet-stream + extensions: + - bin + - exe + - dll + types_hash_bucket_size: 64 + types_hash_max_size: 1024 + underscores_in_headers: false + variables_hash_bucket_size: 64 + variables_hash_max_size: 1024 + http2: + enable: true + body_preread_size: 128k + chunk_size: 8k + max_concurrent_streams: 31 + recv_buffer_size: 128k + recv_timeout: 10s + http3: + enable: true + hq: false + max_concurrent_streams: 100 + stream_buffer_size: 32k + ssl: + buffer_size: 16k + certificate: /etc/ssl/certs/molecule.crt + certificate_key: /etc/ssl/private/molecule.key + ciphers: + - HIGH + - "!aNull" + - "!MD5" + conf_command: Protocol TLSv1.2 + early_data: false + ecdh_curve: auto + ocsp: false + ocsp_cache: + name: cache1 + size: 1m + ocsp_responder: false + prefer_server_ciphers: false + protocols: + - TLSv1 + - TLSv1.1 + - TLSv1.2 + - TLSv1.3 + reject_handshake: false + session_cache: + builtin: + enable: true + size: 20480 + session_tickets: true + session_timeout: 5m + stapling: false + stapling_verify: false + verify_client: false + verify_depth: 1 + proxy: + bind: false + buffer_size: 4k + buffering: true + buffers: + number: 8 + size: 4k + busy_buffers_size: 8k + cache: false + cache_background_update: false + cache_bypass: $cookie_test + cache_convert_head: true + cache_key: $scheme$proxy_host$request_uri + cache_lock: false + cache_lock_age: 5s + cache_lock_timeout: 5s + cache_max_range_offset: 1 + cache_methods: + - GET + - HEAD + cache_min_uses: 1 + cache_path: + - path: /var/cache/nginx/proxy/frontend + levels: "1:1" + use_temp_path: false + inactive: 10m + keys_zone: + name: frontend_proxy_cache + size: 10m + max_size: 2g + min_free: 1g + manager_files: 100 + manager_sleep: 500ms + manager_threshold: 200ms + loader_files: 100 + loader_sleep: 50ms + loader_threshold: 200ms + - path: /var/cache/nginx/proxy/backend + levels: "1:2" + use_temp_path: true + keys_zone: + name: backend_proxy_cache + size: 10m + inactive: 60m + max_size: 10g + cache_revalidate: false + cache_use_stale: false + cache_valid: + - code: 200 + time: 10m + - code: + - 201 + - 202 + time: 10m + - time: 1m + - 2m + connect_timeout: 60s + cookie_domain: + - domain: localhost + replacement: example.com + cookie_flags: false + cookie_path: + path: $uri + replacement: $uri + force_ranges: false + headers_hash_bucket_size: 64 + headers_hash_max_size: 512 + hide_header: + - Date + - X-Accel-Redirect + http_version: '1.1' + ignore_client_abort: false + ignore_headers: + - X-Accel-Redirect + intercept_errors: false + limit_rate: 0 + max_temp_file_size: 1024m + method: GET + next_upstream: + - error + - timeout + next_upstream_timeout: 0 + next_upstream_tries: 0 + no_cache: + - $cookie_nocache + - $arg_nocache$arg_comment + pass_header: + - Date + - X-Accel-Redirect + pass_request_body: false + pass_request_headers: true + read_timeout: 60s + redirect: false + request_buffering: false + send_timeout: 60s + set_body: body + set_header: + - field: Host + value: $proxy_host + - field: Connection + value: close + socket_keepalive: false + ssl_certificate: /etc/ssl/certs/molecule.crt + ssl_certificate_key: /etc/ssl/private/molecule.key + ssl_ciphers: HIGH + ssl_conf_command: + - Protocol TLSv1.2 + ssl_name: $proxy_host + ssl_protocols: TLSv1.2 + ssl_server_name: false + ssl_session_reuse: true + ssl_verify: false + ssl_verify_depth: 1 + store: false + store_access: + user: rw + group: rw + all: r + temp_file_write_size: 8k + temp_path: + path: /var/cache/nginx/proxy + level: 2 + grpc: + bind: + address: $remote_addr + transparent: false + buffer_size: 4k + connect_timeout: 60s + hide_header: X-Accel-Redirect + ignore_headers: X-Accel-Redirect + intercept_errors: false + next_upstream: timeout + next_upstream_timeout: 0 + next_upstream_tries: 0 + pass_header: X-Accel-Charset + read_timeout: 60s + send_timeout: 60s + set_header: + field: Accept-Encoding + value: '""' + socket_keepalive: false + ssl_certificate: /etc/ssl/certs/molecule.crt + ssl_certificate_key: /etc/ssl/private/molecule.key + ssl_ciphers: HIGH + ssl_conf_command: Protocol TLSv1.2 + ssl_name: $proxy_host + ssl_protocols: TLSv1.2 + ssl_server_name: false + ssl_session_reuse: true + ssl_verify: false + ssl_verify_depth: 1 + access: + allow: + - all + deny: + - 192.168.1.66 + auth_basic: + realm: molecule + auth_request: + uri: false + set: + variable: $temp + value: auth + autoindex: + enable: true + exact_size: true + format: html + localtime: true + gunzip: + enable: true + buffers: + number: 32 + size: 4k + gzip: + enable: true + buffers: + number: 32 + size: 4k + comp_level: 1 + disable: + - '"msie6"' + http_version: '1.1' + min_length: 20 + proxied: + - expired + static: always + types: + - text/html + vary: false + headers: + add_headers: + - name: Strict-Transport-Security + value: '"max-age=15768000; includeSubDomains"' + always: true + add_trailers: + name: Strict-Transport-Security + value: '"max-age=15768000; includeSubDomains"' + always: false + expires: + modified: true + time: 12h + limit_req: + limit_reqs: + - zone: one + burst: 5 + delay: false + dry_run: false + log_level: info + status: 503 + zones: + - key: $binary_remote_addr + name: one + size: 1m + rate: 10r/s + log: + access: + - path: /var/log/nginx/access.log + format: main + buffer: 1m + gzip: 5 + flush: 10h + if: $status + format: + - name: main + format: | + '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"' + error_log: + file: /var/log/nginx/error.log + level: notice + open_log_file_cache: + max: 1000 + inactive: 20s + min_uses: 2 + valid: 1m + map: + hash_bucket_size: 128 + hash_max_size: 4096 + mappings: + - string: $http_host + variable: $name + hostnames: true + volatile: true + content: + - value: example.com + new_value: 1 + - string: $http_user_agent + variable: $isblockaccess_ua + content: + - value: default + new_value: 0 + - value: '"~jndi:ldap"' + new_value: 1 + realip: + set_real_ip_from: 0.0.0.0 + real_ip_header: X-Real-IP + real_ip_recursive: false + rewrite: + log: false + uninitialized_variable_warn: false + split_clients: + string: $remote_addr + variable: $upstream_split + content: + - percentage: 20% + value: appv2 + - percentage: "*" + value: app + sub_filter: + sub_filters: + - string: server_hostname + replacement: $hostname + last_modified: false + once: false + types: text/json + custom_directives: + - server {} + servers: + - core: + aio: + threads: default + keepalive_timeout: 75s + listen: + - address: 0.0.0.0 + port: 80 + default_server: true + ssl: false + proxy_protocol: false + fastopen: 12 + backlog: 511 + rcvbuf: 512 + sndbuf: 512 + deffered: false + bind: false + ipv6only: false + reuseport: false + so_keepalive: false + - address: 0.0.0.0 + port: 443 + default_server: true + ssl: false + quic: true + reuseport: true + - address: "[::]" + port: 80 + default_server: true + ssl: false + so_keepalive: + keepidle: 30m + keepintvl: 5 + keepcnt: 10 + open_file_cache: false + server_name: localhost + try_files: + files: $uri + uri: /images/default.gif + http2: + enable: false + chunk_size: 8k + http3: + enable: false + hq: true + quic: + active_connection_id_limit: 10 + gso: false + retry: false + host_key: /etc/ssl/private/rand.key + auth_basic: + realm: false + log: + access: + - path: /var/log/nginx/access.log + format: main + rewrite: + break: true + rewrites: + - regex: (.*).html(.*) + replacement: $1$2 + flag: last + log: false + set: + - variable: $var + value: var + uninitialized_variable_warn: false + locations: + - location: / + core: + alias: / + limit_except: + method: GET + directive: allow all + mirror: + uri: /mirror + proxy: + pass: http://frontend_servers/ + - location: /backend + proxy: + pass: http://backend_servers/ + - location: /mirror + internal: true + proxy: + pass: http://127.0.0.1/ + - template_file: http/default.conf.j2 + deployment_location: /etc/nginx/conf.d/frontend_default.conf + config: + servers: + - core: + listen: + - port: 8081 + server_name: localhost + log: + access: false + autoindex: + enable: false + sub_filter: + sub_filters: + - string: server_hostname + replacement: $hostname + - string: server_address + replacement: $server_addr:$server_port + - string: server_url + replacement: $request_uri + - string: remote_addr + replacement: $remote_addr:$remote_port + - string: server_date + replacement: $time_local + - string: client_browser + replacement: $http_user_agent + - string: request_id + replacement: $request_id + - string: nginx_version + replacement: $nginx_version + - string: document_root + replacement: $document_root + - string: proxied_for_ip + replacement: $http_x_forwarded_for + last_modified: false + once: false + locations: + - location: / + core: + index: frontend_index.html + root: /usr/share/nginx/html + http2: + chunk_size: 10k + - location: /alias + core: + alias: /usr/share/nginx/html + index: frontend_index.html + - location: /return + rewrite: + return: + code: 200 + text: molecule + - template_file: http/default.conf.j2 + deployment_location: /etc/nginx/conf.d/backend/backend_default.conf + config: + servers: + - core: + listen: + - port: 8082 + server_name: localhost + autoindex: + enable: false + sub_filter: + sub_filters: + - string: server_hostname + replacement: $hostname + - string: server_address + replacement: $server_addr:$server_port + - string: server_url + replacement: $request_uri + - string: remote_addr + replacement: $remote_addr:$remote_port + - string: server_date + replacement: $time_local + - string: client_browser + replacement: $http_user_agent + - string: request_id + replacement: $request_id + - string: nginx_version + replacement: $nginx_version + - string: document_root + replacement: $document_root + - string: proxied_for_ip + replacement: $http_x_forwarded_for + last_modified: false + once: false + locations: + - location: / + core: + index: backend_index.html + root: /usr/share/nginx/html + - location: /stub_status + stub_status: true + - location: ~ \.php$ + core: + root: /usr/share/nginx/html + custom_directives: + - fastcgi_split_path_info ^(.+\.php)(/.+)$; + - fastcgi_pass unix:/run/php/php7.2-fpm.sock; + - fastcgi_index index.php; + - include fastcgi_params; + - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + + nginx_config_html_demo_template_enable: true + nginx_config_html_demo_template: + - template_file: www/index.html.j2 + deployment_location: /usr/share/nginx/html/frontend_index.html + backup: true + web_server_name: Frontend + - template_file: www/index.html.j2 + deployment_location: /usr/share/nginx/html/backend_index.html + backup: true + web_server_name: Backend + + nginx_config_stream_template_enable: true + nginx_config_stream_template: + - template_file: stream/default.conf.j2 + deployment_location: /etc/nginx/conf.d/streams/stream_default.conf + backup: true + config: + upstreams: + - name: stream_upstream + zone: + name: stream_zone + size: 64k + least_conn: true + servers: + - address: 0.0.0.0:9091 + weight: 1 + max_conns: 100 + max_fails: 3 + fail_timeout: 5s + backup: false + down: false + resolve: false + core: + preread_buffer_size: 16k + preread_timeout: 30s + proxy_protocol_timeout: 30s + resolver_timeout: 30s + tcp_nodelay: true + variables_hash_bucket_size: 64 + variables_hash_max_size: 1024 + ssl: + alpn: http/1.1 + certificate: /etc/ssl/certs/molecule.crt + certificate_key: /etc/ssl/private/molecule.key + ciphers: + - HIGH + - "!aNull" + - "!MD5" + conf_command: Protocol TLSv1.2 + ecdh_curve: auto + handshake_timeout: 60s + prefer_server_ciphers: false + protocols: + - TLSv1 + - TLSv1.1 + - TLSv1.2 + session_cache: + builtin: + enable: true + size: 20480 + session_tickets: true + session_timeout: 5m + verify_client: false + verify_depth: 1 + proxy: + bind: false + buffer_size: 4k + connect_timeout: 60s + download_rate: 0 + half_close: false + next_upstream: true + next_upstream_timeout: 0 + next_upstream_tries: 0 + protocol: false + requests: 0 + responses: 0 + # session_drop: false # Only NGINX Plus + ssl: false + ssl_certificate: /etc/ssl/certs/molecule.crt + ssl_certificate_key: /etc/ssl/private/molecule.key + ssl_ciphers: HIGH + ssl_conf_command: + - Protocol TLSv1.2 + ssl_name: $hostname + ssl_protocols: TLSv1.2 + ssl_server_name: false + ssl_session_reuse: true + ssl_verify: false + ssl_verify_depth: 1 + timeout: 10m + upload_rate: 0 + log: + access: + - path: /var/log/nginx/access_stream.log + format: main + buffer: 1m + gzip: 5 + flush: 10h + if: $status + format: + - name: main + format: | + '$remote_addr - [$time_local] $status ' + error_log: + file: /var/log/nginx/error_stream.log + level: notice + open_log_file_cache: + max: 1000 + inactive: 20s + min_uses: 2 + valid: 1m + map: + hash_bucket_size: 128 + hash_max_size: 4096 + mappings: + - string: $hostname + variable: $stream_name + hostnames: true + volatile: true + content: + - value: example.com + new_value: 3 + - string: $host + variable: $isblockaccess_ua + content: + - value: default + new_value: 0 + - value: '"~jndi:ldap"' + new_value: 2 + servers: + - core: + listen: + - address: 0.0.0.0 + port: 9090 + ssl: false + proxy_protocol: false + fastopen: 12 + backlog: 511 + rcvbuf: 512 + sndbuf: 512 + bind: false + ipv6only: false + reuseport: false + so_keepalive: false + proxy: + pass: stream_upstream diff --git a/molecule/complete/molecule.yml b/molecule/complete/molecule.yml new file mode 100644 index 00000000..813c8240 --- /dev/null +++ b/molecule/complete/molecule.yml @@ -0,0 +1,51 @@ +--- +dependency: + name: galaxy + options: + role-file: molecule/common/requirements/oss_requirements.yml +driver: + name: docker +lint: | + set -e + ansible-lint --force-color +platforms: + - name: alpine-3.19 + image: alpine:3.19 + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /sbin/init + - name: debian-bullseye + image: debian:bullseye-slim + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /sbin/init + - name: rhel-9 + image: redhat/ubi9:9.4 + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /usr/sbin/init + - name: ubuntu-jammy + image: ubuntu:jammy + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /sbin/init +provisioner: + name: ansible + playbooks: + prepare: prepare.yml + converge: converge.yml + verify: verify.yml + env: + ANSIBLE_ROLES_PATH: ~/.cache/molecule/ansible-role-nginx-config/${MOLECULE_SCENARIO_NAME}/roles:${MOLECULE_PROJECT_DIRECTORY}/..:~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles diff --git a/molecule/complete/prepare.yml b/molecule/complete/prepare.yml new file mode 100644 index 00000000..3abc5b44 --- /dev/null +++ b/molecule/complete/prepare.yml @@ -0,0 +1,11 @@ +--- +- name: Prepare + hosts: all + tasks: + - name: Install NGINX + ansible.builtin.include_role: + name: nginxinc.nginx + vars: + nginx_modules: + - njs + - perl diff --git a/molecule/complete/verify.yml b/molecule/complete/verify.yml new file mode 100644 index 00000000..349d6e58 --- /dev/null +++ b/molecule/complete/verify.yml @@ -0,0 +1,107 @@ +--- +- name: Verify + hosts: all + tasks: + - name: Check if NGINX is installed + ansible.builtin.package: + name: nginx + state: present + check_mode: true + register: install + failed_when: (install is changed) or (install is failed) + + - name: Check if NGINX service is running + ansible.builtin.service: + name: nginx + state: started + enabled: true + check_mode: true + register: service + failed_when: (service is changed) or (service is failed) + + - name: Check that a page returns a status 200 and fail if the words Hello World are not in the page contents + ansible.builtin.uri: + url: http://localhost + return_content: true + register: this + failed_when: "'Hello World' not in this['content']" + + - name: Check client body cache directory exists + ansible.builtin.stat: + path: /var/cache/nginx/client + check_mode: true + register: stat_result + failed_when: not stat_result['stat']['exists'] | bool + + - name: Check proxy cache directory exists + ansible.builtin.stat: + path: /var/cache/nginx/proxy + check_mode: true + register: stat_result + failed_when: not stat_result['stat']['exists'] | bool + + - name: Check default.conf exists + ansible.builtin.stat: + path: /etc/nginx/conf.d/default.conf + check_mode: true + register: stat_result + failed_when: not stat_result['stat']['exists'] | bool + + - name: Check frontend_default.conf exists + ansible.builtin.stat: + path: /etc/nginx/conf.d/frontend_default.conf + check_mode: true + register: stat_result + failed_when: not stat_result['stat']['exists'] | bool + + - name: Check backend_default.conf exists + ansible.builtin.stat: + path: /etc/nginx/conf.d/backend/backend_default.conf + check_mode: true + register: stat_result + failed_when: not stat_result['stat']['exists'] | bool + + - name: Ensure default.conf contains 'location /' + ansible.builtin.lineinfile: + path: /etc/nginx/conf.d/default.conf + line: " location / {" + state: present + check_mode: true + register: conf + failed_when: (conf is changed) or (conf is failed) + + - name: Ensure frontend_default.conf contains 'alias directive' + ansible.builtin.lineinfile: + path: /etc/nginx/conf.d/frontend_default.conf + line: " alias /usr/share/nginx/html;" + state: present + check_mode: true + register: conf + failed_when: (conf is changed) or (conf is failed) + + - name: Ensure default.conf contains 'location /backend' + ansible.builtin.lineinfile: + path: /etc/nginx/conf.d/default.conf + line: " location /backend {" + state: present + check_mode: true + register: conf + failed_when: (conf is changed) or (conf is failed) + + - name: Ensure default.conf contains 'client_max_body_size 1m;' + ansible.builtin.lineinfile: + path: /etc/nginx/conf.d/default.conf + line: client_max_body_size 1m; + state: present + check_mode: true + register: conf + failed_when: (conf is changed) or (conf is failed) + + - name: Ensure default.conf contains 'rewrite (.*).html(.*) $1$2 last;' + ansible.builtin.lineinfile: + path: /etc/nginx/conf.d/default.conf + line: " rewrite (.*).html(.*) $1$2 last;" + state: present + check_mode: true + register: conf + failed_when: (conf is changed) or (conf is failed) diff --git a/molecule/plus/converge.yml b/molecule/complete_plus/converge.yml similarity index 65% rename from molecule/plus/converge.yml rename to molecule/complete_plus/converge.yml index 557bf13a..8a0c5dfa 100644 --- a/molecule/plus/converge.yml +++ b/molecule/complete_plus/converge.yml @@ -3,7 +3,7 @@ hosts: all tasks: - name: Configure NGINX - include_role: + ansible.builtin.include_role: name: ansible-role-nginx-config vars: nginx_config_debug_output: true @@ -22,15 +22,15 @@ deployment_location: /etc/nginx/nginx.conf config: main: - load_module: - - modules/ngx_http_app_protect_module.so - - modules/ngx_http_app_protect_dos_module.so + # load_module: + # - modules/ngx_http_app_protect_module.so + # - modules/ngx_http_app_protect_dos_module.so user: nginx worker_processes: auto error_log: - file: /var/log/nginx/error.log level: notice - pid: /var/run/nginx.pid + pid: /run/nginx.pid worker_rlimit_nofile: 2048 events: worker_connections: 1024 @@ -42,6 +42,7 @@ - /etc/nginx/conf.d/stream/*.conf nginx_config_rest_api_enable: true + nginx_config_rest_api_backup: true nginx_config_rest_api_write: true nginx_config_rest_api_access_log: path: /var/log/nginx/access.log @@ -150,16 +151,27 @@ core: default_type: application/octet-stream keepalive_timeout: 65s - app_protect_waf: - physical_memory_util_thresholds: - high: 100 - low: 100 - cpu_thresholds: - high: 100 - low: 100 - failure_mode_action: pass - cookie_seed: testseed - compressed_requests_action: drop + # app_protect_waf: + # physical_memory_util_thresholds: + # high: 100 + # low: 100 + # cpu_thresholds: + # high: 100 + # low: 100 + # failure_mode_action: pass + # cookie_seed: testseed + # compressed_requests_action: drop + # app_protect_dos: + # liveliness: + # enable: true + # uri: /app_protect_dos_liveliness + # port: 8090 + # readiness: + # enable: true + # uri: /app_protect_dos_readiness + # port: 8090 + # arb_fqdn: 192.168.1.10 + # accelerated_mitigation: false grpc: bind: address: $remote_addr @@ -183,6 +195,11 @@ - field: Accept-Encoding value: '""' socket_keepalive: false + gunzip: + enable: true + buffers: + number: 32 + size: 4k gzip: enable: true buffers: @@ -191,10 +208,11 @@ comp_level: 1 disable: - '"msie6"' - http_version: 1.1 + http_version: '1.1' min_length: 20 proxied: - expired + static: false vary: false auth_jwt: enable: false @@ -207,7 +225,9 @@ name: info leeway: 0s type: nested - require: jwt + require: + values: $jwt_claim_iss + error: 403 auth_request: uri: false set: @@ -248,7 +268,7 @@ always: true expires: modified: true - time: "12h" + time: 12h limit_req: limit_reqs: - zone: one @@ -277,9 +297,40 @@ inactive: 20s min_uses: 2 valid: 1m + map: + hash_bucket_size: 128 + hash_max_size: 4096 + mappings: + - string: $http_host + variable: $name + hostnames: true + volatile: true + content: + - value: example.com + new_value: 1 + - string: $http_user_agent + variable: $isblockaccess_ua + content: + - value: default + new_value: 0 + - value: '"~jndi:ldap"' + new_value: 1 + realip: + set_real_ip_from: + - 0.0.0.0 + real_ip_header: X-Real-IP + real_ip_recursive: false rewrite: log: false uninitialized_variable_warn: false + split_clients: + string: $remote_addr + variable: $upstream_split + content: + - percentage: 20% + value: appv2 + - percentage: "*" + value: app sub_filter: sub_filters: - string: server_hostname @@ -302,26 +353,26 @@ default_server: true server_name: localhost client_max_body_size: 512k - app_protect_waf: - enable: true - policy_file: /etc/app_protect/conf/NginxDefaultPolicy.json - security_log_enable: true - security_log: - - path: /etc/app_protect/conf/log_default.json - dest: syslog:server=10.1.1.1:514 - - path: /etc/app_protect/conf/log_default.json - dest: syslog:server=10.1.1.2:514 - app_protect_dos: - enable: true - policy_file: /etc/app_protect/conf/BADOSDefaultPolicy.json - security_log_enable: true - security_log: - path: /etc/app_protect_dos/log-default.json - dest: syslog:server=10.1.1.1:514 - monitor: - uri: http://10.1.1.1:5000/monitor - protocol: http2 - timeout: 10 + # app_protect_waf: + # enable: true + # policy_file: /etc/app_protect/conf/NginxDefaultPolicy.json + # security_log_enable: true + # security_log: + # - path: /etc/app_protect/conf/log_default.json + # dest: syslog:server=10.1.1.1:514 + # - path: /etc/app_protect/conf/log_default.json + # dest: syslog:server=10.1.1.2:514 + # app_protect_dos: + # enable: true + # policy_file: /etc/app_protect/conf/BADOSDefaultPolicy.json + # security_log_enable: true + # security_log: + # path: /etc/app_protect_dos/log-default.json + # dest: syslog:server=10.1.1.1:514 + # monitor: + # uri: http://10.1.1.1:5000/monitor + # protocol: http2 + # timeout: 10 auth_jwt: enable: realm: realm @@ -341,23 +392,24 @@ format: main locations: - location: / - app_protect_waf: - enable: true - policy_file: /etc/app_protect/conf/NginxDefaultPolicy.json - security_log_enable: true - security_log: - - path: /etc/app_protect/conf/log_default.json - dest: syslog:server=10.1.1.1:514 - - path: /etc/app_protect/conf/log_default.json - dest: syslog:server=10.1.1.2:514 - app_protect_dos: - enable: true - policy_file: /etc/app_protect/conf/BADOSDefaultPolicy.json - security_log_enable: true - security_log: - path: /etc/app_protect_dos/log-default.json - dest: syslog:server=10.1.1.1:514 - monitor: http://10.1.1.1:5000/monitor + # app_protect_waf: + # enable: true + # policy_file: /etc/app_protect/conf/NginxDefaultPolicy.json + # security_log_enable: true + # security_log: + # - path: /etc/app_protect/conf/log_default.json + # dest: syslog:server=10.1.1.1:514 + # - path: /etc/app_protect/conf/log_default.json + # dest: syslog:server=10.1.1.2:514 + # app_protect_dos: + # enable: true + # policy_file: /etc/app_protect/conf/BADOSDefaultPolicy.json + # security_log_enable: true + # security_log: + # path: /etc/app_protect_dos/log-default.json + # dest: syslog:server=10.1.1.1:514 + # monitor: http://10.1.1.1:5000/monitor + # api: true auth_jwt: enable: false leeway: 0s @@ -380,6 +432,7 @@ persistent: false match: nginx port: 80 + keepalive_time: 0 proxy: bind: false buffer_size: 4k @@ -426,7 +479,7 @@ hide_header: - Date - X-Accel-Redirect - http_version: 1.1 + http_version: '1.1' ignore_client_abort: false ignore_headers: - X-Accel-Redirect @@ -488,6 +541,8 @@ last_modified: false once: true - location: /backend + mirror: + uri: /mirror proxy_pass: http://backend_servers/ proxy: set_header: @@ -499,6 +554,10 @@ value: $proxy_add_x_forwarded_for - field: X-Forwarded-Proto value: $scheme + - location: /mirror + internal: true + proxy: + pass: http://127.0.0.1/ - template_file: http/default.conf.j2 deployment_location: /etc/nginx/conf.d/frontend_default.conf config: @@ -516,7 +575,7 @@ - string: server_url replacement: $request_uri - string: remote_addr - replacement: '$remote_addr:$remote_port' + replacement: $remote_addr:$remote_port - string: server_date replacement: $time_local - string: client_browser @@ -556,7 +615,7 @@ - string: server_url replacement: $request_uri - string: remote_addr - replacement: '$remote_addr:$remote_port' + replacement: $remote_addr:$remote_port - string: server_date replacement: $time_local - string: client_browser @@ -587,44 +646,174 @@ nginx_config_html_demo_template_enable: true nginx_config_html_demo_template: - template_file: www/index.html.j2 - html_file_name: frontend_index.html - html_file_location: /usr/share/nginx/html + deployment_location: /usr/share/nginx/html/frontend_index.html web_server_name: Frontend - template_file: www/index.html.j2 - html_file_name: backend_index.html - html_file_location: /usr/share/nginx/html + deployment_location: /usr/share/nginx/html/backend_index.html web_server_name: Backend nginx_config_stream_template_enable: true nginx_config_stream_template: - template_file: stream/default.conf.j2 - conf_file_name: stream_default.conf - conf_file_location: /etc/nginx/conf.d/stream - network_streams: - - listen: - - ip: 0.0.0.0 - port: 9090 - opts: - - udp - proxy_pass: backend - proxy_timeout: 3s - proxy_connect_timeout: 1s - proxy_protocol: false - health_check_plus: false - upstreams: - - name: backend - lb_method: least_conn - zone_name: backend - zone_size: 64k - sticky_cookie: false - servers: - - address: 0.0.0.0 - port: 9091 - weight: 1 - health_check: max_fails=1 fail_timeout=10s - - address: 0.0.0.0 - port: 9092 - down: true - - address: 0.0.0.0 - port: 9093 - backup: true + deployment_location: /etc/nginx/conf.d/streams/stream_default.conf + backup: true + config: + upstreams: + - name: stream_upstream + servers: + - address: 0.0.0.0:9091 + weight: 1 + max_conns: 100 + max_fails: 3 + fail_timeout: 5s + backup: false + down: false + resolve: false + zone: + name: stream_zone + size: 64k + least_conn: true + core: + preread_buffer_size: 16k + preread_timeout: 30s + proxy_protocol_timeout: 30s + resolver_timeout: 30s + tcp_nodelay: true + variables_hash_bucket_size: 64 + variables_hash_max_size: 1024 + ssl: + alpn: http/1.1 + certificate: /etc/ssl/certs/molecule.crt + certificate_key: /etc/ssl/private/molecule.key + ciphers: + - HIGH + - "!aNull" + - "!MD5" + conf_command: Protocol TLSv1.2 + ecdh_curve: auto + handshake_timeout: 60s + prefer_server_ciphers: false + protocols: + - TLSv1 + - TLSv1.1 + - TLSv1.2 + session_cache: + builtin: + enable: true + size: 20480 + session_tickets: true + session_timeout: 5m + verify_client: false + verify_depth: 1 + proxy: + bind: false + buffer_size: 4k + connect_timeout: 60s + download_rate: 0 + half_close: false + next_upstream: true + next_upstream_timeout: 0 + next_upstream_tries: 0 + protocol: false + requests: 0 + responses: 0 + session_drop: false + socket_keepalive: false + ssl: false + ssl_certificate: /etc/ssl/certs/molecule.crt + ssl_certificate_key: /etc/ssl/private/molecule.key + ssl_ciphers: HIGH + ssl_conf_command: + - Protocol TLSv1.2 + ssl_name: $hostname + ssl_protocols: TLSv1.2 + ssl_server_name: false + ssl_session_reuse: true + ssl_verify: false + ssl_verify_depth: 1 + timeout: 10m + upload_rate: 0 + health_check: + match: + - name: nginx_stream + conditions: + - status 200 + timeout: 60s + keyval: + keyvals: + - key: $arg_text + variable: $text + zone: key_stream + zones: + - name: key_stream + size: 10m + state: /var/lib/nginx/state/key.keyval + timeout: 2h + type: string + sync: false + log: + access: + - path: /var/log/nginx/access_stream.log + format: main + buffer: 1m + gzip: 5 + flush: 10h + if: $status + format: + - name: main + format: | + '$remote_addr - [$time_local] $status ' + error_log: + file: /var/log/nginx/error_stream.log + level: notice + open_log_file_cache: + max: 1000 + inactive: 20s + min_uses: 2 + valid: 1m + map: + hash_bucket_size: 128 + hash_max_size: 4096 + mappings: + - string: $hostname + variable: $stream_name + hostnames: true + volatile: true + content: + - value: example.com + new_value: 3 + - string: $host + variable: $isblockaccess_ua + content: + - value: default + new_value: 0 + - value: '"~jndi:ldap"' + new_value: 2 + servers: + - core: + listen: + - address: 0.0.0.0 + port: 9090 + ssl: false + proxy_protocol: false + fastopen: 12 + backlog: 511 + rcvbuf: 512 + sndbuf: 512 + bind: false + ipv6only: false + reuseport: false + so_keepalive: false + proxy: + pass: stream_upstream + health_check: + health_checks: + - interval: 5 + jitter: 0 + fails: 1 + passes: 1 + uri: / + mandatory: false + persistent: false + match: nginx_stream + udp: true diff --git a/molecule/complete_plus/molecule.yml b/molecule/complete_plus/molecule.yml new file mode 100644 index 00000000..63ac8f64 --- /dev/null +++ b/molecule/complete_plus/molecule.yml @@ -0,0 +1,37 @@ +--- +dependency: + name: galaxy + options: + role-file: molecule/common/requirements/plus_requirements.yml +driver: + name: docker +lint: | + set -e + ansible-lint --force-color +platforms: + - name: rhel-8 + image: redhat/ubi9:9.4 + platform: x86_64 + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /usr/sbin/init + - name: ubuntu-jammy + image: ubuntu:jammy + platform: x86_64 + dockerfile: ../common/Dockerfile.j2 + privileged: true + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /sbin/init +provisioner: + name: ansible + playbooks: + prepare: prepare.yml + converge: converge.yml + verify: verify.yml + env: + ANSIBLE_ROLES_PATH: ~/.cache/molecule/ansible-role-nginx-config/${MOLECULE_SCENARIO_NAME}/roles:${MOLECULE_PROJECT_DIRECTORY}/..:~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles diff --git a/molecule/complete_plus/prepare.yml b/molecule/complete_plus/prepare.yml new file mode 100644 index 00000000..1f7f41a7 --- /dev/null +++ b/molecule/complete_plus/prepare.yml @@ -0,0 +1,50 @@ +--- +- name: Prepare + hosts: localhost + gather_facts: false + tasks: + - name: Create ephemeral license certificate file from b64 decoded env var + ansible.builtin.copy: + content: "{{ lookup('env', 'NGINX_CRT') | b64decode }}" + dest: ../common/files/license/nginx-repo.crt + force: false + mode: "0444" + + - name: Create ephemeral license key file from b64 decoded env var + ansible.builtin.copy: + content: "{{ lookup('env', 'NGINX_KEY') | b64decode }}" + dest: ../common/files/license/nginx-repo.key + force: false + mode: "0444" + + - name: Create ephemeral license JWT file from b64 encoded env var + ansible.builtin.copy: + content: "{{ lookup('env', 'NGINX_JWT') }}" + dest: ../common/files/license/license.jwt + force: false + mode: "0444" + +- name: Install NGINX Plus + hosts: all + tasks: + - name: Install NGINX Plus + ansible.builtin.include_role: + name: nginxinc.nginx + vars: + nginx_type: plus + nginx_license: + certificate: ../common/files/license/nginx-repo.crt + key: ../common/files/license/nginx-repo.key + jwt: ../common/files/license/license.jwt + nginx_remove_license: false + + # - name: Install NGINX App Protect WAF + # ansible.builtin.include_role: + # name: nginxinc.nginx_app_protect + # vars: + # nginx_app_protect_waf_enable: true + # nginx_app_protect_dos_enable: true + # nginx_app_protect_setup_license: false + # nginx_app_protect_remove_license: false + # nginx_app_protect_install_signatures: false + # nginx_app_protect_install_threat_campaigns: false diff --git a/molecule/plus/verify.yml b/molecule/complete_plus/verify.yml similarity index 53% rename from molecule/plus/verify.yml rename to molecule/complete_plus/verify.yml index 2c2a5fdc..97fab665 100644 --- a/molecule/plus/verify.yml +++ b/molecule/complete_plus/verify.yml @@ -3,7 +3,7 @@ hosts: all tasks: - name: Check if NGINX Plus is installed - package: + ansible.builtin.package: name: nginx-plus state: present check_mode: true @@ -11,7 +11,7 @@ failed_when: (install is changed) or (install is failed) - name: Check if NGINX service is running - service: + ansible.builtin.service: name: nginx state: started enabled: true @@ -19,52 +19,52 @@ register: service failed_when: (service is changed) or (service is failed) - - name: Functional tests - block: - - name: Check that a page returns a status 200 and fail if the words Hello World are not in the page contents - uri: - url: "http://localhost" - return_content: true - register: this - failed_when: "'Hello World' not in this.content" + # - name: Functional tests + # when: ansible_facts['os_family'] != 'Alpine' + # block: + # - name: Check that a page returns a status 200 and fail if the words Hello World are not in the page contents + # ansible.builtin.uri: + # url: http://localhost + # return_content: true + # register: this + # failed_when: "'Hello World' not in this['content']" - - name: Check that a page returns a status 200 and fail if the words Request Rejected are not in the page contents - uri: - url: "http://localhost/?v=