--- - name: Create WSGI website group group: name: "{{ user }}" gid: "{{ uid | default(omit) }}" state: present - name: Create WSGI website admin user user: name: "{{ admin }}" uid: "{{ admin_uid | default(omit) }}" group: "{{ user }}" shell: /bin/bash createhome: true home: "{{ home }}" state: present - name: Set-up directory for storing user profile configuration files file: path: "{{ home }}/.profile.d" state: directory owner: "{{ admin }}" group: "{{ user }}" mode: 0750 - name: Deploy profile configuration file for auto-activating the virtual environment copy: src: "profile_virtualenv.sh" dest: "{{ home }}/.profile.d/virtualenv.sh" owner: root group: "{{ user }}" mode: 0640 - name: Deploy profile configuration file for setting environment variables template: src: "environment.sh.j2" dest: "{{ home }}/.profile.d/environment.sh" owner: root group: "{{ user }}" mode: 0640 - name: Create WSGI website user user: name: "{{ user }}" uid: "{{ uid | default(omit) }}" group: "{{ user }}" comment: "umask=0007" system: true createhome: false state: present home: "{{ home }}" # This is a workaround for a rather stupid bug that Debian seems # uninterested to backport - # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=865762 shell: /bin/sh - name: Add nginx user to website group user: name: www-data groups: "{{ user }}" append: true notify: - Restart nginx # Ownership set to root so Postfix would not check if correct user owns the # file. - name: Set-up forwarding for mails delivered to local application user/admin template: src: "forward.j2" dest: "{{ home }}/.forward" owner: root group: "{{ user }}" mode: 0640 - name: Install extra packages for website apt: name: "{{ packages }}" state: present register: install_extra_packages notify: - Restart WSGI services # Ignore failures - the virtual environment might not have been # created yet. Don't use --version because Python 2 outputs to stderr, # and Python 3 outputs to stdout. - name: Check current version of Python used in virtual environment (if any) command: "{{ home }}/virtualenv/bin/python -c \"import sys; print(sys.version.split(' ')[0])\"" failed_when: false changed_when: false register: current_python_version - name: Remove existing Python virtual environment (wrong Python version) file: path: "{{ home }}/virtualenv" state: absent when: "current_python_version.rc == 0 and not current_python_version.stdout.startswith(python_version | string)" notify: - Restart WSGI services - name: Create directory for storing the Python virtual environment file: path: "{{ home }}/virtualenv" state: directory owner: "{{ admin }}" group: "{{ user }}" mode: 02750 # @TODO: Get rid of this if possible in Debian Buster. # Do not install setuptools when creating the virtual environment - # otherwise it will also install Debian-specific pkg-resources # package. The pkg-resources package can be removed, but this breaks # the package downloading via pip. # # Install setuptools later on via separate pip invocation. # # The pkg-resources package is also annoying because it shows-up in # the output of the pip freeze command, and also interferes with the # virtual environment management using pip-tools. # # For more details, see: # # - https://github.com/pypa/pip/issues/4022 # - https://bugs.launchpad.net/ubuntu/+source/python-pip/+bug/1635463 # - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=871790 - name: Create Python virtual environment command: '/usr/bin/virtualenv --no-setuptools --python "{{ python_interpreter }}" --prompt "({{ fqdn }})" "{{ home }}/virtualenv"' args: creates: "{{ home }}/virtualenv/bin/{{ python_interpreter | basename }}" become: true become_user: "{{ admin }}" # @TODO: Park of the pkg-resources described above. - name: Install setuptools in virtual environment pip: name: - "setuptools" virtualenv: "{{ home }}/virtualenv" become: true become_user: "{{ admin }}" # @TODO: Park of the pkg-resources described above. - name: Remove the pkg-resources package from virtual environment (see comments above for details) pip: name: pkg-resources virtualenv: "{{ home }}/virtualenv" state: absent become: true become_user: "{{ admin }}" - name: Configure project directory for the Python virtual environment template: src: "venv_project.j2" dest: "{{ home }}/virtualenv/.project" owner: "{{ admin }}" group: "{{ user }}" mode: 0640 - name: Deploy virtualenv wrapper template: src: "venv_exec.j2" dest: "{{ home }}/virtualenv/bin/exec" owner: "{{ admin }}" group: "{{ user }}" mode: 0750 - name: Set-up directory for storing requirements file for upgrade checks file: path: "{{ pip_check_requirements_upgrades_directory }}/{{ fqdn }}" state: directory owner: root group: pipreqcheck mode: 0750 - name: Deploy WSGI requirements files for upgrade checks template: src: "{{ item }}.j2" dest: "{{ pip_check_requirements_upgrades_directory }}/{{ fqdn }}/{{ item }}" owner: root group: pipreqcheck mode: 0640 with_items: - wsgi_requirements.in - wsgi_requirements.txt - name: Deploy Gunicorn requirements file for installation purposes template: src: "wsgi_requirements.txt.j2" dest: "{{ home }}/.wsgi_requirements.txt" owner: "{{ admin }}" group: "{{ user }}" mode: 0640 - name: Install Gunicorn via requirements file become: true become_user: "{{ admin }}" pip: requirements: "{{ home }}/.wsgi_requirements.txt" state: present virtualenv: "{{ home }}/virtualenv" register: install_gunicorn_via_requirements notify: - Restart WSGI services - name: Install additional packages in Python virtual environment become: true become_user: "{{ admin }}" pip: name: "{{ virtualenv_packages }}" state: present virtualenv: "{{ home }}/virtualenv" register: install_additional_packages_in_virtualenv when: virtualenv_packages | length > 0 notify: - Restart WSGI services - name: Deploy systemd socket configuration for website template: src: "systemd_wsgi_website.socket.j2" dest: "/etc/systemd/system/{{ fqdn }}.socket" owner: root group: root mode: 0644 register: deploy_systemd_socket_configuration notify: - Reload systemd - Restart WSGI services - name: Deploy systemd service configuration for website template: src: "systemd_wsgi_website.service.j2" dest: "/etc/systemd/system/{{ fqdn }}.service" owner: root group: root mode: 0644 register: deploy_systemd_service_configuration notify: - Reload systemd - Restart WSGI services - name: Enable the website service service: name: "{{ fqdn }}" enabled: true state: started - name: Create directory where static files can be served from file: path: "{{ home }}/htdocs/" state: directory owner: "{{ admin }}" group: "{{ user }}" mode: 02750 - name: Deploy nginx TLS private key for website copy: dest: "/etc/ssl/private/{{ fqdn }}_https.key" content: "{{ https_tls_key }}" owner: root group: root mode: 0640 notify: - Restart nginx - name: Deploy nginx TLS certificate for website copy: dest: "/etc/ssl/certs/{{ fqdn }}_https.pem" content: "{{ https_tls_certificate }}" owner: root group: root mode: 0644 notify: - Restart nginx - name: Deploy configuration file for checking certificate validity via cron copy: content: "/etc/ssl/certs/{{ fqdn }}_https.pem" dest: "/etc/check_certificate/{{ fqdn }}_https.conf" owner: root group: root mode: 0644 - name: Deploy nginx configuration file for website template: src: "nginx_site.j2" dest: "/etc/nginx/sites-available/{{ fqdn }}" owner: root group: root mode: 0640 validate: "/usr/local/bin/nginx_verify_site.sh -n '{{ fqdn }}' %s" notify: - Restart nginx - name: Enable nginx website file: src: "/etc/nginx/sites-available/{{ fqdn }}" dest: "/etc/nginx/sites-enabled/{{ fqdn }}" state: link notify: - Restart nginx - name: Set-up empty list of WSGI services to restart set_fact: wsgi_services_to_restart: [] when: "wsgi_services_to_restart is not defined" tags: - handlers - name: Add service to list of WSGI services to restart # noqa 503 # [503] Tasks that run when changed should likely be handlers # This specific task is used in order to work around inability of Ansible # to provide properly parametrised handlers for reusable roles. set_fact: wsgi_services_to_restart: "{{ wsgi_services_to_restart + [ fqdn ] }}" when: | fqdn not in wsgi_services_to_restart and ((install_extra_packages is defined and install_extra_packages.changed) or (install_additional_packages_in_virtualenv is defined and install_additional_packages_in_virtualenv.changed) or (deploy_systemd_socket_configuration is defined and deploy_systemd_socket_configuration.changed) or (deploy_systemd_service_configuration is defined and deploy_systemd_service_configuration.changed) or (install_gunicorn_via_requirements is defined and install_gunicorn_via_requirements.changed) or (run_handlers | default(False) | bool())) tags: - handlers - name: Explicitly run all handlers include: ../handlers/main.yml when: "run_handlers | default(False) | bool()" tags: - handlers