From a097e7298a3ba9a182970091a183041c6ec09c8a Mon Sep 17 00:00:00 2001 From: Roy Lenferink Date: Mon, 28 Jul 2025 15:50:47 +0200 Subject: [PATCH 1/3] Add possiblity to include .stream config files --- templates/nginx.conf.j2 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/templates/nginx.conf.j2 b/templates/nginx.conf.j2 index 7cdec602..f1ac09b7 100644 --- a/templates/nginx.conf.j2 +++ b/templates/nginx.conf.j2 @@ -79,3 +79,7 @@ http { {% block http_end %}{% endblock %} } + +stream { + include {{ nginx_conf_path }}/*.stream; +} From c38b9f988123787e437c5611220bfd30531a2756 Mon Sep 17 00:00:00 2001 From: Roy Lenferink Date: Mon, 28 Jul 2025 15:50:56 +0200 Subject: [PATCH 2/3] Update README with stream example --- README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/README.md b/README.md index 39762ce3..0eaa9171 100644 --- a/README.md +++ b/README.md @@ -231,6 +231,46 @@ Create the child template in the path you configured above and extend `geerlingg {% endblock %} ``` +### Example: LDAP stream via Nginx + +This example describes how to setup a secure LDAP stream via Nginx. + +Create the following file in your playbook directory (e.g. `templates/nginx/vhost-stream.j2`): + +``` +server { + listen {{ item.listen }}; + +{% if item.server_name is defined and item.server_name|length > 0 %} + server_name {{ item.server_name }}; +{% endif %} + +{% if item.vhost_parameters is defined %} + {{ item.vhost_parameters|indent(8) }} +{% endif %} + +} +``` + +Then, in your Ansible vars, specify e.g. the following configuration: + +```yaml +nginx_vhosts: + # Configuration for other hosts + # + + # LDAPS + - listen: "636 ssl" + server_name: "ldap.example.com" + template: "{{ playbook_dir }}/templates/nginx/vhost-stream.j2" + filename: "ldap.example.com.636.stream" + vhost_parameters: | + ssl_certificate /etc/letsencrypt/live/ldap.example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/ldap.example.com/privkey.pem; + + proxy_pass ldap-vm1.internal:389; +``` + ## Dependencies None. From 927130d57fe2b95f65f28d9ad790a2dc1378786a Mon Sep 17 00:00:00 2001 From: Roy Lenferink Date: Mon, 28 Jul 2025 19:35:46 +0200 Subject: [PATCH 3/3] Allow users to set 'stream' vhosts via a new nginx_vhosts_stream variable This because the expected behavior is quite different, and stream vhosts require additional behavior (e.g. on Debian/Ubuntu) --- README.md | 60 ++++++++++++----------------------- defaults/main.yml | 15 +++++++++ molecule/default/converge.yml | 16 ++++++++++ tasks/setup-Debian.yml | 7 ++++ tasks/vhosts.yml | 24 ++++++++++++++ templates/nginx.conf.j2 | 7 +++- templates/vhost-stream.j2 | 7 ++++ 7 files changed, 95 insertions(+), 41 deletions(-) create mode 100644 templates/vhost-stream.j2 diff --git a/README.md b/README.md index 0eaa9171..5a764eef 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ An example of a fully-populated nginx_vhosts entry, using a `|` to declare a blo Please take note of the indentation in the above block. The first line should be a normal 2-space indent. All other lines should be indented normally relative to that line. In the generated file, the entire block will be 4-space indented. This style will ensure the config file is indented correctly. + - listen: "80" server_name: "example.com www.example.com" return: "301 https://example.com$request_uri" @@ -63,6 +64,25 @@ An example of a secondary vhost which will redirect to the one shown above. *Note: The `filename` defaults to the first domain in `server_name`, if you have two vhosts with the same domain, eg. a redirect, you need to manually set the `filename` so the second one doesn't override the first one* + nginx_vhosts_stream: [] + +Define stream server entries here. The formatting is comparable with `nginx_vhosts`. + + nginx_vhosts_stream: + - listen: "636 ssl" + filename: "ldap.example.com.stream" + state: "present" + vhost_parameters: | + ssl_certificate /etc/letsencrypt/live/ldap.example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/ldap.example.com/privkey.pem; + + proxy_pass ldap-vm1.internal:389; + +An example of a fully-populated nginx_vhosts_stream entry. The formatting is comparable with `nginx_vhosts`. +**NOTE**: Ensure that the stream module is loaded. Enabling this differs per distibution, but should look like +`load_module modules/ngx_stream_module.so;` (defined via e.g. `nginx_extra_conf_options`). On some distributions +(e.g. RedHat based ones), the stream module is enabled automatically. + nginx_remove_default_vhost: false Whether to remove the 'default' virtualhost configuration supplied by Nginx. Useful if you want the base `/` URL to be directed at one of your own virtual hosts configured in a separate .conf file. @@ -231,46 +251,6 @@ Create the child template in the path you configured above and extend `geerlingg {% endblock %} ``` -### Example: LDAP stream via Nginx - -This example describes how to setup a secure LDAP stream via Nginx. - -Create the following file in your playbook directory (e.g. `templates/nginx/vhost-stream.j2`): - -``` -server { - listen {{ item.listen }}; - -{% if item.server_name is defined and item.server_name|length > 0 %} - server_name {{ item.server_name }}; -{% endif %} - -{% if item.vhost_parameters is defined %} - {{ item.vhost_parameters|indent(8) }} -{% endif %} - -} -``` - -Then, in your Ansible vars, specify e.g. the following configuration: - -```yaml -nginx_vhosts: - # Configuration for other hosts - # - - # LDAPS - - listen: "636 ssl" - server_name: "ldap.example.com" - template: "{{ playbook_dir }}/templates/nginx/vhost-stream.j2" - filename: "ldap.example.com.636.stream" - vhost_parameters: | - ssl_certificate /etc/letsencrypt/live/ldap.example.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/ldap.example.com/privkey.pem; - - proxy_pass ldap-vm1.internal:389; -``` - ## Dependencies None. diff --git a/defaults/main.yml b/defaults/main.yml index 88d38f73..1d8d2db2 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -2,6 +2,9 @@ # Used only for Debian/Ubuntu installation, as the -t option for apt. nginx_default_release: "" +# Used only for Debian installation to install the Nginx stream module. +nginx_install_stream_module: true + # Used only for Redhat installation, enables source Nginx repo. nginx_yum_repo_enabled: true @@ -20,6 +23,7 @@ nginx_service_enabled: true nginx_conf_template: "nginx.conf.j2" nginx_vhost_template: "vhost.j2" +nginx_vhost_stream_template: "vhost-stream.j2" nginx_worker_processes: >- "{{ ansible_processor_vcpus | default(ansible_processor_count) }}" @@ -81,6 +85,17 @@ nginx_vhosts: [] # template: "" # Can be used to override the `nginx_vhost_template` per host. # state: "absent" # To remove the vhost configuration. +nginx_vhosts_stream: [] +# Example vhost below, showing all available options: +# - listen: "80" # default: N/A +# server_name: "example.com" # default: N/A +# filename: "example.com.stream" # Can be used to set the vhost filename. +# vhost_parameters: "" # Must be used to add vhost config blocks (multiline). +# +# # Properties that are only added if defined: +# template: "" # Can be used to override the `nginx_vhost_template` per host. +# state: "absent" # To remove the vhost configuration. + nginx_upstreams: [] # - name: myapp1 # strategy: "ip_hash" # "least_conn", etc. diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml index ee651977..d1546f09 100644 --- a/molecule/default/converge.yml +++ b/molecule/default/converge.yml @@ -4,16 +4,32 @@ vars: nginx_use_ppa: true + + # Test HTTP vhost nginx_remove_default_vhost: true nginx_vhosts: - server_name: "test.dev" root: "/var/www/test" + # Test stream vhost + nginx_vhosts_stream: + - listen: 8080 + filename: "stream.test.dev.stream" + vhost_parameters: + proxy_pass 127.0.0.1:80; + pre_tasks: - name: Update apt cache. apt: update_cache=yes cache_valid_time=600 when: ansible_os_family == 'Debian' changed_when: false + - name: Enable Nginx stream module. + set_fact: + nginx_extra_conf_options: | + load_module modules/ngx_stream_module.so; + when: ansible_os_family == 'Debian' + changed_when: false + roles: - role: geerlingguy.nginx diff --git a/tasks/setup-Debian.yml b/tasks/setup-Debian.yml index 554dc2e7..ebf9a31f 100644 --- a/tasks/setup-Debian.yml +++ b/tasks/setup-Debian.yml @@ -8,3 +8,10 @@ name: "{{ nginx_package_name }}" state: present default_release: "{{ nginx_default_release }}" + +- name: Ensure nginx stream module is installed. + apt: + name: libnginx-mod-stream + state: present + default_release: "{{ nginx_default_release }}" + when: nginx_install_stream_module and nginx_vhosts_stream|length > 0 diff --git a/tasks/vhosts.yml b/tasks/vhosts.yml index 8f990fb0..4d6e5b05 100644 --- a/tasks/vhosts.yml +++ b/tasks/vhosts.yml @@ -37,6 +37,30 @@ tags: - skip_ansible_lint +- name: Add managed vhost stream config files. + template: + src: "{{ item.template|default(nginx_vhost_stream_template) }}" + dest: "{{ nginx_vhost_path }}/{{ item.filename }}" + force: true + owner: root + group: "{{ root_group }}" + mode: 0644 + when: item.state|default('present') != 'absent' + with_items: "{{ nginx_vhosts_stream }}" + notify: reload nginx + tags: + - skip_ansible_lint + +- name: Remove managed vhost stream config files. + file: + path: "{{ nginx_vhost_path }}/{{ item.filename }}" + state: absent + when: item.state|default('present') == 'absent' + with_items: "{{ nginx_vhosts_stream }}" + notify: reload nginx + tags: + - skip_ansible_lint + - name: Remove legacy vhosts.conf file. file: path: "{{ nginx_vhost_path }}/vhosts.conf" diff --git a/templates/nginx.conf.j2 b/templates/nginx.conf.j2 index f1ac09b7..394f5873 100644 --- a/templates/nginx.conf.j2 +++ b/templates/nginx.conf.j2 @@ -73,13 +73,18 @@ http { {% block http_includes %} include {{ nginx_conf_path }}/*.conf; {% if nginx_conf_path != nginx_vhost_path %} - include {{ nginx_vhost_path }}/*; + include {{ nginx_vhost_path }}/*.conf; {% endif %} {% endblock %} {% block http_end %}{% endblock %} } +{% if nginx_vhosts_stream|length > 0 %} stream { include {{ nginx_conf_path }}/*.stream; +{% if nginx_conf_path != nginx_vhost_path %} + include {{ nginx_vhost_path }}/*.stream; +{% endif %} } +{% endif %} diff --git a/templates/vhost-stream.j2 b/templates/vhost-stream.j2 new file mode 100644 index 00000000..52b9d57b --- /dev/null +++ b/templates/vhost-stream.j2 @@ -0,0 +1,7 @@ +server { + listen {{ item.listen }}; + +{% if item.vhost_parameters is defined %} + {{ item.vhost_parameters|indent(4) }} +{% endif %} +}