From e7a8c8aa1cd0b96dcba31d05ab3ae5d1e63d1365 Mon Sep 17 00:00:00 2001 From: Kris Lamoureux Date: Sat, 19 Nov 2022 05:02:28 -0500 Subject: [PATCH] Add port forward script and WordPress - Added Makefile - Added UFW firewall --- .gitignore | 1 + Makefile | 9 +++++ README.md | 12 ++++-- dev/vars/webserver.yml | 42 ++++++++++++++++++++- dev/webserver.yml | 1 + forward-ssh.sh | 26 +++++++++++++ roles/common/tasks/main.yml | 30 +++++++++++++++ roles/docker/tasks/main.yml | 1 - roles/webserver/defaults/main.yml | 3 ++ roles/webserver/files/docker-compose.yml | 28 ++++++++++++++ roles/webserver/handlers/main.yml | 6 +++ roles/webserver/tasks/main.yml | 48 ++++++++++++++++++++++++ roles/webserver/templates/compose-env.j2 | 2 +- webserver.yml | 1 + 14 files changed, 202 insertions(+), 8 deletions(-) create mode 100644 Makefile create mode 100755 forward-ssh.sh create mode 100644 roles/common/tasks/main.yml diff --git a/.gitignore b/.gitignore index 2213c5e..fb9023b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ environments +*.log .playbook .vagrant .vscode diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..050960b --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +all: vagrant + +vagrant: + vagrant up --no-destroy-on-error --no-color | tee ./vagrantup.log + ./forward-ssh.sh + +clean: + vagrant destroy -f --no-color + rm -rf .vagrant ./*.log diff --git a/README.md b/README.md index 16718bf..7055862 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,19 @@ # Free I.T. Athen's Infrastructure This project is used to develop Ansible for deploying and maintaining websites -and services operated by Free I.T. Athens. +and services operated by Free I.T. Athens (FRITA). -- Requires Ansible and Vagrant on the host +- Requires GNU Make, Ansible, and Vagrant on the host ## Quick Start 1. Clone this project -2. Run `vagrant up` to provision a Debian 11 base box +2. Run `make` to provision a Debian 11 base box +3. Go to + - [Traefik Dashboard](https://traefik.local.freeitathens.org:8443/dashboard/#/) + - [WordPress](https://www.local.freeitathens.org) +4. Click through the HTTPS security warning ## Authors -* **Kris Lamoureux** - *Project Founder* - @[krislamo](https://github.com/krislamo) +* **Kris Lamoureux** - *Project Founder* - [@krislamo](https://github.com/krislamo) ## Copyrights and Licenses Copyright (C) 2019, 2020, 2022 Free I.T. Athens diff --git a/dev/vars/webserver.yml b/dev/vars/webserver.yml index 67b1fc7..1f830b6 100644 --- a/dev/vars/webserver.yml +++ b/dev/vars/webserver.yml @@ -1,5 +1,43 @@ +############### +### Secrets ### +############### +secret: + WORDPRESS_DB_PASSWORD: WPpa55w0rd! + +############## +### Docker ### +############## docker_users: - vagrant -webserver_env: - TRAEFIK_DOMAIN: traefik.example.org +################ +#### MariaDB ### +################ +databases: + - name: wordpress + pass: "{{ secret.WORDPRESS_DB_PASSWORD }}" + +####################### +### Webserver Stack ### +####################### +webserver: + ############### + ### Traefik ### + ############### + #TRAEFIK_VERSION: latest + #TRAEFIK_DOMAIN: traefik.local.freeitathens.org + #TRAEFIK_DASHBOARD: true + #TRAEFIK_EXPOSED_DEFAULT: false + #TRAEFIK_TRAEFIK_ENABLE: true + TRAEFIK_DEBUG: true + + ################# + ### WordPress ### + ################# + #WORDPRESS_VERSION: latest + #WORDPRESS_DOMAIN: www.local.freeitathens.org + #WORDPRESS_DB_HOST: host.docker.internal + #WORDPRESS_DB_NAME: wordpress + #WORDPRESS_DB_USER: wordpress + #WORDPRESS_WEB_ENABLED: true + WORDPRESS_DB_PASSWORD: "{{ secret.WORDPRESS_DB_PASSWORD }}" diff --git a/dev/webserver.yml b/dev/webserver.yml index 06bba64..35832e1 100644 --- a/dev/webserver.yml +++ b/dev/webserver.yml @@ -4,5 +4,6 @@ vars_files: - vars/webserver.yml roles: + - common - docker - webserver diff --git a/forward-ssh.sh b/forward-ssh.sh new file mode 100755 index 0000000..471b800 --- /dev/null +++ b/forward-ssh.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Finds the SSH private key under ./.vagrant and connects to +# the Vagrant box, port forwarding localhost ports: 8443, 80, 443 +PRIVATE_KEY="$(find .vagrant -name "private_key")" +HOST_IP="$(vagrant ssh -c "hostname -I | cut -d' ' -f2" 2>/dev/null)" +MATCH_PATTERN="ssh -fNT -i ${PRIVATE_KEY}.*vagrant@" + +function ssh_connect { + sudo ssh -fNT -i "$PRIVATE_KEY" \ + -L 8443:localhost:8443 \ + -L 80:localhost:80 \ + -L 443:localhost:443 \ + -o UserKnownHostsFile=/dev/null \ + -o StrictHostKeyChecking=no \ + vagrant@"${HOST_IP::-1}" 2>/dev/null +} + +set -x +if [ "$(pgrep -afc "$MATCH_PATTERN")" -eq 0 ]; then + ssh_connect +else + pgrep -f "$MATCH_PATTERN" | xargs sudo kill -9 + ssh_connect +fi +set +x diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml new file mode 100644 index 0000000..c9b4068 --- /dev/null +++ b/roles/common/tasks/main.yml @@ -0,0 +1,30 @@ +- name: Create Ansible's temporary remote directory + ansible.builtin.file: + path: "~/.ansible/tmp" + state: directory + mode: 0700 + +- name: Install the Uncomplicated Firewall + ansible.builtin.apt: + name: ufw + state: present + update_cache: true + +- name: Deny incoming traffic by default + community.general.ufw: + default: deny + direction: incoming + +- name: Allow outgoing traffic by default + community.general.ufw: + default: allow + direction: outgoing + +- name: Allow OpenSSH with rate limiting + community.general.ufw: + name: ssh + rule: limit + +- name: Enable firewall + community.general.ufw: + state: enabled diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml index 56dd697..6246c85 100644 --- a/roles/docker/tasks/main.yml +++ b/roles/docker/tasks/main.yml @@ -2,7 +2,6 @@ ansible.builtin.apt: name: ['docker.io', 'docker-compose'] state: present - update_cache: true - name: Create docker-compose root ansible.builtin.file: diff --git a/roles/webserver/defaults/main.yml b/roles/webserver/defaults/main.yml index 363632e..a5c7236 100644 --- a/roles/webserver/defaults/main.yml +++ b/roles/webserver/defaults/main.yml @@ -1 +1,4 @@ webserver_root: "{{ docker_compose_root }}/webserver" +mariadb_trust: + - "172.16.0.0/12" + - "192.168.0.0/16" diff --git a/roles/webserver/files/docker-compose.yml b/roles/webserver/files/docker-compose.yml index d927b20..6754beb 100644 --- a/roles/webserver/files/docker-compose.yml +++ b/roles/webserver/files/docker-compose.yml @@ -1,5 +1,8 @@ version: '3.5' +volumes: + wordpress: + networks: traefik: name: traefik @@ -7,10 +10,12 @@ networks: services: traefik: image: traefik:${TRAEFIK_VERSION:-latest} + restart: always command: - --api.dashboard=${TRAEFIK_DASHBOARD:-true} - --api.debug=${TRAEFIK_DEBUG:-false} - --providers.docker=true + - --providers.docker.exposedbydefault=${TRAEFIK_EXPOSED_DEFAULT:-false} - --entrypoints.web.address=:80 - --entrypoints.web.http.redirections.entrypoint.to=websecure - --entrypoints.web.http.redirections.entrypoint.scheme=https @@ -28,5 +33,28 @@ services: traefik.http.routers.api.entrypoints: local traefik.http.routers.api.service: api@internal traefik.http.routers.api.tls: true + traefik.enable: ${TRAEFIK_WEB_ENABLED:-true} networks: - traefik + + wordpress: + image: wordpress:${WORDPRESS_VERSION:-latest} + restart: always + environment: + WORDPRESS_DB_HOST: ${WORDPRESS_DB_HOST:-host.docker.internal} + WORDPRESS_DB_NAME: ${WORDPRESS_DB_NAME-wordpress} + WORDPRESS_DB_USER: ${WORDPRESS_DB_USER:-wordpress} + WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD} + labels: + traefik.http.routers.wordpress.rule: Host(`${WORDPRESS_DOMAIN:-www.local.freeitathens.org}`) + traefik.http.routers.wordpress.entrypoints: websecure + traefik.http.routers.wordpress.tls: true + traefik.http.services.wordpress.loadbalancer.server.port: 80 + traefik.docker.network: traefik + traefik.enable: ${WORDPRESS_WEB_ENABLED:-true} + volumes: + - wordpress:/var/www/html + networks: + - traefik + extra_hosts: + - host.docker.internal:host-gateway diff --git a/roles/webserver/handlers/main.yml b/roles/webserver/handlers/main.yml index 5a1b951..0b55930 100644 --- a/roles/webserver/handlers/main.yml +++ b/roles/webserver/handlers/main.yml @@ -3,3 +3,9 @@ args: chdir: "{{ webserver_root }}" listen: composeup_webserver + +- name: Restart MariaDB + ansible.builtin.service: + name: mariadb + state: restarted + listen: restart_mariadb diff --git a/roles/webserver/tasks/main.yml b/roles/webserver/tasks/main.yml index d8263e4..1760726 100644 --- a/roles/webserver/tasks/main.yml +++ b/roles/webserver/tasks/main.yml @@ -3,6 +3,37 @@ name: mariadb-server state: present +- name: Change the bind-address to allow Docker + ansible.builtin.lineinfile: + path: /etc/mysql/mariadb.conf.d/50-server.cnf + regex: "^bind-address" + line: "bind-address = 0.0.0.0" + notify: restart_mariadb + +- name: Install MySQL Support for Python 3 + ansible.builtin.apt: + name: python3-pymysql + state: present + +- name: Create MariaDB databases + community.mysql.mysql_db: + name: "{{ item.name }}" + state: present + login_unix_socket: /var/run/mysqld/mysqld.sock + loop: "{{ databases }}" + no_log: "{{ item.pass is defined }}" + +- name: Create MariaDB users + community.mysql.mysql_user: + name: "{{ item.name }}" + password: "{{ item.pass }}" + host: '%' + state: present + priv: "{{ item.name }}.*:ALL" + login_unix_socket: /var/run/mysqld/mysqld.sock + loop: "{{ databases }}" + no_log: "{{ item.pass is defined }}" + - name: Create webserver docker-compose directory ansible.builtin.file: path: "{{ webserver_root }}" @@ -22,3 +53,20 @@ dest: "{{ webserver_root }}/.env" mode: 0600 notify: composeup_webserver + +- name: Allow MariaDB database connections + community.general.ufw: + rule: allow + port: 3306 + proto: tcp + src: "{{ item }}" + loop: "{{ mariadb_trust }}" + +- name: Add HTTP and HTTPS firewall rule + community.general.ufw: + rule: allow + port: "{{ item }}" + proto: tcp + loop: + - "80" + - "443" diff --git a/roles/webserver/templates/compose-env.j2 b/roles/webserver/templates/compose-env.j2 index f536af2..34bb576 100644 --- a/roles/webserver/templates/compose-env.j2 +++ b/roles/webserver/templates/compose-env.j2 @@ -1,4 +1,4 @@ # {{ ansible_managed }} -{% for key, value in webserver_env.items() %} +{% for key, value in webserver.items() %} {{ key }}={{ value }} {% endfor %} diff --git a/webserver.yml b/webserver.yml index f981b76..6878092 100644 --- a/webserver.yml +++ b/webserver.yml @@ -2,5 +2,6 @@ hosts: all become: true roles: + - common - docker - webserver