Compare commits
	
		
			11 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f42cb94872 | |||
| 3abca7ce15 | |||
| bf9c98fd3f | |||
| 511c26392c | |||
| 91c65abb91 | |||
| 34495c80be | |||
| 671a94063d | |||
| 51b6f3b843 | |||
| 7bd4858c7e | |||
| e7a8c8aa1c | |||
| 75ee5be87d | 
							
								
								
									
										13
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,8 +1,7 @@ | ||||
| # Vagrant files | ||||
| .ansible_vault | ||||
| .bitwarden | ||||
| environments | ||||
| *.log | ||||
| .playbook | ||||
| .vagrant | ||||
|  | ||||
| # Unneeded ansible file | ||||
| *.retry | ||||
|  | ||||
| # Custom environments | ||||
| /environments/ | ||||
| .vscode | ||||
|   | ||||
							
								
								
									
										9
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| all: vagrant | ||||
|  | ||||
| vagrant: | ||||
| 	vagrant up --no-destroy-on-error --no-color | tee ./vagrantup.log | ||||
| 	./scripts/forward-ssh.sh | ||||
|  | ||||
| clean: | ||||
| 	vagrant destroy -f --no-color | ||||
| 	rm -rf .vagrant ./*.log | ||||
							
								
								
									
										51
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,22 +1,49 @@ | ||||
| # Free I.T. Athen’s Infrastructure | ||||
| Ansible code used to deploy and maintain websites and services used by Free I.T. Athens. | ||||
| # 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 (FRITA). | ||||
|  | ||||
| ## Getting Started | ||||
| frita-infra is developed in Ansible 2.7.5 using Vagrant 2.2.2 + vagrant-libvirt as a test environment. | ||||
| - Requires GNU Make, Ansible, and Vagrant on the host | ||||
|  | ||||
| Check it out by simply typing: `vagrant up` | ||||
| ## Quick Start | ||||
| 1. Clone this project | ||||
| 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) | ||||
|     - [Nextcloud](https://cloud.local.freeitathens.org) | ||||
| 4. Click through the HTTPS security warning | ||||
|  | ||||
| ## Versioning | ||||
| We use [SemVer](http://semver.org/) for versioning. For the versions available, see the tags on this repository.  | ||||
| ## Production | ||||
| 1. Clone [production-env](https://github.com/freeitathens/production-env/) to `./environments` | ||||
|  | ||||
|     ``` | ||||
|     mkdir -p environments | ||||
|     git clone git@github.com:freeitathens/production-env.git ./environments | ||||
|     ``` | ||||
|  | ||||
| 2. Run `./scripts/vault-key.sh` from the root of the project to obtain the Ansible Vault password | ||||
| 3. Enter the Bitwarden Master Password | ||||
| 4. Run `ansible-playbook` against the production servers, e.g., | ||||
|  | ||||
|     ``` | ||||
|     ansible-playbook -u root -i environments/production --vault-pass-file ./.ansible_vault webserver.yml --check | ||||
|     ``` | ||||
|  | ||||
| 5. Delete the `.ansible_vault` file when you are done | ||||
|  | ||||
| ## 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  Free I.T. Athens | ||||
| Copyright (C) 2019, 2020, 2022  Free I.T. Athens | ||||
|  | ||||
| This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. | ||||
| This program is free software: you can redistribute it and/or modify it under | ||||
| the terms of the GNU General Public License as published by the Free Software | ||||
| Foundation, version 3 of the License. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details. | ||||
| This program is distributed in the hope that it will be useful, but WITHOUT | ||||
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
| FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| You should have received a copy of the GNU General Public License along with | ||||
| this program. If not, see <https://www.gnu.org/licenses/>. | ||||
|   | ||||
							
								
								
									
										52
									
								
								Vagrantfile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								Vagrantfile
									
									
									
									
										vendored
									
									
								
							| @@ -1,43 +1,47 @@ | ||||
| # Copyright (C) 2019  Free I.T. Athens | ||||
| #  | ||||
| # This program is free software: you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation, version 3 of the License. | ||||
| #  | ||||
| # This program is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| #  | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  | ||||
|  | ||||
| # vi: set ft=ruby : | ||||
|  | ||||
| # Set PLAYBOOK shell var for ./dev/playbook.yml | ||||
| PLAYBOOK=ENV["PLAYBOOK"] | ||||
| if !PLAYBOOK | ||||
|   if File.exist?('.playbook') | ||||
|     PLAYBOOK = IO.read('.playbook').split("\n")[0] | ||||
|   end | ||||
|  | ||||
|   if !PLAYBOOK || PLAYBOOK.empty? | ||||
|     PLAYBOOK = "webserver" | ||||
|   end | ||||
| else | ||||
|   File.write(".playbook", PLAYBOOK) | ||||
| end | ||||
|  | ||||
| # Debian 11 | ||||
| Vagrant.configure("2") do |config| | ||||
|  | ||||
|   # Debian Stable box | ||||
|   config.vm.box = "debian/stretch64" | ||||
|   config.vm.box = "debian/bullseye64" | ||||
|   config.vm.synced_folder ".", "/vagrant", disabled: true | ||||
|  | ||||
|   # Set static IP | ||||
|   config.vm.network "private_network", ip: "192.168.121.2" | ||||
|   config.vm.network "private_network", type: "dhcp" | ||||
|  | ||||
|   # Machine Name | ||||
|   config.vm.define :frita do |frita| # | ||||
|   end | ||||
|  | ||||
|   # Disable Machine Name Prefix | ||||
|   # Set libvirt settings | ||||
|   config.vm.provider :libvirt do |libvirt| | ||||
|     libvirt.cpus = 2 | ||||
|     libvirt.memory = 4096 | ||||
|     libvirt.default_prefix = "" | ||||
|   end | ||||
|  | ||||
|   # Set VirtualBox settings | ||||
|   config.vm.provider "virtualbox" do |vbox| | ||||
|     vbox.cpus = 2 | ||||
|     vbox.memory = 4096 | ||||
|   end | ||||
|  | ||||
|   # Provision with Ansible | ||||
|   config.vm.provision "ansible" do |ansible| | ||||
|     ENV['ANSIBLE_ROLES_PATH'] = File.dirname(__FILE__) + "/roles" | ||||
|     ansible.compatibility_mode = "2.0" | ||||
|     ansible.playbook = "site.yml" | ||||
|     ansible.playbook = "dev/" + PLAYBOOK + ".yml" | ||||
|   end | ||||
|  | ||||
| end | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| [defaults] | ||||
| inventory = ./environments/development | ||||
| interpreter_python = /usr/bin/python | ||||
| interpreter_python = /usr/bin/python3 | ||||
|  | ||||
| [ssh_connection] | ||||
| pipelining=True | ||||
|  | ||||
|   | ||||
							
								
								
									
										67
									
								
								dev/vars/webserver.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								dev/vars/webserver.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| ############### | ||||
| ### Secrets ### | ||||
| ############### | ||||
| # These are sample public passwords not encrypted in Ansible Vault, unlike production | ||||
| secret: | ||||
|   TRAEFIK_DREAMHOST_APIKEY: DHap1pa55w0rd! | ||||
|   WORDPRESS_DB_PASSWORD: WPpa55w0rd! | ||||
|   NEXTCLOUD_MYSQL_PASSWORD: NCdbpa55w0rd! | ||||
|   NEXTCLOUD_ADMIN_PASSWORD: NCadm1npa55w0rd! | ||||
|  | ||||
| ############## | ||||
| ### Docker ### | ||||
| ############## | ||||
| docker_users: | ||||
|   - vagrant | ||||
|  | ||||
| ################ | ||||
| #### MariaDB ### | ||||
| ################ | ||||
| databases: | ||||
|   - name: wordpress | ||||
|     pass: "{{ secret.WORDPRESS_DB_PASSWORD }}" | ||||
|   - name: nextcloud | ||||
|     pass: "{{ secret.NEXTCLOUD_MYSQL_PASSWORD }}" | ||||
|  | ||||
| ####################### | ||||
| ### Webserver Stack ### | ||||
| ####################### | ||||
| webserver: | ||||
|   ############### | ||||
|   ### Traefik ### | ||||
|   ############### | ||||
|   #TRAEFIK_VERSION: latest | ||||
|   #TRAEFIK_ROOT_DOMAIN: local.freeitathens.org | ||||
|   #TRAEFIK_DOMAIN: traefik.local.freeitathens.org | ||||
|   #TRAEFIK_DASHBOARD: true | ||||
|   #TRAEFIK_EXPOSED_DEFAULT: false | ||||
|   #TRAEFIK_WEB_ENABLED: true | ||||
|   TRAEFIK_DEBUG: true | ||||
|   TRAEFIK_ACME_PROVIDER: dreamhost | ||||
|   TRAEFIK_ACME_CASERVER: https://localhost/directory | ||||
|   TRAEFIK_ACME_EMAIL: admin@example.org | ||||
|   TRAEFIK_DREAMHOST_APIKEY: "{{ secret.TRAEFIK_DREAMHOST_APIKEY }}" | ||||
|  | ||||
|   ################# | ||||
|   ### 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 }}" | ||||
|  | ||||
|   ################# | ||||
|   ### Nextcloud ### | ||||
|   ################# | ||||
|   #NEXTCLOUD_VERSION: stable | ||||
|   #NEXTCLOUD_DOMAIN: cloud.local.freeitathens.org | ||||
|   #NEXTCLOUD_MYSQL_HOST: host.docker.internal | ||||
|   #NEXTCLOUD_MYSQL_DATABASE: nextcloud | ||||
|   #NEXTCLOUD_MYSQL_USER: nextcloud | ||||
|   #NEXTCLOUD_WEB_ENABLED: true | ||||
|   #NEXTCLOUD_ADMIN: admin | ||||
|   NEXTCLOUD_ADMIN_PASSWORD: "{{ secret.NEXTCLOUD_ADMIN_PASSWORD }}" | ||||
|   NEXTCLOUD_MYSQL_PASSWORD: "{{ secret.NEXTCLOUD_MYSQL_PASSWORD }}" | ||||
							
								
								
									
										9
									
								
								dev/webserver.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								dev/webserver.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| - name: Install FRITA Web Server | ||||
|   hosts: all | ||||
|   become: true | ||||
|   vars_files: | ||||
|     - vars/webserver.yml | ||||
|   roles: | ||||
|     - common | ||||
|     - docker | ||||
|     - webserver | ||||
| @@ -1,46 +0,0 @@ | ||||
| ### WordPress Configuration ### | ||||
|  | ||||
| # Domain | ||||
| wp_domain: www.freeitathens.org | ||||
| wp_admin_email: contact@freeitathens.org | ||||
|  | ||||
| # Version of WordPress to deploy | ||||
| wp_version: 5.1.1 | ||||
| wp_sha1_hash: f1bff89cc360bf5ef7086594e8a9b68b4cbf2192 | ||||
|  | ||||
| # WordPress Home Directory | ||||
| # Note: value is a directory without trailing '/' | ||||
| wp_dir: /var/www/wordpress | ||||
|  | ||||
| # WordPress Database Settings | ||||
| wp_db_host: localhost | ||||
| wp_db_name: wordpress | ||||
| wp_db_user: wordpress_user | ||||
| wp_db_pass: Password1 | ||||
| wp_db_table_prefix: wp_ | ||||
|  | ||||
|  | ||||
| ### Nextcloud Configuration ### | ||||
|  | ||||
| # Domain | ||||
| nc_domain: cloud.freeitathens.org | ||||
| nc_admin_email: contact@freeitathens.org | ||||
|  | ||||
| # Version of Nextcloud to deploy | ||||
| nc_version: 15.0.2 | ||||
| nc_sha256_hash: c1f4cc33e39994ddbe6777370b62c30b7ae52136a0530c0b9922770803ca0fea | ||||
|  | ||||
| # Nextcloud Home Directory | ||||
| # Note: value is a directory without trailing '/' | ||||
| nc_dir: /var/www/nextcloud | ||||
|  | ||||
| # Nextcloud Database Settings | ||||
| nc_db_host: localhost | ||||
| nc_db_name: nextcloud | ||||
| nc_db_user: nextcloud_user | ||||
| nc_db_pass: Password1 | ||||
|  | ||||
| # Nextcloud Admin | ||||
| nc_admin: admin | ||||
| nc_admin_pass: Password1 | ||||
|  | ||||
| @@ -1,22 +0,0 @@ | ||||
| - name: 'Install Ansible dependency: python-apt' | ||||
|   shell: 'apt-get update && apt-get install python-apt -y' | ||||
|   args: | ||||
|     creates: /usr/lib/python2.7/dist-packages/apt | ||||
|     warn: false | ||||
|  | ||||
| - name: 'Install Ansible dependency: aptitude' | ||||
|   apt: | ||||
|     name: 'aptitude' | ||||
|     state: present | ||||
|     force_apt_get: true | ||||
|  | ||||
| - name: 'Install Ansible dependency: python-docker' | ||||
|   apt: | ||||
|     name: python-docker | ||||
|     state: present | ||||
|  | ||||
| - name: Create Ansible's temporary directory | ||||
|   file: | ||||
|     path: /root/.ansible/tmp | ||||
|     state: directory | ||||
|     mode: '0700' | ||||
							
								
								
									
										2
									
								
								roles/common/defaults/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								roles/common/defaults/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| packages: | ||||
|   - dnsutils | ||||
							
								
								
									
										36
									
								
								roles/common/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								roles/common/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| - name: Create Ansible's temporary remote directory | ||||
|   ansible.builtin.file: | ||||
|     path: "~/.ansible/tmp" | ||||
|     state: directory | ||||
|     mode: 0700 | ||||
|  | ||||
| - name: Install useful software | ||||
|   ansible.builtin.apt: | ||||
|     name: "{{ packages }}" | ||||
|     state: present | ||||
|     update_cache: true | ||||
|  | ||||
| - 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 | ||||
							
								
								
									
										3
									
								
								roles/docker/defaults/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								roles/docker/defaults/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| docker_compose_root: /var/lib/compose | ||||
| docker_compose: /usr/bin/docker-compose | ||||
| docker_compose_service: compose | ||||
							
								
								
									
										24
									
								
								roles/docker/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								roles/docker/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| - name: Install Docker | ||||
|   ansible.builtin.apt: | ||||
|     name: ['docker.io', 'docker-compose'] | ||||
|     state: present | ||||
|  | ||||
| - name: Create docker-compose root | ||||
|   ansible.builtin.file: | ||||
|     path: "{{ docker_compose_root }}" | ||||
|     state: directory | ||||
|     mode: 0600 | ||||
|  | ||||
| - name: Add users to docker group | ||||
|   ansible.builtin.user: | ||||
|     name: "{{ item }}" | ||||
|     groups: docker | ||||
|     append: true | ||||
|   loop: "{{ docker_users }}" | ||||
|   when: docker_users is defined | ||||
|  | ||||
| - name: Start Docker and enable on boot | ||||
|   ansible.builtin.service: | ||||
|     name: docker | ||||
|     state: started | ||||
|     enabled: true | ||||
| @@ -1,90 +0,0 @@ | ||||
| - name: Install MySQL Support for Python | ||||
|   apt: | ||||
|     name: python-pymysql | ||||
|     state: present | ||||
|  | ||||
| - name: Create Database | ||||
|   mysql_db: | ||||
|     name: "{{ mw_db_name }}" | ||||
|     state: present | ||||
|     login_unix_socket: /var/run/mysqld/mysqld.sock | ||||
|  | ||||
| - name: Create Database User | ||||
|   mysql_user: | ||||
|     name: "{{ mw_db_user }}" | ||||
|     password: "{{ mw_db_pass }}" | ||||
|     priv: "{{ mw_db_name }}.*:ALL,GRANT" | ||||
|     state: present | ||||
|     login_unix_socket: /var/run/mysqld/mysqld.sock | ||||
|  | ||||
| - name: Install PHP Modules | ||||
|   apt: | ||||
|     name: ['php-xml', 'php-mbstring'] | ||||
|     state: present | ||||
|   notify: Reload Apache2 | ||||
|  | ||||
| - name: Create Public HTML Directory | ||||
|   file: | ||||
|     path: "{{ mw_dir }}/public_html" | ||||
|     state: directory | ||||
|  | ||||
| # https://www.mediawiki.org/wiki/Manual:Short_URL#Moving_a_wiki_from_/wiki_to_/w | ||||
| - name: Create Directory /w for Short URLs | ||||
|   file: | ||||
|     path: "{{ mw_dir }}/public_html/w" | ||||
|     state: directory | ||||
|  | ||||
| - name: Create Logs Directory | ||||
|   file: | ||||
|     path: "{{ mw_dir }}/logs" | ||||
|     state: directory | ||||
|  | ||||
| - name: Download MediaWiki | ||||
|   get_url: | ||||
|     url: "https://releases.wikimedia.org/mediawiki/\ | ||||
|           {{ mw_version | regex_replace('\\.\\d+$', '') }}/\ | ||||
|           mediawiki-{{ mw_version }}.tar.gz" | ||||
|     dest: /tmp/mediawiki-{{ mw_version }}.tar.gz | ||||
|  | ||||
| - name: Extract MediaWiki | ||||
|   unarchive: | ||||
|     src: /tmp/mediawiki-{{ mw_version }}.tar.gz | ||||
|     dest: "{{ mw_dir }}/public_html/w" | ||||
|     owner: www-data | ||||
|     group: www-data | ||||
|     extra_opts: [--strip-components=1] | ||||
|     remote_src: yes | ||||
|  | ||||
| - name: Install MediaWiki | ||||
|   command: | | ||||
|     php maintenance/install.php --server="http://{{ mw_domain }}/" \ | ||||
|     --dbname="{{ mw_db_name }}" --dbuser="{{ mw_db_user }}" \ | ||||
|     --dbpass="{{ mw_db_pass }}" --pass="{{ mw_admin_pass }}" \ | ||||
|     --scriptpath="/w" "{{ mw_namespace }}" "{{ mw_admin }}" | ||||
|   args: | ||||
|     chdir: "{{ mw_dir }}/public_html/w" | ||||
|     creates: "{{ mw_dir }}/public_html/w/LocalSettings.php" | ||||
|  | ||||
| - name: Set MediaWiki Article Path | ||||
|   lineinfile: | ||||
|     path: "{{ mw_dir }}/public_html/w/LocalSettings.php" | ||||
|     regexp: '^\$wgArticlePath' | ||||
|     insertafter: '^\$wgScriptPath' | ||||
|     line: '$wgArticlePath = "/wiki/$1";' | ||||
|  | ||||
| - name: "Enable Apache Module: rewrite" | ||||
|   apache2_module: | ||||
|     name: rewrite | ||||
|     state: present | ||||
|  | ||||
| - name: Apply Apache Configuration | ||||
|   template: | ||||
|     src: mediawiki.conf.j2 | ||||
|     dest: /etc/apache2/sites-available/{{ mw_domain }}.conf | ||||
|   notify: Reload Apache2 | ||||
|  | ||||
| - name: Enable Apache Website | ||||
|   shell: a2ensite {{ mw_domain }} | ||||
|   args: | ||||
|     creates: /etc/apache2/sites-enabled/{{ mw_domain }}.conf | ||||
|   notify: Reload Apache2 | ||||
| @@ -1,15 +0,0 @@ | ||||
| <VirtualHost *:80> | ||||
|   ServerName {{ mw_domain }} | ||||
|  | ||||
|   ServerAdmin {{ mw_admin_email }} | ||||
|   DocumentRoot {{ mw_dir }}/public_html | ||||
|  | ||||
|   RewriteEngine On | ||||
|   RewriteRule ^/?wiki(/.*)?$ %{DOCUMENT_ROOT}/w/index.php [L] | ||||
|   RewriteRule ^/?$ %{DOCUMENT_ROOT}/w/index.php [L] | ||||
|  | ||||
|   ErrorLog {{ mw_dir }}/logs/error.log | ||||
|   CustomLog {{ mw_dir }}/logs/access.log combined | ||||
| </VirtualHost> | ||||
|  | ||||
| # vim: syntax=apache ts=4 sw=4 sts=4 sr noet | ||||
| @@ -1,140 +0,0 @@ | ||||
| # Copyright (C) 2019-2020  Free I.T. Athens | ||||
| # | ||||
| # This program is free software: you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation, version 3 of the License. | ||||
| # | ||||
| # This program is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| # | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  | ||||
| - name: Install MySQL Support for Python | ||||
|   apt: | ||||
|     name: python-pymysql | ||||
|     state: present | ||||
|  | ||||
| - name: Create Database | ||||
|   mysql_db: | ||||
|     name: "{{ nc_db_name }}" | ||||
|     state: present | ||||
|     login_unix_socket: /var/run/mysqld/mysqld.sock | ||||
|  | ||||
| - name: Create Database User | ||||
|   mysql_user: | ||||
|     name: "{{ nc_db_user }}" | ||||
|     password: "{{ nc_db_pass }}" | ||||
|     priv: "{{ nc_db_name }}.*:ALL,GRANT" | ||||
|     state: present | ||||
|     login_unix_socket: /var/run/mysqld/mysqld.sock | ||||
|  | ||||
| - name: Install PHP Modules | ||||
|   apt: | ||||
|     name: [ | ||||
|             # Required | ||||
|             'php-ctype', 'php-curl', 'php-dom', | ||||
|             'php-gd', 'php-iconv', 'php-json', 'php-xml', | ||||
|             'php-mbstring', 'php-posix', 'php-simplexml', | ||||
|             'php-xmlreader', 'php-xmlwriter', 'php-zip', | ||||
|  | ||||
|             # Database Connectors | ||||
|             'php-pgsql', | ||||
|  | ||||
|             # Recommended Packages | ||||
|             'php-fileinfo', 'php-bz2', 'php-intl', | ||||
|  | ||||
|             # Enhanced Performance | ||||
|             'php-redis', 'redis-server', | ||||
|  | ||||
|             # Preview Generation | ||||
|             'php-imagick' | ||||
|           ] | ||||
|     state: present | ||||
|   notify: Reload Apache2 | ||||
|  | ||||
| - name: Create Public HTML Directory | ||||
|   file: | ||||
|     path: "{{ nc_dir }}/public_html" | ||||
|     state: directory | ||||
|  | ||||
| - name: Create Nextcloud Directories | ||||
|   file: | ||||
|     path: "{{ nc_dir }}/public_html/data" | ||||
|     state: directory | ||||
|     owner: www-data | ||||
|     group: www-data | ||||
|  | ||||
| - name: Create Logs Directory | ||||
|   file: | ||||
|     path: "{{ nc_dir }}/logs" | ||||
|     state: directory | ||||
|  | ||||
| - name: Download Nextcloud | ||||
|   get_url: | ||||
|     url: "https://download.nextcloud.com/server/releases/\ | ||||
|           nextcloud-{{ nc_version }}.tar.bz2" | ||||
|     dest: /tmp/nextcloud-{{ nc_version }}.tar.bz2 | ||||
|     checksum: sha256:{{ nc_sha256_hash }} | ||||
|  | ||||
| - name: Extract Nextcloud | ||||
|   unarchive: | ||||
|     src: /tmp/nextcloud-{{ nc_version }}.tar.bz2 | ||||
|     dest: "{{ nc_dir }}/public_html" | ||||
|     owner: www-data | ||||
|     group: www-data | ||||
|     extra_opts: [--strip-components=1] | ||||
|     remote_src: yes | ||||
|  | ||||
| - name: Install Nextcloud | ||||
|   command: | | ||||
|     php occ maintenance:install --database mysql \ | ||||
|     --database-name {{ nc_db_name }} --database-host {{ nc_db_host }} \ | ||||
|     --database-user {{ nc_db_user }} --database-pass {{ nc_db_pass }} \ | ||||
|     --admin-user {{ nc_admin }} --admin-pass {{ nc_admin_pass }} \ | ||||
|     --data-dir {{ nc_dir }}/public_html/data | ||||
|   become_user: www-data | ||||
|   register: nextcloud_install | ||||
|   args: | ||||
|     chdir: "{{ nc_dir }}/public_html" | ||||
|     creates: "{{ nc_dir }}/public_html/config/config.php" | ||||
|  | ||||
| - name: Add Missing Database Indexes | ||||
|   command: php occ db:add-missing-indices | ||||
|   become_user: www-data | ||||
|   register: nextcloud_db_update | ||||
|   args: | ||||
|     chdir: "{{ nc_dir }}/public_html" | ||||
|   when: nextcloud_install.changed | ||||
|  | ||||
| - name: Convert Database Columns to BIGINT | ||||
|   command: php occ db:convert-filecache-bigint | ||||
|   become_user: www-data | ||||
|   args: | ||||
|     chdir: "{{ nc_dir }}/public_html" | ||||
|   when: nextcloud_db_update.changed | ||||
|  | ||||
| - name: Add Domain Name to Trusted Domains | ||||
|   command: | | ||||
|     php occ config:system:set trusted_domains 0 --value={{ nc_domain }} | ||||
|   become_user: www-data | ||||
|   args: | ||||
|     chdir: "{{ nc_dir }}/public_html" | ||||
|   when: nextcloud_install.changed | ||||
|  | ||||
| - name: "Enable Apache2 Module: rewrite" | ||||
|   apache2_module: name=rewrite state=present | ||||
|  | ||||
| - name: Apply Apache Configuration | ||||
|   template: | ||||
|     src: nextcloud.conf.j2 | ||||
|     dest: /etc/apache2/sites-available/{{ nc_domain }}.conf | ||||
|   notify: Reload Apache2 | ||||
|  | ||||
| - name: Enable Apache Website | ||||
|   shell: a2ensite {{ nc_domain }} | ||||
|   args: | ||||
|     creates: /etc/apache2/sites-enabled/{{ nc_domain }}.conf | ||||
|   notify: Reload Apache2 | ||||
| @@ -1,27 +0,0 @@ | ||||
| <VirtualHost *:80> | ||||
|   ServerName {{ nc_domain }} | ||||
|  | ||||
|   ServerAdmin {{ nc_admin_email }} | ||||
|   DocumentRoot {{ nc_dir }}/public_html | ||||
|  | ||||
|   <Directory {{ nc_dir }}/public_html> | ||||
|  | ||||
|     Options +FollowSymLinks | ||||
|     AllowOverride All | ||||
|  | ||||
|     <IfModule mod_dav.c> | ||||
|       Dav off | ||||
|     </IfModule> | ||||
|  | ||||
|     SetEnv HOME {{ nc_dir }}/public_html | ||||
|     SetEnv HTTP_HOME {{ nc_dir }}/public_html | ||||
|  | ||||
|     # Nextcloud recommends 512MB | ||||
|     php_value memory_limit 512M | ||||
|   </Directory> | ||||
|  | ||||
|   ErrorLog {{ nc_dir }}/logs/error.log | ||||
|   CustomLog {{ nc_dir }}/logs/access.log combined | ||||
| </VirtualHost> | ||||
|  | ||||
| # vim: syntax=apache ts=4 sw=4 sts=4 sr noet | ||||
							
								
								
									
										5
									
								
								roles/webserver/defaults/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								roles/webserver/defaults/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| webserver_root: "{{ docker_compose_root }}/webserver" | ||||
| nextcloud_autoinstall: true | ||||
| mariadb_trust: | ||||
|   - "172.16.0.0/12" | ||||
|   - "192.168.0.0/16" | ||||
							
								
								
									
										146
									
								
								roles/webserver/files/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								roles/webserver/files/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | ||||
| version: '3.5' | ||||
|  | ||||
| volumes: | ||||
|   wordpress: | ||||
|   nextcloud: | ||||
|   postgres: | ||||
|  | ||||
| networks: | ||||
|   traefik: | ||||
|     name: traefik | ||||
|   postgres: | ||||
|     name: postgres | ||||
|  | ||||
| services: | ||||
|   traefik: | ||||
|     image: traefik:${TRAEFIK_VERSION:-latest} | ||||
|     restart: always | ||||
|     command: | ||||
|       - --api.dashboard=${TRAEFIK_DASHBOARD:-true} | ||||
|       - --api.debug=${TRAEFIK_DEBUG:-false} | ||||
|       - --log.level=${TRAEFIK_LOG_LEVEL:-ERROR} | ||||
|       - --providers.docker=true | ||||
|       - --providers.docker.exposedbydefault=${TRAEFIK_EXPOSED_DEFAULT:-false} | ||||
|       - --entrypoints.web.address=:80 | ||||
|       - --entrypoints.websecure.address=:443 | ||||
|       - --entrypoints.local.address=:8443 | ||||
|       - --entrypoints.web.http.redirections.entrypoint.to=websecure | ||||
|       - --entrypoints.web.http.redirections.entrypoint.scheme=https | ||||
|       - --entrypoints.web.http.redirections.entrypoint.permanent=true | ||||
|       - --certificatesresolvers.letsencrypt.acme.email=${TRAEFIK_ACME_EMAIL} | ||||
|       - --certificatesresolvers.letsencrypt.acme.storage=/etc/letsencrypt/acme.json | ||||
|       - --certificatesresolvers.letsencrypt.acme.dnschallenge=true | ||||
|       - --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=${TRAEFIK_ACME_PROVIDER:-manual} | ||||
|       - --certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=0 | ||||
|       - --certificatesresolvers.letsencrypt.acme.caserver=${TRAEFIK_ACME_CASERVER:-https://acme-staging-v02.api.letsencrypt.org/directory} | ||||
|     environment: | ||||
|       DREAMHOST_API_KEY: ${TRAEFIK_DREAMHOST_APIKEY} | ||||
|     ports: | ||||
|       - 80:80 | ||||
|       - 443:443 | ||||
|       - "127.0.0.1:8443:8443" | ||||
|     volumes: | ||||
|       - /var/run/docker.sock:/var/run/docker.sock | ||||
|       - ./.acme:/etc/letsencrypt | ||||
|     labels: | ||||
|       traefik.http.routers.api.rule: Host(`${TRAEFIK_DOMAIN:-traefik.local.freeitathens.org}`) | ||||
|       traefik.http.routers.api.entrypoints: local | ||||
|       traefik.http.routers.api.service: api@internal | ||||
|       traefik.http.routers.api.tls: true | ||||
|       traefik.http.routers.api.tls.certresolver: letsencrypt | ||||
|       traefik.http.routers.api.tls.domains[0].main: ${TRAEFIK_ACME_DOMAIN_MAIN:-local.freeitathens.org} | ||||
|       traefik.http.routers.api.tls.domains[0].sans: "${TRAEFIK_ACME_DOMAIN_SANS:-*.local.freeitathens.org}" | ||||
|       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_ACME_DOMAIN_MAIN:-local.freeitathens.org}`) | ||||
|       traefik.http.routers.wordpress.entrypoints: websecure | ||||
|       traefik.http.routers.wordpress.middlewares: "wwwredirect" | ||||
|       traefik.http.routers.wordpress.tls: true | ||||
|       traefik.http.routers.wordpress.tls.certresolver: letsencrypt | ||||
|       traefik.http.routers.wordpress.tls.domains[0].main: ${TRAEFIK_ACME_DOMAIN_MAIN:-local.freeitathens.org} | ||||
|       traefik.http.routers.wordpress.tls.domains[0].sans: "${TRAEFIK_ACME_DOMAIN_SANS:-*.local.freeitathens.org}" | ||||
|       traefik.http.middlewares.wwwredirect.redirectregex.regex: "^https://${TRAEFIK_ACME_DOMAIN_MAIN:-local.freeitathens.org}/(.*)" | ||||
|       traefik.http.middlewares.wwwredirect.redirectregex.replacement: "https://${WORDPRESS_DOMAIN:-www.local.freeitathens.org}/$${1}" | ||||
|       traefik.http.middlewares.wwwredirect.redirectregex.permanent: 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 | ||||
|  | ||||
|   nextcloud: | ||||
|     image: nextcloud:${NEXTCLOUD_VERSION:-stable} | ||||
|     restart: always | ||||
|     environment: | ||||
|       MYSQL_HOST: ${NEXTCLOUD_MYSQL_HOST:-host.docker.internal:3306} | ||||
|       MYSQL_DATABASE: ${NEXTCLOUD_MYSQL_DATABASE-nextcloud} | ||||
|       MYSQL_USER: ${NEXTCLOUD_MYSQL_USER:-nextcloud} | ||||
|       MYSQL_PASSWORD: ${NEXTCLOUD_MYSQL_PASSWORD} | ||||
|     labels: | ||||
|       traefik.http.routers.nextcloud.rule: "Host(`${NEXTCLOUD_DOMAIN:-cloud.local.freeitathens.org}`)" | ||||
|       traefik.http.routers.nextcloud.entrypoints: websecure | ||||
|       traefik.http.routers.nextcloud.tls: true | ||||
|       traefik.http.routers.nextcloud.tls.certresolver: letsencrypt | ||||
|       traefik.http.routers.nextcloud.tls.domains[0].main: ${TRAEFIK_ACME_DOMAIN_MAIN:-local.freeitathens.org} | ||||
|       traefik.http.routers.nextcloud.tls.domains[0].sans: "${TRAEFIK_ACME_DOMAIN_SANS:-*.local.freeitathens.org}" | ||||
|       traefik.http.services.nextcloud.loadbalancer.server.port: 80 | ||||
|       traefik.http.middlewares.nextcloud-webdav.redirectregex.regex: "https://(.*)/.well-known/(card|cal)dav" | ||||
|       traefik.http.middlewares.nextcloud-webdav.redirectregex.replacement: "https://$${1}/remote.php/dav/" | ||||
|       traefik.http.middlewares.nextcloud-webdav.redirectregex.permanent: true | ||||
|       traefik.http.routers.nextcloud.middlewares: nextcloud-webdav | ||||
|       traefik.docker.network: traefik | ||||
|       traefik.enable: ${NEXTCLOUD_WEB_ENABLED:-true} | ||||
|     volumes: | ||||
|       - nextcloud:/var/www/html | ||||
|     networks: | ||||
|       - traefik | ||||
|     extra_hosts: | ||||
|       - host.docker.internal:host-gateway | ||||
|  | ||||
|   timetrex: | ||||
|     image: freeitathens/timetrex:${TIMETREX_VERSION:-latest} | ||||
|     restart: always | ||||
|     environment: | ||||
|       POSTGRES_PASSWORD: password | ||||
|       POSTGRES_HOST: postgres | ||||
|     links: | ||||
|       - postgres | ||||
|     labels: | ||||
|       traefik.http.routers.timetrex.rule: "Host(`${TIMETREX_DOMAIN:-time.local.freeitathens.org}`)" | ||||
|       traefik.http.routers.timetrex.entrypoints: websecure | ||||
|       traefik.http.routers.timetrex.tls: true | ||||
|       traefik.http.routers.timetrex.tls.certresolver: letsencrypt | ||||
|       traefik.http.routers.timetrex.tls.domains[0].main: ${TRAEFIK_ACME_DOMAIN_MAIN:-local.freeitathens.org} | ||||
|       traefik.http.routers.timetrex.tls.domains[0].sans: "${TRAEFIK_ACME_DOMAIN_SANS:-*.local.freeitathens.org}" | ||||
|       traefik.http.services.timetrex.loadbalancer.server.port: 80 | ||||
|       traefik.docker.network: traefik | ||||
|       traefik.enable: ${NEXTCLOUD_WEB_ENABLED:-true} | ||||
|     networks: | ||||
|       - postgres | ||||
|       - traefik | ||||
|  | ||||
|   postgres: | ||||
|     image: postgres:13-bullseye | ||||
|     volumes: | ||||
|       - postgres:/var/lib/postgresql/data | ||||
|     environment: | ||||
|       POSTGRES_DB: timetrex | ||||
|       POSTGRES_USER: timetrex | ||||
|       POSTGRES_PASSWORD: password | ||||
|     networks: | ||||
|       - postgres | ||||
| @@ -1,18 +1,36 @@ | ||||
| # Copyright (C) 2019  Free I.T. Athens | ||||
| # | ||||
| # This program is free software: you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation, version 3 of the License. | ||||
| # | ||||
| # This program is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| # | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| - name: Restart MariaDB | ||||
|   ansible.builtin.service: | ||||
|     name: mariadb | ||||
|     state: restarted | ||||
|   listen: restart_mariadb | ||||
|  | ||||
| - name: Compose up on webserver stack | ||||
|   ansible.builtin.command: "docker-compose up -d" | ||||
|   args: | ||||
|     chdir: "{{ webserver_root }}" | ||||
|   listen: composeup_webserver | ||||
|  | ||||
| - name: Reload Apache2 | ||||
|   service: name=apache2 state=reloaded | ||||
| - name: Grab Nextcloud container information | ||||
|   community.docker.docker_container_info: | ||||
|     name: "{{ webserver_root | basename }}_nextcloud_1" | ||||
|   listen: composeup_webserver | ||||
|   register: nextcloud_info | ||||
|  | ||||
| - name: Wait for Nextcloud to become available | ||||
|   ansible.builtin.wait_for: | ||||
|     host: "{{ nextcloud_info.container.NetworkSettings.Networks.traefik.IPAddress }}" | ||||
|     port: 80 | ||||
|   listen: composeup_webserver | ||||
|  | ||||
| - name: Check Nextcloud status | ||||
|   ansible.builtin.command: "docker exec --user www-data {{ webserver_root | basename }}_nextcloud_1 | ||||
|             php occ status" | ||||
|   listen: composeup_webserver | ||||
|   register: nextcloud_status | ||||
|  | ||||
| - name: Import Nextcloud installation handlers | ||||
|   ansible.builtin.import_tasks: nextcloud.yml | ||||
|   listen: composeup_webserver | ||||
|   when: | ||||
|     - nextcloud_status.stderr[:26] == "Nextcloud is not installed" | ||||
|     - nextcloud_autoinstall | ||||
|   | ||||
							
								
								
									
										35
									
								
								roles/webserver/handlers/nextcloud.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								roles/webserver/handlers/nextcloud.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| - name: Install Nextcloud | ||||
|   ansible.builtin.command: 'docker exec --user www-data {{ webserver_root | basename }}_nextcloud_1 | ||||
|             php occ maintenance:install | ||||
|               --database "mysql" | ||||
|               --database-host "{{ webserver.NEXTCLOUD_MYSQL_HOST | default("host.docker.internal") }}" | ||||
|               --database-name "{{ webserver.NEXTCLOUD_MYSQL_DATABASE | default("nextcloud") }}" | ||||
|               --database-user "{{ webserver.NEXTCLOUD_MYSQL_USER | default("nextcloud") }}" | ||||
|               --database-pass "{{ webserver.NEXTCLOUD_MYSQL_PASSWORD }}" | ||||
|               --admin-user "{{ webserver.NEXTCLOUD_ADMIN | default("admin") }}" | ||||
|               --admin-pass "{{ webserver.NEXTCLOUD_ADMIN_PASSWORD }}"' | ||||
|   register: nextcloud_install | ||||
|   listen: composeup_webserver | ||||
|  | ||||
| - name: Set Nextcloud's Trusted Domain | ||||
|   ansible.builtin.command: 'docker exec --user www-data {{ webserver_root | basename }}_nextcloud_1 | ||||
|             php occ config:system:set trusted_domains 0 | ||||
|               --value="{{ webserver.NEXTCLOUD_DOMAIN | default("cloud.local.freeitathens.org") }}"' | ||||
|   listen: composeup_webserver | ||||
|   when: nextcloud_install.changed | ||||
|  | ||||
| - name: Set Nextcloud's Trusted Proxy | ||||
|   ansible.builtin.command: 'docker exec --user www-data {{ webserver_root | basename }}_nextcloud_1 | ||||
|             php occ config:system:set trusted_proxies 0 --value="traefik"' | ||||
|   listen: composeup_webserver | ||||
|   when: nextcloud_install.changed | ||||
|  | ||||
| - name: Preform Nextcloud database maintenance | ||||
|   ansible.builtin.command: "docker exec --user www-data {{ webserver_root | basename }}_nextcloud_1 {{ item }}" | ||||
|   loop: | ||||
|     - "php occ maintenance:mode --on" | ||||
|     - "php occ db:add-missing-indices" | ||||
|     - "php occ db:convert-filecache-bigint" | ||||
|     - "php occ maintenance:mode --off" | ||||
|   listen: composeup_webserver | ||||
|   when: "'  - needsDbUpgrade: true' in nextcloud_status.stdout_lines" | ||||
| @@ -1,40 +1,72 @@ | ||||
| # Copyright (C) 2019  Free I.T. Athens | ||||
| # | ||||
| # This program is free software: you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation, version 3 of the License. | ||||
| # | ||||
| # This program is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| # | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  | ||||
|  | ||||
| - name: Install Apache2 Web Server | ||||
|   apt: | ||||
|     name: apache2 | ||||
|     state: present | ||||
|  | ||||
| - name: Start Apache2 Web Server | ||||
|   service: | ||||
|     name: apache2 | ||||
|     state: started | ||||
|  | ||||
| - name: Install PHP | ||||
|   apt: | ||||
|     name: php | ||||
|     state: present | ||||
|  | ||||
| - name: Install PHP MySQL Extension | ||||
|   apt: | ||||
|     name: php-mysql | ||||
|     state: present | ||||
|   notify: Reload Apache2 | ||||
|  | ||||
| - name: Install MariaDB Server | ||||
|   apt: | ||||
|   ansible.builtin.apt: | ||||
|     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 }}" | ||||
|     state: directory | ||||
|     mode: 0600 | ||||
|  | ||||
| - name: Install webserver docker-compose.yml | ||||
|   ansible.builtin.copy: | ||||
|     src: docker-compose.yml | ||||
|     dest: "{{ webserver_root }}/docker-compose.yml" | ||||
|     mode: 0600 | ||||
|   notify: composeup_webserver | ||||
|  | ||||
| - name: Install docker-compose .env | ||||
|   ansible.builtin.template: | ||||
|     src: compose-env.j2 | ||||
|     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" | ||||
|   | ||||
							
								
								
									
										4
									
								
								roles/webserver/templates/compose-env.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								roles/webserver/templates/compose-env.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| # {{ ansible_managed }} | ||||
| {% for key, value in webserver.items() %} | ||||
| {{ key }}={{ value }} | ||||
| {% endfor %} | ||||
| @@ -1,100 +0,0 @@ | ||||
| # Copyright (C) 2019  Free I.T. Athens | ||||
| # | ||||
| # This program is free software: you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation, version 3 of the License. | ||||
| # | ||||
| # This program is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| # | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  | ||||
|  | ||||
| # PyMySQL or MySQL-python is required for database tasks | ||||
| - name: Install MySQL Support for Python | ||||
|   apt: | ||||
|     name: python-pymysql | ||||
|     state: present | ||||
|  | ||||
| - name: Create Database | ||||
|   mysql_db: | ||||
|     name: "{{ wp_db_name }}" | ||||
|     state: present | ||||
|     login_unix_socket: /var/run/mysqld/mysqld.sock | ||||
|  | ||||
| - name: Create Database User | ||||
|   mysql_user: | ||||
|     name: "{{ wp_db_user }}" | ||||
|     password: "{{ wp_db_pass }}" | ||||
|     priv: "{{ wp_db_name }}.*:ALL,GRANT" | ||||
|     state: present | ||||
|     login_unix_socket: /var/run/mysqld/mysqld.sock | ||||
|  | ||||
| - name: Create Public HTML Directory | ||||
|   file: | ||||
|     path: "{{ wp_dir }}/public_html" | ||||
|     state: directory | ||||
|  | ||||
| - name: Create Logs Directory | ||||
|   file: | ||||
|     path: "{{ wp_dir }}/logs" | ||||
|     state: directory | ||||
|  | ||||
| - name: Download WordPress | ||||
|   get_url: | ||||
|     url: https://wordpress.org/wordpress-{{ wp_version }}.tar.gz | ||||
|     dest: /tmp/wordpress-{{ wp_version }}.tar.gz | ||||
|     checksum: sha1:{{ wp_sha1_hash }} | ||||
|  | ||||
| - name: Extract WordPress | ||||
|   unarchive: | ||||
|     src: /tmp/wordpress-{{ wp_version }}.tar.gz | ||||
|     dest: "{{ wp_dir }}/public_html" | ||||
|     extra_opts: [--strip-components=1] | ||||
|     owner: "www-data" | ||||
|     group: "www-data" | ||||
|     remote_src: yes | ||||
|  | ||||
| - name: Stat WordPress Salts | ||||
|   stat: | ||||
|     path: "{{ wp_dir }}/salts.txt" | ||||
|   register: salts | ||||
|  | ||||
| - name: Generate Keys and Salts | ||||
|   get_url: | ||||
|     url: https://api.wordpress.org/secret-key/1.1/salt/ | ||||
|     dest: "{{ wp_dir }}/salts.txt" | ||||
|   when: not salts.stat.exists | ||||
|  | ||||
| - name: Grab Keys and Salts | ||||
|   slurp: src="{{ wp_dir }}/salts.txt" | ||||
|   register: salts | ||||
|  | ||||
| - name: Apply WordPress Configuration | ||||
|   template: | ||||
|     src: wp-config.php.j2 | ||||
|     dest: "{{ wp_dir }}/public_html/wp-config.php" | ||||
|     owner: "www-data" | ||||
|     group: "www-data" | ||||
|  | ||||
| - name: Apply Apache Configuration | ||||
|   template: | ||||
|     src: wordpress.conf.j2 | ||||
|     dest: /etc/apache2/sites-available/{{ wp_domain }}.conf | ||||
|   notify: Reload Apache2 | ||||
|  | ||||
| - name: Enable Apache Module rewrite | ||||
|   apache2_module: | ||||
|     state: present | ||||
|     name: rewrite | ||||
|   notify: Reload Apache2 | ||||
|  | ||||
| - name: Enable Apache Website | ||||
|   shell: a2ensite {{ wp_domain }} | ||||
|   args: | ||||
|     creates: /etc/apache2/sites-enabled/{{ wp_domain }}.conf | ||||
|   notify: Reload Apache2 | ||||
|  | ||||
| @@ -1,17 +0,0 @@ | ||||
| <VirtualHost *:80> | ||||
| 	ServerName {{ wp_domain }} | ||||
|  | ||||
| 	ServerAdmin {{ wp_admin_email }} | ||||
| 	DocumentRoot {{ wp_dir }}/public_html | ||||
|      | ||||
| 	ErrorLog {{ wp_dir }}/logs/error.log | ||||
| 	CustomLog {{ wp_dir }}/logs/access.log combined | ||||
| </VirtualHost> | ||||
|  | ||||
| <Directory {{ wp_dir }}/public_html> | ||||
|     Options Indexes FollowSymLinks | ||||
|     AllowOverride All | ||||
|     Require all granted | ||||
| </Directory> | ||||
|  | ||||
| # vim: syntax=apache ts=4 sw=4 sts=4 sr noet | ||||
| @@ -1,64 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| define('DB_NAME', '{{ wp_db_name }}'); | ||||
|  | ||||
| /** The name of the database for WordPress */ | ||||
| /** MySQL database username */ | ||||
| define('DB_USER', '{{ wp_db_user }}'); | ||||
|  | ||||
| /** MySQL database password */ | ||||
| define('DB_PASSWORD', '{{ wp_db_pass }}'); | ||||
|  | ||||
| /** MySQL hostname */ | ||||
| define('DB_HOST', '{{ wp_db_host }}'); | ||||
|  | ||||
| /** Database Charset to use in creating database tables. */ | ||||
| define('DB_CHARSET', 'utf8mb4'); | ||||
|  | ||||
| /** The Database Collate type. Don't change this if in doubt. */ | ||||
| define('DB_COLLATE', ''); | ||||
|  | ||||
| /**#@+ | ||||
|  * Authentication Unique Keys and Salts. | ||||
|  * | ||||
|  * Change these to different unique phrases! | ||||
|  * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service} | ||||
|  * You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again. | ||||
|  * | ||||
|  * @since 2.6.0 | ||||
|  */ | ||||
| {{ salts.content | b64decode }} | ||||
|  | ||||
| /**#@-*/ | ||||
|  | ||||
| /** | ||||
|  * WordPress Database Table prefix. | ||||
|  * | ||||
|  * You can have multiple installations in one database if you give each | ||||
|  * a unique prefix. Only numbers, letters, and underscores please! | ||||
|  */ | ||||
| $table_prefix  = '{{ wp_db_table_prefix }}'; | ||||
|  | ||||
| /** | ||||
|  * For developers: WordPress debugging mode. | ||||
|  * | ||||
|  * Change this to true to enable the display of notices during development. | ||||
|  * It is strongly recommended that plugin and theme developers use WP_DEBUG | ||||
|  * in their development environments. | ||||
|  * | ||||
|  * For information on other constants that can be used for debugging, | ||||
|  * visit the Codex. | ||||
|  * | ||||
|  * @link https://codex.wordpress.org/Debugging_in_WordPress | ||||
|  */ | ||||
| define('WP_DEBUG', false); | ||||
|  | ||||
| /* That's all, stop editing! Happy blogging. */ | ||||
|  | ||||
| /** Absolute path to the WordPress directory. */ | ||||
| if ( !defined('ABSPATH') ) | ||||
| 	define('ABSPATH', dirname(__FILE__) . '/'); | ||||
|  | ||||
| /** Sets up WordPress vars and included files. */ | ||||
| require_once(ABSPATH . 'wp-settings.php'); | ||||
|  | ||||
							
								
								
									
										26
									
								
								scripts/forward-ssh.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										26
									
								
								scripts/forward-ssh.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -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 | ||||
							
								
								
									
										51
									
								
								scripts/vault-key.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										51
									
								
								scripts/vault-key.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| #!/bin/bash | ||||
| BW_USERNAME="contact@freeitathens.org" | ||||
| ANSIBLE_VAULT_ITEM="e16b2542-f6c1-4e9f-8e33-af5201574a15" | ||||
|  | ||||
| # Does the key already exist? | ||||
| if [ -f .ansible_vault ]; then | ||||
|   echo "Ansible Vault file already exists at ./.ansible_vault" | ||||
|   exit 1 | ||||
| fi | ||||
|  | ||||
| # Install Bitwarden CLI binary to ./.bitwarden/bw | ||||
| if [ ! -d .bitwarden ]; then | ||||
|   mkdir .bitwarden | ||||
|   cd .bitwarden || exit 1 | ||||
|   wget "https://vault.bitwarden.com/download/?app=cli&platform=linux" -O bw-linux.zip | ||||
|   unzip bw-linux.zip | ||||
|   rm bw-linux.zip | ||||
|   chmod u+x bw | ||||
| else | ||||
|   cd .bitwarden || exit 1 | ||||
| fi | ||||
|  | ||||
| # Get Master Password to unlock vault | ||||
| read -rsp "Master Password: " BW_PASSWORD | ||||
| export BW_PASSWORD | ||||
| echo | ||||
|  | ||||
| # Login | ||||
| LOGIN_RESPONSE=$(./bw login "$BW_USERNAME" "$BW_PASSWORD" --response --nointeraction) | ||||
| if [ ! "$(echo "$LOGIN_RESPONSE" | jq -r .success)" == "true" ]; then | ||||
|   echo "$LOGIN_RESPONSE" | jq -r .message | ||||
|   exit 1 | ||||
| fi | ||||
|  | ||||
| # Unlock | ||||
| UNLOCK_RESPONSE=$(./bw unlock --passwordenv BW_PASSWORD --response --nointeraction) | ||||
| if [ ! "$(echo "$UNLOCK_RESPONSE" | jq -r .success)" == "true" ]; then | ||||
|   echo "$UNLOCK_RESPONSE" | jq -r .message | ||||
|   exit 1 | ||||
| fi | ||||
|  | ||||
| # Trade password for session | ||||
| unset BW_PASSWORD | ||||
| BW_SESSION=$(echo "$UNLOCK_RESPONSE" | jq -r .data.raw) | ||||
| export BW_SESSION | ||||
|  | ||||
| # Place Ansible Vault secret and logout | ||||
| ./bw get password "$ANSIBLE_VAULT_ITEM" --response --nointeraction | jq -r .data.data > ../.ansible_vault | ||||
| truncate -s -1 ../.ansible_vault | ||||
| chmod 600 ../.ansible_vault | ||||
| ./bw logout --quiet | ||||
| @@ -1,25 +1,7 @@ | ||||
| # Copyright (C) 2019  Free I.T. Athens | ||||
| # | ||||
| # This program is free software: you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation, version 3 of the License. | ||||
| # | ||||
| # This program is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| # | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  | ||||
|  | ||||
| - name: Install FRITA Web Server | ||||
|   hosts: all | ||||
|   become: yes | ||||
|   become: true | ||||
|   roles: | ||||
|     - ansible | ||||
|     - common | ||||
|     - docker | ||||
|     - webserver | ||||
|     #- wordpress | ||||
|     #- nextcloud | ||||
|     #- timetrex | ||||
|     - mediawiki | ||||
|   | ||||
		Reference in New Issue
	
	Block a user