voxpupuli / puppet-nginx

Puppet Module to manage NGINX on various UNIXes
https://forge.puppet.com/puppet/nginx
MIT License
470 stars 881 forks source link

[Feature request]: ipv4_enable: false #1433

Open olevole opened 3 years ago

olevole commented 3 years ago

Affected Puppet, Ruby, OS and module versions/distributions

How to reproduce (e.g Puppet code you use)

Try to use puppet-nginx on INET6-only stack environment

What are you seeing

nginx: [emerg] socket() 0.0.0.0:80 failed (43: Protocol not supported)
/usr/local/etc/rc.d/nginx: WARNING: failed to start nginx

in nginx config:

 listen *:80;

What behaviour did you expect instead

lack of IPv4 bind/listen hardcode

Output log

Any additional information you'd like to impart

We have an experimental build of FreeBSD (it doesn't matter, it can be any Linux container) with the disabled IPv4 stack in kernel and userland, INET6-only:

nooptions         INET                    # InterNETworking
options         INET6                   # IPv6 communications protocols

So we don't even have 127.0.0.1 on loopback ( only ::1 ):

ifconfig:

re0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        ...
        inet6 2a01:4f8:201:3ed::2 prefixlen 128
        ..

When we use a pupppet-nginx module, it always sets a listen parameter for IPv4 via templates/server/server_header.erb:

...
<%- @server_name.each do |s| -%>
server {
  <%- if @listen_ip.is_a?(Array) then -%>
    <%- @listen_ip.each do |ip| -%>
  listen       <%= ip %>:<%= @listen_port %><% if @listen_options %> <%= @listen_options %><% end %>;
    <%- end -%>
  <%- else -%>
  listen       <%= @listen_ip %>:<%= @listen_port %><% if @listen_options %> <%= @listen_options %><% end %>;
  <%- end -%>
...

so different options like listen_ip: '' one don't help.

It would be very helpful to get rid of the V4 hardcode and have the ipv4_enable: false option by analogy with ipv6_enable ,e.g:

nginx::nginx_servers:
  'v6':
    server_name:
      - _
    ipv4_enable: false
    ipv6_enable: true
    ipv6_listen_options: 'default ipv6only=on'

to get the following configuration:

 # MANAGED BY PUPPET
 server {
   listen [::]:80 default ipv6only=on;
b4ldr commented 3 years ago

not ideal but looking at the resource definition seems you should be able to do

nginx::resource::server{'foo':
  listen_ip => '[::]',
}

as listen_ip only validates for string or array. Also since listen directives default to ipv6only=on in nginx 1.4+ it should just work (this is a hack and permanent fix would be better)

olevole commented 3 years ago

not ideal but looking at the resource definition seems you should be able to do

nginx::resource::server{'foo':
  listen_ip => '[::]',
}

as listen_ip only validates for string or array. Also since listen directives default to ipv6only=on in nginx 1.4+ it should just work (this is a hack and permanent fix would be better)

wow, this hack works. The recording can be confusing:

nginx::nginx_servers:
  'v6':
    server_name:
      - _
    ipv6_enable: false
    listen_ip: '[::]'
    ...

:smile:, but the result is working :point_up::

server {
  listen [::]:80;
  server_name           _;
  ...

+

nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful