├── .gitignore ├── README.md ├── Vagrantfile ├── ansible ├── ansible.cfg ├── demo_containers.yml ├── group_vars │ ├── vagrant_dockerhosts.yml │ ├── vagrant_dockerproxy.yml │ └── vagrant_dockerswarm.yml ├── host_vars │ ├── dockerhost01.yml │ ├── dockerhost02.yml │ └── dockerhost03.yml ├── hosts ├── roles │ ├── base │ │ └── tasks │ │ │ └── main.yml │ ├── consul_template │ │ ├── defaults │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── config.yml │ │ │ ├── main.yml │ │ │ ├── packages.yml │ │ │ └── service.yml │ │ └── vars │ │ │ └── main.yml │ ├── docker │ │ ├── defaults │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── config.yml │ │ │ ├── main.yml │ │ │ ├── packages.yml │ │ │ ├── registrator_client.yml │ │ │ ├── service.yml │ │ │ └── swarm_consul_client.yml │ │ └── templates │ │ │ ├── docker.default.j2 │ │ │ ├── registrator_upstart.conf.j2 │ │ │ └── swarm_client_upstart.conf.j2 │ ├── docker_swarm │ │ ├── defaults │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── config.yml │ │ │ ├── main.yml │ │ │ ├── packages.yml │ │ │ └── service.yml │ │ └── templates │ │ │ ├── docker_swarm_upstart.conf.j2 │ │ │ └── swarm_config.j2 │ ├── franklinkim.consul │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── Vagrantfile │ │ ├── ansible.cfg │ │ ├── defaults │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ ├── meta │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── consulate.yml │ │ │ ├── dnsmasq.yml │ │ │ ├── install-ui.yml │ │ │ ├── install.yml │ │ │ ├── main.yml │ │ │ └── service.yml │ │ ├── templates │ │ │ ├── consul-nginx.conf.j2 │ │ │ ├── consul.conf.j2 │ │ │ ├── consul.json.j2 │ │ │ ├── consul.sh.j2 │ │ │ └── consulkv.j2 │ │ └── test.yml │ ├── franklinkim.htpasswd │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── Vagrantfile │ │ ├── ansible.cfg │ │ ├── defaults │ │ │ └── main.yml │ │ ├── meta │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── install.yml │ │ │ ├── main.yml │ │ │ └── manage.yml │ │ └── test.yml │ ├── franklinkim.nginx │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── Vagrantfile │ │ ├── ansible.cfg │ │ ├── defaults │ │ │ └── main.yml │ │ ├── files │ │ │ └── etc-nginx-rules │ │ │ │ ├── cache_busting.conf │ │ │ │ ├── cors_ajax.conf │ │ │ │ ├── cors_web_fonts.conf │ │ │ │ ├── expires.conf │ │ │ │ ├── gzip.conf │ │ │ │ ├── gzip_static.conf │ │ │ │ ├── no_transform.conf │ │ │ │ ├── security.conf │ │ │ │ └── ssl.conf │ │ ├── handlers │ │ │ └── main.yml │ │ ├── meta │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── config.yml │ │ │ ├── install.yml │ │ │ ├── main.yml │ │ │ ├── manage_sites.yml │ │ │ ├── remove_default.yml │ │ │ ├── rules.yml │ │ │ └── service.yml │ │ ├── templates │ │ │ ├── etc-nginx-nginx.conf.j2 │ │ │ ├── etc-nginx-sites-available-site.j2 │ │ │ └── etc-nginx-sites-available-site │ │ │ │ ├── body.j2 │ │ │ │ └── redirect.j2 │ │ └── test.yml │ └── franklinkim.openssl │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── Vagrantfile │ │ ├── ansible.cfg │ │ ├── defaults │ │ └── main.yml │ │ ├── meta │ │ └── main.yml │ │ ├── tasks │ │ ├── config.yml │ │ ├── copy.yml │ │ ├── create.yml │ │ ├── create_dir.yml │ │ ├── install_debian.yml │ │ ├── install_redhat.yml │ │ └── main.yml │ │ ├── templates │ │ └── etc-ssl-openssl.cnf.j2 │ │ └── test.yml ├── vagrant_docker_host.yml ├── vagrant_docker_proxy.yml └── vagrant_docker_swarm.yml ├── bin ├── env ├── env_tls ├── gen_ssl.sh ├── pull_images_tls.sh └── start_containers.sh └── tls └── openssl.cnf /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | .vagrant 4 | /tls 5 | !/tls/openss.cnf 6 | /ansible/roles/docker/files/tls 7 | /ansible/roles/docker_swarm/files/tls 8 | /ansible/group_vars/all.yml 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Docker Swarm POC 2 | This repository contains a POC of Docker Swarm configured in the following 3 | manner: 4 | - 3 Docker hosts (dockerhost[01:03]) 5 | - Run latest Docker daemon 6 | - Run a Docker Swarm daemon pointed at Consul 7 | - Run a Registrator daemon pointed at Consul 8 | - 1 Docker Swarm host (dockerswarm01) 9 | - Runs Docker Swarm and listens to the Docker port 10 | - Is the primary interface for the Docker cluster 11 | - Runs Consul 12 | - Consul provides service discovery via its key/value store 13 | - Web UI available at http://dockerswarm01/ui 14 | - Swarm path of http://dockerswarm01/swarm 15 | 16 | ## Requirements 17 | There are a few requirements to get 18 | - Vagrant (latest): https://www.vagrantup.com/downloads.html 19 | - Vagrant hosts plugin: `vagrant plugin install vagrant-hosts` 20 | - VirtualBox: https://www.virtualbox.org/wiki/Downloads or VMware: http://www.vmware.com/products/fusion 21 | - Ansible: `brew install ansible` 22 | - SSHPass: `brew install https://raw.github.com/eugeneoden/homebrew/eca9de1/Library/Formula/sshpass.rb` 23 | - /etc/hosts: Allows us to call things by hostname: 24 | 25 | ``` 26 | 10.100.199.200 dockerswarm01 27 | 10.100.199.201 dockerhost01 28 | 10.100.199.202 dockerhost02 29 | 10.100.199.203 dockerhost03 30 | ``` 31 | 32 | ## How to use it 33 | Everything can be tried out using Vagrant once the pre-reqs have been installed. 34 | Just follow these simple instructions: 35 | 36 | ``` 37 | # Stand up the environment and provision the hostfile entries 38 | vagrant up 39 | 40 | # Update the `/etc/hosts` files on the VMs 41 | vagrant provision --provision-with hosts 42 | 43 | # Set your env variables to point at Vagrant 44 | source bin/env 45 | 46 | # Pull images down to the docker hosts. 47 | cd ansible/ 48 | ansible-playbook vagrant_docker_images.yml 49 | 50 | # Interact with Docker as normal 51 | docker ps 52 | docker run --rm -i -t ubuntu:latest /bin/bash 53 | ``` 54 | 55 | ### TLS 56 | TLS is functional as long as Swarm is configured to use the `file` type of 57 | discovery. After generating the certificates, set the following variables for 58 | both the `dockerhosts` and `dockerswarm` groups to run TLS: 59 | - use_tls: true 60 | - docker_port: 2376 61 | 62 | The certificates can be generated and the cluster provisioned using the 63 | following commands. **Please note:** The PKI is included in .gitignore and so 64 | will need to be regenerated each time this repo is cloned. 65 | ``` 66 | # Generate SSL 67 | ./bin/gen_ssl.sh 68 | 69 | # Provision the cluster 70 | vagrant up 71 | 72 | # Set your env to Vagrant + TLS 73 | source bin/env_tls 74 | 75 | # Pull images down to the docker hosts. 76 | ./bin/pull_images_tls.sh 77 | ansible-playbook vagrant_docker_images.yml 78 | 79 | # Interact with the cluster 80 | docker ps 81 | docker run --rm -i -t ubuntu:latest /bin/bash 82 | 83 | ``` 84 | 85 | ### Swarm configuration 86 | The Swarm daemon has a few configuration options that are available. They 87 | include: 88 | - Discovery 89 | - Scheduling 90 | - TLS (config described above) 91 | 92 | #### Swarm discovery 93 | Swarm supports multiple discovery mechanisms including: 94 | - File (supported here) 95 | - Consul (supported here) 96 | - EtcD 97 | - Zookeeper 98 | - Hosted service (Docker Hub?) 99 | 100 | **File Discovery**: Uses a static file with a list of Docker hosts. Swarm is 101 | pointed at this list and will create a cluster based on it's contents. This is 102 | the most basic discovery method and is enabled by default in this project 103 | (though currently the project is configured for Consul). 104 | The format of the list should be the following: 105 | ``` 106 | http://< hostname1 >:< port > 107 | http://< hostname2 >:< port > 108 | http://< hostname3 >:< port > 109 | http://< hostname4 >:< port > 110 | ``` 111 | 112 | **Consul Discovery**: This configuration mode is what this project is configured 113 | to use currently. It relies on Consul's key/value store being located on 114 | the Swarm host (dockerswarm01) at /swarm. In addition to maintaining the Swarm 115 | cluster, this Consul host also is the endpoint Registrator uses for service 116 | discovery under the path /services. You can view the cluster in Consul at: 117 | http://dockerswarm01/ui/#/test/kv/swarm/ 118 | 119 | #### Swarm Scheduling 120 | At this point in time, Swarm supports two scheduling modes with one in progress: 121 | - **Binpacking:** pack a machine based on a static set of resources 122 | - **Random:** Pick a host at random 123 | - **Balanced:** Pack machines evenly (In-Progress https://github.com/docker/swarm/pull/227) 124 | 125 | Swarm uses the scheduling configuration in combination with tags in the Docker 126 | daemon's startup configs to enable control over how to pack the machines. You 127 | can edit the various tags on a machine-by-machine basis by editing the host 128 | specific configs found in `ansible/host_vars/.yml` and then specifying 129 | a constraint. An example of a Docker run line for a host in the cluster would be: 130 | ``` 131 | docker --label zone=external \ 132 | --label disk=ssd \ 133 | -H tcp://0.0.0.0:2375 134 | ``` 135 | 136 | An example that will start an Nginx container on the above node through Swarm 137 | could be: 138 | ``` 139 | docker run -d \ 140 | -p 80 \ 141 | -e constraint:zone==external \ 142 | -e constraint:disk==ssd \ 143 | -t nginx:latest 144 | ``` 145 | 146 | The above configuration will start an Nginx server on a Docker host in the Swarm 147 | cluster that has been tagged with `zone=external` and `disk=ssd`. Since there 148 | are ports published, registrator will also pick this up and upsert a value into 149 | the `/services/nginx-80` key in Consul with the value of "ipaddress:port" of the 150 | running container. 151 | 152 | ## Included Projects 153 | 154 | Registrator 155 | - https://github.com/progrium/registrator 156 | 157 | Docker Swarm 158 | - https://github.com/docker/swarm 159 | 160 | Consul 161 | - https://github.com/hashicorp/consul 162 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | VAGRANTFILE_API_VERSION = "2" 2 | 3 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |vagrant| 4 | 5 | # VirtualBox Configuration 6 | vagrant.vm.provider "virtualbox" do |provider, override| 7 | override.vm.box = "vbox-trusty64-20150111.box" 8 | override.vm.box_url = 'https://s3-us-west-2.amazonaws.com/technolo-g/vagrant-boxes/ubuntu/vbox-trusty64-20150111.box' 9 | end 10 | vagrant.vm.provider "virtualbox" do |v| 11 | v.memory = 1024 12 | v.cpus = 1 13 | end 14 | 15 | # Machine Configuration 16 | # Docker Hosts 17 | (1..3).each do |i| 18 | vagrant.vm.define "dockerhost0#{i}" do |config| 19 | config.vm.hostname = "dockerhost0#{i}" 20 | config.vm.network "private_network", ip: "10.100.199.20#{i}" 21 | config.vm.provision :hosts 22 | config.vm.provision :ansible do |ansible| 23 | ansible.playbook = 'ansible/vagrant_docker_host.yml' 24 | ansible.groups = {'vagrant_dockerhosts' => ["dockerhost0#{i}"], 'local' => ['localhost']} 25 | ansible.raw_arguments = '--timeout=30' 26 | ansible.host_key_checking = false 27 | end 28 | end 29 | end 30 | 31 | # Swarm Host 32 | vagrant.vm.define "dockerswarm01" do |config| 33 | config.vm.hostname = "dockerswarm01" 34 | config.vm.network "private_network", ip: "10.100.199.200" 35 | config.vm.network "forwarded_port", guest: 2376, host: 2376 36 | config.vm.network "forwarded_port", guest: 2375, host: 2375 37 | config.vm.provision :hosts 38 | config.vm.provision :ansible do |ansible| 39 | ansible.playbook = 'ansible/vagrant_docker_swarm.yml' 40 | ansible.groups = {'vagrant_dockerswarm' => ["dockerswarm01"], 'local' => ['localhost']} 41 | ansible.raw_arguments = '--timeout=30' 42 | ansible.host_key_checking = false 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | hostfile = hosts 3 | host_key_checking = False 4 | 5 | -------------------------------------------------------------------------------- /ansible/demo_containers.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: local 4 | connection: local 5 | gather_facts: False 6 | vars: 7 | docker_host: "{{ lookup('env','DOCKER_HOST') }}" 8 | tasks: 9 | - name: Run an Nginx container 10 | docker: > 11 | docker_url={{ docker_host }} 12 | image=nginx:latest 13 | publish_all_ports=True 14 | hostname=nginx 15 | state=running 16 | count=10 17 | register: nginx_container 18 | -------------------------------------------------------------------------------- /ansible/group_vars/vagrant_dockerhosts.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | user: vagrant 4 | consul_host: dockerswarm01 5 | 6 | dns_servers: 7 | - 8.8.8.8 8 | - 8.8.4.4 9 | 10 | docker_images: 11 | - ubuntu 12 | - nginx 13 | 14 | -------------------------------------------------------------------------------- /ansible/group_vars/vagrant_dockerproxy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | user: vagrant 4 | -------------------------------------------------------------------------------- /ansible/group_vars/vagrant_dockerswarm.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | user: vagrant 4 | start_docker_service: False 5 | packing_strategy: random 6 | consul_host: dockerswarm01 7 | 8 | cluster_nodes: 9 | - dockerhost01 10 | - dockerhost02 11 | - dockerhost03 12 | -------------------------------------------------------------------------------- /ansible/host_vars/dockerhost01.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | docker_swarm_tags: 4 | - 'status=master' 5 | - 'disk=ssd' 6 | - 'zone=internal' 7 | -------------------------------------------------------------------------------- /ansible/host_vars/dockerhost02.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | docker_swarm_tags: 4 | - 'status=non-master' 5 | - 'disk=ssd' 6 | - 'zone=external' 7 | -------------------------------------------------------------------------------- /ansible/host_vars/dockerhost03.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | docker_swarm_tags: 4 | - 'status=master' 5 | - 'disk=ssd' 6 | - 'zone=external' 7 | -------------------------------------------------------------------------------- /ansible/hosts: -------------------------------------------------------------------------------- 1 | [local] 2 | localhost 3 | 4 | [vagrant_dockerhosts] 5 | dockerhost01 ansible_ssh_private_key_file=../.vagrant/machines/dockerhost01/virtualbox/private_key 6 | dockerhost02 ansible_ssh_private_key_file=../.vagrant/machines/dockerhost02/virtualbox/private_key 7 | dockerhost03 ansible_ssh_private_key_file=../.vagrant/machines/dockerhost03/virtualbox/private_key 8 | 9 | [vagrant_dockerswarm] 10 | dockerswarm01 ansible_ssh_private_key_file=../.vagrant/machines/dockerswarm01/virtualbox/private_key 11 | 12 | -------------------------------------------------------------------------------- /ansible/roles/base/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: update apt 4 | sudo: true 5 | apt: update_cache=yes cache_valid_time=3600 6 | -------------------------------------------------------------------------------- /ansible/roles/consul_template/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for consul_template 3 | -------------------------------------------------------------------------------- /ansible/roles/consul_template/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for consul_template 3 | -------------------------------------------------------------------------------- /ansible/roles/consul_template/tasks/config.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technolo-g/docker-swarm-demo/443e83a4d4a71cac6517932e3588132db0d9a053/ansible/roles/consul_template/tasks/config.yml -------------------------------------------------------------------------------- /ansible/roles/consul_template/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: packages.yml 4 | 5 | #- include: config.yml 6 | 7 | #- include: service.yml 8 | -------------------------------------------------------------------------------- /ansible/roles/consul_template/tasks/packages.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Install the consul-template binary 4 | sudo: True 5 | get_url: > 6 | url=https://s3-us-west-2.amazonaws.com/technolo-g/bins/ubuntu/trusty/consul-template 7 | dest=/usr/local/bin/consul-template 8 | mode=0775 9 | -------------------------------------------------------------------------------- /ansible/roles/consul_template/tasks/service.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technolo-g/docker-swarm-demo/443e83a4d4a71cac6517932e3588132db0d9a053/ansible/roles/consul_template/tasks/service.yml -------------------------------------------------------------------------------- /ansible/roles/consul_template/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for consul_template 3 | -------------------------------------------------------------------------------- /ansible/roles/docker/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | start_docker_service: True 4 | use_tls: False 5 | docker_port: 2375 6 | docker_swarm_tags: 7 | - 'none=none' -------------------------------------------------------------------------------- /ansible/roles/docker/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: restart docker 4 | sudo: true 5 | service: > 6 | name=docker 7 | state=restarted 8 | 9 | - name: restart swarm client 10 | sudo: true 11 | service: > 12 | name=swarm_client 13 | state=restarted 14 | 15 | - name: restart registrator 16 | sudo: true 17 | service: > 18 | name=registrator 19 | state=restarted 20 | -------------------------------------------------------------------------------- /ansible/roles/docker/tasks/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Install /etc/default/docker 4 | sudo: True 5 | template: > 6 | src=docker.default.j2 7 | dest=/etc/default/docker 8 | owner=root 9 | group=root 10 | mode=0644 11 | notify: 12 | - restart docker 13 | when: start_docker_service == True 14 | 15 | - name: Install SSL Certs 16 | sudo: True 17 | copy: > 18 | src=tls 19 | dest=/etc/pki 20 | owner=root 21 | group=root 22 | mode=0600 23 | notify: 24 | - restart docker 25 | when: use_tls == True 26 | -------------------------------------------------------------------------------- /ansible/roles/docker/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: packages.yml 4 | 5 | - include: config.yml 6 | 7 | - include: service.yml 8 | 9 | - { include: swarm_consul_client.yml, when: swarm_discovery is defined and swarm_discovery == 'consul' } 10 | 11 | - { include: registrator_client.yml, when: swarm_discovery is defined and swarm_discovery == 'consul' } 12 | -------------------------------------------------------------------------------- /ansible/roles/docker/tasks/packages.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Install apt key 4 | sudo: true 5 | apt_key: > 6 | id=36A1D7869245C8950F966E92D8576A8BA88D21E9 7 | keyserver=hkp://keyserver.ubuntu.com:80 8 | state=present 9 | 10 | - name: Install Docker repo 11 | sudo: true 12 | apt_repository: > 13 | repo='deb https://get.docker.io/ubuntu docker main' 14 | state=present 15 | 16 | - name: Update apt to get Docker 17 | sudo: true 18 | apt: > 19 | update_cache=yes 20 | cache_valid_time=3600 21 | 22 | - name: Install Docker package 23 | sudo: true 24 | apt: > 25 | name=lxc-docker 26 | state=present 27 | -------------------------------------------------------------------------------- /ansible/roles/docker/tasks/registrator_client.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Install the Registrator binary 4 | sudo: true 5 | get_url: > 6 | url=https://s3-us-west-2.amazonaws.com/technolo-g/bins/ubuntu/trusty/registrator 7 | dest=/usr/local/bin/registrator 8 | mode=0775 9 | 10 | - name: Install the registrator upstart job 11 | sudo: true 12 | template: > 13 | src=registrator_upstart.conf.j2 14 | dest=/etc/init/registrator.conf 15 | owner=root 16 | group=root 17 | mode=0644 18 | notify: restart registrator 19 | when: start_docker_service == true 20 | 21 | - name: Start and enable registrator 22 | sudo: true 23 | service: > 24 | name=registrator 25 | state=started 26 | enabled=true 27 | when: start_docker_service == true 28 | -------------------------------------------------------------------------------- /ansible/roles/docker/tasks/service.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Start Docker 4 | sudo: true 5 | service: > 6 | name=docker 7 | state=started 8 | enabled=true 9 | when: start_docker_service == True 10 | 11 | - name: Disable Docker 12 | sudo: true 13 | service: > 14 | name=docker 15 | state=stopped 16 | enabled=false 17 | when: start_docker_service == False 18 | -------------------------------------------------------------------------------- /ansible/roles/docker/tasks/swarm_consul_client.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Install the Swarm binary 4 | sudo: true 5 | get_url: > 6 | url=https://s3-us-west-2.amazonaws.com/technolo-g/bins/ubuntu/trusty/swarm 7 | dest=/usr/local/bin/swarm 8 | mode=0775 9 | 10 | - name: Ship the upstart config 11 | sudo: True 12 | template: > 13 | src=swarm_client_upstart.conf.j2 14 | dest=/etc/init/swarm_client.conf 15 | owner=root 16 | group=root 17 | mode=0644 18 | notify: 19 | - restart swarm client 20 | when: start_docker_service 21 | 22 | - name: Start and enable Swarm 23 | sudo: True 24 | service: > 25 | name=swarm_client 26 | state=started 27 | enabled=true 28 | when: start_docker_service 29 | -------------------------------------------------------------------------------- /ansible/roles/docker/templates/docker.default.j2: -------------------------------------------------------------------------------- 1 | # Managed by Ansible 2 | # Docker Upstart and SysVinit configuration file 3 | 4 | # Use DOCKER_OPTS to modify the daemon startup options. 5 | DOCKER_OPTS="{% if dns_servers is defined %}{% for server in dns_servers %}--dns={{ server }} {% endfor %} {% endif %} \ 6 | {% for tag in docker_swarm_tags %} --label {{ tag }}{% endfor %} \ 7 | {% if use_tls %} 8 | --tlsverify \ 9 | --tlscacert=/etc/pki/tls/ca.pem \ 10 | --tlscert=/etc/pki/tls/{{ ansible_hostname }}-cert.pem \ 11 | --tlskey=/etc/pki/tls/{{ ansible_hostname }}-key.pem \ 12 | {% endif %} 13 | {% if docker_opts is defined %}{% for opt in docker_opts %} 14 | {{ opt }} \ 15 | {% endfor %}{% endif %} 16 | -H unix:///var/run/docker.sock \ 17 | -H tcp://0.0.0.0:{{ docker_port }}" 18 | -------------------------------------------------------------------------------- /ansible/roles/docker/templates/registrator_upstart.conf.j2: -------------------------------------------------------------------------------- 1 | description "Registrator" 2 | author "Matt" 3 | console log 4 | start on network 5 | stop on runlevel [!2345] 6 | post-stop exec sleep 10 7 | script 8 | /usr/local/bin/registrator \ 9 | -ip={{ ansible_eth1['ipv4']['address'] }} \ 10 | consul://{{ consul_host }}/services 11 | end script 12 | respawn 13 | -------------------------------------------------------------------------------- /ansible/roles/docker/templates/swarm_client_upstart.conf.j2: -------------------------------------------------------------------------------- 1 | description "Docker Swarm Client" 2 | author "Matt" 3 | console log 4 | start on network 5 | stop on runlevel [!2345] 6 | post-stop exec sleep 10 7 | script 8 | /usr/local/bin/swarm join \ 9 | --addr={{ ansible_eth1['ipv4']['address'] }}:{{ docker_port }} \ 10 | {{ swarm_discovery_string }} \ 11 | end script 12 | respawn 13 | -------------------------------------------------------------------------------- /ansible/roles/docker_swarm/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | use_tls: false 4 | packing_strategy: random 5 | docker_port: 2375 6 | swarm_discovery: file 7 | swarm_discovery_string: 'file:///etc/swarm_config' 8 | -------------------------------------------------------------------------------- /ansible/roles/docker_swarm/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: restart swarm 4 | sudo: true 5 | service: > 6 | name=docker_swarm 7 | state=restarted -------------------------------------------------------------------------------- /ansible/roles/docker_swarm/tasks/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Ship the swarm config 4 | sudo: True 5 | template: > 6 | src=swarm_config.j2 7 | dest=/etc/swarm_config 8 | owner=root 9 | group=root 10 | mode=0644 11 | notify: 12 | - restart swarm 13 | when: swarm_discovery == 'file' 14 | 15 | - name: Install SSL Certs 16 | sudo: True 17 | copy: > 18 | src=tls 19 | dest=/etc/pki 20 | owner=root 21 | group=root 22 | mode=0600 23 | notify: 24 | - restart swarm 25 | when: use_tls 26 | -------------------------------------------------------------------------------- /ansible/roles/docker_swarm/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: packages.yml 4 | 5 | - include: config.yml 6 | 7 | - include: service.yml 8 | -------------------------------------------------------------------------------- /ansible/roles/docker_swarm/tasks/packages.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Install the Swarm binary 4 | sudo: True 5 | get_url: > 6 | url=https://s3-us-west-2.amazonaws.com/technolo-g/bins/ubuntu/trusty/swarm 7 | dest=/usr/local/bin/swarm 8 | mode=0775 9 | -------------------------------------------------------------------------------- /ansible/roles/docker_swarm/tasks/service.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Ship the upstart config 4 | sudo: True 5 | template: > 6 | src=docker_swarm_upstart.conf.j2 7 | dest=/etc/init/docker_swarm.conf 8 | owner=root 9 | group=root 10 | mode=0644 11 | notify: 12 | - restart swarm 13 | 14 | - name: Start and enable Swarm 15 | sudo: True 16 | service: > 17 | name=docker_swarm 18 | state=started 19 | enabled=true 20 | -------------------------------------------------------------------------------- /ansible/roles/docker_swarm/templates/docker_swarm_upstart.conf.j2: -------------------------------------------------------------------------------- 1 | description "Docker Swarm Master" 2 | author "Matt" 3 | console log 4 | start on filesystem 5 | stop on runlevel [!2345] 6 | script 7 | /usr/local/bin/swarm manage \ 8 | {% if use_tls %} 9 | --tlsverify \ 10 | --tlscacert=/etc/pki/tls/ca.pem \ 11 | --tlscert=/etc/pki/tls/swarm-cert.pem \ 12 | --tlskey=/etc/pki/tls/swarm-key.pem \ 13 | {% endif %} 14 | -H tcp://0.0.0.0:{{ docker_port }} \ 15 | --strategy {{ packing_strategy }} \ 16 | {{ swarm_discovery_string }} 17 | end script 18 | 19 | -------------------------------------------------------------------------------- /ansible/roles/docker_swarm/templates/swarm_config.j2: -------------------------------------------------------------------------------- 1 | {% for node in cluster_nodes %} 2 | http{% if use_tls %}s{% endif %}://{{ node }}:{{ docker_port }} 3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | bin/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # Installer logs 26 | pip-log.txt 27 | pip-delete-this-directory.txt 28 | 29 | # Unit test / coverage reports 30 | htmlcov/ 31 | .tox/ 32 | .coverage 33 | .cache 34 | nosetests.xml 35 | coverage.xml 36 | 37 | # Translations 38 | *.mo 39 | 40 | # Mr Developer 41 | .mr.developer.cfg 42 | .project 43 | .pydevproject 44 | 45 | # Rope 46 | .ropeproject 47 | 48 | # Django stuff: 49 | *.log 50 | *.pot 51 | 52 | # Sphinx documentation 53 | docs/_build/ 54 | 55 | # Vagrant 56 | .vagrant 57 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Consul Role 2 | 3 | > `consul` is an [ansible](http://www.ansible.com) role which: 4 | > 5 | > * installs consul 6 | > * configures consul 7 | > * installs consul ui 8 | > * configures consul ui 9 | > * optionally installs dnsmasq 10 | > * optionally install consulate 11 | > * configures consul service(s) 12 | 13 | ## Installation 14 | 15 | Using `ansible-galaxy`: 16 | 17 | ``` 18 | $ ansible-galaxy install savagegus.consul 19 | ``` 20 | 21 | Using `arm` ([Ansible Role Manager](https://github.com/mirskytech/ansible-role-manager/)): 22 | 23 | ``` 24 | $ arm install savagegus.ansible-consul 25 | ``` 26 | 27 | Using `git`: 28 | 29 | ``` 30 | $ git clone https://github.com/jivesoftware/ansible-consul.git 31 | ``` 32 | 33 | ## Variables 34 | 35 | Here is a list of all the default variables for this role, which are also available in `defaults/main.yml`. 36 | 37 | ``` 38 | # default version and download locations 39 | consul_version: 0.3.1 40 | consul_archive: "{{ consul_version }}_linux_amd64.zip" 41 | consul_ui_archive: "{{ consul_version }}_web_ui.zip" 42 | consul_download: "https://dl.bintray.com/mitchellh/consul/{{ consul_archive }}" 43 | consul_ui_download: "https://dl.bintray.com/mitchellh/consul/{{ consul_ui_archive }}" 44 | # default directories 45 | consul_download_folder: /tmp 46 | consul_home: /opt/consul 47 | consul_config_dir: /etc/consul.d 48 | consul_config_file: /etc/consul.conf 49 | consul_log_file: /var/log/consul 50 | consul_data_dir: "{{ consul_home }}/data" 51 | consul_ui_dir: "{{ consul_home }}/dist" 52 | consul_binary: consul 53 | # default settings 54 | consul_user: consul 55 | consul_group: consul 56 | # configure consul as a server 57 | consul_is_server: "false" 58 | # configure consul as a ui 59 | consul_is_ui: "false" 60 | # configure consul to start in bootstrap mode 61 | consul_bootstrap: "false" 62 | consul_bootstrap_expect: 3 63 | # configure service 64 | consul_servers: ['127.0.0.1'] 65 | consul_log_level: "INFO" 66 | consul_rejoin_after_leave: "true" 67 | ``` 68 | 69 | An instance might be defined through: 70 | 71 | ``` 72 | # enable ui 73 | consul_is_ui: "true" 74 | # start as a server 75 | consul_is_server: "true" 76 | # name datacenter 77 | consul_datacenter: "test" 78 | # bootstrap 79 | consul_bootstrap: "true" 80 | # name the node 81 | consul_node_name: "vagrant" 82 | # bind to ip 83 | consul_bind_address: "{{ ansible_default_ipv4['address'] }}" 84 | ``` 85 | 86 | ## Handlers 87 | 88 | These are the handlers that are defined in `handlers/main.yml`. 89 | 90 | * `restart consul` 91 | * `restart dnsmasq` 92 | 93 | ## Example playbook 94 | 95 | ``` 96 | --- 97 | 98 | - hosts: all 99 | roles: 100 | - ansible-consul 101 | vars: 102 | consul_is_ui: "true" 103 | consul_is_server: "true" 104 | consul_datacenter: "test" 105 | consul_bootstrap: "true" 106 | consul_node_name: "vagrant" 107 | consul_bind_address: "{{ ansible_default_ipv4['address'] }}" 108 | ``` 109 | 110 | ## Testing 111 | 112 | ``` 113 | $ git clone https://github.com/jivesoftware/ansible-consul.git 114 | $ cd ansible-consul 115 | $ vagrant up 116 | ``` 117 | 118 | ## Contributing 119 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests and examples for any new or changed functionality. 120 | 121 | 1. Fork it 122 | 2. Create your feature branch (`git checkout -b my-new-feature`) 123 | 3. Commit your changes (`git commit -am 'Add some feature'`) 124 | 4. Push to the branch (`git push origin my-new-feature`) 125 | 5. Create new Pull Request 126 | 127 | ## License 128 | Copyright (c) Jive Software under the Apache license. 129 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure("2") do |config| 5 | config.vm.network :private_network, ip: "192.168.33.99" 6 | config.vm.network :forwarded_port, guest: 22, host: 2299 7 | 8 | config.vm.define 'ubuntu1404-amd64' do |instance| 9 | 10 | # Every Vagrant virtual environment requires a box to build off of. 11 | instance.vm.box = 'ubuntu1404-amd64' 12 | 13 | # The url from where the 'config.vm.box' box will be fetched if it 14 | # doesn't already exist on the user's system. 15 | instance.vm.box_url = 'https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box' 16 | 17 | # View the documentation for the provider you're using for more 18 | # information on available options. 19 | config.vm.provision "ansible" do |ansible| 20 | ansible.playbook = "test.yml" 21 | ansible.verbose = 'vv' 22 | ansible.sudo = true 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | roles_path = /etc/ansible/roles/:../ 3 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | consul_version: 0.4.1 3 | consul_archive: "consul_{{ consul_version }}_linux_amd64.zip" 4 | consul_ui_archive: "consul_{{ consul_version }}_web_ui.zip" 5 | consul_download: "https://releases.hashicorp.com/consul/{{ consul_version }}/{{ consul_archive }}" 6 | consul_ui_download: "https://releases.hashicorp.com/consul/{{ consul_version }}/{{ consul_ui_archive }}" 7 | consul_download_folder: /tmp 8 | consul_home: /opt/consul 9 | consul_config_dir: /etc/consul.d 10 | consul_config_file: /etc/consul.conf 11 | consul_log_file: /var/log/consul 12 | consul_data_dir: "{{ consul_home }}/data" 13 | consul_ui_dir: "{{ consul_home }}/dist" 14 | consul_binary: consul 15 | consul_user: consul 16 | consul_group: consul 17 | consul_domain: consul. 18 | consul_is_server: false 19 | consul_is_ui: false 20 | consul_servers: ['127.0.0.1'] 21 | consul_log_level: "INFO" 22 | consul_syslog: false 23 | consul_rejoin_after_leave: true 24 | consul_bind_address: "0.0.0.0" 25 | consul_client_address: "127.0.0.1" 26 | consul_node_name: "{{ ansible_default_ipv4['address'] }}" 27 | consul_datacenter: "default" 28 | consul_ui_require_auth: false 29 | consul_ui_auth_user_file: /etc/htpasswd/consul 30 | consul_enable_nginx_config: true 31 | consul_disable_remote_exec: true 32 | consul_install_dnsmasq: true 33 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart consul 3 | action: service name=consul state=restarted 4 | - name: restart dnsmasq 5 | service: name=dnsmasq state=restarted enabled=yes -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Matthew Finlayson 4 | description: Installs and configures consul 5 | company: Jive Software 6 | platforms: 7 | - name: Ubuntu 8 | versions: 9 | - All 10 | categories: 11 | - system 12 | dependencies: 13 | - { role: franklinkim.nginx, when: consul_is_ui == true } 14 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/tasks/consulate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: update apt 3 | apt: > 4 | update_cache=yes 5 | cache_valid_time=3600 6 | 7 | - name: install deps 8 | apt: > 9 | pkg={{item}} 10 | state=installed 11 | with_items: 12 | - python-pip 13 | - python-dev 14 | 15 | - name: install python module consulate 16 | pip: > 17 | name={{item}} 18 | with_items: 19 | - tornado 20 | - consulate 21 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/tasks/dnsmasq.yml: -------------------------------------------------------------------------------- 1 | - name: update apt 2 | apt: > 3 | update_cache=yes 4 | cache_valid_time=3600 5 | 6 | - name: install deps 7 | apt: > 8 | pkg=dnsmasq 9 | state=installed 10 | 11 | - name: configure dnsmasq 12 | copy: > 13 | content='server=/{{ consul_domain }}/127.0.0.1#8600' 14 | dest=/etc/dnsmasq.d/10-consul 15 | notify: 16 | - restart dnsmasq 17 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/tasks/install-ui.yml: -------------------------------------------------------------------------------- 1 | - name: download consul 2 | get_url: > 3 | url={{consul_ui_download}} 4 | dest={{consul_download_folder}} 5 | register: consul_ui_was_downloaded 6 | 7 | - name: copy and unpack 8 | unarchive: > 9 | src={{ consul_download_folder }}/{{ consul_ui_archive }} 10 | dest={{ consul_home }} 11 | copy=no 12 | when: consul_ui_was_downloaded|changed 13 | 14 | - name: set ownership 15 | file: > 16 | state=directory 17 | path={{consul_ui_dir}} 18 | owner={{consul_user}} 19 | group={{consul_group}} 20 | recurse=yes 21 | when: consul_ui_was_downloaded|changed 22 | 23 | - name: consul nginx config 24 | template: > 25 | src=consul-nginx.conf.j2 26 | dest=/etc/nginx/sites-available/consul 27 | owner=root 28 | group=root 29 | mode=0755 30 | when: consul_is_ui 31 | notify: 32 | - restart nginx 33 | 34 | - name: consul nginx config 35 | file: > 36 | state=link 37 | src=/etc/nginx/sites-available/consul 38 | path=/etc/nginx/sites-enabled/consul 39 | owner=root 40 | group=root 41 | mode=0755 42 | when: consul_is_ui and consul_enable_nginx_config 43 | notify: 44 | - restart nginx 45 | 46 | - name: create nginx home 47 | file: > 48 | state=directory 49 | path=/var/www/consul/htdocs 50 | owner=root 51 | group=root 52 | mode=0755 53 | notify: 54 | - restart nginx 55 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/tasks/install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: update apt 3 | apt: > 4 | update_cache=yes 5 | cache_valid_time=3600 6 | 7 | - name: install deps 8 | apt: > 9 | pkg={{item}} 10 | state=installed 11 | with_items: 12 | - unzip 13 | - jq 14 | 15 | - name: download consul 16 | get_url: > 17 | url={{consul_download}} 18 | dest={{consul_download_folder}} 19 | register: consul_was_downloaded 20 | 21 | - name: create consul directory 22 | file: > 23 | state=directory 24 | path={{ item }} 25 | with_items: 26 | - "{{ consul_home }}" 27 | - "{{ consul_home }}/bin" 28 | - "{{ consul_data_dir }}" 29 | - "{{ consul_config_dir }}" 30 | 31 | - name: copy and unpack 32 | unarchive: > 33 | src={{ consul_download_folder }}/{{ consul_archive }} 34 | dest={{ consul_home }}/bin 35 | copy=no 36 | when: consul_was_downloaded|changed 37 | 38 | - name: create consul group 39 | group: > 40 | name={{consul_group}} 41 | state=present 42 | 43 | - name: create consul user 44 | user: > 45 | name={{consul_user}} 46 | group={{consul_group}} 47 | 48 | - name: set ownership 49 | file: > 50 | state=directory 51 | path={{consul_home}} 52 | owner={{consul_user}} 53 | group={{consul_group}} 54 | recurse=yes 55 | when: consul_was_downloaded|changed 56 | 57 | - name: copy consul upstart script 58 | template: > 59 | src=consul.conf.j2 60 | dest=/etc/init/consul.conf 61 | owner={{consul_user}} 62 | group={{consul_group}} 63 | mode=0755 64 | 65 | - name: add consul to path through profile.d 66 | template: > 67 | src=consul.sh.j2 68 | dest=/etc/profile.d/consul.sh 69 | owner=root 70 | group=root 71 | mode=0755 72 | 73 | - name: copy consulkv script 74 | template: > 75 | src=consulkv.j2 76 | dest={{consul_home}}/bin/consulkv 77 | owner={{consul_user}} 78 | group={{consul_group}} 79 | mode=0755 80 | 81 | - name: consul config file 82 | template: > 83 | src=consul.json.j2 84 | dest={{ consul_config_file }} 85 | owner={{consul_user}} 86 | group={{consul_group}} 87 | mode=0755 88 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: install.yml 3 | - { include: install-ui.yml, when: consul_is_ui == true } 4 | - { include: dnsmasq.yml, when: consul_install_dnsmasq == true } 5 | - include: consulate.yml 6 | - include: service.yml 7 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/tasks/service.yml: -------------------------------------------------------------------------------- 1 | - service: > 2 | name=consul 3 | state=running 4 | enabled=yes -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/templates/consul-nginx.conf.j2: -------------------------------------------------------------------------------- 1 | server { 2 | server_name consul.local; 3 | root /var/www/consul/htdocs; 4 | 5 | # --- listen ---------------------------------------------------------------- 6 | 7 | listen *:80; 8 | 9 | 10 | # --- rule ------------------------------------------------------------------ 11 | include rules/gzip.conf; 12 | include rules/security.conf; 13 | 14 | 15 | # --- locations ------------------------------------------------------------- 16 | 17 | 18 | location / { 19 | proxy_pass http://127.0.0.1:8500; 20 | {%- if consul_ui_require_auth -%} 21 | auth_basic "Restricted"; 22 | auth_basic_user_file {{ consul_ui_auth_user_file }}; 23 | {% endif %} 24 | } 25 | 26 | 27 | 28 | # --- logging --------------------------------------------------------------- 29 | 30 | error_log /var/log/nginx/error-consul.log; 31 | access_log /var/log/nginx/access-consul.log; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/templates/consul.conf.j2: -------------------------------------------------------------------------------- 1 | # Consul Agent (Upstart unit) 2 | description "Consul Agent" 3 | start on (local-filesystems and net-device-up IFACE!=lo) 4 | stop on runlevel [06] 5 | 6 | exec sudo -u {{ consul_user }} -g {{ consul_group }} {{ consul_home }}/bin/consul agent -config-dir {{ consul_config_dir }} -config-file={{ consul_config_file }} >> {{ consul_log_file }} 2>&1 7 | respawn 8 | respawn limit 10 10 9 | kill timeout 10 -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/templates/consul.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | {% if consul_is_ui == true %} 3 | "ui_dir": "{{ consul_home }}/dist", 4 | {% endif %} 5 | {% if consul_join_at_start is defined and consul_join_at_start %} 6 | "start_join": {{ consul_servers|to_nice_json }}, 7 | {% endif %} 8 | {% if consul_disable_remote_exec is defined and consul_disable_remote_exec %} 9 | "disable_remote_exec": {{ "true" if consul_disable_remote_exec else "false" }}, 10 | {% endif %} 11 | "domain": "{{ consul_domain }}", 12 | "data_dir": "{{ consul_data_dir }}", 13 | "log_level": "{{ consul_log_level }}", 14 | {% if consul_syslog %} 15 | "enable_syslog": true, 16 | {% endif %} 17 | "node_name": "{{ consul_node_name }}", 18 | "server": {{ "true" if consul_is_server else "false" }}, 19 | "client_addr": "{{ consul_client_address }}", 20 | "bind_addr": "{{ consul_bind_address }}", 21 | {% if consul_advertise_address is defined %} 22 | "advertise_addr": "{{ consul_advertise_address }}", 23 | {% endif %} 24 | "datacenter": "{{ consul_datacenter }}", 25 | {% if consul_is_server and consul_bootstrap is defined %} 26 | "bootstrap": {{ "true" if consul_bootstrap else "false" }}, 27 | {% endif %} 28 | {% if consul_is_server and consul_bootstrap_expect is defined %} 29 | "bootstrap_expect": {{ consul_bootstrap_expect }}, 30 | {% endif %} 31 | {% if consul_encrypt_key is defined %} 32 | "encrypt": "{{ consul_encrypt_key }}", 33 | {% endif %} 34 | {% if consul_watches is defined %} 35 | "watches": {{ consul_watches|to_nice_json }}, 36 | {% endif %} 37 | "rejoin_after_leave": {{ "true" if consul_rejoin_after_leave else "false" }} 38 | } 39 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/templates/consul.sh.j2: -------------------------------------------------------------------------------- 1 | export PATH={{ consul_home }}/bin:${PATH} 2 | export CONSUL_HOME={{ consul_home }} -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/templates/consulkv.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # From: https://gist.github.com/progrium/b45a9fe697dd68c3ea0f 3 | 4 | CONSUL="http://127.0.0.1:8500" 5 | 6 | main() { 7 | case "$1" in 8 | info) 9 | curl -s "$CONSUL/v1/kv/$2" | jq -r .[] 10 | ;; 11 | get) 12 | curl -s "$CONSUL/v1/kv/$2" | jq -r .[].Value | base64 -d | sed 's/$/\n/' 13 | ;; 14 | set) 15 | curl -s -X PUT -d "$3" "$CONSUL/v1/kv/$2" > /dev/null 16 | ;; 17 | del) 18 | curl -s -X DELETE -d "$3" "$CONSUL/v1/kv/$2" > /dev/null 19 | ;; 20 | ls) 21 | if [[ "$2" == "" ]]; then 22 | curl -s "$CONSUL/v1/kv/?keys" | jq -r .[] 23 | else 24 | curl -s "$CONSUL/v1/kv/$2/?keys" | jq -r .[] | sed "s|$2/||" 25 | fi 26 | ;; 27 | esac 28 | } 29 | 30 | main "$@" -------------------------------------------------------------------------------- /ansible/roles/franklinkim.consul/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | roles: 5 | - ansible-consul 6 | vars: 7 | consul_is_ui: true 8 | consul_is_server: true 9 | consul_datacenter: "test" 10 | consul_bootstrap: true 11 | consul_node_name: "vagrant" 12 | nginx_remove_default: yes 13 | htpasswd: 14 | - name: admin 15 | users: 16 | - { name: admin, password: admin } 17 | nginx_sites: 18 | - id: consul 19 | add_webroot: no 20 | name: consul.local 21 | rules: 22 | - gzip 23 | - security 24 | auth: 25 | name: Consul 26 | file: admin 27 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *~ 3 | !.git* 4 | !.travis.yml 5 | vagrant_* 6 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | language: python 4 | python: "2.7" 5 | before_install: 6 | - sudo apt-get update -qq 7 | - sudo apt-get install -qq python-apt python-pycurl 8 | install: 9 | - pip install ansible 10 | script: 11 | - echo localhost > inventory 12 | - ln -s ansible-htpasswd ../franklinkim.htpasswd 13 | - ansible-playbook --syntax-check -i inventory test.yml 14 | - ansible-playbook -i inventory test.yml --connection=local --sudo -vvvv 15 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) We Are Interactive 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Htpasswd Role 2 | 3 | [![Build Status](https://travis-ci.org/weareinteractive/ansible-htpasswd.png?branch=master)](https://travis-ci.org/weareinteractive/ansible-htpasswd) 4 | [![Stories in Ready](https://badge.waffle.io/weareinteractive/ansible-htpasswd.svg?label=ready&title=Ready)](http://waffle.io/weareinteractive/ansible-htpasswd) 5 | 6 | > `htpasswd` is an [ansible](http://www.ansible.com) role which: 7 | > 8 | > * installs `htpasswd` 9 | > * manages `htpasswd` files 10 | 11 | ## Installation 12 | 13 | Using `ansible-galaxy`: 14 | 15 | ``` 16 | $ ansible-galaxy install franklinkim.htpasswd 17 | ``` 18 | 19 | Using `arm` ([Ansible Role Manager](https://github.com/mirskytech/ansible-role-manager/)): 20 | 21 | ``` 22 | $ arm install franklinkim.htpasswd 23 | ``` 24 | 25 | Using `git`: 26 | 27 | ``` 28 | $ git clone https://github.com/weareinteractive/ansible-htpasswd.git 29 | ``` 30 | 31 | ## Variables 32 | 33 | Here is a list of all the default variables for this role, which are also available in `defaults/main.yml`. 34 | 35 | ``` 36 | # htpasswd: 37 | # - name: myapp 38 | # users: 39 | # - { name: user1, password: secret1 } 40 | # - { name: user1, password: secret2, crypt: [apr_md5_crypt | des_crypt | ldap_sha1 | plaintext] } 41 | 42 | # list of entries 43 | htpasswd: [] 44 | ``` 45 | 46 | ## Example playbook 47 | 48 | ``` 49 | - host: all 50 | roles: 51 | - franklinkim.htpasswd 52 | vars: 53 | htpasswd: 54 | - name: myapp 55 | users: 56 | - { name: user, password: secret } 57 | ``` 58 | 59 | ## Testing 60 | 61 | ``` 62 | $ git clone https://github.com/weareinteractive/ansible-htpasswd.git 63 | $ cd ansible-htpasswd 64 | $ vagrant up 65 | ``` 66 | 67 | ## Contributing 68 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests and examples for any new or changed functionality. 69 | 70 | 1. Fork it 71 | 2. Create your feature branch (`git checkout -b my-new-feature`) 72 | 3. Commit your changes (`git commit -am 'Add some feature'`) 73 | 4. Push to the branch (`git push origin my-new-feature`) 74 | 5. Create new Pull Request 75 | 76 | ## License 77 | Copyright (c) We Are Interactive under the MIT license. 78 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure("2") do |config| 5 | config.vm.network :private_network, ip: "192.168.33.99" 6 | config.vm.network :forwarded_port, guest: 22, host: 2299 7 | 8 | config.vm.define 'ubuntu1404-amd64' do |instance| 9 | 10 | # Every Vagrant virtual environment requires a box to build off of. 11 | instance.vm.box = 'ubuntu1404-amd64' 12 | 13 | # The url from where the 'config.vm.box' box will be fetched if it 14 | # doesn't already exist on the user's system. 15 | instance.vm.box_url = 'https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box' 16 | 17 | # View the documentation for the provider you're using for more 18 | # information on available options. 19 | config.vm.provision "ansible" do |ansible| 20 | ansible.playbook = "test.yml" 21 | ansible.verbose = 'vv' 22 | ansible.sudo = true 23 | end 24 | end 25 | end -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | roles_path = ../ -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # For more information about default variables see: 3 | # http://www.ansibleworks.com/docs/playbooks_variables.html#id26 4 | # 5 | # htpasswd: 6 | # - name: myapp 7 | # users: 8 | # - { name: user1, password: secret1 } 9 | # - { name: user1, password: secret2, crypt: [apr_md5_crypt | des_crypt | ldap_sha1 | plaintext] } 10 | 11 | # list of entries 12 | htpasswd: [] 13 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: franklin 4 | company: We Are Interactive 5 | description: Installs htpasswd and creates auth files 6 | min_ansible_version: 1.6 7 | license: MIT 8 | platforms: 9 | - name: Ubuntu 10 | versions: 11 | - All 12 | categories: 13 | - web 14 | # List your role dependencies here, one per line. Only 15 | # dependencies available via galaxy should be listed here. 16 | # Be sure to remove the '[]' above if you add dependencies 17 | # to this list. 18 | dependencies: [] 19 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/tasks/install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Installing packages 4 | apt: > 5 | pkg={{ item }} 6 | state=present 7 | with_items: 8 | - python-passlib 9 | tags: 10 | - web 11 | - htpasswd 12 | - install 13 | 14 | - name: Creating htpasswd folder 15 | file: > 16 | dest=/etc/htpasswd 17 | state=directory 18 | owner=root 19 | group=root 20 | mode=0755 21 | tags: 22 | - web 23 | - htpasswd 24 | - install 25 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: install.yml 4 | - include: manage.yml 5 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/tasks/manage.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Adding htpasswd files 4 | htpasswd: > 5 | path=/etc/htpasswd/{{ item.0.name }} 6 | name={{ item.1.name }} 7 | password={{ item.1.password }} 8 | crypt_scheme={{ item.1.crypt|default('apr_md5_crypt') }} 9 | owner=root 10 | group=root 11 | mode=0644 12 | with_subelements: 13 | - htpasswd 14 | - users 15 | tags: 16 | - web 17 | - apache2 18 | - htpasswd 19 | - manage 20 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.htpasswd/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | roles: 5 | - franklinkim.htpasswd 6 | vars: 7 | htpasswd: 8 | - name: myapp 9 | users: 10 | - { name: user, password: secret } 11 | 12 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *~ 3 | !.git* 4 | !.travis.yml 5 | vagrant_* 6 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | language: python 4 | python: "2.7" 5 | before_install: 6 | - sudo apt-get update -qq 7 | - sudo apt-get install -qq python-apt python-pycurl 8 | install: 9 | - pip install ansible 10 | - ansible-galaxy install franklinkim.openssl 11 | - ansible-galaxy install franklinkim.htpasswd 12 | script: 13 | - echo localhost > inventory 14 | - ln -s ansible-nginx ../franklinkim.nginx 15 | - ansible-playbook --syntax-check -i inventory test.yml 16 | - ansible-playbook -i inventory test.yml --connection=local --sudo -vvvv 17 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) We Are Interactive 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Nginx Role 2 | 3 | [![Build Status](https://travis-ci.org/weareinteractive/ansible-nginx.png?branch=master)](https://travis-ci.org/weareinteractive/ansible-nginx) 4 | [![Stories in Ready](https://badge.waffle.io/weareinteractive/ansible-nginx.svg?label=ready&title=Ready)](http://waffle.io/weareinteractive/ansible-nginx) 5 | 6 | > `nginx` is an [ansible](http://www.ansible.com) role which: 7 | > 8 | > * installs nginx 9 | > * configures nginx 10 | > * creates sites 11 | > * enables/disables sites 12 | > * optionally removes default host 13 | > * adds rules 14 | > * configures service 15 | 16 | ## Installation 17 | 18 | Using `ansible-galaxy`: 19 | 20 | ``` 21 | $ ansible-galaxy install franklinkim.nginx 22 | ``` 23 | 24 | Using `arm` ([Ansible Role Manager](https://github.com/mirskytech/ansible-role-manager/)): 25 | 26 | ``` 27 | $ arm install franklinkim.nginx 28 | ``` 29 | 30 | Using `git`: 31 | 32 | ``` 33 | $ git clone https://github.com/weareinteractive/ansible-nginx.git 34 | ``` 35 | 36 | ## Dependencies 37 | 38 | * [franklinkim.openssl](https://github.com/weareinteractive/ansible-openssl) 39 | * [franklinkim.htpasswd](https://github.com/weareinteractive/ansible-htpasswd) 40 | 41 | ## Variables 42 | 43 | Here is a list of all the default variables for this role, which are also available in `defaults/main.yml`. 44 | 45 | ``` 46 | # run as a less privileged user for security reasons. 47 | nginx_user: www-data 48 | # auto or a number 49 | nginx_worker_processes: auto 50 | nginx_worker_connections: 768 51 | # default settings 52 | nginx_sendfile: 'on' 53 | nginx_tcp_nopush: 'on' 54 | nginx_tcp_nodelay: 'on' 55 | nginx_keepalive_timeout: 54 56 | nginx_types_hash_max_size: 2048 57 | nginx_server_tokens: 'off' 58 | # remove default site 59 | nginx_remove_default: no 60 | # start on boot 61 | nginx_service_enabled: yes 62 | # current state: started, stopped 63 | nginx_service_state: started 64 | # enabled/disabled sites 65 | nginx_sites: [] 66 | ``` 67 | 68 | A site might be defined through: 69 | 70 | ``` 71 | # site id (required) 72 | id: foo 73 | # server name (required) 74 | name: foo.com 75 | # ip to listen to 76 | ip: '*' 77 | # port to listen to 78 | port: 80 79 | # state: present | absent 80 | state: present 81 | # create the /var/www/[id]/htdocs folder 82 | add_webroot: no 83 | # path to your own site template 84 | template: path/to/template.j2 85 | # /etc/nginx/rules/[rule].conf to include 86 | rules: [] 87 | # list of server aliases 88 | aliases: [] 89 | # list of server redirects 90 | redirects: [] 91 | # enable ssl 92 | ssl: 93 | # port to listen to 94 | port: 443 95 | # @see franklinkim.openssl 96 | key_name: mykey 97 | cert_name: mycert 98 | # enable auth 99 | auth: 100 | # @see franklinkim.htpasswd 101 | name: foo 102 | file: foo 103 | # custom string to append to the site 104 | append: false 105 | ``` 106 | 107 | ## Handlers 108 | 109 | These are the handlers that are defined in `handlers/main.yml`. 110 | 111 | * `restart nginx` 112 | 113 | ## Rules 114 | 115 | In addition there will be copied some configuration rules to `/etc/nginx/rules`: 116 | 117 | * cache_busting.conf 118 | * cors_web_fonts.conf 119 | * gzip.conf 120 | * no_transform.conf 121 | * ssl.conf 122 | * cors_ajax.con 123 | * expires.conf 124 | * gzip_static.conf 125 | * security.conf 126 | 127 | These can be included into your site definitions. 128 | 129 | ## Example playbook 130 | 131 | ``` 132 | - hosts: all 133 | roles: 134 | - franklinkim.nginx 135 | vars: 136 | nginx_worker_processes: 1 137 | nginx_remove_default: yes 138 | htpasswd: 139 | - name: foobar 140 | users: 141 | - { name: foobar, password: foobar } 142 | openssl_self_signed: 143 | - { name: 'foobar.local', country: 'DE', state: 'Bavaria', city: 'Munich', organization: 'Foo Bar', email: 'foo@bar.com' } 144 | nginx_sites: 145 | - id: foobar 146 | add_webroot: yes 147 | name: foobar.local 148 | ssl: 149 | key_name: foobar.local 150 | cert_name: foobar.local 151 | rules: 152 | - gzip 153 | - security 154 | auth: 155 | name: Foo Bar 156 | file: foobar 157 | ``` 158 | 159 | ## Notes 160 | 161 | You can use `franklinkim.apt` to add a repository to get the latest `nginx`: 162 | 163 | ``` 164 | apt_repositories: 165 | - 'ppa:nginx/stable' 166 | ``` 167 | 168 | ## Testing 169 | 170 | ``` 171 | $ git clone https://github.com/weareinteractive/ansible-nginx.git 172 | $ cd ansible-nginx 173 | $ vagrant up 174 | ``` 175 | 176 | ## Contributing 177 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests and examples for any new or changed functionality. 178 | 179 | 1. Fork it 180 | 2. Create your feature branch (`git checkout -b my-new-feature`) 181 | 3. Commit your changes (`git commit -am 'Add some feature'`) 182 | 4. Push to the branch (`git push origin my-new-feature`) 183 | 5. Create new Pull Request 184 | 185 | ## License 186 | Copyright (c) We Are Interactive under the MIT license. 187 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure("2") do |config| 5 | config.vm.network :private_network, ip: "192.168.33.99" 6 | config.vm.network :forwarded_port, guest: 22, host: 2299 7 | 8 | config.vm.define 'ubuntu1404-amd64' do |instance| 9 | 10 | # Every Vagrant virtual environment requires a box to build off of. 11 | instance.vm.box = 'ubuntu1404-amd64' 12 | 13 | # The url from where the 'config.vm.box' box will be fetched if it 14 | # doesn't already exist on the user's system. 15 | instance.vm.box_url = 'https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box' 16 | 17 | # View the documentation for the provider you're using for more 18 | # information on available options. 19 | config.vm.provision "ansible" do |ansible| 20 | ansible.playbook = "test.yml" 21 | ansible.verbose = 'vv' 22 | ansible.sudo = true 23 | end 24 | end 25 | end -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | roles_path = ../ -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # For more information about default variables see: 3 | # http://www.ansibleworks.com/docs/playbooks_variables.html#id26 4 | # 5 | # nginx_sites: 6 | # - id: foo (required) 7 | # name: foo.com (required) 8 | # ip: '*' 9 | # port: 80 10 | # state: present 11 | # add_webroot: no 12 | # template: path/to/template.j2 13 | # aliases: [] 14 | # redirects: [] 15 | # ssl: 16 | # port: 443 17 | # key_name: mykey 18 | # cert_name: mycert 19 | # rules: [] 20 | # auth: 21 | # name: foo 22 | # file: foo 23 | # append: '' 24 | # 25 | 26 | # run as a less privileged user for security reasons. 27 | nginx_user: www-data 28 | # auto or a number 29 | nginx_worker_processes: auto 30 | nginx_worker_connections: 768 31 | # default settings 32 | nginx_sendfile: 'on' 33 | nginx_tcp_nopush: 'on' 34 | nginx_tcp_nodelay: 'on' 35 | nginx_keepalive_timeout: 54 36 | nginx_types_hash_max_size: 2048 37 | nginx_server_tokens: 'off' 38 | # remove default site 39 | nginx_remove_default: no 40 | # start on boot 41 | nginx_service_enabled: yes 42 | # current state: started, stopped 43 | nginx_service_state: started 44 | # enabled/disabled sites 45 | nginx_sites: [] -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/files/etc-nginx-rules/cache_busting.conf: -------------------------------------------------------------------------------- 1 | # Built-in filename-based cache busting 2 | 3 | # https://github.com/h5bp/html5-boilerplate/blob/5370479476dceae7cc3ea105946536d6bc0ee468/.htaccess#L403 4 | # This will route all requests for /css/style.20120716.css to /css/style.css 5 | # Read also this: github.com/h5bp/html5-boilerplate/wiki/cachebusting 6 | # This is not included by default, because it'd be better if you use the build 7 | # script to manage the file names. 8 | location ~* (.+)\.(?:\d+)\.(js|css|png|jpg|jpeg|gif)$ { 9 | try_files $uri $1.$2; 10 | } 11 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/files/etc-nginx-rules/cors_ajax.conf: -------------------------------------------------------------------------------- 1 | # Cross domain AJAX requests 2 | add_header "Access-Control-Allow-Origin" "*"; 3 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/files/etc-nginx-rules/cors_web_fonts.conf: -------------------------------------------------------------------------------- 1 | # Cross domain webfont access 2 | location ~* \.(?:ttf|ttc|otf|eot|woff)$ { 3 | add_header "Access-Control-Allow-Origin" "*"; 4 | 5 | # Also, set cache rules for webfonts. 6 | # 7 | # See http://wiki.nginx.org/HttpCoreModule#location 8 | # And https://github.com/h5bp/server-configs/issues/85 9 | # And https://github.com/h5bp/server-configs/issues/86 10 | expires 1M; 11 | access_log off; 12 | add_header Cache-Control "public"; 13 | } 14 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/files/etc-nginx-rules/expires.conf: -------------------------------------------------------------------------------- 1 | # Expire rules for static content 2 | 3 | # No default expire rule. This config mirrors that of apache as outlined in the 4 | # html5-boilerplate .htaccess file. However, nginx applies rules by location, 5 | # the apache rules are defined by type. A concequence of this difference is that 6 | # if you use no file extension in the url and serve html, with apache you get an 7 | # expire time of 0s, with nginx you'd get an expire header of one month in the 8 | # future (if the default expire rule is 1 month). Therefore, do not use a 9 | # default expire rule with nginx unless your site is completely static 10 | 11 | # cache.appcache, your document html and data 12 | location ~* \.(?:manifest|appcache|html?|xml|json)$ { 13 | expires -1; 14 | access_log /var/log/nginx/static.log; 15 | } 16 | 17 | # Feed 18 | location ~* \.(?:rss|atom)$ { 19 | expires 1h; 20 | add_header Cache-Control "public"; 21 | } 22 | 23 | # Media: images, icons, video, audio, HTC 24 | location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ { 25 | expires 1M; 26 | access_log off; 27 | add_header Cache-Control "public"; 28 | } 29 | 30 | # CSS and Javascript 31 | location ~* \.(?:css|js)$ { 32 | expires 1y; 33 | access_log off; 34 | add_header Cache-Control "public"; 35 | } 36 | 37 | # WebFonts 38 | # If you are NOT using cross-domain-fonts.conf, uncomment the following directive 39 | # location ~* \.(?:ttf|ttc|otf|eot|woff)$ { 40 | # expires 1M; 41 | # access_log off; 42 | # add_header Cache-Control "public"; 43 | # } 44 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/files/etc-nginx-rules/gzip.conf: -------------------------------------------------------------------------------- 1 | # Enable compression both for HTTP/1.0 and HTTP/1.1 (required for CloudFront). 2 | gzip_http_version 1.0; 3 | 4 | # Compression level (1-9). 5 | # 5 is a perfect compromise between size and cpu usage, offering about 6 | # 75% reduction for most ascii files (almost identical to level 9). 7 | gzip_comp_level 5; 8 | 9 | # Don't compress anything that's already small and unlikely to shrink much 10 | # if at all (the default is 20 bytes, which is bad as that usually leads to 11 | # larger files after gzipping). 12 | gzip_min_length 256; 13 | 14 | # Compress data even for clients that are connecting to us via proxies, 15 | # identified by the "Via" header (required for CloudFront). 16 | gzip_proxied any; 17 | 18 | # Tell proxies to cache both the gzipped and regular version of a resource 19 | # whenever the client's Accept-Encoding capabilities header varies; 20 | # Avoids the issue where a non-gzip capable client (which is extremely rare 21 | # today) would display gibberish if their proxy gave them the gzipped version. 22 | gzip_vary on; 23 | 24 | # Compress all output labeled with one of the following MIME-types. 25 | gzip_types 26 | application/atom+xml 27 | application/javascript 28 | application/json 29 | application/rss+xml 30 | application/vnd.ms-fontobject 31 | application/x-font-ttf 32 | application/x-web-app-manifest+json 33 | application/xhtml+xml 34 | application/xml 35 | font/opentype 36 | image/svg+xml 37 | image/x-icon 38 | text/css 39 | text/plain 40 | text/x-component; 41 | # text/html is always compressed by HttpGzipModule -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/files/etc-nginx-rules/gzip_static.conf: -------------------------------------------------------------------------------- 1 | # This should be turned on if you are going to have pre-compressed copies (.gz) of 2 | # static files available. If not it should be left off as it will cause extra I/O 3 | # for the check. It is best if you enable this in a location{} block for 4 | # a specific directory, or on an individual server{} level. 5 | gzip_static on; -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/files/etc-nginx-rules/no_transform.conf: -------------------------------------------------------------------------------- 1 | # Prevent mobile network providers from modifying your site 2 | add_header "Cache-Control" "no-transform"; 3 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/files/etc-nginx-rules/security.conf: -------------------------------------------------------------------------------- 1 | # Block access to hidden files and directories. 2 | # This includes directories used by version control systems such as Git and SVN. 3 | location ~* (?:^|/)\. { 4 | deny all; 5 | access_log off; 6 | log_not_found off; 7 | } 8 | 9 | # Block access to backup and source files. 10 | # These files may be left by some text editors and can pose a great security 11 | # danger when anyone has access to them. 12 | location ~* (?:\.(?:bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~)$ { 13 | deny all; 14 | access_log off; 15 | log_not_found off; 16 | } 17 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/files/etc-nginx-rules/ssl.conf: -------------------------------------------------------------------------------- 1 | # Protect against the BEAST attack by preferring RC4-SHA when using SSLv3 and TLS protocols. 2 | # Note that TLSv1.1 and TLSv1.2 are immune to the beast attack but only work with OpenSSL v1.0.1 and higher and has limited client support. 3 | ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; 4 | ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES"; 5 | ssl_prefer_server_ciphers on; 6 | 7 | # Optimize SSL by caching session parameters for 10 minutes. This cuts down on the number of expensive SSL handshakes. 8 | # The handshake is the most CPU-intensive operation, and by default it is re-negotiated on every new/parallel connection. 9 | # By enabling a cache (of type "shared between all Nginx workers"), we tell the client to re-use the already negotiated state. 10 | # Further optimization can be achieved by raising keepalive_timeout, but that shouldn't be done unless you serve primarily HTTPS. 11 | ssl_session_cache shared:SSL:10m; # a 1mb cache can hold about 4000 sessions, so we can hold 40000 sessions 12 | ssl_session_timeout 10m; -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # For more information about handlers see: 3 | # http://www.ansibleworks.com/docs/playbooks.html#handlers-running-operations-on-change 4 | # 5 | 6 | - name: restart nginx 7 | service: name=nginx state=restarted 8 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: franklin 4 | company: We Are Interactive 5 | description: Installs and configures nginx 6 | min_ansible_version: 1.6 7 | license: MIT 8 | platforms: 9 | - name: Ubuntu 10 | versions: 11 | - All 12 | categories: 13 | - system 14 | # List your role dependencies here, one per line. Only 15 | # dependencies available via galaxy should be listed here. 16 | # Be sure to remove the '[]' above if you add dependencies 17 | # to this list. 18 | dependencies: 19 | - franklinkim.openssl 20 | - franklinkim.htpasswd 21 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/tasks/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Configuring nginx 4 | template: > 5 | src=etc-nginx-nginx.conf.j2 6 | dest=/etc/nginx/nginx.conf 7 | owner=root 8 | group=root 9 | mode=644 10 | notify: restart nginx 11 | tags: 12 | - web 13 | - nginx 14 | - config 15 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/tasks/install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Installing packages 4 | apt: > 5 | pkg={{ item }} 6 | state=present 7 | with_items: 8 | - nginx 9 | tags: 10 | - web 11 | - nginx 12 | - install 13 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: install.yml 4 | - include: config.yml 5 | - include: rules.yml 6 | - include: remove_default.yml 7 | - include: manage_sites.yml 8 | - include: service.yml 9 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/tasks/manage_sites.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Creating webroots 4 | file: > 5 | dest=/var/www/{{ item.id }}/htdocs 6 | state=directory 7 | when: item.add_webroot is defined and item.add_webroot == true 8 | with_items: nginx_sites 9 | tags: 10 | - web 11 | - nginx-html 12 | - manage 13 | 14 | - name: Creating sites 15 | template: > 16 | src={{ item.template|default('etc-nginx-sites-available-site.j2') }} 17 | dest=/etc/nginx/sites-available/{{ item.id }} 18 | owner=root 19 | group=root 20 | mode=0644 21 | with_items: nginx_sites 22 | tags: 23 | - web 24 | - nginx-html 25 | - manage 26 | 27 | - name: Enabling sites 28 | file: > 29 | src=/etc/nginx/sites-available/{{ item.id }} 30 | dest=/etc/nginx/sites-enabled/{{ item.id }} 31 | state=link 32 | when: item.state is not defined or item.state == 'present' 33 | notify: restart nginx 34 | with_items: nginx_sites 35 | tags: 36 | - web 37 | - nginx 38 | - manage_sites 39 | 40 | - name: Disabling sites 41 | file: > 42 | src=/etc/nginx/sites-available/{{ item.id }} 43 | dest=/etc/nginx/sites-enabled/{{ item.id }} 44 | state=absent 45 | when: item.state is defined and item.state == 'absent' 46 | notify: restart nginx 47 | with_items: nginx_sites 48 | tags: 49 | - web 50 | - nginx 51 | - manage_sites 52 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/tasks/remove_default.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Disabling default site 4 | file: > 5 | path=/etc/nginx/sites-enabled/default 6 | state=absent 7 | when: nginx_remove_default 8 | tags: 9 | - web 10 | - nginx 11 | - remove_default 12 | 13 | - name: Removing default host 14 | file: > 15 | path=/etc/nginx/sites-available/default 16 | state=absent 17 | when: nginx_remove_default 18 | tags: 19 | - web 20 | - nginx 21 | - remove_default 22 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/tasks/rules.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Adding rules 4 | copy: > 5 | src=etc-nginx-rules/ 6 | dest=/etc/nginx/rules/ 7 | owner=root 8 | group=root 9 | mode=0644 10 | tags: 11 | - web 12 | - nginx 13 | - rules 14 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/tasks/service.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Configuring service 4 | service: > 5 | name=nginx 6 | state={{ nginx_service_state }} 7 | enabled={{ nginx_service_enabled }} 8 | tags: 9 | - web 10 | - nginx 11 | - service 12 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/templates/etc-nginx-nginx.conf.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | # nginx Configuration File 3 | # http://wiki.nginx.org/Configuration 4 | 5 | # Run as a less privileged user for security reasons. 6 | user {{ nginx_user }}; 7 | 8 | # How many worker threads to run; 9 | # "auto" sets it to the number of CPU cores available in the system, and 10 | # offers the best performance. Don't set it higher than the number of CPU 11 | # cores if changing this parameter. 12 | 13 | # The maximum number of connections for Nginx is calculated by: 14 | # max_clients = worker_processes * worker_connections 15 | worker_processes {{ nginx_worker_processes }}; 16 | 17 | 18 | events { 19 | # When you need > 8000 * cpu_cores connections, you start optimizing your OS, 20 | # and this is probably the point at which you hire people who are smarter than 21 | # you, as this is *a lot* of requests. 22 | worker_connections {{ nginx_worker_connections }}; 23 | } 24 | 25 | # Default log file 26 | # (this is only used when you don't override access_log on a server{} level) 27 | error_log /var/log/nginx/error.log warn; 28 | pid /run/nginx.pid; 29 | 30 | http { 31 | ## 32 | # Basic Settings 33 | ## 34 | 35 | # If we set index here, we won't have to anywhere else 36 | index index.html index.htm; 37 | 38 | # Speed up file transfers by using sendfile() to copy directly 39 | # between descriptors rather than using read()/write(). 40 | sendfile {{ nginx_sendfile }}; 41 | 42 | # Tell Nginx not to send out partial frames; this increases throughput 43 | # since TCP frames are filled up before being sent out. (adds TCP_CORK) 44 | tcp_nopush {{ nginx_tcp_nopush }}; 45 | 46 | # Tell Nginx to enable the Nagle buffering algorithm for TCP packets, which 47 | # collates several smaller packets together into one larger packet, thus saving 48 | # bandwidth at the cost of a nearly imperceptible increase to latency. (removes TCP_NODELAY) 49 | tcp_nodelay {{ nginx_tcp_nodelay }}; 50 | 51 | # How long to allow each connection to stay idle; longer values are better 52 | # for each individual client, particularly for SSL, but means that worker 53 | # connections are tied up longer. (Default: 65) 54 | keepalive_timeout {{ nginx_keepalive_timeout }}; 55 | 56 | types_hash_max_size {{ nginx_types_hash_max_size }}; 57 | 58 | # Hide nginx version information. 59 | server_tokens {{ nginx_server_tokens }}; 60 | 61 | # Define the MIME types for files. 62 | include /etc/nginx/mime.types; 63 | default_type application/octet-stream; 64 | 65 | ## 66 | # Logging Settings 67 | ## 68 | 69 | # Format to use in log files 70 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 71 | '$status $body_bytes_sent "$http_referer" ' 72 | '"$http_user_agent" "$http_x_forwarded_for"'; 73 | 74 | # Default log file 75 | # (this is only used when you don't override access_log on a server{} level) 76 | access_log /var/log/nginx/access.log; 77 | error_log /var/log/nginx/error.log; 78 | 79 | ## 80 | # Gzip Settings 81 | ## 82 | 83 | gzip on; 84 | gzip_disable "msie6"; 85 | 86 | # gzip_vary on; 87 | # gzip_proxied any; 88 | # gzip_comp_level 6; 89 | # gzip_buffers 16 8k; 90 | # gzip_http_version 1.1; 91 | # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; 92 | 93 | ## 94 | # nginx-naxsi config 95 | ## 96 | # Uncomment it if you installed nginx-naxsi 97 | ## 98 | 99 | #include /etc/nginx/naxsi_core.rules; 100 | 101 | ## 102 | # nginx-passenger config 103 | ## 104 | # Uncomment it if you installed nginx-passenger 105 | ## 106 | 107 | #passenger_root /usr; 108 | #passenger_ruby /usr/bin/ruby; 109 | 110 | ## 111 | # Virtual Host Configs 112 | ## 113 | 114 | include /etc/nginx/conf.d/*; 115 | include /etc/nginx/sites-enabled/*; 116 | } -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/templates/etc-nginx-sites-available-site.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | {% include "etc-nginx-sites-available-site/redirect.j2" %} 4 | 5 | {% include "etc-nginx-sites-available-site/body.j2" %} 6 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/templates/etc-nginx-sites-available-site/body.j2: -------------------------------------------------------------------------------- 1 | server { 2 | server_name {{ item.name }}{% for value in item.aliases|default([]) %} {{ value }}{% endfor %}; 3 | root /var/www/{{ item.id }}/htdocs; 4 | 5 | # --- listen ---------------------------------------------------------------- 6 | 7 | listen {{ item.ip|default('*') }}:{{item.port|default(80)}}; 8 | {% if item.ssl is defined %} 9 | listen {{ item.ip|default('*') }}:{{item.ssl.port|default(443)}} ssl; 10 | {% endif %} 11 | 12 | {% if item.ssl is defined %} 13 | # --- ssl ------------------------------------------------------------------- 14 | include rules/ssl.conf; 15 | 16 | ssl_certificate {{ openssl_certs_path }}/{{ item.ssl.cert_name|default('server') }}.crt; 17 | ssl_certificate_key {{ openssl_keys_path }}/{{ item.ssl.key_name|default('server') }}.key; 18 | {% endif %} 19 | 20 | {% if item.rules is defined %} 21 | # --- rule ------------------------------------------------------------------ 22 | {% for value in item.rules %} 23 | include rules/{{ value }}.conf; 24 | {% endfor %} 25 | {% endif %} 26 | 27 | {% if item.auth is defined %} 28 | # --- auth ------------------------------------------------------------------ 29 | 30 | auth_basic "{{ item.auth.name|default(item.id) }}"; 31 | auth_basic_user_file /etc/htpasswd/{{ item.auth.file|default(item.id) }}; 32 | {% endif %} 33 | 34 | # --- locations ------------------------------------------------------------- 35 | 36 | {% if item.proxy_pass is defined %} 37 | 38 | location {{ item.proxy_pass.location }} { 39 | proxy_pass {{ item.proxy_pass.target }}; 40 | } 41 | 42 | {% else %} 43 | 44 | location / { 45 | try_files $uri $uri/ =404; 46 | } 47 | 48 | {% endif %} 49 | 50 | {% if item.status_allow_address is defined %} 51 | 52 | location /nginx_status { 53 | stub_status on; 54 | access_log off; 55 | allow {{ status_allow_address }}; 56 | deny all; 57 | } 58 | 59 | {% endif %} 60 | 61 | # --- logging --------------------------------------------------------------- 62 | 63 | error_log /var/log/nginx/error-{{ item.id }}.log; 64 | access_log /var/log/nginx/access-{{ item.id }}.log; 65 | 66 | {% if item.append is defined %} 67 | # --- appended -------------------------------------------------------------- 68 | 69 | {{ item.append }} 70 | {% endif %} 71 | } 72 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/templates/etc-nginx-sites-available-site/redirect.j2: -------------------------------------------------------------------------------- 1 | {% for value in item.redirects|default([]) %} 2 | server { 3 | server_name {{ value }}; 4 | listen {{ item.ip|default('*') }}:{{item.port|default(80)}}; 5 | {% if item.ssl is defined %} 6 | listen {{ item.ip|default('*') }}:{{item.ssl.port|default(443)}} ssl; 7 | {% endif %} 8 | 9 | {% if item.ssl is defined %} 10 | # --- ssl ------------------------------------------------------------------- 11 | 12 | include rules/ssl.conf; 13 | 14 | ssl_certificate {{ openssl_certs_path }}/{{ item.ssl.cert_name|default('server') }}.crt; 15 | ssl_certificate_key {{ openssl_keys_path }}/{{ item.ssl.key_name|default('server') }}.key; 16 | {% endif %} 17 | 18 | # --- redirects -------------------------------------------------------------- 19 | 20 | rewrite ^/(.*)$ $scheme://{{ item.name }}/$1 permanent; 21 | } 22 | {% endfor %} 23 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.nginx/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | roles: 5 | - franklinkim.nginx 6 | vars: 7 | nginx_worker_processes: 1 8 | nginx_remove_default: yes 9 | htpasswd: 10 | - name: foobar 11 | users: 12 | - { name: foobar, password: foobar } 13 | openssl_self_signed: 14 | - { name: 'foobar.local', country: 'DE', state: 'Bavaria', city: 'Munich', organization: 'Foo Bar', email: 'foo@bar.com' } 15 | nginx_sites: 16 | - id: foobar 17 | add_webroot: yes 18 | name: foobar.local 19 | ssl: 20 | key_name: foobar.local 21 | cert_name: foobar.local 22 | rules: 23 | - gzip 24 | - security 25 | auth: 26 | name: Foo Bar 27 | file: foobar 28 | # proxy_pass: 29 | # location: '/' 30 | # target: 'http://localhost:8500' 31 | # status_allow_address: 0.0.0.0 32 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *~ 3 | !.git* 4 | !.travis.yml 5 | vagrant_* 6 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | language: python 4 | python: "2.7" 5 | before_install: 6 | - sudo apt-get update -qq 7 | - sudo apt-get install -qq python-apt python-pycurl 8 | install: 9 | - pip install ansible 10 | script: 11 | - echo localhost > inventory 12 | - ln -s ansible-openssl ../franklinkim.openssl 13 | - ansible-playbook --syntax-check -i inventory test.yml 14 | - ansible-playbook -i inventory test.yml --connection=local --sudo -vvvv 15 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) We Are Interactive 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Openssl Role 2 | 3 | [![Build Status](https://travis-ci.org/weareinteractive/ansible-openssl.png?branch=master)](https://travis-ci.org/weareinteractive/ansible-openssl) 4 | [![Stories in Ready](https://badge.waffle.io/weareinteractive/ansible-openssl.svg?label=ready&title=Ready)](http://waffle.io/weareinteractive/ansible-openssl) 5 | 6 | > `openssl` is an [ansible](http://www.ansible.com) role which: 7 | > 8 | > * installs openssl 9 | > * configures openssl 10 | > * imports ssl certificates and keys 11 | > * creates a self-signed certificate 12 | 13 | ## Installation 14 | 15 | Using `ansible-galaxy`: 16 | 17 | ``` 18 | $ ansible-galaxy install franklinkim.openssl 19 | ``` 20 | 21 | Using `arm` ([Ansible Role Manager](https://github.com/mirskytech/ansible-role-manager/)): 22 | 23 | ``` 24 | $ arm install franklinkim.openssl 25 | ``` 26 | 27 | Using `git`: 28 | 29 | ``` 30 | $ git clone https://github.com/weareinteractive/ansible-openssl.git 31 | ``` 32 | 33 | ## Variables 34 | 35 | Here is a list of all the default variables for this role, which are also available in `defaults/main.yml`. 36 | 37 | ``` 38 | # openssl_keys: 39 | # - { name: mykey, key: "mykeycontents" } 40 | # openssl_certs: 41 | # - { name: mycert, cert: "mycertcontents" } 42 | # openssl_self_signed: 43 | # - { name: 'foobar.com', country: 'DE', state: 'Bavaria', city: 'Munich', organization: 'Foo Bar', unit: '', email: 'foo@bar.com', days: 3650 } 44 | # openssl_config: 45 | # default_bits: 2048 46 | # countryName_default: DE 47 | # stateOrProvinceName_default: Bavaria 48 | # localityName_default: Munich 49 | # organizationName_default: 'My Organization' 50 | # organizationalUnitName_default: 'My Organization Unit' 51 | # commonName_default: 'foobar.com' 52 | # openssl_config_template: templates/openssl.cnf.j2 53 | 54 | # keys to import 55 | openssl_keys: [] 56 | # certificates to import 57 | openssl_certs: [] 58 | # path to certificates 59 | openssl_certs_path: /etc/ssl/certs 60 | # path to keys 61 | openssl_keys_path: /etc/ssl/private 62 | # self signed certificates 63 | openssl_self_signed: [] 64 | # config variables 65 | openssl_config: {} 66 | # config template to install, relative to the ansible repository root 67 | openssl_config_template: 68 | ``` 69 | 70 | ## Example playbook 71 | 72 | ``` 73 | - host: all 74 | roles: 75 | - franklinkim.openssl 76 | vars: 77 | openssl_keys: 78 | - { name: foobar.com, key: "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDhSsYh36iAShzd\nNM0dSxiVXFe3WCZbePTQSNQ0hnFyBF1AfQKzpo9kFP3h+/IxzUNcPREAqOjmIfl4\ndVTXicyqVrqwt1su90+DitRmvYU0e4PDAA9pwQAxdT1qGBnzBFMgs/JpwQNQetCz\nzISDYn0QbaBGLXs6+UkDGyKu8LCX/T0vOLQ/LecDleZrXf6ubqK7H9SGtGsPLlDw\nonAe+KKieDYJlfHX9omaC953fp8aKDA7V5g/3KbkhsERDl6b/++fNjlestgnZMms\nYdDsM6MzBlt+3f0YQQXzVsmO8LGJxLMSMEmmg76e1VegPq+FyjMQp8r+8i2y/Tvz\nadL0bnivAgMBAAECggEBAKhbp4rCx/nu6HkKL0n3x4w+cLJrpmZvEovgEOybl4V7\n62/4u58jFj7VTRCmpcw/t1njrKQQldL8iqBRFjDoIlEc9PCAZRzI5dvIUIfikvuw\nXbvIfLwr5YgQM+/nyOSJU9G5h6st+NsYnIPwjwpb/FfdhItNC6z7g2tVyOpwpZc9\n2WwJadASIew3GOSd3gLoZLiO+r6XdPc//VcAxaNhu1B5RMHpQxeKa7KQ9T3CzCj4\nTBvIxV5LKAiGMlE26WZR7X2xkLzWswCsk8SAv9ulqbuKlSoPMh86BadM5H6SeGuP\ncsTcTGgoAmhbNmUN/j3lOjHJed7oUKEQGVgGIh4W1OkCgYEA+ECUtXl/sQzUiAYz\nKy556wb31v31D+tVftYU5BzwB/YO7T1ApY1/Bzs/KbnXiKu3eb3IyfEVe/CTcyE9\nhTrJJr5b6Nesa4n0PMpxHfZbWloGoewyfVl7Dgu6/KFctKFm17QcFSG7NsGraE6L\nBQ80gWo94Fyt1nXN9+myUeKga5sCgYEA6FLAgUFS7ykFA0bh5MLV1Q9IZav86Hky\nOmgM1ysd/B9ObRAxKaQezvK+4uyaUW55d8pQZJE2YQo84KPX1wFiAPkR5dwm/C1J\nuH9fz5OycXTUS0LJYGFLmeyKSQ4N+V+8Ex5laFqhHXE8Rzpi/QbYuf4V2EDPlY4g\n6kQgtzS/qn0CgYAQfDlj062nFDMI1WCQfYWbFdtfa33akMYcphq9Cy7lWHGlT2v7\nkmndERIgszac3MpSS0gKIPhMQq2H960eK8kvyXRRAgFxIrgVUVwxoSpv1YqbNhQk\nPsztIdpI7G47kHxD1rIGtTa5bCL1ykFxFJFoBqYVQBJLK4eB7wLobSQ6AQKBgEiB\n+z7cCmxGGyBosPvaqy4x9OB2ixprKPf9nXRSKquTgcCcOxvJ8yuXq2fbfFZJ6nMu\nm2SnxZcHwPRDbovWDKZNFf7tdOVjpQyGBHsel6S9V7ydfYgtFZFWt9oRHt9jt6kn\n5XJqRrqPqsZ4PIjH6EA0QtEZeTAuCavT03oaZm9pAoGBAPVuxRWNqfF7fWbLZiHG\nq3ykwooYtbSfixRe2y/h7IHrQyCbAEG/V2FBPKTNhh0zwHpRTS4PFRL3h+ZQNYrr\n/n+zN/OJl/75P53NDlZ5n1m1eYPMbVjDvvTDDdWqkESLUvTRT7JnyiXApRY0EWTA\nArNAJBxDBD66sa5BM9hZV9fG\n-----END PRIVATE KEY-----\n" } 79 | openssl_certs: 80 | - { name: foobar.com, cert: "-----BEGIN CERTIFICATE-----\nMIIDuTCCAqGgAwIBAgIJAO7EaRwLzPYyMA0GCSqGSIb3DQEBCwUAMHMxCzAJBgNV\nBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gxEDAOBgNV\nBAoMB0ZvbyBCYXIxEzARBgNVBAMMCmZvb2Jhci5jb20xGjAYBgkqhkiG9w0BCQEW\nC2Zvb0BiYXIuY29tMB4XDTE0MDgwMjE1NTMxNloXDTI0MDczMDE1NTMxNlowczEL\nMAkGA1UEBhMCREUxEDAOBgNVBAgMB0JhdmFyaWExDzANBgNVBAcMBk11bmljaDEQ\nMA4GA1UECgwHRm9vIEJhcjETMBEGA1UEAwwKZm9vYmFyLmNvbTEaMBgGCSqGSIb3\nDQEJARYLZm9vQGJhci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\nAQDhSsYh36iAShzdNM0dSxiVXFe3WCZbePTQSNQ0hnFyBF1AfQKzpo9kFP3h+/Ix\nzUNcPREAqOjmIfl4dVTXicyqVrqwt1su90+DitRmvYU0e4PDAA9pwQAxdT1qGBnz\nBFMgs/JpwQNQetCzzISDYn0QbaBGLXs6+UkDGyKu8LCX/T0vOLQ/LecDleZrXf6u\nbqK7H9SGtGsPLlDwonAe+KKieDYJlfHX9omaC953fp8aKDA7V5g/3KbkhsERDl6b\n/++fNjlestgnZMmsYdDsM6MzBlt+3f0YQQXzVsmO8LGJxLMSMEmmg76e1VegPq+F\nyjMQp8r+8i2y/TvzadL0bnivAgMBAAGjUDBOMB0GA1UdDgQWBBTMI1BoL1dh9tov\nQxJHM6GnZfBhMTAfBgNVHSMEGDAWgBTMI1BoL1dh9tovQxJHM6GnZfBhMTAMBgNV\nHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQALezxaXABZEQE6RDmtfBE7jdGy\nxWJVLxSoH0+YNNVXDYNCwNdDMBbjcH6B//aaGLc6Zqif7+HlRfmr4SVfjIP8UQZR\nSQ2s/tcftR6Wp2aadIdUZZkIvmaWvyFfBrrm8F6Ot22Y8EIgjSl/y4kewM6qD1MY\nxC7qAwze2k0yPqVdAXFYJh/+thRTV4YA9R8OCVVRO4xoEOGsTOsHQYH7+/lR3U+o\nbmBu+k1pPK+LYCoQyIrIB6xHqRYf4nHirxlbu4+aAY1Rc57Okbk68g6ThA27r8Ay\n/14Fu1Ry6NAq/1zeSzX4JrFQOlZDNtqF0UXgph2RehMZjtQG2b4B8gLpwPRe\n-----END CERTIFICATE-----\n" } 81 | openssl_self_signed: 82 | - { name: 'foobar.org', country: 'DE', state: 'Bavaria', city: 'Munich', organization: 'Foo Bar', unit: '', email: 'foo@bar.com', days: 3650 } 83 | ``` 84 | 85 | ## Testing 86 | 87 | ``` 88 | $ git clone https://github.com/weareinteractive/ansible-openssl.git 89 | $ cd ansible-openssl 90 | $ vagrant up 91 | ``` 92 | 93 | ## Contributing 94 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests and examples for any new or changed functionality. 95 | 96 | 1. Fork it 97 | 2. Create your feature branch (`git checkout -b my-new-feature`) 98 | 3. Commit your changes (`git commit -am 'Add some feature'`) 99 | 4. Push to the branch (`git push origin my-new-feature`) 100 | 5. Create new Pull Request 101 | 102 | ## License 103 | Copyright (c) We Are Interactive under the MIT license. 104 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure("2") do |config| 5 | config.vm.network :private_network, ip: "192.168.33.99" 6 | config.vm.network :forwarded_port, guest: 22, host: 2299 7 | 8 | config.vm.define 'ubuntu1404-amd64' do |instance| 9 | 10 | # Every Vagrant virtual environment requires a box to build off of. 11 | instance.vm.box = 'ubuntu1404-amd64' 12 | 13 | # The url from where the 'config.vm.box' box will be fetched if it 14 | # doesn't already exist on the user's system. 15 | instance.vm.box_url = 'https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box' 16 | 17 | # View the documentation for the provider you're using for more 18 | # information on available options. 19 | config.vm.provision "ansible" do |ansible| 20 | ansible.playbook = "test.yml" 21 | ansible.verbose = 'vv' 22 | ansible.sudo = true 23 | end 24 | end 25 | end -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | roles_path = ../ -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # For more information about default variables see: 3 | # http://www.ansibleworks.com/docs/playbooks_variables.html#id26 4 | # 5 | # openssl_keys: 6 | # - { name: mykey, key: "mykeycontents" } 7 | # openssl_certs: 8 | # - { name: mycert, cert: "mycertcontents" } 9 | # openssl_self_signed: 10 | # - { name: 'foobar.com', domains: ['*.foobar.com', 'foobar.com'], country: 'DE', state: 'Bavaria', city: 'Munich', organization: 'Foo Bar', unit: '', email: 'foo@bar.com', days: 3650 } 11 | # openssl_config: 12 | # default_bits: 2048 13 | # countryName_default: DE 14 | # stateOrProvinceName_default: Bavaria 15 | # localityName_default: Munich 16 | # organizationName_default: 'My Organization' 17 | # organizationalUnitName_default: 'My Organization Unit' 18 | # commonName_default: 'foobar.com' 19 | # openssl_config_template: templates/openssl.cnf.j2 20 | 21 | # keys to import 22 | openssl_keys: [] 23 | # certificates to import 24 | openssl_certs: [] 25 | # path to certificates 26 | openssl_certs_path: /etc/ssl/certs 27 | # path to keys 28 | openssl_keys_path: /etc/ssl/private 29 | # self signed certificates 30 | openssl_self_signed: [] 31 | # config variables 32 | openssl_config: {} 33 | # config template to install, relative to the ansible repository root 34 | openssl_config_template: -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: franklin 4 | company: We Are Interactive 5 | description: Installs opensll and creates/imports certificates 6 | min_ansible_version: 1.6 7 | license: MIT 8 | # 9 | # Below are all platforms currently available. Just uncomment 10 | # the ones that apply to your role. If you don't see your 11 | # platform on this list, let us know and we'll get it added! 12 | # 13 | platforms: 14 | # - name: EL 15 | # versions: 16 | # - all 17 | # - 5 18 | # - 6 19 | # - name: GenericUNIX 20 | # versions: 21 | # - all 22 | # - any 23 | # - name: Fedora 24 | # versions: 25 | # - all 26 | # - 16 27 | # - 17 28 | # - 18 29 | # - 19 30 | # - 20 31 | # - name: opensuse 32 | # versions: 33 | # - all 34 | # - 12.1 35 | # - 12.2 36 | # - 12.3 37 | # - 13.1 38 | # - 13.2 39 | # - name: GenericBSD 40 | # versions: 41 | # - all 42 | # - any 43 | # - name: FreeBSD 44 | # versions: 45 | # - all 46 | # - 8.0 47 | # - 8.1 48 | # - 8.2 49 | # - 8.3 50 | # - 8.4 51 | # - 9.0 52 | # - 9.1 53 | # - 9.1 54 | # - 9.2 55 | - name: Ubuntu 56 | versions: 57 | - all 58 | # - lucid 59 | # - maverick 60 | # - natty 61 | # - oneiric 62 | # - precise 63 | # - quantal 64 | # - raring 65 | # - saucy 66 | # - trusty 67 | # - name: SLES 68 | # versions: 69 | # - all 70 | # - 10SP3 71 | # - 10SP4 72 | # - 11 73 | # - 11SP1 74 | # - 11SP2 75 | # - 11SP3 76 | # - name: GenericLinux 77 | # versions: 78 | # - all 79 | # - any 80 | # - name: Debian 81 | # versions: 82 | # - all 83 | # - etch 84 | # - lenny 85 | # - squeeze 86 | # - wheezy 87 | # 88 | # Below are all categories currently available. Just as with 89 | # the platforms above, uncomment those that apply to your role. 90 | # 91 | categories: 92 | # - cloud 93 | # - cloud:ec2 94 | # - cloud:gce 95 | # - cloud:rax 96 | # - database 97 | # - database:nosql 98 | # - database:sql 99 | # - development 100 | # - monitoring 101 | # - networking 102 | # - packaging 103 | - system 104 | # - web 105 | dependencies: [] 106 | # List your role dependencies here, one per line. Only 107 | # dependencies available via galaxy should be listed here. 108 | # Be sure to remove the '[]' above if you add dependencies 109 | # to this list. 110 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/tasks/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Configuring 4 | template: > 5 | src={{ openssl_config_template if openssl_config_template else 'etc-ssl-openssl.cnf.j2' }} 6 | dest=/etc/ssl/openssl.cnf 7 | owner=root 8 | group=root 9 | mode=0644 10 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/tasks/copy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Copying ssl keys 4 | copy: > 5 | content="{{ item.key }}" 6 | dest={{ openssl_keys_path }}/{{ item.name }}.key 7 | owner=root 8 | group=root 9 | mode=0600 10 | with_items: openssl_keys 11 | tags: 12 | - system 13 | - openssl 14 | - copy 15 | 16 | - name: copying ssl certs 17 | copy: > 18 | content="{{ item.cert }}" 19 | dest={{ openssl_certs_path }}/{{ item.name }}.crt 20 | owner=root 21 | group=root 22 | mode=0644 23 | with_items: openssl_certs 24 | tags: 25 | - system 26 | - openssl 27 | - copy 28 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/tasks/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Creating certs dir 4 | include: > 5 | create_dir.yml 6 | item={{ openssl_certs_path }} 7 | mode="0755" 8 | tags: 9 | - system 10 | - openssl 11 | - create 12 | 13 | - name: Creating keys dir 14 | include: > 15 | create_dir.yml 16 | item={{ openssl_keys_path }} 17 | mode="0700" 18 | tags: 19 | - system 20 | - openssl 21 | - create 22 | 23 | - name: Creating self-signed server SSL cert 24 | command: > 25 | openssl req -new -nodes -x509 -subj "/C={{ item.country|default('') }}/ST={{ item.state|default('') }}/L={{ item.city|default('') }}/O={{ item.organization|default('') }}/OU={{ item.unit|default('') }}/{% if item.domains is defined %}{% for domain in item.domains %}CN={{ domain }}/{% endfor %}{% else %}CN={{ item.name }}/{% endif %}emailAddress={{ item.email|default('') }}" -days {{ item.days|default(3650) }} -keyout {{ openssl_keys_path }}/{{ item.name }}.key -out {{ openssl_certs_path }}/{{ item.name }}.crt -extensions v3_ca 26 | creates={{ openssl_certs_path }}/{{ item.name }}.crt 27 | with_items: openssl_self_signed 28 | tags: 29 | - system 30 | - openssl 31 | - create 32 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/tasks/create_dir.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Checking dir exists 4 | stat: > 5 | path={{ item }} 6 | register: item_stat 7 | 8 | - name: Creating directory 9 | file: > 10 | path={{ item }} 11 | state=directory 12 | owner=root 13 | group=root 14 | mode={{ mode }} 15 | when: not item_stat.stat.exists -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/tasks/install_debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Installing packages 4 | apt: > 5 | pkg={{ item }} 6 | state=present 7 | with_items: 8 | - openssl 9 | tags: 10 | - system 11 | - openssl 12 | - install 13 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/tasks/install_redhat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Installing packages 4 | yum: > 5 | name={{ item }} 6 | state=present 7 | with_items: 8 | - openssl 9 | tags: 10 | - system 11 | - openssl 12 | - install 13 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: install_debian.yml 4 | when: ansible_os_family == 'Debian' 5 | - include: install_redhat.yml 6 | when: ansible_os_family == 'RedHat' 7 | - include: config.yml 8 | - include: create.yml 9 | - include: copy.yml 10 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/templates/etc-ssl-openssl.cnf.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | # 3 | # OpenSSL example configuration file. 4 | # This is mostly being used for generation of certificate requests. 5 | # 6 | 7 | # This definition stops the following lines choking if HOME isn't 8 | # defined. 9 | HOME = . 10 | RANDFILE = $ENV::HOME/.rnd 11 | 12 | # Extra OBJECT IDENTIFIER info: 13 | #oid_file = $ENV::HOME/.oid 14 | oid_section = new_oids 15 | 16 | # To use this configuration file with the "-extfile" option of the 17 | # "openssl x509" utility, name here the section containing the 18 | # X.509v3 extensions to use: 19 | # extensions = 20 | # (Alternatively, use a configuration file that has only 21 | # X.509v3 extensions in its main [= default] section.) 22 | 23 | [ new_oids ] 24 | 25 | # We can add new OIDs in here for use by 'ca', 'req' and 'ts'. 26 | # Add a simple OID like this: 27 | # testoid1=1.2.3.4 28 | # Or use config file substitution like this: 29 | # testoid2=${testoid1}.5.6 30 | 31 | # Policies used by the TSA examples. 32 | tsa_policy1 = 1.2.3.4.1 33 | tsa_policy2 = 1.2.3.4.5.6 34 | tsa_policy3 = 1.2.3.4.5.7 35 | 36 | #################################################################### 37 | [ ca ] 38 | default_ca = CA_default # The default ca section 39 | 40 | #################################################################### 41 | [ CA_default ] 42 | 43 | dir = ./demoCA # Where everything is kept 44 | certs = $dir/certs # Where the issued certs are kept 45 | crl_dir = $dir/crl # Where the issued crl are kept 46 | database = $dir/index.txt # database index file. 47 | #unique_subject = no # Set to 'no' to allow creation of 48 | # several ctificates with same subject. 49 | new_certs_dir = $dir/newcerts # default place for new certs. 50 | 51 | certificate = $dir/cacert.pem # The CA certificate 52 | serial = $dir/serial # The current serial number 53 | crlnumber = $dir/crlnumber # the current crl number 54 | # must be commented out to leave a V1 CRL 55 | crl = $dir/crl.pem # The current CRL 56 | private_key = $dir/private/cakey.pem# The private key 57 | RANDFILE = $dir/private/.rand # private random number file 58 | 59 | x509_extensions = usr_cert # The extentions to add to the cert 60 | 61 | # Comment out the following two lines for the "traditional" 62 | # (and highly broken) format. 63 | name_opt = ca_default # Subject Name options 64 | cert_opt = ca_default # Certificate field options 65 | 66 | # Extension copying option: use with caution. 67 | # copy_extensions = copy 68 | 69 | # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs 70 | # so this is commented out by default to leave a V1 CRL. 71 | # crlnumber must also be commented out to leave a V1 CRL. 72 | # crl_extensions = crl_ext 73 | 74 | default_days = 365 # how long to certify for 75 | default_crl_days= 30 # how long before next CRL 76 | default_md = default # use public key default MD 77 | preserve = no # keep passed DN ordering 78 | 79 | # A few difference way of specifying how similar the request should look 80 | # For type CA, the listed attributes must be the same, and the optional 81 | # and supplied fields are just that :-) 82 | policy = policy_match 83 | 84 | # For the CA policy 85 | [ policy_match ] 86 | countryName = match 87 | stateOrProvinceName = match 88 | organizationName = match 89 | organizationalUnitName = optional 90 | commonName = supplied 91 | emailAddress = optional 92 | 93 | # For the 'anything' policy 94 | # At this point in time, you must list all acceptable 'object' 95 | # types. 96 | [ policy_anything ] 97 | countryName = optional 98 | stateOrProvinceName = optional 99 | localityName = optional 100 | organizationName = optional 101 | organizationalUnitName = optional 102 | commonName = supplied 103 | emailAddress = optional 104 | 105 | #################################################################### 106 | [ req ] 107 | default_bits = {{ openssl_config.default_bits|default(2048) }} 108 | default_keyfile = privkey.pem 109 | distinguished_name = req_distinguished_name 110 | attributes = req_attributes 111 | x509_extensions = v3_ca # The extentions to add to the self signed cert 112 | 113 | # Passwords for private keys if not present they will be prompted for 114 | # input_password = secret 115 | # output_password = secret 116 | 117 | # This sets a mask for permitted string types. There are several options. 118 | # default: PrintableString, T61String, BMPString. 119 | # pkix : PrintableString, BMPString (PKIX recommendation before 2004) 120 | # utf8only: only UTF8Strings (PKIX recommendation after 2004). 121 | # nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). 122 | # MASK:XXXX a literal mask value. 123 | # WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. 124 | string_mask = utf8only 125 | 126 | # req_extensions = v3_req # The extensions to add to a certificate request 127 | 128 | [ req_distinguished_name ] 129 | countryName = Country Name (2 letter code) 130 | countryName_default = {{ openssl_config.countryName_default|default('AU') }} 131 | countryName_min = 2 132 | countryName_max = 2 133 | 134 | stateOrProvinceName = State or Province Name (full name) 135 | stateOrProvinceName_default = {{ openssl_config.stateOrProvinceName_default|default('Some-State') }} 136 | 137 | localityName = Locality Name (eg, city) 138 | localityName_default = {{ openssl_config.localityName_default|default('') }} 139 | 140 | 0.organizationName = Organization Name (eg, company) 141 | 0.organizationName_default = {{ openssl_config.organizationName_default|default('Internet Widgits Pty Ltd') }} 142 | 143 | # we can do this but it is not needed normally :-) 144 | #1.organizationName = Second Organization Name (eg, company) 145 | #1.organizationName_default = World Wide Web Pty Ltd 146 | 147 | organizationalUnitName = Organizational Unit Name (eg, section) 148 | organizationalUnitName_default = {{ openssl_config.organizationalUnitName_default|default('') }} 149 | 150 | commonName = Common Name (e.g. server FQDN or YOUR name) 151 | commonName_default = {{ openssl_config.commonName_default|default('') }} 152 | commonName_max = 64 153 | 154 | emailAddress = Email Address 155 | emailAddress_max = 64 156 | 157 | # SET-ex3 = SET extension number 3 158 | 159 | [ req_attributes ] 160 | challengePassword = A challenge password 161 | challengePassword_min = 4 162 | challengePassword_max = 20 163 | 164 | unstructuredName = An optional company name 165 | 166 | [ usr_cert ] 167 | 168 | # These extensions are added when 'ca' signs a request. 169 | 170 | # This goes against PKIX guidelines but some CAs do it and some software 171 | # requires this to avoid interpreting an end user certificate as a CA. 172 | 173 | basicConstraints=CA:FALSE 174 | 175 | # Here are some examples of the usage of nsCertType. If it is omitted 176 | # the certificate can be used for anything *except* object signing. 177 | 178 | # This is OK for an SSL server. 179 | # nsCertType = server 180 | 181 | # For an object signing certificate this would be used. 182 | # nsCertType = objsign 183 | 184 | # For normal client use this is typical 185 | # nsCertType = client, email 186 | 187 | # and for everything including object signing: 188 | # nsCertType = client, email, objsign 189 | 190 | # This is typical in keyUsage for a client certificate. 191 | # keyUsage = nonRepudiation, digitalSignature, keyEncipherment 192 | 193 | # This will be displayed in Netscape's comment listbox. 194 | nsComment = "OpenSSL Generated Certificate" 195 | 196 | # PKIX recommendations harmless if included in all certificates. 197 | subjectKeyIdentifier=hash 198 | authorityKeyIdentifier=keyid,issuer 199 | 200 | # This stuff is for subjectAltName and issuerAltname. 201 | # Import the email address. 202 | # subjectAltName=email:copy 203 | # An alternative to produce certificates that aren't 204 | # deprecated according to PKIX. 205 | # subjectAltName=email:move 206 | 207 | # Copy subject details 208 | # issuerAltName=issuer:copy 209 | 210 | #nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem 211 | #nsBaseUrl 212 | #nsRevocationUrl 213 | #nsRenewalUrl 214 | #nsCaPolicyUrl 215 | #nsSslServerName 216 | 217 | # This is required for TSA certificates. 218 | # extendedKeyUsage = critical,timeStamping 219 | 220 | [ v3_req ] 221 | 222 | # Extensions to add to a certificate request 223 | 224 | basicConstraints = CA:FALSE 225 | keyUsage = nonRepudiation, digitalSignature, keyEncipherment 226 | 227 | [ v3_ca ] 228 | 229 | 230 | # Extensions for a typical CA 231 | 232 | 233 | # PKIX recommendation. 234 | 235 | subjectKeyIdentifier=hash 236 | 237 | authorityKeyIdentifier=keyid:always,issuer 238 | 239 | # This is what PKIX recommends but some broken software chokes on critical 240 | # extensions. 241 | #basicConstraints = critical,CA:true 242 | # So we do this instead. 243 | basicConstraints = CA:true 244 | 245 | # Key usage: this is typical for a CA certificate. However since it will 246 | # prevent it being used as an test self-signed certificate it is best 247 | # left out by default. 248 | # keyUsage = cRLSign, keyCertSign 249 | 250 | # Some might want this also 251 | # nsCertType = sslCA, emailCA 252 | 253 | # Include email address in subject alt name: another PKIX recommendation 254 | # subjectAltName=email:copy 255 | # Copy issuer details 256 | # issuerAltName=issuer:copy 257 | 258 | # DER hex encoding of an extension: beware experts only! 259 | # obj=DER:02:03 260 | # Where 'obj' is a standard or added object 261 | # You can even override a supported extension: 262 | # basicConstraints= critical, DER:30:03:01:01:FF 263 | 264 | [ crl_ext ] 265 | 266 | # CRL extensions. 267 | # Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. 268 | 269 | # issuerAltName=issuer:copy 270 | authorityKeyIdentifier=keyid:always 271 | 272 | [ proxy_cert_ext ] 273 | # These extensions should be added when creating a proxy certificate 274 | 275 | # This goes against PKIX guidelines but some CAs do it and some software 276 | # requires this to avoid interpreting an end user certificate as a CA. 277 | 278 | basicConstraints=CA:FALSE 279 | 280 | # Here are some examples of the usage of nsCertType. If it is omitted 281 | # the certificate can be used for anything *except* object signing. 282 | 283 | # This is OK for an SSL server. 284 | # nsCertType = server 285 | 286 | # For an object signing certificate this would be used. 287 | # nsCertType = objsign 288 | 289 | # For normal client use this is typical 290 | # nsCertType = client, email 291 | 292 | # and for everything including object signing: 293 | # nsCertType = client, email, objsign 294 | 295 | # This is typical in keyUsage for a client certificate. 296 | # keyUsage = nonRepudiation, digitalSignature, keyEncipherment 297 | 298 | # This will be displayed in Netscape's comment listbox. 299 | nsComment = "OpenSSL Generated Certificate" 300 | 301 | # PKIX recommendations harmless if included in all certificates. 302 | subjectKeyIdentifier=hash 303 | authorityKeyIdentifier=keyid,issuer 304 | 305 | # This stuff is for subjectAltName and issuerAltname. 306 | # Import the email address. 307 | # subjectAltName=email:copy 308 | # An alternative to produce certificates that aren't 309 | # deprecated according to PKIX. 310 | # subjectAltName=email:move 311 | 312 | # Copy subject details 313 | # issuerAltName=issuer:copy 314 | 315 | #nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem 316 | #nsBaseUrl 317 | #nsRevocationUrl 318 | #nsRenewalUrl 319 | #nsCaPolicyUrl 320 | #nsSslServerName 321 | 322 | # This really needs to be in place for it to be a proxy certificate. 323 | proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo 324 | 325 | #################################################################### 326 | [ tsa ] 327 | 328 | default_tsa = tsa_config1 # the default TSA section 329 | 330 | [ tsa_config1 ] 331 | 332 | # These are used by the TSA reply generation only. 333 | dir = ./demoCA # TSA root directory 334 | serial = $dir/tsaserial # The current serial number (mandatory) 335 | crypto_device = builtin # OpenSSL engine to use for signing 336 | signer_cert = $dir/tsacert.pem # The TSA signing certificate 337 | # (optional) 338 | certs = $dir/cacert.pem # Certificate chain to include in reply 339 | # (optional) 340 | signer_key = $dir/private/tsakey.pem # The TSA private key (optional) 341 | 342 | default_policy = tsa_policy1 # Policy if request did not specify it 343 | # (optional) 344 | other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional) 345 | digests = md5, sha1 # Acceptable message digests (mandatory) 346 | accuracy = secs:1, millisecs:500, microsecs:100 # (optional) 347 | clock_precision_digits = 0 # number of digits after dot. (optional) 348 | ordering = yes # Is ordering defined for timestamps? 349 | # (optional, default: no) 350 | tsa_name = yes # Must the TSA name be included in the reply? 351 | # (optional, default: no) 352 | ess_cert_id_chain = no # Must the ESS cert id chain be included? 353 | # (optional, default: no) 354 | -------------------------------------------------------------------------------- /ansible/roles/franklinkim.openssl/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | roles: 5 | - franklinkim.openssl 6 | vars: 7 | openssl_keys: 8 | - { name: foobar.com, key: "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDhSsYh36iAShzd\nNM0dSxiVXFe3WCZbePTQSNQ0hnFyBF1AfQKzpo9kFP3h+/IxzUNcPREAqOjmIfl4\ndVTXicyqVrqwt1su90+DitRmvYU0e4PDAA9pwQAxdT1qGBnzBFMgs/JpwQNQetCz\nzISDYn0QbaBGLXs6+UkDGyKu8LCX/T0vOLQ/LecDleZrXf6ubqK7H9SGtGsPLlDw\nonAe+KKieDYJlfHX9omaC953fp8aKDA7V5g/3KbkhsERDl6b/++fNjlestgnZMms\nYdDsM6MzBlt+3f0YQQXzVsmO8LGJxLMSMEmmg76e1VegPq+FyjMQp8r+8i2y/Tvz\nadL0bnivAgMBAAECggEBAKhbp4rCx/nu6HkKL0n3x4w+cLJrpmZvEovgEOybl4V7\n62/4u58jFj7VTRCmpcw/t1njrKQQldL8iqBRFjDoIlEc9PCAZRzI5dvIUIfikvuw\nXbvIfLwr5YgQM+/nyOSJU9G5h6st+NsYnIPwjwpb/FfdhItNC6z7g2tVyOpwpZc9\n2WwJadASIew3GOSd3gLoZLiO+r6XdPc//VcAxaNhu1B5RMHpQxeKa7KQ9T3CzCj4\nTBvIxV5LKAiGMlE26WZR7X2xkLzWswCsk8SAv9ulqbuKlSoPMh86BadM5H6SeGuP\ncsTcTGgoAmhbNmUN/j3lOjHJed7oUKEQGVgGIh4W1OkCgYEA+ECUtXl/sQzUiAYz\nKy556wb31v31D+tVftYU5BzwB/YO7T1ApY1/Bzs/KbnXiKu3eb3IyfEVe/CTcyE9\nhTrJJr5b6Nesa4n0PMpxHfZbWloGoewyfVl7Dgu6/KFctKFm17QcFSG7NsGraE6L\nBQ80gWo94Fyt1nXN9+myUeKga5sCgYEA6FLAgUFS7ykFA0bh5MLV1Q9IZav86Hky\nOmgM1ysd/B9ObRAxKaQezvK+4uyaUW55d8pQZJE2YQo84KPX1wFiAPkR5dwm/C1J\nuH9fz5OycXTUS0LJYGFLmeyKSQ4N+V+8Ex5laFqhHXE8Rzpi/QbYuf4V2EDPlY4g\n6kQgtzS/qn0CgYAQfDlj062nFDMI1WCQfYWbFdtfa33akMYcphq9Cy7lWHGlT2v7\nkmndERIgszac3MpSS0gKIPhMQq2H960eK8kvyXRRAgFxIrgVUVwxoSpv1YqbNhQk\nPsztIdpI7G47kHxD1rIGtTa5bCL1ykFxFJFoBqYVQBJLK4eB7wLobSQ6AQKBgEiB\n+z7cCmxGGyBosPvaqy4x9OB2ixprKPf9nXRSKquTgcCcOxvJ8yuXq2fbfFZJ6nMu\nm2SnxZcHwPRDbovWDKZNFf7tdOVjpQyGBHsel6S9V7ydfYgtFZFWt9oRHt9jt6kn\n5XJqRrqPqsZ4PIjH6EA0QtEZeTAuCavT03oaZm9pAoGBAPVuxRWNqfF7fWbLZiHG\nq3ykwooYtbSfixRe2y/h7IHrQyCbAEG/V2FBPKTNhh0zwHpRTS4PFRL3h+ZQNYrr\n/n+zN/OJl/75P53NDlZ5n1m1eYPMbVjDvvTDDdWqkESLUvTRT7JnyiXApRY0EWTA\nArNAJBxDBD66sa5BM9hZV9fG\n-----END PRIVATE KEY-----\n" } 9 | openssl_certs: 10 | - { name: foobar.com, cert: "-----BEGIN CERTIFICATE-----\nMIIDuTCCAqGgAwIBAgIJAO7EaRwLzPYyMA0GCSqGSIb3DQEBCwUAMHMxCzAJBgNV\nBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gxEDAOBgNV\nBAoMB0ZvbyBCYXIxEzARBgNVBAMMCmZvb2Jhci5jb20xGjAYBgkqhkiG9w0BCQEW\nC2Zvb0BiYXIuY29tMB4XDTE0MDgwMjE1NTMxNloXDTI0MDczMDE1NTMxNlowczEL\nMAkGA1UEBhMCREUxEDAOBgNVBAgMB0JhdmFyaWExDzANBgNVBAcMBk11bmljaDEQ\nMA4GA1UECgwHRm9vIEJhcjETMBEGA1UEAwwKZm9vYmFyLmNvbTEaMBgGCSqGSIb3\nDQEJARYLZm9vQGJhci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\nAQDhSsYh36iAShzdNM0dSxiVXFe3WCZbePTQSNQ0hnFyBF1AfQKzpo9kFP3h+/Ix\nzUNcPREAqOjmIfl4dVTXicyqVrqwt1su90+DitRmvYU0e4PDAA9pwQAxdT1qGBnz\nBFMgs/JpwQNQetCzzISDYn0QbaBGLXs6+UkDGyKu8LCX/T0vOLQ/LecDleZrXf6u\nbqK7H9SGtGsPLlDwonAe+KKieDYJlfHX9omaC953fp8aKDA7V5g/3KbkhsERDl6b\n/++fNjlestgnZMmsYdDsM6MzBlt+3f0YQQXzVsmO8LGJxLMSMEmmg76e1VegPq+F\nyjMQp8r+8i2y/TvzadL0bnivAgMBAAGjUDBOMB0GA1UdDgQWBBTMI1BoL1dh9tov\nQxJHM6GnZfBhMTAfBgNVHSMEGDAWgBTMI1BoL1dh9tovQxJHM6GnZfBhMTAMBgNV\nHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQALezxaXABZEQE6RDmtfBE7jdGy\nxWJVLxSoH0+YNNVXDYNCwNdDMBbjcH6B//aaGLc6Zqif7+HlRfmr4SVfjIP8UQZR\nSQ2s/tcftR6Wp2aadIdUZZkIvmaWvyFfBrrm8F6Ot22Y8EIgjSl/y4kewM6qD1MY\nxC7qAwze2k0yPqVdAXFYJh/+thRTV4YA9R8OCVVRO4xoEOGsTOsHQYH7+/lR3U+o\nbmBu+k1pPK+LYCoQyIrIB6xHqRYf4nHirxlbu4+aAY1Rc57Okbk68g6ThA27r8Ay\n/14Fu1Ry6NAq/1zeSzX4JrFQOlZDNtqF0UXgph2RehMZjtQG2b4B8gLpwPRe\n-----END CERTIFICATE-----\n" } 11 | openssl_self_signed: 12 | - { name: 'foobar.org', country: 'DE', state: 'Bavaria', city: 'Munich', organization: 'Foo Bar', unit: '', email: 'foo@bar.com', days: 3650 } 13 | - { name: '*.foobar.org', domains: ['foobar.org', '*.foobar.org'], country: 'DE', state: 'Bavaria', city: 'Munich', organization: 'Foo Bar', unit: '', email: 'foo@bar.com', days: 3650 } 14 | openssl_keys_path: /etc/my-ssl/private 15 | openssl_certs_path: /etc/my-ssl/certs 16 | openssl_config: 17 | default_bits: 2048 18 | countryName_default: DE 19 | stateOrProvinceName_default: Bavaria 20 | localityName_default: Munich 21 | organizationName_default: 'My Organization' 22 | organizationalUnitName_default: 'My Organization Unit' 23 | commonName_default: 'foobar.com' -------------------------------------------------------------------------------- /ansible/vagrant_docker_host.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: vagrant_dockerhosts 4 | sudo: False 5 | remote_user: "{{ user }}" 6 | vars: 7 | swarm_discovery: consul 8 | swarm_discovery_string: "consul://{{ consul_host }}/swarm" 9 | roles: 10 | - role: base 11 | - role: docker 12 | tasks: 13 | - name: Pull images 14 | sudo: True 15 | command: > 16 | docker pull {{ item }}:latest 17 | with_items: docker_images 18 | 19 | -------------------------------------------------------------------------------- /ansible/vagrant_docker_proxy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: vagrant_dockerproxy 4 | sudo: False 5 | remote_user: "{{ user }}" 6 | roles: 7 | - role: base 8 | - role: consul_template 9 | -------------------------------------------------------------------------------- /ansible/vagrant_docker_swarm.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: vagrant_dockerswarm 4 | sudo: true 5 | remote_user: "{{ user }}" 6 | vars: 7 | consul_is_ui: true 8 | consul_is_server: true 9 | consul_datacenter: "test" 10 | consul_bootstrap: true 11 | consul_node_name: "vagrant" 12 | consul_bind_address: "{{ ansible_default_ipv4['address'] }}" 13 | nginx_remove_default: true 14 | swarm_discovery: consul 15 | swarm_discovery_string: "consul://{{ consul_host }}/swarm" 16 | 17 | roles: 18 | - role: base 19 | - role: franklinkim.consul 20 | - role: docker 21 | - role: docker_swarm 22 | -------------------------------------------------------------------------------- /bin/env: -------------------------------------------------------------------------------- 1 | export DOCKER_HOST=tcp://dockerswarm01:2375 2 | unset DOCKER_TLS_VERIFY 3 | -------------------------------------------------------------------------------- /bin/env_tls: -------------------------------------------------------------------------------- 1 | export DOCKER_HOST=tcp://dockerswarm01:2376 2 | export DOCKER_CERT_PATH="`pwd`/tls" 3 | export DOCKER_TLS_VERIFY=1 4 | -------------------------------------------------------------------------------- /bin/gen_ssl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # http://apetec.com/support/GenerateSAN-CSR.htm 3 | # https://rtcamp.com/wordpress-nginx/tutorials/ssl/multidomain-ssl-subject-alternative-names/ 4 | # http://wiki.samat.org/CheatSheet/OpenSSL 5 | 6 | rm -rf tls/*.pem || mkdir -p tls 7 | rm -rf tls/*.srl 8 | 9 | cd tls 10 | 11 | echo 'Creating CA (ca-key.pem, ca.pem)' 12 | echo 01 > ca.srl 13 | openssl genrsa -des3 -passout pass:password -out ca-key.pem 2048 14 | openssl req -new -passin pass:password \ 15 | -subj '/CN=Non-Prod Test CA/C=US' \ 16 | -x509 -days 365 -key ca-key.pem -out ca.pem 17 | 18 | 19 | echo 'Creating Swarm certificates (swarm-key.pem, swarm-cert.pem)' 20 | openssl genrsa -des3 -passout pass:password -out swarm-key.pem 2048 21 | openssl req -passin pass:password -subj '/CN=dockerswarm01' -new -key swarm-key.pem -out swarm-client.csr 22 | echo 'extendedKeyUsage = clientAuth,serverAuth' > extfile.cnf 23 | openssl x509 -passin pass:password -req -days 365 -in swarm-client.csr -CA ca.pem -CAkey ca-key.pem -out swarm-cert.pem -extfile extfile.cnf 24 | openssl rsa -passin pass:password -in swarm-key.pem -out swarm-key.pem 25 | 26 | # Set the default keys to be Swarm 27 | cp -rp swarm-key.pem key.pem 28 | cp -rp swarm-cert.pem cert.pem 29 | 30 | echo 'Creating host certificates (dockerhost01-3-key.pem, dockerhost01-3-cert.pem)' 31 | openssl genrsa -passout pass:password -des3 -out dockerhost01-key.pem 2048 32 | openssl req -passin pass:password -subj '/CN=dockerhost01' -new -key dockerhost01-key.pem -out dockerhost01.csr 33 | openssl x509 -passin pass:password -req -days 365 -in dockerhost01.csr -CA ca.pem -CAkey ca-key.pem -out dockerhost01-cert.pem -extfile openssl.cnf 34 | openssl rsa -passin pass:password -in dockerhost01-key.pem -out dockerhost01-key.pem 35 | 36 | openssl genrsa -passout pass:password -des3 -out dockerhost02-key.pem 2048 37 | openssl req -passin pass:password -subj '/CN=dockerhost02' -new -key dockerhost02-key.pem -out dockerhost02.csr 38 | openssl x509 -passin pass:password -req -days 365 -in dockerhost02.csr -CA ca.pem -CAkey ca-key.pem -out dockerhost02-cert.pem -extfile openssl.cnf 39 | openssl rsa -passin pass:password -in dockerhost02-key.pem -out dockerhost02-key.pem 40 | 41 | openssl genrsa -passout pass:password -des3 -out dockerhost03-key.pem 2048 42 | openssl req -passin pass:password -subj '/CN=dockerhost03' -new -key dockerhost03-key.pem -out dockerhost03.csr 43 | openssl x509 -passin pass:password -req -days 365 -in dockerhost03.csr -CA ca.pem -CAkey ca-key.pem -out dockerhost03-cert.pem -extfile openssl.cnf 44 | openssl rsa -passin pass:password -in dockerhost03-key.pem -out dockerhost03-key.pem 45 | 46 | rm -f *.csr 47 | 48 | rm -rf ../ansible/roles/docker/files/tls 49 | mkdir -p ../ansible/roles/docker/files/tls 50 | mv docker* ../ansible/roles/docker/files/tls/ 51 | cp -rp ca.pem ../ansible/roles/docker/files/tls/ 52 | 53 | rm -rf ../ansible/roles/docker_swarm/files/tls 54 | mkdir -p ../ansible/roles/docker_swarm/files/tls 55 | mv swarm* ../ansible/roles/docker_swarm/files/tls/ 56 | cp -rp ca.pem ../ansible/roles/docker_swarm/files/tls/ 57 | -------------------------------------------------------------------------------- /bin/pull_images_tls.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export DOCKER_CERT_PATH="`pwd`/tls" 3 | export DOCKER_TLS_VERIFY=1 4 | 5 | docker -H tcp://dockerhost01:2376 pull ubuntu:latest & 6 | docker -H tcp://dockerhost02:2376 pull ubuntu:latest & 7 | docker -H tcp://dockerhost03:2376 pull ubuntu:latest 8 | 9 | docker -H tcp://dockerhost01:2376 pull nginx:latest & 10 | docker -H tcp://dockerhost02:2376 pull nginx:latest & 11 | docker -H tcp://dockerhost03:2376 pull nginx:latest 12 | -------------------------------------------------------------------------------- /bin/start_containers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker run -d \ 4 | -p 80 \ 5 | -e constraint:zone=internal \ 6 | -e constraint:disk=ssd \ 7 | -t nginx:latest 8 | 9 | docker run -d \ 10 | -p 80 \ 11 | -e constraint:zone=external \ 12 | -e constraint:disk=ssd \ 13 | -t nginx:latest 14 | -------------------------------------------------------------------------------- /tls/openssl.cnf: -------------------------------------------------------------------------------- 1 | # 2 | # OpenSSL example configuration file. 3 | # This is mostly being used for generation of certificate requests. 4 | # 5 | 6 | # This definition stops the following lines choking if HOME isn't 7 | # defined. 8 | HOME = . 9 | RANDFILE = $ENV::HOME/.rnd 10 | oid_section = new_oids 11 | extensions = v3_req 12 | 13 | [ new_oids ] 14 | tsa_policy1 = 1.2.3.4.1 15 | tsa_policy2 = 1.2.3.4.5.6 16 | tsa_policy3 = 1.2.3.4.5.7 17 | 18 | #################################################################### 19 | [ ca ] 20 | default_ca = CA_default # The default ca section 21 | 22 | #################################################################### 23 | [ CA_default ] 24 | dir = ./tls # Where everything is kept 25 | certs = $dir/certs # Where the issued certs are kept 26 | crl_dir = $dir/crl # Where the issued crl are kept 27 | database = $dir/index.txt # database index file. 28 | new_certs_dir = $dir/newcerts # default place for new certs. 29 | certificate = $dir/cacert.pem # The CA certificate 30 | serial = $dir/serial # The current serial number 31 | crlnumber = $dir/crlnumber 32 | crl = $dir/crl.pem # The current CRL 33 | private_key = $dir/private/cakey.pem# The private key 34 | RANDFILE = $dir/private/.rand # private random number file 35 | x509_extensions = usr_cert # The extentions to add to the cert 36 | name_opt = ca_default # Subject Name options 37 | cert_opt = ca_default # Certificate field options 38 | default_days = 365 # how long to certify for 39 | default_crl_days= 30 # how long before next CRL 40 | default_md = default # use public key default MD 41 | preserve = no # keep passed DN ordering 42 | policy = policy_match 43 | 44 | [ policy_match ] 45 | countryName = match 46 | stateOrProvinceName = match 47 | organizationName = match 48 | organizationalUnitName = optional 49 | commonName = supplied 50 | emailAddress = optional 51 | 52 | [ policy_anything ] 53 | countryName = optional 54 | stateOrProvinceName = optional 55 | localityName = optional 56 | organizationName = optional 57 | organizationalUnitName = optional 58 | commonName = supplied 59 | emailAddress = optional 60 | 61 | #################################################################### 62 | [ req ] 63 | default_bits = 1024 64 | default_keyfile = privkey.pem 65 | distinguished_name = req_distinguished_name 66 | attributes = req_attributes 67 | x509_extensions = v3_ca # The extentions to add to the self signed cert 68 | string_mask = utf8only 69 | req_extensions = v3_req # The extensions to add to a certificate request 70 | 71 | [ req_distinguished_name ] 72 | countryName = Country Name (2 letter code) 73 | countryName_default = AU 74 | countryName_min = 2 75 | countryName_max = 2 76 | stateOrProvinceName = State or Province Name (full name) 77 | stateOrProvinceName_default = Some-State 78 | localityName = Locality Name (eg, city) 79 | 0.organizationName = Organization Name (eg, company) 80 | 0.organizationName_default = Internet Widgits Pty Ltd 81 | organizationalUnitName = Organizational Unit Name (eg, section) 82 | commonName = Common Name (e.g. server FQDN or YOUR name) 83 | commonName_max = 64 84 | emailAddress = Email Address 85 | emailAddress_max = 64 86 | 87 | [ req_attributes ] 88 | challengePassword = A challenge password 89 | challengePassword_min = 4 90 | challengePassword_max = 20 91 | unstructuredName = An optional company name 92 | 93 | [ usr_cert ] 94 | basicConstraints=CA:FALSE 95 | nsComment = "OpenSSL Generated Certificate" 96 | subjectKeyIdentifier=hash 97 | authorityKeyIdentifier=keyid,issuer 98 | 99 | [ v3_req ] 100 | # Extensions to add to a certificate request 101 | basicConstraints = CA:FALSE 102 | keyUsage = nonRepudiation, digitalSignature, keyEncipherment 103 | subjectAltName = @alt_names 104 | 105 | [ v3_ca ] 106 | subjectAltName = @alt_names 107 | subjectKeyIdentifier=hash 108 | authorityKeyIdentifier=keyid:always,issuer 109 | basicConstraints = CA:true 110 | 111 | [ crl_ext ] 112 | authorityKeyIdentifier=keyid:always 113 | 114 | [ alt_names ] 115 | IP.1 = 10.100.199.200 116 | IP.2 = 10.100.199.201 117 | IP.3 = 10.100.199.202 118 | IP.4 = 10.100.199.203 119 | 120 | --------------------------------------------------------------------------------