Compare commits
	
		
			1 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f42cb94872 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| .ansible* | ||||
| .ansible_vault | ||||
| .bitwarden | ||||
| environments | ||||
| *.log | ||||
|   | ||||
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,9 +1,7 @@ | ||||
| SHELL := /bin/bash | ||||
|  | ||||
| all: vagrant | ||||
|  | ||||
| vagrant: | ||||
| 	set -o pipefail; vagrant up --no-destroy-on-error --no-color | tee ./vagrantup.log | ||||
| 	vagrant up --no-destroy-on-error --no-color | tee ./vagrantup.log | ||||
| 	./scripts/forward-ssh.sh | ||||
|  | ||||
| clean: | ||||
|   | ||||
							
								
								
									
										65
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,78 +1,49 @@ | ||||
| # 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). | ||||
|  | ||||
| - Requires GNU Make, Ansible, and Vagrant on the host | ||||
|  | ||||
| ## Quick Start | ||||
|  | ||||
| 1. Clone this project | ||||
| 2. Run `make` to provision a Rocky 9 base box | ||||
| 2. Run `make` to provision a Debian 11 base box | ||||
| 3. Go to | ||||
|    - [Traefik Dashboard](https://traefik.local.freeitathens.org:9443/dashboard/#/) | ||||
|    - [WordPress](https://www.local.freeitathens.org) | ||||
|    - [Nextcloud](https://cloud.local.freeitathens.org) | ||||
|    - [Mediawiki](https://wiki.local.freeitathens.org) | ||||
|     - [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 | ||||
|  | ||||
| ## Production | ||||
| 1. Clone [production-env](https://github.com/freeitathens/production-env/) to `./environments` | ||||
|  | ||||
| 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 | ||||
|     ``` | ||||
|  | ||||
|    ``` | ||||
|    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 | ||||
| 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 --diff --check | ||||
|    ``` | ||||
|     ``` | ||||
|     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 | ||||
|  | ||||
| ### Using Ansible Vault to add or rotate values | ||||
|  | ||||
| Do not submit ciphertext into Ansible Vault with the indention formatting.<br /> | ||||
| To submit, press `CTRL+d` twice. | ||||
|  | ||||
| - Decrypt Ansible Vault values | ||||
|  | ||||
|   ``` | ||||
|   ansible-vault decrypt --vault-pass-file .ansible_vault | ||||
|   ``` | ||||
|  | ||||
| - Encrypt new Ansible Vault values | ||||
|  | ||||
|   ``` | ||||
|   ansible-vault encrypt --vault-pass-file .ansible_vault | ||||
|   ``` | ||||
|  | ||||
|   - e.g., | ||||
|     `pwgen -s 100 1 | ansible-vault encrypt --vault-pass-file .ansible_vault` | ||||
|  | ||||
| ## Authors | ||||
|  | ||||
| - **Kris Lamoureux** - _Project Founder_ - | ||||
|   [@krislamo](https://github.com/krislamo) | ||||
| * **Kris Lamoureux** - *Project Founder* - [@krislamo](https://github.com/krislamo) | ||||
|  | ||||
| ## Copyrights and Licenses | ||||
|  | ||||
| Copyright (C) 2019, 2020, 2022, 2023, 2025 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 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/>. | ||||
|   | ||||
							
								
								
									
										24
									
								
								Vagrantfile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								Vagrantfile
									
									
									
									
										vendored
									
									
								
							| @@ -14,13 +14,9 @@ else | ||||
|   File.write(".playbook", PLAYBOOK) | ||||
| end | ||||
|  | ||||
| # Optionally allow more verbosity in Ansible | ||||
| VAGRANT_ANSIBLE_VERBOSE=ENV["VAGRANT_ANSIBLE_VERBOSE"] || false | ||||
|  | ||||
| # Debian 11 | ||||
| Vagrant.configure("2") do |config| | ||||
|   config.vm.box = "rockylinux/9" | ||||
|   config.vm.hostname = "fritadev" | ||||
|   config.vm.disk :disk, size: "100GB", primary: true | ||||
|   config.vm.box = "debian/bullseye64" | ||||
|   config.vm.synced_folder ".", "/vagrant", disabled: true | ||||
|   config.vm.network "private_network", type: "dhcp" | ||||
|  | ||||
| @@ -33,7 +29,6 @@ Vagrant.configure("2") do |config| | ||||
|     libvirt.cpus = 2 | ||||
|     libvirt.memory = 4096 | ||||
|     libvirt.default_prefix = "" | ||||
|     libvirt.machine_virtual_size = 100 | ||||
|   end | ||||
|  | ||||
|   # Set VirtualBox settings | ||||
| @@ -42,24 +37,11 @@ Vagrant.configure("2") do |config| | ||||
|     vbox.memory = 4096 | ||||
|   end | ||||
|  | ||||
|   # Expand XFS rootfs | ||||
|   config.vm.provision "shell", inline: <<-SHELL | ||||
|     set -xe | ||||
|     df -h / | ||||
|     dnf install -y cloud-utils-growpart | ||||
|     PART="$(findmnt -n -o SOURCE /)" | ||||
|     DISK="$(lsblk -n -o PKNAME "$PART")" | ||||
|     NUM="$(lsblk -n -o KNAME "$PART" | sed 's/.*[^0-9]//')" | ||||
|     growpart "/dev/$DISK" "$NUM" && \ | ||||
|     xfs_growfs / | ||||
|     df -h / | ||||
|   SHELL | ||||
|  | ||||
|   # Provision with Ansible | ||||
|   config.vm.provision "ansible" do |ansible| | ||||
|     ENV['ANSIBLE_ROLES_PATH'] = File.dirname(__FILE__) + "/roles" | ||||
|     ansible.compatibility_mode = "2.0" | ||||
|     ansible.playbook = "dev/" + PLAYBOOK + ".yml" | ||||
|     ansible.verbose = VAGRANT_ANSIBLE_VERBOSE | ||||
|   end | ||||
|  | ||||
| end | ||||
|   | ||||
| @@ -3,4 +3,4 @@ inventory = ./environments/development | ||||
| interpreter_python = /usr/bin/python3 | ||||
|  | ||||
| [ssh_connection] | ||||
| pipelining = True | ||||
| pipelining=True | ||||
|   | ||||
| @@ -7,17 +7,12 @@ secret: | ||||
|   WORDPRESS_DB_PASSWORD: WPpa55w0rd! | ||||
|   NEXTCLOUD_MYSQL_PASSWORD: NCdbpa55w0rd! | ||||
|   NEXTCLOUD_ADMIN_PASSWORD: NCadm1npa55w0rd! | ||||
|   MEDIAWIKI_MYSQL_PASSWORD: MWdbpa55w0rd! | ||||
|  | ||||
| ############## | ||||
| ### Common ### | ||||
| ### Docker ### | ||||
| ############## | ||||
| users: | ||||
|   oci: | ||||
|     uid: 2000 | ||||
|     gid: 2000 | ||||
|     home: true | ||||
|     ansible_temp: true | ||||
| docker_users: | ||||
|   - vagrant | ||||
|  | ||||
| ################ | ||||
| #### MariaDB ### | ||||
| @@ -27,8 +22,6 @@ databases: | ||||
|     pass: "{{ secret.WORDPRESS_DB_PASSWORD }}" | ||||
|   - name: nextcloud | ||||
|     pass: "{{ secret.NEXTCLOUD_MYSQL_PASSWORD }}" | ||||
|   - name: mediawiki | ||||
|     pass: "{{ secret.MEDIAWIKI_MYSQL_PASSWORD }}" | ||||
|  | ||||
| ####################### | ||||
| ### Webserver Stack ### | ||||
| @@ -37,12 +30,12 @@ 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_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 | ||||
| @@ -52,29 +45,23 @@ webserver: | ||||
|   ################# | ||||
|   ### 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_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_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 }}" | ||||
|  | ||||
|   ################# | ||||
|   ### MediaWiki ### | ||||
|   ################# | ||||
|   # MEDIAWIKI_VERSION: stable | ||||
|   # MEDIAWIKI_DOMAIN: wiki.local.freeitathens.org | ||||
|   | ||||
| @@ -5,5 +5,5 @@ | ||||
|     - vars/webserver.yml | ||||
|   roles: | ||||
|     - common | ||||
|     - podman | ||||
|     - docker | ||||
|     - webserver | ||||
|   | ||||
| @@ -1,5 +1,2 @@ | ||||
| common_packages: | ||||
| packages: | ||||
|   - dnsutils | ||||
|   - ncdu | ||||
|   - tree | ||||
|   - vim | ||||
|   | ||||
| @@ -2,87 +2,35 @@ | ||||
|   ansible.builtin.file: | ||||
|     path: "~/.ansible/tmp" | ||||
|     state: directory | ||||
|     mode: "755" | ||||
|  | ||||
| - name: Create system user groups | ||||
|   ansible.builtin.group: | ||||
|     name: "{{ item.key }}" | ||||
|     gid: "{{ item.value.gid }}" | ||||
|     state: present | ||||
|   loop: "{{ users | dict2items }}" | ||||
|   loop_control: | ||||
|     label: "{{ item.key }}" | ||||
|   when: users is defined | ||||
|  | ||||
| - name: Create system users | ||||
|   ansible.builtin.user: | ||||
|     name: "{{ item.key }}" | ||||
|     state: present | ||||
|     uid: "{{ item.value.uid }}" | ||||
|     group: "{{ item.value.gid }}" | ||||
|     groups: "{{ item.value.groups | default([]) }}" | ||||
|     shell: "{{ item.value.shell | default('/bin/bash') }}" | ||||
|     create_home: "{{ item.value.home | default(false) }}" | ||||
|     home: "{{ item.value.homedir | default('/home/' + item.key) }}" | ||||
|     system: "{{ item.value.system | default(false) }}" | ||||
|   loop: "{{ users | dict2items }}" | ||||
|   loop_control: | ||||
|     label: "{{ item.key }}" | ||||
|   when: users is defined | ||||
|  | ||||
| - name: Create Ansible's temporary remote directory for users | ||||
|   ansible.builtin.file: | ||||
|     path: "{{ item.value.homedir | default('/home/' + item.key) }}/.ansible/tmp" | ||||
|     state: directory | ||||
|     mode: "755" | ||||
|     owner: "{{ item.key }}" | ||||
|     group: "{{ item.value.gid }}" | ||||
|   loop: "{{ users | dict2items }}" | ||||
|   loop_control: | ||||
|     label: "{{ item.key }}" | ||||
|   when: | ||||
|     - users is defined | ||||
|     - item.value.ansible_temp | default(false) | ||||
|  | ||||
| - name: Install EPEL repository | ||||
|   ansible.builtin.dnf: | ||||
|     name: epel-release | ||||
|     state: present | ||||
|     update_cache: true | ||||
|     mode: 0700 | ||||
|  | ||||
| - name: Install useful software | ||||
|   ansible.builtin.dnf: | ||||
|     name: "{{ common_packages }}" | ||||
|   ansible.builtin.apt: | ||||
|     name: "{{ packages }}" | ||||
|     state: present | ||||
|     update_cache: true | ||||
|  | ||||
| - name: Install firewalld | ||||
|   ansible.builtin.dnf: | ||||
|     name: firewalld | ||||
| - name: Install the Uncomplicated Firewall | ||||
|   ansible.builtin.apt: | ||||
|     name: ufw | ||||
|     state: present | ||||
|     update_cache: true | ||||
|  | ||||
| - name: Start and enable firewalld service | ||||
|   ansible.builtin.systemd: | ||||
|     name: firewalld | ||||
|     state: started | ||||
|     enabled: true | ||||
| - name: Deny incoming traffic by default | ||||
|   community.general.ufw: | ||||
|     default: deny | ||||
|     direction: incoming | ||||
|  | ||||
| - name: Set default zone to drop (deny incoming by default) | ||||
|   ansible.posix.firewalld: | ||||
|     zone: drop | ||||
| - 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 | ||||
|     permanent: true | ||||
|     immediate: true | ||||
|  | ||||
| - name: Allow SSH in drop zone with rate limiting via rich rule | ||||
|   ansible.posix.firewalld: | ||||
|     zone: drop | ||||
|     rich_rule: 'rule service name="ssh" accept limit value="10/m"' | ||||
|     permanent: true | ||||
|     immediate: true | ||||
|     state: enabled | ||||
|  | ||||
| - name: Set drop as the default zone | ||||
|   ansible.builtin.command: | ||||
|     cmd: firewall-cmd --set-default-zone=drop | ||||
|   changed_when: false | ||||
|   | ||||
| @@ -1,4 +0,0 @@ | ||||
| - name: Restart systemd-logind | ||||
|   ansible.builtin.systemd: | ||||
|     name: systemd-logind | ||||
|     state: restarted | ||||
| @@ -1,49 +0,0 @@ | ||||
| - name: Install Podman | ||||
|   ansible.builtin.dnf: | ||||
|     name: ["podman", "podman-docker", "podman-compose"] | ||||
|     state: present | ||||
|  | ||||
| - name: Create /etc/containers/nodocker to quiet CLI emulation notice | ||||
|   ansible.builtin.file: | ||||
|     path: /etc/containers/nodocker | ||||
|     state: touch | ||||
|     mode: "644" | ||||
|  | ||||
| - name: Create logind.conf.d directory | ||||
|   ansible.builtin.file: | ||||
|     path: /etc/systemd/logind.conf.d | ||||
|     state: directory | ||||
|     mode: "755" | ||||
|  | ||||
| - name: Create linger directory | ||||
|   ansible.builtin.file: | ||||
|     path: /var/lib/systemd/linger | ||||
|     state: directory | ||||
|     mode: "755" | ||||
|  | ||||
| - name: Enable lingering for oci user | ||||
|   ansible.builtin.file: | ||||
|     path: /var/lib/systemd/linger/oci | ||||
|     state: touch | ||||
|     mode: "644" | ||||
|   notify: Restart systemd-logind | ||||
|  | ||||
| - name: Force handler execution for user lingering | ||||
|   ansible.builtin.meta: flush_handlers | ||||
|  | ||||
| - name: Create user systemd directory | ||||
|   ansible.builtin.file: | ||||
|     path: "/home/oci/.config/systemd/user" | ||||
|     state: directory | ||||
|     mode: "755" | ||||
|     owner: oci | ||||
|     group: oci | ||||
|  | ||||
| - name: Enable oci's podman socket | ||||
|   ansible.builtin.systemd: | ||||
|     name: podman.socket | ||||
|     enabled: true | ||||
|     state: started | ||||
|     scope: user | ||||
|   become_user: oci | ||||
|   become: true | ||||
| @@ -1,18 +1,20 @@ | ||||
| version: '3.5' | ||||
|  | ||||
| volumes: | ||||
|   wordpress: | ||||
|   nextcloud: | ||||
|   mediawiki: | ||||
|   postgres: | ||||
|  | ||||
| networks: | ||||
|   traefik: | ||||
|     name: traefik | ||||
|   postgres: | ||||
|     name: postgres | ||||
|  | ||||
| services: | ||||
|   traefik: | ||||
|     image: ${TRAEFIK_IMAGE:-docker.io/library/traefik}:${TRAEFIK_VERSION:-latest} | ||||
|     image: traefik:${TRAEFIK_VERSION:-latest} | ||||
|     restart: always | ||||
|     security_opt: | ||||
|       - label=type:container_runtime_t | ||||
|     command: | ||||
|       - --api.dashboard=${TRAEFIK_DASHBOARD:-true} | ||||
|       - --api.debug=${TRAEFIK_DEBUG:-false} | ||||
| @@ -21,7 +23,7 @@ services: | ||||
|       - --providers.docker.exposedbydefault=${TRAEFIK_EXPOSED_DEFAULT:-false} | ||||
|       - --entrypoints.web.address=:80 | ||||
|       - --entrypoints.websecure.address=:443 | ||||
|       - --entrypoints.local.address=:9443 | ||||
|       - --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 | ||||
| @@ -34,11 +36,11 @@ services: | ||||
|     environment: | ||||
|       DREAMHOST_API_KEY: ${TRAEFIK_DREAMHOST_APIKEY} | ||||
|     ports: | ||||
|       - "${ENTRYWEB:-127.0.0.1:8080}:80" | ||||
|       - "${ENTRYSECURE:-127.0.0.1:8443}:443" | ||||
|       - "${ENTRYLOCAL:-127.0.0.1:9443}:9443" | ||||
|       - 80:80 | ||||
|       - 443:443 | ||||
|       - "127.0.0.1:8443:8443" | ||||
|     volumes: | ||||
|       - ${OCI_SOCK:-/run/user/2000/podman/podman.sock}:/var/run/docker.sock:ro,Z | ||||
|       - /var/run/docker.sock:/var/run/docker.sock | ||||
|       - ./.acme:/etc/letsencrypt | ||||
|     labels: | ||||
|       traefik.http.routers.api.rule: Host(`${TRAEFIK_DOMAIN:-traefik.local.freeitathens.org}`) | ||||
| @@ -53,7 +55,7 @@ services: | ||||
|       - traefik | ||||
|  | ||||
|   wordpress: | ||||
|     image: ${WORDPRESS_IMAGE:-docker.io/library/wordpress}:${WORDPRESS_VERSION:-latest} | ||||
|     image: wordpress:${WORDPRESS_VERSION:-latest} | ||||
|     restart: always | ||||
|     environment: | ||||
|       WORDPRESS_DB_HOST: ${WORDPRESS_DB_HOST:-host.docker.internal} | ||||
| @@ -61,9 +63,7 @@ services: | ||||
|       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}`) || | ||||
|         Host(`${TRAEFIK_ACME_DOMAIN_MAIN:-local.freeitathens.org}`) | ||||
|       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 | ||||
| @@ -84,7 +84,7 @@ services: | ||||
|       - host.docker.internal:host-gateway | ||||
|  | ||||
|   nextcloud: | ||||
|     image: ${NEXTCLOUD_IMAGE:-docker.io/library/nextcloud}:${NEXTCLOUD_VERSION:-stable} | ||||
|     image: nextcloud:${NEXTCLOUD_VERSION:-stable} | ||||
|     restart: always | ||||
|     environment: | ||||
|       MYSQL_HOST: ${NEXTCLOUD_MYSQL_HOST:-host.docker.internal:3306} | ||||
| @@ -112,23 +112,35 @@ services: | ||||
|     extra_hosts: | ||||
|       - host.docker.internal:host-gateway | ||||
|  | ||||
|   mediawiki: | ||||
|     image: ${MEDIAWIKI_IMAGE:-docker.io/library/mediawiki}:${MEDIAWIKI_VERSION:-stable} | ||||
|   timetrex: | ||||
|     image: freeitathens/timetrex:${TIMETREX_VERSION:-latest} | ||||
|     restart: always | ||||
|     environment: | ||||
|       POSTGRES_PASSWORD: password | ||||
|       POSTGRES_HOST: postgres | ||||
|     links: | ||||
|       - postgres | ||||
|     labels: | ||||
|       traefik.http.routers.mediawiki.rule: "Host(`${MEDIAWIKI_DOMAIN:-wiki.local.freeitathens.org}`)" | ||||
|       traefik.http.routers.mediawiki.entrypoints: websecure | ||||
|       traefik.http.routers.mediawiki.tls: true | ||||
|       traefik.http.routers.mediawiki.tls.certresolver: letsencrypt | ||||
|       traefik.http.routers.mediawiki.tls.domains[0].main: ${TRAEFIK_ACME_DOMAIN_MAIN:-local.freeitathens.org} | ||||
|       traefik.http.routers.mediawiki.tls.domains[0].sans: "${TRAEFIK_ACME_DOMAIN_SANS:-*.local.freeitathens.org}" | ||||
|       traefik.http.services.mediawiki.loadbalancer.server.port: 80 | ||||
|       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: ${MEDIAWIKI_WEB_ENABLED:-true} | ||||
|     volumes: | ||||
|       - ./LocalSettings.php:/var/www/html/LocalSettings.php:ro,Z | ||||
|       - mediawiki:/var/www/html/images | ||||
|       traefik.enable: ${NEXTCLOUD_WEB_ENABLED:-true} | ||||
|     networks: | ||||
|       - postgres | ||||
|       - traefik | ||||
|     extra_hosts: | ||||
|       - host.docker.internal:host-gateway | ||||
|  | ||||
|   postgres: | ||||
|     image: postgres:13-bullseye | ||||
|     volumes: | ||||
|       - postgres:/var/lib/postgresql/data | ||||
|     environment: | ||||
|       POSTGRES_DB: timetrex | ||||
|       POSTGRES_USER: timetrex | ||||
|       POSTGRES_PASSWORD: password | ||||
|     networks: | ||||
|       - postgres | ||||
|   | ||||
| @@ -1,22 +0,0 @@ | ||||
| user nginx; | ||||
| worker_processes auto; | ||||
| error_log /var/log/nginx/error.log; | ||||
| pid /run/nginx.pid; | ||||
|  | ||||
| include /usr/share/nginx/modules/*.conf; | ||||
|  | ||||
| events { | ||||
|     worker_connections 1024; | ||||
| } | ||||
|  | ||||
| stream { | ||||
|     server { | ||||
|         listen 80; | ||||
|         proxy_pass 127.0.0.1:8080; | ||||
|     } | ||||
|  | ||||
|     server { | ||||
|         listen 443; | ||||
|         proxy_pass 127.0.0.1:8443; | ||||
|     } | ||||
| } | ||||
| @@ -1,38 +1,14 @@ | ||||
| - name: Restart nginx | ||||
|   ansible.builtin.systemd: | ||||
|     name: nginx | ||||
|     state: restarted | ||||
|  | ||||
| - name: Restart MariaDB | ||||
|   ansible.builtin.service: | ||||
|     name: mariadb | ||||
|     state: restarted | ||||
|   listen: restart_mariadb | ||||
|  | ||||
| - name: Start podman compose project | ||||
|   ansible.builtin.command: | ||||
|     cmd: podman compose up -d | ||||
|     chdir: "/home/oci/webserver" | ||||
|   notify: Generate systemd service files | ||||
|   changed_when: false | ||||
|   become_user: oci | ||||
|   become: true | ||||
|  | ||||
| - name: Reload systemd user daemon | ||||
|   ansible.builtin.systemd: | ||||
|     daemon_reload: true | ||||
|     scope: user | ||||
|   notify: Enable systemd user service | ||||
|   become_user: oci | ||||
|   become: true | ||||
|  | ||||
| - name: Enable systemd user service | ||||
|   ansible.builtin.systemd: | ||||
|     name: webserver | ||||
|     enabled: true | ||||
|     scope: user | ||||
|   become_user: oci | ||||
|   become: true | ||||
| - name: Compose up on webserver stack | ||||
|   ansible.builtin.command: "docker-compose up -d" | ||||
|   args: | ||||
|     chdir: "{{ webserver_root }}" | ||||
|   listen: composeup_webserver | ||||
|  | ||||
| - name: Grab Nextcloud container information | ||||
|   community.docker.docker_container_info: | ||||
| @@ -47,9 +23,8 @@ | ||||
|   listen: composeup_webserver | ||||
|  | ||||
| - name: Check Nextcloud status | ||||
|   ansible.builtin.command: | ||||
|     "docker exec --user www-data {{ webserver_root | basename }}_nextcloud_1 | ||||
|     php occ status" | ||||
|   ansible.builtin.command: "docker exec --user www-data {{ webserver_root | basename }}_nextcloud_1 | ||||
|             php occ status" | ||||
|   listen: composeup_webserver | ||||
|   register: nextcloud_status | ||||
|  | ||||
| @@ -59,12 +34,3 @@ | ||||
|   when: | ||||
|     - nextcloud_status.stderr[:26] == "Nextcloud is not installed" | ||||
|     - nextcloud_autoinstall | ||||
|  | ||||
| - name: Install webserver docker-compose.yml | ||||
|   ansible.builtin.copy: | ||||
|     src: docker-compose.yml | ||||
|     dest: /home/oci/webserver/compose.yml | ||||
|     mode: "600" | ||||
|     owner: oci | ||||
|     group: oci | ||||
|   notify: Generate systemd service files | ||||
|   | ||||
| @@ -24,15 +24,6 @@ | ||||
|   listen: composeup_webserver | ||||
|   when: nextcloud_install.changed | ||||
|  | ||||
| - name: Install Nextcloud background jobs cron | ||||
|   ansible.builtin.cron: | ||||
|     name: Nextcloud background job | ||||
|     minute: "*/5" | ||||
|     job: "/usr/bin/docker exec -u www-data webserver_nextcloud_1 /usr/local/bin/php -f /var/www/html/cron.php" | ||||
|     user: root | ||||
|   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: | ||||
| @@ -41,4 +32,4 @@ | ||||
|     - "php occ db:convert-filecache-bigint" | ||||
|     - "php occ maintenance:mode --off" | ||||
|   listen: composeup_webserver | ||||
|   when: "'  - needsDbUpgrade: true' in nextcloud_status.stdout_lines or nextcloud_install.changed" | ||||
|   when: "'  - needsDbUpgrade: true' in nextcloud_status.stdout_lines" | ||||
|   | ||||
| @@ -1,102 +1,72 @@ | ||||
| - name: Install MariaDB Server | ||||
|   ansible.builtin.dnf: | ||||
|   ansible.builtin.apt: | ||||
|     name: mariadb-server | ||||
|     state: present | ||||
|  | ||||
| - name: Change the bind-address to allow Docker | ||||
|   ansible.builtin.lineinfile: | ||||
|     path: /etc/my.cnf.d/mariadb-server.cnf | ||||
|     path: /etc/mysql/mariadb.conf.d/50-server.cnf | ||||
|     regex: "^bind-address" | ||||
|     line: "bind-address            = 0.0.0.0" | ||||
|   notify: restart_mariadb | ||||
|  | ||||
| - name: Start and enable MariaDB service | ||||
|   ansible.builtin.systemd: | ||||
|     name: mariadb | ||||
|     state: started | ||||
|     enabled: true | ||||
|  | ||||
| - name: Install MySQL Support for Python 3 | ||||
|   ansible.builtin.dnf: | ||||
|     name: python3-PyMySQL | ||||
|   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/lib/mysql/mysql.sock | ||||
|     login_unix_socket: /var/run/mysqld/mysqld.sock | ||||
|   loop: "{{ databases }}" | ||||
|   no_log: true | ||||
|   no_log: "{{ item.pass is defined }}" | ||||
|  | ||||
| - name: Create MariaDB users | ||||
|   community.mysql.mysql_user: | ||||
|     name: "{{ item.name }}" | ||||
|     password: "{{ item.pass }}" | ||||
|     host: "%" | ||||
|     host: '%' | ||||
|     state: present | ||||
|     priv: "{{ item.name }}.*:ALL" | ||||
|     login_unix_socket: /var/lib/mysql/mysql.sock | ||||
|     login_unix_socket: /var/run/mysqld/mysqld.sock | ||||
|   loop: "{{ databases }}" | ||||
|   no_log: true | ||||
|   no_log: "{{ item.pass is defined }}" | ||||
|  | ||||
| - name: Create webserver stack directory | ||||
| - name: Create webserver docker-compose directory | ||||
|   ansible.builtin.file: | ||||
|     path: /home/oci/webserver | ||||
|     path: "{{ webserver_root }}" | ||||
|     state: directory | ||||
|     mode: "700" | ||||
|     owner: oci | ||||
|     group: oci | ||||
|     mode: 0600 | ||||
|  | ||||
| - name: Install webserver compose file | ||||
| - name: Install webserver docker-compose.yml | ||||
|   ansible.builtin.copy: | ||||
|     src: docker-compose.yml | ||||
|     dest: /home/oci/webserver/compose.yml | ||||
|     mode: "600" | ||||
|     owner: oci | ||||
|     group: oci | ||||
|   notify: Start podman compose project | ||||
|     dest: "{{ webserver_root }}/docker-compose.yml" | ||||
|     mode: 0600 | ||||
|   notify: composeup_webserver | ||||
|  | ||||
| - name: Generate webserver environment configuration | ||||
| - name: Install docker-compose .env | ||||
|   ansible.builtin.template: | ||||
|     src: compose-env.j2 | ||||
|     dest: /home/oci/webserver/.env | ||||
|     mode: "400" | ||||
|     owner: oci | ||||
|     group: oci | ||||
|   notify: Start podman compose project | ||||
|     dest: "{{ webserver_root }}/.env" | ||||
|     mode: 0600 | ||||
|   notify: composeup_webserver | ||||
|  | ||||
| - name: Install nginx | ||||
|   ansible.builtin.dnf: | ||||
|     name: ["nginx", "nginx-mod-stream"] | ||||
|     state: present | ||||
|     update_cache: true | ||||
| - name: Allow MariaDB database connections | ||||
|   community.general.ufw: | ||||
|     rule: allow | ||||
|     port: 3306 | ||||
|     proto: tcp | ||||
|     src: "{{ item }}" | ||||
|   loop: "{{ mariadb_trust }}" | ||||
|  | ||||
| - name: Allow nginx to make network connections | ||||
|   ansible.posix.seboolean: | ||||
|     name: httpd_can_network_connect | ||||
|     state: true | ||||
|     persistent: true | ||||
|  | ||||
| - name: Deploy nginx proxy config | ||||
|   ansible.builtin.copy: | ||||
|     src: nginx.conf | ||||
|     dest: /etc/nginx/nginx.conf | ||||
|     mode: "644" | ||||
|   notify: Restart nginx | ||||
|  | ||||
| - name: Allow HTTP and HTTPS in firewall | ||||
|   ansible.posix.firewalld: | ||||
|     service: "{{ item }}" | ||||
|     permanent: true | ||||
|     state: enabled | ||||
|     immediate: true | ||||
| - name: Add HTTP and HTTPS firewall rule | ||||
|   community.general.ufw: | ||||
|     rule: allow | ||||
|     port: "{{ item }}" | ||||
|     proto: tcp | ||||
|   loop: | ||||
|     - http | ||||
|     - https | ||||
|  | ||||
| - name: Start and enable nginx | ||||
|   ansible.builtin.systemd: | ||||
|     name: nginx | ||||
|     state: started | ||||
|     enabled: true | ||||
|     - "80" | ||||
|     - "443" | ||||
|   | ||||
| @@ -8,7 +8,7 @@ MATCH_PATTERN="ssh -fNT -i ${PRIVATE_KEY}.*vagrant@" | ||||
|  | ||||
| function ssh_connect { | ||||
|   sudo ssh -fNT -i "$PRIVATE_KEY" \ | ||||
|     -L 9443:localhost:9443 \ | ||||
|     -L 8443:localhost:8443 \ | ||||
|     -L 80:localhost:80 \ | ||||
|     -L 443:localhost:443 \ | ||||
|     -o UserKnownHostsFile=/dev/null \ | ||||
|   | ||||
| @@ -3,5 +3,5 @@ | ||||
|   become: true | ||||
|   roles: | ||||
|     - common | ||||
|     - podman | ||||
|     - docker | ||||
|     - webserver | ||||
|   | ||||
		Reference in New Issue
	
	Block a user