diff --git a/defaults/main.yml b/defaults/main.yml index 8a31906..44ef68b 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -33,7 +33,7 @@ redmine_service_name: '{{ redmine_systemd_service_name }}' redmine_web_root: '{{ redmine_glob_root_dir }}/{{ redmine_inst_dir }}/public' redmine_nginx_behind_haproxy_settings: False redmine_nginx_frontend: True -redmine_nginx_use_common_virthost: True +redmine_nginx_static_data_valid_time: '30d' nginx_virthosts: '{{ redmine_nginx_virthosts }}' redmine_nginx_serveraliases: [] diff --git a/tasks/main.yml b/tasks/main.yml index 717171f..5ab8d91 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -9,3 +9,5 @@ when: ansible_distribution_file_variety == "Debian" - import_tasks: unicorn.yml when: ansible_distribution_file_variety == "Debian" +- import_tasks: nginx.yml + when: ansible_distribution_file_variety == "Debian" diff --git a/tasks/nginx.yml b/tasks/nginx.yml new file mode 100644 index 0000000..13b52d8 --- /dev/null +++ b/tasks/nginx.yml @@ -0,0 +1,32 @@ +--- +- block: + - name: Install a nginx configuration of the unicorn backend + template: + src: nginx_unicorn.conf.j2 + dest: /etc/nginx/conf.d/nginx_unicorn.conf + notify: Restart nginx + + tags: [ 'ruby', 'redmine', 'unicorn', 'unicorn_nginx' ] + when: ansible_distribution_version is version_compare('18.04', '==') + +- name: Install and enable the nginx virtualhost files on Deb based systems + block: + - name: Install the nginx virtualhost files + template: + src: nginx-redmine-virthost.j2 + dest: '/etc/nginx/sites-available/{{ item.virthost_name }}' + owner: root + group: root + mode: 0444 + with_items: '{{ nginx_virthosts | default(omit) }}' + notify: Reload nginx + + - name: Enable the nginx virtualhosts + file: + src: '/etc/nginx/sites-available/{{ item.virthost_name }}' + dest: '/etc/nginx/sites-enabled/{{ item.virthost_name }}' + state: link + with_items: '{{ nginx_virthosts | default(omit) }}' + notify: Reload nginx + + tags: [ 'ruby', 'redmine', 'unicorn', 'unicorn_nginx', 'virtualhost', 'nginx' ] diff --git a/tasks/unicorn.yml b/tasks/unicorn.yml index 6b22842..6bfb1c4 100644 --- a/tasks/unicorn.yml +++ b/tasks/unicorn.yml @@ -3,10 +3,6 @@ - name: Install the unicorn package apt: pkg=unicorn state=present cache_valid_time=1800 - - name: Install a nginx configuration of the unicorn backend - template: src=nginx_unicorn.conf.j2 dest=/etc/nginx/conf.d/nginx_unicorn.conf - notify: Restart nginx - tags: [ 'ruby', 'redmine', 'unicorn', 'unicorn_nginx' ] when: ansible_distribution_version is version_compare('18.04', '==') diff --git a/templates/nginx-redmine-virthost.j2 b/templates/nginx-redmine-virthost.j2 new file mode 100644 index 0000000..fee40fc --- /dev/null +++ b/templates/nginx-redmine-virthost.j2 @@ -0,0 +1,369 @@ +{% if nginx_websockets_support is defined and nginx_websockets_support %} +include /etc/nginx/snippets/nginx-websockets.conf; +{% else %} +{% if item.websockets is defined and item.websockets %} +include /etc/nginx/snippets/nginx-websockets.conf; +{% endif %} +{% endif %} + +{% if item.upstream_backends is defined %} +{% for u_bk in item.upstream_backends %} +upstream {{ u_bk.name }} { + {% for srv in u_bk.servers %} + server {{ srv }}; + {% endfor %} +} + +{% endfor %} +{% endif %} +server { + listen {{ item.http_port | default ('80') }}; + server_name {{ item.server_name }} {% if item.serveraliases is defined %}{{ item.serveraliases }}{% endif %}; +{% if nginx_block_dotfiles %} + location ~ /\.(?!well-known).* { + deny all; + access_log off; + log_not_found off; + return 404; + } +{% endif %} + +{% if letsencrypt_acme_install %} + include /etc/nginx/snippets/letsencrypt-proxy.conf; +{% endif %} + + {% if item.access_log is defined %} + access_log {{ item.access_log }}; + {% else %} + access_log /var/log/nginx/{{ item.server_name }}_access.log; + {% endif %} + + {% if item.error_log is defined %} + error_log {{ item.error_log }}; + {% else %} + error_log /var/log/nginx/{{ item.server_name }}_error.log; + {% endif %} + + server_tokens {{ item.server_tokens | default('off') }}; + +{% if item.ssl_enabled and item.ssl_only %} + location / { + return 301 https://{{ item.server_name }}$request_uri; + } +{% else %} + root {{ item.root | default('/usr/share/nginx/html/') }}; + index {{ item.index | default('index.html index.htm') }}; + error_page 500 502 503 504 {{ item.error_page | default('/50x.html') }}; + location = /50x.html { + root {{ item.error_path | default('/usr/share/nginx/html') }}; + } + location = /favicon.ico { + log_not_found off; + access_log off; + } + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + {% if haproxy_ips is defined %} + # We are behind haproxy + {% for ip in haproxy_ips %} + set_real_ip_from {{ ip }}; + {% endfor %} + real_ip_header X-Forwarded-For; + {% endif %} + + {% if item.max_body is defined %} + client_max_body_size {{ item.max_body }}; + {% else %} + client_max_body_size {{ nginx_client_max_body_size }}; + {% endif %} + + {% if item.body_timeout is defined %} + client_body_timeout {{ item.body_timeout }}; + {% else %} + client_body_timeout {{ nginx_client_body_timeout }}; + {% endif %} + + {% if nginx_cors_enabled %} + {% if nginx_cors_global %} + include /etc/nginx/snippets/nginx-cors.conf; + {% endif %} + {% endif %} + + {% if item.additional_options is defined %} + {% for add_opt in item.additional_options %} + {{ add_opt }}; + {% endfor %} + {% endif %} + + {% if item.http_acls is defined %} + {% for acl in item.http_acls %} + {{ acl }}; + {% endfor %} + {% endif %} + + {% if nginx_websockets_support is defined and nginx_websockets_support %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + {% else %} + {% if item.websockets is defined and item.websockets %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + {% endif %} + {% endif %} + + # See https://www.redmine.org/projects/redmine/wiki/BrowserCaching + # The old workaround is not required anymore at least since redmine 4.2 + #location ~* /(javascripts|stylesheets)/.+(css|js|jpg|gif|ico|png)(\?[0-9]+)?$ { + location ~* \.(ico|css|js|gif|jp?g|png)(\?[0-9]+)?$ { + # add_header X-SV-test 304-killer; use this do-nothing HTTP Header, if you need to play with the regexp + #- for testing without fear of breaking anything! + expires {{ redmine_nginx_static_data_valid_time }}; + } + {% if item.proxy_standard_setup is defined and item.proxy_standard_setup %} + + {% if item.proxy_standard_setup is defined and item.proxy_standard_setup %} + + # Proxy stuff + {% if item.include_global_proxy_conf is defined and not item.include_global_proxy_conf %} + {% else %} + include /etc/nginx/snippets/nginx-proxy-params.conf; + {% endif %} + + {% if item.proxy_additional_options is defined %} + {% for popt in item.proxy_additional_options %} + {{ popt }}; + {% endfor %} + {% endif %} + + {% if item.locations is defined %} + {% for location in item.locations -%} + + location {{ location.location }} { + + {% if nginx_cors_enabled %} + {% if not nginx_cors_global %} + {% if location.cors is defined and location.cors %} + include /etc/nginx/snippets/nginx-cors.conf; + {% endif %} + {% endif %} + {% endif %} + + {% if location.target is defined %} + proxy_pass {{ location.target }}; + {% elif location.php_target is defined %} + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass {% if phpfpm_listen_on_socket is defined and phpfpm_listen_on_socket %}unix:{% endif %}{{ location.php_target }}; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param REMOTE_ADDR $http_x_forwarded_for; + #fastcgi_param REMOTE_ADDR $remote_addr; + include fastcgi_params; + {% endif %} + + {% if location.websockets is defined and location.websockets %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + {% endif %} + + {% if location.extra_conf is defined %} + {{ location.extra_conf }} + {% endif %} + + {% if location.acls is defined %} + {% for acl in location.acls %} + {{ acl }}; + {% endfor %} + {% endif %} + + {% if location.other_opts is defined %} + {% for opt in location.other_opts %} + {{ opt }}; + {% endfor %} + {% endif %} + } + {% endfor %} + {% endif %} + {% endif %} + + {% if item.extra_parameters is defined %} + {{ item.extra_parameters }} + {% endif %} + +{% endif %} + +} + +{% if item.ssl_enabled %} +server { + listen {% if item.https_port is defined %} {{ item.https_port }} {% else %} {{ https_port | default('443') }} {% endif %} ssl {% if ansible_distribution_release != "trusty" %} http2{% endif %}; + server_name {{ item.server_name }} {% if item.serveraliases is defined %}{{ item.serveraliases }}{% endif %}; + + {% if item.access_log is defined %} + access_log {{ item.access_log }}; + {% else %} + access_log /var/log/nginx/{{ item.server_name }}_ssl_access.log; + {% endif %} + + {% if item.error_log is defined %} + error_log {{ item.error_log }}; + {% else %} + error_log /var/log/nginx/{{ item.server_name }}_ssl_error.log; + {% endif %} + + root {{ item.root | default('/usr/share/nginx/html/') }}; + index {{ item.index | default('index.html index.htm') }}; + error_page 500 502 503 504 {{ item.error_page | default('/50x.html') }}; + location = /50x.html { + root {{ item.error_path | default('/usr/share/nginx/html') }}; + } + location = /favicon.ico { + log_not_found off; + access_log off; + } + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } +{% if nginx_block_dotfiles %} + location ~ /\.(?!well-known).* { + deny all; + access_log off; + log_not_found off; + return 404; + } +{% endif %} + + {% if haproxy_ips is defined %} + # We are behind haproxy + {% for ip in haproxy_ips %} + set_real_ip_from {{ ip }}; + {% endfor %} + real_ip_header X-Forwarded-For; + {% endif %} + + {% if item.max_body is defined %} + client_max_body_size {{ item.max_body }}; + {% else %} + client_max_body_size {{ nginx_client_max_body_size }}; + {% endif %} + {% if item.body_timeout is defined %} + client_body_timeout {{ item.body_timeout }}; + {% else %} + client_body_timeout {{ nginx_client_body_timeout }}; + {% endif %} + + include /etc/nginx/snippets/nginx-server-ssl.conf; + + server_tokens {{ item.server_tokens | default('off') }}; + + {% if nginx_cors_enabled %} + {% if nginx_cors_global %} + include /etc/nginx/snippets/nginx-cors.conf; + {% endif %} + {% endif %} + + {% if nginx_websockets_support is defined and nginx_websockets_support %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + {% else %} + {% if item.websockets is defined and item.websockets %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + {% endif %} + {% endif %} + + {% if item.additional_options is defined %} + {% for add_opt in item.additional_options %} + {{ add_opt }}; + {% endfor %} + {% endif %} + + {% if item.https_acls is defined %} + {% for acl in item.https_acls %} + {{ acl }}; + {% endfor %} + {% endif %} + + # See https://www.redmine.org/projects/redmine/wiki/BrowserCaching + # The old workaround is not required anymore at least since redmine 4.2 + #location ~* /(javascripts|stylesheets)/.+(css|js|jpg|gif|ico|png)(\?[0-9]+)?$ { + location ~* \.(ico|css|js|gif|jp?g|png)(\?[0-9]+)?$ { + # add_header X-SV-test 304-killer; use this do-nothing HTTP Header, if you need to play with the regexp + #- for testing without fear of breaking anything! + expires {{ redmine_nginx_static_data_valid_time }}; + } + {% if item.proxy_standard_setup is defined and item.proxy_standard_setup %} + + # Proxy stuff + {% if item.include_global_proxy_conf is defined and not item.include_global_proxy_conf %} + {% else %} + include /etc/nginx/snippets/nginx-proxy-params.conf; + {% endif %} + + {% if item.proxy_additional_options is defined %} + {% for popt in item.proxy_additional_options %} + {{ popt }} + {% endfor %} + {% endif %} + + {% if item.locations is defined %} + {% for location in item.locations -%} + location {{ location.location }} { + + {% if nginx_cors_enabled %} + {% if not nginx_cors_global %} + {% if location.cors is defined and location.cors %} + include /etc/nginx/snippets/nginx-cors.conf; + {% endif %} + {% endif %} + {% endif %} + + {% if location.target is defined %} + proxy_pass {{ location.target }}; + {% elif location.php_target is defined %} + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass {% if phpfpm_listen_on_socket is defined and phpfpm_listen_on_socket %}unix:{% endif %}{{ location.php_target }}; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param REMOTE_ADDR $http_x_forwarded_for; + #fastcgi_param REMOTE_ADDR $remote_addr; + include fastcgi_params; + {% endif %} + + {% if location.websockets is defined and location.websockets %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + {% endif %} + + {% if location.extra_conf is defined %} + {{ location.extra_conf }} + {% endif %} + + {% if location.acls is defined %} + {% for acl in location.acls %} + {{ acl }}; + {% endfor %} + {% endif %} + + {% if location.other_opts is defined %} + {% for opt in location.other_opts %} + {{ opt }}; + {% endfor %} + {% endif %} + } + {% endfor %} + {% endif %} + {% endif %} + + {% if item.extra_parameters is defined %} + {{ item.extra_parameters }} + {% endif %} +} + +{% endif %} diff --git a/vars/main.yml b/vars/main.yml index b9f7fff..c084191 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -50,8 +50,8 @@ redmine_base_apache_modules: - expires nginx_frontend: '{{ redmine_nginx_frontend }}' -nginx_use_common_virthost: '{{ redmine_nginx_use_common_virthost }}' -nginx_behind_haproxy_settings: '{{ redmine_nginx_behind_haproxy_settings}}' +nginx_use_common_virthost: False +nginx_behind_haproxy_settings: '{{ redmine_nginx_behind_haproxy_settings }}' redmine_nginx_virthosts: - virthost_name: '{{ ansible_fqdn }}' listen: '{{ http_port }}'