From 7679ca66dcc2557cd412a15c3b4f32622f61a48b Mon Sep 17 00:00:00 2001 From: Andrea Dell'Amico Date: Tue, 2 Jun 2020 15:48:56 +0200 Subject: [PATCH] Import the old role. --- README.md | 119 +++++++++++++++++++++++----- defaults/main.yml | 93 +++++++++++++++++++++- files/apache-letsencrypt-acme.sh | 25 ++++++ handlers/main.yml | 7 +- meta/main.yml | 57 +++---------- tasks/apache-basic-auth.yml | 30 +++++++ tasks/apache-letsencrypt.yml | 43 ++++++++++ tasks/apache-modules.yml | 79 ++++++++++++++++++ tasks/apache-ppa.yml | 14 ++++ tasks/apache.yml | 42 ++++++++++ tasks/main.yml | 9 ++- templates/info.conf.j2 | 20 +++++ templates/letsencrypt-proxy.conf.j2 | 1 + templates/ports.conf | 3 + templates/status.conf.j2 | 32 ++++++++ 15 files changed, 507 insertions(+), 67 deletions(-) create mode 100644 files/apache-letsencrypt-acme.sh create mode 100644 tasks/apache-basic-auth.yml create mode 100644 tasks/apache-letsencrypt.yml create mode 100644 tasks/apache-modules.yml create mode 100644 tasks/apache-ppa.yml create mode 100644 tasks/apache.yml create mode 100644 templates/info.conf.j2 create mode 100644 templates/letsencrypt-proxy.conf.j2 create mode 100644 templates/ports.conf create mode 100644 templates/status.conf.j2 diff --git a/README.md b/README.md index 3637db8..580aa40 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,114 @@ Role Name ========= -A brief description of the role goes here. - -Requirements ------------- - -Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. +A role that installs and configures the apache web server Role Variables -------------- -A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. +The most important variables are listed below: + +``` yaml +apache_service_enabled: True +apache_user: www-data +apache_pkg_state: latest +apache_group: '{{ apache_user }}' +apache_from_ppa: False +apache_ppa_repo: 'ppa:ondrej/apache2' + +apache_listen_ports: + - 80 + - '{{ apache_ssl_port }}' + +# Possible choices: event, prefork (the old ones), worker (the threaded version), itm +apache_mpm_mode: worker + +apache_packages: + - apache2 + - apache2-utils + - libapache2-mod-xsendfile + - unzip + - zip + +apache_modules_packages: + - 'apache2-mpm-{{ apache_mpm_mode }}' + +# Only one can be present at the same time. It needs to be listed as the last one +apache_worker_modules: +# - { name: 'mpm_itm', state: 'absent' } + - { name: 'mpm_event', state: 'absent' } + - { name: 'mpm_prefork', state: 'absent' } + - { name: 'mpm_{{ apache_mpm_mode }}', state: 'present' } + +# apache RPAF is needed to obtain the real client addresses when behind a reverse proxy +apache_rpaf_install: False + +apache_default_modules: + - headers + - rewrite + - expires + - xsendfile + +apache_ssl_modules_enabled: True +apache_ssl_port: 443 +apache_ssl_modules: + - ssl + - socache_shmcb +apache_http_proxy_modules_enabled: False +apache_http_proxy_modules: + - proxy + - proxy_ajp + - proxy_http + +apache_status_module: True +apache_status_location: '/server-status' +apache_status_allowed_hosts: + - 127.0.0.1/8 + +apache_info_module: True +apache_info_location: '/server-info' +apache_info_allowed_hosts: + - 127.0.0.1/8 + +apache_basic_auth: False +apache_basic_auth_single_file: True +apache_basic_auth_dir: /etc/apache2/auth +apache_basic_auth_file: '{{ apache_basic_auth_dir }}/htpasswd' + +apache_basic_auth_modules: + - auth_basic + - authn_file + - authz_user + +# Put them in a vault file. auth_file is optional. Not used when apache_basic_auth_single_file is true +apache_basic_users: + - { username:'', password:'', state:'present,absent', auth_file:'path_to_file' } + +# +apache_additional_packages: False +apache_additional_packages_list: +# - libapache2-mod-uwsgi +# - ... +# +# Set this variable to load the modules you need +apache_additional_modules: False +apache_additional_modules_list: [] +# - +# - + +apache_letsencrypt_managed: True +apache_letsencrypt_proxy_modules: + - proxy + - proxy_http + +apache_letsencrypt_proxy_conf: + - letsencrypt-proxy.conf +``` Dependencies ------------ -A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. - -Example Playbook ----------------- - -Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: - - - hosts: servers - roles: - - { role: username.rolename, x: 42 } +None License ------- @@ -35,4 +118,4 @@ EUPL-1.2 Author Information ------------------ -An optional section for the role authors to include contact information, or a website (HTML is not allowed). +Andrea Dell'Amico, diff --git a/defaults/main.yml b/defaults/main.yml index 95d3c70..231756a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,2 +1,93 @@ --- -# defaults file for ansible-role-template \ No newline at end of file +apache_service_enabled: True +apache_user: www-data +apache_pkg_state: present +apache_group: '{{ apache_user }}' +apache_from_ppa: False +apache_ppa_repo: 'ppa:ondrej/apache2' + +apache_listen_ports: + - 80 + - '{{ apache_ssl_port }}' + +# Possible choices: event, prefork (the old ones), worker (the threaded version), itm +apache_mpm_mode: worker + +apache_packages: + - apache2 + - apache2-utils + - libapache2-mod-xsendfile + - unzip + - zip + +apache_modules_packages: + - 'apache2-mpm-{{ apache_mpm_mode }}' + +# Only one can be present at the same time. It needs to be listed as the last one +apache_worker_modules: +# - { name: 'mpm_itm', state: 'absent' } + - { name: 'mpm_event', state: 'absent' } + - { name: 'mpm_prefork', state: 'absent' } + - { name: 'mpm_{{ apache_mpm_mode }}', state: 'present' } + +# apache RPAF is needed to obtain the real client addresses when behind a reverse proxy +apache_rpaf_install: False + +apache_default_modules: + - headers + - rewrite + - expires + - xsendfile + +apache_ssl_modules_enabled: True +apache_ssl_port: 443 +apache_ssl_modules: + - ssl + - socache_shmcb +apache_http_proxy_modules_enabled: False +apache_http_proxy_modules: + - proxy + - proxy_ajp + - proxy_http + +apache_status_module: True +apache_status_location: '/server-status' +apache_status_allowed_hosts: + - 127.0.0.1/8 + +apache_info_module: True +apache_info_location: '/server-info' +apache_info_allowed_hosts: + - 127.0.0.1/8 + +apache_basic_auth: False +apache_basic_auth_single_file: True +apache_basic_auth_dir: /etc/apache2/auth +apache_basic_auth_file: '{{ apache_basic_auth_dir }}/htpasswd' + +apache_basic_auth_modules: + - auth_basic + - authn_file + - authz_user + +# Put them in a vault file. auth_file is optional. Not used when apache_basic_auth_single_file is true +# apache_basic_users: +# - { username:'', password:'', state:'present,absent', auth_file:'path_to_file' } + +# +apache_additional_packages_list: [] +# - libapache2-mod-uwsgi +# - ... +# +# Set this variable to load the modules you need +apache_additional_modules_list: [] +# - +# - + +apache_letsencrypt_managed: True +apache_letsencrypt_proxy_modules: + - proxy + - proxy_http + +apache_letsencrypt_proxy_conf: + - letsencrypt-proxy.conf diff --git a/files/apache-letsencrypt-acme.sh b/files/apache-letsencrypt-acme.sh new file mode 100644 index 0000000..5d10a4e --- /dev/null +++ b/files/apache-letsencrypt-acme.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +LE_SERVICES_SCRIPT_DIR=/usr/lib/acme/hooks +LE_LOG_DIR=/var/log/letsencrypt +DATE=$( date ) + +[ ! -d $LE_LOG_DIR ] && mkdir $LE_LOG_DIR +echo "$DATE" >> $LE_LOG_DIR/apache.log + +if [ -f /etc/default/letsencrypt ] ; then + . /etc/default/letsencrypt +else + echo "No letsencrypt default file" >> $LE_LOG_DIR/apache.log +fi + +echo "Reload the apache service" >> $LE_LOG_DIR/apache.log +if [ -x /bin/systemctl ] ; then + systemctl reload apache2 >> $LE_LOG_DIR/apache.log 2>&1 +else + service apache2 reload >> $LE_LOG_DIR/apache.log 2>&1 +fi + +echo "Done." >> $LE_LOG_DIR/apache.log + +exit 0 diff --git a/handlers/main.yml b/handlers/main.yml index 27474e0..a4fd00a 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,2 +1,7 @@ --- -# handlers file for ansible-role-template \ No newline at end of file +- name: apache2 reload + service: name=apache2 state=reloaded + +- name: apache2 restart + service: name=apache2 state=restarted + diff --git a/meta/main.yml b/meta/main.yml index 1126a5e..fddbfd8 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,61 +1,26 @@ galaxy_info: - author: your name - description: your description + author: Andrea Dell'Amico + description: Systems Architect company: ISTI-CNR - # If the issue tracker for your role is not on github, uncomment the - # next line and provide a value issue_tracker_url: https://redmine-s2i2s.isti.cnr.it/projects/provisioning - # Some suggested licenses: - # - BSD (default) - # - MIT - # - GPLv2 - # - GPLv3 - # - Apache - # - CC-BY - license: EUPL-1.2 + license: EUPL 1.2+ min_ansible_version: 2.8 - # If this a Container Enabled role, provide the minimum Ansible Container version. - # min_ansible_container_version: - - # Optionally specify the branch Galaxy will use when accessing the GitHub - # repo for this role. During role install, if no tags are available, - # Galaxy will use this branch. During import Galaxy will access files on - # this branch. If Travis integration is configured, only notifications for this - # branch will be accepted. Otherwise, in all cases, the repo's default branch - # (usually master) will be used. - #github_branch: - - # - # Provide a list of supported platforms, and for each platform a list of versions. - # If you don't wish to enumerate all versions for a particular platform, use 'all'. # To view available platforms and versions (or releases), visit: # https://galaxy.ansible.com/api/v1/platforms/ # - # platforms: - # - name: Fedora - # versions: - # - all - # - 25 - # - name: SomePlatform - # versions: - # - all - # - 1.0 - # - 7 - # - 99.99 + platforms: + - name: Ubuntu + versions: + - bionic - galaxy_tags: [] - # List tags for your role here, one per line. A tag is a keyword that describes - # and categorizes the role. Users find roles by searching for tags. Be sure to - # remove the '[]' above, if you add tags to this list. - # - # NOTE: A tag is limited to a single word comprised of alphanumeric characters. - # Maximum 20 tags per role. + galaxy_tags: + - apache + - httpd dependencies: [] - # List your role dependencies here, one per line. Be sure to remove the '[]' above, - # if you add dependencies to this list. + diff --git a/tasks/apache-basic-auth.yml b/tasks/apache-basic-auth.yml new file mode 100644 index 0000000..246438c --- /dev/null +++ b/tasks/apache-basic-auth.yml @@ -0,0 +1,30 @@ +--- +- name: Apache auth modules on Debian or Ubuntu + block: + - name: Load the basic auth modules + apache2_module: name={{ item }} state=present + with_items: '{{ apache_basic_auth_modules }}' + notify: apache2 reload + + - name: Install the python-passlib library + apt: pkg=python-passlib state=present + + when: ansible_distribution_file_variety == "Debian" + tags: [ 'apache', 'apache_basic_auth' ] + +- name: Create the authentication directory + file: path={{ apache_basic_auth_dir }} mode=0750 owner=root group={{ apache_group }} state=directory + tags: [ 'apache', 'apache_basic_auth' ] + +- name: Create the basic auth file when it is unique to all the virtualhosts + htpasswd: path={{ apache_basic_auth_file }} name={{ item.username }} password={{ item.password }} create=yes state={{ item.state }} owner=root group={{ apache_group }} mode=0640 + when: apache_basic_users is defined and apache_basic_auth_single_file + with_items: '{{ apache_basic_users }}' + tags: [ 'apache', 'apache_basic_auth' ] + +- name: Create the basic auth files + htpasswd: path={{ item.auth_file }} name={{ item.username }} password={{ item.password }} create=yes state={{ item.state }} owner=root group={{ apache_group }} mode=0640 + with_items: '{{ apache_basic_users | default([]) }}' + when: apache_basic_users is defined and not apache_basic_auth_single_file + tags: [ 'apache', 'apache_basic_auth' ] + diff --git a/tasks/apache-letsencrypt.yml b/tasks/apache-letsencrypt.yml new file mode 100644 index 0000000..4b1d662 --- /dev/null +++ b/tasks/apache-letsencrypt.yml @@ -0,0 +1,43 @@ +--- +- block: + - name: Enable the proxy modules needed by letsencrypt + apache2_module: name={{ item }} state=present + with_items: '{{ apache_letsencrypt_proxy_modules }}' + ignore_errors: True + notify: apache2 reload + + - name: Install the apache letsencrypt directives on trusty + template: src={{ item }}.j2 dest=/etc/apache2/conf-available/{{ item }} owner=root group=root mode=0644 + with_items: '{{ apache_letsencrypt_proxy_conf }}' + ignore_errors: True + notify: apache2 reload + + - name: Enable the apache letsencrypt directives on trusty + file: src=/etc/apache2/conf-available/{{ item }} dest=/etc/apache2/conf-enabled/{{ item }} state=link + with_items: '{{ apache_letsencrypt_proxy_conf }}' + ignore_errors: True + notify: apache2 reload + + - name: Create the acme hooks directory if it does not yet exist + file: dest={{ letsencrypt_acme_services_scripts_dir }} state=directory owner=root group=root + + - name: Install a letsencrypt hook for apache + copy: src=apache-letsencrypt-acme.sh dest={{ letsencrypt_acme_services_scripts_dir }}/apache2 owner=root group=root mode=4555 + + when: + - letsencrypt_acme_install is defined and letsencrypt_acme_install + - apache_letsencrypt_managed + tags: [ 'apache', 'letsencrypt' ] + +- block: + - name: Disable the letsencrypt conf + file: dest=/etc/apache2/conf-enabled/letsencrypt-proxy.conf state=absent + ignore_errors: True + notify: apache2 reload + + - name: Remove the letsencrypt hook for apache + file: path={{ letsencrypt_acme_services_scripts_dir }}/apache2 state=absent + + when: not apache_letsencrypt_managed + tags: [ 'apache', 'letsencrypt' ] + diff --git a/tasks/apache-modules.yml b/tasks/apache-modules.yml new file mode 100644 index 0000000..2efc7de --- /dev/null +++ b/tasks/apache-modules.yml @@ -0,0 +1,79 @@ +--- +- block: + - name: Load the required modules + apache2_module: name={{ item }} state=present force=yes + with_items: '{{ apache_default_modules }}' + notify: apache2 reload + ignore_errors: True + tags: [ 'apache', 'apache_modules' ] + +- name: Manage the RPAF module on Debian or Ubuntu + block: + - name: Install the libapache2-mod-rpaf module + apt: pkg=libapache2-mod-rpaf state=present + when: apache_rpaf_install + + - name: Enable the apache rpaf module + apache2_module: name=rpaf state=present + when: apache_rpaf_install + notify: apache2 reload + + when: ansible_distribution_file_variety == "Debian" + tags: [ 'apache', 'apache_mods', 'apache_rpaf' ] + +- block: + - name: Load the apache ssl modules + apache2_module: name={{ item }} state=present + with_items: '{{ apache_ssl_modules }}' + when: apache_ssl_modules_enabled + notify: apache2 reload + + - name: Load some apache proxy modules + apache2_module: name={{ item }} state=present + with_items: '{{ apache_http_proxy_modules }}' + when: apache_http_proxy_modules_enabled + notify: apache2 reload + + tags: [ 'apache', 'apache_mods', 'apache_ssl' ] + +- name: Manage some optional modules + block: + - name: Load additional apache modules if any + apache2_module: name={{ item }} state=present + with_items: '{{ apache_additional_modules_list }}' + notify: apache2 reload + + - name: Disable apache modules if any + apache2_module: name={{ item }} state=absent + with_items: '{{ apache_modules_to_be_removed | default ([]) }}' + notify: apache2 reload + + - name: Load the apache status module + apache2_module: name={{ item }} state=present + with_items: status + when: apache_status_module + notify: apache2 reload + tags: [ 'apache', 'apache_mods', 'apache_status' ] + + - name: Configure the apache status module + template: src={{ item }}.j2 dest=/etc/apache2/mods-available/{{ item }} owner=root group=root mode=0644 + with_items: status.conf + when: apache_status_module + notify: apache2 reload + tags: [ 'apache', 'apache_mods', 'apache_status' ] + + - name: Load the apache info module + apache2_module: name={{ item }} state=present + with_items: info + when: apache_info_module + notify: apache2 reload + tags: [ 'apache', 'apache_mods', 'apache_info' ] + + - name: Configure the apache info module + template: src={{ item }}.j2 dest=/etc/apache2/mods-available/{{ item }} owner=root group=root mode=0644 + with_items: info.conf + when: apache_info_module + notify: apache2 reload + tags: [ 'apache', 'apache_mods', 'apache_info' ] + + tags: [ 'apache', 'apache_mods' ] diff --git a/tasks/apache-ppa.yml b/tasks/apache-ppa.yml new file mode 100644 index 0000000..33a1099 --- /dev/null +++ b/tasks/apache-ppa.yml @@ -0,0 +1,14 @@ +--- +- block: + - name: Install the Ubuntu apache PPA + apt_repository: repo='{{ apache_ppa_repo }}' update_cache=yes + + when: apache_from_ppa + tags: [ 'apache', 'apache_ppa' ] + +- block: + - name: Remove the Ubuntu apache PPA + apt_repository: repo='{{ apache_ppa_repo }}' update_cache=yes state=absent + + when: not apache_from_ppa + tags: [ 'apache', 'apache_ppa' ] diff --git a/tasks/apache.yml b/tasks/apache.yml new file mode 100644 index 0000000..d9e35dc --- /dev/null +++ b/tasks/apache.yml @@ -0,0 +1,42 @@ +--- +- name: Manage the apache packages on Ubuntu or Debian + block: + - name: Install the apache packages + apt: pkg={{ apache_packages }} state={{ apache_pkg_state }} cache_valid_time=3600 + tags: [ 'apache', 'apache_main_packages' ] + + - name: Install the apache modules packages + apt: pkg={{ apache_modules_packages }} state={{ apache_pkg_state }} cache_valid_time=3600 + when: not apache_from_ppa + tags: [ 'apache', 'apache_additional_packages' ] + + - name: Install the apache additional packages, if any + apt: pkg={{ apache_additional_packages_list }} state={{ apache_pkg_state }} cache_valid_time=3600 + tags: [ 'apache', 'apache_additional_packages' ] + + - name: Instal the ports conf file + template: src=ports.conf dest=/etc/apache2/ports.conf + notify: apache2 reload + tags: [ 'apache', 'apache_conf' ] + + - name: Remove the default virtualhost file + file: dest=/etc/apache2/sites-enabled/{{ item }} state=absent + with_items: + - 000-default + - 000-default.conf + notify: apache2 reload + + when: ansible_distribution_file_variety == "Debian" + tags: apache + +- name: Ensure that the apache service is enabled and started + service: name=apache2 state=started enabled=yes + when: apache_service_enabled + ignore_errors: True + tags: apache + +- name: Ensure that the apache service is disabled and stopped if we do not want it running + service: name=apache2 state=stopped enabled=no + when: not apache_service_enabled + ignore_errors: True + tags: apache diff --git a/tasks/main.yml b/tasks/main.yml index 53c6cae..d9446a6 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,2 +1,9 @@ --- -# tasks file for ansible-role-template \ No newline at end of file +- import_tasks: apache-ppa.yml + when: ansible_distribution_file_variety == "Debian" +- import_tasks: apache.yml +- import_tasks: apache-modules.yml +- import_tasks: apache-basic-auth.yml + when: apache_basic_auth +- import_tasks: apache-letsencrypt.yml + when: letsencrypt_acme_install is defined and letsencrypt_acme_install diff --git a/templates/info.conf.j2 b/templates/info.conf.j2 new file mode 100644 index 0000000..413dfc2 --- /dev/null +++ b/templates/info.conf.j2 @@ -0,0 +1,20 @@ + + + # Allow remote server configuration reports, with the URL of + # http://servername/server-info (requires that mod_info.c be loaded). + # Uncomment and change the "192.0.2.0/24" to allow access from other hosts. + # + + SetHandler server-info + Require local + {% if nagios_monitoring_server_ip is defined %} + {% for addr in nagios_monitoring_server_ip %} + Require ip {{ addr }} + {% endfor %} + {% endif %} + {% for addr in apache_info_allowed_hosts %} + Require ip {{ addr }} + {% endfor %} + + + diff --git a/templates/letsencrypt-proxy.conf.j2 b/templates/letsencrypt-proxy.conf.j2 new file mode 100644 index 0000000..4dddd47 --- /dev/null +++ b/templates/letsencrypt-proxy.conf.j2 @@ -0,0 +1 @@ +ProxyPass "/.well-known/acme-challenge" "http://127.0.0.1:{{ letsencrypt_acme_standalone_port}}/.well-known/acme-challenge" diff --git a/templates/ports.conf b/templates/ports.conf new file mode 100644 index 0000000..bc9e42f --- /dev/null +++ b/templates/ports.conf @@ -0,0 +1,3 @@ +{% for port in apache_listen_ports %} +Listen {{ port }} +{% endfor %} diff --git a/templates/status.conf.j2 b/templates/status.conf.j2 new file mode 100644 index 0000000..28d37ed --- /dev/null +++ b/templates/status.conf.j2 @@ -0,0 +1,32 @@ + + # Allow server status reports generated by mod_status, + # with the URL of http://servername/server-status + # Uncomment and change the "192.0.2.0/24" to allow access from other hosts. + + + SetHandler server-status + Require local + {% if nagios_monitoring_server_ip is defined %} + {% for addr in nagios_monitoring_server_ip %} + Require ip {{ addr }} + {% endfor %} + {% endif %} + {% for addr in apache_status_allowed_hosts %} + Require ip {{ addr }} + {% endfor %} + + + # Keep track of extended status information for each request + ExtendedStatus On + + # Determine if mod_status displays the first 63 characters of a request or + # the last 63, assuming the request itself is greater than 63 chars. + # Default: Off + #SeeRequestTail On + + + # Show Proxy LoadBalancer status in mod_status + ProxyStatus On + + + \ No newline at end of file