17 Commits

Author SHA1 Message Date
7b24236e92 Fix permissions for MediaWiki LocalSettings.php 2025-07-03 01:30:44 -04:00
efd29c08fb Add MediaWiki container to webserver stack 2025-06-29 21:38:53 -04:00
bda79d0b37 Update Traefik syntax and add nginx SELinux perm 2025-06-08 22:54:52 -04:00
d2473533d5 Migrate from Docker on Debian to Podman on Rocky
- Upgrade base OS from Debian 11 to Rocky Linux 9
- Configure 100GB XFS filesystem with auto-expansion
- Replace Docker with rootless Podman for improved security
- Add nginx reverse proxy for non-privileged port handling
- Move the Traefik dashboard from port 8443 to 9443
- Configure SELinux contexts for container operations
2025-06-08 22:14:49 -04:00
236ec455cc Add cron and fix database maintenance task 2023-10-03 23:30:28 -04:00
69c38221ec Update .env template and add --diff 2023-10-03 20:45:15 -04:00
63c544d9e9 Add ncdu and tree packages 2022-11-25 02:58:00 -05:00
c8015351b4 Add strong random example of generating secrets 2022-11-25 01:02:13 -05:00
7048aa8418 Add Ansible Vault instructions to README 2022-11-25 00:57:02 -05:00
3abca7ce15 Remove old Nextcloud role 2022-11-24 02:11:09 -05:00
bf9c98fd3f Automated Nextcloud installation 2022-11-24 02:00:52 -05:00
511c26392c Add Nextcloud to docker-compose.yml 2022-11-22 03:27:34 -05:00
91c65abb91 Redirect to www from root domain 2022-11-20 21:32:39 -05:00
34495c80be Remove old WordPress role 2022-11-20 05:11:43 -05:00
671a94063d Example production-env clone 2022-11-20 05:06:20 -05:00
51b6f3b843 Install dnsutils 2022-11-20 01:49:52 -05:00
7bd4858c7e Add DNS-01 ACME wildcard certificate
- Add Ansible Vault convenience script
2022-11-19 20:58:07 -05:00
26 changed files with 613 additions and 449 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
.ansible*
.bitwarden
environments environments
*.log *.log
.playbook .playbook

View File

@@ -1,8 +1,10 @@
SHELL := /bin/bash
all: vagrant all: vagrant
vagrant: vagrant:
vagrant up --no-destroy-on-error --no-color | tee ./vagrantup.log set -o pipefail; vagrant up --no-destroy-on-error --no-color | tee ./vagrantup.log
./forward-ssh.sh ./scripts/forward-ssh.sh
clean: clean:
vagrant destroy -f --no-color vagrant destroy -f --no-color

View File

@@ -1,30 +1,78 @@
# Free I.T. Athen's Infrastructure # Free I.T. Athen's Infrastructure
This project is used to develop Ansible for deploying and maintaining websites This project is used to develop Ansible for deploying and maintaining websites
and services operated by Free I.T. Athens (FRITA). and services operated by Free I.T. Athens (FRITA).
- Requires GNU Make, Ansible, and Vagrant on the host - Requires GNU Make, Ansible, and Vagrant on the host
## Quick Start ## Quick Start
1. Clone this project 1. Clone this project
2. Run `make` to provision a Debian 11 base box 2. Run `make` to provision a Rocky 9 base box
3. Go to 3. Go to
- [Traefik Dashboard](https://traefik.local.freeitathens.org:8443/dashboard/#/) - [Traefik Dashboard](https://traefik.local.freeitathens.org:9443/dashboard/#/)
- [WordPress](https://www.local.freeitathens.org) - [WordPress](https://www.local.freeitathens.org)
- [Nextcloud](https://cloud.local.freeitathens.org)
- [Mediawiki](https://wiki.local.freeitathens.org)
4. Click through the HTTPS security warning 4. Click through the HTTPS security warning
## 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 --diff --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 ## Authors
* **Kris Lamoureux** - *Project Founder* - [@krislamo](https://github.com/krislamo)
- **Kris Lamoureux** - _Project Founder_ -
[@krislamo](https://github.com/krislamo)
## Copyrights and Licenses ## Copyrights and Licenses
Copyright (C) 2019, 2020, 2022 Free I.T. Athens
Copyright (C) 2019, 2020, 2022, 2023, 2025 Free I.T. Athens
This program is free software: you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
Foundation, version 3 of the License. Foundation, version 3 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT This program is distributed in the hope that it will be useful, but WITHOUT ANY
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 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 You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>. this program. If not, see <https://www.gnu.org/licenses/>.

34
Vagrantfile vendored
View File

@@ -14,9 +14,13 @@ else
File.write(".playbook", PLAYBOOK) File.write(".playbook", PLAYBOOK)
end end
# Debian 11 # Optionally allow more verbosity in Ansible
VAGRANT_ANSIBLE_VERBOSE=ENV["VAGRANT_ANSIBLE_VERBOSE"] || false
Vagrant.configure("2") do |config| Vagrant.configure("2") do |config|
config.vm.box = "debian/bullseye64" config.vm.box = "rockylinux/9"
config.vm.hostname = "fritadev"
config.vm.disk :disk, size: "100GB", primary: true
config.vm.synced_folder ".", "/vagrant", disabled: true config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.network "private_network", type: "dhcp" config.vm.network "private_network", type: "dhcp"
@@ -24,16 +28,38 @@ Vagrant.configure("2") do |config|
config.vm.define :frita do |frita| # config.vm.define :frita do |frita| #
end end
# Disable Machine Name Prefix # Set libvirt settings
config.vm.provider :libvirt do |libvirt| config.vm.provider :libvirt do |libvirt|
libvirt.cpus = 2
libvirt.memory = 4096
libvirt.default_prefix = "" libvirt.default_prefix = ""
libvirt.machine_virtual_size = 100
end end
# Set VirtualBox settings
config.vm.provider "virtualbox" do |vbox|
vbox.cpus = 2
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 # Provision with Ansible
config.vm.provision "ansible" do |ansible| config.vm.provision "ansible" do |ansible|
ENV['ANSIBLE_ROLES_PATH'] = File.dirname(__FILE__) + "/roles" ENV['ANSIBLE_ROLES_PATH'] = File.dirname(__FILE__) + "/roles"
ansible.compatibility_mode = "2.0" ansible.compatibility_mode = "2.0"
ansible.playbook = "dev/" + PLAYBOOK + ".yml" ansible.playbook = "dev/" + PLAYBOOK + ".yml"
ansible.verbose = VAGRANT_ANSIBLE_VERBOSE
end end
end end

View File

@@ -3,4 +3,4 @@ inventory = ./environments/development
interpreter_python = /usr/bin/python3 interpreter_python = /usr/bin/python3
[ssh_connection] [ssh_connection]
pipelining=True pipelining = True

View File

@@ -1,14 +1,23 @@
############### ###############
### Secrets ### ### Secrets ###
############### ###############
# These are sample public passwords not encrypted in Ansible Vault, unlike production
secret: secret:
TRAEFIK_DREAMHOST_APIKEY: DHap1pa55w0rd!
WORDPRESS_DB_PASSWORD: WPpa55w0rd! WORDPRESS_DB_PASSWORD: WPpa55w0rd!
NEXTCLOUD_MYSQL_PASSWORD: NCdbpa55w0rd!
NEXTCLOUD_ADMIN_PASSWORD: NCadm1npa55w0rd!
MEDIAWIKI_MYSQL_PASSWORD: MWdbpa55w0rd!
############## ##############
### Docker ### ### Common ###
############## ##############
docker_users: users:
- vagrant oci:
uid: 2000
gid: 2000
home: true
ansible_temp: true
################ ################
#### MariaDB ### #### MariaDB ###
@@ -16,6 +25,10 @@ docker_users:
databases: databases:
- name: wordpress - name: wordpress
pass: "{{ secret.WORDPRESS_DB_PASSWORD }}" pass: "{{ secret.WORDPRESS_DB_PASSWORD }}"
- name: nextcloud
pass: "{{ secret.NEXTCLOUD_MYSQL_PASSWORD }}"
- name: mediawiki
pass: "{{ secret.MEDIAWIKI_MYSQL_PASSWORD }}"
####################### #######################
### Webserver Stack ### ### Webserver Stack ###
@@ -24,20 +37,44 @@ webserver:
############### ###############
### Traefik ### ### Traefik ###
############### ###############
#TRAEFIK_VERSION: latest # TRAEFIK_VERSION: latest
#TRAEFIK_DOMAIN: traefik.local.freeitathens.org # TRAEFIK_ROOT_DOMAIN: local.freeitathens.org
#TRAEFIK_DASHBOARD: true # TRAEFIK_DOMAIN: traefik.local.freeitathens.org
#TRAEFIK_EXPOSED_DEFAULT: false # TRAEFIK_DASHBOARD: true
#TRAEFIK_TRAEFIK_ENABLE: true # TRAEFIK_EXPOSED_DEFAULT: false
# TRAEFIK_WEB_ENABLED: true
TRAEFIK_DEBUG: 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 ###
################# #################
#WORDPRESS_VERSION: latest # WORDPRESS_VERSION: latest
#WORDPRESS_DOMAIN: www.local.freeitathens.org # WORDPRESS_DOMAIN: www.local.freeitathens.org
#WORDPRESS_DB_HOST: host.docker.internal # WORDPRESS_DB_HOST: host.docker.internal
#WORDPRESS_DB_NAME: wordpress # WORDPRESS_DB_NAME: wordpress
#WORDPRESS_DB_USER: wordpress # WORDPRESS_DB_USER: wordpress
#WORDPRESS_WEB_ENABLED: true # WORDPRESS_WEB_ENABLED: true
WORDPRESS_DB_PASSWORD: "{{ secret.WORDPRESS_DB_PASSWORD }}" 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 }}"
#################
### MediaWiki ###
#################
# MEDIAWIKI_VERSION: stable
# MEDIAWIKI_DOMAIN: wiki.local.freeitathens.org

View File

@@ -5,5 +5,5 @@
- vars/webserver.yml - vars/webserver.yml
roles: roles:
- common - common
- docker - podman
- webserver - webserver

View File

@@ -0,0 +1,5 @@
common_packages:
- dnsutils
- ncdu
- tree
- vim

View File

@@ -2,29 +2,87 @@
ansible.builtin.file: ansible.builtin.file:
path: "~/.ansible/tmp" path: "~/.ansible/tmp"
state: directory state: directory
mode: 0700 mode: "755"
- name: Install the Uncomplicated Firewall - name: Create system user groups
ansible.builtin.apt: ansible.builtin.group:
name: ufw 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 state: present
update_cache: true update_cache: true
- name: Deny incoming traffic by default - name: Install useful software
community.general.ufw: ansible.builtin.dnf:
default: deny name: "{{ common_packages }}"
direction: incoming state: present
update_cache: true
- name: Allow outgoing traffic by default - name: Install firewalld
community.general.ufw: ansible.builtin.dnf:
default: allow name: firewalld
direction: outgoing state: present
- name: Allow OpenSSH with rate limiting - name: Start and enable firewalld service
community.general.ufw: ansible.builtin.systemd:
name: ssh name: firewalld
rule: limit state: started
enabled: true
- name: Enable firewall - name: Set default zone to drop (deny incoming by default)
community.general.ufw: ansible.posix.firewalld:
zone: drop
state: enabled 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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,4 @@
- name: Restart systemd-logind
ansible.builtin.systemd:
name: systemd-logind
state: restarted

View File

@@ -0,0 +1,49 @@
- 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

View File

@@ -1,4 +1,5 @@
webserver_root: "{{ docker_compose_root }}/webserver" webserver_root: "{{ docker_compose_root }}/webserver"
nextcloud_autoinstall: true
mariadb_trust: mariadb_trust:
- "172.16.0.0/12" - "172.16.0.0/12"
- "192.168.0.0/16" - "192.168.0.0/16"

View File

@@ -1,7 +1,7 @@
version: '3.5'
volumes: volumes:
wordpress: wordpress:
nextcloud:
mediawiki:
networks: networks:
traefik: traefik:
@@ -9,36 +9,51 @@ networks:
services: services:
traefik: traefik:
image: traefik:${TRAEFIK_VERSION:-latest} image: ${TRAEFIK_IMAGE:-docker.io/library/traefik}:${TRAEFIK_VERSION:-latest}
restart: always restart: always
security_opt:
- label=type:container_runtime_t
command: command:
- --api.dashboard=${TRAEFIK_DASHBOARD:-true} - --api.dashboard=${TRAEFIK_DASHBOARD:-true}
- --api.debug=${TRAEFIK_DEBUG:-false} - --api.debug=${TRAEFIK_DEBUG:-false}
- --log.level=${TRAEFIK_LOG_LEVEL:-ERROR}
- --providers.docker=true - --providers.docker=true
- --providers.docker.exposedbydefault=${TRAEFIK_EXPOSED_DEFAULT:-false} - --providers.docker.exposedbydefault=${TRAEFIK_EXPOSED_DEFAULT:-false}
- --entrypoints.web.address=:80 - --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.local.address=:9443
- --entrypoints.web.http.redirections.entrypoint.to=websecure - --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https - --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true - --entrypoints.web.http.redirections.entrypoint.permanent=true
- --entrypoints.websecure.address=:443 - --certificatesresolvers.letsencrypt.acme.email=${TRAEFIK_ACME_EMAIL}
- --entrypoints.local.address=:8443 - --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: ports:
- 80:80 - "${ENTRYWEB:-127.0.0.1:8080}:80"
- 443:443 - "${ENTRYSECURE:-127.0.0.1:8443}:443"
- "127.0.0.1:8443:8443" - "${ENTRYLOCAL:-127.0.0.1:9443}:9443"
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - ${OCI_SOCK:-/run/user/2000/podman/podman.sock}:/var/run/docker.sock:ro,Z
- ./.acme:/etc/letsencrypt
labels: labels:
traefik.http.routers.api.rule: Host(`${TRAEFIK_DOMAIN:-traefik.local.freeitathens.org}`) traefik.http.routers.api.rule: Host(`${TRAEFIK_DOMAIN:-traefik.local.freeitathens.org}`)
traefik.http.routers.api.entrypoints: local traefik.http.routers.api.entrypoints: local
traefik.http.routers.api.service: api@internal traefik.http.routers.api.service: api@internal
traefik.http.routers.api.tls: true 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} traefik.enable: ${TRAEFIK_WEB_ENABLED:-true}
networks: networks:
- traefik - traefik
wordpress: wordpress:
image: wordpress:${WORDPRESS_VERSION:-latest} image: ${WORDPRESS_IMAGE:-docker.io/library/wordpress}:${WORDPRESS_VERSION:-latest}
restart: always restart: always
environment: environment:
WORDPRESS_DB_HOST: ${WORDPRESS_DB_HOST:-host.docker.internal} WORDPRESS_DB_HOST: ${WORDPRESS_DB_HOST:-host.docker.internal}
@@ -46,9 +61,18 @@ services:
WORDPRESS_DB_USER: ${WORDPRESS_DB_USER:-wordpress} WORDPRESS_DB_USER: ${WORDPRESS_DB_USER:-wordpress}
WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD} WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
labels: labels:
traefik.http.routers.wordpress.rule: Host(`${WORDPRESS_DOMAIN:-www.local.freeitathens.org}`) traefik.http.routers.wordpress.rule:
Host(`${WORDPRESS_DOMAIN:-www.local.freeitathens.org}`) ||
Host(`${TRAEFIK_ACME_DOMAIN_MAIN:-local.freeitathens.org}`)
traefik.http.routers.wordpress.entrypoints: websecure traefik.http.routers.wordpress.entrypoints: websecure
traefik.http.routers.wordpress.middlewares: "wwwredirect"
traefik.http.routers.wordpress.tls: true 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.http.services.wordpress.loadbalancer.server.port: 80
traefik.docker.network: traefik traefik.docker.network: traefik
traefik.enable: ${WORDPRESS_WEB_ENABLED:-true} traefik.enable: ${WORDPRESS_WEB_ENABLED:-true}
@@ -58,3 +82,53 @@ services:
- traefik - traefik
extra_hosts: extra_hosts:
- host.docker.internal:host-gateway - host.docker.internal:host-gateway
nextcloud:
image: ${NEXTCLOUD_IMAGE:-docker.io/library/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
mediawiki:
image: ${MEDIAWIKI_IMAGE:-docker.io/library/mediawiki}:${MEDIAWIKI_VERSION:-stable}
restart: always
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.docker.network: traefik
traefik.enable: ${MEDIAWIKI_WEB_ENABLED:-true}
volumes:
- ./LocalSettings.php:/var/www/html/LocalSettings.php:ro,Z
- mediawiki:/var/www/html/images
networks:
- traefik
extra_hosts:
- host.docker.internal:host-gateway

View File

@@ -0,0 +1,22 @@
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;
}
}

View File

@@ -1,11 +1,70 @@
- name: Compose up on webserver stack - name: Restart nginx
ansible.builtin.command: "docker-compose up -d" ansible.builtin.systemd:
args: name: nginx
chdir: "{{ webserver_root }}" state: restarted
listen: composeup_webserver
- name: Restart MariaDB - name: Restart MariaDB
ansible.builtin.service: ansible.builtin.service:
name: mariadb name: mariadb
state: restarted state: restarted
listen: restart_mariadb 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: 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
- 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

View File

@@ -0,0 +1,44 @@
- 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: 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:
- "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 or nextcloud_install.changed"

View File

@@ -1,72 +1,102 @@
- name: Install MariaDB Server - name: Install MariaDB Server
ansible.builtin.apt: ansible.builtin.dnf:
name: mariadb-server name: mariadb-server
state: present state: present
- name: Change the bind-address to allow Docker - name: Change the bind-address to allow Docker
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
path: /etc/mysql/mariadb.conf.d/50-server.cnf path: /etc/my.cnf.d/mariadb-server.cnf
regex: "^bind-address" regex: "^bind-address"
line: "bind-address = 0.0.0.0" line: "bind-address = 0.0.0.0"
notify: restart_mariadb 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 - name: Install MySQL Support for Python 3
ansible.builtin.apt: ansible.builtin.dnf:
name: python3-pymysql name: python3-PyMySQL
state: present state: present
- name: Create MariaDB databases - name: Create MariaDB databases
community.mysql.mysql_db: community.mysql.mysql_db:
name: "{{ item.name }}" name: "{{ item.name }}"
state: present state: present
login_unix_socket: /var/run/mysqld/mysqld.sock login_unix_socket: /var/lib/mysql/mysql.sock
loop: "{{ databases }}" loop: "{{ databases }}"
no_log: "{{ item.pass is defined }}" no_log: true
- name: Create MariaDB users - name: Create MariaDB users
community.mysql.mysql_user: community.mysql.mysql_user:
name: "{{ item.name }}" name: "{{ item.name }}"
password: "{{ item.pass }}" password: "{{ item.pass }}"
host: '%' host: "%"
state: present state: present
priv: "{{ item.name }}.*:ALL" priv: "{{ item.name }}.*:ALL"
login_unix_socket: /var/run/mysqld/mysqld.sock login_unix_socket: /var/lib/mysql/mysql.sock
loop: "{{ databases }}" loop: "{{ databases }}"
no_log: "{{ item.pass is defined }}" no_log: true
- name: Create webserver docker-compose directory - name: Create webserver stack directory
ansible.builtin.file: ansible.builtin.file:
path: "{{ webserver_root }}" path: /home/oci/webserver
state: directory state: directory
mode: 0600 mode: "700"
owner: oci
group: oci
- name: Install webserver docker-compose.yml - name: Install webserver compose file
ansible.builtin.copy: ansible.builtin.copy:
src: docker-compose.yml src: docker-compose.yml
dest: "{{ webserver_root }}/docker-compose.yml" dest: /home/oci/webserver/compose.yml
mode: 0600 mode: "600"
notify: composeup_webserver owner: oci
group: oci
notify: Start podman compose project
- name: Install docker-compose .env - name: Generate webserver environment configuration
ansible.builtin.template: ansible.builtin.template:
src: compose-env.j2 src: compose-env.j2
dest: "{{ webserver_root }}/.env" dest: /home/oci/webserver/.env
mode: 0600 mode: "400"
notify: composeup_webserver owner: oci
group: oci
notify: Start podman compose project
- name: Allow MariaDB database connections - name: Install nginx
community.general.ufw: ansible.builtin.dnf:
rule: allow name: ["nginx", "nginx-mod-stream"]
port: 3306 state: present
proto: tcp update_cache: true
src: "{{ item }}"
loop: "{{ mariadb_trust }}"
- name: Add HTTP and HTTPS firewall rule - name: Allow nginx to make network connections
community.general.ufw: ansible.posix.seboolean:
rule: allow name: httpd_can_network_connect
port: "{{ item }}" state: true
proto: tcp 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
loop: loop:
- "80" - http
- "443" - https
- name: Start and enable nginx
ansible.builtin.systemd:
name: nginx
state: started
enabled: true

View File

@@ -1,4 +1,4 @@
# {{ ansible_managed }} # {{ ansible_managed }}
{% for key, value in webserver.items() %} {% for key, value in webserver.items() %}
{{ key }}={{ value }} {{ key }}={{ value }}
{% endfor %} {% endfor %}

View File

@@ -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

View File

@@ -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

View File

@@ -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');

View File

@@ -8,7 +8,7 @@ MATCH_PATTERN="ssh -fNT -i ${PRIVATE_KEY}.*vagrant@"
function ssh_connect { function ssh_connect {
sudo ssh -fNT -i "$PRIVATE_KEY" \ sudo ssh -fNT -i "$PRIVATE_KEY" \
-L 8443:localhost:8443 \ -L 9443:localhost:9443 \
-L 80:localhost:80 \ -L 80:localhost:80 \
-L 443:localhost:443 \ -L 443:localhost:443 \
-o UserKnownHostsFile=/dev/null \ -o UserKnownHostsFile=/dev/null \

51
scripts/vault-key.sh Executable file
View 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

View File

@@ -3,5 +3,5 @@
become: true become: true
roles: roles:
- common - common
- docker - podman
- webserver - webserver