YAML(/ˈjæməl/,尾音相似camel駱駝)是一個可讀性高,用來表達數據序列的格式。YAML參考了其餘多種語言,包括:C語言、Python、Perl,並從XML、電子郵件的數據格式(RFC 2822)中得到靈感。Clark Evans在2001年首次發表了這種語言,另外Ingy döt Net與Oren Ben-Kiki也是這語言的共同設計者。目前已經有數種編程語言或腳本語言支持(或者說解析)這種語言。php
YAML是"YAML Ain't a Markup Language"(YAML不是一種標記語言)的遞歸縮寫。在開發的這種語言時,YAML 的意思實際上是:"Yet Another Markup Language"(還是一種標記語言),但爲了強調這種語言以數據作爲中心,而不是以標記語言爲重點,而用反向縮略語重命名。html
一個簡單的示例: 遠程主機np1.lxk.com安裝memcached並設置開機自動啓動node
- hosts: np1.lxk.com remote_user: root tasks: - name: 'install memcached package' yum: 'name=memcached state=installed' - name: 'start memcached server' service: 'name=memcached enabled=true state=started' - hosts: np2.lxk.com remote_user: root tasks: - name: install memcached package yum: name=memcached state=installed - name: start memcached server service: name=memcached enabled=true state=started
[root@nfs ansible_workshop]# ansible-playbook --syntax-check memcached.yaml playbook: memcached.yaml
PLAY [np1.lxk.com] ****nginx
TASK [Gathering Facts] ****
ok: [np1.lxk.com]web
TASK [install memcached package] **
ok: [np1.lxk.com]shell
TASK [start memcached server] *****
ok: [np1.lxk.com]編程
PLAY [np2.lxk.com] ****vim
TASK [Gathering Facts] ****
ok: [np2.lxk.com]centos
TASK [install memcached package] **
changed: [np2.lxk.com]tomcat
TASK [start memcached server] *****
changed: [np2.lxk.com]
PLAY RECAP ****
np1.lxk.com : ok=3 changed=0 unreachable=0 failed=0
np2.lxk.com : ok=3 changed=2 unreachable=0 failed=0
4. 運行memcached.yaml ```leaf [root@nfs ansible_workshop]# ansible-playbook memcached.yaml PLAY [np1.lxk.com] ******************************************************************************************************** TASK [Gathering Facts] **************************************************************************************************** ok: [np1.lxk.com] TASK [install memcached package] ****************************************************************************************** ok: [np1.lxk.com] TASK [start memcached server] ********************************************************************************************* ok: [np1.lxk.com] PLAY [np2.lxk.com] ******************************************************************************************************** TASK [Gathering Facts] **************************************************************************************************** ok: [np2.lxk.com] TASK [install memcached package] ****************************************************************************************** changed: [np2.lxk.com] TASK [start memcached server] ********************************************************************************************* changed: [np2.lxk.com] PLAY RECAP **************************************************************************************************************** np1.lxk.com : ok=3 changed=0 unreachable=0 failed=0 np2.lxk.com : ok=3 changed=2 unreachable=0 failed=0
[root@np1 ~]# systemctl is-enabled memcached enabled #已設置爲開機自動運行 [root@np1 ~]# systemctl status memcached #已經啓動成功 ● memcached.service - Memcached Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; vendor preset: disabled) Active: active (running) since Sun 2018-06-10 12:20:56 CST; 5min ago Main PID: 18030 (memcached) CGroup: /system.slice/memcached.service └─18030 /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024 Jun 10 12:20:56 np1.lxk.com systemd[1]: Started Memcached. Jun 10 12:20:56 np1.lxk.com systemd[1]: Starting Memcached...
[root@nfs ansible_workshop]# ansible-playbook --check --list-hosts memcached.yaml playbook: memcached.yaml play #1 (np1.lxk.com): np1.lxk.com TAGS: [] pattern: [u'np1.lxk.com'] hosts (1): np1.lxk.com play #2 (np2.lxk.com): np2.lxk.com TAGS: [] pattern: [u'np2.lxk.com'] hosts (1): np2.lxk.com
示例: 爲memcached提供監聽在11311端口的配置文件,並重啓服務
- hosts: np1.lxk.com remote_user: root tasks: - name: 'install memcached package' yum: 'name=memcached state=installed' - name: 'install conf file' copy: 'src=/etc/sysconfig/memcached dest=/etc/sysconfig/memcached' notify: 'restart memcached service' - name: 'start memcached server' service: 'name=memcached enabled=true state=started' handlers: - name: 'restart memcached service' service: 'name=memcached state=restarted'
[root@nfs ansible_workshop]# ansible-playbook --syntax-check memcached_v2.yaml playbook: memcached_v2.yaml
跟下面一步內容相同,只是語句不一樣,語句以下: ~]# ansible-playbook --check memcached_v2.yaml
[root@nfs ansible_workshop]# ansible-playbook memcached_v2.yaml PLAY [np1.lxk.com] ******************************************************************************************************** TASK [Gathering Facts] **************************************************************************************************** ok: [np1.lxk.com] TASK [install memcached package] ****************************************************************************************** ok: [np1.lxk.com] TASK [install conf file] ************************************************************************************************** changed: [np1.lxk.com] TASK [start memcached server] ********************************************************************************************* ok: [np1.lxk.com] RUNNING HANDLER [restart memcached service] ******************************************************************************* changed: [np1.lxk.com] PLAY RECAP **************************************************************************************************************** np1.lxk.com : ok=5 changed=2 unreachable=0 failed=0
[root@np1 ~]# systemctl status memcached ● memcached.service - Memcached Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; vendor preset: disabled) Active: active (running) since Sun 2018-06-10 13:28:42 CST; 5min ago Main PID: 19732 (memcached) CGroup: /system.slice/memcached.service └─19732 /usr/bin/memcached -u memcached -p 11311 -m 64 -c 1024 Jun 10 13:28:42 np1.lxk.com systemd[1]: Started Memcached. Jun 10 13:28:42 np1.lxk.com systemd[1]: Starting Memcached... #經過ss -tnlp也能夠查看,可是太長了。這裏也能夠看到memcached監聽的端口爲11311
注:若配置文件發生改變,再一次運行memcached_v2.yaml時,會觸發複製配置文件並重啓服務。配置文件不發生改變,不會觸發。
示例:經過自定義變量安裝tree
- hosts: np1.lxk.com remote_user: root vars: - pkgname: 'tree' tasks: - name: install {{ pkgname }} yum: name={{ pkgname }} state=installed
[root@nfs ansible_workshop]# ansible-playbook pkgs.yaml PLAY [np1.lxk.com] ******************************************************************************************************** TASK [Gathering Facts] **************************************************************************************************** ok: [np1.lxk.com] TASK [install tree] ******************************************************************************************************* ok: [np1.lxk.com] PLAY RECAP **************************************************************************************************************** np1.lxk.com : ok=2 changed=0 unreachable=0 failed=0
示例2:使用pkgs.yaml文件,不修改文件內容,經過ansible-playbook中的-e選項給定變量的參數
[root@nfs ansible_workshop]# ansible-playbook --check -e pkgname='httpd' pkgs.yaml PLAY [np1.lxk.com] ******************************************************************************************************** TASK [Gathering Facts] **************************************************************************************************** ok: [np1.lxk.com] TASK [install httpd] ****************************************************************************************************** ok: [np1.lxk.com] PLAY RECAP **************************************************************************************************************** np1.lxk.com : ok=2 changed=0 unreachable=0 failed=0
能夠看到運行時的TASK對象變爲了httpd
示例:組中的主機傳遞參數:
/etc/ansible/hosts配置:
[root@nfs ansible_workshop]# tail -15 /etc/ansible/hosts [db] node1.lxk.com node2.lxk.com [db:vars] pkgname='mariadb-server' [web] np1.lxk.com np2.lxk.com [web:vars] pkgname='nginx' [nfs] nfs.lxk.com
yaml文件內容:
- hosts: db remote_user: root tasks: - name: install {{ pkgname }} yum: name={{ pkgname }} state=installed - hosts: web remote_user: root tasks: - name: install {{ pkgname }} yum: name={{ pkgname }} state=installed
幹跑模式結果:
[root@nfs ansible_workshop]# ansible-playbook --check pkgs.yaml PLAY [db] ***************************************************************************************************************** TASK [Gathering Facts] **************************************************************************************************** ok: [node2.lxk.com] ok: [node1.lxk.com] TASK [install mariadb-server] ********************************************************************************************* ok: [node2.lxk.com] ok: [node1.lxk.com] PLAY [web] **************************************************************************************************************** TASK [Gathering Facts] **************************************************************************************************** ok: [np2.lxk.com] ok: [np1.lxk.com] TASK [install nginx] ****************************************************************************************************** changed: [np2.lxk.com] changed: [np1.lxk.com] PLAY RECAP **************************************************************************************************************** node1.lxk.com : ok=2 changed=0 unreachable=0 failed=0 node2.lxk.com : ok=2 changed=0 unreachable=0 failed=0 np1.lxk.com : ok=2 changed=1 unreachable=0 failed=0 np2.lxk.com : ok=2 changed=1 unreachable=0 failed=0
經過以上示例能夠看出,在hosts文件中也能夠傳遞參數。
示例:經過invertory參數鏈接目標主機
[root@node1 ~]# vim /etc/ssh/sshd_config 增長如下內容: port 22 port 22022 [root@node1 ~]# systemctl restart sshd [root@node1 ~]# ss -tnl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 *:22 *:* LISTEN 0 100 127.0.0.1:25 *:* LISTEN 0 128 *:22022 *:* LISTEN 0 50 *:3306 *:* LISTEN 0 128 :::22 :::* LISTEN 0 100 ::1:25 :::* LISTEN 0 128 :::22022 :::*
node1.lxk.com ansible_ssh_port=22022 node2.lxk.com ansible_ssh_root=root ansible_ssh_pass=magedu.com
[root@nfs ansible_workshop]# cat pkgs.yaml - hosts: all remote_user: root vars: - pkgname: 'tree' tasks: - name: install {{ pkgname }} yum: name={{ pkgname }} state=installed
[root@nfs ansible_workshop]# ansible all -m shell -a '[[ -f /etc/hosts ]]' node1.lxk.com | SUCCESS | rc=0 >> node2.lxk.com | SUCCESS | rc=0 >>
字面量: 字符串:使用單引號或雙引號; 數字:整數,浮點數; 列表:[item1, item2, ...] 元組:(item1, item2, ...) 字典:{key1:value1, key2:value2, ...} 布爾型:true/false
運算符: 算術運算: +, -, *, /, //, %, ** 比較操做: ==, !=, >, >=, <, <= 邏輯運算: and, or, not
示例:
- hosts: websrvs remote_user: root tasks: - name: install nginx yum: name=nginx state=present - name: install conf file template: src=files/nginx.conf.j2 dest=/etc/nginx/nginx.conf notify: restart nginx tags: instconf - name: start nginx service service: name=nginx state=started handlers: - name: restart nginx service: name=nginx state=restarted
模板配置文件 :nginx.conf.j2
worker_processes {{ ansible_processor_vcpus - 1 }}; listen {{ http_port }}; server_name
示例1: 複製模板至目標主機:
主機列表:
node1.lxk.com node2.lxk.com np1.lxk.com np2.lxk.com nfs.lxk.com
[root@nfs ansible_workshop]# cat test.j2 hostname: {{ansible_fqdn }} #調用系統變量中的主機名 vars: {{ pkgname }} #調用自定義變量,可在ansible-playbook中用-e選項給定
[root@nfs ansible_workshop]# cat test.yaml - hosts: all remote_user: root tasks: - name: install file template: src=/root/ansible_workshop/test.j2 dest=/tmp/test.conf
[root@nfs ansible_workshop]# ansible-playbook -e pkgname='somepkg' test.yaml PLAY [all] **************************************************************************************************************** TASK [Gathering Facts] **************************************************************************************************** ok: [node2.lxk.com] ok: [np1.lxk.com] ok: [np2.lxk.com] ok: [node1.lxk.com] ok: [nfs.lxk.com] TASK [install file] ******************************************************************************************************* changed: [np2.lxk.com] changed: [np1.lxk.com] changed: [node2.lxk.com] changed: [node1.lxk.com] changed: [nfs.lxk.com] PLAY RECAP **************************************************************************************************************** nfs.lxk.com : ok=2 changed=1 unreachable=0 failed=0 node1.lxk.com : ok=2 changed=1 unreachable=0 failed=0 node2.lxk.com : ok=2 changed=1 unreachable=0 failed=0 np1.lxk.com : ok=2 changed=1 unreachable=0 failed=0 np2.lxk.com : ok=2 changed=1 unreachable=0 failed=0
示例2: 在目標主機上安裝tomcat,配置文件中jvmRoute設置爲各自主機名,並提供manaager-gui和admin-gui的登陸用戶
<Engine name="Catalina" defaultHost="localhost" jvmRoute="{{ ansible_hostname }}" >
<role rolename="manaager-gui"/> <role rolename="admin-gui"/> <user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/>
- hosts: tomcat remote_user: root tasks: - name: install tomcat-admin-webapps yum: name=tomcat-admin-webapps state=installed - name: install tomcat-users.xml copy: src=/root/ansible_workshop/tomcat-users.xml dest=/etc/tomcat/tomcat-users.xml owner=root group=tomcat mode=0640 notify: restart tomcat - name: install server.xml template: src=/root/ansible_workshop/server.xml.j2 dest=/etc/tomcat/server.xml owner=root group=tomcat - name: start tomcat service: name=tomcat state=started handlers: - name: restart tomcat service: name=tomcat state=restarted
[root@nfs ansible_workshop]# ansible-playbook tomcat.yaml PLAY [tomcat] ************************************************************************************************************* TASK [Gathering Facts] **************************************************************************************************** ok: [np2.lxk.com] ok: [np1.lxk.com] TASK [install tomcat-admin-webapps] *************************************************************************************** ok: [np2.lxk.com] ok: [np1.lxk.com] TASK [install tomcat-users.xml] ******************************************************************************************* changed: [np2.lxk.com] changed: [np1.lxk.com] TASK [install server.xml] ************************************************************************************************* changed: [np1.lxk.com] changed: [np2.lxk.com] TASK [start tomcat] ******************************************************************************************************* changed: [np2.lxk.com] changed: [np1.lxk.com] RUNNING HANDLER [restart tomcat] ****************************************************************************************** changed: [np2.lxk.com] changed: [np1.lxk.com] PLAY RECAP **************************************************************************************************************** np1.lxk.com : ok=6 changed=4 unreachable=0 failed=0 np2.lxk.com : ok=6 changed=4 unreachable=0 failed=0
[root@np1 ~]# grep np1 /etc/tomcat/server.xml <Engine name="Catalina" defaultHost="localhost" jvmRoute="np1" > [root@np1 ~]# cat /etc/tomcat/tomcat-users.xml | head -44 | tail -3 <role rolename="manaager-gui"/> <role rolename="admin-gui"/> <user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/>
tags用於讓用戶選擇運行playbook中的部分代碼。ansible具備冪等性,所以會自動跳過沒有變化的部分,即使如此,有些代碼爲測試其確實沒有發生變化的時間依然會很是地長。此時,若是確信其沒有變化,就能夠經過tags跳過此些代碼片段。
示例:
- hosts: tomcat remote_user: root tasks: - name: install tomcat-admin-webapps yum: name=tomcat-admin-webapps state=installed - name: install tomcat-users.xml copy: src=/root/ansible_workshop/tomcat-users.xml dest=/etc/tomcat/tomcat-users.xml owner=root group=tomcat mode=0640 tags: tcusers notify: restart tomcat - name: install server.xml template: src=/root/ansible_workshop/server.xml.j2 dest=/etc/tomcat/server.xml owner=root group=tomcat notify: restart tomcat tags: serverconf - name: start tomcat service: name=tomcat state=started handlers: - name: restart tomcat service: name=tomcat state=restarted
[root@nfs ansible_workshop]# ansible-playbook --check --tags=tcusers tomcat.yaml PLAY [tomcat] ************************************************************************************************************* TASK [Gathering Facts] **************************************************************************************************** ok: [np1.lxk.com] ok: [np2.lxk.com] TASK [install tomcat-users.xml] ******************************************************************************************* ok: [np2.lxk.com] ok: [np1.lxk.com] PLAY RECAP **************************************************************************************************************** np1.lxk.com : ok=2 changed=0 unreachable=0 failed=0 np2.lxk.com : ok=2 changed=0 unreachable=0 failed=0
經測試,使用--tags指定tags以後,只運行了指定tags的任務。
條件測試:when語句:在task中使用,jinja2的語法格式
示例:當系統版本是7時,複製nginx.conf.c7.j2。系統版本是6時,複製nginx.conf.c6
tasks: - name: install conf file to centos7 template: src=files/nginx.conf.c7.j2 when: ansible_distribution_major_version == "7" - name: install conf file to centos6 template: src=files/nginx.conf.c6.j2 when: ansible_distribution_major_version == "6"
循環:迭代,須要重複執行的任務;
對迭代項的引用,固定變量名爲」item「,然後,要在task中使用with_items給定要迭代的元素列表;
- name: install some packages yum: name={{ item }} state=present #item:固定字符,不能更改 with_items: #使用如下值給item賦值 - nginx - memcached - php-fpm - name: add some groups group: name={{ item }} state=present with_items: - group11 - group12 - group13 - name: add some users user: name={{ item.name }} group={{ item.group }} state=present #name={{ item.name }} 指明變量名 #group={{ item.group}} 指明變量組 with_items: - { name: 'user11', group: 'group11' } - { name: 'user12', group: 'group12' } - { name: 'user13', group: 'group13' }
示例:在目標主機上一次性安裝三個包並啓動起來
- hosts: np1.lxk.com remote_user: root tasks: - name: install {{ item }} yum: name={{ item }} state=installed with_items: - nginx - memcached - php-fpm - name: start {{ item }} service: name={{ item }} state=started with_items: - nginx - memcached - php-fpm
[root@nfs ansible_workshop]# ansible-playbook nmp.yaml PLAY [np1.lxk.com] ******************************************************************************************************** TASK [Gathering Facts] **************************************************************************************************** ok: [np1.lxk.com] TASK [install {{ item }}] ************************************************************************************************* ok: [np1.lxk.com] => (item=[u'nginx', u'memcached', u'php-fpm']) TASK [start {{ item }}] *************************************************************************************************** changed: [np1.lxk.com] => (item=nginx) ok: [np1.lxk.com] => (item=memcached) ok: [np1.lxk.com] => (item=php-fpm) PLAY RECAP **************************************************************************************************************** np1.lxk.com : ok=3 changed=1 unreachable=0 failed=0
roles
ansilbe自1.2版本引入的新特性,用於層次性、結構化地組織playbook。roles可以根據層次型結構自動裝載變量文件、tasks以及handlers等。要使用roles只須要在playbook中使用include指令便可。簡單來說,roles就是經過分別將變量、文件、任務、模板及處理器放置於單獨的目錄中,並能夠便捷地include它們的一種機制。角色通常用於基於主機構建服務的場景中,但也能夠是用於構建守護進程等場景中。
一個roles的案例以下所示:
site.yml webservers.yml dbservers.yml roles/ common/ files/ templates/ tasks/ handlers/ vars/ meta/ webservers/ files/ templates/ tasks/ handlers/ vars/ meta/
而在playbook中,能夠這樣使用roles:
- hosts: webservers roles: - common - webservers
也能夠向roles傳遞參數,例如:
- hosts: webservers roles: - common - { role: foo_app_instance, dir: '/opt/a', port: 5000 } - { role: foo_app_instance, dir: '/opt/b', port: 5001 }
甚至也能夠條件式地使用roles,例如:
- hosts: webservers roles: - { role: some_role, when: "ansible_os_family == 'RedHat'" }
建立role的步驟
(1) 建立以roles命名的目錄; (2) 在roles目錄中分別建立以各角色名稱命名的目錄,如webservers等; (3) 在每一個角色命名的目錄中分別建立files、handlers、meta、tasks、templates和vars目錄;用不到的目錄能夠建立爲空目錄,也能夠不建立; (4) 在playbook文件中,調用各角色;
role內各目錄中可用的文件
tasks目錄:至少應該包含一個名爲main.yml的文件,其定義了此角色的任務列表;此文件可使用include包含其它的位於此目錄中的task文件; files目錄:存放由copy或script等模塊調用的文件; templates目錄:template模塊會自動在此目錄中尋找Jinja2模板文件; handlers目錄:此目錄中應當包含一個main.yml文件,用於定義此角色用到的各handler;在handler中使用include包含的其它的handler文件也應該位於此目錄中; vars目錄:應當包含一個main.yml文件,用於定義此角色用到的變量; meta目錄:應當包含一個main.yml文件,用於定義此角色的特殊設定及其依賴關係;ansible 1.3及其之後的版本才支持; default目錄:爲當前角色設定默認變量時使用此目錄;應當包含一個main.yml文件;
示例1:安裝nginx併爲其提供配置文件和主頁
/etc/ansible/role
[root@nfs roles]# mkdir -pv ./nginx/{files,templates,tasks,handlers,vars,meta,default}
[root@nfs nginx]# cat tasks/main.yml #提供任務列表 - name: install epel-release package yum: name=epel-release state=installed - name: install nginx package yum: name=nginx state=installed - name: create doc root file: path={{ docroot }} state=directory - name: install home page copy: src=index.html dest={{ docroot }}/ - name: install conf file template: src=server.conf.j2 dest=/etc/nginx/conf.d/server.conf notify: reload nginx - name: start nginx service service: name=nginx enabled=true state=started [root@nfs nginx]# cat vars/main.yml #提供變量 docroot: /data/nginx/ [root@nfs nginx]# cat templates/server.conf.j2 #提供配置文件模板 server { listen 80; server_name {{ ansible_fqdn }} {{ ansible_hostname }} ; location / { root {{ docroot }}; index index.html index.jsp; } } [root@nfs nginx]# cat files/index.html #提供主頁 <h1> Welcome to Nginx</h1> [root@nfs nginx]# cat handlers/main.yml #提供條件式觸發文件 - name: reload nginx service: name=nginx state=reloaded
在其它位置提供nginx.yaml文件:
[root@nfs ansible_workshop]# cat nginx.yaml - hosts: np1.lxk.com remote_user: root roles: - nginx
[root@nfs ansible_workshop]# ansible-playbook nginx.yaml PLAY [np1.lxk.com] ******************************************************************************************************** TASK [Gathering Facts] **************************************************************************************************** ok: [np1.lxk.com] TASK [nginx : install epel-release package] ******************************************************************************* changed: [np1.lxk.com] TASK [nginx : install nginx package] ************************************************************************************** ok: [np1.lxk.com] TASK [nginx : create doc root] ******************************************************************************************** changed: [np1.lxk.com] TASK [nginx : install home page] ****************************************************************************************** changed: [np1.lxk.com] TASK [nginx : install conf file] ****************************************************************************************** changed: [np1.lxk.com] TASK [nginx : start nginx service] **************************************************************************************** changed: [np1.lxk.com] RUNNING HANDLER [nginx : reload nginx] ************************************************************************************ changed: [np1.lxk.com] PLAY RECAP **************************************************************************************************************** np1.lxk.com : ok=8 changed=6 unreachable=0 failed=0
示例2:
同示例1,修改如下內容:
[root@nfs nginx]# cat templates/proxy.conf.j2 server { listen 80; server_name {{ ansible_fqdn }} {{ ansible_hostname }}; location / { proxy_pass {{ backendurl }}; } }
[root@nfs nginx]# cat vars/main.yml servertype: web backendurl: 'http://127.0.0.1:8080' docroot: /data/nginx/
[root@nfs nginx]# cat tasks/main.yml - name: install epel-release package yum: name=epel-release state=installed - name: install nginx package yum: name=nginx state=installed - name: create doc root file: path={{ docroot }} state=directory when: servertype == 'web' - name: install home page copy: src=index.html dest={{ docroot }}/ when: servertype == 'web' - name: install web conf file template: src=server.conf.j2 dest=/etc/nginx/conf.d/server.conf when: servertype == 'web' notify: reload nginx - name: install proxy conf file template: src=proxy.conf.j2 dest=/etc/nginx/conf.d/server.conf when: servertype == 'proxy' notify: reload nginx - name: start nginx service service: name=nginx enabled=true state=started
4.nginx.yaml修改成以下:
[root@nfs nginx]# cat /root/ansible_workshop/nginx.yaml - hosts: tomcat remote_user: root roles: - { role: nginx, servertype: proxy } - hosts: web remote_user: root roles: - nginx