Compare commits
	
		
			10 Commits
		
	
	
		
			62665a67b7
			...
			nextcloud
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						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,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"
 | 
			
		||||
							
								
								
									
										110
									
								
								roles/webserver/files/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								roles/webserver/files/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
version: '3.5'
 | 
			
		||||
 | 
			
		||||
volumes:
 | 
			
		||||
  wordpress:
 | 
			
		||||
  nextcloud:
 | 
			
		||||
 | 
			
		||||
networks:
 | 
			
		||||
  traefik:
 | 
			
		||||
    name: traefik
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
@@ -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,24 +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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user