Since Arch, Nginx and Ansible are already all pretty mature tools by themselves, I though that installing Nginx on Arch system using Ansible playbook would be a matter of seconds. But judging from an actual experience, it is a little bit harder.

The official ansible nginx role does not support Arch. Then there is a role made by Jeff Geerling, which does support Arch, but with a quirk. The role does run sometimes (I was not able to isolate 100%, usually after completely removing Nginx package), but then won't run again.

TASK [geerlingguy.nginx : Ensure nginx service is running as configured.] ***************
fatal: []: FAILED! => {"changed": false, "msg": "Unable to start service nginx: Job for nginx.service failed because the control process exited with error code.\nSee \"systemctl status nginx.service\" and \"journalctl -xeu nginx.service\" for details.\n"}

The reason is that Nginx won't restart with a provided nginx.conf template.

sudo systemctl restart nginx # fail
sudo journalctl -xeu nginx

The journal contains:

[emerg] 870#870: "pid" directive is duplicate in /etc/nginx/nginx.conf:4

When commenting the line 4 Nginx restarts flawlessly.

The reason for this is that PID is also referenced in /usr/lib/systemd/system/nginx.service as a line:

ExecStart=/usr/bin/nginx -g 'pid /run/; error_log stderr;'

If I understand it correctly, there is no need for L4 in nginx.conf when managing Arch. More relevant information at

The setup-Archlinux.yml is run before nginx.conf template is copied over. Should there be another Arch related task below the after "Copy" but before "Ensure running", or perhaps should there be an Arch specific template for nginx.conf file? Templating is impractical here, as L3-L4 lines are the only lines that are not inside a block, so I propose to put them in a in a jinja2 block as well as a path of least resistance. Not sure about the L1 (not in a block but no issue reported).


  1. Edit vars/Archlinux.yml and remove L6 containing nginx_pidfile: /run/
  2. Edit templates/nginx.conf.j2 and put L5 into the conditional block:
{% if nginx_pidfile is defined %}
pid        {{ nginx_pidfile }};
{% endif %}

I am not sure if this is the best solution, but proves as proof of concept, until the upstream provides a solution.

This is a 39th post of #100daystooffload.