├── tasks ├── main.yml ├── prerequisites.yml ├── configure.yml ├── install.yml └── site.yml ├── .gitignore ├── handlers └── main.yml ├── templates ├── status-site ├── default-site ├── uwsgi_params ├── static-site ├── fastcgi_params └── nginx.conf ├── meta └── main.yml ├── main.yml ├── inventory ├── test.yml ├── boxed.yml ├── .travis.yml ├── LICENSE.md ├── Vagrantfile ├── files └── mime.types ├── README.md └── defaults └── main.yml /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: prerequisites.yml 4 | - include: install.yml 5 | - include: configure.yml 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Don't commit vagrant's machine specifications, 2 | # which are unique for each installation. 3 | /.vagrant/ 4 | 5 | # Ignore the www directory used for boxed installs 6 | /~www/ -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: restart nginx 4 | sudo: yes 5 | service: name=nginx state=restarted 6 | 7 | - name: reload nginx 8 | sudo: yes 9 | service: name=nginx state=reloaded -------------------------------------------------------------------------------- /templates/status-site: -------------------------------------------------------------------------------- 1 | server { 2 | listen 127.0.0.1; 3 | server_name _; 4 | 5 | location /nginx_status { 6 | stub_status on; 7 | access_log off; 8 | allow 127.0.0.1; 9 | deny all; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tasks/prerequisites.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Prerequisites for provisioning (pycurl) 4 | when: ansible_os_family == 'Debian' 5 | sudo: yes 6 | apt: 7 | name: python-pycurl 8 | tags: 9 | - nginx 10 | - frontend 11 | - python 12 | - deps 13 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | galaxy_info: 4 | author: zenoamaro 5 | description: A role to install and configure NGiNX 6 | version: 0.2 7 | license: MIT 8 | min_ansible_version: 1.4 9 | 10 | platforms: 11 | - name: Debian 12 | - name: Ubuntu 13 | versions: 14 | - precise 15 | - trusty 16 | 17 | categories: 18 | - web 19 | 20 | dependencies: [] 21 | -------------------------------------------------------------------------------- /main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Quick-provisioning playbook 4 | # --------------------------- 5 | 6 | # A Simple, straight playbook for quick remote installations. 7 | # You will be asked which hosts to provision before-hand. 8 | 9 | 10 | - name: 'Nginx' 11 | 12 | vars_prompt: 13 | selected_hosts: Specify the hosts to provision 14 | 15 | hosts: "{{selected_hosts}}" 16 | 17 | roles: 18 | - '.' # The current directory itself is the role 19 | 20 | -------------------------------------------------------------------------------- /templates/default-site: -------------------------------------------------------------------------------- 1 | # This is a default site configuration which will simply 2 | # return 404, preventing chance access to any other virtualhost. 3 | 4 | server { 5 | listen {{nginx_default_http_port}} default_server; 6 | server_name _; 7 | 8 | error_page 404 /404.html; 9 | 10 | # Everything is a 404 11 | location / { 12 | return 404; 13 | } 14 | 15 | # You may need this to prevent return 404; recursion 16 | location = /404.html { 17 | internal; 18 | } 19 | } -------------------------------------------------------------------------------- /inventory: -------------------------------------------------------------------------------- 1 | [boxed] 2 | 192.168.33.10 ansible_ssh_private_key_file=.vagrant/machines/boxed/virtualbox/private_key 3 | 4 | [test-ubuntu-precise] 5 | 192.168.33.20 ansible_ssh_private_key_file=.vagrant/machines/test-ubuntu-precise/virtualbox/private_key 6 | 7 | [test-ubuntu-trusty] 8 | 192.168.33.21 ansible_ssh_private_key_file=.vagrant/machines/test-ubuntu-trusty/virtualbox/private_key 9 | 10 | [test:children] 11 | test-ubuntu-precise 12 | test-ubuntu-trusty 13 | 14 | [vagrant:children] 15 | test 16 | boxed 17 | 18 | [vagrant:vars] 19 | ansible_ssh_user=vagrant -------------------------------------------------------------------------------- /test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Integration testing playbook 4 | # ---------------------------- 5 | 6 | # A playbook for testing and integration. 7 | 8 | # It will provision the `test` hosts in the inventory, 9 | # which will, by default, specify the provided vagrant VM. 10 | 11 | # This playbook should aim to test the most extensive 12 | # or comprehensive configuration possible for your role. 13 | 14 | 15 | - name: 'Role integration tests' 16 | 17 | hosts: test 18 | 19 | vars: 20 | # custom_configuration: value 21 | 22 | roles: 23 | - '.' # The current directory itself is the role 24 | 25 | -------------------------------------------------------------------------------- /templates/uwsgi_params: -------------------------------------------------------------------------------- 1 | uwsgi_param QUERY_STRING $query_string; 2 | uwsgi_param REQUEST_METHOD $request_method; 3 | uwsgi_param CONTENT_TYPE $content_type; 4 | uwsgi_param CONTENT_LENGTH $content_length; 5 | uwsgi_param REQUEST_URI $request_uri; 6 | uwsgi_param PATH_INFO $document_uri; 7 | uwsgi_param DOCUMENT_ROOT $document_root; 8 | uwsgi_param SERVER_PROTOCOL $server_protocol; 9 | uwsgi_param REMOTE_ADDR $remote_addr; 10 | uwsgi_param REMOTE_PORT $remote_port; 11 | uwsgi_param SERVER_ADDR $server_addr; 12 | uwsgi_param SERVER_PORT $server_port; 13 | uwsgi_param SERVER_NAME $server_name; -------------------------------------------------------------------------------- /boxed.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Boxed installation playbook 4 | # --------------------------- 5 | 6 | # A Simple, straight playbook for producing 7 | # a boxed installation in a vagrant VM. 8 | 9 | 10 | - name: 'Nginx boxed installation' 11 | 12 | hosts: vagrant 13 | 14 | # vars: 15 | # custom_configuration: value 16 | 17 | post_tasks: 18 | # Produce a default site pointing to the shared folder 19 | - include: tasks/site.yml 20 | site: www 21 | port: 80 22 | server_name: 192.168.33.20 23 | access_log: /var/www/site/~access.log 24 | error_log: /var/www/site/~error.log 25 | document_root: /var/www/site 26 | 27 | roles: 28 | - '.' # The current directory itself is the role 29 | 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Configuration directives for Travis CI 4 | # -------------------------------------- 5 | 6 | # See the Travis documentation for help on writing this file. 7 | 8 | # [Travis CI] http://travis-ci.org 9 | # [configuration] http://about.travis-ci.org/docs/user/build-configuration/ 10 | 11 | 12 | language: python # Needed to run ansible 13 | 14 | python: 15 | - "2.7" 16 | 17 | install: 18 | - pip install ansible 19 | 20 | script: 21 | # Syntax check every ansible playbook in root 22 | # Don't check main, though, as vars_prompt still 23 | # trigger during syntax checks, and travis fails 24 | - find . -maxdepth 1 -type f -name '*.yml' -not -name '.*' -not -name 'main.yml' | xargs -t -n1 ansible-playbook --syntax-check -i inventory 25 | 26 | notifications: 27 | email: 28 | - zenoamaro@gmail.com -------------------------------------------------------------------------------- /templates/static-site: -------------------------------------------------------------------------------- 1 | server { 2 | 3 | listen {{port|default(nginx_default_http_port)}}; 4 | {% if server_name is defined and server_name %} 5 | server_name {{server_name}}; 6 | {% else %} 7 | server_name default_server; 8 | {% endif %} 9 | 10 | {% if log_assets|default(False) and access_log|default(False) %} 11 | access_log {{access_log}}; 12 | {% else %} 13 | access_log off; 14 | {% endif %} 15 | {% if error_log|default(False) %} 16 | error_log {{error_log}}; 17 | {% endif %} 18 | 19 | root {{document_root}}; 20 | expires max; # Cache assets indefinitely 21 | 22 | # Ignore files starting with `~` 23 | location ~ ^~*$ { 24 | return 404; 25 | } 26 | 27 | # Log access to html files, and expire them in 1h 28 | location ~*\.(html)$ { 29 | {% if access_log|default(False) %} 30 | access_log {{access_log}}; 31 | {% endif %} 32 | expires 1h; 33 | } 34 | 35 | # Redirect server error pages to the static page /50x.html 36 | error_page 500 502 503 504 /50x.html; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015, zenoamaro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /tasks/configure.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Create sites directories 4 | sudo: yes 5 | file: 6 | dest: "{{item}}" 7 | state: directory 8 | with_items: 9 | - "{{nginx_available_sites_dir}}" 10 | - "{{nginx_enabled_sites_dir}}" 11 | notify: restart nginx 12 | tags: 13 | - nginx 14 | - frontend 15 | - conf 16 | 17 | - name: Configure Nginx 18 | sudo: yes 19 | template: 20 | src: "{{item}}" 21 | dest: "{{nginx_conf_dir}}/{{item}}" 22 | with_items: 23 | - nginx.conf 24 | - fastcgi_params 25 | - uwsgi_params 26 | notify: restart nginx 27 | tags: 28 | - nginx 29 | - frontend 30 | - conf 31 | 32 | - name: Configure Nginx 33 | sudo: yes 34 | copy: 35 | src: "{{item}}" 36 | dest: "{{nginx_conf_dir}}/{{item}}" 37 | with_items: 38 | - mime.types 39 | notify: restart nginx 40 | tags: 41 | - nginx 42 | - frontend 43 | - conf 44 | 45 | - include: site.yml 46 | site: "{{nginx_default_site_name}}" 47 | template: default-site 48 | when: nginx_create_default_site 49 | 50 | - include: site.yml 51 | site: status 52 | template: status-site 53 | when: nginx_create_status_site 54 | -------------------------------------------------------------------------------- /tasks/install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Targeting specific OSes or distributions: 4 | # 5 | # - `ansible_system` → Linux, BSD, ... 6 | # - `ansible_os_family` → Debian, RedHat, ... 7 | # - `ansible_distribution` → Debian, Ubuntu, RedHat, ... 8 | # - `ansible_distribution_release` → precise, wheezy, ... 9 | # - `ansible_pkg_mgr` → apt, yum, ... 10 | # - `ansible_architecture` → x86_64, x86_32, ... 11 | 12 | 13 | # Debian 14 | # ------ 15 | 16 | - name: Adding APT repository key 17 | when: ansible_os_family == 'Debian' 18 | sudo: yes 19 | apt_key: 20 | url: "http://nginx.org/keys/nginx_signing.key" 21 | tags: 22 | - nginx 23 | - frontend 24 | - repo 25 | 26 | - name: Add official APT repository 27 | when: ansible_os_family == 'Debian' 28 | sudo: yes 29 | apt_repository: 30 | repo: "deb http://nginx.org/packages/{{ansible_distribution|lower}}/ {{ansible_distribution_release}} nginx" 31 | tags: 32 | - nginx 33 | - frontend 34 | - repo 35 | 36 | - name: Install Nginx 37 | when: ansible_os_family == 'Debian' 38 | sudo: yes 39 | apt: 40 | name: "nginx={{nginx_version}}" 41 | state: present 42 | update_cache: yes 43 | cache_valid_time: 3600 44 | tags: 45 | - nginx 46 | - frontend 47 | - deps 48 | -------------------------------------------------------------------------------- /templates/fastcgi_params: -------------------------------------------------------------------------------- 1 | fastcgi_param QUERY_STRING $query_string; 2 | fastcgi_param REQUEST_METHOD $request_method; 3 | fastcgi_param CONTENT_TYPE $content_type; 4 | fastcgi_param CONTENT_LENGTH $content_length; 5 | 6 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 7 | fastcgi_param SCRIPT_NAME $fastcgi_script_name; 8 | fastcgi_param PATH_INFO $fastcgi_path_info; 9 | fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; 10 | fastcgi_param REQUEST_URI $request_uri; 11 | fastcgi_param DOCUMENT_URI $document_uri; 12 | fastcgi_param DOCUMENT_ROOT $document_root; 13 | fastcgi_param SERVER_PROTOCOL $server_protocol; 14 | 15 | fastcgi_param GATEWAY_INTERFACE CGI/1.1; 16 | fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; 17 | 18 | fastcgi_param REMOTE_ADDR $remote_addr; 19 | fastcgi_param REMOTE_PORT $remote_port; 20 | fastcgi_param SERVER_ADDR $server_addr; 21 | fastcgi_param SERVER_PORT $server_port; 22 | fastcgi_param SERVER_NAME $server_name; 23 | 24 | fastcgi_param HTTPS $https; 25 | 26 | # PHP only, required if PHP was built with --enable-force-cgi-redirect 27 | fastcgi_param REDIRECT_STATUS 200; -------------------------------------------------------------------------------- /tasks/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Include this task to create and link or remove a virtualhost. 4 | # 5 | # site: The name of the site 6 | # template: The template used to produce the site 7 | # (a simple static-serving website by default) 8 | # state: can be `present`, `enabled` (default), or `absent` 9 | # 10 | # Be aware that you will probably have to play with paths like this: 11 | # 12 | # - include: ../../nginx/tasks/site.yml 13 | # template: ../../caller/templates/virtualhost 14 | # 15 | # Other specified properties will be available to the template. 16 | 17 | - name: "Site {{site}} | Create site" 18 | sudo: yes 19 | template: 20 | src: "{{template|default('static-site')}}" 21 | dest: "{{nginx_available_sites_dir}}/{{site}}" 22 | when: state is not defined or state in ['present', 'enabled'] 23 | notify: reload nginx 24 | tags: 25 | - nginx 26 | - frontend 27 | - conf 28 | - sites 29 | 30 | - name: "Site {{site}} | Remove site" 31 | sudo: yes 32 | file: 33 | dest: "{{nginx_available_sites_dir}}/{{site}}" 34 | state: 'absent' 35 | when: state is defined and state == 'absent' 36 | notify: reload nginx 37 | tags: 38 | - nginx 39 | - frontend 40 | - conf 41 | - sites 42 | 43 | - name: "Site {{site}} | Set site as {{'enabled' if (state is not defined or state == 'enabled') else 'disabled'}}" 44 | sudo: yes 45 | file: 46 | src: "{{nginx_available_sites_dir}}/{{site}}" 47 | dest: "{{nginx_enabled_sites_dir}}/{{site}}" 48 | state: "{{'link' if (state is not defined or state == 'enabled') else 'absent'}}" 49 | notify: reload nginx 50 | tags: 51 | - nginx 52 | - frontend 53 | - conf 54 | - sites 55 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure '2' do |config| 5 | 6 | 7 | # Standalone box 8 | # -------------- 9 | 10 | # Provision this machine to obtain a standalone box 11 | # listening on the default ports. 12 | 13 | config.vm.define 'boxed' do |box| 14 | box.vm.box = "ubuntu/trusty64" 15 | # Configure the network topology to your needs 16 | config.vm.network :private_network, ip: "192.168.33.10" 17 | # config.vm.network :public_network 18 | config.vm.provision :ansible do |ansible| 19 | ansible.playbook = './boxed.yml' 20 | ansible.inventory_path = './inventory' 21 | end 22 | # Forward this installation to a port on the host 23 | # config.vm.network :forwarded_port, guest: 80, host: 8080 24 | # You may want to share a folder from your host system. 25 | config.vm.synced_folder './~www', '/var/www/site', 26 | :mount_options => ['dmode=777', 'fmode=777'], 27 | :disabled => false 28 | end 29 | 30 | 31 | # Test machines 32 | # ------------- 33 | 34 | # These test machines will configure the installation with all 35 | # its extensions enabled, in order to test the validity 36 | # of the role. 37 | 38 | # Ubuntu machines are available: 39 | # - "test-ubuntu-precise" 40 | # - "test-ubuntu-trusty" 41 | 42 | def apply_test_ansible_defaults(ansible) 43 | ansible.playbook = './test.yml' 44 | ansible.inventory_path = './inventory' 45 | end 46 | 47 | config.vm.define 'test-ubuntu-trusty', autostart:false do |box| 48 | box.vm.box = "ubuntu/trusty64" 49 | config.vm.network :private_network, ip: "192.168.33.21" 50 | config.vm.provision :ansible do |ansible| 51 | apply_test_ansible_defaults ansible 52 | ansible.extra_vars = {} 53 | end 54 | end 55 | 56 | config.vm.define 'test-ubuntu-precise', autostart:false do |box| 57 | box.vm.box = "ubuntu/precise64" 58 | config.vm.network :private_network, ip: "192.168.33.20" 59 | config.vm.provision :ansible do |ansible| 60 | apply_test_ansible_defaults ansible 61 | ansible.extra_vars = {} 62 | end 63 | end 64 | 65 | end 66 | -------------------------------------------------------------------------------- /files/mime.types: -------------------------------------------------------------------------------- 1 | types { 2 | text/html html htm shtml; 3 | text/css css; 4 | text/xml xml rss; 5 | image/gif gif; 6 | image/jpeg jpeg jpg; 7 | application/x-javascript js; 8 | application/atom+xml atom; 9 | 10 | text/mathml mml; 11 | text/plain txt; 12 | text/vnd.sun.j2me.app-descriptor jad; 13 | text/vnd.wap.wml wml; 14 | text/x-component htc; 15 | 16 | image/png png; 17 | image/tiff tif tiff; 18 | image/vnd.wap.wbmp wbmp; 19 | image/x-icon ico; 20 | image/x-jng jng; 21 | image/x-ms-bmp bmp; 22 | image/svg+xml svg svgz; 23 | 24 | application/java-archive jar war ear; 25 | application/json json; 26 | application/mac-binhex40 hqx; 27 | application/msword doc; 28 | application/pdf pdf; 29 | application/postscript ps eps ai; 30 | application/rtf rtf; 31 | application/vnd.ms-excel xls; 32 | application/vnd.ms-powerpoint ppt; 33 | application/vnd.wap.wmlc wmlc; 34 | application/vnd.google-earth.kml+xml kml; 35 | application/vnd.google-earth.kmz kmz; 36 | application/x-7z-compressed 7z; 37 | application/x-cocoa cco; 38 | application/x-java-archive-diff jardiff; 39 | application/x-java-jnlp-file jnlp; 40 | application/x-makeself run; 41 | application/x-perl pl pm; 42 | application/x-pilot prc pdb; 43 | application/x-rar-compressed rar; 44 | application/x-redhat-package-manager rpm; 45 | application/x-sea sea; 46 | application/x-shockwave-flash swf; 47 | application/x-stuffit sit; 48 | application/x-tcl tcl tk; 49 | application/x-x509-ca-cert der pem crt; 50 | application/x-xpinstall xpi; 51 | application/xhtml+xml xhtml; 52 | application/zip zip; 53 | 54 | application/octet-stream bin exe dll; 55 | application/octet-stream deb; 56 | application/octet-stream dmg; 57 | application/octet-stream eot; 58 | application/octet-stream iso img; 59 | application/octet-stream msi msp msm; 60 | application/ogg ogx; 61 | 62 | audio/midi mid midi kar; 63 | audio/mpeg mpga mpega mp2 mp3 m4a; 64 | audio/ogg oga ogg spx; 65 | audio/x-realaudio ra; 66 | audio/webm weba; 67 | 68 | video/3gpp 3gpp 3gp; 69 | video/mp4 mp4; 70 | video/mpeg mpeg mpg mpe; 71 | video/ogg ogv; 72 | video/quicktime mov; 73 | video/webm webm; 74 | video/x-flv flv; 75 | video/x-mng mng; 76 | video/x-ms-asf asx asf; 77 | video/x-ms-wmv wmv; 78 | video/x-msvideo avi; 79 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Nginx for Ansible 2 | ================= 3 | 4 | A role for deploying and configuring [Nginx](http://nginx.com) and extensions on unix hosts using [Ansible](http://www.ansibleworks.com/). 5 | 6 | It can additionally be used as a playbook for quickly provisioning hosts. 7 | 8 | Vagrant machines are provided to produce a boxed install of Nginx or a VM for integration testing. 9 | 10 | 11 | Supports 12 | -------- 13 | Supported Nginx versions: 14 | - Nginx 1.6.x 15 | - Nginx 1.5.x 16 | - Nginx 1.4.x 17 | 18 | Supported targets: 19 | - Ubuntu 14.04 LTS "Trusty Tahr" 20 | - Ubuntu 12.04 LTS "Precise Pangolin" 21 | - Debian (untested) 22 | 23 | Installation methods: 24 | - Binary packages from the official repositories at [nginx](http://wiki.nginx.org/Install) 25 | 26 | Callable tasks: 27 | - `site`: Creates and enables (or removes) a nginx site 28 | 29 | 30 | Usage 31 | ----- 32 | Clone this repo into your roles directory: 33 | 34 | $ git clone https://github.com/zenoamaro/ansible-nginx.git roles/nginx 35 | 36 | And add it to your play's roles: 37 | 38 | - hosts: ... 39 | roles: 40 | - nginx 41 | - ... 42 | 43 | It is recommended that you pin your NGINX version by setting `nginx_version` to something like `1.6.2`, `1.6.*` or even `1.*`. 44 | 45 | This roles comes preloaded with almost every available default. You can override each one in your hosts/group vars, in your inventory, or in your play. See the annotated defaults in `defaults/main.yml` for help in configuration. All provided variables start with `nginx_`. 46 | 47 | The role provides a default fallback site which returns 404 to all requests not matched by other rules. You can set `nginx_create_default_site` to `false` to disable it. 48 | 49 | You can also use the role as a playbook. You will be asked which hosts to provision, and you can further configure the play by using `--extra-vars`. 50 | 51 | $ ansible-playbook -i inventory --extra-vars='{...}' main.yml 52 | 53 | To provision a standalone Nginx box, create a `~www` directory (by default) with the contents you wish to serve, and start the `boxed` VM, which is a Ubuntu 14.04 box: 54 | 55 | $ vagrant up boxed 56 | 57 | You will find Nginx listening on the VM's on address `192.168.33.20` in the private network. You can then connect to it as usual. You will want to customize it so to serve your sites and assets. 58 | 59 | Run the tests by provisioning the appropriate VM: 60 | 61 | $ vagrant up test-ubuntu-trusty 62 | 63 | At the moment, the following test boxes are available: 64 | 65 | - `test-ubuntu-precise` 66 | - `test-ubuntu-trusty` 67 | 68 | 69 | Still to do 70 | ----------- 71 | - Support other distros 72 | - Add a library of modules (if possible) 73 | - Add useful snippets for tuning, proxying, and writing virtualhosts 74 | - Add quick site definition and shared folder for boxed instances 75 | 76 | 77 | Changelog 78 | --------- 79 | ### 0.2 80 | - Added version pinning. Currently tracking `v1.6.x`. 81 | 82 | ### 0.1.1 83 | - The package list is not being updated in playbooks anymore. 84 | - Added more test machines. 85 | 86 | ### 0.1 87 | Initial version. 88 | 89 | 90 | License 91 | ------- 92 | The MIT License (MIT) 93 | 94 | Copyright (c) 2015, zenoamaro 95 | 96 | Permission is hereby granted, free of charge, to any person obtaining a copy 97 | of this software and associated documentation files (the "Software"), to deal 98 | in the Software without restriction, including without limitation the rights 99 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 100 | copies of the Software, and to permit persons to whom the Software is 101 | furnished to do so, subject to the following conditions: 102 | 103 | The above copyright notice and this permission notice shall be included in 104 | all copies or substantial portions of the Software. 105 | 106 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 107 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 108 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 109 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 110 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 111 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 112 | THE SOFTWARE. -------------------------------------------------------------------------------- /templates/nginx.conf: -------------------------------------------------------------------------------- 1 | # Resources and server options 2 | # ---------------------------- 3 | 4 | user {{nginx_user}} {{nginx_group}}; 5 | pid {{nginx_pid_file}}; 6 | 7 | {% if nginx_workers_count is defined %} 8 | worker_processes {{nginx_workers_count}} 9 | {% else %} 10 | worker_processes {{nginx_workers_per_core * ansible_processor_count * ansible_processor_cores}}; # {{nginx_workers_per_core}} per core. 11 | {% endif %} 12 | 13 | events { 14 | worker_connections {{nginx_worker_connections}}; 15 | 16 | # Accept as many connections as possible, after nginx 17 | # gets notification about a new connection. 18 | # May flood worker_connections, if that option is set too low. 19 | multi_accept {{'on' if nginx_multi_accept else 'off'}}; 20 | 21 | {% if ansible_system == 'Linux' %} 22 | use epoll; 23 | {% endif %} 24 | } 25 | 26 | # Override OS' limit values 27 | worker_rlimit_nofile {{nginx_worker_rlimit_nofile}}; 28 | 29 | http { 30 | 31 | 32 | # Logging 33 | # ------- 34 | 35 | error_log '{{nginx_error_log_file}}' {{nginx_error_log_level|default('')}}; 36 | 37 | {% for name, format in nginx_log_formats.items() %} 38 | log_format {{name}} '{{format|replace('\'', '\\\'')}}'; 39 | {% endfor %} 40 | 41 | # Send the nginx version number in error pages and server headers. 42 | server_tokens {{'on' if nginx_server_tokens else 'off'}}; 43 | access_log '{{nginx_access_log_file}}' {{nginx_access_log_format}} {% if nginx_access_log_buffer %}buffer={{nginx_access_log_buffer}}{% endif %}; 44 | 45 | 46 | # Access control 47 | # -------------- 48 | 49 | {% for rule in nginx_access_control_rules %} 50 | {{rule}}; 51 | {% endfor %} 52 | 53 | {% if nginx_blocked_user_agents %} 54 | {% if nginx_blocked_user_agents is string %} 55 | if ($http_user_agent ~* {{nginx_blocked_user_agents}}) { 56 | {% else %} 57 | if ($http_user_agent ~* {{nginx_blocked_user_agents|join('|')}}) { 58 | {% endif %} 59 | return {{nginx_blocked_user_agents_status_code}}; 60 | } 61 | {% endif %} 62 | 63 | 64 | # Compression 65 | # ----------- 66 | 67 | gzip {{'on' if nginx_gzip else 'off'}}; 68 | gzip_http_version {{nginx_gzip_http_version}}; 69 | gzip_comp_level {{nginx_gzip_comp_level}}; 70 | gzip_min_length {{nginx_gzip_min_length}}; 71 | gzip_proxied {{nginx_gzip_proxied|join(' ')}}; 72 | gzip_vary {{'on' if nginx_gzip_vary else 'off'}}; 73 | gzip_types {{nginx_gzip_types|join(' ')}}; 74 | gzip_disable {{nginx_gzip_disable}}; 75 | 76 | 77 | # MIME 78 | # ---- 79 | 80 | include {{nginx_mimetype_definitions_file}}; 81 | default_type {{nginx_default_mimetype}}; 82 | 83 | 84 | # SSL 85 | # --- 86 | 87 | ssl_protocols {{nginx_ssl_protocols|join(' ')}}; 88 | ssl_ciphers {{nginx_ssl_ciphers|join(':')}}; 89 | ssl_prefer_server_ciphers {{'on' if nginx_ssl_prefer_server_ciphers else 'off'}}; 90 | ssl_session_cache {{nginx_ssl_session_cache}}; 91 | ssl_session_timeout {{nginx_ssl_session_timeout}}; 92 | 93 | 94 | # Resources and server options 95 | # ---------------------------- 96 | 97 | # Caches information about open FDs, freqently accessed files. 98 | open_file_cache max={{nginx_open_file_cache_max}} inactive={{nginx_open_file_cache_inactive}}; 99 | open_file_cache_valid {{nginx_open_file_cache_valid}}; 100 | open_file_cache_min_uses {{nginx_open_file_cache_min_uses}}; 101 | open_file_cache_errors {{'on' if nginx_open_file_cache_errors else 'off'}}; 102 | 103 | # Sendfile copies data between one FD and other 104 | # from within the kernel. More efficient than read() + write(), 105 | # since the requires transferring data to and from the user space. 106 | sendfile {{'on' if nginx_sendfile else 'off'}}; 107 | 108 | # Causes nginx to attempt to send its HTTP response head 109 | # in one packet, instead of using partial frames. 110 | # This is useful for prepending headers before calling 111 | # sendfile, or for throughput optimization. 112 | tcp_nopush {{'on' if nginx_tcp_nopush else 'off'}}; 113 | 114 | # Don't buffer data-sends (disable Nagle algorithm). 115 | # Good for sending frequent small bursts of data in real time. 116 | tcp_nodelay {{'on' if nginx_tcp_nodelay else 'off'}}; 117 | 118 | # Timeout for keep-alive connections. 119 | # Server will close connections after this time. 120 | keepalive_timeout {{nginx_keepalive_timeout}}; 121 | 122 | # Number of requests a client can make over the keep-alive connection. 123 | keepalive_requests {{nginx_keepalive_requests}}; 124 | 125 | # allow the server to close the connection after a client 126 | # stops responding. Frees up socket-associated memory. 127 | reset_timedout_connection {{'on' if nginx_reset_timedout_connection else 'off'}}; 128 | 129 | # Send the client a "request timed out" if the body 130 | # is not loaded by this time. 131 | client_body_timeout {{nginx_client_body_timeout}}; 132 | 133 | # Specifies the maximum accepted body size of a client request, as 134 | # indicated by the request header Content-Length. 135 | # 136 | # If the stated content length is greater than this size, then the 137 | # client receives the HTTP error code 413 ("Request Entity Too 138 | # Large"). It should be noted that web browsers do not usually 139 | # know how to properly display such an HTTP error. 140 | # 141 | # Set to 0 to disable. 142 | client_max_body_size {{nginx_client_max_body_size}}; 143 | 144 | # If the client stops reading data, free up the stale 145 | # client connection after this much time. 146 | send_timeout {{nginx_send_timeout}}; 147 | 148 | server_names_hash_bucket_size {{nginx_server_names_hash_bucket_size}}; 149 | types_hash_max_size {{nginx_types_hash_max_size}}; 150 | types_hash_bucket_size {{nginx_types_hash_bucket_size}}; 151 | 152 | 153 | # Include custom directives and enabled sites 154 | # ------------------------------------------- 155 | 156 | include {{nginx_additional_conf_dir}}/*.conf; 157 | include {{nginx_enabled_sites_dir}}/*; 158 | 159 | } -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Change this to pin your nginx version. 4 | # This track the stable repos, not mainline. 5 | # You can use wildcards here. 6 | nginx_version: 1.6.* 7 | 8 | nginx_user: www-data 9 | nginx_group: "{{nginx_user}}" 10 | 11 | 12 | # Locations 13 | # --------- 14 | 15 | nginx_conf_dir: /etc/nginx 16 | nginx_additional_conf_dir: "{{nginx_conf_dir}}/conf.d" 17 | nginx_log_dir: /var/log/nginx 18 | nginx_runtime_dir: /var/run 19 | nginx_available_sites_dir: "{{nginx_conf_dir}}/sites-available" 20 | nginx_enabled_sites_dir: "{{nginx_conf_dir}}/sites-enabled" 21 | 22 | nginx_create_status_site: yes 23 | nginx_create_default_site: yes 24 | nginx_default_site_name: default 25 | 26 | 27 | # SSL 28 | # --- 29 | 30 | nginx_ssl_prefer_server_ciphers: on 31 | nginx_ssl_session_cache: shared:SSL:10m 32 | nginx_ssl_session_timeout: 10m 33 | 34 | nginx_ssl_protocols: 35 | - 'TLSv1' 36 | - 'TLSv1.1' 37 | - 'TLSv1.2' 38 | 39 | nginx_ssl_ciphers: 40 | - 'EECDH+AES128' 41 | - 'RSA+AES128' 42 | - 'EECDH+AES256' 43 | - 'RSA+AES256' 44 | - 'EECDH+3DES' 45 | - 'RSA+3DES' 46 | - 'EECDH+RC4' 47 | - 'RSA+RC4' 48 | - '!MD5' 49 | 50 | 51 | # Resources 52 | # --------- 53 | 54 | nginx_default_http_port: 80 55 | nginx_default_https_port: 443 56 | 57 | nginx_pid_file: "{{nginx_runtime_dir}}/nginx.pid" 58 | 59 | # How many workers to be made available for processing requests. 60 | # If defined, this will have priority over the per-cpu setting. 61 | # nginx_workers_count: 2 62 | 63 | # Rather than specifying a predeterminate amount of workers, 64 | # you can decide on a per-core setting. 65 | nginx_workers_per_core: 1 66 | 67 | # Override OS' limit values 68 | nginx_worker_rlimit_nofile: 10000 69 | 70 | nginx_worker_connections: 1024 71 | nginx_keepalive_timeout: 65 72 | 73 | nginx_server_names_hash_bucket_size: 64 74 | nginx_types_hash_max_size: 2048 75 | nginx_types_hash_bucket_size: 64 76 | 77 | # Accept as many connections as possible, after nginx 78 | # gets notification about a new connection. 79 | # May flood worker_connections, if that option is set too low. 80 | nginx_multi_accept: yes 81 | 82 | # Caches information about open FDs, freqently accessed files. 83 | nginx_open_file_cache_max: 200000 84 | nginx_open_file_cache_inactive: 20s 85 | nginx_open_file_cache_valid: 30s 86 | nginx_open_file_cache_min_uses: 2 87 | nginx_open_file_cache_errors: yes 88 | 89 | # Sendfile copies data between one FD and other 90 | # from within the kernel. More efficient than read() + write(), 91 | # since the requires transferring data to and from the user space. 92 | nginx_sendfile: yes 93 | 94 | # Causes nginx to attempt to send its HTTP response head 95 | # in one packet, instead of using partial frames. 96 | # This is useful for prepending headers before calling 97 | # sendfile, or for throughput optimization. 98 | nginx_tcp_nopush: yes 99 | 100 | # Don't buffer data-sends (disable Nagle algorithm). 101 | # Good for sending frequent small bursts of data in real time. 102 | nginx_tcp_nodelay: yes 103 | 104 | # Timeout for keep-alive connections. 105 | # Server will close connections after this time. 106 | nginx_keepalive_timeout: 30 107 | 108 | # Number of requests a client can make over the keep-alive connection. 109 | nginx_keepalive_requests: 100 110 | 111 | # allow the server to close the connection after a client 112 | # stops responding. Frees up socket-associated memory. 113 | nginx_reset_timedout_connection: yes 114 | 115 | # Send the client a "request timed out" if the body 116 | # is not loaded by this time. Default 60. 117 | nginx_client_body_timeout: 10 118 | 119 | # Specifies the maximum accepted body size of a client request, as 120 | # indicated by the request header Content-Length. 121 | # 122 | # If the stated content length is greater than this size, then the 123 | # client receives the HTTP error code 413 ("Request Entity Too 124 | # Large"). It should be noted that web browsers do not usually 125 | # know how to properly display such an HTTP error. 126 | # 127 | # Set to 0 to disable. 128 | nginx_client_max_body_size: 1m 129 | 130 | # If the client stops reading data, free up the stale 131 | # client connection after this much time. 132 | nginx_send_timeout: 2 133 | 134 | 135 | # Mime and content-types 136 | # ---------------------- 137 | 138 | nginx_mimetype_definitions_file: "{{nginx_conf_dir}}/mime.types" 139 | nginx_default_mimetype: application/octet-stream 140 | 141 | 142 | # Compression 143 | # ----------- 144 | 145 | nginx_gzip: yes 146 | nginx_gzip_http_version: 1.0 147 | nginx_gzip_comp_level: 6 148 | nginx_gzip_min_length: 1100 149 | nginx_gzip_proxied: 150 | - expired 151 | - no-cache 152 | - no-store 153 | - private 154 | - auth 155 | nginx_gzip_vary: yes 156 | nginx_gzip_types: 157 | - text/plain 158 | - text/css 159 | - application/x-javascript 160 | - text/xml 161 | - application/xml 162 | - application/xml+rss 163 | - text/javascript 164 | - application/javascript 165 | - application/json 166 | nginx_gzip_disable: 'MSIE [1-6]\.' 167 | 168 | 169 | # Logging 170 | # ------- 171 | 172 | nginx_log_formats: 173 | main: $remote_addr - $remote_user ($time_local) $status "$request" $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" 174 | 175 | nginx_error_log_file: "{{nginx_log_dir}}/error.log" 176 | nginx_error_log_level: error 177 | 178 | nginx_access_log_file: "{{nginx_log_dir}}/access.log" 179 | nginx_access_log_format: main 180 | nginx_access_log_buffer: 16k # Buffer log writes to speed up IO 181 | 182 | 183 | 184 | # Fast CGI parameters 185 | # ------------------- 186 | 187 | nginx_fastcgi_query_string: $query_string 188 | nginx_fastcgi_request_method: $request_method 189 | nginx_fastcgi_content_type: $content_type 190 | nginx_fastcgi_content_length: $content_length 191 | nginx_fastcgi_script_filename: $request_filename 192 | nginx_fastcgi_script_name: $fastcgi_script_name 193 | nginx_fastcgi_request_uri: $request_uri 194 | nginx_fastcgi_document_uri: $document_uri 195 | nginx_fastcgi_document_root: $document_root 196 | nginx_fastcgi_server_protocol: $server_protocol 197 | nginx_fastcgi_gateway_interface: CGI/1.1 198 | nginx_fastcgi_server_software: nginx/$nginx_version 199 | nginx_fastcgi_remote_addr: $remote_addr 200 | nginx_fastcgi_remote_port: $remote_port 201 | nginx_fastcgi_server_addr: $server_addr 202 | nginx_fastcgi_server_port: $server_port 203 | nginx_fastcgi_server_name: $server_name 204 | nginx_fastcgi_https: $https 205 | nginx_fastcgi_redirect_status: 200 206 | 207 | 208 | # Access control and security 209 | # --------------------------- 210 | 211 | nginx_server_tokens: no 212 | 213 | # A list of access control rules. 214 | # Allows everything by default. Override with your rules. 215 | nginx_access_control_rules: 216 | # - deny 192.168.1.1 217 | # - allow 192.168.1.0/24 218 | # - deny all 219 | - allow all 220 | 221 | 222 | # A regex that should match user agents to be blocked. 223 | # Can also be a list, which will be joined with pipes. 224 | # Bear in mind that it will still compile as a regex. 225 | nginx_blocked_user_agents: '' 226 | nginx_blocked_user_agents_status_code: 403 227 | --------------------------------------------------------------------------------