Compare commits

..

No commits in common. "master" and "1.1.0-1" have entirely different histories.

80 changed files with 912 additions and 2249 deletions

View File

@ -1,14 +0,0 @@
---
profile: production
warn_list:
- role-name
- schema[meta]
skip_list: []
exclude_paths:
- .github/
- .venv/
- venv/

View File

@ -1,17 +0,0 @@
---
name: Deploy on Ansible Galaxy
'on':
- push
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- name: galaxy
uses: robertdebock/galaxy-action@1.2.0
with:
galaxy_api_key: ${{ secrets.galaxy_api_key }}

View File

@ -1,39 +0,0 @@
---
name: ci
'on':
pull_request:
push:
branches:
- master
jobs:
yaml-lint:
name: YAML Lint
runs-on: ubuntu-latest
steps:
- name: Fetch code
uses: actions/checkout@v3
- name: Set up Python 3.
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install test dependencies.
run: pip3 install yamllint
- name: Lint code.
run: |
yamllint .
ansible-lint:
name: Ansible Lint
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Run ansible-lint
uses: ansible/ansible-lint@main

View File

@ -1,43 +0,0 @@
---
name: Molecule
'on':
pull_request:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
scenario:
- debian-11
- debian-12
- ubuntu-20.04
- ubuntu-22.04
- ubuntu-24.04
allowed-to-fail:
- false
include:
- scenario: debian-13
allowed-to-fail: true
steps:
- name: Checkout
uses: actions/checkout@v3
with:
path: "${{ github.repository }}"
- name: Molecule
uses: gofrolist/molecule-action@v2.7.62
with:
molecule_options: --base-config molecule/_shared/base.yml
molecule_args: --scenario-name ${{ matrix.scenario }}
continue-on-error: ${{ matrix.allowed-to-fail }}
- name: Fake command
run: echo "End of job"

7
.gitignore vendored
View File

@ -1,9 +1,2 @@
.vagrant* .vagrant*
*.swp *.swp
*.retry
*.pyc
/tests/hanxhx.php
/.idea
/.venv
/venv
/.ansible

13
.travis.yml 100644
View File

@ -0,0 +1,13 @@
env:
- PLATFORM=debian-wheezy
- PLATFORM=debian-jessie
sudo: required
language: python
services:
- docker
script:
- docker build -f tests/$PLATFORM.Dockerfile -t test-$PLATFORM . && docker run --name $PLATFORM test-$PLATFORM

View File

@ -1,8 +0,0 @@
---
extends: default
rules:
line-length: disable
ignore-from-file: .gitignore

View File

@ -1,50 +1,29 @@
Nginx for Debian/Ubuntu Ansible role Nginx for Debian Ansible role
===================================== =============================
[![Ansible Galaxy](http://img.shields.io/badge/ansible--galaxy-HanXHX.nginx-blue.svg)](https://galaxy.ansible.com/HanXHX/nginx/) ![GitHub Workflow Status (master branch)](https://img.shields.io/github/actions/workflow/status/hanxhx/ansible-nginx/molecule.yml?branch=master) [![Ansible Galaxy](http://img.shields.io/badge/ansible--galaxy-HanXHX.nginx-blue.svg)](https://galaxy.ansible.com/list#/roles/4399) [![Build Status](https://travis-ci.org/HanXHX/ansible-nginx.svg?branch=master)](https://travis-ci.org/HanXHX/ansible-nginx)
Install and configure Nginx on Debian/Ubuntu. Install and configure Nginx on Debian.
Features: Features:
- SSL/TLS "hardened" support - SSL/TLS "hardened" support
- Manage basic auth on site / location - Manage basic auth on vhost / location
- Proxy + Upstream - Proxy + Upstream
- Fast PHP configuration - Fast PHP configuration
- Preconfigured site templates (should work on many app) - Preconfigured vhost templates (should work on many app)
- Auto-configure HTTP2 on SSL/TLS sites - Auto-configure HTTP2 on SSL/TLS vhosts
- Manage dynamic modules (install and loading)
- Deploy custom facts.d with sites config
- Can listen with proxy protocol
- Generate certificates with acme.sh (let's encrypt) -- *EXPERIMENTAL*
Supported OS:
| OS | Working | Stable (active support) |
|----------------------|---------|--------------------------------------------------------------------------------------------------------|
| Debian Jessie (8) | Yes | Check latest supported version ([1.5.0](https://github.com/HanXHX/ansible-nginx/releases/tag/1.5.0)) |
| Debian Stretch (9) | Yes | Check latest supported version ([1.9.0](https://github.com/HanXHX/ansible-nginx/releases/tag/1.9.0)) |
| Debian Buster (10) | Yes | Check latest supported version ([1.10.0](https://github.com/HanXHX/ansible-nginx/releases/tag/1.10.0)) |
| Debian Bullseye (11) | Yes | Yes |
| Debian Bookworm (12) | Yes | Yes |
| Debian Trixie (13) | WIP | Not yet |
| Ubuntu 20.04 | Yes | Yes |
| Ubuntu 22.04 | Yes | Yes |
| Ubuntu 24.04 | Yes | Yes |
Requirements Requirements
------------ ------------
- Ansible >=2.11 None. If you set true to `nginx_backports`, you must install backports repository before lauching this role.
- If you set true to `nginx_backports`, you must install backports repository before lauching this role.
Role Variables Role Variables
-------------- --------------
### Packaging ### Packaging
Debian:
- `nginx_apt_package`: APT nginx package (try: apt-cache search ^nginx) - `nginx_apt_package`: APT nginx package (try: apt-cache search ^nginx)
- `nginx_backports`: Install nginx from backport repository (bool) - `nginx_backports`: Install nginx from backport repository (bool)
@ -55,8 +34,6 @@ Debian:
- `nginx_resolver`: list of DNS resolver (default: OpenDNS) - `nginx_resolver`: list of DNS resolver (default: OpenDNS)
- `nginx_error_log_level`: default log level - `nginx_error_log_level`: default log level
- `nginx_auto_config_httpv2`: boolean, auto configure HTTP2 where possible - `nginx_auto_config_httpv2`: boolean, auto configure HTTP2 where possible
- `nginx_fastcgi_fix_realpath`: boolean, use realpath for fastcgi (fix problems with symlinks and PHP opcache)
- `nginx_default_hsts`: string, default header sent for HSTS
### Nginx Configuration ### Nginx Configuration
@ -65,23 +42,12 @@ Debian:
- `nginx_pid`: daemon pid file - `nginx_pid`: daemon pid file
- `nginx_events_*`: all variables in events block - `nginx_events_*`: all variables in events block
- `nginx_http_*`: all variables in http block - `nginx_http_*`: all variables in http block
- `nginx_custom_core`: instructions list (for core, will put data in `/etc/nginx/nginx.conf`)
- `nginx_custom_http`: instructions list (will put data in `/etc/nginx/conf.d/custom.conf`) - `nginx_custom_http`: instructions list (will put data in `/etc/nginx/conf.d/custom.conf`)
- `nginx_module_packages`: package list module to install (Debian)
### Misc
- `nginx_debug_role`: set _true_ if you need to see output of no\_log tasks
About modules
-------------
Last updates from Debian backports loads modules from /etc/nginx/modules-enabled directory. Disabling/Enabling is not supported anymore. Please wait further update.
Fine configuration Fine configuration
------------------ ------------------
[Site configuration](doc/site.md) [Vhost configuration](doc/vhost.md)
[PHP configuration](doc/php.md) [PHP configuration](doc/php.md)
@ -91,48 +57,22 @@ Fine configuration
[Basic Auth](doc/auth.md) [Basic Auth](doc/auth.md)
[acme.sh](doc/acme.md)
Note
----
- Active support for Debian/Ubuntu.
Dependencies Dependencies
------------ ------------
See: [requirements.yml](requirements.yml). None
Example Playbook
----------------
If you need to dev this role locally with molecule See [tests/test.yml](tests/test.yml).
--------------------------------------------------
Check available scenarios in [molecule](molecule) directory.
With `debian-12` scenario:
```commandline
molecule -v -c molecule/_shared/base.yml verify -s debian-12
```
License License
------- -------
GPLv2 GPLv2
Donation
--------
If this code helped you, or if youve used them for your projects, feel free to buy me some :beers:
- Bitcoin: `1BQwhBeszzWbUTyK4aUyq3SRg7rBSHcEQn`
- Ethereum: `63abe6b2648fd892816d87a31e3d9d4365a737b5`
- Litecoin: `LeNDw34zQLX84VvhCGADNvHMEgb5QyFXyD`
- Monero: `45wbf7VdQAZS5EWUrPhen7Wo4hy7Pa7c7ZBdaWQSRowtd3CZ5vpVw5nTPphTuqVQrnYZC72FXDYyfP31uJmfSQ6qRXFy3bQ`
No crypto-currency? :star: the project is also a way of saying thank you! :sunglasses:
Author Information Author Information
------------------ ------------------

32
Vagrantfile vendored 100644
View File

@ -0,0 +1,32 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# vi: set tabstop=2 :
# vi: set shiftwidth=2 :
Vagrant.configure("2") do |config|
vms = [
[ "debian-wheezy", "deb/wheezy-amd64" , "192.168.33.27" ],
[ "debian-jessie", "deb/jessie-amd64", "192.168.33.28" ],
[ "debian-stretch", "sharlak/debian_stretch_64", "192.168.33.29" ]
]
config.vm.provider "virtualbox" do |v|
v.cpus = 1
v.memory = 256
end
vms.each do |vm|
config.vm.define vm[0] do |m|
m.vm.box = vm[1]
m.vm.network "private_network", ip: vm[2]
m.vm.provision "ansible" do |ansible|
ansible.playbook = "tests/test.yml"
ansible.groups = { "test" => [ vm[0] ] }
ansible.verbose = 'vv'
ansible.sudo = true
end
end
end
end

View File

@ -1,6 +1,5 @@
--- ---
# Debian
nginx_apt_package: nginx-full nginx_apt_package: nginx-full
nginx_backports: false nginx_backports: false
@ -9,29 +8,31 @@ nginx_backports: false
# #
nginx_root: "/srv/www" nginx_root: "/srv/www"
nginx_log_dir: '/var/log/nginx' nginx_log_dir: '/var/log/nginx'
nginx_pid: '/run/nginx.pid'
nginx_resolver_hosts: ['8.8.8.8', '8.8.4.4'] nginx_resolver_hosts: ['8.8.8.8', '8.8.4.4']
nginx_resolver_valid: '300s' nginx_resolver_valid: '300s'
nginx_resolver_timeout: '5s' nginx_resolver_timeout: '5s'
nginx_error_log_level: 'warn' # http://nginx.org/en/docs/ngx_core_module.html#error_log nginx_error_log_level: 'warn' # http://nginx.org/en/docs/ngx_core_module.html#error_log
nginx_auto_config_httpv2: true nginx_auto_config_httpv2: true
nginx_default_site: null nginx_default_vhost: null
nginx_default_site_ssl: null nginx_default_vhost_ssl: null
nginx_fastcgi_fix_realpath: true
nginx_default_hsts: 'max-age=63072000; includeSubDomains'
# #
# Nginx directories # Nginx directories
# #
nginx_htpasswd_dir: '{{ nginx_etc_dir }}/htpasswd' nginx_htpasswd_dir: '/etc/nginx/htpasswd'
nginx_ssl_dir: '{{ nginx_etc_dir }}/ssl' nginx_ssl_dir: '/etc/nginx/ssl'
nginx_helper_dir: '{{ nginx_etc_dir }}/helper' nginx_helper_dir: '/etc/nginx/helper'
# #
# Load upstream # Load upstream
# #
# PHP # PHP
nginx_php: [] nginx_php: false
nginx_php_sockets:
- unix_socket: "/var/run/php5-fpm.sock"
nginx_upstreams: []
# #
# Nginx configuration # Nginx configuration
@ -44,6 +45,7 @@ nginx_worker_processes: '{{ ansible_processor_vcpus }}'
# #
nginx_events_worker_connections: '512' nginx_events_worker_connections: '512'
nginx_events_multi_accept: 'on' nginx_events_multi_accept: 'on'
nginx_events_use: 'epoll'
# #
# Nginx HTTP # Nginx HTTP
@ -82,29 +84,11 @@ nginx_http_gzip_disable: '"msie6"'
# Custom global configuration # Custom global configuration
# #
nginx_custom_http: [] nginx_custom_http: []
nginx_custom_core: []
# #
# Nginx default # Vhosts
# #
nginx_default_listen: nginx_vhosts: []
- '80'
- '[::]:80'
nginx_default_listen_ssl:
- '443'
- '[::]:443'
nginx_default_listen_proxy_protocol: []
nginx_default_listen_proxy_protocol_ssl: []
#
# Sites
#
nginx_sites: []
#
# Upstreams
#
nginx_upstreams: []
# #
# htpasswd # htpasswd
@ -116,28 +100,9 @@ nginx_htpasswd: []
# #
nginx_ssl_pairs: [] nginx_ssl_pairs: []
#
# Dynamic modules
#
nginx_module_packages: []
nginx_load_modules: []
# #
# Diffie-Hellman # Diffie-Hellman
# #
nginx_dh: null nginx_dh: null
nginx_dh_path: '{{ nginx_ssl_dir }}/dhparam.pem' nginx_dh_path: '{{ nginx_ssl_dir }}/dhparam.pem'
nginx_dh_length: 2048 nginx_dh_length: 2048
#
# acme.sh
#
nginx_acmesh: false
nginx_acmesh_dir: "/opt/acme.sh"
nginx_acmesh_git_dir: "/tmp/acme.sh"
nginx_acmesh_test: false
#
# Debug
#
nginx_debug_role: false

View File

@ -1,15 +0,0 @@
acme.sh
=======
Notes
-----
This feature is experimental.
Variables
---------
- `nginx_acmesh`: (bool) Enable/Disable acme.sh feature
- `nginx_acmesh_dir`: (string) Install directory
- `nginx_acmesh_git_dir`: (string) Git directory (removed after install)
- `nginx_acmesh_test`: (bool) If set to true (default false), uses test mode

View File

@ -4,33 +4,33 @@ Auth Basic management
Description Description
----------- -----------
Auth basic is managed in a separate list. Each auth file can be shared between locations or sites. Auth basic is managed in a separate list. Each auth file can be shared between locations or vhosts.
Each htpasswd has few keys: Each htpasswd has few keys:
- `name`: (M) used to create file and as pointee - `name`: (M) used to create file and as pointee
- `description`: (M) Used for the message box :) - `description`: (M) Used for the message box :)
- `users`: each users is composed with 3 keys: `name` (M), `password` (M) and `state` (O) present/absent (default: present) - `users`: each users is composed with 3 keys: `name` (M), `password` (M) and `state` present/absent (default: present)
- `state`: (O) present or absent. Default: present - `state`: (O) present or absent. Default: present
`nginx_htpasswd` should be placed in a vault file. `nginx_htpasswd` should be placed in a vaut file.
Example Example
------- -------
```yaml ```
nginx_sites: nginx_vhosts:
# htpasswd on all site # htpasswd on all vhost
- name: test.local - name: test.local
htpasswd: 'hello' htpasswd: 'hello'
template: '_base' template: '_base'
# htpasswd only in /hello # htpasswd only in /hello
- name: test-location.local - name: test-location.local
template: '_base' template: '_base'
location: location:
'/hello': '/hello':
- htpasswd: 'hello' - htpasswd: 'hello'
nginx_htpasswd: nginx_htpasswd:
- name: 'hello' - name: 'hello'

View File

@ -1,22 +1,18 @@
PHP PHP
=== ===
`nginx_php`: - `nginx_php`: boolean if you need to preconfigure PHP (default: false)
- `upstream_name` (M) - `nginx_php_sockets`: list of sockets (see bellow)
- `sockets`: (O) socket list
If `sockets` is not provided, if uses local unix socket (based on PHP version).
You should see [Nginx upstream module doc](http://nginx.org/en/docs/http/ngx_http_upstream_module.html). You should see [Nginx upstream module doc](http://nginx.org/en/docs/http/ngx_http_upstream_module.html).
Each socket have: Each socket have:
- `unix` - `unix_socket`
- `host`
- `port`
- `weight`
- `max_fails`
- `fail_timeout`
XOR With default configuration, it works fine with PHP-FPM. But if you install PHP7 with Dotdeb, path changed between version, you must set well this list.
- `host` (M)
- `port` (M)
- `weight` (O)
- `max_fails` (O)
- `fail_timeout` (O)

View File

@ -1,139 +0,0 @@
Site management
===============
You can see many examples in: [molecule/_shared/group_vars/all/main.yml](../molecule/_shared/group_vars/all/main.yml).
`nginx_sites`: List of dict. A site has few keys. See bellow.
Common
------
- `name`: (M) Domain or list of domain used.
- `state`: (O) Site status. Can be "present" (default), "absent" and "disabled".
- `filename`: (O) Specify filename in `/etc/nginx/sites-*`. Do NOT specify default (reserved keyword). It will be used for log filenames and directories creation.
(O): Optional
(M): Mandatory
(D): Depends other keys...
You can use 2 config (at the same time time):
- pre-built: Some configuration are templated (Wordpress, Symfony...), auto create root dir, perform an "A+" on ssllabs for https... etc
- custom: Push your own site config template. Usefull when you have a complex configuration.
Pre-built site config
---------------------
# Keys
- `template`: (M) template used to create site. Optional if you set `state`=`absent` or using `redirect_to`.
- `redirect_from`: (O) Domain list to redirect to the first `name`. You can use this key to redirect non-www to www
- `redirect_to`: (O) Redirect all requests to this domain. Please set scheme (http:// or https:// or $sheme).
- `headers`: (O) Set additionals header as key/value list. You can append "always" to the value. Show [nginx doc](http://nginx.org/en/docs/http/ngx_http_headers_module.html).
- `redirect_to_code`: Redirect code (default: 302)
- `redirect_https`: (O) Boolean. Redirect HTTP to HTTPS. If "true", you _MUST_ set `proto` to `['https']`.
- `location`: (O) Add new custom locations (it does not overwrite!)
- `location_order`: (O) Due to non preditive `location` order, you can provide the good order (see test-location.local in [molecule/_shared/group_vars/all/main.yml](../molecule/_shared/group_vars/all/main.yml)).
- `location_before`: (O) Add new custom locations before generated location by template
- `location_order_before`: (O) Manages location order for `location_before`
- `more`: (O) Add more custom infos.
- `upstream_params`: (O) Add upstream params (useful when you want to pass variables to PHP)
- `override_try_files`: (O) overrides default try\_files defined in template
- `manage_local_content`: (O) Boolean. Set to false if you do not want to manage local content (images, css...). This option is useless if you use `_proxy` template or `redirect_to` feature.
- `htpasswd`: (O) References name key in `nginx_htpasswd`. Enable auth basic on all site. Set "false" to disable.
- `proto`: (O) list of protocol used. Default is a list with "http". If you need http and https, you must set a list with "http" and "https". You can only set "https" without http support.
- `ssl_name`: (D) name of the key used when using TLS/SSL. Optional when `proto` contains "https". If you don't set this value, it will search by `name`.
- `ssl_template` (O) "strong" (default) or "legacy". You can disable SSL helpers and add your own directives by setting "false".
- `listen_proxy_protocol` (O) Enable proxy protocol on http port.
- `listen_proxy_protocol_ssl` (O) Enable proxy protocol on https port.
- `hsts` (O) overwrite default header for hsts
### Templates
- `_base`: static template
- `_dokuwiki`
- `_redirect`: should not be called explicitly
- `_phalcon`: Phalcon PHP Framework
- `_php`: PHP base template. Can work with many frameworks/tools
- `_php_index`: Same as above. But you can only run index.php
- `_proxy`
- `_wordpress`
Templates works as parent-child.
### About proxy template
Proxy template allow you to use Nginx as reverse proxy. Usefull when you have an application service such as Redmine, Jenkins...
You have many key added to site key:
- `upstream_name`: (O) upstream name used to pass proxy
- `proxy_params`: (M) list of raw params passed to the site
(O) : Optional
### Default sites
You can manage default site by setting domain name to these variables.
- `nginx_default_site`
- `nginx_default_site_ssl`
*IT WORKS ONLY WITH PRE-BUIT SITES*
### Example
```yaml
nginx_sites:
- name: 'mywebsite.com'
template: '_wordpress'
headers:
x-ansibled: '1'
manage_local_content: false
```
Custom site config
------------------
### Keys
- `custom_template`: (M) template path used
You can add some extra infos if needed.
### Example:
```yaml
nginx_sites:
- name: 'mycustom-website.com'
custom_template: 'my/template_dir/the-template.conf.j2'
allow_admin: '192.168.0.0/24'
```
In `my/template_dir/the-template.conf.j2`:
```
#
# {{ ansible_managed }} - {{ item.name }}
#
server {
listen 8080 http2 proxy_protocol;
server_name {{ item.name }};
index index.html;
root /var/www/{{ item.name }};
location / {
try_files $uri $uri/ =404;
}
location /admin {
allow {{ item.allow_admin }};
deny all;
}
}
```

View File

@ -8,49 +8,35 @@ Variables
- `nginx_dh`: DH content - `nginx_dh`: DH content
- `nginx_dh_length`: DH key length (default is 2048) - `nginx_dh_length`: DH key length (default is 2048)
- `nginx_dh_path`: file location - `nginx_dh_path`: file localation
- `nginx_ssl_dir`: directory where you install your SSL/TLS keys - `nginx_ssl_dir`: directory where you install your SSL/TLS keys
- `nginx_ssl_pairs` - `nginx_ssl_pairs`
Cert/Key pairs Cert/Key pairs
-------------- --------------
Each pair must have a `name`. This list have 3 mandatory keys:
Note: `name` is used to deploy key/cert. With defaults values dans `name` = "foo", key is -> /etc/nginx/ssl/foo/foo.key
### Content mode - `name`: MUST be unique
Key/Cert content is stored in variable. Useful with vault.
- `key`: content of the private key - `key`: content of the private key
- `cert`: content of the public key - `cert`: content of the public key
### Remote file OR
You can use these variables if you use another task/role to manages your certificates.
- `dest_cert`: remote path where certificate is located - `dest_cert`: remote path where certificate is located
- `dest_key`: remote path where key is located - `dest_key`: remote path where key is located
### Self-signed
Create a self-signed pair and deploy it. Do not use this feature in production. Note: `name` is used to deploy key/cert. With defaults values dans `name` = "foo", key is -> /etc/nginx/ssl/foo/foo.key
- `self_signed`: set true to use this feature
- `force`: optional feature (default: false), force regen pair (not idempotent)
### Acme
Uses acme.sh to create free certificates. It uses HTTP-01 challenge. Use this feature for standalone servers.
- `acme`: set true to use this feature. It uses `name` (can be a string or string list).
Have a look to [acme configuration](acme.md).
Tips Tips
---- ----
- In `nginx_sites`, `ssl_name` is mandatory. This role will search in `nginx_ssl_pairs` with site `name` (first in list if it's a list). Deploying key/cert is not mandatory with this role. You can manage it in other place ([letsencrypt](https://letsencrypt.org/)? :)). You just need to set `dest_cert` and `dest_key`!
If you set all, you can deploy your key everywhere with wanted data!
Diffie-Hellman Diffie-Hellman
-------------- --------------
@ -60,22 +46,12 @@ If you do not specify any dh param, this role auto generates it.
Example Example
------- -------
```yaml ```
nginx_sites: nginx_vhosts;
- name: 'test-ssl.local' - name: 'test-ssl.local'
proto: ['http', 'https'] proto: ['http', 'https']
template: '_base' template: '_base'
ssl_name: 'mysuperkey' ssl_name: 'mysuperkey'
- name: 'test-ssl2.local'
proto: ['http', 'https']
template: '_base'
- name: 'test-ssl3.local'
proto: ['http', 'https']
template: '_base'
- name: 'test-self-signed.local'
proto: ['http', 'https']
template: '_base'
ssl_name: 'this.is.self.signed'
nginx_ssl_pairs: nginx_ssl_pairs:
- name: mysuperkey - name: mysuperkey
@ -87,10 +63,5 @@ nginx_ssl_pairs:
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
....(snip).... ....(snip)....
-----END CERTIFICATE----- -----END CERTIFICATE-----
- name: test-ssl2.local
acme: true
- name: this.is.self.signed
self_signed: true
force: false
``` ```

View File

@ -3,13 +3,14 @@ Upstream management
`nginx_upstreams`: List of dict. An upstream has few keys. See bellow. `nginx_upstreams`: List of dict. An upstream has few keys. See bellow.
Note: Few params are unavailable on old Nginx version. But this role do _not_ put it if your version is too old!
Upstream params Upstream params
--------------- ---------------
- `name`: upstream name. Can be use in site with *proxy_pass http://upstream_name* - `name`: upstream name. Can be use in vhost with *proxy_pass http://upstream_name*
- `params`: list of param (hash, zone...) - `params`: list of param (hash, zone...)
- `servers`: each upstream MUST have at least 1 server - `servers`: each upstream MUST have at least 1 server
- `state`: Optional. Can be 'absent' or 'present'
Server params Server params
------------- -------------
@ -24,18 +25,5 @@ All this params are optional. You should see [Nginx upstream doc](http://nginx.o
- `backup` - `backup`
- `down` - `down`
- `route` - `route`
- `slow_start` - `slow`start`
Example
-------
```yaml
nginx_upstreams:
- name: 'proxy_apache'
servers:
- path: '127.0.0.1:80'
max_conns: 150
weight: 10
down: false
state: 'present'
```

65
doc/vhost.md 100644
View File

@ -0,0 +1,65 @@
Vhost management
================
You can see many examples in: [tests/test.yml](../tests/test.yml).
`nginx_vhosts`: List of dict. A vhost has few keys. See bellow.
Common
------
- `name`: (M) Domain or list of domain used.
- `template`: (D) template used to create vhost. Optional if you set `delete` to true or using `redirect_tor`.
- `enable`: (O) Enable the vhost (default is true)
- `delete`: (O) Delete the vhost (default is false)
- `redirect_from`: (O) Domain list to redirect to the first `name`. You can use this key to redirect non-www to www
- `redirect_to`: (O) Redirect all requests to this domain. Please set scheme (http:// or https:// or $sheme).
- `redirect_to_code`: Redirect code (default: 302)
- `location`: (O) Add new custom locations (it does not overwrite!)
- `more`: (O) Add more custom infos.
- `upstream_params`: (O) Add upstream params (useful when you want to pass variables to PHP)
- `override_try_files`: (O) overrides default try\_files defined in template
- `manage_local_content`: (O) Boolean. Set to false if you do not want to manage local content (images, css...). This option is useless if you use `_proxy` template or `redirect_to` feature.
- `htpasswd`: (O) References name key in `nginx_htpasswd`. Enable auth basic on all vhost.
- `proto`: (O) list of protocol used. Default is a list with "http". If you need http and https, you must set a list with "http" and "https". You can only set "https" without http support.
- `ssl_name`: (D) name of the key used when using TLS/SSL. Mandatory when `proto` contains "https"
(O): Optional
(M): Mandatory
(D): Depends other keys...
Templates
---------
- `_base`: static template
- `_backuppc`: access to [BackupPC](http://backuppc.sourceforge.net/) (be careful: you need to install [fcgiwrap](https://packages.debian.org/jessie/fcgiwrap))
- `_dokuwiki`
- `_redirect`: should not be called explicitly
- `_nagios3`: access to Nagios3 (be careful: you need to install [fcgiwrap](https://packages.debian.org/jessie/fcgiwrap))
- `_phalcon`: Phalcon PHP Framework
- `_php`: PHP base template. Can work with many frameworks/tools
- `_php_index`: Same as above. But you can only run index.php
- `_proxy`
- `_wordpress`
Templates works as parent-child.
About proxy template
--------------------
Proxy template allow you to use Nginx as reverse proxy. Usefull when you have an application service such as Redmine, Jenkins...
You have many key added to vhost key:
- `upstream_name`: (O) upstream name used to pass proxy
- `proxy_params`: (M) list of raw params passed to the vhost
(O) : Optional
Default vhosts
--------------
You can manage default vhost by setting domain name to these variables.
- `nginx_default_vhost`
- `nginx_default_vhost_ssl`

View File

@ -0,0 +1 @@
<h1>HTML works</h1>

View File

@ -0,0 +1,3 @@
<?php
echo "<h1>PHP works!</h1>";

View File

@ -1,68 +0,0 @@
def nginx_site_filename(site):
if 'filename' in site:
return site['filename']
else:
return nginx_site_name(site)
def nginx_site_name(site):
if isinstance(site['name'], list):
return site['name'][0]
else:
return site['name']
def nginx_ssl_dir(pair, ssl_dir):
return ssl_dir + '/' + nginx_site_filename(pair)
def nginx_key_path(pair, ssl_dir):
if 'dest_key' in pair:
return pair['dest_key']
else:
return nginx_ssl_dir(pair, ssl_dir) + '/' + nginx_site_filename(pair) + '.key'
def nginx_cert_path(pair, ssl_dir):
if 'dest_cert' in pair:
return pair['dest_cert']
else:
return nginx_ssl_dir(pair, ssl_dir) + '/' + nginx_site_filename(pair) + '.crt'
def nginx_all_site_names(site):
all_sites = []
if isinstance(site['name'], list):
all_sites = all_sites + site['name']
else:
all_sites.append(site['name'])
if 'redirect_from' in site:
if isinstance(site['redirect_from'], list):
all_sites = all_sites + site['redirect_from']
else:
all_sites.append(site['redirect_from'])
return all_sites
def nginx_search_by_ssl_name(sites, ssl_name):
if isinstance(ssl_name, list):
comp_ssl_name = ssl_name[0]
else:
comp_ssl_name = ssl_name
res = None
for site in sites:
if 'ssl_name' in site and site['ssl_name'] == comp_ssl_name:
res = site
break
return res
class FilterModule(object):
''' Nginx module '''
def filters(self):
return {
'nginx_site_filename': nginx_site_filename,
'nginx_site_name': nginx_site_name,
'nginx_ssl_dir': nginx_ssl_dir,
'nginx_key_path': nginx_key_path,
'nginx_cert_path': nginx_cert_path,
'nginx_all_site_names': nginx_all_site_names,
'nginx_search_by_ssl_name': nginx_search_by_ssl_name
}

View File

@ -1,10 +0,0 @@
def php_default_upstream_socket(php_version):
return '/run/php/php%s-fpm.sock' % php_version
class FilterModule(object):
''' PHP module '''
def filters(self):
return {
'php_default_upstream_socket': php_default_upstream_socket,
}

View File

@ -1,14 +1,4 @@
--- ---
- name: Reload nginx - name: reload nginx
ansible.builtin.service: action: service name=nginx state=reloaded enabled=yes
name: nginx
state: reloaded
- name: Restart nginx
ansible.builtin.service:
name: nginx
state: restarted
- name: Setup
ansible.builtin.setup:

View File

@ -1,32 +1,16 @@
--- ---
galaxy_info: galaxy_info:
author: Emilien Mantel author: Emilien Mantel
namespace: HanXHX description: Nginx for Debian
role_name: nginx company:
description: Nginx for Debian / Ubuntu license: GPLv2
company: TripleStack min_ansible_version: 2.0
license: GPLv2
min_ansible_version: '2.11'
platforms: platforms:
- name: Debian - name: Debian
versions: versions:
- buster - wheezy
- bullseye - jessie
- bookworm categories:
- name: Ubuntu - web
versions:
- focal
- jammy
galaxy_tags:
- web
- debian
- proxy
- http
- http2
- https
- ssl
- tls
- nginx
- cdn
dependencies: [] dependencies: []

View File

@ -1,19 +0,0 @@
# Molecule managed
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
{% if item.env is defined %}
{% for var, value in item.env.items() %}
{% if value %}
ENV {{ var }} {{ value }}
{% endif %}
{% endfor %}
{% endif %}
RUN apt-get update && \
apt-get install -y python3 sudo bash ca-certificates iproute2 python-apt-common \
&& apt-get clean

View File

@ -1,42 +0,0 @@
---
scenario:
test_sequence:
- dependency
- syntax
- create
- prepare
- converge
- idempotence
- verify
- destroy
dependency:
name: galaxy
options:
requirements-file: ./molecule/_shared/requirements.yml
role-file: ./molecule/_shared/requirements.yml
driver:
name: docker
role_name_check: 1
provisioner:
name: ansible
env:
ANSIBLE_FILTER_PLUGINS: "../../filter_plugins"
config_options:
defaults:
deprecation_warnings: false
callback_whitelist: timer,profile_tasks
fact_caching: jsonfile
fact_caching_connection: ./cache
forks: 100
connection:
pipelining: true
playbooks:
converge: ../_shared/converge.yml
prepare: ../_shared/prepare.yml
verify: ../_shared/verify.yml
inventory:
links:
group_vars: ../_shared/group_vars
verifier:
name: ansible

View File

@ -1,9 +0,0 @@
---
- name: Converge # noqa: role-name[path]
hosts: all
gather_facts: true
vars:
nginx_debug_role: true
roles:
- ../../../

View File

@ -1,250 +0,0 @@
---
# Internal vars
int_ansible_ssl_dir: '/etc/ansible-ssl'
# Role vars
nginx_worker_processes: 1 # Ansible can't detect CPU count
nginx_apt_package: 'nginx-extras'
nginx_module_packages: ['libnginx-mod-http-headers-more-filter']
nginx_custom_core:
- 'worker_rlimit_nofile 4242;'
nginx_upstreams:
- name: 'test'
servers:
- path: '127.0.0.1:80'
max_conns: 150
weight: 10
down: false
- name: 'test-absent'
servers:
- path: '127.0.0.1:80'
max_conns: 150
weight: 10
down: false
state: 'absent'
nginx_htpasswd:
- name: 'hello'
description: 'Please login!'
users:
- name: 'hx'
password: 'asdfg'
state: 'absent'
- name: 'hanx'
password: 'qwerty'
- name: 'deleteme'
description: 'Please login!'
users: []
state: 'absent'
nginx_acmesh: true
nginx_acmesh_test: true
nginx_ssl_pairs:
- name: 'test-ssl-selfsigned.local'
self_signed: true
force: false
- name:
- 'test-ssl-predeployed.local'
- 'test-multiple-name.local' # Hack: tests for acme with multiple name, without using acme
dest_key: "{{ int_ansible_ssl_dir }}/test.key"
dest_cert: "{{ int_ansible_ssl_dir }}/test.crt"
- name: 'test-ssl.local'
key: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvavrJWFp3Al2VwRgKx+4Y2mbRRvoxvyd2pyN0xMJ/tCJscaG
8s60v6WZ9FcCOeMkSI2DXsk4z7pbQdQn0h2GDr/5MOJkPAVWSWEN46tpaLZ3v0zp
88ZIbnEk1G0PsdFuW/pnLsakPlAMrl1VArFsV6YsatLt30UIYYcRO97StkoOehCx
A5w+XqtfHZeQZ0/DS81633gwYUcMuSTUFZ60r7ge1/m77DTSKg3rTVk5sebP8cjS
+aWHvxP/GyvvDsT+3gjRJx2/5O3JkfH0zaOsaU2Avj0PR0c5rhynrNO/l1k+GJJB
cbBrM+yA8Ofzp4oXUrCfaIq3RuL3Pd+khcKsiwIDAQABAoIBAQCPpAMQ7BUfbosQ
m1+5SOx7XR8Z12kSSX3CcY12rJSFRakB2TeZ6rE38lIFmV82N67iw0kaH4nGx3sU
/3aoyXMc+IXfX5RJYEFYkQfTw5ywkH9fgQAsfZ2dBlK+DVo1cEYDoj9CTW1VQ4pX
Ape+0l8agd5hiBxdWgpe0ctbbARnx584viLiA/iPBDNxKi9zEYw+WP7hSj5QWahr
a09tubcC4L6tjvv8CoZTRSKfCW64vWRDvE6vmA+zJN9Arc1WTYzF1KO1Gybwf8h7
stJb191smAgGDFhKo0j58ncyAnrS1k4mapm86QQhlfIA6DKvvC0qm3KdQns5b7HM
PyzW0hwBAoGBAO2mTVTOsziom9vtBwM0nRMMEgynR2X3EKMJz2mjcCf66f1F+aQ5
DvQFM2V8S2s1nGnPh8NKKZ8DxW1NKuR4qx82zeAXpUs9ibHxOnw4YRC485zqc2Wt
fSO1OEDYeKyzWP1nGGtCntYUXzJnWn/wz0mBGKzLKTuLwyFIKx1b7bybAoGBAMxR
N+lT57rX6d4GUqcgNOuWMZ/D8egnE5+hsoiFnHOisRLOgUgBBSy4rwAZx+rdHYT+
RO11L1PLYEzyvnO0f13R+N7aqKwNXDSzZGA+jb4pjkVidIC2smG/JYKJH5Z+kakw
mwMKP0wdRZJsCaMgScHmWJS8d6Ox/XJJoWrTWTbRAoGAWJlEgVaiaIArwz1F/QLz
gHNik0cWDkSi9jWlFxwwpycbbypUXM5M7dq2g6JoN6sACk6trbgLdlYgl5RKZm06
VuPGs0H9hOSHXkix5jfasDJT2G9r4D9ixRo9w6cwriobBjYWW3612tgzeYYgrkwn
655uhZUkZSfA8rqGIGbyZfsCgYAf5WH8G+wmIATTc1s92epJCOZwUY+XNVp75itP
4sPczX4lOHW4PuiG5cH0GxI5mRE9rNAn3c5on2xGNvMCbyAfDmNyruH8Eg3d8E9w
MvO/xw79x/P2EA9i8QszCKMUxGeK6RqZ6+SbxkoRJKqQe77n9UTI228179hoGhSH
77ySsQKBgQC8SSZn6a8PpSIIFXB9WCFMwfGFYbUz0wvpaeZP8GKx3BEzMeJqSUaJ
hrQgpwQXkueeamlCQcvV3AUCoBRWTYRLDrWiUIXuIgikDWBFp6TBvTnVRI7iktly
fNED7jXOSjJqnFmdkZlAI5V8dM++mVYVykJD6jcaVRQvxqFLrhSaRg==
-----END RSA PRIVATE KEY-----
cert: |
-----BEGIN CERTIFICATE-----
MIIDBTCCAe2gAwIBAgIJALKJfbk5vuieMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNV
BAMMDnRlc3Qtc3NsLmxvY2FsMB4XDTE2MDExMTE2NDI0NFoXDTI2MDEwODE2NDI0
NFowGTEXMBUGA1UEAwwOdGVzdC1zc2wubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQC9q+slYWncCXZXBGArH7hjaZtFG+jG/J3anI3TEwn+0Imx
xobyzrS/pZn0VwI54yRIjYNeyTjPultB1CfSHYYOv/kw4mQ8BVZJYQ3jq2lotne/
TOnzxkhucSTUbQ+x0W5b+mcuxqQ+UAyuXVUCsWxXpixq0u3fRQhhhxE73tK2Sg56
ELEDnD5eq18dl5BnT8NLzXrfeDBhRwy5JNQVnrSvuB7X+bvsNNIqDetNWTmx5s/x
yNL5pYe/E/8bK+8OxP7eCNEnHb/k7cmR8fTNo6xpTYC+PQ9HRzmuHKes07+XWT4Y
kkFxsGsz7IDw5/OnihdSsJ9oirdG4vc936SFwqyLAgMBAAGjUDBOMB0GA1UdDgQW
BBRaSF1L+ivPhmIVGQjtviBqZWDS9DAfBgNVHSMEGDAWgBRaSF1L+ivPhmIVGQjt
viBqZWDS9DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCjrgB9+Zuq
Rx7T2mRUl4jf75dLabuBQD0ePALTtvNyBSghhzSr90mE7GlFOYAv0JsmEa3R1LVF
wLPIdrIhNHpt7hN0PkhUlfgmxBnRSCfhpiq4xxsDVFM7ehtDz4+dv1LUDMXo07+E
f24g9aqmypiFzHisUQrYIhtQmHxRpKyGp6kDAW9qNxg6k/Um00aHdYfuD9ER4ksR
f8Hto7f+vssKxCRY2OZXqq13PxEwC5+hgAUkTdrycA/moXFuHJi3lCnCND7sSzvG
tXBggOusyFZFC4bs2m+V+Z+RN+tK2c/c0nq5HR8MV5HwIm4Z8GoT2/0BfJ00cgWL
lVz0gDBfdH8f
-----END CERTIFICATE-----
nginx_custom_http:
- 'add_header X-ansible 1;'
- 'geoip_country {% if ansible_os_family == "Debian" %}/usr/share/GeoIP/GeoIP.dat{% else %}/usr/local/share/GeoIP/GeoIP.dat{% endif %};'
- 'map $geoip_country_code $allowed_country {'
- ' default yes;'
- ' MA no;'
- ' DZ no;'
- ' TN no;'
- '}'
nginx_default_site: 'test.local'
nginx_default_site_ssl: 'test-ssl-predeployed.local'
nginx_sites:
- name:
- 'test.local'
- 'test-alias.local'
- 'test2-alias.local'
template: '_base'
filename: 'first-test'
override_try_files: '$uri/ $uri =404'
headers:
'X-Frame-Options': 'deny always'
'X-ansible-default': '1'
manage_local_content: false
use_error_log: true
more:
- 'autoindex off;'
location:
'/test':
- 'return 403;'
'/gunther':
- 'return 404;'
'/status':
- 'stub_status on;'
- 'access_log off;'
- 'allow 127.0.0.1;'
- 'deny all;'
- name: 'test-htpasswd.local'
template: '_base'
location_before:
'/hello':
- htpasswd: 'hello'
location:
'/public':
- htpasswd: false
use_error_log: true
- name: 'test-htpasswd-all.local'
template: '_base'
htpasswd: 'hello'
- name: 'test-location.local'
template: '_base'
location_before:
'/b':
- 'alias /var/tmp;'
'/c':
- 'alias /var/tmp;'
location:
'/':
- 'alias /var/tmp;'
'/a':
- 'alias /var/tmp;'
location_order_before:
- '/b'
- '/c'
location_order:
- '/'
- '/a'
- name: 'test-php.local'
php_upstream: "manual"
upstream_params:
- 'fastcgi_param FOO bar;'
redirect_from:
- 'www.test-php.local'
template: '_php'
use_error_log: true
use_access_log: true
- name: 'test-php-index.local'
template: '_php_index'
php_upstream: 'hx_unix'
- name: 'test-php-index2.local'
template: '_php_index2'
php_upstream: 'hx_ip'
- name: 'test-proxy.local'
listen:
- 8080
template: '_proxy'
upstream_name: 'test'
headers:
'X-proxyfied': '1'
- name: 'deleted.local'
state: 'absent'
- name: 'redirect-to.local'
redirect_to: 'http://test.local'
- name: 'test-ssl.local'
proto: ['http', 'https']
template: '_base'
- name:
- 'test-ssl-selfsigned.local'
- 'www.test-ssl-selfsigned.local'
proto: ['http', 'https']
template: '_base'
hsts: 'max-age=1664;'
- name: 'test-ssl-predeployed.local'
proto: ['http', 'https']
template: '_base'
ssl_name: 'test-ssl-predeployed.local'
headers:
'X-ansible-default': '1'
ssl_template: false
- name: 'test-ssl-redirect.local'
proto: ['https']
template: '_base'
ssl_name: 'test-ssl.local'
redirect_https: true
- name:
- 'test-ssl-redirect-many.local'
- 'test-ssl-redirect-many2.local'
listen_ssl: [8443]
proto: ['https']
template: '_base'
ssl_name: 'test-ssl.local'
redirect_https: true
redirect_from:
- 'www.test-ssl-redirect-many.local'
- 'www.test-ssl-redirect-many2.local'
- name: 'test-ssl-proxy-protocol.local'
proto: ['http', 'https']
listen_proxy_protocol: [20080]
listen_proxy_protocol_ssl: [20443]
template: '_base'
ssl_name: 'test-ssl.local'
headers:
'X-Proxy-Protocol': '1'
# - name: '{{ ngrok.stdout }}'
# proto: ['http', 'https']
# listen_proxy_protocol: [21080]
# listen_proxy_protocol_ssl: [21443]
# template: '_base'
# ssl_name: '{{ ngrok.stdout }}'
# headers:
# 'X-acme': '1'
# - name: 'test-custom-template.local'
# custom_template: 'templates/custom_template.conf.j2'
# root: '/tmp/custom-template'
nginx_php: "{{ [{'upstream_name': 'manual', 'sockets': [{'host': '127.0.0.1', 'port': '9636'}]}] }}"
nginx_dh_length: 1024

View File

@ -1,109 +0,0 @@
---
- name: Prepare
hosts: all
gather_facts: true
tasks:
- name: APT_REPOSITORY | Install backports
ansible.builtin.apt_repository:
repo: 'deb http://httpredir.debian.org/debian {{ ansible_distribution_release }}-backports main'
state: present
when: nginx_backports is defined and nginx_backports
- name: APT | Install needed packages
ansible.builtin.apt:
pkg: "{{ packages }}"
update_cache: true
cache_valid_time: 3600
state: present
vars:
packages:
- cron
- curl
- daemonize
- jq
- nghttp2
- strace
- vim
- unzip
- name: APT | Install PHP
ansible.builtin.apt:
pkg: "{{ pkgs }}"
update_cache: true
cache_valid_time: 3600
state: present
vars:
pkgs:
- php-cli
- php-fpm
- name: SHELL | Get current PHP version # noqa: risky-shell-pipe
ansible.builtin.shell: php --version | awk '/^PHP/ { print $2 }' | grep -o -E '^.{3}'
changed_when: false
register: cur_php_version
- name: SERVICE | Ensure PHP-FPM is started
ansible.builtin.service:
name: "php{{ cur_php_version.stdout }}-fpm"
state: started
- name: USER | Create PHP User foo
ansible.builtin.user:
name: foo
system: true
- name: INCLUDE_ROLE | hanxhx.php
ansible.builtin.include_role:
name: "hanxhx.php"
vars:
php_version: "{{ cur_php_version.stdout }}"
php_autoremove_default_pool: false
php_fpm_poold:
- name: 'hx_unix'
user: 'foo'
php_value:
display_errors: 'Off'
php_admin_value:
memory_limit: '98M'
- name: 'hx_ip'
listen: '127.0.0.1:9636'
- name: FILE | Create an internal SSL dir
ansible.builtin.file:
path: "{{ int_ansible_ssl_dir }}"
state: directory
mode: "0750"
owner: root
group: root
- name: COPY | Deploy test cert/key
ansible.builtin.copy:
src: "file/{{ item }}"
dest: "{{ int_ansible_ssl_dir }}/{{ item }}"
mode: "0640"
owner: root
group: root
loop:
- 'test.key'
- 'test.crt'
- name: COPY | Add all hosts in /etc/hosts
ansible.builtin.copy:
content: |
127.0.0.1 localhost
{% for s in nginx_sites %}
{% if s.name is string %}
127.0.0.1 {{ s.name }}
{% else %}
127.0.0.1 {% for n in s.name %}{{ n }} {% endfor %}
{% endif %}
{% if s.redirect_from is defined %}
127.0.0.1 {% for rf in s.redirect_from %}{{ rf }} {% endfor %}
{% endif %}
{% endfor %}
dest: "/etc/hosts"
mode: "0644"
owner: root
group: root
unsafe_writes: true

View File

@ -1,7 +0,0 @@
---
roles:
- name: hanxhx.php
collections:
- community.general

View File

@ -1,16 +0,0 @@
# {{ ansible_managed }} - custom template
server {
listen 80;
listen 8888 http2;
listen 9999 http2 proxy_protocol;
server_name {{ item.name }};
index index.html index.htm;
root {{ item.root }};
location / {
try_files $uri $uri/ =404;
}
}

View File

@ -1,266 +0,0 @@
---
- name: Verify
hosts: all
gather_facts: true
vars:
nginx_root: "/srv/www"
tasks:
# --------------------------------
# Deploy index files
# --------------------------------
- name: -- Add PHP file --
ansible.builtin.copy:
dest: "{{ nginx_root }}/{{ item }}/public/index.php"
content: "<?php phpinfo();"
mode: "0644"
owner: root
group: root
loop:
- 'test-php.local'
- 'test-php-index.local'
- 'test-php-index2.local'
- name: -- Add Directories --
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
loop:
- "{{ nginx_root }}/test-htpasswd.local/public/hello"
- "/tmp/custom-template"
- name: -- Add HTML file --
ansible.builtin.copy:
dest: "{{ item }}/index.html"
content: "Index HTML test OK\n"
mode: "0644"
owner: root
group: root
loop:
- '{{ nginx_root }}/first-test/public'
- '/var/tmp'
- '{{ nginx_root }}/test-htpasswd-all.local/public'
- '{{ nginx_root }}/test-ssl.local/public'
- '{{ nginx_root }}/test-ssl-selfsigned.local/public'
- '{{ nginx_root }}/test-ssl-predeployed.local/public'
- '{{ nginx_root }}/test-ssl-proxy-protocol.local/public'
- name: -- Create directory --
ansible.builtin.file:
path: "{{ nginx_root }}/test-htpasswd.local/public/hello"
state: directory
mode: "0755"
owner: root
group: root
- name: -- Add HTML file hello --
ansible.builtin.copy:
dest: "{{ nginx_root }}/test-htpasswd.local/public/hello/index.html"
content: "hello\n"
mode: "0644"
owner: root
group: root
# --------------------------------
# Test custom facts
# --------------------------------
- name: -- CHECK FACTS --
ansible.builtin.assert:
that: "ansible_local.nginx.fact_nginx_sites[0].name[0] == 'test.local'"
# --------------------------------
# Simple sites tests
# --------------------------------
- name: -- VERIFY SITES --
ansible.builtin.uri:
url: "http://{{ item | nginx_site_name }}{% if item.listen is defined %}:{{ item.listen[0] }}{% endif %}/"
status_code: '200,301,302,401,403'
follow_redirects: none
loop: "{{ nginx_sites }}"
when: item.state is undefined or item.state != "absent"
changed_when: false
- name: -- VERIFY FORBIDDEN --
ansible.builtin.uri:
url: "http://test-php-index.local/phpinfo.php"
status_code: 403
- name: -- VERIFY REDIRECT SITES --
ansible.builtin.uri:
url: "http://{{ item.redirect_from[0] }}/"
status_code: 301
follow_redirects: none
loop: "{{ nginx_sites }}"
when: item.redirect_from is defined and (item.state is undefined or item.state != "absent") and (item.proto is not defined or 'https' not in item.proto)
changed_when: false
- name: -- VERIFY REDIRECT HTTPS SITES --
ansible.builtin.uri:
url: "https://{{ item.redirect_from[0] }}:{{ item.listen_ssl[0] | default(443) }}/"
status_code: 301
follow_redirects: none
validate_certs: false
loop: "{{ nginx_sites }}"
when: item.redirect_from is defined and (item.state is undefined or item.state != "absent") and item.proto is defined and 'https' in item.proto
changed_when: false
# --------------------------------
# PHP
# --------------------------------
- name: -- VERIFY PHP SITES --
ansible.builtin.uri:
url: "http://{{ item.name }}/"
return_content: true
register: p
loop: "{{ nginx_sites }}"
when: >
item.template is defined and
(item.template == '_php' or item.template == '_php_index' or item.template == '_php_index2')
failed_when: p.content.find('PHP Version') == -1
- name: -- VERIFY INDEX2 --
ansible.builtin.uri:
url: "http://test-php-index2.local/lorem.php?ipsum=sit&dolor=amet"
return_content: true
register: p2
failed_when: p2.content.find('PHP Version') == -1
# --------------------------------
# Basic Auth
# --------------------------------
- name: -- VERIFY AUTH BASIC NONE --
ansible.builtin.uri:
url: "http://test-htpasswd.local/hello/"
status_code: 401
- name: -- VERIFY AUTH BASIC FAIL --
ansible.builtin.uri:
url: "http://test-htpasswd.local/hello/"
status_code: 401
user: "fail"
password: "fail"
force_basic_auth: true
- name: -- VERIFY AUTH BASIC OK --
ansible.builtin.uri:
url: "http://test-htpasswd.local/hello/"
user: "hanx"
password: "qwerty"
force_basic_auth: true
- name: -- VERIFY AUTH BASIC FAIL GLOBAL --
ansible.builtin.uri:
url: "http://test-htpasswd-all.local/"
status_code: 401
user: "fail"
password: "fail"
force_basic_auth: true
- name: -- VERIFY AUTH BASIC OK GLOBAL --
ansible.builtin.uri:
url: "http://test-htpasswd-all.local/"
user: "hanx"
password: "qwerty"
force_basic_auth: true
# --------------------------------
# SSL
# --------------------------------
- name: -- VERIFY SSL --
ansible.builtin.uri:
url: "https://{{ item }}/"
return_content: true
validate_certs: false
register: sslok
failed_when: sslok.content.find('Index HTML test OK') == -1
loop:
- 'test-ssl-predeployed.local'
- 'test-ssl-selfsigned.local'
- 'test-ssl.local'
- name: -- VERIFY SSL REDIRECT --
ansible.builtin.uri:
url: "http://{{ item.name }}/"
validate_certs: false
status_code: 301
return_content: true
follow_redirects: none
register: sslredirok
failed_when: '"https://%s%s" % (item.name, ":" + item.port if item.port is defined else "") not in sslredirok.location'
loop:
- name: 'test-ssl-redirect.local'
- name: 'test-ssl-redirect-many.local'
port: '8443'
- name: 'test-ssl-redirect-many2.local'
port: '8443'
# --------------------------------
# Default sites
# --------------------------------
- name: -- VERIFY DEFAULT SITE --
ansible.builtin.uri:
url: 'http://127.0.0.1/'
return_content: true
register: vdefault
failed_when: >
vdefault.content.find('Index HTML test OK') == -1 or
vdefault.x_ansible_default is not defined
- name: -- VERIFY DEFAULT SITE + STUB STATUS--
ansible.builtin.uri:
url: 'http://127.0.0.1/status'
return_content: true
register: vdefault_status
failed_when: >
vdefault_status.content.find('Active connections') == -1 or
vdefault_status.x_ansible_default is not defined
- name: -- VERIFY DEFAULT SSL SITE --
ansible.builtin.uri:
url: 'https://127.0.0.1/'
return_content: true
validate_certs: false
register: vdefault
failed_when: >
vdefault.content.find('Index HTML test OK') == -1 or
vdefault.x_ansible_default is not defined
- name: -- VERIFY NOT DEFAULT SITE --
ansible.builtin.uri:
url: 'http://test-php.local/'
return_content: true
register: vphp
failed_when: vphp.x_ansible_default is defined
- name: -- VERIFY NOT DEFAULT SSL SITE --
ansible.builtin.uri:
url: 'https://test-ssl.local/'
return_content: true
validate_certs: false
register: notdefaultssl
failed_when: notdefaultssl.x_ansible_default is defined
# --------------------------------
# Check Proxy protocol
# --------------------------------
- name: SHELL | Check HTTP proxy protocol
ansible.builtin.shell: set -o pipefail && curl -I --haproxy-protocol http://test-ssl-proxy-protocol.local:20080 | grep -qi 'X-Proxy-Protocol'
args:
executable: /bin/bash
changed_when: false
- name: SHELL | Check HTTPS proxy protocol
ansible.builtin.shell: set -o pipefail && curl -I --haproxy-protocol -k https://test-ssl-proxy-protocol.local:20443 | grep -qi 'X-Proxy-Protocol'
args:
executable: /bin/bash
changed_when: false
# --------------------------------
# Check HTTP2
# --------------------------------
- name: SHELL | Check HTTP2
ansible.builtin.shell: set -o pipefail && nghttp -nv https://localhost 2> /dev/null | grep -q h2
args:
executable: /bin/bash
changed_when: false

View File

@ -1,13 +0,0 @@
---
platforms:
- name: debian-11
image: dokken/debian-11
command: /lib/systemd/systemd
dockerfile: ../_shared/Dockerfile.j2
capabilities:
- SYS_ADMIN
cgroupns_mode: host
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
privileged: true

View File

@ -1,13 +0,0 @@
---
platforms:
- name: debian-13
image: dokken/debian-13
command: /lib/systemd/systemd
dockerfile: ../_shared/Dockerfile.j2
capabilities:
- SYS_ADMIN
cgroupns_mode: host
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
privileged: true

View File

@ -1,13 +0,0 @@
---
platforms:
- name: debian-12
image: dokken/debian-13
command: /lib/systemd/systemd
dockerfile: ../_shared/Dockerfile.j2
capabilities:
- SYS_ADMIN
cgroupns_mode: host
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
privileged: true

View File

@ -1,20 +0,0 @@
---
platforms:
- name: ubuntu-20.04
image: dokken/ubuntu-20.04
command: /lib/systemd/systemd
dockerfile: ../_shared/Dockerfile.j2
capabilities:
- SYS_ADMIN
cgroupns_mode: host
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
privileged: true
# Segfault on Ubuntu 20.04 with `nginx-extras` package...
provisioner:
inventory:
host_vars:
ubuntu-20.04:
nginx_apt_package: 'nginx-full'

View File

@ -1,13 +0,0 @@
---
platforms:
- name: ubuntu-22.04
image: dokken/ubuntu-22.04
command: /lib/systemd/systemd
dockerfile: ../_shared/Dockerfile.j2
capabilities:
- SYS_ADMIN
cgroupns_mode: host
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
privileged: true

View File

@ -1,13 +0,0 @@
---
platforms:
- name: ubuntu-24.04
image: dokken/ubuntu-24.04
command: /lib/systemd/systemd
dockerfile: ../_shared/Dockerfile.j2
capabilities:
- SYS_ADMIN
cgroupns_mode: host
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
privileged: true

View File

@ -1,4 +0,0 @@
---
collections:
- community.general

View File

@ -1,57 +1,21 @@
--- ---
- name: TEMPLATE | Deploy nginx.conf - name: TEMPLATE | Deploy nginx.conf
ansible.builtin.template: template: >
src: "etc/nginx/nginx.conf.j2" src=etc/nginx/nginx.conf.j2
dest: "{{ nginx_etc_dir }}/nginx.conf" dest=/etc/nginx/nginx.conf
mode: "0644" notify: reload nginx
owner: root
group: root
notify: Reload nginx
- name: TEMPLATE | Deploy all helpers - name: TEMPLATE | Deploy all helpers
ansible.builtin.template: template: >
src: "{{ item }}" src={{ item }}
dest: "{{ nginx_helper_dir }}/{{ item | basename | regex_replace('.j2$', '') }}" dest={{ nginx_helper_dir }}/{{ item | basename | regex_replace('\.j2$','') }}
mode: "0644"
owner: root
group: root
with_fileglob: '../templates/etc/nginx/helper/*.j2' with_fileglob: '../templates/etc/nginx/helper/*.j2'
notify: Reload nginx notify: reload nginx
- name: TEMPLATE | Deploy custom http configuration - name: TEMPLATE | Deploy custom http configuration
ansible.builtin.template: template: >
src: "etc/nginx/conf.d/custom.conf.j2" src=etc/nginx/conf.d/custom.conf.j2
dest: "{{ nginx_etc_dir }}/conf.d/custom.conf" dest=/etc/nginx/conf.d/custom.conf
mode: "0644" notify: reload nginx
owner: root
group: root
notify: Reload nginx
- name: LINEINFILE | Fix path
ansible.builtin.lineinfile:
regexp: '{{ item.0.regexp }}'
line: '{{ item.0.line }}'
dest: '{{ item.1 }}'
loop: "{{ list_one | product(list_two) | list }}"
vars:
list_one:
- regexp: '^fastcgi_param SCRIPT_FILENAME'
line: 'fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;'
- regexp: '^fastcgi_param DOCUMENT_ROOT'
line: 'fastcgi_param DOCUMENT_ROOT $realpath_root;'
list_two:
- '{{ nginx_etc_dir }}/fastcgi.conf'
when: nginx_fastcgi_fix_realpath
- name: COPY | Add modules manually
ansible.builtin.copy:
content: |
{% for m in nginx_load_modules %}
load_module {{ m }};
{% endfor %}
dest: "{{ nginx_etc_dir }}/modules-enabled/000-modules.conf"
mode: "0644"
owner: root
group: root
notify: Reload nginx

View File

@ -1,21 +1,19 @@
--- ---
- name: FILE | Delete htpasswd file - name: FILE | Delete htpasswd file
ansible.builtin.file: file: >
path: "{{ nginx_htpasswd_dir }}/{{ item.name }}" path={{ nginx_htpasswd_dir }}/{{ item.name }}
state: absent state=absent
loop: "{{ nginx_htpasswd }}" with_items: nginx_htpasswd
when: item.state is defined and item.state == 'absent' when: item.state is defined and item.state == 'absent'
no_log: "{{ not nginx_debug_role }}"
- name: HTPASSWD | Manage files - name: HTPASSWD | Manage files
community.general.htpasswd: htpasswd: >
name: "{{ item.1.name }}" name={{ item.1.name }}
password: "{{ item.1.password }}" password={{ item.1.password }}
path: "{{ nginx_htpasswd_dir }}/{{ item.0.name }}" state={{ item.1.state | default('present') }}
mode: "0644" path={{ nginx_htpasswd_dir }}/{{ item.0.name }}
owner: root with_subelements:
group: root - nginx_htpasswd
loop: "{{ nginx_htpasswd | subelements('users') }}" - users
when: item.0.state is not defined or item.0.state == 'present' when: item.0.state is not defined or item.0.state == 'present'
no_log: "{{ not nginx_debug_role }}"

13
tasks/install.yml 100644
View File

@ -0,0 +1,13 @@
---
- name: APT | Install nginx and dependencies
apt: >
pkg={{ nginx_apt_package }}
state=present
update_cache=yes
cache_valid_time=3600
default_release={{ ansible_distribution_release + '-backports' if nginx_backports else ansible_distribution_release }}
- name: APT | Install python-passlib
apt: pkg=python-passlib state=present

View File

@ -1,27 +0,0 @@
---
- name: SET_FACT | Bypass https://github.com/ansible/ansible/issues/19874
ansible.builtin.set_fact:
ansible_distribution_release: 'buster'
when: ansible_facts.distribution_major_version == "buster/sid"
- name: APT | Update cache
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
changed_when: false
- name: APT | Install nginx and dependencies
ansible.builtin.apt:
pkg: "{{ nginx_apt_package }}"
default_release: "{{ ansible_distribution_release + '-backports' if (nginx_backports and ansible_distribution == 'Debian') else ansible_distribution_release }}"
- name: APT | Install nginx modules
ansible.builtin.apt:
pkg: "{{ nginx_module_packages }}"
state: present
- name: APT | Install passlib lib
ansible.builtin.apt:
pkg: "python3-passlib"
state: present

View File

@ -1,36 +0,0 @@
---
- name: STAT | Check acme.sh is installed
ansible.builtin.stat:
path: "{{ nginx_acmesh_dir }}"
register: acme
- name: Install acme.sh if needed
when: not acme.stat.exists
block:
- name: APT | Install git
ansible.builtin.apt:
pkg: git
- name: GIT | Get acme.sh
ansible.builtin.git:
repo: 'https://github.com/Neilpang/acme.sh.git'
dest: '{{ nginx_acmesh_git_dir }}'
update: false
version: master
- name: COMMAND | Install acme.sh
ansible.builtin.command: ./acme.sh --install --home "{{ nginx_acmesh_dir }}"
args:
chdir: "{{ nginx_acmesh_git_dir }}"
creates: "{{ nginx_acmesh_dir }}"
- name: COMMAND | Force acme.sh to use letsencrypt (instead of zerossl)
ansible.builtin.command: '{{ nginx_acmesh_dir }}/acme.sh --set-default-ca --server letsencrypt --home "{{ nginx_acmesh_dir }}"'
changed_when: true
- name: FILE | Remove temp acme.sh dir
ansible.builtin.file:
path: '{{ nginx_acmesh_git_dir }}'
state: absent

View File

@ -1,8 +0,0 @@
---
- name: INCLUDE_TASKS | Install
ansible.builtin.include_tasks: "{{ ansible_os_family }}.yml"
- name: IMPORT_TASKS | acme
ansible.builtin.import_tasks: "acme.yml"
when: nginx_acmesh

View File

@ -1,30 +1,23 @@
--- ---
- name: INCLUDE_VARS | Related to OS - name: INCLUDE | Install
ansible.builtin.include_vars: "{{ ansible_os_family }}.yml" include: install.yml
tags: ['nginx::site', 'nginx::ssl']
- name: INCLUDE_TASKS | Install - name: INCLUDE | Prepare
ansible.builtin.import_tasks: "install/main.yml" include: prepare.yml
tags: ['nginx::site', 'nginx::ssl']
- name: IMPORT_TASKS| Prepare - name: INCLUDE | Install
ansible.builtin.import_tasks: prepare.yml include: config.yml
tags: ['nginx::site', 'nginx::ssl']
- name: IMPORT_TASKS| Install - name: INCLUDE | Upstream configuration
ansible.builtin.import_tasks: config.yml include: upstream.yml
- name: IMPORT_TASKS| Upstream configuration - name: INCLUDE | htpasswd configuration
ansible.builtin.import_tasks: upstream.yml include: htpasswd.yml
- name: IMPORT_TASKS| htpasswd configuration - name: INCLUDE | SSL configuration
ansible.builtin.import_tasks: htpasswd.yml include: ssl.yml
- name: IMPORT_TASKS| SSL configuration - name: INCLUDE | Vhosts configuration
ansible.builtin.import_tasks: ssl/main.yml include: vhost.yml
tags: ['nginx::ssl']
- name: IMPORT_TASKS| Sites configuration
ansible.builtin.import_tasks: site.yml
tags: ['nginx::site']

View File

@ -1,47 +1,16 @@
--- ---
- name: SHELL | Get Nginx version - name: SHELL | Get Nginx version
ansible.builtin.shell: nginx -v 2>&1 | sed -r 's#.*/##;' | cut -d ' ' -f 1 shell: nginx -v 2>&1 | sed -r 's#.*/##;' | cut -d ' ' -f 1
args:
executable: /bin/sh
register: nginx_version register: nginx_version
changed_when: false changed_when: false
check_mode: false
tags:
- skip_ansible_lint
- name: SHELL | Get module list - name: SHELL | Get module list
ansible.builtin.shell: | shell: nginx -V 2>&1 | tr -- - '\n' | grep -A 1 with | grep _module | sed -r 's/_module\s*$//g' |sort
nginx -V 2>&1 | register: nginx_modules
tr -- - '\n' |
grep -A 1 with |
grep _module |
sed -r 's/_module//g; s/\s+//g' |
sort
args:
executable: /bin/sh
register: shell_modules
changed_when: false changed_when: false
check_mode: false
tags:
- skip_ansible_lint
- name: SET_FACT | Save modules
ansible.builtin.set_fact:
nginx_modules: "{{ shell_modules.stdout_lines }}"
- name: FILE | Create folders - name: FILE | Create folders
ansible.builtin.file: file: dest={{ item }} owner=root mode=0755 state=directory
dest: "{{ item.dir }}" with_items: "{{ nginx_dirs }}"
owner: "{{ item.owner }}"
mode: "{{ item.mode }}"
state: directory
loop: "{{ nginx_dirs }}"
- name: FILE | Create ansible facts dir
ansible.builtin.file:
path: /etc/ansible/facts.d
state: directory
mode: "0755"
owner: root
group: root

View File

@ -1,125 +0,0 @@
---
- name: FAIL | Check filenames
ansible.builtin.fail:
msg: "Forbidden keyword default on site {{ item | nginx_site_name }}"
when: item.filename is defined and item.filename == 'default'
loop: "{{ nginx_sites }}"
loop_control:
label: "{{ item | nginx_site_name }}"
- name: FAIL | Check HTTPS redir and proto
ansible.builtin.fail:
msg: "You can't have HTTP proto and HTTPS redirection at the same time"
when:
((item.proto is defined and 'http' in item.proto) or (item.proto is not defined)) and
(item.redirect_http is defined and item.redirect_http)
loop: "{{ nginx_sites }}"
loop_control:
label: "{{ item | nginx_site_name }}"
- name: FILE | Create root directory
ansible.builtin.file:
path: "{{ nginx_root }}"
state: directory
mode: "0755"
owner: root
group: root
- name: FILE | Create root public folders (foreach nginx_sites)
ansible.builtin.file:
path: "{{ nginx_root }}/{{ item | nginx_site_filename }}/public"
state: directory
owner: "{{ item.owner | default(nginx_user) }}"
group: "{{ item.group | default(nginx_user) }}"
mode: "{{ item.mode | default('0755') }}"
loop: "{{ nginx_sites }}"
when: >
item.root is not defined and
(item.template is defined and item.template not in nginx_templates_no_dir) and
(item.state is not defined or not item.state != 'absent') and
item.redirect_to is not defined
loop_control:
label: "{{ item | nginx_site_name }}"
- name: TEMPLATE | Create sites
ansible.builtin.template:
src: "etc/nginx/sites-available/{{ item.template if item.redirect_to is not defined else '_redirect' }}.j2"
dest: "{{ nginx_etc_dir }}/sites-available/{{ item | nginx_site_filename }}"
mode: "0644"
owner: root
group: root
notify: 'Reload nginx'
when: (item.state is not defined or item.state != 'absent') and item.custom_template is not defined
loop: "{{ nginx_sites }}"
loop_control:
label: "{{ item | nginx_site_name }}"
- name: TEMPLATE | Create sites with preconfigured template
ansible.builtin.template:
src: "{{ item.custom_template }}"
dest: "{{ nginx_etc_dir }}/sites-available/{{ item | nginx_site_filename }}"
mode: "0644"
owner: root
group: root
notify: 'Reload nginx'
when: (item.state is not defined or item.state != 'absent') and item.custom_template is defined
loop: "{{ nginx_sites }}"
loop_control:
label: "{{ item | nginx_site_name }}"
- name: FILE | Delete sites
ansible.builtin.file:
path: "{{ nginx_etc_dir }}/{{ item.1 }}/{{ item.0 | nginx_site_filename }}"
state: absent
loop: "{{ nginx_sites | product(dirs) | list }}"
notify: 'Reload nginx'
when: item.0.state is defined and item.0.state == 'absent'
vars:
dirs: ['sites-available', 'sites-enabled']
loop_control:
label: "{{ nginx_etc_dir }}/{{ item.1 }}/{{ item.0 | nginx_site_filename }}"
- name: FILE | Enable sites
ansible.builtin.file:
src: "{{ nginx_etc_dir }}/sites-available/{{ item | nginx_site_filename }}"
dest: "{{ nginx_etc_dir }}/sites-enabled/{{ item | nginx_site_filename }}"
state: link
loop: "{{ nginx_sites }}"
notify: 'Reload nginx'
when: >
item.state is not defined or item.state == 'present'
loop_control:
label: "{{ item | nginx_site_name }}"
- name: FILE | Disable sites
ansible.builtin.file:
path: "{{ nginx_etc_dir }}/sites-enabled/{{ item | nginx_site_filename }}"
state: absent
loop: "{{ nginx_sites }}"
notify: 'Reload nginx'
when: item.state is defined and item.state == 'disabled'
loop_control:
label: "{{ item | nginx_site_name }}"
- name: FILE | Delete default site when explicitely defined
ansible.builtin.file:
path: "{{ nginx_etc_dir }}/sites-enabled/default"
state: absent
notify: 'Reload nginx'
when: nginx_default_site is not none
- name: FILE | Auto set default site
ansible.builtin.file:
src: "{{ nginx_etc_dir }}/sites-available/default"
dest: "{{ nginx_etc_dir }}/sites-enabled/default"
state: link
notify: 'Reload nginx'
when: nginx_default_site is none
- name: TEMPLATE | Deploy facts
ansible.builtin.template:
src: etc/ansible/facts.d/nginx.fact.j2
dest: /etc/ansible/facts.d/nginx.fact
mode: "0644"
notify: ['Setup']

39
tasks/ssl.yml 100644
View File

@ -0,0 +1,39 @@
---
- name: COMMAND | Generate DH file
command: openssl dhparam -out {{ nginx_dh_path }} {{ nginx_dh_length }}
args:
creates: "{{ nginx_dh_path }}"
when: nginx_dh is not string
notify: reload nginx
- name: COPY | Deploy DH file from vars
copy: >
content="{{ nginx_dh }}"
dest="{{ nginx_dh_path }}"
when: nginx_dh is string
notify: reload nginx
- name: FILE | Create SSL directories
file: >
path="{{ nginx_ssl_dir + '/' + item.name }}"
state=directory
with_items: nginx_ssl_pairs
when: item.dest_key is not defined or item.dest_cert is not defined
- name: COPY | Deploy SSL keys
copy: >
content="{{ item.key }}"
dest="{{ nginx_ssl_dir + '/' + item.name + '/' + item.name + '.key' if item.dest_key is not defined else item.dest_key }}"
with_items: nginx_ssl_pairs
when: item.key is defined
notify: reload nginx
- name: COPY | Deploy SSL certs
copy: >
content="{{ item.cert }}"
dest="{{ nginx_ssl_dir + '/' + item.name + '/' + item.name + '.crt' if item.dest_cert is not defined else item.dest_cert }}"
with_items: nginx_ssl_pairs
when: item.cert is defined
notify: reload nginx

View File

@ -1,103 +0,0 @@
---
- name: SET_FACT | Assign default...
ansible.builtin.set_fact:
acme_create: []
- name: STAT | Check if certificates are already installed
ansible.builtin.stat:
path: "{{ item | nginx_cert_path(nginx_ssl_dir) }}"
loop: "{{ nginx_ssl_pairs }}"
when: item.acme is defined and item.acme
register: acme_installed_certs
- name: SET_FACT | Assign var with certificates to create
ansible.builtin.set_fact:
acme_create: "{{ acme_create | default([]) + [item.item] }}"
loop: "{{ acme_installed_certs.results }}"
when: item.skipped is not defined and (not item.stat.exists or item.stat.size == 0)
- name: BLOCK | Start acme
block:
- name: TEMPLATE | Create fake site
ansible.builtin.template:
src: "etc/nginx/conf.d/FAKESITE.conf.j2"
dest: "{{ nginx_etc_dir }}/conf.d/FAKESITE_{{ item | nginx_site_name }}.conf"
mode: "0644"
owner: root
group: root
loop: "{{ acme_create }}"
register: fake_site
notify: Restart nginx
- name: TEMPLATE | Create fake site
ansible.builtin.template:
src: "etc/nginx/conf.d/FAKESITE.conf.j2"
dest: "/tmp/FAKESITE_{{ item | nginx_site_name }}.conf"
mode: "0644"
owner: root
group: root
loop: "{{ acme_create }}"
- name: FILE | Delete current site if needed # noqa: no-handler
ansible.builtin.file:
path: "{{ nginx_etc_dir }}/sites-enabled/{{ item | nginx_site_name }}"
state: absent
loop: "{{ acme_create }}"
when: fake_site.changed
notify: Restart nginx
- name: META | Ensure nginx is restarted if needed
ansible.builtin.meta: flush_handlers
- name: COMMAND | Get certificates
ansible.builtin.command: |
{{ nginx_acmesh_bin }}
--home {{ nginx_acmesh_dir }}
--issue{% for s in nginx_sites | nginx_search_by_ssl_name(item.name) | nginx_all_site_names %} -d {{ s }}{% endfor %}
--nginx
{% if nginx_acmesh_test %}--test --log{% endif %}
args:
creates: "{{ nginx_acmesh_dir }}/{{ item | nginx_site_name }}/fullchain.cer"
loop: "{{ acme_create }}"
register: acme_get
failed_when: acme_get.rc != 0 and acme_get.rc != 2
no_log: "{{ not nginx_debug_role }}"
- name: FILE | Create SSL dir per site
ansible.builtin.file:
path: "{{ nginx_ssl_dir }}/{{ item | nginx_site_name }}"
loop: "{{ acme_create }}"
- name: COMMAND | Install certificates
ansible.builtin.command: |
{{ nginx_acmesh_bin }}
--home {{ nginx_acmesh_dir }}
--install-cert -d {{ nginx_sites | nginx_search_by_ssl_name(item | nginx_site_name) | nginx_site_name }}
--fullchain-file {{ item | nginx_cert_path(nginx_ssl_dir) }}
--key-file {{ item | nginx_key_path(nginx_ssl_dir) }}
--reloadcmd "service nginx reload"
args:
creates: "{{ item | nginx_cert_path(nginx_ssl_dir) }}"
loop: "{{ nginx_ssl_pairs }}"
when: item.acme is defined and item.acme
notify: Restart nginx
rescue:
- name: FAIL | Explicit
ansible.builtin.fail:
msg: "Something is bad... Auto crash!"
always:
- name: FILE | Delete fake sites
ansible.builtin.file:
path: "{{ nginx_etc_dir }}/conf.d/FAKESITE_{{ item | nginx_site_name }}.conf"
state: absent
loop: "{{ acme_create }}"
notify: Restart nginx
- name: META | Flush handlers
ansible.builtin.meta: flush_handlers

View File

@ -1,8 +0,0 @@
---
- name: IMPORT_TASKS | standard.yml
ansible.builtin.import_tasks: standard.yml
- name: IMPORT_TASKS | acme.yml
ansible.builtin.import_tasks: acme.yml
when: nginx_acmesh

View File

@ -1,86 +0,0 @@
---
- name: Generate DH if needed
when: nginx_dh is not string
block:
- name: STAT | Get info about DH file
ansible.builtin.stat:
path: "{{ nginx_dh_path }}"
get_checksum: false
register: stat_dh_file
- name: SHELL | Get info about DH file
ansible.builtin.shell: |
set -o pipefail &&
openssl dhparam -in {{ nginx_dh_path }} -text -noout 2>&1 | awk '/DH Parameters/ { print substr($3, 2) }'
args:
executable: /bin/bash
changed_when: false
register: dh_info
when: stat_dh_file.stat.exists
- name: COMMAND | Generate DH file # noqa: no-changed-when
ansible.builtin.command: openssl dhparam -out {{ nginx_dh_path }} {{ nginx_dh_length }}
when: not stat_dh_file.stat.exists or (dh_info.stdout | int != nginx_dh_length | int)
notify: Restart nginx
- name: COPY | Deploy DH file from vars
ansible.builtin.copy:
content: "{{ nginx_dh }}"
dest: "{{ nginx_dh_path }}"
owner: root
group: root
mode: "0640"
when: nginx_dh is string
notify: Restart nginx
- name: FILE | Create SSL directories
ansible.builtin.file:
path: "{{ item | nginx_ssl_dir(nginx_ssl_dir) }}"
state: directory
owner: root
group: root
mode: "0750"
loop: "{{ nginx_ssl_pairs }}"
when: item.dest_key is not defined or item.dest_cert is not defined
no_log: "{{ not nginx_debug_role }}"
- name: COPY | Deploy SSL keys
ansible.builtin.copy:
content: "{{ item.key }}"
dest: "{{ item | nginx_key_path(nginx_ssl_dir) }}"
owner: root
group: root
mode: "0640"
loop: "{{ nginx_ssl_pairs }}"
when: item.key is defined
notify: Restart nginx
no_log: "{{ not nginx_debug_role }}"
- name: COPY | Deploy SSL certs
ansible.builtin.copy:
content: "{{ item.cert }}"
dest: "{{ item | nginx_cert_path(nginx_ssl_dir) }}"
owner: root
group: root
mode: "0644"
loop: "{{ nginx_ssl_pairs }}"
when: item.cert is defined
notify: Restart nginx
no_log: "{{ not nginx_debug_role }}"
- name: COMMAND | Create self-signed certificates
ansible.builtin.command: |
openssl req
-new -newkey rsa:2048 -sha256 -days 3650 -nodes -x509
-subj '/CN={{ item | nginx_site_name }}'
-keyout {{ item | nginx_key_path(nginx_ssl_dir) }}
-out {{ item | nginx_cert_path(nginx_ssl_dir) }}
args:
chdir: "{{ item | nginx_ssl_dir(nginx_ssl_dir) }}"
creates: "{{ '/tmp/dummy' if item.force is defined and item.force else item | nginx_cert_path(nginx_ssl_dir) }}"
loop: "{{ nginx_ssl_pairs }}"
when: item.self_signed is defined
notify: Restart nginx
no_log: "{{ not nginx_debug_role }}"

View File

@ -1,29 +1,11 @@
--- ---
- name: TEMPLATE | Deploy PHP upstream to Nginx - name: TEMPLATE | Deploy PHP upstream to Nginx
ansible.builtin.template: template: src=etc/nginx/upstream/php.conf.j2 dest=/etc/nginx/conf.d/php.conf
src: "etc/nginx/conf.d/php.conf.j2" when: nginx_php
dest: "{{ nginx_etc_dir }}/conf.d/php.conf" notify: reload nginx
mode: "0644"
owner: root
group: root
notify: Reload nginx
- name: TEMPLATE | Deploy other upstreams - name: TEMPLATE | Deploy other upstreams
ansible.builtin.template: template: src=etc/nginx/upstream/upstream.conf.j2 dest=/etc/nginx/conf.d/upstream-{{ item.name }}.conf
src: "etc/nginx/conf.d/_upstream.conf.j2" with_items: nginx_upstreams
dest: "{{ nginx_etc_dir }}/conf.d/upstream-{{ item.name }}.conf" notify: reload nginx
mode: "0644"
owner: root
group: root
loop: "{{ nginx_upstreams }}"
when: item.state is not defined or item.state == 'present'
notify: Reload nginx
- name: FILE | Delete other upstreams
ansible.builtin.file:
path: "{{ nginx_etc_dir }}/conf.d/upstream-{{ item.name }}.conf"
state: absent
loop: "{{ nginx_upstreams }}"
when: item.state is defined and item.state == 'absent'
notify: Reload nginx

93
tasks/vhost.yml 100644
View File

@ -0,0 +1,93 @@
---
- name: FAIL | Check vhost and SSL/TLS support
fail: msg="Missmatch configuration for vhost {{ item.name if item.name is string else item.name[0] }}"
when: >
item.proto is defined and
'https' in item.proto and
item.ssl_name is not defined
with_items: nginx_vhosts
- name: FILE | Create root directory
file: >
path={{ nginx_root }}
state=directory
- name: FILE | Create root folders (foreach nginx_vhosts)
file: >
path={{ nginx_root }}/{{ item.name if item.name is string else item.name[0] }}
state=directory
owner={{ item.owner | default('www-data') }}
group={{ item.group | default('www-data') }}
mode={{ item.mode | default('0755') }}
with_items: nginx_vhosts
when: >
item.root is not defined and
(item.template is defined and item.template not in nginx_templates_no_dir) and
(item.delete is not defined or not item.delete) and
item.redirect_to is not defined
- name: FILE | Create root public folders (foreach nginx_vhosts)
file: >
path={{ nginx_root }}/{{ item.name if item.name is string else item.name[0] }}/public
state=directory
owner={{ item.owner | default('www-data') }}
group={{ item.group | default('www-data') }}
mode={{ item.mode | default('0755') }}
with_items: nginx_vhosts
when: >
item.root is not defined and
(item.template is defined and item.template not in nginx_templates_no_dir) and
(item.delete is not defined or not item.delete) and
item.redirect_to is not defined
- name: TEMPLATE | Create vhosts
template: >
src=etc/nginx/sites-available/{{ item.template if item.redirect_to is not defined else '_redirect' }}.j2
dest=/etc/nginx/sites-available/{{ item.name if item.name is string else item.name[0] }}
with_items: nginx_vhosts
notify: reload nginx
when: item.delete is not defined or not item.delete
#- name: COPY | Add index.html / index.php
# copy: src={{ item }} dest={{ nginx_root }}/{{ item.name }}/public/{{ item }} owner=www-data group=www-data mode=0666
# with_fileglob: "web/*"
- name: FILE | Delete vhosts
file: path=/etc/nginx/sites-available/{{ item.name if item.name is string else item.name[0] }} state=absent
with_items: nginx_vhosts
notify: reload nginx
when: item.delete is defined and item.delete
- name: FILE | Enable vhosts
file: >
src=/etc/nginx/sites-available/{{ item.name if item.name is string else item.name[0] }}
dest=/etc/nginx/sites-enabled/{{ item.name if item.name is string else item.name[0] }}
state=link
with_items: nginx_vhosts
notify: reload nginx
when: >
((item.enable is not defined) or
(item.enable is defined and item.enable)) and
(item.delete is not defined or not item.delete)
- name: FILE | Disable vhosts
file: path=/etc/nginx/sites-enabled/{{ item.name if item.name is string else item.name[0] }} state=absent
with_items: nginx_vhosts
notify: reload nginx
when: (item.enable is defined and not item.enable) or (item.delete is defined and item.delete)
- name: FILE | Delete default vhost when explicitely defined
file: >
path=/etc/nginx/sites-enabled/default
state=absent
notify: reload nginx
when: nginx_default_vhost is not none
- name: FILE | Auto set default vhost
file: >
src=/etc/nginx/sites-available/default
dest=/etc/nginx/sites-enabled/default
state=link
notify: reload nginx
when: nginx_default_vhost is none

View File

@ -1,4 +0,0 @@
{
"fact_nginx_sites":
{{ nginx_sites | to_nice_json(indent=8) }}
}

View File

@ -1,18 +0,0 @@
{% set site = nginx_sites | nginx_search_by_ssl_name(item.name) %}
{% set __listen = item.listen | default(nginx_default_listen) %}
{% set __listen_proxy_protocol = item.listen_proxy_protocol | default(nginx_default_listen_proxy_protocol) %}
server {
{% for port in __listen %}
listen {{ port }};
{% endfor %}
{% for port in __listen_proxy_protocol %}
listen {{ port }} proxy_protocol;
{% endfor %}
server_name {{ site | nginx_all_site_names | join(" ") }};
location / {
return 503;
}
}

View File

@ -1,29 +0,0 @@
#
# {{ ansible_managed }}
#
{% for php in nginx_php %}
upstream {{ php.upstream_name }} {
{% for sock in php.sockets | default([]) %}
{% if sock.host is defined %}
server {{ sock.host }}:{{ sock.port }} weight={{ sock.weight | default('1') }} max_fails={{ sock.max_fails | default('5') }} fail_timeout={{ sock.fail_timeout | default('10s') }};
{% else %}
server unix:{{ sock.unix }} weight={{ sock.weight | default('1') }};
{% endif %}
{% endfor %}
}
{% endfor %}
{% if ansible_local.hanxhx_php.fpm_pool is defined%}
# -------------------------------------------------------
# Auto-detected PHP config for HanXHX.php ansible role
# -------------------------------------------------------
{% for php in ansible_local.hanxhx_php.fpm_pool %}
upstream {{ php.name }} {
server {% if php.listen.startswith('/') %}unix:{{ php.listen }}{% else %}{{ php.listen }}{% endif %};
}
{% endfor %}
{% endif %}
# vim:filetype=nginx

View File

@ -1,23 +1,20 @@
# #
# {{ ansible_managed }} # {{ ansible_managed }}
# See: https://ssl-config.mozilla.org/#server=nginx&version=1.18.0&config=intermediate&openssl=1.1.1n&hsts=false&guideline=5.7 #
ssl_session_timeout 1d; ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_tickets off; ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_dhparam {{ nginx_dh_path }}; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
add_header X-Frame-Options DENY;
# intermediate configuration add_header X-Content-Type-Options nosniff;
ssl_protocols TLSv1.2 TLSv1.3; {% if nginx_version.stdout | version_compare('1.3.7', 'ge') %}
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
# OCSP stapling
ssl_stapling on; ssl_stapling on;
ssl_stapling_verify on; ssl_stapling_verify on;
{% endif %}
# Replace with the IP address of your resolver
resolver {{ nginx_resolver_hosts | join(' ') }} valid={{ nginx_resolver_valid }}; resolver {{ nginx_resolver_hosts | join(' ') }} valid={{ nginx_resolver_valid }};
resolver_timeout {{ nginx_resolver_timeout }};
ssl_dhparam {{ nginx_dh_path }};
# vim:filetype=nginx # vim:filetype=nginx

View File

@ -1,21 +1,20 @@
# #
# {{ ansible_managed }} # {{ ansible_managed }}
# See: https://ssl-config.mozilla.org/#server=nginx&version=1.18.0&config=modern&openssl=1.1.1n&hsts=false&guideline=5.7 #
ssl_session_timeout 1d; ssl_ciphers "AES256+EECDH:AES256+EDH";
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_tickets off; ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
# modern configuration add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
ssl_protocols TLSv1.3; add_header X-Frame-Options DENY;
ssl_prefer_server_ciphers off; add_header X-Content-Type-Options nosniff;
{% if nginx_version.stdout | version_compare('1.3.7', 'ge') %}
# OCSP stapling
ssl_stapling on; ssl_stapling on;
ssl_stapling_verify on; ssl_stapling_verify on;
{% endif %}
# Replace with the IP address of your resolver
resolver {{ nginx_resolver_hosts | join(' ') }} valid={{ nginx_resolver_valid }}; resolver {{ nginx_resolver_hosts | join(' ') }} valid={{ nginx_resolver_valid }};
resolver_timeout {{ nginx_resolver_timeout }}; resolver_timeout {{ nginx_resolver_timeout }};
ssl_dhparam {{ nginx_dh_path }};
# vim:filetype=nginx # vim:filetype=nginx

View File

@ -5,10 +5,6 @@
user {{ nginx_user }}; user {{ nginx_user }};
worker_processes {{ nginx_worker_processes }}; worker_processes {{ nginx_worker_processes }};
pid {{ nginx_pid }}; pid {{ nginx_pid }};
{% for i in nginx_custom_core %}
{{ i }}
{% endfor %}
include {{ nginx_etc_dir }}/modules-enabled/*.conf;
events { events {
worker_connections {{ nginx_events_worker_connections }}; worker_connections {{ nginx_events_worker_connections }};
@ -18,7 +14,7 @@ events {
http { http {
types_hash_max_size {{ nginx_http_types_hash_max_size }}; types_hash_max_size {{ nginx_http_types_hash_max_size }};
include {{ nginx_etc_dir }}/mime.types; include /etc/nginx/mime.types;
default_type {{ nginx_http_default_type }}; default_type {{ nginx_http_default_type }};
access_log {{ nginx_http_access_log }}; access_log {{ nginx_http_access_log }};
@ -49,8 +45,8 @@ http {
gzip_vary {{ nginx_http_gzip_vary }}; gzip_vary {{ nginx_http_gzip_vary }};
gzip_disable {{ nginx_http_gzip_disable }}; gzip_disable {{ nginx_http_gzip_disable }};
include {{ nginx_etc_dir }}/conf.d/*.conf; include /etc/nginx/conf.d/*.conf;
include {{ nginx_etc_dir }}/sites-enabled/*; include /etc/nginx/sites-enabled/*;
} }
# vim:filetype=nginx # vim:filetype=nginx

View File

@ -0,0 +1,33 @@
{% extends "_base.j2" %}
{% block root %}
root /usr/share/backuppc/cgi-bin;
{% endblock %}
{% block template_try_files %}
{% endblock %}
{% block template_index %}
index index.cgi;
{% endblock %}
{% block template_local_content %}
location ~ /\.ht {
deny all;
}
location /backuppc/image {
alias /usr/share/backuppc/image;
expires 60d;
}
{% endblock %}
{% block template_upstream_location %}
location ~ \.cgi$ {
gzip off;
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_index BackupPC_Admin;
fastcgi_param SCRIPT_FILENAME /usr/share/backuppc/cgi-bin$fastcgi_script_name;
}
{% endblock %}

View File

@ -1,68 +1,20 @@
{% set __proto = item.proto | default(['http']) %} {% set __proto = item.proto | default(['http']) %}
{% set __main_name = item | nginx_site_name %} {% set __main_name = item.name if item.name is string else item.name[0] %}
{% set __listen = item.listen | default(nginx_default_listen) %} {% set __listen = item.listen | default(['80']) %}
{% set __listen_ssl = item.listen_ssl | default(nginx_default_listen_ssl) %} {% set __listen_ssl = item.listen_ssl | default(['443']) %}
{% set __listen_proxy_protocol = item.listen_proxy_protocol | default(nginx_default_listen_proxy_protocol) %}
{% set __listen_proxy_protocol_ssl = item.listen_proxy_protocol_ssl | default(nginx_default_listen_proxy_protocol_ssl) %}
{% set __location = item.location | default({}) %} {% set __location = item.location | default({}) %}
{% set __location_before = item.location_before | default({}) %}
{% set __headers = item.headers | default(nginx_servers_default_headers) %}
{% set __ssl_name = item.ssl_name | default(__main_name) %}
{% set __location_order = item.location_order | default(__location.keys()) %}
{% set __location_order_before = item.location_order_before | default(__location_before.keys()) %}
{% set __http2 = nginx_auto_config_httpv2 and 'http_v2' in nginx_modules %}
{% macro listen_http() %}
{% endmacro %}
{% macro server_name(name) %}
{% if name is string %}{{ name }}{% else %}{{ name | join(" ") }}{% endif %}
{% endmacro %}
{% macro locations(list, order) %}
{% if order | length > 0 %}
# --> Custom locations
{% for location in order %}
location {{ location }} {
{% set opts = list[location] %}
{% for opt in opts %}
{% if opt.htpasswd is defined %}
{{ htpasswd(opt.htpasswd, 2) }}
{% else %}
{{ opt }}
{% endif %}
{% endfor %}
}
{% endfor %}
# <-- Custom locations
{% endif %}
{% endmacro %}
{% macro htpasswd(htpasswd_name, indent=1) -%} {% macro htpasswd(htpasswd_name, indent=1) -%}
{%- if htpasswd_name != false %} {% for ht in nginx_htpasswd if ht.name == htpasswd_name %}
{%- for ht in nginx_htpasswd if ht.name == htpasswd_name %}
{{ "\t" * indent }}auth_basic "{{ ht.description }}"; {{ "\t" * indent }}auth_basic "{{ ht.description }}";
{{ "\t" * indent }}auth_basic_user_file {{ nginx_htpasswd_dir }}/{{ ht.name }}; {{ "\t" * indent }}auth_basic_user_file {{ nginx_htpasswd_dir }}/{{ ht.name }};
{%- endfor %} {% endfor%}
{%- endif %}
{%- endmacro %} {%- endmacro %}
{% macro ssl(ssl_name) %} {% macro ssl(ssl_name) %}
{% for sn in nginx_ssl_pairs if (sn.name is defined and (sn | nginx_site_name) == ssl_name) %} {% for sn in nginx_ssl_pairs if sn.name == ssl_name %}
ssl_certificate {{ sn | nginx_cert_path(nginx_ssl_dir) }}; ssl_certificate {{ nginx_ssl_dir + '/' + ssl_name + '/' + ssl_name + '.crt' if sn.dest_cert is not defined else sn.dest_cert }};
ssl_certificate_key {{ sn | nginx_key_path(nginx_ssl_dir) }}; ssl_certificate_key {{ nginx_ssl_dir + '/' + ssl_name + '/' + ssl_name + '.key' if sn.dest_key is not defined else sn.dest_key }};
{% endfor %} {% endfor %}
{%- endmacro %} {%- endmacro %}
{% macro httpsredirect(name) %}
server {
{% for port in __listen %}
listen {{ port }};
{% endfor %}
{% for port in __listen_proxy_protocol %}
listen {{ port }} proxy_protocol;
{% endfor %}
server_name {{ server_name(name) }};
location / {
return 301 https://{{ name }}{% if '443' not in __listen_ssl and 443 not in __listen_ssl %}:{{ __listen_ssl[0] }}{% endif %}$request_uri;
}
}
{% endmacro %}
# #
# {{ ansible_managed }} # {{ ansible_managed }}
# #
@ -73,63 +25,42 @@ server {
server { server {
{% if 'http' in __proto %} {% if 'http' in __proto %}
{% for port in __listen %} {% for port in __listen %}
listen {{ port }}{% if nginx_default_site == __main_name %} default_server{% endif %}; listen {{ port }}{% if nginx_default_vhost == __main_name %} default_server{% endif %};
{% endfor %}
{% for port in __listen_proxy_protocol %}
listen {{ port }}{% if nginx_default_site == __main_name %} default_server{% endif %} proxy_protocol;
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% if 'https' in __proto %} {% if 'https' in __proto %}
{% for port in __listen_ssl %} {% for port in __listen_ssl %}
listen {{ port }}{% if nginx_default_site_ssl == __main_name %} default_server{% endif %} ssl{% if __http2 %} http2{% endif %}; listen {{ port }}{% if nginx_default_vhost_ssl == __main_name %} default_server{% endif %} ssl{% if nginx_auto_config_httpv2 and 'http_v2' in nginx_modules.stdout_lines %}http2{% endif %};
{% endfor %} {% endfor %}
{% for port in __listen_proxy_protocol_ssl %} {{ ssl(item.ssl_name) }}
listen {{ port }}{% if nginx_default_site_ssl == __main_name %} default_server{% endif %} ssl{% if __http2 %} http2{% endif %} proxy_protocol;
{% endfor %}
{{ ssl(__ssl_name) }}
{% if item.ssl_template is not defined or item.ssl_template != false %}
include {{ nginx_helper_dir + '/ssl-' + item.ssl_template | default('strong') }}; include {{ nginx_helper_dir + '/ssl-' + item.ssl_template | default('strong') }};
add_header Strict-Transport-Security "{{ item.hsts | default(nginx_default_hsts) }}" always;
{% endif %} {% endif %}
{% endif %} server_name {% if item.name is string %}{{ item.name }}{% else %}{{ item.name | join(' ') }}{% endif %};
server_name {{ server_name(item.name) }};
{% block root %} {% block root %}
{% if item.root is defined %} {% if item.root is defined %}
root {{ item.root }}; root {{ item.root }};
{% else %} {% else %}
root {{ nginx_root }}/{{ item | nginx_site_filename }}/public; root {{ nginx_root }}/{{ __main_name }}/public;
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block template_index %} {% block template_index %}
index {{ item.index | default('index.html index.htm') }}; index {{ item.index | default('index.html index.htm') }};
{% endblock %} {% endblock %}
{% block template_more %}
{% if item.more is defined and item.more is iterable %} {% if item.more is defined and item.more is iterable %}
{% for line in item.more %} {% for line in item.more %}
{{ line }} {{ line }}
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% endblock %}
{% if item.htpasswd is defined %} {% if item.htpasswd is defined %}
{{ htpasswd(item.htpasswd, 1) }} {{ htpasswd(item.htpasswd, 1) }}
{% endif %} {% endif %}
{% block template_headers %} {% if not __location.has_key('/') %}
# --> Custom headers
{% for key, value in __headers.items() %}
add_header {{ key }} "{{ value | regex_replace('\s+always$', '') }}"{% if value | regex_search('\s+always$') %} always{% endif %};
{% endfor %}
# <-- Custom headers
{% endblock %}
{{ locations(__location_before, __location_order_before) }}
{% if not '/' in __location %}
location / { location / {
{% block template_try_files %} {% block template_try_files %}
try_files {{ item.override_try_files | default('$uri $uri/ =404') }}; try_files {{ override_try_files | default('$uri $uri/ =404') }};
{% endblock %} {% endblock %}
} }
{% endif %} {% endif %}
@ -139,8 +70,6 @@ server {
{% block template_custom_location %} {% block template_custom_location %}
{% endblock %} {% endblock %}
{{ locations(__location, __location_order) }}
{% block template_local_content %} {% block template_local_content %}
{% if item.manage_local_content is not defined or item.manage_local_content %} {% if item.manage_local_content is not defined or item.manage_local_content %}
location ~ /\.ht { location ~ /\.ht {
@ -153,42 +82,38 @@ server {
log_not_found off; log_not_found off;
} }
location ~* \.(txt|js|css|png|jpe?g|gif|ico|svg|(o|t)tf|woff2?|eot)$ { location ~* \.(txt|js|css|png|jpe?g|gif|ico|svg)$ {
expires 30d; expires 30d;
log_not_found off; log_not_found off;
} }
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% if item.use_access_log is defined %} {% if __location is iterable and __location | length > 0 %}
{% if item.use_access_log %} # --> Custom locations
{% for location, opts in __location.iteritems() %}
location {{ location }} {
{% for opt in opts %}
{% if opt.htpasswd is defined %}{{ htpasswd(opt.htpasswd, 2) }}{% else %}
{{ opt }}
{% endif %}
{% endfor %}
}
{% endfor %} # <-- Custom locations
{% endif %}
{% if item.use_access_log is defined and item.use_access_log %}
access_log {{ nginx_log_dir }}/{{ __main_name }}_access.log combined; access_log {{ nginx_log_dir }}/{{ __main_name }}_access.log combined;
{% else %} {% else %}
access_log off; access_log off;
{% endif %} {% endif %}
{% endif %} {% if item.use_error_log is defined and item.use_error_log %}
{% if item.use_error_log is defined %}
{% if item.use_error_log %}
error_log {{ nginx_log_dir }}/{{ __main_name }}_error.log {{ nginx_error_log_level }}; error_log {{ nginx_log_dir }}/{{ __main_name }}_error.log {{ nginx_error_log_level }};
{% else %} {% else %}
error_log off; error_log off;
{% endif %} {% endif %}
{% endif %}
} }
{% if item.redirect_https is defined and item.redirect_https %}
#
# Redirect HTTP to HTTPS
#
{% if item.name is string %}
{{ httpsredirect(item.name) }}
{% else %}
{% for i in item.name %}
{{ httpsredirect(i) }}
{% endfor %}
{% endif %}
{% endif %}
{% if item.redirect_from is defined and item.redirect_from is iterable %} {% if item.redirect_from is defined and item.redirect_from is iterable %}
# #
# Redirect from # Redirect from
@ -197,36 +122,9 @@ server {
{% for port in __listen %} {% for port in __listen %}
listen {{ port }}; listen {{ port }};
{% endfor %} {% endfor %}
{% for port in __listen_proxy_protocol %} server_name {{ item.redirect_from | join(' ') }};
listen {{ port }} proxy_protocol; return 301 $scheme://{{ __main_name }}$request_uri;
{% endfor %}
server_name {{ server_name(item.redirect_from) }};
location / {
return 301 $scheme://{{ __main_name }}$request_uri;
}
} }
{% if 'https' in __proto %}
server {
{% for port in __listen_ssl %}
listen {{ port }} ssl{% if __http2 %} http2{% endif %};
{% endfor %}
{% for port in __listen_proxy_protocol_ssl %}
listen {{ port }} ssl{% if __http2 %} http2{% endif %} proxy_protocol;
{% endfor %}
{{ ssl(__ssl_name) }}
{% if item.ssl_template is not defined or item.ssl_template != false %}
include {{ nginx_helper_dir + '/ssl-' + item.ssl_template | default('strong') }};
add_header Strict-Transport-Security "{{ item.hsts | default(nginx_default_hsts) }}" always;
{% endif %}
server_name {{ server_name(item.redirect_from) }};
location / {
return 301 https://{{ __main_name }}{% if '443' not in __listen_ssl and 443 not in __listen_ssl %}:{{ __listen_ssl[0] }}{% endif %}$request_uri;
}
}
{% endif %}
{% endif %} {% endif %}
# vim:filetype=nginx # vim:filetype=nginx

View File

@ -0,0 +1,47 @@
{% extends "_base.j2" %}
{% block root %}
root /usr/share/nagios3/htdocs;
{% endblock %}
{% block template_try_files %}
{% endblock %}
{% block template_index %}
index index.php index.html;
{% endblock %}
{% block template_local_content %}
location ~ /\.ht {
deny all;
}
location /stylesheets {
alias /etc/nagios3/stylesheets;
expires 60d;
}
{% endblock %}
{% block template_upstream_location %}
location /cgi-bin/nagios3 {
root /usr/lib;
try_files $uri =404;
{% if nginx_version.stdout | version_compare('1.6.1', 'lt') %}
include fastcgi_params;
{% else %}
include fastcgi.conf;
{% endif %}
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param AUTH_USER $remote_user;
fastcgi_param REMOTE_USER $remote_user;
}
location ~ \.php$ {
fastcgi_pass php;
fastcgi_index index.php;
{% if nginx_version.stdout | version_compare('1.6.1', 'lt') %}
include fastcgi_params;
{% else %}
include fastcgi.conf;
{% endif %}
}
{% endblock %}

View File

@ -1,22 +1,25 @@
{% extends "_base.j2" %} {% extends "_base.j2" %}
{% block template_index %} {% block template_index %}
index {{ item.index | default('index.html index.htm index.php') }}; index {{ item.index | default('index.html index.htm index.php') }};
{% endblock %} {% endblock %}
{% block template_try_files %} {% block template_try_files %}
try_files {{ item.override_try_files | default('$uri $uri/ =404') }}; try_files {{ override_try_files | default('$uri $uri/ /index.php') }};
{% endblock %} {% endblock %}
{% block template_upstream_location %} {% block template_upstream_location %}
location ~ \.php$ { location ~ \.php$ {
fastcgi_pass {{ item.php_upstream }}; fastcgi_pass php;
fastcgi_index index.php; fastcgi_index index.php;
{% if item.upstream_params is defined and item.upstream_params is iterable %} {% if item.upstream_params is defined and item.upstream_params is iterable %}
{% for param in item.upstream_params %} {% for param in item.upstream_params %}
{{ param }} {{ param }}
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% if nginx_version.stdout | version_compare('1.6.1', 'lt') %}
include fastcgi_params;
{% else %}
include fastcgi.conf; include fastcgi.conf;
{% endif %}
} }
{% endblock %} {% endblock %}

View File

@ -2,14 +2,18 @@
{% block template_upstream_location %} {% block template_upstream_location %}
location = /index.php { location = /index.php {
fastcgi_pass {{ item.php_upstream }}; fastcgi_pass php;
fastcgi_index index.php; fastcgi_index index.php;
{% if item.upstream_params is defined and item.upstream_params is iterable %} {% if item.upstream_params is defined and item.upstream_params is iterable %}
{% for param in item.upstream_params %} {% for param in item.upstream_params %}
{{ param }} {{ param }}
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% if nginx_version.stdout | version_compare('1.6.1', 'lt') %}
include fastcgi_params;
{% else %}
include fastcgi.conf; include fastcgi.conf;
{% endif %}
} }
{% endblock %} {% endblock %}

View File

@ -1,18 +0,0 @@
{% extends "_php.j2" %}
{% block template_try_files %}
try_files {{ item.override_try_files | default('$uri $uri/ /index.php') }};
{% endblock %}
{% block template_upstream_location %}
location = /index.php {
fastcgi_pass {{ item.php_upstream }};
fastcgi_index index.php;
{% if item.upstream_params is defined and item.upstream_params is iterable %}
{% for param in item.upstream_params %}
{{ param }}
{% endfor %}
{% endif %}
include fastcgi.conf;
}
{% endblock %}

View File

@ -7,7 +7,7 @@
{% endblock %} {% endblock %}
{% block template_try_files %} {% block template_try_files %}
include {{ nginx_etc_dir }}/proxy_params; include /etc/nginx/proxy_params;
proxy_pass http://{{ item.upstream_name }}; proxy_pass http://{{ item.upstream_name }};
{% if item.proxy_params is defined and item.proxy_params is iterable %} {% if item.proxy_params is defined and item.proxy_params is iterable %}
{% for param in item.proxy_params %} {% for param in item.proxy_params %}

View File

@ -1,27 +0,0 @@
{% extends "_php.j2" %}
{% block template_try_files %}
try_files $uri /index.php$is_args$args;
{% endblock %}
{% block template_upstream_location %}
location /bundles {
try_files $uri =404;
}
location ~ ^/index\.php(/|$) {
fastcgi_pass {{ item.php_upstream }};
fastcgi_index index.php;
{% if item.upstream_params is defined and item.upstream_params is iterable %}
{% for param in item.upstream_params %}
{{ param }}
{% endfor %}
{% endif %}
include fastcgi.conf;
internal;
}
location ~ \.php$ {
return 404;
}
{% endblock %}

View File

@ -3,9 +3,3 @@
{% block template_try_files %} {% block template_try_files %}
try_files $uri $uri/ /index.php?$args; try_files $uri $uri/ /index.php?$args;
{% endblock %} {% endblock %}
{% block template_custom_location %}
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}
{% endblock %}

View File

@ -0,0 +1,15 @@
#
# {{ ansible_managed }}
#
upstream php {
{% for item in nginx_php_sockets %}
{% if item.unix_socket is defined %}
server unix:{{ item.unix_socket }} weight={{ item.weight | default('1') }};
{% else %}
server {{ item.host }}:{{ item.port }} weight={{ item.weight | default('1') }} max_fails={{ item.max_fails | default('5') }} fail_timeout={{ item.fail_timeout | default('10s') }};
{% endif %}
{% endfor %}
}
# vim:filetype=nginx

View File

@ -1,5 +1,5 @@
{%- macro s(key, value, is_bool, min_version) %} {%- macro s(key, value, is_bool, min_version) %}
{% if nginx_version.stdout is version(min_version, 'ge') %} {% if nginx_version.stdout | version_compare(min_version, 'ge') %}
{% if is_bool and value %} {{ key }}{% elif not is_bool %} {{ key }}={{ value }}{% endif %} {% if is_bool and value %} {{ key }}{% elif not is_bool %} {{ key }}={{ value }}{% endif %}
{% endif %} {% endif %}
{%- endmacro -%} {%- endmacro -%}

View File

@ -0,0 +1,4 @@
FROM williamyeh/ansible:debian8-onbuild
RUN apt-get update
CMD ["sh", "tests/test.sh"]

View File

@ -0,0 +1,4 @@
FROM williamyeh/ansible:debian7-onbuild
RUN apt-get update
CMD ["sh", "tests/test.sh"]

1
tests/inventory 100644
View File

@ -0,0 +1 @@
localhost

21
tests/test.sh 100644
View File

@ -0,0 +1,21 @@
#!/bin/sh
# Thanks to https://servercheck.in/blog/testing-ansible-roles-travis-ci-github
DIR=$( dirname $0 )
INVENTORY_FILE="$DIR/inventory"
PLAYBOOK="$DIR/test.yml"
set -ev
# Check syntax
ansible-playbook -i $INVENTORY_FILE -c local --syntax-check -vv $PLAYBOOK
# Check role
ansible-playbook -i $INVENTORY_FILE -c local --sudo -vv $PLAYBOOK
# Check indempotence
ansible-playbook -i $INVENTORY_FILE -c local --sudo -vv $PLAYBOOK \
| grep -q 'changed=0.*failed=0' \
&& (echo 'Idempotence test: pass' && exit 0) \
|| (echo 'Idempotence test: fail' && exit 1)

328
tests/test.yml 100644
View File

@ -0,0 +1,328 @@
---
- hosts: all
pre_tasks:
- name: APT_REPOSITORY | Install backports
apt_repository: repo='deb http://httpredir.debian.org/debian {{ ansible_distribution_release }}-backports main' state=present
- name: APT | Install needed packages
apt: pkg={{ item }} update_cache=yes cache_valid_time=3600 state=present
with_items:
- php5-fpm
- curl
- fcgiwrap
- name: SERVICE | Force start services
service: name={{ item }} state=started
register: sf
with_items:
- php5-fpm
- fcgiwrap
- name: PAUSE | Prevent bugs (CGI not fully loaded)
pause: seconds=5
when: sf.changed
- name: FILE | Create an internal SSL dir
file: path={{ int_ansible_ssl_dir }} state=directory
- name: COPY | Deploy test certificate
copy: src=file/test.crt dest={{ int_ansible_ssl_dir }}/test.crt
- name: COPY | Deploy test key
copy: src=file/test.key dest={{ int_ansible_ssl_dir }}/test.key
vars:
# Internal vars
int_ansible_ssl_dir: '/etc/ansible-ssl'
# Role vars
nginx_backports: true
nginx_php: true
nginx_upstreams:
- name: 'test'
servers:
- path: '127.0.0.1:80'
max_conns: 150
weight: 10
down: false
nginx_htpasswd:
- name: 'hello'
description: 'Please login!'
users:
- name: 'hx'
password: 'asdfg'
state: 'absent'
- name: 'hanx'
password: 'qwerty'
- name: 'nagios'
description: 'Please login to Nagios!'
users:
- name: 'nagiosadmin'
password: 'nagios'
- name: 'deleteme'
description: 'Please login!'
users: []
state: 'absent'
nginx_ssl_pairs:
- name: 'test-ssl-predeployed.local'
dest_key: "{{ int_ansible_ssl_dir }}/test.key"
dest_cert: "{{ int_ansible_ssl_dir }}/test.crt"
- name: 'test-ssl.local'
key: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvavrJWFp3Al2VwRgKx+4Y2mbRRvoxvyd2pyN0xMJ/tCJscaG
8s60v6WZ9FcCOeMkSI2DXsk4z7pbQdQn0h2GDr/5MOJkPAVWSWEN46tpaLZ3v0zp
88ZIbnEk1G0PsdFuW/pnLsakPlAMrl1VArFsV6YsatLt30UIYYcRO97StkoOehCx
A5w+XqtfHZeQZ0/DS81633gwYUcMuSTUFZ60r7ge1/m77DTSKg3rTVk5sebP8cjS
+aWHvxP/GyvvDsT+3gjRJx2/5O3JkfH0zaOsaU2Avj0PR0c5rhynrNO/l1k+GJJB
cbBrM+yA8Ofzp4oXUrCfaIq3RuL3Pd+khcKsiwIDAQABAoIBAQCPpAMQ7BUfbosQ
m1+5SOx7XR8Z12kSSX3CcY12rJSFRakB2TeZ6rE38lIFmV82N67iw0kaH4nGx3sU
/3aoyXMc+IXfX5RJYEFYkQfTw5ywkH9fgQAsfZ2dBlK+DVo1cEYDoj9CTW1VQ4pX
Ape+0l8agd5hiBxdWgpe0ctbbARnx584viLiA/iPBDNxKi9zEYw+WP7hSj5QWahr
a09tubcC4L6tjvv8CoZTRSKfCW64vWRDvE6vmA+zJN9Arc1WTYzF1KO1Gybwf8h7
stJb191smAgGDFhKo0j58ncyAnrS1k4mapm86QQhlfIA6DKvvC0qm3KdQns5b7HM
PyzW0hwBAoGBAO2mTVTOsziom9vtBwM0nRMMEgynR2X3EKMJz2mjcCf66f1F+aQ5
DvQFM2V8S2s1nGnPh8NKKZ8DxW1NKuR4qx82zeAXpUs9ibHxOnw4YRC485zqc2Wt
fSO1OEDYeKyzWP1nGGtCntYUXzJnWn/wz0mBGKzLKTuLwyFIKx1b7bybAoGBAMxR
N+lT57rX6d4GUqcgNOuWMZ/D8egnE5+hsoiFnHOisRLOgUgBBSy4rwAZx+rdHYT+
RO11L1PLYEzyvnO0f13R+N7aqKwNXDSzZGA+jb4pjkVidIC2smG/JYKJH5Z+kakw
mwMKP0wdRZJsCaMgScHmWJS8d6Ox/XJJoWrTWTbRAoGAWJlEgVaiaIArwz1F/QLz
gHNik0cWDkSi9jWlFxwwpycbbypUXM5M7dq2g6JoN6sACk6trbgLdlYgl5RKZm06
VuPGs0H9hOSHXkix5jfasDJT2G9r4D9ixRo9w6cwriobBjYWW3612tgzeYYgrkwn
655uhZUkZSfA8rqGIGbyZfsCgYAf5WH8G+wmIATTc1s92epJCOZwUY+XNVp75itP
4sPczX4lOHW4PuiG5cH0GxI5mRE9rNAn3c5on2xGNvMCbyAfDmNyruH8Eg3d8E9w
MvO/xw79x/P2EA9i8QszCKMUxGeK6RqZ6+SbxkoRJKqQe77n9UTI228179hoGhSH
77ySsQKBgQC8SSZn6a8PpSIIFXB9WCFMwfGFYbUz0wvpaeZP8GKx3BEzMeJqSUaJ
hrQgpwQXkueeamlCQcvV3AUCoBRWTYRLDrWiUIXuIgikDWBFp6TBvTnVRI7iktly
fNED7jXOSjJqnFmdkZlAI5V8dM++mVYVykJD6jcaVRQvxqFLrhSaRg==
-----END RSA PRIVATE KEY-----
cert: |
-----BEGIN CERTIFICATE-----
MIIDBTCCAe2gAwIBAgIJALKJfbk5vuieMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNV
BAMMDnRlc3Qtc3NsLmxvY2FsMB4XDTE2MDExMTE2NDI0NFoXDTI2MDEwODE2NDI0
NFowGTEXMBUGA1UEAwwOdGVzdC1zc2wubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQC9q+slYWncCXZXBGArH7hjaZtFG+jG/J3anI3TEwn+0Imx
xobyzrS/pZn0VwI54yRIjYNeyTjPultB1CfSHYYOv/kw4mQ8BVZJYQ3jq2lotne/
TOnzxkhucSTUbQ+x0W5b+mcuxqQ+UAyuXVUCsWxXpixq0u3fRQhhhxE73tK2Sg56
ELEDnD5eq18dl5BnT8NLzXrfeDBhRwy5JNQVnrSvuB7X+bvsNNIqDetNWTmx5s/x
yNL5pYe/E/8bK+8OxP7eCNEnHb/k7cmR8fTNo6xpTYC+PQ9HRzmuHKes07+XWT4Y
kkFxsGsz7IDw5/OnihdSsJ9oirdG4vc936SFwqyLAgMBAAGjUDBOMB0GA1UdDgQW
BBRaSF1L+ivPhmIVGQjtviBqZWDS9DAfBgNVHSMEGDAWgBRaSF1L+ivPhmIVGQjt
viBqZWDS9DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCjrgB9+Zuq
Rx7T2mRUl4jf75dLabuBQD0ePALTtvNyBSghhzSr90mE7GlFOYAv0JsmEa3R1LVF
wLPIdrIhNHpt7hN0PkhUlfgmxBnRSCfhpiq4xxsDVFM7ehtDz4+dv1LUDMXo07+E
f24g9aqmypiFzHisUQrYIhtQmHxRpKyGp6kDAW9qNxg6k/Um00aHdYfuD9ER4ksR
f8Hto7f+vssKxCRY2OZXqq13PxEwC5+hgAUkTdrycA/moXFuHJi3lCnCND7sSzvG
tXBggOusyFZFC4bs2m+V+Z+RN+tK2c/c0nq5HR8MV5HwIm4Z8GoT2/0BfJ00cgWL
lVz0gDBfdH8f
-----END CERTIFICATE-----
nginx_custom_http:
- 'add_header X-ansible 1;'
nginx_default_vhost: 'test.local'
nginx_default_vhost_ssl: 'test-ssl-predeployed.local'
nginx_vhosts:
- name:
- 'test.local'
- 'test-alias.local'
- 'test2-alias.local'
template: '_base'
override_try_files: '$uri $uri index.htm index.html'
manage_local_content: false
more:
- 'autoindex off;'
- 'add_header X-ansible-default 1;'
location:
'/test':
- 'return 403;'
'/gunther':
- 'return 404;'
- name: 'test-htpasswd.local'
template: '_base'
location:
'/hello':
- htpasswd: 'hello'
- 'default_type "text/html; charset=UTF-8";'
- 'echo hello;'
- name: 'test-htpasswd-all.local'
template: '_base'
htpasswd: 'hello'
- name: 'test-location.local'
template: '_base'
location:
'/':
- 'alias /var/tmp;'
- name: 'test-php.local'
upstream_params:
- 'fastcgi_param FOO bar;'
redirect_from:
- 'www.test-php.local'
template: '_php'
- name: 'test-php-index.local'
template: '_php_index'
- name: 'test-proxy.local'
listen:
- 8080
template: '_proxy'
upstream_name: 'test'
more:
- 'add_header X-proxyfied 1;'
- name: 'deleted.local'
delete: true
- name: 'redirect-to.local'
redirect_to: 'http://test.local'
- name: 'backuppc.local'
template: '_backuppc'
htpasswd: 'hello'
- name: 'nagios3.local'
template: '_nagios3'
htpasswd: 'nagios'
- name: 'test-ssl.local'
proto: ['http', 'https']
template: '_base'
ssl_name: 'test-ssl.local'
- name: 'test-ssl-predeployed.local'
proto: ['http', 'https']
template: '_base'
ssl_name: 'test-ssl-predeployed.local'
more:
- 'add_header X-ansible-default 1;'
nginx_dh_length: 1024
roles:
- ../../
post_tasks:
# --------------------------------
# Apps
# --------------------------------
- name: APT | Install web apps
apt: pkg={{ item }} state=present
with_items:
- nagios3
- backuppc
- name: SERVICE | Ensure backuppc is started
service: name=backuppc state=started
# --------------------------------
# Deploy index files
# --------------------------------
- name: -- Add PHP file --
copy: dest="{{ nginx_root }}/{{ item }}/public/index.php" content="<?php phpinfo();"
with_items: ['test-php.local', 'test-php-index.local']
- name: -- Add HTML file --
copy: dest="{{ item }}/index.html" content="Index HTML test OK\n"
with_items: ['{{ nginx_root }}/test.local/public', '/var/tmp', '{{ nginx_root }}/test-htpasswd-all.local/public', '{{ nginx_root }}/test-ssl.local/public', '{{ nginx_root }}/test-ssl-predeployed.local/public']
# --------------------------------
# Simple vhosts tests
# --------------------------------
- name: -- VERIFY VHOSTS --
command: "curl -H 'Host: {{ item.name if item.name is string else item.name[0] }}' http://127.0.0.1{% if item.listen is defined %}:{{ item.listen[0] }}{% endif %}/"
with_items: nginx_vhosts
when: item.delete is undefined or not item.delete
changed_when: false
- name: -- VERIFY FORBIDDEN --
command: "curl -H 'Host: test-php-index.local' http://127.0.0.1/phpinfo.php"
register: f
failed_when: f.stdout.find('403 Forbidden') == -1
changed_when: false
- name: -- VERIFY REDIRECT VHOSTS --
command: "curl -H 'Host: {{ item.redirect_from[0] }}' http://127.0.0.1/"
with_items: nginx_vhosts
when: item.redirect_from is defined and (item.delete is undefined or not item.delete)
changed_when: false
register: r
failed_when: r.stdout.find('301 Moved Permanently') == -1
# --------------------------------
# PHP
# --------------------------------
- name: -- VERIFY PHP VHOSTS --
command: "curl -H 'Host: {{ item }}' http://127.0.0.1/"
register: p
changed_when: false
failed_when: p.stdout.find('PHP Version') == -1
with_items: ['test-php.local', 'test-php-index.local']
# --------------------------------
# Basic Auth
# --------------------------------
- name: -- VERIFY AUTH BASIC NONE --
command: "curl -H 'Host: test-htpasswd.local' http://127.0.0.1/hello"
changed_when: false
register: authnone
failed_when: authnone.stdout.find('401 Authorization Required') == -1
- name: -- VERIFY AUTH BASIC FAIL --
command: "curl -u fail:fail -H 'Host: test-htpasswd.local' http://127.0.0.1/hello"
changed_when: false
register: authfail
failed_when: authfail.stdout.find('401 Authorization Required') == -1
- name: -- VERIFY AUTH BASIC OK --
command: "curl -u hanx:qwerty -H 'Host: test-htpasswd.local' http://127.0.0.1/hello"
changed_when: false
register: authok
failed_when: authok.stdout.find('hello') == -1
- name: -- VERIFY AUTH BASIC FAIL GLOBAL --
command: "curl -u fail:fail -H 'Host: test-htpasswd-all.local' http://127.0.0.1/"
changed_when: false
register: authgfail
failed_when: authgfail.stdout.find('401 Authorization Required') == -1
- name: -- VERIFY AUTH BASIC OK --
command: "curl -u hanx:qwerty -H 'Host: test-htpasswd-all.local' http://127.0.0.1/"
changed_when: false
register: authgok
failed_when: authgok.stdout.find('401 Authorization Required') != -1
# --------------------------------
# BackupPC
# --------------------------------
- name: -- VERIFY BACKUPPC --
command: "curl -u hanx:qwerty -H 'Host: backuppc.local' http://127.0.0.1/"
changed_when: false
register: authbpc
failed_when: authbpc.stdout.find('BackupPC Server Status') == -1
# --------------------------------
# Nagios
# --------------------------------
- name: -- VERIFY NAGIOS3 PHP --
command: "curl -u nagiosadmin:nagios -H 'Host: nagios3.local' http://127.0.0.1/side.php"
changed_when: false
register: nagios_php
failed_when: nagios_php.stdout.find('Nagios Core') == -1
- name: -- VERIFY NAGIOS3 CGI --
command: "curl -u nagiosadmin:nagios -H 'Host: nagios3.local' http://127.0.0.1/cgi-bin/nagios3/summary.cgi"
changed_when: false
register: nagios_cgi
failed_when: nagios_cgi.stdout.find('Nagios Event Summary') == -1
# --------------------------------
# SSL
# --------------------------------
- name: -- VERIFY SSL --
command: "curl --insecure -H 'Host: {{ item }}' https://127.0.0.1/"
changed_when: false
register: sslok
failed_when: sslok.stdout.find('Index HTML test OK') == -1
with_items:
- 'test-ssl-predeployed.local'
- 'test-ssl.local'
# --------------------------------
# Default vhosts
# --------------------------------
- name: -- VERIFY DEFAULT VHOST --
command: "curl -v http://127.0.0.1/"
changed_when: false
register: vdefault
failed_when: >
vdefault.stdout.find('Index HTML test OK') == -1 or
vdefault.stderr.find('X-ansible-default') == -1
- name: -- VERIFY DEFAULT SSL VHOST --
command: "curl --insecure -v https://127.0.0.1/"
changed_when: false
register: defaultssl
failed_when: >
defaultssl.stdout.find('Index HTML test OK') == -1 or
defaultssl.stderr.find('X-ansible-default') == -1
- name: -- VERIFY NOT DEFAULT VHOST --
command: "curl -v -H 'Host: test-php.local' http://127.0.0.1/"
changed_when: false
register: vphp
failed_when: vphp.stderr.find('X-ansible-default') != -1
- name: -- VERIFY NOT DEFAULT SSL VHOST --
command: "curl --insecure -v -H 'Host: test-ssl.local' https://127.0.0.1/"
changed_when: false
register: notdefaultssl
failed_when: notdefaultssl.stderr.find('X-ansible-default') != -1

View File

@ -1,5 +0,0 @@
---
nginx_events_use: 'epoll'
nginx_pid: '/run/nginx.pid'
nginx_etc_dir: '/etc/nginx'

View File

@ -1,5 +1,3 @@
---
nginx_upstream_server_params: nginx_upstream_server_params:
- key: 'weight' - key: 'weight'
default: 1 default: 1
@ -25,28 +23,11 @@ nginx_upstream_server_params:
# min_version: '1.5.12' # min_version: '1.5.12'
nginx_dirs: nginx_dirs:
- dir: "{{ nginx_htpasswd_dir }}" - "{{ nginx_htpasswd_dir }}"
mode: "0750" - "{{ nginx_ssl_dir }}"
owner: "{{ nginx_user }}" - "{{ nginx_helper_dir }}"
- dir: "{{ nginx_ssl_dir }}"
mode: "0750"
owner: "root"
- dir: "{{ nginx_helper_dir }}"
mode: "0755"
owner: "root"
- dir: "{{ nginx_etc_dir }}/modules-available"
mode: "0755"
owner: "root"
- dir: "{{ nginx_etc_dir }}/modules-enabled"
mode: "0755"
owner: "root"
nginx_templates_no_dir: nginx_templates_no_dir:
- '_proxy' - '_proxy'
- '_nagios3'
nginx_servers_default_headers: - '_backuppc'
'X-Frame-Options': 'DENY always'
'X-Content-Type-Options': 'nosniff always'
'X-XSS-Protection': '1; mode=block always'
nginx_acmesh_bin: "{{ nginx_acmesh_dir }}/acme.sh"