diff --git a/deploy/ansible/20auto-upgrades b/deploy/ansible/20auto-upgrades new file mode 100644 index 00000000..f29c25ff --- /dev/null +++ b/deploy/ansible/20auto-upgrades @@ -0,0 +1,4 @@ +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Unattended-Upgrade "1"; +Unattended-Upgrade::Automatic-Reboot "true"; +Unattended-Upgrade::Automatic-Reboot-Time "02:00"; diff --git a/deploy/ansible/install.yml b/deploy/ansible/install.yml new file mode 100644 index 00000000..ab3900a7 --- /dev/null +++ b/deploy/ansible/install.yml @@ -0,0 +1,222 @@ +--- +# Run this with: +# ansible-playbook -i deploy/ansible/inventory.ini --become --ask-become-pass deploy/ansible/install.yml + +# Other useful commands: +# ansible all -i [HOST], -u user -m ping +# ansible all -i [HOST], -u user -a /bin/date +# scp -3 -v [OLDHOST]:backup/backup.gz [HOST]:tmp/ + +# /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. +# +# No mail as yet. +# +# No etckeeper as yet. +# +# a2enmod ssl rewrite + + - name: Configure web server + hosts: web + # remote_user: + # become_user: + # become_method: + + tasks: + - name: Install unattended upgrades + apt: + name: unattended-upgrades + + - name: Configure unattended upgrades + copy: + src: 20auto-upgrades + dest: /etc/apt/apt.conf.d/20auto-upgrades + + - name: Install Apache + apt: + name: apache2,libapache2-mod-wsgi-py3 + + - 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 + regexp: '^#?PasswordAuthentication ' + line: 'PasswordAuthentication no' + 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' + + - name: Create the database directory + file: + path: /var/lib/www/database + state: directory + owner: www-data + group: www-data + mode: '0755' + + - name: Git checkout + ansible.builtin.git: + repo: 'https://k.sfconservancy.org/website' + dest: /var/www/website + version: master + + - name: Create static dir + file: + path: /var/www/website/conservancy/static + state: directory + owner: www-data + group: www-data + mode: '0755' + + - 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 diff --git a/deploy/ansible/inventory.ini b/deploy/ansible/inventory.ini new file mode 100644 index 00000000..f4432766 --- /dev/null +++ b/deploy/ansible/inventory.ini @@ -0,0 +1,2 @@ +[web] +debian@hickory.sfconservancy.org ansible_connection=ssh diff --git a/systemd/README.md b/systemd/README.md index 0119860d..68584325 100644 --- a/systemd/README.md +++ b/systemd/README.md @@ -15,3 +15,5 @@ Updates will fail unless `/var/www/website` has a git upstream, so set that with git remote add upstream https://k.sfconservancy.org/website git branch --set-upstream-to=upstream/master master + +Note that the update script does not run `migrate`.