commit 8f14b1fb1cff6c087b2c086c40ed07b026e5672b from: gonzalo date: Tue Aug 29 09:58:51 2023 UTC Update my this playbook to deploy httpd sites/vhosts, it meant to be use it as many times as you want to keep adding new domains, test in other setups are welcome :) commit - 598e7f37abea2352d383073f3557a0700b28fe19 commit + 8f14b1fb1cff6c087b2c086c40ed07b026e5672b blob - ba5dc1f214d59543dfd947176373a93f4c9d9467 blob + fe79dd890a84fd966586b9b7a1b3b41f6df30f63 --- README.md +++ README.md @@ -11,8 +11,14 @@ OpenBSD >=6.1 -{release,stable,current} Notes ----- -You need to run this after the playbook: +To add the domains you need to modify the file "defaults/main.yml" and adapt it to +what you want, if you have already a /etc/httpd.conf the playbook will just add the +includes of the vhosts added (BE CAREFUL BARELY TESTED :) otherwise it will copy the +httpd.conf in the templates directory and also add at the end the includes. +You need to run this after the playbook to create the certificates, remember to have the +dns entry for the added domains. + ``` # acme-client -vAD foobar.com ``` @@ -21,12 +27,19 @@ To renew the certs a cronjob must be placed: ``` #!/bin/sh -acme-client foobar.com +## debug +#set -x -if [ $? -eq 0 ] -then - /etc/rc.d/httpd reload -fi +UPDATE=0 + +for domain in $(awk '/^domain/ { print $2 }' /etc/acme-client.conf) +do + acme-client $domain + ocspcheck -vNo /etc/ssl/$domain.{ocsp,crt} + if [ $? -eq 0 ]; then + UPDATE=1 + fi +done ``` We asume that, you already have an entry on pf.conf like: @@ -50,25 +63,17 @@ pass in on $ext_if proto tcp from any to any port 443 ... ``` -And also you already have a DNS entry for your domain. - - Example Playbook ---------------- ``` --- - hosts: test - roles: - - role: gonzalo-.httpd-ssl - become: yes - become_method: doas - - vars: - domain: 'foobar.com' - alias: 'www.foobar.com' - httpd_conf: '/etc/httpd' - www_dir: '/var/www/sites' + gather_facts: false + roles: + - /home/gonzalo/src/ansible-role-httpd + become: yes + become_method: doas ``` License @@ -79,4 +84,4 @@ BSD Author Information ------------------ -https://x61.sh/ +https://x61.ar/ blob - 791d4a5101de2d18addaa8694ce1513edeb8cae6 blob + fafee005fc31a6c8f29ce08f9eb40873f1743602 --- defaults/main.yml +++ defaults/main.yml @@ -1,2 +1,27 @@ --- -# defaults file for httpd-ssl \ No newline at end of file +# defaults file for httpd_domain_config +vhosts_dir: '/etc/httpd.d' +vhosts_www: '/var/www' +domain_list: + - domain: foobar.com + alias: + - www.foobar.com + - v6.foobar.com + - domain: foo.com + alias: + - www.foo.com + - domain: foobar.org + alias: + - blog.foo.org + - domain: test.org + alias: + - www.tests.org + - domain: test.net + alias: + - www.tests.net + - domain: test.com + alias: + - www.tests.com + - domain: openbsd.org + alias: + - www.openbsd.org blob - 0d96c2c92c04240aa62f12b62b710ca55c4613ab blob + b5d47ab7172c8d8661bfb321423bcf89ab8a2ccf --- meta/main.yml +++ meta/main.yml @@ -13,5 +13,18 @@ galaxy_info: platforms: - name: OpenBSD versions: + - 7.4 + - 7.3 + - 7.2 + - 7.1 + - 7.0 + - 6.9 + - 6.8 + - 6.7 + - 6.6 + - 6.5 + - 6.4 + - 6.3 + - 6.2 - 6.1 dependencies: [] blob - 3b995bf06e6fb43e0a659f24dcd15935b9a465f4 blob + 4bdbe47eb50320faaf03c3442d3d181ba8565289 --- tasks/main.yml +++ tasks/main.yml @@ -1,31 +1,104 @@ --- +- name: Check if httpd.conf exists + stat: + path: '/etc/httpd.conf' + register: httpd_conf_status -- file: - path: "{{ httpd_conf }}" - state: directory +- name: Copy httpd.conf from template if not exists + ansible.builtin.template: + src: httpd.conf.j2 + dest: /etc/httpd.conf + owner: root + group: wheel + mode: '0644' + when: not httpd_conf_status.stat.exists -- file: - path: "/var/www/{{ vhosts_dir }}" - state: directory - owner: root - group: daemon +- name: Check if acme-client.conf exists + ansible.builtin.stat: + path: /etc/acme-client.conf + register: acme_status -- file: - path: "/var/www/{{ vhosts_dir }}/{{ domain }}" - state: directory - owner: root - group: daemon +- name: Check if etc vhosts directory exist + stat: + path: "{{ vhosts_dir }}" + register: vhosts_dir_status -- blockinfile: | - dest=/etc/acme-client.conf backup=yes - content="domain {{ domain }} { - alternative names { {{ alias }} } - domain key "/etc/ssl/private/{{ domain }}.key" - domain certificate "/etc/ssl/{{ domain }}.crt" - domain full chain certificate "/etc/ssl/{{ domain }}.fullchain.pem" - sign with letsencrypt - }" - insertafter=EOF +- name: Create etc vhosts directory + ansible.builtin.file: + path: "{{ vhosts_dir }}" + state: directory + owner: root + group: wheel + mode: '0755' + when: not vhosts_dir_status.stat.exists -- template: src=httpd.conf.j2 dest="/etc/httpd.conf" owner="root" group="wheel" mode="0644" -- template: src=site.conf.j2 dest="/etc/httpd/{{ domain }}.conf" owner="root" group="wheel" mode="0644" +- name: Template vhost files + ansible.builtin.template: + src: vhost.conf.j2 + dest: "{{ vhosts_dir }}/{{ item.domain }}.conf" + owner: root + group: wheel + mode: '0644' + loop: "{{ domain_list }}" + +- name: Check if vhosts www directory exist + ansible.builtin.stat: + path: "{{ vhosts_www }}/{{ item.domain }}/htdocs" + loop: "{{ domain_list }}" + register: vhosts_www_status + +- name: Ensure htdocs directories exist + ansible.builtin.file: + path: "{{ vhosts_www }}/{{ item.domain }}/htdocs" + state: directory + owner: root + group: wheel + mode: '0755' + loop: "{{ domain_list }}" + when: not (vhosts_www_status.results[loop.index0].stat.exists | default(false)) + +- name: Template vhost files + ansible.builtin.template: + src: vhost.conf.j2 + dest: "{{ vhosts_dir }}/{{ item.domain }}.conf" + owner: root + group: wheel + mode: '0644' + loop: "{{ domain_list }}" + when: httpd_conf_status.stat.exists + +- name: Add vhost includes to httpd.conf + ansible.builtin.lineinfile: + path: /etc/httpd.conf + line: "include \"{{ vhosts_dir }}/{{ item.domain }}.conf\"" + regexp: '^include "{{ vhosts_dir }}/{{ item.domain }}\.conf"$' + create: yes + loop: "{{ domain_list }}" + +- name: Copy acme-client.conf if not exists + ansible.builtin.copy: + src: "/etc/examples/acme-client.conf" + dest: "/etc/acme-client.conf" + owner: root + group: wheel + mode: '0644' + when: not acme_status.stat.exists + +- name: Add acme-client configuration + ansible.builtin.blockinfile: + dest: /etc/acme-client.conf + block: | + {% for domain_entry in domain_list %} + domain {{ domain_entry.domain }} { + alternative names { {% for alias in domain_entry.alias %}{{ alias }}{% if not loop.last %} {% endif %}{% endfor %} } + domain key "/etc/ssl/private/{{ domain_entry.domain }}.key" + domain full chain certificate "/etc/ssl/{{ domain_entry.domain }}.crt" + sign with letsencrypt + } + {% endfor %} + insertafter: EOF + +- name: Reload service httpd + ansible.builtin.service: + name: httpd + state: reloaded blob - 8272e15a73500438a9cca02b82044fa860618975 blob + a0f34f023628568ee27fdee354ae91ef024a21d7 --- templates/httpd.conf.j2 +++ templates/httpd.conf.j2 @@ -1,14 +1,9 @@ -ext_addr="*" - types { include "/usr/share/misc/mime.types" } -## Sites -include "{{ httpd_conf }}/{{ domain }}.conf" - ## Default server "default" { - listen on $ext_addr port 80 - listen on $ext_addr port 443 + listen on * port 80 + listen on * port 443 alias match "%d+%.%d+%.%d+%.%d+" alias match "%w*::*" @@ -17,7 +12,7 @@ server "default" { ## PHP-FPM #location "*.php" { - # fastcgi socket "/run/php-fpm.sock" + # fastcgi socket "/run/php-fpm.sock" #} ## @@ -26,3 +21,4 @@ server "default" { root "/htdocs" } + blob - /dev/null blob + 3bef4886b2bab5c1269e17699b485c6134ddfcdd (mode 644) --- /dev/null +++ templates/vhost.conf.j2 @@ -0,0 +1,40 @@ +## {{ item.domain }} - HTTP +server "{{ item.domain }}" { + {% if item.alias %} + {% for alias in item.alias %} + alias "{{ alias }}" + {% endfor %} + {% endif %} + + listen on * port 80 + + ## acme-client + location "/.well-known/acme-challenge/*" { + root "/acme" + request strip 2 + } + + root "/{{ item.domain }}/htdocs" +} + +## {{ item.domain }} - HTTPS +#server "{{ item.domain }}" { +# {% if item.alias %} +# {% for alias in item.alias %} +# alias "{{ alias }}" +# {% endfor %} +# {% endif %} + +# listen on * tls port 443 + +# tls { +# certificate "/etc/ssl/{{ item.domain }}.fullchain.pem" +# key "/etc/ssl/private/{{ item.domain }}.key" +# } + +# log { access "{{ item.domain }}-access.log", error "{{ item.domain }}-error.log" } + +# directory { index index.html } + +# root "{{ vhosts_www }}/{{ item.domain }}/htdocs" +#} blob - 878877b0776c44f55fc4e458f70840f31da5bb01 blob + d1dd55625b1981b0553815dd2e90aa0bf29a50e6 --- tests/inventory +++ tests/inventory @@ -1,2 +1,2 @@ +[test] localhost - blob - b8ccf87de7d5da29f745ef58254336172175609f blob + 6a6770bb3e594f8a2084d4de7a03c6876c3fd029 --- tests/test.yml +++ tests/test.yml @@ -1,7 +1,7 @@ --- -- hosts: localhost - gather_facts: true - become: True - become_method: doas +- hosts: test + gather_facts: false roles: - - httpd-ssl + - /home/gonzalo/src/ansible-role-httpd + become: yes + become_method: doas blob - 3182b31bc64066dc07887e8a11daa05def063796 blob + 145f91b16e5672d713793c487bde4009e3c3de13 --- vars/main.yml +++ vars/main.yml @@ -1,2 +1,2 @@ --- -# vars file for httpd-ssl \ No newline at end of file +# vars file for httpd-ssl