32 Commits

Author SHA1 Message Date
385e60aee5 Update proxy playbook 2023-11-02 23:29:54 -04:00
5633468f41 Fix linting issues on Docker role 2023-10-22 13:48:20 -04:00
7f91b24adb Add Debian/Official Docker repo toggle
- Default docker_official toggle to false (for now)
- Preempt MariaDB restart before container restarts
- Start containers in a handler
2023-10-22 11:33:05 -04:00
5b09029239 Update base role to pass linting 2023-10-20 21:30:25 -04:00
7adb5f10e9 Update Gitea role for docker_compose_deploy
- Add MariaDB to dev playbook
- Set Git user in "users:"
- Define Gitea external compose project
- Forward SSH port in forwarding script
- Create user groups with system users
- Install python3-pymysql for Ansible
- Strip old Gitea deployment methods
- Bind MariaDB to docker0 for Docker access
2023-10-20 15:41:44 -04:00
c3b4321667 Add Gitea dev playbook and host_vars 2023-10-19 16:40:34 -04:00
d05c5d3086 Slight tweaks on Ansible output 2023-10-19 16:36:05 -04:00
ac412f16ef Simplify the "Import GPG keys" loop 2023-10-19 14:09:10 -04:00
2354a8fb8c Verify successful GPG imports 2023-10-19 13:37:35 -04:00
251a7c0dd5 Import PGP key and verify git commits 2023-10-19 02:56:36 -04:00
1d8ae8a0b6 Install ntpsec 2023-10-19 01:27:31 -04:00
6b2feaee5e Hide docker-compose secrets from diff output 2023-10-18 23:03:52 -04:00
31e0538b84 Add locale configuration tasks to base role 2023-10-18 16:32:09 -04:00
a65c4b9cf6 Handle Ansible undefined loop variable
- Default docker_compose_deploy to empty list if undefined
- Add conditional check to avoid looping through an empty list
2023-10-10 00:14:52 -04:00
7ee6e4810d Convert booleans to lowercase 2023-10-10 00:00:00 -04:00
87aa7ecf8b Add external compose support in the docker role
- Use ansible.posix.synchronize for compose.yml
- Set fact for compose service restarts
- Introduce plain Docker dev host
- Optionally verify repos via GPG before sync
- Hide docker_repos_path in .folder
- Tweak .env for conciseness
- Add --diff to Ansible in Vagrantfile
- Clean output with loop_control
- Embed GPG in base role
2023-10-09 23:47:49 -04:00
0377a5e642 Add option for private OCI registry auth 2023-09-29 22:18:59 -04:00
2e02efcbb7 Add Makefile, roles_path, and SSH tunnel variable 2023-09-26 21:14:06 -04:00
8fed63792b Ask permission for starting vagrant SSH tunnels 2023-09-16 00:04:58 -04:00
2c4fcbacc3 Introduce forward-ssh.sh method & reorganize
- Abandoned update-hosts.sh in favor of loopback SSH forwarding
- Adopted *.local.krislamo.org as a wildcard loopback domain
- Bound Traefik to ports 443/80 on Dockerbox dev
- Removed outdated Gitea config from Dockerbox
- Relocated production playbooks to a new directory
2023-09-15 23:46:45 -04:00
b81372c07a Fix the Vagrantfile for Github runners 2023-08-30 19:45:42 -04:00
9b5be29a1a Update Vagrantfile to use external settings 2023-08-21 18:46:47 -04:00
ef5aacdbbd No deploy keys without compose deploy variable 2023-07-21 23:52:18 -04:00
a635c7aa48 Add option to deploy external docker-compose stack 2023-07-20 03:51:44 -04:00
56aee460ad Limit Github actions to specific branches 2023-07-20 00:33:42 -04:00
027ba46f6b Add Github actions and remove old ansible stuff 2023-07-08 23:43:52 -04:00
48216db8f9 Updated Nextcloud settings and added cron job 2023-06-18 23:52:10 -04:00
fa1dc4acb7 Fix WireGuard firewall rule 2023-06-15 03:09:13 -04:00
228cd5795b Config adjustments for Jellyfin/Samba deployment
- Ignored .vscode
- Added firewall exclusion option
- Allowed guest access in Samba
2023-06-09 22:26:47 -04:00
74a559f1f6 Update mediaserver playbook and fix Wireguard task 2023-06-08 03:47:54 -04:00
4c2a1550c4 Adding samba and general user management 2023-06-07 02:12:17 -04:00
f02cf7b0cc Refactor docker playbook
- Removed copyright notice
- Variablize 'hosts' value in the playbook
- Install Jenkins agent before running Docker role
2023-05-08 16:26:16 -04:00
61 changed files with 806 additions and 271 deletions

39
.github/workflows/vagrant.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: homelab-ci
on:
push:
branches:
- main
- testing
jobs:
homelab-ci:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Cache Vagrant boxes
uses: actions/cache@v3
with:
path: ~/.vagrant.d/boxes
key: ${{ runner.os }}-vagrant-${{ hashFiles('Vagrantfile') }}
restore-keys: |
${{ runner.os }}-vagrant-
- name: Install Ansible
run: brew install ansible@7
- name: Software Versions
run: |
printf "VirtualBox "
vboxmanage --version
vagrant --version
export PATH="/usr/local/opt/ansible@7/bin:$PATH"
ansible --version
- name: Vagrant Up with Dockerbox Playbook
run: |
export PATH="/usr/local/opt/ansible@7/bin:$PATH"
PLAYBOOK=dockerbox vagrant up
vagrant ssh -c "docker ps"

3
.gitignore vendored
View File

@@ -1,3 +1,4 @@
.vagrant
.playbook .playbook
.vagrant*
.vscode
/environments/ /environments/

10
Makefile Normal file
View File

@@ -0,0 +1,10 @@
.PHONY: clean install
all: install
install:
vagrant up --no-destroy-on-error
sudo ./forward-ssh.sh
clean:
vagrant destroy -f && rm -rf .vagrant

50
Vagrantfile vendored
View File

@@ -1,43 +1,41 @@
# -*- mode: ruby -*- # -*- mode: ruby -*-
# vi: set ft=ruby : # vi: set ft=ruby :
SSH_FORWARD=ENV["SSH_FORWARD"] require 'yaml'
if !(SSH_FORWARD == "true") settings_path = '.vagrant.yml'
SSH_FORWARD = false settings = {}
if File.exist?(settings_path)
settings = YAML.load_file(settings_path)
end end
PLAYBOOK=ENV["PLAYBOOK"] VAGRANT_BOX = settings['VAGRANT_BOX'] || 'debian/bookworm64'
if !PLAYBOOK VAGRANT_CPUS = settings['VAGRANT_CPUS'] || 2
if File.exist?('.playbook') VAGRANT_MEM = settings['VAGRANT_MEM'] || 2048
PLAYBOOK = IO.read('.playbook').split("\n")[0] SSH_FORWARD = settings['SSH_FORWARD'] || false
end
if !PLAYBOOK || PLAYBOOK.empty? # Default to shell environment variable: PLAYBOOK (priority #1)
PLAYBOOK = "\nERROR: Set env PLAYBOOK" PLAYBOOK=ENV["PLAYBOOK"]
end if !PLAYBOOK || PLAYBOOK.empty?
else # PLAYBOOK setting in .vagrant.yml (priority #2)
File.write(".playbook", PLAYBOOK) PLAYBOOK = settings['PLAYBOOK'] || 'default'
end end
Vagrant.configure("2") do |config| Vagrant.configure("2") do |config|
config.vm.box = "debian/bullseye64" config.vm.box = VAGRANT_BOX
config.vm.network "private_network", type: "dhcp" config.vm.network "private_network", type: "dhcp"
config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.synced_folder "./scratch", "/vagrant/scratch"
config.ssh.forward_agent = SSH_FORWARD config.ssh.forward_agent = SSH_FORWARD
# Machine Name # Libvrit provider
config.vm.define :moxie do |moxie| #
end
config.vm.provider :libvirt do |libvirt| config.vm.provider :libvirt do |libvirt|
libvirt.cpus = 2 libvirt.cpus = VAGRANT_CPUS
libvirt.memory = 4096 libvirt.memory = VAGRANT_MEM
libvirt.default_prefix = ""
end end
config.vm.provider "virtualbox" do |vbox| # Virtualbox provider
vbox.memory = 4096 config.vm.provider :virtualbox do |vbox|
vbox.cpus = VAGRANT_CPUS
vbox.memory = VAGRANT_MEM
end end
# Provision with Ansible # Provision with Ansible
@@ -45,6 +43,6 @@ Vagrant.configure("2") do |config|
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.raw_arguments = ["--diff"]
end end
end end

View File

@@ -1,6 +1,7 @@
[defaults] [defaults]
inventory = ./environments/development inventory = ./environments/development
interpreter_python = /usr/bin/python3 interpreter_python = /usr/bin/python3
roles_path = ./roles
[connection] [connection]
pipelining = true pipelining = true

4
dev/default.yml Normal file
View File

@@ -0,0 +1,4 @@
- name: Install 'default' aka nothing
hosts: all
become: true
tasks: []

8
dev/docker.yml Normal file
View File

@@ -0,0 +1,8 @@
- name: Install Docker Server
hosts: all
become: true
vars_files:
- host_vars/docker.yml
roles:
- base
- docker

View File

@@ -1,4 +1,4 @@
- name: Install Docker Box Server - name: Install Dockerbox Server
hosts: all hosts: all
become: true become: true
vars_files: vars_files:

10
dev/gitea.yml Normal file
View File

@@ -0,0 +1,10 @@
- name: Install Gitea Server
hosts: all
become: true
vars_files:
- host_vars/gitea.yml
roles:
- base
- docker
- mariadb
- gitea

View File

@@ -9,14 +9,14 @@ docker_users:
# traefik # traefik
traefik_version: latest traefik_version: latest
traefik_dashboard: true traefik_dashboard: true
traefik_domain: traefik.vm.krislamo.org traefik_domain: traefik.local.krislamo.org
traefik_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin traefik_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin
#traefik_acme_email: realemail@example.com # Let's Encrypt settings #traefik_acme_email: realemail@example.com # Let's Encrypt settings
#traefik_production: true #traefik_production: true
# bitwarden # bitwarden
# Get Installation ID & Key at https://bitwarden.com/host/ # Get Installation ID & Key at https://bitwarden.com/host/
bitwarden_domain: vault.vm.krislamo.org bitwarden_domain: vault.local.krislamo.org
bitwarden_dbpass: password bitwarden_dbpass: password
bitwarden_install_id: 4ea840a3-532e-4cb6-a472-abd900728b23 bitwarden_install_id: 4ea840a3-532e-4cb6-a472-abd900728b23
bitwarden_install_key: 1yB3Z2gRI0KnnH90C6p bitwarden_install_key: 1yB3Z2gRI0KnnH90C6p

48
dev/host_vars/docker.yml Normal file
View File

@@ -0,0 +1,48 @@
# base
allow_reboot: false
manage_network: false
# Import my GPG key for git signature verification
root_gpgkeys:
- name: kris@lamoureux.io
id: FBF673CEEC030F8AECA814E73EDA9C3441EDA925
# docker
docker_users:
- vagrant
#docker_login_url: https://myregistry.example.com
#docker_login_user: myuser
#docker_login_pass: YOUR_PASSWD
docker_compose_env_nolog: false # dev only setting
docker_compose_deploy:
# Traefik
- name: traefik
url: https://github.com/krislamo/traefik
version: 31ee724feebc1d5f91cb17ffd6892c352537f194
enabled: true
accept_newhostkey: true # Consider verifying manually instead
trusted_keys:
- FBF673CEEC030F8AECA814E73EDA9C3441EDA925
env:
ENABLE: true
# Traefik 2 (no other external compose to test currently)
- name: traefik2
url: https://github.com/krislamo/traefik
version: 31ee724feebc1d5f91cb17ffd6892c352537f194
enabled: true
accept_newhostkey: true # Consider verifying manually instead
trusted_keys:
- FBF673CEEC030F8AECA814E73EDA9C3441EDA925
env:
ENABLE: true
VERSION: "2.10"
DOMAIN: traefik2.local.krislamo.org
NAME: traefik2
ROUTER: traefik2
NETWORK: traefik2
WEB_PORT: 127.0.0.1:8000:80
WEBSECURE_PORT: 127.0.0.1:4443:443
LOCAL_PORT: 127.0.0.1:8444:8443

View File

@@ -9,40 +9,36 @@ docker_users:
# traefik # traefik
traefik_version: latest traefik_version: latest
traefik_dashboard: true traefik_dashboard: true
traefik_domain: traefik.vm.krislamo.org traefik_domain: traefik.local.krislamo.org
traefik_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin traefik_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin
traefik_web_entry: 0.0.0.0:80
traefik_websecure_entry: 0.0.0.0:443
#traefik_acme_email: realemail@example.com # Let's Encrypt settings #traefik_acme_email: realemail@example.com # Let's Encrypt settings
#traefik_production: true #traefik_production: true
traefik_http_only: true # if behind reverse-proxy #traefik_http_only: true # if behind reverse-proxy
# nextcloud # nextcloud
nextcloud_version: stable nextcloud_version: stable
nextcloud_admin: admin nextcloud_admin: admin
nextcloud_pass: password nextcloud_pass: password
nextcloud_domain: cloud.vm.krislamo.org nextcloud_domain: cloud.local.krislamo.org
nextcloud_dbversion: latest nextcloud_dbversion: latest
nextcloud_dbpass: password nextcloud_dbpass: password
# gitea
gitea_domain: git.vm.krislamo.org
gitea_version: 1
gitea_dbversion: latest
gitea_dbpass: password
# jenkins # jenkins
jenkins_version: lts jenkins_version: lts
jenkins_domain: jenkins.vm.krislamo.org jenkins_domain: jenkins.local.krislamo.org
# prometheus (includes grafana) # prometheus (includes grafana)
prom_version: latest prom_version: latest
prom_domain: prom.vm.krislamo.org prom_domain: prom.local.krislamo.org
grafana_version: latest grafana_version: latest
grafana_domain: grafana.vm.krislamo.org grafana_domain: grafana.local.krislamo.org
prom_targets: "['10.0.2.15:9100']" prom_targets: "['10.0.2.15:9100']"
# nginx # nginx
nginx_domain: nginx.vm.krislamo.org nginx_domain: nginx.local.krislamo.org
nginx_name: staticsite nginx_name: staticsite
nginx_repo_url: https://git.krislamo.org/kris/example-website/ nginx_repo_url: https://git.krislamo.org/kris/example-website/
nginx_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin nginx_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin

50
dev/host_vars/gitea.yml Normal file
View File

@@ -0,0 +1,50 @@
# base
allow_reboot: false
manage_network: false
users:
git:
uid: 1001
gid: 1001
home: true
system: true
# Import my GPG key for git signature verification
root_gpgkeys:
- name: kris@lamoureux.io
id: FBF673CEEC030F8AECA814E73EDA9C3441EDA925
# docker
docker_official: true # docker's apt repos
docker_users:
- vagrant
docker_compose_env_nolog: false # dev only setting
docker_compose_deploy:
# Traefik
- name: traefik
url: https://github.com/krislamo/traefik
version: 398eb48d311db78b86abf783f903af4a1658d773
enabled: true
accept_newhostkey: true
trusted_keys:
- FBF673CEEC030F8AECA814E73EDA9C3441EDA925
env:
ENABLE: true
# Gitea
- name: gitea
url: https://github.com/krislamo/gitea
version: b0ce66f6a1ab074172eed79eeeb36d7e9011ef8f
enabled: true
trusted_keys:
- FBF673CEEC030F8AECA814E73EDA9C3441EDA925
env:
USER_UID: "{{ users.git.uid }}"
USER_GID: "{{ users.git.gid }}"
DB_PASSWD: "{{ gitea.DB_PASSWD }}"
# gitea
gitea:
DB_NAME: gitea
DB_USER: gitea
DB_PASSWD: password

View File

@@ -1,9 +1,32 @@
base_domain: vm.krislamo.org base_domain: local.krislamo.org
# base # base
allow_reboot: false allow_reboot: false
manage_network: false manage_network: false
users:
jellyfin:
uid: 1001
gid: 1001
shell: /usr/sbin/nologin
home: false
system: true
samba:
users:
- name: jellyfin
password: jellyfin
shares:
- name: jellyfin
path: /srv/jellyfin
owner: jellyfin
group: jellyfin
valid_users: jellyfin
firewall:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
# proxy # proxy
proxy: proxy:
#production: true #production: true
@@ -35,3 +58,4 @@ traefik_http_only: true # if behind reverse-proxy
# jellyfin # jellyfin
jellyfin_domain: "jellyfin.{{ base_domain }}" jellyfin_domain: "jellyfin.{{ base_domain }}"
jellyfin_version: latest jellyfin_version: latest
jellyfin_media: /srv/jellyfin

View File

@@ -5,14 +5,14 @@ docker_users:
# traefik # traefik
traefik_version: latest traefik_version: latest
traefik_dashboard: true traefik_dashboard: true
traefik_domain: traefik.vm.krislamo.org traefik_domain: traefik.local.krislamo.org
traefik_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin traefik_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin
# container settings # container settings
nextcloud_version: stable nextcloud_version: stable
nextcloud_admin: admin nextcloud_admin: admin
nextcloud_pass: password nextcloud_pass: password
nextcloud_domain: cloud.vm.krislamo.org nextcloud_domain: cloud.local.krislamo.org
# database settings # database settings
nextcloud_dbversion: latest nextcloud_dbversion: latest

View File

@@ -9,13 +9,13 @@ docker_users:
# traefik # traefik
traefik_version: latest traefik_version: latest
traefik_dashboard: true traefik_dashboard: true
traefik_domain: traefik.vm.krislamo.org traefik_domain: traefik.local.krislamo.org
traefik_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin traefik_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin
#traefik_acme_email: realemail@example.com # Let's Encrypt settings #traefik_acme_email: realemail@example.com # Let's Encrypt settings
#traefik_production: true #traefik_production: true
# nginx # nginx
nginx_domain: nginx.vm.krislamo.org nginx_domain: nginx.local.krislamo.org
nginx_name: staticsite nginx_name: staticsite
nginx_repo_url: https://git.krislamo.org/kris/example-website/ nginx_repo_url: https://git.krislamo.org/kris/example-website/
nginx_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin nginx_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin

View File

@@ -1,9 +1,21 @@
base_domain: vm.krislamo.org base_domain: local.krislamo.org
# base # base
allow_reboot: false allow_reboot: false
manage_network: false manage_network: false
users:
git:
uid: 1001
gid: 1001
home: true
system: true
# Import my GPG key for git signature verification
root_gpgkeys:
- name: kris@lamoureux.io
id: FBF673CEEC030F8AECA814E73EDA9C3441EDA925
# proxy # proxy
proxy: proxy:
#production: true #production: true
@@ -15,14 +27,49 @@ proxy:
- "{{ base_domain }}" - "{{ base_domain }}"
servers: servers:
- domain: "{{ bitwarden_domain }}" - domain: "{{ bitwarden_domain }}"
proxy_pass: "http://127.0.0.1:8080" proxy_pass: "http://127.0.0.1"
- domain: "{{ gitea_domain }}" - domain: "{{ gitea_domain }}"
proxy_pass: "http://127.0.0.1:3000" proxy_pass: "http://127.0.0.1"
# docker # docker
docker_official: true # docker's apt repos
docker_users: docker_users:
- vagrant - vagrant
docker_compose_env_nolog: false # dev only setting
docker_compose_deploy:
# Traefik
- name: traefik
url: https://github.com/krislamo/traefik
version: e97db75e2e214582fac5f5e495687ab5cdf855ad
path: docker-compose.web.yml
enabled: true
accept_newhostkey: true
trusted_keys:
- FBF673CEEC030F8AECA814E73EDA9C3441EDA925
env:
ENABLE: true
# Gitea
- name: gitea
url: https://github.com/krislamo/gitea
version: b0ce66f6a1ab074172eed79eeeb36d7e9011ef8f
enabled: true
trusted_keys:
- FBF673CEEC030F8AECA814E73EDA9C3441EDA925
env:
ENTRYPOINT: web
ENABLE_TLS: false
USER_UID: "{{ users.git.uid }}"
USER_GID: "{{ users.git.gid }}"
DB_PASSWD: "{{ gitea.DB_PASSWD }}"
# gitea
gitea_domain: "git.{{ base_domain }}"
gitea:
DB_NAME: gitea
DB_USER: gitea
DB_PASSWD: password
# bitwarden # bitwarden
# Get Installation ID & Key at https://bitwarden.com/host/ # Get Installation ID & Key at https://bitwarden.com/host/
bitwarden_domain: "vault.{{ base_domain }}" bitwarden_domain: "vault.{{ base_domain }}"
@@ -30,8 +77,3 @@ bitwarden_dbpass: password
bitwarden_install_id: 4ea840a3-532e-4cb6-a472-abd900728b23 bitwarden_install_id: 4ea840a3-532e-4cb6-a472-abd900728b23
bitwarden_install_key: 1yB3Z2gRI0KnnH90C6p bitwarden_install_key: 1yB3Z2gRI0KnnH90C6p
#bitwarden_prodution: true #bitwarden_prodution: true
# gitea
gitea_domain: "git.{{ base_domain }}"
gitea_version: 1
gitea_dbpass: password

View File

@@ -9,14 +9,14 @@ docker_users:
# traefik # traefik
traefik_version: latest traefik_version: latest
traefik_dashboard: true traefik_dashboard: true
traefik_domain: traefik.vm.krislamo.org traefik_domain: traefik.local.krislamo.org
traefik_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin traefik_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin
#traefik_acme_email: realemail@example.com # Let's Encrypt settings #traefik_acme_email: realemail@example.com # Let's Encrypt settings
#traefik_production: true #traefik_production: true
# container settings # container settings
wordpress_version: latest wordpress_version: latest
wordpress_domain: wordpress.vm.krislamo.org wordpress_domain: wordpress.local.krislamo.org
wordpress_multisite: true wordpress_multisite: true
# database settings # database settings

View File

@@ -5,8 +5,8 @@
- host_vars/proxy.yml - host_vars/proxy.yml
roles: roles:
- base - base
- mariadb
- proxy - proxy
- docker - docker
- mariadb
- gitea - gitea
- bitwarden - bitwarden

View File

@@ -1,21 +0,0 @@
# Copyright (C) 2020 Kris Lamoureux
#
# 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 Docker Server
hosts: dockerhosts
become: true
roles:
- base
- docker
- jenkins

View File

@@ -1,25 +0,0 @@
# Copyright (C) 2020 Kris Lamoureux
#
# 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 Docker Box Server
hosts: dockerhosts
become: true
roles:
- base
- docker
- traefik
- nextcloud
- jenkins
- prometheus
- nginx

91
forward-ssh.sh Executable file
View File

@@ -0,0 +1,91 @@
#!/bin/bash
# Finds the SSH private key under ./.vagrant and connects to
# the Vagrant box, port forwarding localhost ports: 8443, 80, 443
# Root check
if [ "$EUID" -ne 0 ]; then
echo "[ERROR]: Please run script as root"
exit 1
fi
# Clean environment
unset PRIVATE_KEY
unset HOST_IP
unset MATCH_PATTERN
unset PKILL_ANSWER
# Function to create the SSH tunnel
function ssh_connect {
read -rp "Start a new vagrant SSH tunnel? [y/N] " PSTART_ANSWER
echo
case "$PSTART_ANSWER" in
[yY])
printf "[INFO]: Starting new vagrant SSH tunnel on PID "
sudo -u "$USER" ssh -fNT -i "$PRIVATE_KEY" \
-L 22:localhost:22 \
-L 80:localhost:80 \
-L 443:localhost:443 \
-L 8443:localhost:8443 \
-o UserKnownHostsFile=/dev/null \
-o StrictHostKeyChecking=no \
vagrant@"$HOST_IP" 2>/dev/null
sleep 2
pgrep -f "$MATCH_PATTERN"
;;
*)
echo "[INFO]: Delined to start a new vagrant SSH tunnel"
exit 0
;;
esac
}
# Check for valid PRIVATE_KEY location
PRIVATE_KEY="$(find .vagrant -name "private_key" 2>/dev/null)"
if ! ssh-keygen -l -f "$PRIVATE_KEY" &>/dev/null; then
echo "[ERROR]: The SSH key '$PRIVATE_KEY' is not valid. Is your virtual machine running?"
exit 1
fi
echo "[CHECK]: Valid key at $PRIVATE_KEY"
# Grab first IP or use whatever HOST_IP_FIELD is set to and check that the guest is up
HOST_IP="$(vagrant ssh -c "hostname -I | cut -d' ' -f${HOST_IP_FIELD:-1}" 2>/dev/null)"
HOST_IP="${HOST_IP::-1}" # trim
if ! ping -c 1 "$HOST_IP" &>/dev/null; then
echo "[ERROR]: Cannot ping the host IP '$HOST_IP'"
exit 1
fi
echo "[CHECK]: Host at $HOST_IP is up"
# Pattern for matching processes running
MATCH_PATTERN="ssh -fNT -i ${PRIVATE_KEY}.*vagrant@"
# Check amount of processes that match the pattern
if [ "$(pgrep -afc "$MATCH_PATTERN")" -eq 0 ]; then
ssh_connect
else
# Processes found, so prompt to kill remaining ones then start tunnel
printf "\n[WARNING]: Found processes running:\n"
pgrep -fa "$MATCH_PATTERN"
printf '\n'
read -rp "Would you like to kill these processes? [y/N] " PKILL_ANSWER
echo
case "$PKILL_ANSWER" in
[yY])
echo "[WARNING]: Killing old vagrant SSH tunnel(s): "
pgrep -f "$MATCH_PATTERN" | tee >(xargs kill -15)
echo
if [ "$(pgrep -afc "$MATCH_PATTERN")" -eq 0 ]; then
ssh_connect
else
echo "[ERROR]: Unable to kill processes:"
pgrep -f "$MATCH_PATTERN"
exit 1
fi
;;
*)
echo "[INFO]: Declined to kill existing processes"
exit 0
;;
esac
fi

7
playbooks/docker.yml Normal file
View File

@@ -0,0 +1,7 @@
- name: Install Docker Server
hosts: "{{ PLAYBOOK_HOST | default('none') }}"
become: true
roles:
- base
- jenkins
- docker

11
playbooks/dockerbox.yml Normal file
View File

@@ -0,0 +1,11 @@
- name: Install Dockerbox Server
hosts: "{{ PLAYBOOK_HOST | default('none') }}"
become: true
roles:
- base
- docker
- traefik
- nextcloud
- jenkins
- prometheus
- nginx

View File

@@ -1,8 +1,9 @@
- name: Install Media Server - name: Install Media Server
hosts: mediaservers hosts: "{{ PLAYBOOK_HOST | default('none') }}"
become: true become: true
roles: roles:
- base - base
- jenkins
- proxy - proxy
- docker - docker
- traefik - traefik

View File

@@ -1,6 +1,8 @@
allow_reboot: true
manage_firewall: true
manage_network: false manage_network: false
network_type: static network_type: static
allow_reboot: true locale_default: en_US.UTF-8
packages: packages:
- apache2-utils - apache2-utils

View File

@@ -5,6 +5,10 @@
listen: reboot_host listen: reboot_host
when: allow_reboot when: allow_reboot
- name: Reconfigure locales
ansible.builtin.command: dpkg-reconfigure -f noninteractive locales
listen: reconfigure_locales
- name: Restart WireGuard - name: Restart WireGuard
ansible.builtin.service: ansible.builtin.service:
name: wg-quick@wg0 name: wg-quick@wg0
@@ -22,3 +26,9 @@
name: ddclient name: ddclient
state: restarted state: restarted
listen: restart_ddclient listen: restart_ddclient
- name: Restart Samba
ansible.builtin.service:
name: smbd
state: restarted
listen: restart_samba

View File

@@ -1,23 +1,5 @@
- name: 'Install Ansible dependency: python3-apt'
ansible.builtin.shell: 'apt-get update && apt-get install python3-apt -y'
args:
creates: /usr/lib/python3/dist-packages/apt
warn: false
- name: Install additional Ansible dependencies
ansible.builtin.apt:
name: "{{ item }}"
state: present
force_apt_get: true
update_cache: true
loop:
- aptitude
- python3-docker
- python3-pymysql
- python3-psycopg2
- name: Create Ansible's temporary remote directory - name: Create Ansible's temporary remote directory
ansible.builtin.file: ansible.builtin.file:
path: "~/.ansible/tmp" path: "~/.ansible/tmp"
state: directory state: directory
mode: 0700 mode: "700"

View File

@@ -7,7 +7,7 @@
ansible.builtin.template: ansible.builtin.template:
src: ddclient.conf.j2 src: ddclient.conf.j2
dest: /etc/ddclient.conf dest: /etc/ddclient.conf
mode: 0600 mode: "600"
register: ddclient_settings register: ddclient_settings
- name: Start ddclient and enable on boot - name: Start ddclient and enable on boot

View File

@@ -32,14 +32,14 @@
ansible.builtin.template: ansible.builtin.template:
src: fail2ban-ssh.conf.j2 src: fail2ban-ssh.conf.j2
dest: /etc/fail2ban/jail.d/sshd.conf dest: /etc/fail2ban/jail.d/sshd.conf
mode: 0640 mode: "640"
notify: restart_fail2ban notify: restart_fail2ban
- name: Install Fail2ban IP allow list - name: Install Fail2ban IP allow list
ansible.builtin.template: ansible.builtin.template:
src: fail2ban-allowlist.conf.j2 src: fail2ban-allowlist.conf.j2
dest: /etc/fail2ban/jail.d/allowlist.conf dest: /etc/fail2ban/jail.d/allowlist.conf
mode: 0640 mode: "640"
when: fail2ban_ignoreip is defined when: fail2ban_ignoreip is defined
notify: restart_fail2ban notify: restart_fail2ban

View File

@@ -11,10 +11,10 @@
ansible.builtin.template: ansible.builtin.template:
src: msmtprc.j2 src: msmtprc.j2
dest: /root/.msmtprc dest: /root/.msmtprc
mode: 0600 mode: "600"
- name: Install /etc/aliases - name: Install /etc/aliases
ansible.builtin.copy: ansible.builtin.copy:
dest: /etc/aliases dest: /etc/aliases
content: "root: {{ mail.rootalias }}" content: "root: {{ mail.rootalias }}"
mode: 0644 mode: "644"

View File

@@ -9,6 +9,7 @@
- name: Import Firewall tasks - name: Import Firewall tasks
ansible.builtin.import_tasks: firewall.yml ansible.builtin.import_tasks: firewall.yml
tags: firewall tags: firewall
when: manage_firewall
- name: Import Network tasks - name: Import Network tasks
ansible.builtin.import_tasks: network.yml ansible.builtin.import_tasks: network.yml
@@ -29,3 +30,8 @@
ansible.builtin.import_tasks: wireguard.yml ansible.builtin.import_tasks: wireguard.yml
tags: wireguard tags: wireguard
when: wireguard is defined when: wireguard is defined
- name: Import Samba tasks
ansible.builtin.import_tasks: samba.yml
tags: samba
when: samba is defined

View File

@@ -10,6 +10,6 @@
ansible.builtin.template: ansible.builtin.template:
src: "interface.j2" src: "interface.j2"
dest: "/etc/network/interfaces.d/{{ item.name }}" dest: "/etc/network/interfaces.d/{{ item.name }}"
mode: 0400 mode: "400"
loop: "{{ interfaces }}" loop: "{{ interfaces }}"
notify: reboot_host notify: reboot_host

View File

@@ -4,22 +4,43 @@
state: present state: present
- name: Create Samba users - name: Create Samba users
ansible.builtin.command: "smbpasswd -a -s {{ item.name }}" ansible.builtin.command: "smbpasswd -a {{ item.name }}"
args: args:
stdin: "{{ item.password }}\n{{ item.password }}" stdin: "{{ item.password }}\n{{ item.password }}"
loop: "{{ samba.users }}" loop: "{{ samba.users }}"
loop_control:
label: "{{ item.name }}"
register: samba_users register: samba_users
changed_when: "'User added' in samba_users.stdout" changed_when: "'Added user' in samba_users.stdout"
- name: Ensure share directories exist - name: Ensure share directories exist
ansible.builtin.file: ansible.builtin.file:
path: "{{ item.path }}" path: "{{ item.path }}"
owner: "{{ item.owner }}"
group: "{{ item.group }}"
state: directory state: directory
mode: 0755 mode: "755"
loop: "{{ samba.shares }}" loop: "{{ samba.shares }}"
- name: Configure Samba shares - name: Configure Samba shares
ansible.builtin.template: ansible.builtin.template:
src: smb.conf.j2 src: smb.conf.j2
dest: /etc/samba/smb.conf dest: /etc/samba/smb.conf
notify: samba_restart mode: "700"
notify: restart_samba
- name: Start smbd and enable on boot
ansible.builtin.service:
name: smbd
state: started
enabled: true
- name: Allow SMB connections
community.general.ufw:
rule: allow
port: 445
proto: tcp
from: "{{ item }}"
state: enabled
loop: "{{ samba.firewall }}"
when: manage_firewall

View File

@@ -4,13 +4,100 @@
state: present state: present
update_cache: true update_cache: true
- name: Install GPG
ansible.builtin.apt:
name: gpg
state: present
- name: Check for existing GPG keys
ansible.builtin.command: "gpg --list-keys {{ item.id }} 2>/dev/null"
register: gpg_check
loop: "{{ root_gpgkeys }}"
failed_when: false
changed_when: false
when: root_gpgkeys is defined
- name: Import GPG keys
ansible.builtin.command:
"gpg --keyserver {{ item.item.server | default('keys.openpgp.org') }} --recv-key {{ item.item.id }}"
register: gpg_check_import
loop: "{{ gpg_check.results }}"
loop_control:
label: "{{ item.item }}"
changed_when: false
when: root_gpgkeys is defined and item.rc != 0
- name: Check GPG key imports
ansible.builtin.fail:
msg: "{{ item.stderr }}"
loop: "{{ gpg_check_import.results }}"
loop_control:
label: "{{ item.item.item }}"
when: root_gpgkeys is defined and (not item.skipped | default(false)) and ('imported' not in item.stderr)
- name: Install NTPsec
ansible.builtin.apt:
name: ntpsec
state: present
- name: Install locales
ansible.builtin.apt:
name: locales
state: present
- name: Generate locale
community.general.locale_gen:
name: "{{ locale_default }}"
state: present
notify: reconfigure_locales
- name: Set the default locale
ansible.builtin.lineinfile:
path: /etc/default/locale
regexp: "^LANG="
line: "LANG={{ locale_default }}"
- name: Manage root authorized_keys - name: Manage root authorized_keys
ansible.builtin.template: ansible.builtin.template:
src: authorized_keys.j2 src: authorized_keys.j2
dest: /root/.ssh/authorized_keys dest: /root/.ssh/authorized_keys
mode: 0400 mode: "400"
when: authorized_keys is defined when: authorized_keys is defined
- 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 }}"
shell: "{{ item.value.shell | default('/bin/bash') }}"
create_home: "{{ item.value.home | default(false) }}"
system: "{{ item.value.system | default(false) }}"
loop: "{{ users | dict2items }}"
loop_control:
label: "{{ item.key }}"
when: users is defined
- name: Set authorized_keys for system users
ansible.posix.authorized_key:
user: "{{ item.key }}"
key: "{{ item.value.key }}"
state: present
loop: "{{ users | dict2items }}"
loop_control:
label: "{{ item.key }}"
when: users is defined and item.value.key is defined
- name: Manage filesystem mounts - name: Manage filesystem mounts
ansible.posix.mount: ansible.posix.mount:
path: "{{ item.path }}" path: "{{ item.path }}"

View File

@@ -11,6 +11,7 @@
args: args:
chdir: /etc/wireguard/ chdir: /etc/wireguard/
creates: /etc/wireguard/privatekey creates: /etc/wireguard/privatekey
executable: /usr/bin/bash
- name: Grab WireGuard private key for configuration - name: Grab WireGuard private key for configuration
ansible.builtin.slurp: ansible.builtin.slurp:
@@ -21,7 +22,7 @@
ansible.builtin.template: ansible.builtin.template:
src: wireguard.j2 src: wireguard.j2
dest: /etc/wireguard/wg0.conf dest: /etc/wireguard/wg0.conf
mode: 0400 mode: "400"
notify: restart_wireguard notify: restart_wireguard
- name: Start WireGuard interface - name: Start WireGuard interface
@@ -34,5 +35,5 @@
community.general.ufw: community.general.ufw:
rule: allow rule: allow
port: "{{ wireguard.listenport }}" port: "{{ wireguard.listenport }}"
proto: tcp proto: udp
when: wireguard.listenport is defined when: wireguard.listenport is defined

View File

@@ -13,7 +13,16 @@
[{{ share.name }}] [{{ share.name }}]
path = {{ share.path }} path = {{ share.path }}
browsable = yes browsable = yes
{% if share.guest_allow is defined and share.guest_allow %}
guest ok = yes
{% else %}
guest ok = no guest ok = no
{% endif %}
read only = {{ 'yes' if share.read_only | default(false) else 'no' }} read only = {{ 'yes' if share.read_only | default(false) else 'no' }}
{% if share.valid_users is defined %}
valid users = {{ share.valid_users }} valid users = {{ share.valid_users }}
{% endif %}
{% if share.force_user is defined %}
force user = {{ share.force_user }}
{% endif %}
{% endfor %} {% endfor %}

View File

@@ -26,18 +26,18 @@
args: args:
creates: "{{ bitwarden_root }}/bwdata/config.yml" creates: "{{ bitwarden_root }}/bwdata/config.yml"
- name: Install docker-compose override - name: Install compose override
ansible.builtin.template: ansible.builtin.template:
src: compose.override.yml.j2 src: compose.override.yml.j2
dest: "{{ bitwarden_root }}/bwdata/docker/docker-compose.override.yml" dest: "{{ bitwarden_root }}/bwdata/docker/docker-compose.override.yml"
when: traefik_version is defined when: bitwarden_override | default(true)
notify: rebuild_bitwarden notify: rebuild_bitwarden
- name: Disable bitwarden-nginx HTTP on 80 - name: Disable bitwarden-nginx HTTP on 80
ansible.builtin.replace: ansible.builtin.replace:
path: "{{ bitwarden_root }}/bwdata/config.yml" path: "{{ bitwarden_root }}/bwdata/config.yml"
regexp: "^http_port: 80$" regexp: "^http_port: 80$"
replace: "http_port: 127.0.0.1:8080" replace: "http_port: {{ bitwarden_http_port | default('127.0.0.1:9080') }}"
when: not bitwarden_standalone when: not bitwarden_standalone
notify: rebuild_bitwarden notify: rebuild_bitwarden
@@ -45,7 +45,7 @@
ansible.builtin.replace: ansible.builtin.replace:
path: "{{ bitwarden_root }}/bwdata/config.yml" path: "{{ bitwarden_root }}/bwdata/config.yml"
regexp: "^https_port: 443$" regexp: "^https_port: 443$"
replace: "https_port: 127.0.0.1:8443" replace: "https_port: {{ bitwarden_https_port | default('127.0.0.1:9443') }}"
when: not bitwarden_standalone when: not bitwarden_standalone
notify: rebuild_bitwarden notify: rebuild_bitwarden

View File

@@ -23,10 +23,13 @@ send "{{ bitwarden_install_id }}\r"
expect "Enter your installation key:" expect "Enter your installation key:"
send "{{ bitwarden_install_key }}\r" send "{{ bitwarden_install_key }}\r"
expect "Do you have a SSL certificate to use? (y/n):" expect "Enter your region (US/EU) \\\[US\\\]:"
send "US\r"
expect "Do you have a SSL certificate to use? (y/N):"
send "n\r" send "n\r"
expect "Do you want to generate a self-signed SSL certificate? (y/n):" expect "Do you want to generate a self-signed SSL certificate? (y/N):"
{% if bitwarden_standalone and not bitwarden_production %} {% if bitwarden_standalone and not bitwarden_production %}
send "y\r" send "y\r"
{% else %} {% else %}

View File

@@ -6,13 +6,11 @@ services:
- traefik - traefik
labels: labels:
traefik.http.routers.bitwarden.rule: "Host(`{{ bitwarden_domain }}`)" traefik.http.routers.bitwarden.rule: "Host(`{{ bitwarden_domain }}`)"
traefik.http.routers.bitwarden.entrypoints: websecure traefik.http.routers.bitwarden.entrypoints: {{ bitwarden_entrypoint | default('web') }}
traefik.http.routers.bitwarden.tls.certresolver: letsencrypt traefik.http.routers.bitwarden.tls: {{ bitwarden_traefik_tls | default('false') }}
traefik.http.routers.bitwarden.middlewares: "securehttps@file"
traefik.http.services.bitwarden.loadbalancer.server.port: 8080 traefik.http.services.bitwarden.loadbalancer.server.port: 8080
traefik.docker.network: traefik traefik.docker.network: traefik
traefik.enable: "true" traefik.enable: "true"
networks: networks:
traefik: traefik:
external: true external: true

View File

@@ -1,3 +1,11 @@
docker_apt_keyring: /etc/apt/keyrings/docker.asc
docker_apt_keyring_hash: 1500c1f56fa9e26b9b8f42452a553675796ade0807cdce11975eb98170b3a570
docker_apt_keyring_url: https://download.docker.com/linux/debian/gpg
docker_apt_repo: https://download.docker.com/linux/debian
docker_compose_root: /var/lib/compose docker_compose_root: /var/lib/compose
docker_compose: /usr/bin/docker-compose
docker_compose_service: compose docker_compose_service: compose
docker_compose: "{{ (docker_official | bool) | ternary('/usr/bin/docker compose', '/usr/bin/docker-compose') }}"
docker_official: false
docker_repos_keys: "{{ docker_repos_path }}/.keys"
docker_repos_keytype: rsa
docker_repos_path: /srv/.compose_repos

View File

@@ -2,3 +2,53 @@
ansible.builtin.systemd: ansible.builtin.systemd:
daemon_reload: true daemon_reload: true
listen: compose_systemd listen: compose_systemd
- name: Find which services had a docker-compose.yml updated
ansible.builtin.set_fact:
compose_restart_list: "{{ (compose_restart_list | default([])) + [item.item.name] }}"
loop: "{{ compose_update.results }}"
loop_control:
label: "{{ item.item.name }}"
when: item.changed
listen: compose_restart
- name: Find which services had their .env updated
ansible.builtin.set_fact:
compose_restart_list: "{{ (compose_restart_list | default([])) + [item.item.name] }}"
loop: "{{ compose_env_update.results }}"
loop_control:
label: "{{ item.item.name }}"
when: item.changed
listen: compose_restart
- name: Restart MariaDB
ansible.builtin.service:
name: mariadb
state: restarted
when: not mariadb_restarted
listen: restart_mariadb # hijack handler for early restart
- name: Set MariaDB as restarted
ansible.builtin.set_fact:
mariadb_restarted: true
when: not mariadb_restarted
listen: restart_mariadb
- name: Restart compose services
ansible.builtin.systemd:
state: restarted
name: "{{ docker_compose_service }}@{{ item }}"
loop: "{{ compose_restart_list | default([]) | unique }}"
when: compose_restart_list is defined
listen: compose_restart
- name: Start compose services and enable on boot
ansible.builtin.service:
name: "{{ docker_compose_service }}@{{ item.name }}"
state: started
enabled: true
loop: "{{ docker_compose_deploy }}"
loop_control:
label: "{{ docker_compose_service }}@{{ item.name }}"
when: item.enabled is defined and item.enabled is true
listen: compose_enable

View File

@@ -1,22 +1,140 @@
- name: Install Docker - name: Add official Docker APT key
ansible.builtin.get_url:
url: "{{ docker_apt_keyring_url }}"
dest: "{{ docker_apt_keyring }}"
checksum: "sha256:{{ docker_apt_keyring_hash }}"
mode: "644"
owner: root
group: root
when: docker_official
- name: Remove official Docker APT key
ansible.builtin.file:
path: "{{ docker_apt_keyring }}"
state: absent
when: not docker_official
- name: Add/remove official Docker APT repository
ansible.builtin.apt_repository:
repo: >
deb [arch=amd64 signed-by={{ docker_apt_keyring }}]
{{ docker_apt_repo }} {{ ansible_distribution_release }} stable
state: "{{ 'present' if docker_official else 'absent' }}"
filename: "{{ docker_apt_keyring | regex_replace('^.*/', '') }}"
- name: Install/uninstall Docker from Debian repositories
ansible.builtin.apt: ansible.builtin.apt:
name: ['docker.io', 'docker-compose'] name: ['docker.io', 'docker-compose', 'containerd', 'runc']
state: present state: "{{ 'absent' if docker_official else 'present' }}"
autoremove: true
update_cache: true update_cache: true
- name: Install/uninstall Docker from Docker repositories
ansible.builtin.apt:
name: ['docker-ce', 'docker-ce-cli', 'containerd.io',
'docker-buildx-plugin', 'docker-compose-plugin']
state: "{{ 'present' if docker_official else 'absent' }}"
autoremove: true
update_cache: true
- name: Login to private registry
community.docker.docker_login:
registry_url: "{{ docker_login_url | default('') }}"
username: "{{ docker_login_user }}"
password: "{{ docker_login_pass }}"
when: docker_login_user is defined and docker_login_pass is defined
- name: Create docker-compose root - name: Create docker-compose root
ansible.builtin.file: ansible.builtin.file:
path: "{{ docker_compose_root }}" path: "{{ docker_compose_root }}"
state: directory state: directory
mode: 0500 mode: "500"
- name: Install docker-compose systemd service - name: Install docker-compose systemd service
ansible.builtin.template: ansible.builtin.template:
src: docker-compose.service.j2 src: docker-compose.service.j2
dest: "/etc/systemd/system/{{ docker_compose_service }}@.service" dest: "/etc/systemd/system/{{ docker_compose_service }}@.service"
mode: 0400 mode: "400"
notify: compose_systemd notify: compose_systemd
- name: Create directories to clone docker-compose repositories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "400"
loop:
- "{{ docker_repos_path }}"
- "{{ docker_repos_keys }}"
when: docker_compose_deploy is defined
- name: Generate OpenSSH deploy keys for docker-compose clones
community.crypto.openssh_keypair:
path: "{{ docker_repos_keys }}/id_{{ docker_repos_keytype }}"
type: "{{ docker_repos_keytype }}"
comment: "{{ ansible_hostname }}-deploy-key"
mode: "400"
state: present
when: docker_compose_deploy is defined
- name: Check for git installation
ansible.builtin.apt:
name: git
state: present
when: docker_compose_deploy is defined
- name: Clone external docker-compose projects
ansible.builtin.git:
repo: "{{ item.url }}"
dest: "{{ docker_repos_path }}/{{ item.name }}"
version: "{{ item.version }}"
accept_newhostkey: "{{ item.accept_newhostkey | default(false) }}"
gpg_whitelist: "{{ item.trusted_keys | default([]) }}"
verify_commit: "{{ true if (item.trusted_keys is defined and item.trusted_keys) else false }}"
key_file: "{{ docker_repos_keys }}/id_{{ docker_repos_keytype }}"
loop: "{{ docker_compose_deploy }}"
loop_control:
label: "{{ item.url }}"
when: docker_compose_deploy is defined
- name: Create directories for docker-compose projects using the systemd service
ansible.builtin.file:
path: "{{ docker_compose_root }}/{{ item.name }}"
state: directory
mode: "400"
loop: "{{ docker_compose_deploy }}"
loop_control:
label: "{{ item.name }}"
when: docker_compose_deploy is defined
- name: Synchronize docker-compose.yml
ansible.posix.synchronize:
src: "{{ docker_repos_path }}/{{ item.name }}/{{ item.path | default('docker-compose.yml') }}"
dest: "{{ docker_compose_root }}/{{ item.name }}/docker-compose.yml"
delegate_to: "{{ inventory_hostname }}"
register: compose_update
notify:
- compose_restart
- compose_enable
loop: "{{ docker_compose_deploy | default([]) }}"
loop_control:
label: "{{ item.name }}"
when: docker_compose_deploy is defined and docker_compose_deploy | length > 0
- name: Set environment variables for docker-compose projects
ansible.builtin.template:
src: docker-compose-env.j2
dest: "{{ docker_compose_root }}/{{ item.name }}/.env"
mode: "400"
register: compose_env_update
notify:
- compose_restart
- compose_enable
no_log: "{{ docker_compose_env_nolog | default(true) }}"
loop: "{{ docker_compose_deploy }}"
loop_control:
label: "{{ item.name }}"
when: docker_compose_deploy is defined and item.env is defined
- name: Add users to docker group - name: Add users to docker group
ansible.builtin.user: ansible.builtin.user:
name: "{{ item }}" name: "{{ item }}"
@@ -30,3 +148,4 @@
name: docker name: docker
state: started state: started
enabled: true enabled: true
when: docker_managed | default(true)

View File

@@ -0,0 +1,10 @@
# {{ ansible_managed }}
{% if item.env is defined %}
{% for key, value in item.env.items() %}
{% if value is boolean %}
{{ key }}={{ value | lower }}
{% else %}
{{ key }}={{ value }}
{% endif %}
{% endfor %}
{% endif %}

View File

@@ -1,5 +1,5 @@
[Unit] [Unit]
Description=%i docker-compose service Description=%i {{ docker_compose_service }} service
PartOf=docker.service PartOf=docker.service
After=docker.service After=docker.service

View File

@@ -1,38 +1,23 @@
- name: Create Gitea directory - name: Install MySQL module for Ansible
ansible.builtin.file: ansible.builtin.apt:
path: "{{ gitea_root }}" name: python3-pymysql
state: directory state: present
- name: Create Gitea database - name: Create Gitea database
community.mysql.mysql_db: community.mysql.mysql_db:
name: "{{ gitea_dbname }}" name: "{{ gitea.DB_NAME }}"
state: present state: present
login_unix_socket: /var/run/mysqld/mysqld.sock login_unix_socket: /var/run/mysqld/mysqld.sock
- name: Create Gitea database user - name: Create Gitea database user
community.mysql.mysql_user: community.mysql.mysql_user:
name: "{{ gitea_dbuser }}" name: "{{ gitea.DB_USER }}"
password: "{{ gitea_dbpass }}" password: "{{ gitea.DB_PASSWD }}"
host: '%' host: '%'
state: present state: present
priv: "{{ gitea_dbname }}.*:ALL" priv: "{{ gitea.DB_NAME }}.*:ALL"
login_unix_socket: /var/run/mysqld/mysqld.sock login_unix_socket: /var/run/mysqld/mysqld.sock
- name: Create git user
ansible.builtin.user:
name: git
state: present
- name: Git user uid
ansible.builtin.getent:
database: passwd
key: git
- name: Git user gid
ansible.builtin.getent:
database: group
key: git
- name: Create git's .ssh directory - name: Create git's .ssh directory
ansible.builtin.file: ansible.builtin.file:
path: /home/git/.ssh path: /home/git/.ssh
@@ -70,28 +55,11 @@
dest: /usr/local/bin/gitea dest: /usr/local/bin/gitea
mode: 0755 mode: 0755
- name: Install Gitea's docker-compose file
ansible.builtin.template:
src: docker-compose.yml.j2
dest: "{{ gitea_root }}/docker-compose.yml"
notify: restart_gitea
- name: Install Gitea's docker-compose variables
ansible.builtin.template:
src: compose-env.j2
dest: "{{ gitea_root }}/.env"
notify: restart_gitea
- name: Create Gitea's logging directory - name: Create Gitea's logging directory
ansible.builtin.file: ansible.builtin.file:
name: /var/log/gitea name: /var/log/gitea
state: directory state: directory
- name: Create Gitea's initial log file
ansible.builtin.file:
name: /var/log/gitea/gitea.log
state: touch
- name: Install Gitea's Fail2ban filter - name: Install Gitea's Fail2ban filter
ansible.builtin.template: ansible.builtin.template:
src: fail2ban-filter.conf.j2 src: fail2ban-filter.conf.j2
@@ -103,9 +71,3 @@
src: fail2ban-jail.conf.j2 src: fail2ban-jail.conf.j2
dest: /etc/fail2ban/jail.d/gitea.conf dest: /etc/fail2ban/jail.d/gitea.conf
notify: restart_fail2ban notify: restart_fail2ban
- name: Start and enable Gitea service
ansible.builtin.service:
name: "{{ docker_compose_service }}@{{ gitea_name }}"
state: started
enabled: true

View File

@@ -1,5 +1,4 @@
jellyfin_name: jellyfin jellyfin_name: jellyfin
jellyfin_volume: "{{ jellyfin_name }}"
jellyfin_router: "{{ jellyfin_name }}" jellyfin_router: "{{ jellyfin_name }}"
jellyfin_rooturl: "https://{{ jellyfin_domain }}" jellyfin_rooturl: "https://{{ jellyfin_domain }}"
jellyfin_root: "{{ docker_compose_root }}/{{ jellyfin_name }}" jellyfin_root: "{{ docker_compose_root }}/{{ jellyfin_name }}"

View File

@@ -4,11 +4,6 @@
state: directory state: directory
mode: 0500 mode: 0500
- name: Create jellyfin user
ansible.builtin.user:
name: jellyfin
state: present
- name: Get user jellyfin uid - name: Get user jellyfin uid
ansible.builtin.getent: ansible.builtin.getent:
database: passwd database: passwd

View File

@@ -1,7 +1,8 @@
version: '3.7' version: '3.7'
volumes: volumes:
{{ jellyfin_volume }}: config:
cache:
networks: networks:
traefik: traefik:
@@ -24,6 +25,6 @@ services:
- "traefik.docker.network=traefik" - "traefik.docker.network=traefik"
- "traefik.enable=true" - "traefik.enable=true"
volumes: volumes:
- ./config:/config - config:/config
- ./cache:/cache - cache:/cache
- {{ jellyfin_volume }}:/media - {{ jellyfin_media }}:/media

View File

@@ -1,3 +0,0 @@
mariadb_trust:
- "172.16.0.0/12"
- "192.168.0.0/16"

View File

@@ -0,0 +1,12 @@
- name: Restart MariaDB
ansible.builtin.service:
name: mariadb
state: restarted
when: not mariadb_restarted
listen: restart_mariadb
- name: Set MariaDB as restarted
set_fact:
mariadb_restarted: true
when: not mariadb_restarted
listen: restart_mariadb

View File

@@ -3,23 +3,24 @@
name: mariadb-server name: mariadb-server
state: present state: present
- name: Change the bind-address to allow Docker - name: Set MariaDB restarted fact
set_fact:
mariadb_restarted: false
- name: Regather facts for the potentially new docker0 interface
ansible.builtin.setup:
- name: Change the bind-address to allow from docker0
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
path: /etc/mysql/mariadb.conf.d/50-server.cnf path: /etc/mysql/mariadb.conf.d/50-server.cnf
regex: "^bind-address" regex: "^bind-address"
line: "bind-address = 0.0.0.0" line: "bind-address = {{ ansible_facts.docker0.ipv4.address }}"
register: mariadb_conf notify: restart_mariadb
- name: Restart MariaDB - name: Allow database connections from Docker
ansible.builtin.service:
name: mariadb
state: restarted
when: mariadb_conf.changed
- name: Allow database connections
community.general.ufw: community.general.ufw:
rule: allow rule: allow
port: "3306" port: "3306"
proto: tcp proto: tcp
src: "{{ item }}" src: "{{ item }}"
loop: "{{ mariadb_trust }}" loop: "{{ mariadb_trust | default(['172.16.0.0/12']) }}"

View File

@@ -29,6 +29,8 @@
networks: networks:
- name: "{{ nextcloud_container }}" - name: "{{ nextcloud_container }}"
- name: traefik - name: traefik
env:
PHP_MEMORY_LIMIT: 1024M
labels: labels:
traefik.http.routers.nextcloud.rule: "Host(`{{ nextcloud_domain }}`)" traefik.http.routers.nextcloud.rule: "Host(`{{ nextcloud_domain }}`)"
traefik.http.routers.nextcloud.entrypoints: websecure traefik.http.routers.nextcloud.entrypoints: websecure
@@ -103,6 +105,13 @@
- "php occ maintenance:mode --off" - "php occ maintenance:mode --off"
when: nextcloud_install.changed 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 nextcloud /usr/local/bin/php -f /var/www/html/cron.php"
user: root
- name: Remove Nextcloud's CAN_INSTALL file - name: Remove Nextcloud's CAN_INSTALL file
ansible.builtin.file: ansible.builtin.file:
path: "{{ nextcloud_root }}/config/CAN_INSTALL" path: "{{ nextcloud_root }}/config/CAN_INSTALL"

View File

@@ -19,14 +19,14 @@
ansible.builtin.template: ansible.builtin.template:
src: nginx.conf.j2 src: nginx.conf.j2
dest: /etc/nginx/nginx.conf dest: /etc/nginx/nginx.conf
mode: '0644' mode: 0644
notify: reload_nginx notify: reload_nginx
- name: Install nginx sites configuration - name: Install nginx sites configuration
ansible.builtin.template: ansible.builtin.template:
src: server-nginx.conf.j2 src: server-nginx.conf.j2
dest: "/etc/nginx/sites-available/{{ item.domain }}.conf" dest: "/etc/nginx/sites-available/{{ item.domain }}.conf"
mode: '0644' mode: 0400
loop: "{{ proxy.servers }}" loop: "{{ proxy.servers }}"
notify: reload_nginx notify: reload_nginx
register: nginx_sites register: nginx_sites

View File

@@ -1,42 +0,0 @@
#!/bin/bash
COMMENT="Project Moxie"
DOMAIN="vm.krislamo.org"
HOST[0]="traefik.${DOMAIN}"
HOST[1]="cloud.${DOMAIN}"
HOST[2]="git.${DOMAIN}"
HOST[3]="jenkins.${DOMAIN}"
HOST[4]="prom.${DOMAIN}"
HOST[5]="grafana.${DOMAIN}"
HOST[6]="nginx.${DOMAIN}"
HOST[7]="vault.${DOMAIN}"
HOST[8]="wordpress.${DOMAIN}"
HOST[9]="site1.wordpress.${DOMAIN}"
HOST[10]="site2.wordpress.${DOMAIN}"
HOST[11]="unifi.${DOMAIN}"
HOST[12]="jellyfin.${DOMAIN}"
# Get Vagrantbox guest IP
VAGRANT_OUTPUT=$(vagrant ssh -c "hostname -I | cut -d' ' -f2" 2>/dev/null)
# Remove ^M from the end
[ ${#VAGRANT_OUTPUT} -gt 1 ] && IP=${VAGRANT_OUTPUT::-1}
echo "Purging project addresses from /etc/hosts"
sudo sed -i "s/# $COMMENT//g" /etc/hosts
for address in "${HOST[@]}"; do
sudo sed -i "/$address/d" /etc/hosts
done
# Remove trailing newline
sudo sed -i '${/^$/d}' /etc/hosts
if [ -n "$IP" ]; then
echo -e "Adding new addresses...\n"
echo -e "# $COMMENT" | sudo tee -a /etc/hosts
for address in "${HOST[@]}"; do
echo -e "$IP\t$address" | sudo tee -a /etc/hosts
done
else
echo "Cannot find address. Is the Vagrant box running?"
fi