File diff d8a702c8c922 → aa26e2f7f090
deploy/install.yml
Show inline comments
 
new file 100644
 
# Ansible playbook for basic web server configuration.
 
#
 
# Run with:
 
# ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook deploy/install.yml -i deploy/inventory.ini --verbose
 

	
 
# Notes:
 
#
 
# /etc/apache2 uses OS defaults aside from "site-available", "sites-enabled" and
 
# "conservancy.conf".
 
#
 
# Current site does not use "django.contrib.staticfiles", so no need to run
 
# `collectstatic`.
 
#
 
# SQLite database lives at /var/lib/www/database.
 
#
 
# Disabled Rackspace CDN videos.
 

	
 
 - name: Configure web server
 
   hosts: web
 
   become: true
 
   vars:
 
     ansible_ssh_pipelining: true
 
   tasks:
 
     - name: Install unattended upgrades
 
       apt:
 
         name: unattended-upgrades
 

	
 
     - name: Configure unattended upgrades overrides
 
       # See defaults in 50unattended-upgrades.
 
       copy:
 
         dest: /etc/apt/apt.conf.d/20auto-upgrades
 
         content: |
 
           APT::Periodic::Update-Package-Lists "1";
 
           APT::Periodic::Unattended-Upgrade "1";
 
           Unattended-Upgrade::Automatic-Reboot "true";
 
           Unattended-Upgrade::Automatic-Reboot-Time "02:00";
 
           Unattended-Upgrade::Mail "root";
 

	
 
     - name: Add extensive history logging
 
       blockinfile:
 
         path: /etc/bash.bashrc
 
         block: |
 
           # Write to history file immediately (rather than only when shell is
 
           # closed). For setting history length see HISTSIZE and HISTFILESIZE in
 
           # bash(1).
 
           shopt -s histappend
 
           PROMPT_COMMAND='history -a'
 
           HISTSIZE=1000000
 
           HISTFILESIZE=1000000
 
         insertafter: EOF
 

	
 
     - name: Mount the media volume
 
       # OSUOSL VMs come with fixed storage that's tied to the cores and RAM
 
       # selection. Easier to put this data on an external volume.
 
       ansible.posix.mount:
 
         src: /dev/sdb1
 
         path: /var/www/media
 
         fstype: ext4
 
         state: mounted
 
         boot: false
 

	
 
     - name: Install Apache
 
       apt:
 
         name: apache2,libapache2-mod-wsgi-py3
 

	
 
     - apache2_module:
 
         state: present
 
         name: ssl
 

	
 
     - apache2_module:
 
         state: present
 
         name: rewrite
 

	
 
     # The proxy and proxy-http modules are required to rewrite /.well-known/
 
     # requests to the mail server if the file doesn't exist. This is use to
 
     # renew Let's Encrypt certificates.
 
     - apache2_module:
 
         state: present
 
         name: proxy
 

	
 
     - apache2_module:
 
         state: present
 
         name: proxy-http
 

	
 
     - name: Install Postfix
 
       apt:
 
         pkg:
 
           - postfix
 
           # libsasl2-modules fixes "SASL authentication failure: No worthy mechs found"
 
           - libsasl2-modules
 
           - mailutils
 

	
 
     # # Commented because you only want this on first run ever.
 
     # - name: Add file for SMTP credentials
 
     #   copy:
 
     #     dest: /etc/postfix/sasl_passwd
 
     #     content: |-
 
     #       # After updating, run `sudo postmap hash:/etc/postfix/sasl_passwd`.
 
     #       [mail.sfconservancy.org]:587 conference@sfconservancy.org:PASSWORD
 
           
 
     - name: Configure Postfix for relaying
 
       copy:
 
         src: postfix/main.cf
 
         dest: /etc/postfix/main.cf
 
       notify:
 
         - restart postfix
 

	
 
     - name: Alias mail to root
 
       copy:
 
         dest: /etc/aliases
 
         content: |-
 
           postmaster: root
 
           root: sysadmin@sfconservancy.org, sysadmin@sturm.com.au
 
       notify:
 
         - restart postfix
 

	
 
     - name: Install Certbot
 
       apt:
 
         name: certbot, python3-certbot-apache
 

	
 
     - name: Install Python dependencies
 
       apt:
 
         name: python3-django,python3-bs4,python3-html5lib,python3-django-countries
 

	
 
     - name: Install Python essentials
 
       apt:
 
         name: python3-venv,python3-pip,python3-wheel
 

	
 
     - name: Install Python build dependencies
 
       apt:
 
         name: build-essential,python3-dev,libffi-dev
 

	
 
     - name: Security settings
 
       apt:
 
         name: fail2ban
 

	
 
     - name: Disable SSH password authentication
 
       lineinfile:
 
         path: /etc/ssh/sshd_config
 
         line: 'PasswordAuthentication no'
 
         regexp: 'PasswordAuthentication '
 
       notify:
 
         - restart sshd
 

	
 
     - name: Install utilities
 
       apt:
 
         name: tmux,curl,git,magic-wormhole,htop,rsync
 

	
 
     - name: Create the project directory
 
       file:
 
         path: /var/www/website
 
         state: directory
 
         owner: www-data
 
         group: www-data
 
         mode: '0755'
 

	
 
     # TODO: Needs to force owner to www-data:www-data
 
     - name: Git checkout
 
       ansible.builtin.git:
 
         repo: 'https://k.sfconservancy.org/website'
 
         dest: /var/www/website
 
         version: master
 
         remote: upstream
 

	
 
     - name: Create the database directory
 
       file:
 
         path: /var/lib/www/database
 
         state: directory
 
         owner: www-data
 
         group: www-data
 
         mode: '0755'
 

	
 
     - name: Create static dir
 
       file:
 
         path: /var/www/website/conservancy/static
 
         state: directory
 
         owner: www-data
 
         group: www-data
 
         mode: '0755'
 

	
 
     - name: Install `netfilter-persistent` && `iptables-persistent` packages
 
       apt:
 
         pkg:
 
           - iptables-persistent
 
           - netfilter-persistent
 

	
 
     - name: Install iptables  # May need kernel reload/reboot
 
       apt:
 
         name: iptables,iptables-netflow-dkms
 

	
 
     - name: Flush existing firewall rules
 
       iptables:
 
         flush: true
 

	
 
     - name: Firewall rule - allow all loopback traffic
 
       iptables:
 
         action: append
 
         chain: INPUT
 
         in_interface: lo
 
         jump: ACCEPT
 

	
 
     - name: Firewall rule - allow established connections
 
       iptables:
 
         chain: INPUT
 
         ctstate: ESTABLISHED,RELATED
 
         jump: ACCEPT
 

	
 
     - name: Firewall rule - allow port ping traffic
 
       iptables:
 
         chain: INPUT
 
         jump: ACCEPT
 
         protocol: icmp
 

	
 
     - name: Firewall rule - allow port 22/SSH traffic
 
       iptables:
 
         chain: INPUT
 
         destination_port: '22'
 
         jump: ACCEPT
 
         protocol: tcp
 

	
 
     - name: Firewall rule - allow port 80/HTTP traffic
 
       iptables:
 
         chain: INPUT
 
         destination_port: '80'
 
         jump: ACCEPT
 
         protocol: tcp
 

	
 
     - name: Firewall rule - allow port 443/HTTPS traffic
 
       iptables:
 
         chain: INPUT
 
         destination_port: '443'
 
         jump: ACCEPT
 
         protocol: tcp
 

	
 
     - name: Firewall rule - drop any traffic without rule
 
       iptables:
 
         chain: INPUT
 
         jump: DROP
 

	
 
     - name: Flush existing firewall rules
 
       iptables:
 
         ip_version: ipv6
 
         flush: true
 

	
 
     - name: Firewall rule - allow all loopback traffic v6
 
       iptables:
 
         ip_version: ipv6
 
         action: append
 
         chain: INPUT
 
         in_interface: lo
 
         jump: ACCEPT
 

	
 
     - name: Firewall rule - allow established connections v6
 
       iptables:
 
         ip_version: ipv6
 
         chain: INPUT
 
         ctstate: ESTABLISHED,RELATED
 
         jump: ACCEPT
 

	
 
     - name: Firewall rule - allow port ping traffic v6
 
       iptables:
 
         ip_version: ipv6
 
         chain: INPUT
 
         jump: ACCEPT
 
         protocol: icmp
 

	
 
     - name: Firewall rule - allow port 22/SSH traffic v6
 
       iptables:
 
         ip_version: ipv6
 
         chain: INPUT
 
         destination_port: '22'
 
         jump: ACCEPT
 
         protocol: tcp
 

	
 
     - name: Firewall rule - allow port 80/HTTP traffic v6
 
       iptables:
 
         ip_version: ipv6
 
         chain: INPUT
 
         destination_port: '80'
 
         jump: ACCEPT
 
         protocol: tcp
 

	
 
     - name: Firewall rule - allow port 443/HTTPS traffic v6
 
       iptables:
 
         ip_version: ipv6
 
         chain: INPUT
 
         destination_port: '443'
 
         jump: ACCEPT
 
         protocol: tcp
 

	
 
     - name: Firewall rule - drop any traffic without rule v6
 
       iptables:
 
         ip_version: ipv6
 
         chain: INPUT
 
         jump: DROP
 

	
 
   handlers:
 
     - name: restart sshd
 
       service:
 
         name: ssh
 
         state: reloaded
 

	
 
     - name: restart postfix
 
       service:
 
         name: postfix
 
         state: reloaded