├── roles ├── nginx │ ├── .gitignore │ ├── ansible.cfg │ ├── meta │ │ ├── .galaxy_install_info │ │ └── main.yml │ ├── templates │ │ ├── auth_basic.j2 │ │ ├── config.conf.j2 │ │ ├── config_stream.conf.j2 │ │ ├── site.conf.j2 │ │ ├── nginx.repo.j2 │ │ └── nginx.conf.j2 │ ├── test │ │ ├── test.yml │ │ ├── custom_bar.conf.j2 │ │ └── example-vars.yml │ ├── tasks │ │ ├── remove-defaults.yml │ │ ├── ensure-dirs.yml │ │ ├── installation.packages.yml │ │ ├── remove-unwanted.yml │ │ ├── selinux.yml │ │ ├── remove-extras.yml │ │ ├── main.yml │ │ ├── configuration.yml │ │ └── nginx-official-repo.yml │ ├── vars │ │ └── main.yml │ ├── Vagrantfile │ ├── handlers │ │ └── main.yml │ ├── .travis.yml │ ├── defaults │ │ └── main.yml │ └── README.md ├── graphite │ ├── vars │ │ ├── Debian.yml │ │ └── RedHat.yml │ ├── handlers │ │ └── main.yml │ ├── files │ │ └── users.json │ ├── templates │ │ ├── supervisor-graphite.conf.j2 │ │ ├── storage-schemas.conf.j2 │ │ ├── nginx-graphite.conf.j2 │ │ ├── storage-aggregation.conf.j2 │ │ ├── local_settings.py.j2 │ │ └── carbon.conf.j2 │ └── tasks │ │ └── main.yml ├── grafana │ ├── handlers │ │ └── main.yml │ ├── templates │ │ ├── nginx-grafana.conf.j2 │ │ └── grafana.ini.j2 │ └── tasks │ │ └── main.yml ├── statsdaemon │ ├── handlers │ │ └── main.yml │ ├── templates │ │ └── supervisor-statsdaemon.conf.j2 │ └── tasks │ │ └── main.yml ├── postgres │ ├── handlers │ │ └── main.yml │ ├── files │ │ └── pg_hba.conf │ └── tasks │ │ └── main.yml ├── python │ └── tasks │ │ └── main.yml ├── common │ └── tasks │ │ └── main.yml └── supervisor │ ├── files │ ├── supervisor-RedHat │ └── supervisord.conf │ └── tasks │ └── main.yml ├── requirements.yml ├── .gitignore ├── Vagrantfile ├── monitoring.yml ├── LICENSE └── README.md /roles/nginx/.gitignore: -------------------------------------------------------------------------------- 1 | ### Vagrant ### 2 | .vagrant/ -------------------------------------------------------------------------------- /requirements.yml: -------------------------------------------------------------------------------- 1 | - src: jdauphant.nginx 2 | name: nginx 3 | -------------------------------------------------------------------------------- /roles/nginx/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | roles_path = ../ 3 | -------------------------------------------------------------------------------- /roles/graphite/vars/Debian.yml: -------------------------------------------------------------------------------- 1 | nginx_user: www-data 2 | nginx_group: www-data -------------------------------------------------------------------------------- /roles/graphite/vars/RedHat.yml: -------------------------------------------------------------------------------- 1 | nginx_user: nginx 2 | nginx_group: nginx 3 | -------------------------------------------------------------------------------- /roles/grafana/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart nginx 2 | action: service name=nginx state=restarted -------------------------------------------------------------------------------- /roles/nginx/meta/.galaxy_install_info: -------------------------------------------------------------------------------- 1 | {install_date: 'Thu Feb 16 22:45:05 2017', version: v2.7.4} 2 | -------------------------------------------------------------------------------- /roles/statsdaemon/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: reload supervisor 2 | shell: supervisorctl reload 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Vagrant ### 2 | .vagrant/ 3 | vagrant_ansible_inventory* 4 | 5 | ### Ansible ### 6 | *.retry -------------------------------------------------------------------------------- /roles/postgres/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart postgresql 2 | service: name=postgresql state=restarted enabled=yes -------------------------------------------------------------------------------- /roles/nginx/templates/auth_basic.j2: -------------------------------------------------------------------------------- 1 | #{{ ansible_managed }} 2 | 3 | {% for v in item.value %} 4 | {{ v }} 5 | {% endfor %} 6 | -------------------------------------------------------------------------------- /roles/graphite/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: reload supervisor 2 | shell: supervisorctl reload 3 | 4 | - name: restart nginx 5 | action: service name=nginx state=restarted -------------------------------------------------------------------------------- /roles/nginx/test/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: "{{hosts_group|default('all')}}" 3 | vars_files: 4 | - 'example-vars.yml' 5 | roles: 6 | - "{{role_name|default('nginx')}}" -------------------------------------------------------------------------------- /roles/nginx/test/custom_bar.conf.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | upstream backend { 3 | server 10.0.0.101; 4 | } 5 | server { 6 | server_name {{ item.value.server_name }}; 7 | location / { 8 | proxy_pass http://backend; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /roles/statsdaemon/templates/supervisor-statsdaemon.conf.j2: -------------------------------------------------------------------------------- 1 | [program:statsdaemon] 2 | command=/opt/statsdaemon/statsdaemon-0.7.1.linux-amd64.go1.4.2/statsdaemon 3 | process_name=%(program_name)s 4 | autostart=true 5 | autorestart=true 6 | stopsignal=QUIT 7 | -------------------------------------------------------------------------------- /roles/nginx/templates/config.conf.j2: -------------------------------------------------------------------------------- 1 | #{{ ansible_managed }} 2 | 3 | {% for v in item.value %} 4 | {% if v.find('\n') != -1 %} 5 | {{v}} 6 | {% else %} 7 | {% if v != "" %}{{ v.replace(";",";\n ").replace(" {"," {\n ").replace(" }"," \n}\n") }}{% if v.find('{') == -1%}; 8 | {% endif %}{% endif %}{% endif %} 9 | {% endfor %} 10 | -------------------------------------------------------------------------------- /roles/nginx/templates/config_stream.conf.j2: -------------------------------------------------------------------------------- 1 | #{{ ansible_managed }} 2 | 3 | {% for v in item.value %} 4 | {% if v.find('\n') != -1 %} 5 | {{v}} 6 | {% else %} 7 | {% if v != "" %}{{ v.replace(";",";\n ").replace(" {"," {\n ").replace(" }"," \n}\n") }}{% if v.find('{') == -1%}; 8 | {% endif %}{% endif %}{% endif %} 9 | {% endfor %} 10 | -------------------------------------------------------------------------------- /roles/nginx/templates/site.conf.j2: -------------------------------------------------------------------------------- 1 | #{{ ansible_managed }} 2 | 3 | server { 4 | {% for v in item.value %} 5 | {% if v.find('\n') != -1 %} 6 | {{v.replace("\n","\n ")}} 7 | {% else %} 8 | {% if v != "" %}{{ v.replace(";",";\n ").replace(" {"," {\n ").replace(" }"," \n }\n") }}{% if v.find('{') == -1%}; 9 | {% endif %}{% endif %}{% endif %} 10 | {% endfor %} 11 | } 12 | -------------------------------------------------------------------------------- /roles/postgres/files/pg_hba.conf: -------------------------------------------------------------------------------- 1 | # TYPE DATABASE USER CIDR-ADDRESS METHOD 2 | 3 | local all postgres trust 4 | 5 | local all all trust 6 | 7 | host all all 127.0.0.1/32 md5 8 | 9 | host all all ::1/128 md5 10 | 11 | host all all 0.0.0.0/0 md5 -------------------------------------------------------------------------------- /roles/nginx/tasks/remove-defaults.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Disable the default site 3 | file: 4 | path: "{{nginx_conf_dir}}/sites-enabled/default" 5 | state: absent 6 | notify: 7 | - reload nginx 8 | 9 | - name: Remove the default configuration 10 | file: 11 | path: "{{nginx_conf_dir}}/conf.d/default.conf" 12 | state: absent 13 | when: > 14 | 'default' not in nginx_configs.keys() 15 | notify: 16 | - reload nginx 17 | -------------------------------------------------------------------------------- /roles/nginx/templates/nginx.repo.j2: -------------------------------------------------------------------------------- 1 | [nginx] 2 | name=nginx repo 3 | {% if nginx_official_repo_mainline %} 4 | baseurl=http://nginx.org/packages/mainline/{{"rhel" if ansible_distribution == "RedHat" else "centos"}}/{{ansible_distribution_version.split('.')[0]}}/{{ansible_architecture}}/ 5 | {% else %} 6 | baseurl=http://nginx.org/packages/{{"rhel" if ansible_distribution == "RedHat" else "centos"}}/{{ansible_distribution_version.split('.')[0]}}/{{ansible_architecture}}/ 7 | {% endif %} 8 | enabled=1 9 | -------------------------------------------------------------------------------- /roles/nginx/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | nginx_env: 4 | RUNLEVEL: 1 5 | 6 | nginx_installation_types_using_service: ["packages", "configuration-only"] 7 | 8 | nginx_is_el: "{{ ansible_distribution in ['RedHat', 'CentOS'] }}" 9 | 10 | nginx_http_default_params: 11 | - sendfile "on" 12 | - tcp_nopush "on" 13 | - tcp_nodelay "on" 14 | - keepalive_timeout "65" 15 | - access_log "{{nginx_log_dir}}/access.log" 16 | - "error_log {{nginx_log_dir}}/error.log {{nginx_error_log_level}}" 17 | - server_tokens off 18 | - types_hash_max_size 2048 19 | -------------------------------------------------------------------------------- /roles/nginx/tasks/ensure-dirs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create the directories for site specific configurations 3 | file: 4 | path: "{{nginx_conf_dir}}/{{ item }}" 5 | state: directory 6 | owner: root 7 | group: "{{nginx_group}}" 8 | mode: 0755 9 | with_items: 10 | - "sites-available" 11 | - "sites-enabled" 12 | - "auth_basic" 13 | - "conf.d" 14 | - "conf.d/stream" 15 | 16 | - name: Ensure log directory exist 17 | file: 18 | path: "{{ nginx_log_dir }}" 19 | state: directory 20 | owner: "{{nginx_user}}" 21 | group: "{{nginx_group}}" 22 | mode: 0755 23 | -------------------------------------------------------------------------------- /roles/graphite/files/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "model": "auth.user", 4 | "pk": 2, 5 | "fields": { 6 | "password": "pbkdf2_sha256$24000$lNn2aL7yUOl8$Ty5+rh7GnRKitQ8gr+NutGiBZE9PAKFfY+mjv504m6w=", 7 | "last_login": null, 8 | "is_superuser": true, 9 | "username": "admin", 10 | "first_name": "", 11 | "last_name": "", 12 | "email": "admin@example.com", 13 | "is_staff": true, 14 | "is_active": true, 15 | "date_joined": "2017-02-17T14:20:19.771Z", 16 | "groups": [], 17 | "user_permissions": [] 18 | } 19 | } 20 | ] -------------------------------------------------------------------------------- /roles/graphite/templates/supervisor-graphite.conf.j2: -------------------------------------------------------------------------------- 1 | [program:gunicorn-graphite] 2 | command=/opt/graphite/bin/gunicorn -b 127.0.0.1:8080 -w {{ graphite.workers }} -u {{ nginx_user }} -g {{ nginx_user }} --log-file=/opt/graphite/storage/log/webapp/gunicorn.log --pythonpath /opt/graphite/webapp/ wsgi:application 3 | process_name=%(program_name)s 4 | autostart=true 5 | autorestart=true 6 | stopsignal=QUIT 7 | user={{ nginx_user }} 8 | 9 | [program:carbon-cache] 10 | command=/opt/graphite/bin/python /opt/graphite/bin/carbon-cache.py --debug start 11 | process_name=%(program_name)s 12 | autostart=true 13 | autorestart=true 14 | stopsignal=QUIT -------------------------------------------------------------------------------- /roles/nginx/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: "DAUPHANT Julien" 4 | license: BSD 5 | min_ansible_version: 2.0 6 | platforms: 7 | - name: EL 8 | versions: 9 | - all 10 | - name: Fedora 11 | versions: 12 | - all 13 | - name: opensuse 14 | versions: 15 | - all 16 | - name: Ubuntu 17 | versions: 18 | - all 19 | - name: Debian 20 | versions: 21 | - all 22 | - name: FreeBSD 23 | versions: 24 | - 10.0 25 | - 10.1 26 | - 10.2 27 | - 10.3 28 | - 11.0 29 | categories: 30 | - web 31 | allow_duplicates: yes 32 | dependencies: [] 33 | 34 | -------------------------------------------------------------------------------- /roles/python/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: install python-related packages debian/ubuntu 2 | apt: pkg={{ item }} state=latest 3 | with_items: 4 | - python 5 | - python-dev 6 | - python-setuptools 7 | when: ansible_os_family == "Debian" 8 | 9 | - name: install python-related packages redhat/centos 10 | yum: pkg={{ item }} state=latest 11 | with_items: 12 | - python 13 | - python-devel 14 | - python-setuptools 15 | when: ansible_os_family == "RedHat" 16 | 17 | - name: install pip 18 | easy_install: name=pip 19 | 20 | - name: install virtualenv 21 | pip: name=virtualenv 22 | 23 | - name: upgrade setuptools 24 | pip: name=setuptools 25 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | VAGRANTFILE_API_VERSION = "2" 2 | 3 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 4 | 5 | config.vm.define "monitoring" do |monitoring| 6 | # monitoring.vm.box = "centos/7" 7 | # monitoring.vm.box = "debian/jessie64" 8 | monitoring.vm.box = "ubuntu/xenial64" 9 | monitoring.vm.network :private_network, ip: "172.0.0.10" 10 | 11 | monitoring.vm.provision "ansible_local" do |ansible| 12 | ansible.playbook = "monitoring.yml" 13 | # ansible.raw_arguments = ["-vvv"] 14 | end 15 | end 16 | 17 | config.vm.provider "virtualbox" do |v| 18 | v.customize ["modifyvm", :id, "--memory", "1024"] 19 | end 20 | 21 | end 22 | -------------------------------------------------------------------------------- /roles/graphite/templates/storage-schemas.conf.j2: -------------------------------------------------------------------------------- 1 | # Schema definitions for Whisper files. Entries are scanned in order, 2 | # and first match wins. This file is scanned for changes every 60 seconds. 3 | # 4 | # [name] 5 | # pattern = regex 6 | # retentions = timePerPoint:timeToStore, timePerPoint:timeToStore, ... 7 | 8 | # Carbon's internal metrics. This entry should match what is specified in 9 | # CARBON_METRIC_PREFIX and CARBON_METRIC_INTERVAL settings 10 | [carbon] 11 | pattern = ^carbon\. 12 | retentions = 60s:90d 13 | 14 | [default_1min_for_90day] 15 | pattern = .* 16 | retentions = 60s:90d 17 | 18 | 19 | [statsd] 20 | pattern = ^stats.* 21 | retentions = 10s:6h,1m:7d,10m:5y 22 | -------------------------------------------------------------------------------- /roles/nginx/tasks/installation.packages.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install the epel packages for EL distributions 3 | package: name=epel-release state=present 4 | when: nginx_is_el|bool and nginx_install_epel_repo|bool 5 | 6 | - name: Install the nginx packages from official repo for EL distributions 7 | yum: name={{ item }} state=present enablerepo="nginx" 8 | with_items: "{{ nginx_pkgs }}" 9 | when: nginx_is_el|bool and nginx_official_repo 10 | 11 | - name: Install the nginx packages for all other distributions 12 | package: name={{ item }} state=present 13 | with_items: "{{ nginx_pkgs }}" 14 | environment: "{{ nginx_env }}" 15 | when: not nginx_is_el|bool or not nginx_official_repo 16 | -------------------------------------------------------------------------------- /roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: update apt package cache 2 | apt: update_cache=yes 3 | when: ansible_os_family == "Debian" 4 | 5 | - name: install epel-repo rpm 6 | yum: name=epel-release state=installed 7 | when: ansible_os_family == 'RedHat' 8 | 9 | - name: install common packages debian/ubuntu 10 | apt: pkg={{ item }} state=latest 11 | with_items: 12 | - build-essential 13 | - git 14 | when: ansible_os_family == "Debian" 15 | 16 | - name: install git redhat/centos 17 | yum: name=git state=latest 18 | when: ansible_os_family == "RedHat" 19 | 20 | 21 | - name: install development tools redhat/centos 22 | yum: name='@Development tools' state=present 23 | when: ansible_os_family == "RedHat" -------------------------------------------------------------------------------- /roles/nginx/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! 5 | VAGRANTFILE_API_VERSION = "2" 6 | 7 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 8 | # All Vagrant configuration is done here. The most common configuration 9 | # options are documented and commented below. For a complete reference, 10 | # please see the online documentation at vagrantup.com. 11 | 12 | # Every Vagrant virtual environment requires a box to build off of. 13 | config.vm.box = "ubuntu/trusty64" 14 | 15 | config.vm.provision :ansible do |ansible| 16 | ansible.playbook = "test.yml" 17 | ansible.sudo = true 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /roles/nginx/tasks/remove-unwanted.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Remove unwanted sites 3 | file: 4 | path: "{{nginx_conf_dir}}/{{ item[0] }}/{{ item[1] }}.conf" 5 | state: absent 6 | with_nested: 7 | - [ 'sites-enabled', 'sites-available'] 8 | - "{{ nginx_remove_sites }}" 9 | notify: 10 | - reload nginx 11 | 12 | - name: Remove unwanted conf 13 | file: 14 | path: "{{nginx_conf_dir}}/conf.d/{{ item[1] }}.conf" 15 | state: absent 16 | with_items: "{{ nginx_remove_configs }}" 17 | notify: 18 | - reload nginx 19 | 20 | - name: Remove unwanted auth_basic_files 21 | file: 22 | path: "{{nginx_conf_dir}}/auth_basic/{{ item[1] }}" 23 | state: absent 24 | with_items: "{{ nginx_remove_auth_basic_files }}" 25 | notify: 26 | - reload nginx 27 | -------------------------------------------------------------------------------- /roles/nginx/tasks/selinux.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install the selinux python module 3 | package: name={{ item }} state=present 4 | with_items: 5 | - libselinux-python 6 | - libsemanage-python 7 | when: ansible_os_family == "RedHat" 8 | 9 | - name: Install the selinux python module 10 | package: name={{ item }} state=present 11 | with_items: 12 | - python-selinux 13 | - python-semanage 14 | when: ansible_os_family == "Debian" 15 | 16 | - name: Set SELinux boolean to allow nginx to set rlimit 17 | seboolean: name=httpd_setrlimit state=yes persistent=yes 18 | 19 | - name: Set SELinux boolean to allow nginx to proxy on redhat/centos 20 | seboolean: 21 | name: httpd_can_network_connect 22 | state: yes 23 | persistent: yes 24 | when: ansible_os_family == "RedHat" 25 | -------------------------------------------------------------------------------- /roles/statsdaemon/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Prepare Statsdaemon directory 2 | file: state=directory path=/opt/statsdaemon 3 | 4 | - name: Download Statsdaemon 5 | get_url: 6 | url: https://github.com/bitly/statsdaemon/releases/download/v0.7.1/statsdaemon-0.7.1.linux-amd64.go1.4.2.tar.gz 7 | dest: "/opt/statsdaemon/statsdaemon-0.7.1.linux-amd64.go1.4.2.tar.gz" 8 | 9 | - name: Unpack statsdaemon 10 | unarchive: 11 | src: "/opt/statsdaemon/statsdaemon-0.7.1.linux-amd64.go1.4.2.tar.gz" 12 | dest: "/opt/statsdaemon" 13 | copy: no 14 | creates: "/opt/statsdaemon/statsdaemon-0.7.1.linux-amd64.go1.4.2" 15 | 16 | - name: Copy supervisor configuration for statsd 17 | template: src=supervisor-statsdaemon.conf.j2 dest=/etc/supervisor/conf.d/statsdaemon.conf 18 | notify: 19 | - reload supervisor -------------------------------------------------------------------------------- /roles/grafana/templates/nginx-grafana.conf.j2: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name {{ grafana.vhost }}; 4 | 5 | client_max_body_size 64M; 6 | keepalive_timeout 5; 7 | 8 | location / { 9 | add_header Access-Control-Allow-Origin "*"; 10 | add_header Access-Control-Allow-Methods "GET, OPTIONS"; 11 | add_header Access-Control-Allow-Headers "origin, authorization, accept"; 12 | 13 | proxy_set_header Host $http_host; 14 | proxy_redirect off; 15 | proxy_set_header X-Real-IP $remote_addr; 16 | proxy_set_header X-Scheme $scheme; 17 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 18 | proxy_connect_timeout 10; 19 | proxy_read_timeout 10; 20 | proxy_pass http://localhost:3000/; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /roles/graphite/templates/nginx-graphite.conf.j2: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name {{ graphite.vhost }}; 4 | 5 | client_max_body_size 64M; 6 | keepalive_timeout 5; 7 | 8 | location /static/ { 9 | alias /opt/graphite/static/; 10 | } 11 | 12 | location / { 13 | add_header Access-Control-Allow-Origin "*"; 14 | add_header Access-Control-Allow-Methods "GET, OPTIONS"; 15 | add_header Access-Control-Allow-Headers "origin, authorization, accept"; 16 | 17 | proxy_set_header Host $http_host; 18 | proxy_redirect off; 19 | proxy_set_header X-Real-IP $remote_addr; 20 | proxy_set_header X-Scheme $scheme; 21 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 22 | proxy_connect_timeout 10; 23 | proxy_read_timeout 10; 24 | proxy_pass http://localhost:8080/; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /roles/nginx/tasks/remove-extras.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Find enabled sites 3 | shell: ls -1 {{nginx_conf_dir}}/sites-enabled || true 4 | register: enabled_sites 5 | changed_when: False 6 | 7 | - name: Disable unmanaged sites 8 | file: 9 | path: "{{nginx_conf_dir}}/sites-enabled/{{ item }}" 10 | state: absent 11 | with_items: "{{ enabled_sites.stdout_lines | default([]) }}" 12 | # 'item.conf' => 'item' 13 | when: item[:-5] not in nginx_sites.keys() 14 | notify: 15 | - reload nginx 16 | 17 | - name: Find config files 18 | shell: find {{nginx_conf_dir}}/conf.d -maxdepth 1 -type f -name '*.conf' -exec basename {} \; 19 | register: config_files 20 | changed_when: False 21 | 22 | - name: Remove unmanaged config files 23 | file: 24 | name: "{{nginx_conf_dir}}/conf.d/{{ item }}" 25 | state: absent 26 | with_items: "{{ config_files.stdout_lines | default([]) }}" 27 | # 'item.conf' => 'item' 28 | when: item[:-5] not in nginx_configs.keys() 29 | notify: 30 | - reload nginx 31 | -------------------------------------------------------------------------------- /monitoring.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: False 3 | pre_tasks: 4 | - name: Install python for Ansible 5 | raw: test -e /usr/bin/python || (apt -y update && apt install -y python) || yum install -y python2 6 | register: output 7 | changed_when: output.stdout != "" 8 | - setup: # aka gather_facts 9 | become: True 10 | vars: 11 | graphite: 12 | version: master 13 | timezone: Europe/Paris 14 | workers: 4 15 | host: 0.0.0.0 16 | vhost: graphite.monitoring.dev 17 | secret_key: 'ob3sow^ik#4q(k5*tgw&6j+osyr^@0jus$yd+-#^&^d#%yim1!' 18 | carbon: 19 | host: 0.0.0.0 20 | ssl: no 21 | db_graphite: 22 | name: graphite 23 | user: graphite 24 | password: graphite 25 | grafana: 26 | vhost: grafana.monitoring.dev 27 | roles: 28 | - common 29 | - python 30 | - supervisor 31 | - role: nginx 32 | nginx_sites: {} 33 | - postgres 34 | - graphite 35 | - statsdaemon 36 | - grafana 37 | -------------------------------------------------------------------------------- /roles/nginx/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: selinux.yml 3 | when: ansible_selinux and ansible_selinux.status == "enabled" 4 | tags: [packages,selinux,nginx] 5 | 6 | - include: nginx-official-repo.yml 7 | when: nginx_official_repo == True 8 | tags: [packages,nginx] 9 | 10 | - include: installation.packages.yml 11 | when: nginx_installation_type == "packages" 12 | tags: [packages,nginx] 13 | 14 | - include: ensure-dirs.yml 15 | tags: [configuration,nginx] 16 | 17 | - include: remove-defaults.yml 18 | when: not keep_only_specified 19 | tags: [configuration,nginx] 20 | 21 | - include: remove-extras.yml 22 | when: keep_only_specified 23 | tags: [configuration,nginx] 24 | 25 | - include: remove-unwanted.yml 26 | tags: [configuration,nginx] 27 | 28 | - include: configuration.yml 29 | tags: [configuration,nginx] 30 | 31 | - name: Start the nginx service 32 | service: name={{ nginx_service_name }} state=started enabled=yes 33 | when: nginx_installation_type in nginx_installation_types_using_service and nginx_daemon_mode == "on" 34 | tags: [service,nginx] 35 | -------------------------------------------------------------------------------- /roles/nginx/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: restart nginx 4 | debug: msg="checking config first" 5 | changed_when: True 6 | notify: 7 | - check nginx configuration 8 | - restart nginx - after config check 9 | 10 | - name: reload nginx 11 | debug: msg="checking config first" 12 | changed_when: True 13 | notify: 14 | - check nginx configuration 15 | - reload nginx - after config check 16 | 17 | - name: check nginx configuration 18 | command: "{{ nginx_binary_name }} -t" 19 | register: result 20 | changed_when: "result.rc != 0" 21 | check_mode: no 22 | when: nginx_installation_type in nginx_installation_types_using_service 23 | 24 | - name: restart nginx - after config check 25 | service: name={{ nginx_service_name }} state=restarted 26 | when: nginx_installation_type in nginx_installation_types_using_service and nginx_daemon_mode == "on" 27 | 28 | - name: reload nginx - after config check 29 | service: name={{ nginx_service_name }} state=reloaded 30 | when: nginx_installation_type in nginx_installation_types_using_service and nginx_daemon_mode == "on" 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Daan Debie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /roles/supervisor/files/supervisor-RedHat: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # /etc/rc.d/init.d/supervisord 4 | # 5 | # Supervisor is a client/server system that 6 | # allows its users to monitor and control a 7 | # number of processes on UNIX-like operating 8 | # systems. 9 | # 10 | # chkconfig: - 64 36 11 | # description: Supervisor Server 12 | # processname: supervisord 13 | 14 | # Source init functions 15 | . /etc/rc.d/init.d/functions 16 | 17 | prog="supervisord" 18 | 19 | prefix="/usr/" 20 | exec_prefix="${prefix}" 21 | prog_bin="${exec_prefix}/bin/supervisord" 22 | PIDFILE="/var/run/$prog.pid" 23 | 24 | start() 25 | { 26 | echo -n $"Starting $prog: " 27 | daemon $prog_bin --pidfile $PIDFILE 28 | [ -f $PIDFILE ] && success $"$prog startup" || failure $"$prog startup" 29 | echo 30 | } 31 | 32 | stop() 33 | { 34 | echo -n $"Shutting down $prog: " 35 | [ -f $PIDFILE ] && killproc $prog || success $"$prog shutdown" 36 | echo 37 | } 38 | 39 | case "$1" in 40 | 41 | start) 42 | start 43 | ;; 44 | 45 | stop) 46 | stop 47 | ;; 48 | 49 | status) 50 | status $prog 51 | ;; 52 | 53 | restart) 54 | stop 55 | start 56 | ;; 57 | 58 | *) 59 | echo "Usage: $0 {start|stop|restart|status}" 60 | ;; 61 | 62 | esac -------------------------------------------------------------------------------- /roles/nginx/templates/nginx.conf.j2: -------------------------------------------------------------------------------- 1 | #{{ ansible_managed }} 2 | user {{ nginx_user }} {{ nginx_group }}; 3 | 4 | worker_processes {{ nginx_worker_processes }}; 5 | 6 | {% if nginx_pid_file %} 7 | pid {{ nginx_pid_file }}; 8 | {% endif %} 9 | 10 | worker_rlimit_nofile {{ nginx_worker_rlimit_nofile }}; 11 | 12 | {% if nginx_extra_root_params is defined and nginx_extra_root_params is iterable %} 13 | {% for line in nginx_extra_root_params %} 14 | {{ line }}; 15 | {% endfor %} 16 | {% endif %} 17 | 18 | events { 19 | {% for v in nginx_events_params %} 20 | {{ v }}; 21 | {% endfor %} 22 | } 23 | 24 | 25 | http { 26 | 27 | include {{ nginx_conf_dir }}/mime.types; 28 | default_type application/octet-stream; 29 | {% for v in nginx_http_params %} 30 | {{ v }}; 31 | {% endfor %} 32 | 33 | include {{ nginx_conf_dir }}/conf.d/*.conf; 34 | include {{ nginx_conf_dir }}/sites-enabled/*; 35 | } 36 | 37 | {% if nginx_official_repo_mainline %} 38 | stream { 39 | 40 | {% for v in nginx_stream_params %} 41 | {{ v }}; 42 | {% endfor %} 43 | 44 | include {{ nginx_conf_dir }}/conf.d/stream/*.conf; 45 | } 46 | {% endif %} 47 | 48 | {% if nginx_daemon_mode == "off" %} 49 | daemon off; 50 | {% endif %} 51 | -------------------------------------------------------------------------------- /roles/supervisor/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # RedHat has an ancient version of Supervisor in it's distribution repos, so we install it with pip 2 | - name: install supervisor redhat/centos 3 | pip: name=supervisor 4 | when: ansible_os_family == "RedHat" 5 | 6 | - name: install supervisor debian/ubuntu 7 | apt: pkg=supervisor state=latest 8 | when: ansible_os_family == "Debian" 9 | 10 | - name: ensure supervisor conf.d directory exists 11 | file: 12 | path: /etc/supervisor/conf.d 13 | state: directory 14 | 15 | - name: ensure supervisor log directory exists 16 | file: 17 | path: /var/log/supervisor 18 | state: directory 19 | 20 | - name: Copy supervisor global configuration 21 | copy: src=supervisord.conf dest=/etc/supervisord.conf 22 | 23 | - name: Install as service with automatic start on redhat/centos 24 | copy: src=supervisor-RedHat dest=/etc/rc.d/init.d/supervisord mode=0755 group=root owner=root 25 | when: ansible_os_family == "RedHat" 26 | 27 | - name: Enable and run service on RedHat 28 | service: name=supervisord state=started enabled=yes 29 | when: ansible_os_family == "RedHat" 30 | 31 | - name: Enable and run service on Ubuntu/Debian 32 | service: name=supervisor state=started enabled=yes 33 | when: ansible_os_family == "Debian" 34 | -------------------------------------------------------------------------------- /roles/supervisor/files/supervisord.conf: -------------------------------------------------------------------------------- 1 | ; supervisor config file 2 | 3 | [unix_http_server] 4 | file=/var/run//supervisor.sock ; (the path to the socket file) 5 | chmod=0700 ; sockef file mode (default 0700) 6 | 7 | [supervisord] 8 | logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) 9 | pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) 10 | childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) 11 | 12 | ; the below section must remain in the config file for RPC 13 | ; (supervisorctl/web interface) to work, additional interfaces may be 14 | ; added by defining them in separate rpcinterface: sections 15 | [rpcinterface:supervisor] 16 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 17 | 18 | [supervisorctl] 19 | serverurl=unix:///var/run//supervisor.sock ; use a unix:// URL for a unix socket 20 | 21 | ; The [include] section can just contain the "files" setting. This 22 | ; setting can list multiple files (separated by whitespace or 23 | ; newlines). It can also contain wildcards. The filenames are 24 | ; interpreted as relative to this file. Included files *cannot* 25 | ; include files themselves. 26 | 27 | [include] 28 | files = /etc/supervisor/conf.d/*.conf -------------------------------------------------------------------------------- /roles/graphite/templates/storage-aggregation.conf.j2: -------------------------------------------------------------------------------- 1 | # Aggregation methods for whisper files. Entries are scanned in order, 2 | # and first match wins. This file is scanned for changes every 60 seconds 3 | # 4 | # [name] 5 | # pattern = 6 | # xFilesFactor = 7 | # aggregationMethod = 8 | # 9 | # name: Arbitrary unique name for the rule 10 | # pattern: Regex pattern to match against the metric name 11 | # xFilesFactor: Ratio of valid data points required for aggregation to the next retention to occur 12 | # aggregationMethod: function to apply to data points for aggregation 13 | # 14 | # IMPORTANT. Read this for more information! 15 | # https://github.com/etsy/statsd/blob/master/docs/graphite.md 16 | 17 | [min] 18 | pattern = \.lower$ 19 | xFilesFactor = 0.1 20 | aggregationMethod = min 21 | 22 | [max] 23 | pattern = \.upper$ 24 | xFilesFactor = 0.1 25 | aggregationMethod = max 26 | 27 | [sum] 28 | pattern = \.sum$ 29 | xFilesFactor = 0 30 | aggregationMethod = sum 31 | 32 | [count] 33 | pattern = \.count$ 34 | xFilesFactor = 0 35 | aggregationMethod = sum 36 | 37 | [count_legacy] 38 | pattern = ^stats_counts.* 39 | xFilesFactor = 0 40 | aggregationMethod = sum 41 | 42 | [default_average] 43 | pattern = .* 44 | xFilesFactor = 0.3 45 | aggregationMethod = average 46 | -------------------------------------------------------------------------------- /roles/grafana/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: add Apt repository debian/ubuntu 2 | apt_repository: 3 | repo: deb https://packagecloud.io/grafana/stable/debian/ jessie main 4 | state: present 5 | when: ansible_os_family == "Debian" 6 | 7 | - name: add signing key debian/ubuntu 8 | apt_key: 9 | url: "https://packagecloud.io/gpg.key" 10 | state: present 11 | when: ansible_os_family == "Debian" 12 | 13 | - name: update repositories cache and install Grafana package debian/ubuntu 14 | apt: 15 | name: grafana 16 | update_cache: yes 17 | when: ansible_os_family == "Debian" 18 | 19 | - name: install grafana redhat/centos 20 | yum: 21 | name: https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.4.2-1.x86_64.rpm 22 | state: present 23 | when: ansible_os_family == "RedHat" 24 | 25 | - name: Copy grafana configuration 26 | template: src=grafana.ini.j2 dest=/etc/grafana/grafana.ini owner=root group=grafana 27 | 28 | - name: Enable and run Grafana 29 | service: name=grafana-server state=started enabled=yes 30 | 31 | - name: Copy nginx configuration for grafana 32 | template: src=nginx-grafana.conf.j2 dest=/etc/nginx/sites-available/grafana.conf owner={{ nginx_user }} group={{ nginx_group }} 33 | 34 | - name: Link nginx configuration for grafana 35 | file: src=/etc/nginx/sites-available/grafana.conf dest=/etc/nginx/sites-enabled/grafana.conf state=link owner={{ nginx_user }} group={{ nginx_group }} 36 | notify: 37 | - restart nginx 38 | -------------------------------------------------------------------------------- /roles/nginx/.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: python 3 | python: "2.7" 4 | before_install: 5 | - sudo apt-get update -qq 6 | - sudo apt-get install -qq python-apt python-pycurl 7 | install: 8 | - pip install ansible ansible-lint 9 | - ansible --version 10 | script: 11 | - ansible-lint tasks/main.yml 12 | - echo localhost > inventory 13 | - ansible-playbook -i inventory --syntax-check --list-tasks test/test.yml -e "role_name=ansible-role-nginx" -e "hosts_group=hosts_group" 14 | - ansible-playbook -i inventory --connection=local --sudo -vvvv test/test.yml -u root -e "role_name=ansible-role-nginx" -e "hosts_group=localhost" 15 | - > 16 | ansible-playbook -i inventory --connection=local --sudo -vvvv test/test.yml -u root -e "role_name=ansible-role-nginx" -e "hosts_group=localhost" 17 | | grep -q 'changed=0.*failed=0' 18 | && (echo 'Idempotence test: pass' && exit 0) 19 | || (echo 'Idempotence test: fail' && exit 1) 20 | - cat /etc/nginx/nginx.conf 21 | - cat /etc/nginx/sites-enabled/default.conf 22 | - cat /etc/nginx/sites-enabled/foo.conf 23 | - cat /etc/nginx/sites-enabled/bar.conf 24 | - cat /etc/nginx/sites-enabled/custom_bar.conf 25 | - grep 'server_name bar.example.com;' /etc/nginx/sites-enabled/custom_bar.conf 26 | - cat /etc/nginx/conf.d/proxy.conf 27 | - cat /etc/nginx/conf.d/upstream.conf 28 | - cat /etc/nginx/conf.d/geo.conf 29 | - cat /etc/nginx/conf.d/gzip.conf 30 | - sudo cat /etc/nginx/auth_basic/demo 31 | - sudo nginx -t 32 | after_script: 33 | - ls -l /etc/nginx 34 | - ls -l /etc/nginx/* 35 | notifications: 36 | webhooks: https://galaxy.ansible.com/api/v1/notifications/ 37 | -------------------------------------------------------------------------------- /roles/nginx/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | nginx_pkgs: 3 | - nginx 4 | 5 | nginx_install_epel_repo: True 6 | 7 | nginx_official_repo: False 8 | nginx_official_repo_mainline: False 9 | 10 | keep_only_specified: False 11 | 12 | nginx_installation_type: "packages" 13 | nginx_binary_name: "nginx" 14 | nginx_service_name: "{{nginx_binary_name}}" 15 | nginx_conf_dir: "{% if ansible_os_family == 'FreeBSD' %}/usr/local/etc/nginx{% else %}/etc/nginx{% endif %}" 16 | 17 | nginx_user: "{% if ansible_os_family == 'RedHat' or ansible_os_family == 'Suse' %}nginx{% elif ansible_os_family == 'Debian' %}www-data{% elif ansible_os_family == 'FreeBSD' %}www{% endif %}" 18 | nginx_group: "{{nginx_user}}" 19 | 20 | nginx_pid_file: '/var/run/{{nginx_service_name}}.pid' 21 | 22 | nginx_worker_processes: "{% if ansible_processor_vcpus is defined %}{{ ansible_processor_vcpus }}{% else %}auto{% endif %}" 23 | nginx_worker_rlimit_nofile: 1024 24 | nginx_log_dir: "/var/log/nginx" 25 | nginx_error_log_level: "error" 26 | 27 | nginx_extra_root_params: [] 28 | nginx_events_params: 29 | - worker_connections {% if nginx_max_clients is defined %}{{nginx_max_clients}}{% else %}512{% endif %} 30 | 31 | nginx_http_params: "{{ nginx_http_default_params }}" 32 | 33 | nginx_stream_params: [] 34 | 35 | nginx_sites: 36 | default: 37 | - listen 80 default_server 38 | - server_name _ 39 | - root "{% if ansible_os_family == 'FreeBSD' %}/usr/local/www/nginx-dist{% else %}/usr/share/nginx/html{% endif %}" 40 | - index index.html 41 | nginx_remove_sites: [] 42 | 43 | nginx_configs: {} 44 | nginx_stream_configs: {} 45 | nginx_remove_configs: [] 46 | 47 | nginx_auth_basic_files: {} 48 | nginx_remove_auth_basic_files: [] 49 | 50 | nginx_daemon_mode: "on" 51 | -------------------------------------------------------------------------------- /roles/nginx/tasks/configuration.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Copy the nginx configuration file 3 | template: 4 | src: nginx.conf.j2 5 | dest: "{{ nginx_conf_dir }}/nginx.conf" 6 | notify: 7 | - restart nginx 8 | 9 | - name: Ensure auth_basic files created 10 | template: 11 | src: auth_basic.j2 12 | dest: "{{ nginx_conf_dir }}/auth_basic/{{ item.key }}" 13 | owner: root 14 | group: "{{ nginx_group }}" 15 | mode: 0750 16 | with_dict: "{{ nginx_auth_basic_files }}" 17 | 18 | - name: Create the configurations for sites 19 | template: 20 | src: "{{ item.value.template | default('site.conf.j2') }}" 21 | dest: "{{ nginx_conf_dir }}/sites-available/{{ item.key }}.conf" 22 | with_dict: "{{ nginx_sites }}" 23 | when: item.key not in nginx_remove_sites 24 | notify: 25 | - reload nginx 26 | 27 | - name: Create links for sites-enabled 28 | file: 29 | state: link 30 | src: "{{ nginx_conf_dir }}/sites-available/{{ item.key }}.conf" 31 | dest: "{{ nginx_conf_dir }}/sites-enabled/{{ item.key }}.conf" 32 | with_dict: "{{ nginx_sites }}" 33 | when: item.key not in nginx_remove_sites 34 | notify: 35 | - reload nginx 36 | 37 | - name: Create the configurations for independent config file 38 | template: 39 | src: config.conf.j2 40 | dest: "{{ nginx_conf_dir }}/conf.d/{{ item.key }}.conf" 41 | with_dict: "{{ nginx_configs }}" 42 | notify: 43 | - reload nginx 44 | 45 | - name: Create the configurations for independent config file for streams 46 | template: 47 | src: config_stream.conf.j2 48 | dest: "{{ nginx_conf_dir }}/conf.d/stream/{{ item.key }}.conf" 49 | with_dict: "{{ nginx_stream_configs }}" 50 | notify: 51 | - reload nginx 52 | when: nginx_official_repo_mainline 53 | -------------------------------------------------------------------------------- /roles/nginx/tasks/nginx-official-repo.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure APT official nginx key 3 | apt_key: url=http://nginx.org/keys/nginx_signing.key 4 | environment: "{{ nginx_env }}" 5 | when: ansible_os_family == 'Debian' 6 | 7 | - name: Ensure APT official nginx repository 8 | apt_repository: repo="deb http://nginx.org/packages/{{ ansible_distribution|lower }}/ {{ ansible_distribution_release }} nginx" 9 | environment: "{{ nginx_env }}" 10 | when: ansible_os_family == 'Debian' and not nginx_official_repo_mainline 11 | 12 | - name: Ensure APT official nginx repository (mainline) 13 | apt_repository: repo="deb http://nginx.org/packages/mainline/{{ ansible_distribution|lower }}/ {{ ansible_distribution_release }} nginx" 14 | environment: "{{ nginx_env }}" 15 | when: ansible_os_family == 'Debian' and nginx_official_repo_mainline 16 | 17 | - name: Ensure RPM official nginx key 18 | rpm_key: key=http://nginx.org/keys/nginx_signing.key 19 | environment: "{{ nginx_env }}" 20 | when: ansible_os_family == 'RedHat' 21 | 22 | - name: Ensure YUM official nginx repository 23 | template: src=nginx.repo.j2 dest=/etc/yum.repos.d/nginx.repo 24 | when: ansible_os_family == 'RedHat' 25 | 26 | - name: Ensure zypper official nginx repository 27 | zypper_repository: repo="http://nginx.org/packages/sles/12" name="nginx" disable_gpg_check=yes 28 | environment: "{{ nginx_env }}" 29 | when: ansible_distribution == 'SLES' and ansible_distribution_version == '12' and not nginx_official_repo_mainline 30 | 31 | - name: Ensure zypper official nginx repository (mainline) 32 | zypper_repository: repo="http://nginx.org/packages/mainline/sles/12" name="nginx" disable_gpg_check=yes 33 | environment: "{{ nginx_env }}" 34 | when: ansible_distribution == 'SLES' and ansible_distribution_version == '12' and nginx_official_repo_mainline 35 | -------------------------------------------------------------------------------- /roles/postgres/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: install postgresql packages debian/ubuntu 2 | apt: pkg={{ item }} state=latest 3 | with_items: 4 | - postgresql 5 | - postgresql-contrib 6 | - postgresql-client 7 | - libpq-dev 8 | when: ansible_os_family == "Debian" 9 | 10 | - name: install postgresql packages redhat/centos 11 | yum: pkg={{ item }} state=latest 12 | with_items: 13 | - postgresql 14 | - postgresql-server 15 | - postgresql-contrib 16 | - postgresql-libs 17 | - postgresql-devel 18 | when: ansible_os_family == "RedHat" 19 | 20 | # Aparently RedHat-family OSes don't automatically initialize DB cluster... 21 | - name: init postgresql database 22 | command: service postgresql initdb creates=/var/lib/pgsql/data/postgresql.conf 23 | when: ansible_os_family == "RedHat" 24 | 25 | # ...nor do they install themselves as starting at boot time 26 | - name: ensure postgresql is running automatically at boot time 27 | command: chkconfig postgresql on 28 | when: ansible_os_family == "RedHat" 29 | 30 | # And on top of that, authentication is configured as ident instead of md5 31 | - name: copy pg_hba.conf 32 | copy: src=pg_hba.conf dest=/var/lib/pgsql/data/pg_hba.conf backup=on 33 | notify: 34 | - restart postgresql 35 | when: ansible_os_family == "RedHat" 36 | 37 | # Start PostgreSQL. This could/should be done as a notify, but somehow that doesn't properly happen... (TODO) 38 | - name: start postgresql service 39 | service: name=postgresql state=started 40 | when: ansible_os_family == "RedHat" 41 | 42 | - name: install postgresql python bindings 43 | pip: name=psycopg2 44 | 45 | - name: setup database 46 | become_user: postgres 47 | postgresql_db: 48 | db: "{{ db_graphite.name }}" 49 | encoding: 'UTF-8' 50 | lc_collate: 'en_US.UTF-8' 51 | lc_ctype: 'en_US.UTF-8' 52 | template: 'template0' 53 | state: present 54 | 55 | - name: grant access for database to user 56 | become_user: postgres 57 | postgresql_user: 58 | db: "{{ db_graphite.name }}" 59 | user: "{{ db_graphite.user }}" 60 | password: "{{ db_graphite.password }}" 61 | role_attr_flags: "CREATEDB,SUPERUSER" 62 | state: present 63 | -------------------------------------------------------------------------------- /roles/nginx/test/example-vars.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # The user to run nginx 3 | nginx_user: "www-data" 4 | 5 | nginx_hhvm: | 6 | add_header X-backend hhvm; 7 | try_files $uri $uri/ /index.php?$args; 8 | location ~ \.(hh|php)$ { 9 | try_files $uri =404; 10 | fastcgi_pass unix:/var/run/hhvm/sock; 11 | fastcgi_index index.php; 12 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 13 | include fastcgi_params; 14 | } 15 | 16 | # A list of directives for the events section. 17 | nginx_events_params: 18 | - worker_connections 512 19 | 20 | # A list of hashs that define the servers for nginx, 21 | # as with http parameters. Any valid server parameters 22 | # can be defined here. 23 | 24 | nginx_sites: 25 | default: 26 | - listen 80 27 | - server_name _ 28 | - root "/usr/share/nginx/html" 29 | - index index.html 30 | foo: 31 | - listen 8080 32 | - server_name localhost 33 | - root "/tmp/site1" 34 | - location / { try_files $uri $uri/ /index.html; } 35 | - location /images/ { try_files $uri $uri/ /index.html; } 36 | bar: 37 | - listen 9090 38 | - server_name ansible 39 | - root "/tmp/site2" 40 | - location / { try_files $uri $uri/ /index.html; } 41 | - location /images/ { 42 | try_files $uri $uri/ /index.html; 43 | allow 127.0.0.1; 44 | deny all; 45 | } 46 | - auth_basic "Restricted" 47 | - auth_basic_user_file auth_basic/demo 48 | hhvm_test: 49 | - | 50 | listen 80; 51 | server_name test_hhvm; 52 | root "/tmp/hhvm"; 53 | {{nginx_hhvm}} 54 | custom_bar: 55 | template: custom_bar.conf.j2 56 | server_name: bar.example.com 57 | 58 | # A list of hashs that define additional configuration 59 | nginx_configs: 60 | proxy: 61 | - proxy_set_header X-Real-IP $remote_addr 62 | - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 63 | upstream: 64 | - upstream foo { server 127.0.0.1:8080 weight=10; } 65 | geo: 66 | - geo $local { 67 | default 0; 68 | 127.0.0.1 1; 69 | } 70 | gzip: 71 | - gzip on 72 | - gzip_disable msie6 73 | 74 | # A list of hashs that define uer/password files 75 | nginx_auth_basic_files: 76 | demo: 77 | - foo:$apr1$mEJqnFmy$zioG2q1iDWvRxbHuNepIh0 # foo:demo , generated by : htpasswd -nb foo demo 78 | - bar:$apr1$H2GihkSo$PwBeV8cVWFFQlnAJtvVCQ. # bar:demo , generated by : htpasswd -nb bar demo 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Graphite, StatsD & Grafana with Ansible 2 | 3 | This playbook makes it really easy to setup [Graphite](http://graphite.readthedocs.org/en/latest/), [StatsD(aemon)](https://github.com/bitly/statsdaemon) and [Grafana](http://grafana.org/) on a server (VPS or Dedicated). You can also optionally install it on a Virtual Machine using Vagrant so you can play around with it. It uses [Ansible](http://www.ansible.com/), a great configuration management tool written in Python, to automatically install the applications and all dependencies and configure everything to work optimally. 4 | 5 | What gets installed: 6 | 7 | * PostgreSQL database 8 | * NginX webserver/reverse proxy 9 | * Python, Pip & VirtualEnv 10 | * Memcached 11 | * The 3 core Graphite components: 12 | * [Carbon](https://github.com/graphite-project/carbon) 13 | * [Whisper](https://github.com/graphite-project/whisper) 14 | * [The Graphite webapp](https://github.com/graphite-project/graphite-web) 15 | * [StatsDaemon](https://github.com/bitly/statsdaemon) ([StatsD](https://github.com/etsy/statsd) implementation in Go) 16 | * [Grafana](http://grafana.org/) 17 | 18 | ## Let's do this! 19 | 20 | If you want to install Graphite on a VM using Vagrant, you first need to install [Vagrant](http://www.vagrantup.com/) and a Virtual Machine provider of choice ([VirtualBox](https://www.virtualbox.org/) is free and works out of the box with Vagrant). 21 | 22 | You can configure your install by modifying the variables in the _monitoring.yml_ file before provisioning. 23 | 24 | Then: 25 | 26 | ``` 27 | $ git clone https://github.com/DandyDev/graphite-statsd-ansible-vagrant 28 | $ cd /path/to/graphite-statsd-ansible-vagrant 29 | $ vagrant up 30 | ``` 31 | 32 | ## Different OSes 33 | 34 | By default, the Vagrant box runs Ubuntu 16.04, but the playbook supports Debian 8 and CentOS 7 as well! To try those out, uncomment the appropriate lines in the Vagrantfile and comment out the Ubuntu lines. 35 | 36 | ## Using the playbook standalone 37 | 38 | You can of course also use the playbook without Vagrant. In that case you must provide your own inventory file specifying the host on which to install Sentry. The playbook has been tested on Ubuntu 16.04, Debian 8 and CentOS 7. Other flavors of Linux might work as well. 39 | 40 | ## Secret key 41 | 42 | On production environments you will want to set the ``secret_key`` setting under the ``graphite`` namespace to a unique key that acts as a signing token. Generate a secret key for [here](http://www.miniwebtool.com/django-secret-key-generator/) 43 | 44 | ## Superuser 45 | 46 | The playbook will automatically create a superuser for Graphite with credentials `admin / admin`. Don't forget to change those! 47 | 48 | ## Known issues / TODO 49 | 50 | * This hasn't been tested on other Providers than VirtualBox yet 51 | 52 | ## Contribute 53 | 54 | If you have any suggestions, feel free to create an issue here on Github and/or fork this repo, make changes and submit a pull request! 55 | -------------------------------------------------------------------------------- /roles/graphite/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - include_vars: "{{ ansible_os_family }}.yml" 2 | 3 | - name: install required packages for graphite debian/ubuntu 4 | apt: pkg={{ item }} state=latest 5 | with_items: 6 | - memcached 7 | - libcairo2-dev 8 | - libffi-dev # for cairocffi 9 | when: ansible_os_family == "Debian" 10 | 11 | - name: install required packages for graphite redhat/centos 12 | yum: pkg={{ item }} state=latest 13 | with_items: 14 | - memcached 15 | - cairo-devel 16 | - bitmap-fonts 17 | - libffi-devel # for cairocffi 18 | when: ansible_os_family == "RedHat" 19 | 20 | - name: ensure graphite directory exists 21 | file: 22 | path: /opt/graphite/ 23 | state: directory 24 | 25 | - name: create virtualenv if needed, install graphite python deps and install graphite itself 26 | pip: name={{ item }} virtualenv=/opt/graphite chdir=/opt/graphite virtualenv_site_packages=no 27 | with_items: 28 | - psycopg2 29 | - scandir 30 | - gunicorn 31 | - python-memcached 32 | - https://github.com/graphite-project/whisper/tarball/master 33 | - https://github.com/graphite-project/carbon/tarball/master 34 | - https://github.com/graphite-project/graphite-web/tarball/master 35 | 36 | # CARBON CONFIG 37 | 38 | - name: Configure carbon cache 39 | template: src=carbon.conf.j2 dest=/opt/graphite/conf/carbon.conf mode=0644 40 | 41 | - name: Configure carbon storage schema 42 | template: src=storage-schemas.conf.j2 dest=/opt/graphite/conf/storage-schemas.conf mode=0644 43 | 44 | - name: Configure carbon storage aggregation 45 | template: src=storage-aggregation.conf.j2 dest=/opt/graphite/conf/storage-aggregation.conf mode=0644 46 | 47 | # GRAPHITE WEBAPP CONFIG 48 | 49 | - name: graphite conf 50 | template: src=local_settings.py.j2 dest=/opt/graphite/webapp/graphite/local_settings.py mode=0644 51 | 52 | - name: migrate auth for graphite 53 | shell: export PYTHONPATH=/opt/graphite/webapp/; /opt/graphite/bin/python /opt/graphite/bin/django-admin.py migrate auth --settings=graphite.settings --noinput 54 | 55 | - name: migrate the rest for graphite 56 | shell: export PYTHONPATH=/opt/graphite/webapp/; /opt/graphite/bin/python /opt/graphite/bin/django-admin.py migrate --settings=graphite.settings --run-syncdb --noinput 57 | 58 | - name: collect static stuff 59 | shell: export PYTHONPATH=/opt/graphite/webapp/; /opt/graphite/bin/python /opt/graphite/bin/django-admin.py collectstatic --settings=graphite.settings --noinput 60 | 61 | - name: copy fixtures 62 | copy: 63 | src: users.json 64 | dest: /tmp/users.json 65 | 66 | - name: load fixtures 67 | shell: export PYTHONPATH=/opt/graphite/webapp/; /opt/graphite/bin/python /opt/graphite/bin/django-admin.py loaddata /tmp/users.json --settings=graphite.settings 68 | 69 | - name: remove fixtures 70 | file: 71 | dest: /tmp/users.json 72 | state: absent 73 | 74 | - name: graphite log folder 75 | file: state=directory path=/opt/graphite/storage/log/webapp 76 | 77 | - name: graphite wsgi 78 | copy: 79 | remote_src: true 80 | src: /opt/graphite/conf/graphite.wsgi.example 81 | dest: /opt/graphite/webapp/wsgi.py 82 | 83 | # SUPERVISOR 84 | 85 | - name: Copy supervisor configuration for graphite 86 | template: src=supervisor-graphite.conf.j2 dest=/etc/supervisor/conf.d/graphite.conf 87 | notify: 88 | - reload supervisor 89 | 90 | # NGinx 91 | 92 | - name: Set file permissions 93 | file: 94 | path: /opt/graphite 95 | state: directory 96 | recurse: true 97 | owner: "{{ nginx_user }}" 98 | group: "{{ nginx_group }}" 99 | 100 | - name: Copy nginx configuration for graphite 101 | template: src=nginx-graphite.conf.j2 dest=/etc/nginx/sites-available/graphite.conf owner={{ nginx_user }} group={{ nginx_group }} 102 | 103 | - name: Link nginx configuration for graphite 104 | file: src=/etc/nginx/sites-available/graphite.conf dest=/etc/nginx/sites-enabled/graphite.conf state=link owner={{ nginx_user }} group={{ nginx_group }} 105 | notify: 106 | - restart nginx 107 | -------------------------------------------------------------------------------- /roles/graphite/templates/local_settings.py.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | ## Graphite local_settings.py 3 | # Edit this file to customize the default Graphite webapp settings 4 | # 5 | # Additional customizations to Django settings can be added to this file as well 6 | 7 | ##################################### 8 | # General Configuration # 9 | ##################################### 10 | # Set this to a long, random unique string to use as a secret key for this 11 | # install. This key is used for salting of hashes used in auth tokens, 12 | # CRSF middleware, cookie storage, etc. This should be set identically among 13 | # instances if used behind a load balancer. 14 | SECRET_KEY = '{{ graphite.secret_key }}' 15 | 16 | # In Django 1.5+ set this to the list of hosts your graphite instances is 17 | # accessible as. See: 18 | # https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-ALLOWED_HOSTS 19 | ALLOWED_HOSTS = [ '*' ] 20 | 21 | # Set your local timezone (Django's default is America/Chicago) 22 | # If your graphs appear to be offset by a couple hours then this probably 23 | # needs to be explicitly set to your local timezone. 24 | #TIME_ZONE = 'America/Los_Angeles' 25 | TIME_ZONE = 'UTC' 26 | 27 | # Override this to provide documentation specific to your Graphite deployment 28 | #DOCUMENTATION_URL = "http://graphite.readthedocs.org/" 29 | 30 | # Logging 31 | #LOG_RENDERING_PERFORMANCE = True 32 | #LOG_CACHE_PERFORMANCE = True 33 | #LOG_METRIC_ACCESS = True 34 | 35 | # Enable full debug page display on exceptions (Internal Server Error pages) 36 | #DEBUG = True 37 | 38 | # If using RRD files and rrdcached, set to the address or socket of the daemon 39 | #FLUSHRRDCACHED = 'unix:/var/run/rrdcached.sock' 40 | 41 | # This lists the memcached servers that will be used by this webapp. 42 | # If you have a cluster of webapps you should ensure all of them 43 | # have the *exact* same value for this setting. That will maximize cache 44 | # efficiency. Setting MEMCACHE_HOSTS to be empty will turn off use of 45 | # memcached entirely. 46 | # 47 | # You should not use the loopback address (127.0.0.1) here if using clustering 48 | # as every webapp in the cluster should use the exact same values to prevent 49 | # unneeded cache misses. Set to [] to disable caching of images and fetched data 50 | MEMCACHE_HOSTS = ['localhost:11211'] 51 | #DEFAULT_CACHE_DURATION = 60 # Cache images and data for 1 minute 52 | 53 | 54 | ##################################### 55 | # Filesystem Paths # 56 | ##################################### 57 | # Change only GRAPHITE_ROOT if your install is merely shifted from /opt/graphite 58 | # to somewhere else 59 | #GRAPHITE_ROOT = '/opt/graphite' 60 | 61 | # Most installs done outside of a separate tree such as /opt/graphite will only 62 | # need to change these three settings. Note that the default settings for each 63 | # of these is relative to GRAPHITE_ROOT 64 | #CONF_DIR = '/opt/graphite/conf' 65 | #STORAGE_DIR = '/opt/graphite/storage' 66 | #CONTENT_DIR = '/opt/graphite/webapp/content' 67 | 68 | # To further or fully customize the paths, modify the following. Note that the 69 | # default settings for each of these are relative to CONF_DIR and STORAGE_DIR 70 | # 71 | ## Webapp config files 72 | #DASHBOARD_CONF = '/opt/graphite/conf/dashboard.conf' 73 | #GRAPHTEMPLATES_CONF = '/opt/graphite/conf/graphTemplates.conf' 74 | 75 | ## Data directories 76 | # NOTE: If any directory is unreadable in DATA_DIRS it will break metric browsing 77 | #WHISPER_DIR = '/opt/graphite/storage/whisper' 78 | #RRD_DIR = '/opt/graphite/storage/rrd' 79 | #DATA_DIRS = [WHISPER_DIR, RRD_DIR] # Default: set from the above variables 80 | #LOG_DIR = '/opt/graphite/storage/log/webapp' 81 | #INDEX_FILE = '/opt/graphite/storage/index' # Search index file 82 | 83 | 84 | ##################################### 85 | # Email Configuration # 86 | ##################################### 87 | # This is used for emailing rendered Graphs 88 | # Default backend is SMTP 89 | #EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' 90 | #EMAIL_HOST = 'localhost' 91 | #EMAIL_PORT = 25 92 | #EMAIL_HOST_USER = '' 93 | #EMAIL_HOST_PASSWORD = '' 94 | #EMAIL_USE_TLS = False 95 | # To drop emails on the floor, enable the Dummy backend: 96 | #EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' 97 | 98 | 99 | ##################################### 100 | # Authentication Configuration # 101 | ##################################### 102 | ## LDAP / ActiveDirectory authentication setup 103 | {% if graphite_ldap_enabled is defined and graphite_ldap_enabled %} 104 | USE_LDAP_AUTH = True 105 | LDAP_URI = "{{ graphite_ldap_uri }}" 106 | LDAP_SEARCH_BASE = "{{ graphite_ldap_search_base }}" 107 | LDAP_BASE_USER = "{{ graphite_ldap_base_user }}" 108 | LDAP_BASE_PASS = "{{ graphite_ldap_base_pass }}" 109 | LDAP_USER_QUERY = "{{ graphite_ldap_user_query }}" 110 | {% else %} 111 | #USE_LDAP_AUTH = True 112 | #LDAP_SERVER = "ldap.mycompany.com" 113 | #LDAP_PORT = 389 114 | # OR 115 | #LDAP_URI = "ldaps://ldap.mycompany.com:636" 116 | #LDAP_SEARCH_BASE = "OU=users,DC=mycompany,DC=com" 117 | #LDAP_BASE_USER = "CN=some_readonly_account,DC=mycompany,DC=com" 118 | #LDAP_BASE_PASS = "readonly_account_password" 119 | #LDAP_USER_QUERY = "(username=%s)" #For Active Directory use "(sAMAccountName=%s)" 120 | {% endif %} 121 | # 122 | # If you want to further customize the ldap connection options you should 123 | # directly use ldap.set_option to set the ldap module's global options. 124 | # For example: 125 | # 126 | #import ldap 127 | #ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_ALLOW) 128 | #ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, "/etc/ssl/ca") 129 | #ldap.set_option(ldap.OPT_X_TLS_CERTFILE, "/etc/ssl/mycert.pem") 130 | #ldap.set_option(ldap.OPT_X_TLS_KEYFILE, "/etc/ssl/mykey.pem") 131 | # See http://www.python-ldap.org/ for further details on these options. 132 | 133 | ## REMOTE_USER authentication. See: https://docs.djangoproject.com/en/dev/howto/auth-remote-user/ 134 | #USE_REMOTE_USER_AUTHENTICATION = True 135 | 136 | # Override the URL for the login link (e.g. for django_openid_auth) 137 | #LOGIN_URL = '/account/login' 138 | 139 | 140 | ########################## 141 | # Database Configuration # 142 | ########################## 143 | # By default sqlite is used. If you cluster multiple webapps you will need 144 | # to setup an external database (such as MySQL) and configure all of the webapp 145 | # instances to use the same database. Note that this database is only used to store 146 | # Django models such as saved graphs, dashboards, user preferences, etc. 147 | # Metric data is not stored here. 148 | # 149 | # DO NOT FORGET TO RUN 'manage.py syncdb' AFTER SETTING UP A NEW DATABASE 150 | # 151 | # The following built-in database engines are available: 152 | # django.db.backends.postgresql # Removed in Django 1.4 153 | # django.db.backends.postgresql_psycopg2 154 | # django.db.backends.mysql 155 | # django.db.backends.sqlite3 156 | # django.db.backends.oracle 157 | # 158 | # The default is 'django.db.backends.sqlite3' with file 'graphite.db' 159 | # located in STORAGE_DIR 160 | # 161 | DATABASES = { 162 | 'default': { 163 | # You can swap out the engine for MySQL easily by changing this value 164 | # to ``django.db.backends.mysql`` or to PostgreSQL with 165 | # ``django.db.backends.postgresql_psycopg2`` 166 | 'ENGINE': 'django.db.backends.postgresql_psycopg2', 167 | 'NAME': '{{ db_graphite.name }}', 168 | 'USER': '{{ db_graphite.user }}', 169 | 'PASSWORD': '{{ db_graphite.password }}', 170 | 'HOST': 'localhost', 171 | 'PORT': '', 172 | } 173 | } 174 | 175 | 176 | 177 | ######################### 178 | # Cluster Configuration # 179 | ######################### 180 | # (To avoid excessive DNS lookups you want to stick to using IP addresses only in this entire section) 181 | # 182 | # This should list the IP address (and optionally port) of the webapp on each 183 | # remote server in the cluster. These servers must each have local access to 184 | # metric data. Note that the first server to return a match for a query will be 185 | # used. 186 | #CLUSTER_SERVERS = ["10.0.2.2:80", "10.0.2.3:80"] 187 | 188 | ## These are timeout values (in seconds) for requests to remote webapps 189 | #REMOTE_STORE_FETCH_TIMEOUT = 6 # Timeout to fetch series data 190 | #REMOTE_STORE_FIND_TIMEOUT = 2.5 # Timeout for metric find requests 191 | #REMOTE_STORE_RETRY_DELAY = 60 # Time before retrying a failed remote webapp 192 | #REMOTE_FIND_CACHE_DURATION = 300 # Time to cache remote metric find results 193 | 194 | ## Remote rendering settings 195 | # Set to True to enable rendering of Graphs on a remote webapp 196 | #REMOTE_RENDERING = True 197 | # List of IP (and optionally port) of the webapp on each remote server that 198 | # will be used for rendering. Note that each rendering host should have local 199 | # access to metric data or should have CLUSTER_SERVERS configured 200 | #RENDERING_HOSTS = [] 201 | #REMOTE_RENDER_CONNECT_TIMEOUT = 1.0 202 | 203 | # If you are running multiple carbon-caches on this machine (typically behind a relay using 204 | # consistent hashing), you'll need to list the ip address, cache query port, and instance name of each carbon-cache 205 | # instance on the local machine (NOT every carbon-cache in the entire cluster). The default cache query port is 7002 206 | # and a common scheme is to use 7102 for instance b, 7202 for instance c, etc. 207 | # 208 | # You *should* use 127.0.0.1 here in most cases 209 | #CARBONLINK_HOSTS = ["127.0.0.1:7002:a", "127.0.0.1:7102:b", "127.0.0.1:7202:c"] 210 | #CARBONLINK_TIMEOUT = 1.0 211 | 212 | ##################################### 213 | # Additional Django Settings # 214 | ##################################### 215 | # Uncomment the following line for direct access to Django settings such as 216 | # MIDDLEWARE_CLASSES or APPS 217 | #from graphite.app_settings import * 218 | 219 | -------------------------------------------------------------------------------- /roles/nginx/README.md: -------------------------------------------------------------------------------- 1 | nginx 2 | ===== 3 | 4 | This role installs and configures the nginx web server. The user can specify 5 | any http configuration parameters they wish to apply their site. Any number of 6 | sites can be added with configurations of your choice. 7 | 8 | [![Build Status](https://travis-ci.org/jdauphant/ansible-role-nginx.svg?branch=master)](https://travis-ci.org/jdauphant/ansible-role-nginx) 9 | [![Ansible Galaxy](https://img.shields.io/ansible/role/466.svg)](https://galaxy.ansible.com/jdauphant/nginx/) 10 | 11 | Requirements 12 | ------------ 13 | 14 | This role requires Ansible 2.0 or higher and platform requirements are listed 15 | in the metadata file. (Some older version of the role support Ansible 1.4) 16 | For FreeBSD a working pkgng setup is required (see: https://www.freebsd.org/doc/handbook/pkgng-intro.html ) 17 | 18 | Install 19 | ------- 20 | 21 | ```sh 22 | ansible-galaxy install jdauphant.nginx 23 | ``` 24 | 25 | Role Variables 26 | -------------- 27 | 28 | The variables that can be passed to this role and a brief description about 29 | them are as follows. (For all variables, take a look at [defaults/main.yml](defaults/main.yml)) 30 | 31 | ```yaml 32 | # The user to run nginx 33 | nginx_user: "www-data" 34 | 35 | # A list of directives for the events section. 36 | nginx_events_params: 37 | - worker_connections 512 38 | - debug_connection 127.0.0.1 39 | - use epoll 40 | - multi_accept on 41 | 42 | # A list of hashs that define the servers for nginx, 43 | # as with http parameters. Any valid server parameters 44 | # can be defined here. 45 | nginx_sites: 46 | default: 47 | - listen 80 48 | - server_name _ 49 | - root "/usr/share/nginx/html" 50 | - index index.html 51 | foo: 52 | - listen 8080 53 | - server_name localhost 54 | - root "/tmp/site1" 55 | - location / { try_files $uri $uri/ /index.html; } 56 | - location /images/ { try_files $uri $uri/ /index.html; } 57 | bar: 58 | - listen 9090 59 | - server_name ansible 60 | - root "/tmp/site2" 61 | - location / { try_files $uri $uri/ /index.html; } 62 | - location /images/ { 63 | try_files $uri $uri/ /index.html; 64 | allow 127.0.0.1; 65 | deny all; 66 | } 67 | 68 | # A list of hashs that define additional configuration 69 | nginx_configs: 70 | proxy: 71 | - proxy_set_header X-Real-IP $remote_addr 72 | - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 73 | upstream: 74 | - upstream foo { server 127.0.0.1:8080 weight=10; } 75 | geo: 76 | - geo $local { 77 | default 0; 78 | 127.0.0.1 1; 79 | } 80 | gzip: 81 | - gzip on 82 | - gzip_disable msie6 83 | 84 | # A list of hashs that define user/password files 85 | nginx_auth_basic_files: 86 | demo: 87 | - foo:$apr1$mEJqnFmy$zioG2q1iDWvRxbHuNepIh0 # foo:demo , generated by : htpasswd -nb foo demo 88 | - bar:$apr1$H2GihkSo$PwBeV8cVWFFQlnAJtvVCQ. # bar:demo , generated by : htpasswd -nb bar demo 89 | 90 | ``` 91 | 92 | Examples 93 | ======== 94 | 95 | 1) Install nginx with HTTP directives of choices, but with no sites 96 | configured and no additionnal configuration: 97 | 98 | ```yaml 99 | - hosts: all 100 | roles: 101 | - {role: nginx, 102 | nginx_http_params: ["sendfile on", "access_log /var/log/nginx/access.log"] 103 | } 104 | ``` 105 | 106 | 2) Install nginx with different HTTP directives than previous example, but no 107 | sites configured and no additionnal configuration. 108 | 109 | ```yaml 110 | - hosts: all 111 | roles: 112 | - {role: nginx, 113 | nginx_http_params: ["tcp_nodelay on", "error_log /var/log/nginx/error.log"]} 114 | ``` 115 | 116 | Note: Please make sure the HTTP directives passed are valid, as this role 117 | won't check for the validity of the directives. See the nginx documentation 118 | for details. 119 | 120 | 3) Install nginx and add a site to the configuration. 121 | 122 | ```yaml 123 | - hosts: all 124 | 125 | roles: 126 | - role: nginx 127 | nginx_http_params: 128 | - sendfile "on" 129 | - access_log "/var/log/nginx/access.log" 130 | nginx_sites: 131 | bar: 132 | - listen 8080 133 | - location / { try_files $uri $uri/ /index.html; } 134 | - location /images/ { try_files $uri $uri/ /index.html; } 135 | nginx_configs: 136 | proxy: 137 | - proxy_set_header X-Real-IP $remote_addr 138 | - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 139 | ``` 140 | 141 | 4) Install nginx and add extra variables to default config 142 | 143 | ```yaml 144 | -hosts: all 145 | vars: 146 | - my_extra_params: 147 | - client_max_body_size 200M 148 | # retain defaults and add additional `client_max_body_size` param 149 | roles: 150 | - role: jdauphant.nginx 151 | nginx_http_params: "{{ nginx_http_params_defaults + my_extra_params }}" 152 | ``` 153 | 154 | Note: Each site added is represented by list of hashes, and the configurations 155 | generated are populated in /etc/nginx/site-available/, a link is from /etc/nginx/site-enable/ to /etc/nginx/site-available 156 | 157 | The file name for the specific site configurtaion is specified in the hash 158 | with the key "file_name", any valid server directives can be added to hash. 159 | Additional configuration are created in /etc/nginx/conf.d/ 160 | 161 | 5) Install Nginx , add 2 sites (different method) and add additional configuration 162 | 163 | ```yaml 164 | --- 165 | - hosts: all 166 | roles: 167 | - role: nginx 168 | nginx_http_params: 169 | - sendfile on 170 | - access_log /var/log/nginx/access.log 171 | nginx_sites: 172 | foo: 173 | - listen 8080 174 | - server_name localhost 175 | - root /tmp/site1 176 | - location / { try_files $uri $uri/ /index.html; } 177 | - location /images/ { try_files $uri $uri/ /index.html; } 178 | bar: 179 | - listen 9090 180 | - server_name ansible 181 | - root /tmp/site2 182 | - location / { try_files $uri $uri/ /index.html; } 183 | - location /images/ { try_files $uri $uri/ /index.html; } 184 | nginx_configs: 185 | proxy: 186 | - proxy_set_header X-Real-IP $remote_addr 187 | - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 188 | ``` 189 | 190 | 6) Install Nginx , add 2 sites, add additional configuration and an upstream configuration block 191 | 192 | ```yaml 193 | --- 194 | - hosts: all 195 | roles: 196 | - role: nginx 197 | nginx_error_log_level: info 198 | nginx_http_params: 199 | - sendfile on 200 | - access_log /var/log/nginx/access.log 201 | nginx_sites: 202 | foo: 203 | - listen 8080 204 | - server_name localhost 205 | - root /tmp/site1 206 | - location / { try_files $uri $uri/ /index.html; } 207 | - location /images/ { try_files $uri $uri/ /index.html; } 208 | bar: 209 | - listen 9090 210 | - server_name ansible 211 | - root /tmp/site2 212 | - if ( $host = example.com ) { rewrite ^(.*)$ http://www.example.com$1 permanent; } 213 | - location / { 214 | try_files $uri $uri/ /index.html; 215 | auth_basic "Restricted"; 216 | auth_basic_user_file auth_basic/demo; 217 | } 218 | - location /images/ { try_files $uri $uri/ /index.html; } 219 | nginx_configs: 220 | proxy: 221 | - proxy_set_header X-Real-IP $remote_addr 222 | - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 223 | upstream: 224 | # Results in: 225 | # upstream foo_backend { 226 | # server 127.0.0.1:8080 weight=10; 227 | # } 228 | - upstream foo_backend { server 127.0.0.1:8080 weight=10; } 229 | nginx_auth_basic_files: 230 | demo: 231 | - foo:$apr1$mEJqnFmy$zioG2q1iDWvRxbHuNepIh0 # foo:demo , generated by : htpasswd -nb foo demo 232 | - bar:$apr1$H2GihkSo$PwBeV8cVWFFQlnAJtvVCQ. # bar:demo , generated by : htpasswd -nb bar demo 233 | ``` 234 | 235 | 7) Install Nginx, add a site and use special yaml syntax to make the location blocks multiline for clarity 236 | 237 | ```yaml 238 | --- 239 | - hosts: all 240 | roles: 241 | - role: nginx 242 | nginx_http_params: 243 | - sendfile on 244 | - access_log /var/log/nginx/access.log 245 | nginx_sites: 246 | foo: 247 | - listen 443 ssl 248 | - server_name foo.example.com 249 | - set $myhost foo.example.com 250 | - | 251 | location / { 252 | proxy_set_header Host foo.example.com; 253 | } 254 | - | 255 | location ~ /v2/users/.+?/organizations { 256 | if ($request_method = PUT) { 257 | set $myhost bar.example.com; 258 | } 259 | if ($request_method = DELETE) { 260 | set $myhost bar.example.com; 261 | } 262 | proxy_set_header Host $myhost; 263 | } 264 | ``` 265 | 8) Example to use this role with my ssl-certs role to generate or copie ssl certificate ( https://galaxy.ansible.com/list#/roles/3115 ) 266 | ```yaml 267 | - hosts: all 268 | roles: 269 | - jdauphant.ssl-certs 270 | - role: jdauphant.nginx 271 | nginx_configs: 272 | ssl: 273 | - ssl_certificate_key {{ssl_certs_privkey_path}} 274 | - ssl_certificate {{ssl_certs_cert_path}} 275 | nginx_sites: 276 | default: 277 | - listen 443 ssl 278 | - server_name _ 279 | - root "/usr/share/nginx/html" 280 | - index index.html 281 | ``` 282 | 9) Site configuration using a custom template. 283 | Instead of defining a site config file using a list of attributes, 284 | you may use a hash/dictionary that includes the filename of an alternate template. 285 | Additional values are accessible within the template via the `item.value` variable. 286 | ```yaml 287 | - hosts: all 288 | 289 | roles: 290 | - role: nginx 291 | nginx_sites: 292 | custom_bar: 293 | template: custom_bar.conf.j2 294 | server_name: custom_bar.example.com 295 | ``` 296 | Custom template: custom_bar.conf.j2: 297 | ```handlebars 298 | # {{ ansible_managed }} 299 | upstream backend { 300 | server 10.0.0.101; 301 | } 302 | server { 303 | server_name {{ item.value.server_name }}; 304 | location / { 305 | proxy_pass http://backend; 306 | } 307 | } 308 | ``` 309 | Using a custom template allows for unlimited flexibility in configuring the site config file. 310 | This example demonstrates the common practice of configuring a site server block 311 | in the same file as its complementary upstream block. 312 | If you use this option: 313 | * _The hash **must** include a `template:` value, or the configuration task will fail._ 314 | * _This role cannot check tha validity of your custom template. 315 | If you use this method, the conf file formtting provided by this role is unavailable, 316 | and it is up to you to provide a template with valid content and formatting for NGINX._ 317 | 318 | Dependencies 319 | ------------ 320 | 321 | None 322 | 323 | License 324 | ------- 325 | BSD 326 | 327 | Author Information 328 | ------------------ 329 | 330 | - Original : Benno Joy 331 | - Modified by : DAUPHANT Julien 332 | -------------------------------------------------------------------------------- /roles/grafana/templates/grafana.ini.j2: -------------------------------------------------------------------------------- 1 | ##################### Grafana Configuration Example ##################### 2 | # 3 | # Everything has defaults so you only need to uncomment things you want to 4 | # change 5 | 6 | # possible values : production, development 7 | ; app_mode = production 8 | 9 | # instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty 10 | ; instance_name = ${HOSTNAME} 11 | 12 | #################################### Paths #################################### 13 | [paths] 14 | # Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) 15 | # 16 | ;data = /var/lib/grafana 17 | # 18 | # Directory where grafana can store logs 19 | # 20 | ;logs = /var/log/grafana 21 | # 22 | # Directory where grafana will automatically scan and look for plugins 23 | # 24 | ;plugins = /var/lib/grafana/plugins 25 | 26 | # 27 | #################################### Server #################################### 28 | [server] 29 | # Protocol (http or https) 30 | ;protocol = http 31 | 32 | # The ip address to bind to, empty will bind to all interfaces 33 | ;http_addr = 34 | 35 | # The http port to use 36 | ;http_port = 3000 37 | 38 | # The public facing domain name used to access grafana from a browser 39 | ;domain = localhost 40 | 41 | # Redirect to correct domain if host header does not match domain 42 | # Prevents DNS rebinding attacks 43 | ;enforce_domain = false 44 | 45 | # The full public facing url you use in browser, used for redirects and emails 46 | # If you use reverse proxy and sub path specify full url (with sub path) 47 | root_url = http://{{ grafana.vhost }} 48 | 49 | # Log web requests 50 | ;router_logging = false 51 | 52 | # the path relative working path 53 | ;static_root_path = public 54 | 55 | # enable gzip 56 | ;enable_gzip = false 57 | 58 | # https certs & key file 59 | ;cert_file = 60 | ;cert_key = 61 | 62 | #################################### Database #################################### 63 | [database] 64 | # You can configure the database connection by specifying type, host, name, user and password 65 | # as seperate properties or as on string using the url propertie. 66 | 67 | # Either "mysql", "postgres" or "sqlite3", it's your choice 68 | ;type = sqlite3 69 | ;host = 127.0.0.1:3306 70 | ;name = grafana 71 | ;user = root 72 | # If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;""" 73 | ;password = 74 | 75 | # Use either URL or the previous fields to configure the database 76 | # Example: mysql://user:secret@host:port/database 77 | ;url = 78 | 79 | # For "postgres" only, either "disable", "require" or "verify-full" 80 | ;ssl_mode = disable 81 | 82 | # For "sqlite3" only, path relative to data_path setting 83 | ;path = grafana.db 84 | 85 | #################################### Session #################################### 86 | [session] 87 | # Either "memory", "file", "redis", "mysql", "postgres", default is "file" 88 | ;provider = file 89 | 90 | # Provider config options 91 | # memory: not have any config yet 92 | # file: session dir path, is relative to grafana data_path 93 | # redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=grafana` 94 | # mysql: go-sql-driver/mysql dsn config string, e.g. `user:password@tcp(127.0.0.1:3306)/database_name` 95 | # postgres: user=a password=b host=localhost port=5432 dbname=c sslmode=disable 96 | ;provider_config = sessions 97 | 98 | # Session cookie name 99 | ;cookie_name = grafana_sess 100 | 101 | # If you use session in https only, default is false 102 | ;cookie_secure = false 103 | 104 | # Session life time, default is 86400 105 | ;session_life_time = 86400 106 | 107 | #################################### Analytics #################################### 108 | [analytics] 109 | # Server reporting, sends usage counters to stats.grafana.org every 24 hours. 110 | # No ip addresses are being tracked, only simple counters to track 111 | # running instances, dashboard and error counts. It is very helpful to us. 112 | # Change this option to false to disable reporting. 113 | reporting_enabled = false 114 | 115 | # Set to false to disable all checks to https://grafana.net 116 | # for new vesions (grafana itself and plugins), check is used 117 | # in some UI views to notify that grafana or plugin update exists 118 | # This option does not cause any auto updates, nor send any information 119 | # only a GET request to http://grafana.net to get latest versions 120 | ;check_for_updates = true 121 | 122 | # Google Analytics universal tracking code, only enabled if you specify an id here 123 | ;google_analytics_ua_id = 124 | 125 | #################################### Security #################################### 126 | [security] 127 | # default admin user, created on startup 128 | ;admin_user = admin 129 | 130 | # default admin password, can be changed before first start of grafana, or in profile settings 131 | ;admin_password = admin 132 | 133 | # used for signing 134 | ;secret_key = SW2YcwTIb9zpOOhoPsMm 135 | 136 | # Auto-login remember days 137 | ;login_remember_days = 7 138 | ;cookie_username = grafana_user 139 | ;cookie_remember_name = grafana_remember 140 | 141 | # disable gravatar profile images 142 | ;disable_gravatar = false 143 | 144 | # data source proxy whitelist (ip_or_domain:port separated by spaces) 145 | ;data_source_proxy_whitelist = 146 | 147 | [snapshots] 148 | # snapshot sharing options 149 | external_enabled = false 150 | ;external_snapshot_url = https://snapshots-origin.raintank.io 151 | ;external_snapshot_name = Publish to snapshot.raintank.io 152 | 153 | # remove expired snapshot 154 | ;snapshot_remove_expired = true 155 | 156 | # remove snapshots after 90 days 157 | ;snapshot_TTL_days = 90 158 | 159 | #################################### Users #################################### 160 | [users] 161 | # disable user signup / registration 162 | allow_sign_up = false 163 | 164 | # Allow non admin users to create organizations 165 | allow_org_create = false 166 | 167 | # Set to true to automatically assign new users to the default organization (id 1) 168 | ;auto_assign_org = true 169 | 170 | # Default role new users will be automatically assigned (if disabled above is set to true) 171 | ;auto_assign_org_role = Viewer 172 | 173 | # Background text for the user field on the login page 174 | ;login_hint = email or username 175 | 176 | # Default UI theme ("dark" or "light") 177 | ;default_theme = dark 178 | 179 | [auth] 180 | # Set to true to disable (hide) the login form, useful if you use OAuth, defaults to false 181 | ;disable_login_form = false 182 | 183 | #################################### Anonymous Auth ########################## 184 | [auth.anonymous] 185 | # enable anonymous access 186 | ;enabled = false 187 | 188 | # specify organization name that should be used for unauthenticated users 189 | ;org_name = Main Org. 190 | 191 | # specify role for unauthenticated users 192 | ;org_role = Viewer 193 | 194 | #################################### Github Auth ########################## 195 | [auth.github] 196 | ;enabled = false 197 | ;allow_sign_up = true 198 | ;client_id = some_id 199 | ;client_secret = some_secret 200 | ;scopes = user:email,read:org 201 | ;auth_url = https://github.com/login/oauth/authorize 202 | ;token_url = https://github.com/login/oauth/access_token 203 | ;api_url = https://api.github.com/user 204 | ;team_ids = 205 | ;allowed_organizations = 206 | 207 | #################################### Google Auth ########################## 208 | [auth.google] 209 | ;enabled = false 210 | ;allow_sign_up = true 211 | ;client_id = some_client_id 212 | ;client_secret = some_client_secret 213 | ;scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email 214 | ;auth_url = https://accounts.google.com/o/oauth2/auth 215 | ;token_url = https://accounts.google.com/o/oauth2/token 216 | ;api_url = https://www.googleapis.com/oauth2/v1/userinfo 217 | ;allowed_domains = 218 | 219 | #################################### Generic OAuth ########################## 220 | [auth.generic_oauth] 221 | ;enabled = false 222 | ;name = OAuth 223 | ;allow_sign_up = true 224 | ;client_id = some_id 225 | ;client_secret = some_secret 226 | ;scopes = user:email,read:org 227 | ;auth_url = https://foo.bar/login/oauth/authorize 228 | ;token_url = https://foo.bar/login/oauth/access_token 229 | ;api_url = https://foo.bar/user 230 | ;team_ids = 231 | ;allowed_organizations = 232 | 233 | #################################### Grafana.net Auth #################### 234 | [auth.grafananet] 235 | ;enabled = false 236 | ;allow_sign_up = true 237 | ;client_id = some_id 238 | ;client_secret = some_secret 239 | ;scopes = user:email 240 | ;allowed_organizations = 241 | 242 | #################################### Auth Proxy ########################## 243 | [auth.proxy] 244 | ;enabled = false 245 | ;header_name = X-WEBAUTH-USER 246 | ;header_property = username 247 | ;auto_sign_up = true 248 | ;ldap_sync_ttl = 60 249 | ;whitelist = 192.168.1.1, 192.168.2.1 250 | 251 | #################################### Basic Auth ########################## 252 | [auth.basic] 253 | ;enabled = true 254 | 255 | #################################### Auth LDAP ########################## 256 | [auth.ldap] 257 | ;enabled = false 258 | ;config_file = /etc/grafana/ldap.toml 259 | ;allow_sign_up = true 260 | 261 | #################################### SMTP / Emailing ########################## 262 | [smtp] 263 | ;enabled = false 264 | ;host = localhost:25 265 | ;user = 266 | ;password = 267 | ;cert_file = 268 | ;key_file = 269 | ;skip_verify = false 270 | ;from_address = admin@grafana.localhost 271 | 272 | [emails] 273 | ;welcome_email_on_sign_up = false 274 | 275 | #################################### Logging ########################## 276 | [log] 277 | # Either "console", "file", "syslog". Default is console and file 278 | # Use space to separate multiple modes, e.g. "console file" 279 | ;mode = console file 280 | 281 | # Either "trace", "debug", "info", "warn", "error", "critical", default is "info" 282 | ;level = info 283 | 284 | # optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug 285 | ;filters = 286 | 287 | 288 | # For "console" mode only 289 | [log.console] 290 | ;level = 291 | 292 | # log line format, valid options are text, console and json 293 | ;format = console 294 | 295 | # For "file" mode only 296 | [log.file] 297 | ;level = 298 | 299 | # log line format, valid options are text, console and json 300 | ;format = text 301 | 302 | # This enables automated log rotate(switch of following options), default is true 303 | ;log_rotate = true 304 | 305 | # Max line number of single file, default is 1000000 306 | ;max_lines = 1000000 307 | 308 | # Max size shift of single file, default is 28 means 1 << 28, 256MB 309 | ;max_size_shift = 28 310 | 311 | # Segment log daily, default is true 312 | ;daily_rotate = true 313 | 314 | # Expired days of log file(delete after max days), default is 7 315 | ;max_days = 7 316 | 317 | [log.syslog] 318 | ;level = 319 | 320 | # log line format, valid options are text, console and json 321 | ;format = text 322 | 323 | # Syslog network type and address. This can be udp, tcp, or unix. If left blank, the default unix endpoints will be used. 324 | ;network = 325 | ;address = 326 | 327 | # Syslog facility. user, daemon and local0 through local7 are valid. 328 | ;facility = 329 | 330 | # Syslog tag. By default, the process' argv[0] is used. 331 | ;tag = 332 | 333 | 334 | #################################### AMQP Event Publisher ########################## 335 | [event_publisher] 336 | ;enabled = false 337 | ;rabbitmq_url = amqp://localhost/ 338 | ;exchange = grafana_events 339 | 340 | ;#################################### Dashboard JSON files ########################## 341 | [dashboards.json] 342 | ;enabled = false 343 | ;path = /var/lib/grafana/dashboards 344 | 345 | #################################### Alerting ###################################### 346 | [alerting] 347 | # Makes it possible to turn off alert rule execution. 348 | ;execute_alerts = true 349 | 350 | #################################### Internal Grafana Metrics ########################## 351 | # Metrics available at HTTP API Url /api/metrics 352 | [metrics] 353 | # Disable / Enable internal metrics 354 | ;enabled = true 355 | 356 | # Publish interval 357 | ;interval_seconds = 10 358 | 359 | # Send internal metrics to Graphite 360 | [metrics.graphite] 361 | # Enable by setting the address setting (ex localhost:2003) 362 | ;address = 363 | ;prefix = prod.grafana.%(instance_name)s. 364 | 365 | #################################### Internal Grafana Metrics ########################## 366 | # Url used to to import dashboards directly from Grafana.net 367 | [grafana_net] 368 | ;url = https://grafana.net 369 | 370 | #################################### External image storage ########################## 371 | [external_image_storage] 372 | # Used for uploading images to public servers so they can be included in slack/email messages. 373 | # you can choose between (s3, webdav) 374 | ;provider = 375 | 376 | [external_image_storage.s3] 377 | ;bucket_url = 378 | ;access_key = 379 | ;secret_key = 380 | 381 | [external_image_storage.webdav] 382 | ;url = 383 | ;username = 384 | ;password = -------------------------------------------------------------------------------- /roles/graphite/templates/carbon.conf.j2: -------------------------------------------------------------------------------- 1 | [cache] 2 | # Configure carbon directories. 3 | # 4 | # OS environment variables can be used to tell carbon where graphite is 5 | # installed, where to read configuration from and where to write data. 6 | # 7 | # GRAPHITE_ROOT - Root directory of the graphite installation. 8 | # Defaults to ../ 9 | # GRAPHITE_CONF_DIR - Configuration directory (where this file lives). 10 | # Defaults to $GRAPHITE_ROOT/conf/ 11 | # GRAPHITE_STORAGE_DIR - Storage directory for whipser/rrd/log/pid files. 12 | # Defaults to $GRAPHITE_ROOT/storage/ 13 | # 14 | # To change other directory paths, add settings to this file. The following 15 | # configuration variables are available with these default values: 16 | # 17 | # STORAGE_DIR = $GRAPHITE_STORAGE_DIR 18 | # LOCAL_DATA_DIR = STORAGE_DIR/whisper/ 19 | # WHITELISTS_DIR = STORAGE_DIR/lists/ 20 | # CONF_DIR = STORAGE_DIR/conf/ 21 | # LOG_DIR = STORAGE_DIR/log/ 22 | # PID_DIR = STORAGE_DIR/ 23 | # 24 | # For FHS style directory structures, use: 25 | # 26 | # STORAGE_DIR = /var/lib/carbon/ 27 | # CONF_DIR = /etc/carbon/ 28 | # LOG_DIR = /var/log/carbon/ 29 | # PID_DIR = /var/run/ 30 | # 31 | #LOCAL_DATA_DIR = /opt/graphite/storage/whisper/ 32 | 33 | # Enable daily log rotation. If disabled, a kill -HUP can be used after a manual rotate 34 | ENABLE_LOGROTATION = True 35 | 36 | # Specify the user to drop privileges to 37 | # If this is blank carbon runs as the user that invokes it 38 | # This user must have write access to the local data directory 39 | USER = 40 | # 41 | # NOTE: The above settings must be set under [relay] and [aggregator] 42 | # to take effect for those daemons as well 43 | 44 | # Limit the size of the cache to avoid swapping or becoming CPU bound. 45 | # Sorts and serving cache queries gets more expensive as the cache grows. 46 | # Use the value "inf" (infinity) for an unlimited cache size. 47 | MAX_CACHE_SIZE = inf 48 | 49 | # Limits the number of whisper update_many() calls per second, which effectively 50 | # means the number of write requests sent to the disk. This is intended to 51 | # prevent over-utilizing the disk and thus starving the rest of the system. 52 | # When the rate of required updates exceeds this, then carbon's caching will 53 | # take effect and increase the overall throughput accordingly. 54 | MAX_UPDATES_PER_SECOND = 500 55 | 56 | # If defined, this changes the MAX_UPDATES_PER_SECOND in Carbon when a 57 | # stop/shutdown is initiated. This helps when MAX_UPDATES_PER_SECOND is 58 | # relatively low and carbon has cached a lot of updates; it enables the carbon 59 | # daemon to shutdown more quickly. 60 | # MAX_UPDATES_PER_SECOND_ON_SHUTDOWN = 1000 61 | 62 | # Softly limits the number of whisper files that get created each minute. 63 | # Setting this value low (like at 50) is a good way to ensure your graphite 64 | # system will not be adversely impacted when a bunch of new metrics are 65 | # sent to it. The trade off is that it will take much longer for those metrics' 66 | # database files to all get created and thus longer until the data becomes usable. 67 | # Setting this value high (like "inf" for infinity) will cause graphite to create 68 | # the files quickly but at the risk of slowing I/O down considerably for a while. 69 | MAX_CREATES_PER_MINUTE = 50 70 | 71 | LINE_RECEIVER_INTERFACE = 0.0.0.0 72 | LINE_RECEIVER_PORT = 2003 73 | 74 | # Set this to True to enable the UDP listener. By default this is off 75 | # because it is very common to run multiple carbon daemons and managing 76 | # another (rarely used) port for every carbon instance is not fun. 77 | ENABLE_UDP_LISTENER = True 78 | UDP_RECEIVER_INTERFACE = 0.0.0.0 79 | UDP_RECEIVER_PORT = 2003 80 | 81 | PICKLE_RECEIVER_INTERFACE = 0.0.0.0 82 | PICKLE_RECEIVER_PORT = 2004 83 | 84 | # Set to false to disable logging of successful connections 85 | LOG_LISTENER_CONNECTIONS = True 86 | 87 | # Per security concerns outlined in Bug #817247 the pickle receiver 88 | # will use a more secure and slightly less efficient unpickler. 89 | # Set this to True to revert to the old-fashioned insecure unpickler. 90 | USE_INSECURE_UNPICKLER = False 91 | 92 | CACHE_QUERY_INTERFACE = 0.0.0.0 93 | CACHE_QUERY_PORT = 7002 94 | 95 | # Set this to False to drop datapoints received after the cache 96 | # reaches MAX_CACHE_SIZE. If this is True (the default) then sockets 97 | # over which metrics are received will temporarily stop accepting 98 | # data until the cache size falls below 95% MAX_CACHE_SIZE. 99 | USE_FLOW_CONTROL = True 100 | 101 | # By default, carbon-cache will log every whisper update and cache hit. This can be excessive and 102 | # degrade performance if logging on the same volume as the whisper data is stored. 103 | LOG_UPDATES = False 104 | LOG_CACHE_HITS = False 105 | LOG_CACHE_QUEUE_SORTS = True 106 | 107 | # The thread that writes metrics to disk can use on of the following strategies 108 | # determining the order in which metrics are removed from cache and flushed to 109 | # disk. The default option preserves the same behavior as has been historically 110 | # available in version 0.9.10. 111 | # 112 | # sorted - All metrics in the cache will be counted and an ordered list of 113 | # them will be sorted according to the number of datapoints in the cache at the 114 | # moment of the list's creation. Metrics will then be flushed from the cache to 115 | # disk in that order. 116 | # 117 | # max - The writer thread will always pop and flush the metric from cache 118 | # that has the most datapoints. This will give a strong flush preference to 119 | # frequently updated metrics and will also reduce random file-io. Infrequently 120 | # updated metrics may only ever be persisted to disk at daemon shutdown if 121 | # there are a large number of metrics which receive very frequent updates OR if 122 | # disk i/o is very slow. 123 | # 124 | # naive - Metrics will be flushed from the cache to disk in an unordered 125 | # fashion. This strategy may be desirable in situations where the storage for 126 | # whisper files is solid state, CPU resources are very limited or deference to 127 | # the OS's i/o scheduler is expected to compensate for the random write 128 | # pattern. 129 | # 130 | CACHE_WRITE_STRATEGY = sorted 131 | 132 | # On some systems it is desirable for whisper to write synchronously. 133 | # Set this option to True if you'd like to try this. Basically it will 134 | # shift the onus of buffering writes from the kernel into carbon's cache. 135 | WHISPER_AUTOFLUSH = False 136 | 137 | # By default new Whisper files are created pre-allocated with the data region 138 | # filled with zeros to prevent fragmentation and speed up contiguous reads and 139 | # writes (which are common). Enabling this option will cause Whisper to create 140 | # the file sparsely instead. Enabling this option may allow a large increase of 141 | # MAX_CREATES_PER_MINUTE but may have longer term performance implications 142 | # depending on the underlying storage configuration. 143 | # WHISPER_SPARSE_CREATE = False 144 | 145 | # Only beneficial on linux filesystems that support the fallocate system call. 146 | # It maintains the benefits of contiguous reads/writes, but with a potentially 147 | # much faster creation speed, by allowing the kernel to handle the block 148 | # allocation and zero-ing. Enabling this option may allow a large increase of 149 | # MAX_CREATES_PER_MINUTE. If enabled on an OS or filesystem that is unsupported 150 | # this option will gracefully fallback to standard POSIX file access methods. 151 | WHISPER_FALLOCATE_CREATE = True 152 | 153 | # Enabling this option will cause Whisper to lock each Whisper file it writes 154 | # to with an exclusive lock (LOCK_EX, see: man 2 flock). This is useful when 155 | # multiple carbon-cache daemons are writing to the same files 156 | # WHISPER_LOCK_WRITES = False 157 | 158 | # Set this to True to enable whitelisting and blacklisting of metrics in 159 | # CONF_DIR/whitelist and CONF_DIR/blacklist. If the whitelist is missing or 160 | # empty, all metrics will pass through 161 | # USE_WHITELIST = False 162 | 163 | # By default, carbon itself will log statistics (such as a count, 164 | # metricsReceived) with the top level prefix of 'carbon' at an interval of 60 165 | # seconds. Set CARBON_METRIC_INTERVAL to 0 to disable instrumentation 166 | # CARBON_METRIC_PREFIX = carbon 167 | # CARBON_METRIC_INTERVAL = 60 168 | 169 | # Enable AMQP if you want to receve metrics using an amqp broker 170 | # ENABLE_AMQP = False 171 | 172 | # Verbose means a line will be logged for every metric received 173 | # useful for testing 174 | # AMQP_VERBOSE = False 175 | 176 | # AMQP_HOST = localhost 177 | # AMQP_PORT = 5672 178 | # AMQP_VHOST = / 179 | # AMQP_USER = guest 180 | # AMQP_PASSWORD = guest 181 | # AMQP_EXCHANGE = graphite 182 | # AMQP_METRIC_NAME_IN_BODY = False 183 | 184 | # The manhole interface allows you to SSH into the carbon daemon 185 | # and get a python interpreter. BE CAREFUL WITH THIS! If you do 186 | # something like time.sleep() in the interpreter, the whole process 187 | # will sleep! This is *extremely* helpful in debugging, assuming 188 | # you are familiar with the code. If you are not, please don't 189 | # mess with this, you are asking for trouble :) 190 | # 191 | # ENABLE_MANHOLE = False 192 | # MANHOLE_INTERFACE = 127.0.0.1 193 | # MANHOLE_PORT = 7222 194 | # MANHOLE_USER = admin 195 | # MANHOLE_PUBLIC_KEY = ssh-rsa AAAAB3NzaC1yc2EAAAABiwAaAIEAoxN0sv/e4eZCPpi3N3KYvyzRaBaMeS2RsOQ/cDuKv11dlNzVeiyc3RFmCv5Rjwn/lQ79y0zyHxw67qLyhQ/kDzINc4cY41ivuQXm2tPmgvexdrBv5nsfEpjs3gLZfJnyvlcVyWK/lId8WUvEWSWHTzsbtmXAF2raJMdgLTbQ8wE= 196 | 197 | # Patterns for all of the metrics this machine will store. Read more at 198 | # http://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol#Bindings 199 | # 200 | # Example: store all sales, linux servers, and utilization metrics 201 | # BIND_PATTERNS = sales.#, servers.linux.#, #.utilization 202 | # 203 | # Example: store everything 204 | # BIND_PATTERNS = # 205 | 206 | # To configure special settings for the carbon-cache instance 'b', uncomment this: 207 | #[cache:b] 208 | #LINE_RECEIVER_PORT = 2103 209 | #PICKLE_RECEIVER_PORT = 2104 210 | #CACHE_QUERY_PORT = 7102 211 | # and any other settings you want to customize, defaults are inherited 212 | # from [carbon] section. 213 | # You can then specify the --instance=b option to manage this instance 214 | 215 | 216 | 217 | [relay] 218 | LINE_RECEIVER_INTERFACE = 0.0.0.0 219 | LINE_RECEIVER_PORT = 2013 220 | PICKLE_RECEIVER_INTERFACE = 0.0.0.0 221 | PICKLE_RECEIVER_PORT = 2014 222 | 223 | # Set to false to disable logging of successful connections 224 | LOG_LISTENER_CONNECTIONS = True 225 | 226 | # Carbon-relay has several options for metric routing controlled by RELAY_METHOD 227 | # 228 | # Use relay-rules.conf to route metrics to destinations based on pattern rules 229 | #RELAY_METHOD = rules 230 | # 231 | # Use consistent-hashing for even distribution of metrics between destinations 232 | #RELAY_METHOD = consistent-hashing 233 | # 234 | # Use consistent-hashing but take into account an aggregation-rules.conf shared 235 | # by downstream carbon-aggregator daemons. This will ensure that all metrics 236 | # that map to a given aggregation rule are sent to the same carbon-aggregator 237 | # instance. 238 | # Enable this for carbon-relays that send to a group of carbon-aggregators 239 | #RELAY_METHOD = aggregated-consistent-hashing 240 | RELAY_METHOD = rules 241 | 242 | # If you use consistent-hashing you can add redundancy by replicating every 243 | # datapoint to more than one machine. 244 | REPLICATION_FACTOR = 1 245 | 246 | # This is a list of carbon daemons we will send any relayed or 247 | # generated metrics to. The default provided would send to a single 248 | # carbon-cache instance on the default port. However if you 249 | # use multiple carbon-cache instances then it would look like this: 250 | # 251 | # DESTINATIONS = 127.0.0.1:2004:a, 127.0.0.1:2104:b 252 | # 253 | # The general form is IP:PORT:INSTANCE where the :INSTANCE part is 254 | # optional and refers to the "None" instance if omitted. 255 | # 256 | # Note that if the destinations are all carbon-caches then this should 257 | # exactly match the webapp's CARBONLINK_HOSTS setting in terms of 258 | # instances listed (order matters!). 259 | # 260 | # If using RELAY_METHOD = rules, all destinations used in relay-rules.conf 261 | # must be defined in this list 262 | DESTINATIONS = 127.0.0.1:2004 263 | 264 | # This defines the maximum "message size" between carbon daemons. 265 | # You shouldn't need to tune this unless you really know what you're doing. 266 | MAX_DATAPOINTS_PER_MESSAGE = 500 267 | MAX_QUEUE_SIZE = 10000 268 | 269 | # Set this to False to drop datapoints when any send queue (sending datapoints 270 | # to a downstream carbon daemon) hits MAX_QUEUE_SIZE. If this is True (the 271 | # default) then sockets over which metrics are received will temporarily stop accepting 272 | # data until the send queues fall below 80% MAX_QUEUE_SIZE. 273 | USE_FLOW_CONTROL = True 274 | 275 | # Set this to True to enable whitelisting and blacklisting of metrics in 276 | # CONF_DIR/whitelist and CONF_DIR/blacklist. If the whitelist is missing or 277 | # empty, all metrics will pass through 278 | # USE_WHITELIST = False 279 | 280 | # By default, carbon itself will log statistics (such as a count, 281 | # metricsReceived) with the top level prefix of 'carbon' at an interval of 60 282 | # seconds. Set CARBON_METRIC_INTERVAL to 0 to disable instrumentation 283 | # CARBON_METRIC_PREFIX = carbon 284 | # CARBON_METRIC_INTERVAL = 60 285 | 286 | 287 | [aggregator] 288 | LINE_RECEIVER_INTERFACE = 0.0.0.0 289 | LINE_RECEIVER_PORT = 2023 290 | 291 | PICKLE_RECEIVER_INTERFACE = 0.0.0.0 292 | PICKLE_RECEIVER_PORT = 2024 293 | 294 | # Set to false to disable logging of successful connections 295 | LOG_LISTENER_CONNECTIONS = True 296 | 297 | # If set true, metric received will be forwarded to DESTINATIONS in addition to 298 | # the output of the aggregation rules. If set false the carbon-aggregator will 299 | # only ever send the output of aggregation. 300 | FORWARD_ALL = True 301 | 302 | # This is a list of carbon daemons we will send any relayed or 303 | # generated metrics to. The default provided would send to a single 304 | # carbon-cache instance on the default port. However if you 305 | # use multiple carbon-cache instances then it would look like this: 306 | # 307 | # DESTINATIONS = 127.0.0.1:2004:a, 127.0.0.1:2104:b 308 | # 309 | # The format is comma-delimited IP:PORT:INSTANCE where the :INSTANCE part is 310 | # optional and refers to the "None" instance if omitted. 311 | # 312 | # Note that if the destinations are all carbon-caches then this should 313 | # exactly match the webapp's CARBONLINK_HOSTS setting in terms of 314 | # instances listed (order matters!). 315 | DESTINATIONS = 127.0.0.1:2004 316 | 317 | # If you want to add redundancy to your data by replicating every 318 | # datapoint to more than one machine, increase this. 319 | REPLICATION_FACTOR = 1 320 | 321 | # This is the maximum number of datapoints that can be queued up 322 | # for a single destination. Once this limit is hit, we will 323 | # stop accepting new data if USE_FLOW_CONTROL is True, otherwise 324 | # we will drop any subsequently received datapoints. 325 | MAX_QUEUE_SIZE = 10000 326 | 327 | # Set this to False to drop datapoints when any send queue (sending datapoints 328 | # to a downstream carbon daemon) hits MAX_QUEUE_SIZE. If this is True (the 329 | # default) then sockets over which metrics are received will temporarily stop accepting 330 | # data until the send queues fall below 80% MAX_QUEUE_SIZE. 331 | USE_FLOW_CONTROL = True 332 | 333 | # This defines the maximum "message size" between carbon daemons. 334 | # You shouldn't need to tune this unless you really know what you're doing. 335 | MAX_DATAPOINTS_PER_MESSAGE = 500 336 | 337 | # This defines how many datapoints the aggregator remembers for 338 | # each metric. Aggregation only happens for datapoints that fall in 339 | # the past MAX_AGGREGATION_INTERVALS * intervalSize seconds. 340 | MAX_AGGREGATION_INTERVALS = 5 341 | 342 | # By default (WRITE_BACK_FREQUENCY = 0), carbon-aggregator will write back 343 | # aggregated data points once every rule.frequency seconds, on a per-rule basis. 344 | # Set this (WRITE_BACK_FREQUENCY = N) to write back all aggregated data points 345 | # every N seconds, independent of rule frequency. This is useful, for example, 346 | # to be able to query partially aggregated metrics from carbon-cache without 347 | # having to first wait rule.frequency seconds. 348 | # WRITE_BACK_FREQUENCY = 0 349 | 350 | # Set this to True to enable whitelisting and blacklisting of metrics in 351 | # CONF_DIR/whitelist and CONF_DIR/blacklist. If the whitelist is missing or 352 | # empty, all metrics will pass through 353 | # USE_WHITELIST = False 354 | 355 | # By default, carbon itself will log statistics (such as a count, 356 | # metricsReceived) with the top level prefix of 'carbon' at an interval of 60 357 | # seconds. Set CARBON_METRIC_INTERVAL to 0 to disable instrumentation 358 | # CARBON_METRIC_PREFIX = carbon 359 | # CARBON_METRIC_INTERVAL = 60 --------------------------------------------------------------------------------