diff --git a/roles/nginx/.ansible-lint b/roles/nginx/.ansible-lint new file mode 100644 index 0000000..f865478 --- /dev/null +++ b/roles/nginx/.ansible-lint @@ -0,0 +1,16 @@ +--- +profile: production +strict: true + +# Enable checking of loop variable prefixes in roles +loop_var_prefix: "^(__|{role}_)" + +skip_list: + - var-naming[no-role-prefix] + +warn_list: + - role-name[path] + - var-naming[no-role-prefix] + +exclude_paths: + - .github/ diff --git a/roles/nginx/.gitignore b/roles/nginx/.gitignore new file mode 100644 index 0000000..8cd0df3 --- /dev/null +++ b/roles/nginx/.gitignore @@ -0,0 +1,2 @@ +.vscode +.idea \ No newline at end of file diff --git a/roles/nginx/.yamllint b/roles/nginx/.yamllint new file mode 100644 index 0000000..611db54 --- /dev/null +++ b/roles/nginx/.yamllint @@ -0,0 +1,8 @@ +--- +rules: + brackets: + forbid: false + min-spaces-inside: 0 + max-spaces-inside: 2 + min-spaces-inside-empty: -1 + max-spaces-inside-empty: 2 diff --git a/roles/nginx/README.md b/roles/nginx/README.md new file mode 100644 index 0000000..9ce29f0 --- /dev/null +++ b/roles/nginx/README.md @@ -0,0 +1,37 @@ +ansible-nginx +========= + +Deploy NGINX with a minimal configuration. + +Requirements +------------ + +None + +Role Variables +-------------- + +None + +Dependencies +------------ + +None + +Example Playbook +---------------- + +```yaml +roles: + - role: genlab.nginx +``` + +License +------- + +BSD + +Author Information +------------------ + +corvus-migratorius@proton.me diff --git a/roles/nginx/conda.dev.yml b/roles/nginx/conda.dev.yml new file mode 100644 index 0000000..2b3ef23 --- /dev/null +++ b/roles/nginx/conda.dev.yml @@ -0,0 +1,11 @@ +--- +name: ansible-nginx +channels: + - conda-forge +dependencies: + - python~=3.12.0 + - pip>=24.2 + - actionlint + - pip: + - -r requirements.txt + - -r requirements.ci.txt diff --git a/roles/nginx/conda.prod.yml b/roles/nginx/conda.prod.yml new file mode 100644 index 0000000..e401511 --- /dev/null +++ b/roles/nginx/conda.prod.yml @@ -0,0 +1,9 @@ +--- +name: ansible-nginx +channels: + - conda-forge +dependencies: + - python~=3.12.0 + - pip>=24.2 + - pip: + - -r requirements.txt diff --git a/roles/nginx/defaults/main.yml b/roles/nginx/defaults/main.yml new file mode 100644 index 0000000..b9f6c1f --- /dev/null +++ b/roles/nginx/defaults/main.yml @@ -0,0 +1,2 @@ +--- +nginx_version: "1.26.3" diff --git a/roles/nginx/handlers/main.yml b/roles/nginx/handlers/main.yml new file mode 100644 index 0000000..aaf83c0 --- /dev/null +++ b/roles/nginx/handlers/main.yml @@ -0,0 +1,16 @@ +--- +- name: "Update apt cache" + ansible.builtin.apt: + update_cache: true + cache_valid_time: 3600 + +- name: "Start nginx" + ansible.builtin.service: + name: nginx + state: started + enabled: true + +- name: "Reload nginx" + ansible.builtin.service: + name: nginx + state: reloaded diff --git a/roles/nginx/meta/main.yml b/roles/nginx/meta/main.yml new file mode 100644 index 0000000..33b67c1 --- /dev/null +++ b/roles/nginx/meta/main.yml @@ -0,0 +1,17 @@ +--- +galaxy_info: + role_name: "nginx" + namespace: genlab + author: "Alexander Gorelyshev" + company: "Genlab, LLC" + description: "" + license: "MIT" + min_ansible_version: "2.1" + + platforms: + - name: "Ubuntu" + versions: [ "focal", "jammy", "noble" ] + + galaxy_tags: [ ] + +dependencies: [] diff --git a/roles/nginx/molecule/default/converge.yml b/roles/nginx/molecule/default/converge.yml new file mode 100644 index 0000000..c6034a0 --- /dev/null +++ b/roles/nginx/molecule/default/converge.yml @@ -0,0 +1,36 @@ +--- +- name: Converge + hosts: all + post_tasks: + - name: "Create a test site root" + ansible.builtin.file: + path: /var/www/html + state: directory + owner: nginx + group: nginx + mode: "0755" + + - name: "Push a test index file" + ansible.builtin.copy: + src: index.html + dest: /var/www/html + owner: nginx + group: nginx + mode: "0644" + + roles: + # using default NGINX verison + - role: genlab.nginx + site: + confname: test-var + content: | + server { + listen 80; + server_name example.com www.example.com; + + location / { + root /var/www/html; + index index.html; + } + } + dir_sites: '{{ lookup("env", "MOLECULE_PROJECT_DIRECTORY") }}/molecule/default/site-configs/' diff --git a/roles/nginx/molecule/default/files/index.html b/roles/nginx/molecule/default/files/index.html new file mode 100644 index 0000000..19d993f --- /dev/null +++ b/roles/nginx/molecule/default/files/index.html @@ -0,0 +1 @@ +Hello from ansible-nginx! diff --git a/roles/nginx/molecule/default/molecule.yml b/roles/nginx/molecule/default/molecule.yml new file mode 100644 index 0000000..d82158e --- /dev/null +++ b/roles/nginx/molecule/default/molecule.yml @@ -0,0 +1,27 @@ +--- +dependency: + name: galaxy + +driver: + name: docker + +platforms: + - name: ubuntu + image: geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2404}-ansible:latest + pre_build_image: true + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + +provisioner: + name: ansible + +verifier: + name: ansible + +lint: | + set -e + yamllint . + ansible-lint . diff --git a/roles/nginx/molecule/default/site-configs/test-dir.conf b/roles/nginx/molecule/default/site-configs/test-dir.conf new file mode 100644 index 0000000..0830bee --- /dev/null +++ b/roles/nginx/molecule/default/site-configs/test-dir.conf @@ -0,0 +1,9 @@ +server { + listen 8080; + server_name test.com; + + location / { + root /var/www/html; + index index.html; + } +} diff --git a/roles/nginx/molecule/default/verify.yml b/roles/nginx/molecule/default/verify.yml new file mode 100644 index 0000000..416523b --- /dev/null +++ b/roles/nginx/molecule/default/verify.yml @@ -0,0 +1,73 @@ +# kics-scan disable=2e8d4922-8362-4606-8c14-aa10466a1ce3 +--- +- name: Verify + hosts: all + gather_facts: false + any_errors_fatal: true + + pre_tasks: + - name: "Include default vars" + ansible.builtin.include_vars: + dir: '{{ lookup("env", "MOLECULE_PROJECT_DIRECTORY") }}/defaults/' + extensions: + - 'yml' + + tasks: + - name: "Verify NGINX version" + register: nginx_version_output + changed_when: false + failed_when: nginx_version_output.rc != 0 + ansible.builtin.command: /usr/sbin/nginx -v + + # version is displayed as e.g. 'nginx version: nginx/1.26.3' + - name: "Extract NGINX version" + ansible.builtin.set_fact: + nginx_version: "{{ nginx_version_output.stderr.split('/')[1] }}" + + - name: "Check expected NGINX version" + ansible.builtin.assert: + that: nginx_version.startswith(nginx_version) + fail_msg: "Unexpected NGINX version found: '{{ nginx_version }}'" + + - name: "Gather service facts" + ansible.builtin.service_facts: + + - name: "Assert NGINX service is running" + ansible.builtin.assert: + that: ansible_facts.services['nginx.service'].state == 'running' + fail_msg: "NGINX service is not running." + + - name: "Assert NGINX service is enabled" + ansible.builtin.assert: + that: ansible_facts.services['nginx.service'].status == 'enabled' + fail_msg: "NGINX service is not enabled." + + - name: "Get an HTTP response from the test site (single site deployment from a variable)" + register: response + ansible.builtin.uri: + url: http://localhost:80 + status_code: 200 + return_content: true + + - name: "Check the response correctness" + vars: + message: "{{ response.content | trim }}" + ansible.builtin.assert: + that: message == 'Hello from ansible-nginx!' + success_msg: "{{ message }}" + fail_msg: "Unexpected response from the test site: '{{ message }}'" + + - name: "Get an HTTP response from the test site (site deployment from a dictionary)" + register: response + ansible.builtin.uri: + url: http://localhost:8080 + status_code: 200 + return_content: true + + - name: "Check the response correctness" + vars: + message: "{{ response.content | trim }}" + ansible.builtin.assert: + that: message == 'Hello from ansible-nginx!' + success_msg: "{{ message }}" + fail_msg: "Unexpected response from the test site: '{{ message }}'" diff --git a/roles/nginx/renovate.json b/roles/nginx/renovate.json new file mode 100644 index 0000000..5db72dd --- /dev/null +++ b/roles/nginx/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ] +} diff --git a/roles/nginx/requirements.ci.txt b/roles/nginx/requirements.ci.txt new file mode 100644 index 0000000..f99c76a --- /dev/null +++ b/roles/nginx/requirements.ci.txt @@ -0,0 +1,6 @@ +ansible-lint +molecule==24.12.0 +molecule-plugins[docker] +docker~=7.1.0 +requests==2.31.0 # pinned to the latest version not breaking Docker SDK +yamllint diff --git a/roles/nginx/requirements.txt b/roles/nginx/requirements.txt new file mode 100644 index 0000000..92f8677 --- /dev/null +++ b/roles/nginx/requirements.txt @@ -0,0 +1 @@ +ansible~=11.3.0 diff --git a/roles/nginx/requirements.yml b/roles/nginx/requirements.yml new file mode 100644 index 0000000..3d5f1cd --- /dev/null +++ b/roles/nginx/requirements.yml @@ -0,0 +1,3 @@ +# requirements file +--- +collections: [] diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml new file mode 100644 index 0000000..b0bfb81 --- /dev/null +++ b/roles/nginx/tasks/main.yml @@ -0,0 +1,53 @@ +--- +- name: "Install gpg-agent" + ansible.builtin.apt: + name: gpg-agent + state: present + update_cache: true + cache_valid_time: 3600 + +- name: "Add NGINX signing key" + ansible.builtin.apt_key: + url: https://nginx.org/keys/nginx_signing.key + state: present + +- name: "Add NGINX repository" + notify: "Update apt cache" + ansible.builtin.apt_repository: + repo: "deb http://nginx.org/packages/{{ ansible_distribution | lower }}/ {{ ansible_distribution_release }} nginx" + state: present + +- name: "Install specific NGINX version" + notify: "Start nginx" + ansible.builtin.apt: + name: "nginx={{ nginx_version }}*" + state: present + +- name: "Remove default site configuration if it exists" + notify: "Reload nginx" + ansible.builtin.file: + path: /etc/nginx/conf.d/default.conf + state: absent + +- name: "Deploy a single site configuration" + when: site is defined + notify: "Reload nginx" + ansible.builtin.copy: + dest: "/etc/nginx/conf.d/{{ site.confname }}.conf" + owner: root + group: root + mode: "0644" + content: "{{ site.content }}" + +- name: "Deploy custom site configurations" + when: dir_sites is defined + with_fileglob: + - "{{ dir_sites }}/*.conf" + notify: "Reload nginx" + ansible.builtin.copy: + src: "{{ item }}" + dest: "/etc/nginx/conf.d/{{ item | basename }}" + owner: root + group: root + mode: '0644' + # validate: '/usr/sbin/nginx -t -c %s' diff --git a/roles/nginx/vars/main.yml b/roles/nginx/vars/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/nginx/vars/main.yml @@ -0,0 +1 @@ +---