1 Commits

Author SHA1 Message Date
533dd40722 Upgrade Nextcloud setup to use compose files
- Integrated MariaDB role into Dockerbox configuration
- Moved proxy role to the end to avoid early endpoint activation
- Temporarily disabled select roles for future re-evaluation
- Introduced flush_handlers task for early MariaDB restart
- Moved a few Nextcloud tasks to handlers
- Configured Nextcloud to utilize the host's MariaDB instance
- Enhanced overall code linting quality
2024-04-21 21:45:33 -04:00
20 changed files with 50 additions and 222 deletions

View File

@@ -3,9 +3,8 @@ name: homelab-ci
on:
push:
branches:
- github_actions
# - main
# - testing
- main
- testing
jobs:
homelab-ci:

3
.gitignore vendored
View File

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

View File

@@ -4,12 +4,8 @@ manage_network: false
# Import my GPG key for git signature verification
root_gpgkeys:
- name: kris@lamoureux.io
id: 42A3A92C5DA0F3E5F71A3710105B748C1362EB96
# Older key, but still in use
- name: kris@lamoureux.io
id: FBF673CEEC030F8AECA814E73EDA9C3441EDA925
server: keyserver.ubuntu.com
# proxy
proxy:
@@ -37,7 +33,7 @@ docker_compose_deploy:
# Nextcloud
- name: nextcloud
url: https://github.com/krislamo/nextcloud
version: fe6d349749f178e91ae7ff726d557f48ebf84356
version: 0abc5cc6ba64ed94b7ddc6fd934f0fd62b8a6d11
env:
DATA: ./data

View File

@@ -1,14 +0,0 @@
# base
allow_reboot: false
manage_network: false
users:
kris:
uid: 1001
gid: 1001
home: true
# podman
user_namespaces:
- kris

View File

@@ -1,8 +0,0 @@
- name: Install Podman server
hosts: all
become: true
vars_files:
- host_vars/podman.yml
roles:
- base
- podman

View File

@@ -4,5 +4,4 @@
roles:
- base
- jenkins
- proxy
- docker

View File

@@ -3,9 +3,9 @@
become: true
roles:
- base
- jenkins
- docker
- mariadb
- traefik
- nextcloud
- proxy
- jenkins
- prometheus
- nginx

View File

@@ -26,7 +26,7 @@
ansible.builtin.template:
src: smb.conf.j2
dest: /etc/samba/smb.conf
mode: "644"
mode: "700"
notify: restart_samba
- name: Start smbd and enable on boot

View File

@@ -80,10 +80,8 @@
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:

View File

@@ -18,28 +18,6 @@
src: /etc/wireguard/privatekey
register: wgkey
- name: Check if WireGuard preshared key file exists
ansible.builtin.stat:
path: /etc/wireguard/presharedkey-{{ item.name }}
loop: "{{ wireguard.peers }}"
loop_control:
label: "{{ item.name }}"
register: presharedkey_files
- name: Grab WireGuard preshared key for configuration
ansible.builtin.slurp:
src: /etc/wireguard/presharedkey-{{ item.item.name }}
register: wgshared
loop: "{{ presharedkey_files.results }}"
loop_control:
label: "{{ item.item.name }}"
when: item.stat.exists
- name: Grab WireGuard private key for configuration
ansible.builtin.slurp:
src: /etc/wireguard/privatekey
register: wgkey
- name: Install WireGuard configuration
ansible.builtin.template:
src: wireguard.j2

View File

@@ -1,6 +1,4 @@
# {{ ansible_managed }}
[Interface] # {{ ansible_hostname }}
[Interface]
PrivateKey = {{ wgkey['content'] | b64decode | trim }}
Address = {{ wireguard.address }}
{% if wireguard.listenport is defined %}
@@ -8,26 +6,8 @@ ListenPort = {{ wireguard.listenport }}
{% endif %}
{% for peer in wireguard.peers %}
{% if peer.name is defined %}
[Peer] # {{ peer.name }}
{% else %}
[Peer]
{% endif %}
PublicKey = {{ peer.publickey }}
{% if peer.presharedkey is defined %}
PresharedKey = {{ peer.presharedkey }}
{% else %}
{% set preshared_key = (
wgshared.results
| selectattr('item.item.name', 'equalto', peer.name)
| first
).content
| default(none)
%}
{% if preshared_key is not none %}
PresharedKey = {{ preshared_key | b64decode | trim }}
{% endif %}
{% endif %}
{% if peer.endpoint is defined %}
Endpoint = {{ peer.endpoint }}
{% endif %}

View File

@@ -1,10 +1,7 @@
bitwarden_name: bitwarden
bitwarden_user: bitwarden
bitwarden_root: /home/bitwarden
bitwarden_root: "/var/lib/{{ bitwarden_name }}"
bitwarden_logs_identity: "{{ bitwarden_root }}/bwdata/logs/identity/Identity"
bitwarden_logs_identity_date:
"{{ ansible_date_time.year }}{{ ansible_date_time.month }}{{
ansible_date_time.day }}"
bitwarden_logs_identity_date: "{{ ansible_date_time.year }}{{ ansible_date_time.month }}{{ ansible_date_time.day }}"
bitwarden_database: "{{ bitwarden_name }}"
bitwarden_realips: "172.16.0.0/12"
bitwarden_standalone: false

View File

@@ -3,39 +3,35 @@
name: expect
state: present
- name: Create Bitwarden directory
ansible.builtin.file:
path: "{{ bitwarden_root }}"
state: directory
mode: "755"
- name: Download Bitwarden script
ansible.builtin.get_url:
url: "https://raw.githubusercontent.com/\
bitwarden/self-host/master/bitwarden.sh"
bitwarden/self-host/master/bitwarden.sh"
dest: "{{ bitwarden_root }}"
owner: "{{ bitwarden_user }}"
group: "{{ bitwarden_user }}"
mode: u+x
- name: Install Bitwarden script wrapper
ansible.builtin.template:
src: bw_wrapper.j2
dest: "{{ bitwarden_root }}/bw_wrapper"
owner: "{{ bitwarden_user }}"
group: "{{ bitwarden_user }}"
mode: u+x
- name: Run Bitwarden installation script
ansible.builtin.command: "{{ bitwarden_root }}/bw_wrapper"
args:
creates: "{{ bitwarden_root }}/bwdata/config.yml"
become_user: "{{ bitwarden_user }}"
become: true
- name: Install compose override
ansible.builtin.template:
src: compose.override.yml.j2
dest: "{{ bitwarden_root }}/bwdata/docker/docker-compose.override.yml"
owner: "{{ bitwarden_user }}"
group: "{{ bitwarden_user }}"
mode: "644"
become_user: "{{ bitwarden_user }}"
become: true
when: bitwarden_override | default(true)
notify: rebuild_bitwarden
@@ -44,8 +40,6 @@
path: "{{ bitwarden_root }}/bwdata/config.yml"
regexp: "^http_port: 80$"
replace: "http_port: {{ bitwarden_http_port | default('127.0.0.1:9080') }}"
become_user: "{{ bitwarden_user }}"
become: true
when: not bitwarden_standalone
notify: rebuild_bitwarden
@@ -53,10 +47,7 @@
ansible.builtin.replace:
path: "{{ bitwarden_root }}/bwdata/config.yml"
regexp: "^https_port: 443$"
replace:
"https_port: {{ bitwarden_https_port | default('127.0.0.1:9443') }}"
become_user: "{{ bitwarden_user }}"
become: true
replace: "https_port: {{ bitwarden_https_port | default('127.0.0.1:9443') }}"
when: not bitwarden_standalone
notify: rebuild_bitwarden
@@ -65,8 +56,6 @@
path: "{{ bitwarden_root }}/bwdata/config.yml"
regexp: "^ssl_managed_lets_encrypt: true$"
replace: "ssl_managed_lets_encrypt: false"
become_user: "{{ bitwarden_user }}"
become: true
when: not bitwarden_standalone or not bitwarden_production
notify: rebuild_bitwarden
@@ -75,8 +64,6 @@
path: "{{ bitwarden_root }}/bwdata/config.yml"
regexp: "^ssl: true$"
replace: "ssl: false"
become_user: "{{ bitwarden_user }}"
become: true
when: not bitwarden_standalone
notify: rebuild_bitwarden
@@ -85,16 +72,12 @@
path: "{{ bitwarden_root }}/bwdata/config.yml"
line: "- {{ bitwarden_realips }}"
insertafter: "^real_ips"
become_user: "{{ bitwarden_user }}"
become: true
notify: rebuild_bitwarden
- name: Install Bitwarden systemd service
ansible.builtin.template:
src: bitwarden.service.j2
dest: "/etc/systemd/system/{{ bitwarden_name }}.service"
owner: "{{ bitwarden_user }}"
group: "{{ bitwarden_user }}"
mode: "644"
register: bitwarden_systemd
notify: rebuild_bitwarden
@@ -103,8 +86,6 @@
ansible.builtin.file:
path: "{{ bitwarden_logs_identity }}"
state: directory
owner: "{{ bitwarden_user }}"
group: "{{ bitwarden_user }}"
mode: "755"
notify: touch_bitwarden

View File

@@ -24,21 +24,15 @@
- name: Install/uninstall Docker from Debian repositories
ansible.builtin.apt:
name: ["docker.io", "docker-compose", "containerd", "runc"]
name: ['docker.io', 'docker-compose', 'containerd', 'runc']
state: "{{ 'absent' if docker_official else 'present' }}"
autoremove: 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",
]
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
@@ -141,6 +135,14 @@
label: "{{ item.name }}"
when: docker_compose_deploy is defined and item.env is defined
- name: Add users to docker group
ansible.builtin.user:
name: "{{ item }}"
groups: docker
append: true
loop: "{{ docker_users }}"
when: docker_users is defined
- name: Start Docker and enable on boot
ansible.builtin.service:
name: docker

View File

@@ -15,7 +15,7 @@ services:
networks:
- traefik
labels:
- "traefik.http.routers.{{ jellyfin_router }}.rule=Host({{ jellyfin_domains }})"
- "traefik.http.routers.{{ jellyfin_router }}.rule=Host(`{{ jellyfin_domain }}`)"
{% if traefik_http_only %}
- "traefik.http.routers.{{ jellyfin_router }}.entrypoints=web"
{% else %}

View File

@@ -16,12 +16,10 @@
regex: "^bind-address"
line: "bind-address = {{ ansible_facts.docker0.ipv4.address }}"
notify: restart_mariadb
when: ansible_facts.docker0 is defined
- name: Flush handlers to ensure MariaDB restarts immediately
ansible.builtin.meta: flush_handlers
tags: restart_mariadb
when: ansible_facts.docker0 is defined
- name: Allow database connections from Docker
community.general.ufw:

View File

@@ -1,62 +0,0 @@
- name: Install Podman
ansible.builtin.apt:
name: ["podman", "podman-compose", "podman-docker"]
state: present
- name: Get user info for namespace users
ansible.builtin.getent:
database: passwd
key: "{{ item }}"
loop: "{{ user_namespaces }}"
register: user_info
- name: Configure /etc/subuid for rootless users
ansible.builtin.lineinfile:
path: "/etc/subuid"
line:
"{{ item.item }}:{{ 100000 +
((item.ansible_facts.getent_passwd[item.item][1] | int - 1000) * 65536)
}}:65536"
regexp: "^{{ item.item }}:"
create: true
backup: true
mode: "0644"
loop: "{{ user_info.results }}"
- name: Configure /etc/subgid for rootless users
ansible.builtin.lineinfile:
path: "/etc/subgid"
line:
"{{ item.item }}:{{ 100000 +
((item.ansible_facts.getent_passwd[item.item][1] | int - 1000) * 65536)
}}:65536"
regexp: "^{{ item.item }}:"
create: true
backup: true
mode: "0644"
loop: "{{ user_info.results }}"
- name: Create nodocker file to disable Docker CLI emulation message
ansible.builtin.file:
path: /etc/containers/nodocker
state: touch
owner: root
group: root
mode: "0644"
- name: Create global containers config directory
ansible.builtin.file:
path: /etc/containers
state: directory
mode: "0755"
- name: Configure global containers.conf for rootless
ansible.builtin.copy:
content: |
[engine]
cgroup_manager = "cgroupfs"
events_logger = "journald"
runtime = "crun"
dest: /etc/containers/containers.conf
mode: "0644"
backup: true

View File

@@ -45,11 +45,10 @@
register: nginx_sites
- name: Generate self-signed certificate
ansible.builtin.command:
'openssl req -newkey rsa:4096 -x509 -sha256 -days 3650 -nodes \
-subj "/C=US/ST=Local/L=Local/O=Org/OU=IT/CN=example.com" \
-keyout /etc/ssl/private/nginx-selfsigned.key \
-out /etc/ssl/certs/nginx-selfsigned.crt'
ansible.builtin.command: 'openssl req -newkey rsa:4096 -x509 -sha256 -days 3650 -nodes \
-subj "/C=US/ST=Local/L=Local/O=Org/OU=IT/CN=example.com" \
-keyout /etc/ssl/private/nginx-selfsigned.key \
-out /etc/ssl/certs/nginx-selfsigned.crt'
args:
creates: /etc/ssl/certs/nginx-selfsigned.crt
when: proxy.production is not defined or not proxy.production
@@ -57,22 +56,15 @@
- name: Install LE's certbot
ansible.builtin.apt:
name: ["certbot", "python3-certbot-dns-cloudflare"]
name: ['certbot', 'python3-certbot-dns-cloudflare']
state: present
when: proxy.production is defined and proxy.production
- name: Grab Cloudflare API token for configuration
ansible.builtin.slurp:
src: /root/.cloudflare-api
register: cfapi
when: proxy.production is defined and proxy.production and proxy.dns_cloudflare is defined
- name: Install Cloudflare API token
ansible.builtin.template:
src: cloudflare.ini.j2
dest: /root/.cloudflare.ini
mode: "400"
diff: false
when: proxy.production is defined and proxy.production and proxy.dns_cloudflare is defined
- name: Create nginx post renewal hook directory
@@ -86,19 +78,19 @@
ansible.builtin.copy:
src: reload-nginx.sh
dest: /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh
mode: "0755"
mode: '0755'
when: proxy.production is defined and proxy.production
- name: Run Cloudflare DNS-01 challenges on wildcard domains
ansible.builtin.shell: '/usr/bin/certbot certonly \
--non-interactive \
--agree-tos \
--email "{{ proxy.dns_cloudflare.email }}" \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.cloudflare.ini \
-d "*.{{ item }}" \
-d "{{ item }}" \
{{ proxy.dns_cloudflare.opts | default("") }}'
--non-interactive \
--agree-tos \
--email "{{ proxy.dns_cloudflare.email }}" \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.cloudflare.ini \
-d "*.{{ item }}" \
-d "{{ item }}" \
{{ proxy.dns_cloudflare.opts | default("") }}'
args:
creates: "/etc/letsencrypt/live/{{ item }}/fullchain.pem"
loop: "{{ proxy.dns_cloudflare.wildcard_domains }}"

View File

@@ -1,2 +1,2 @@
# Cloudflare API token used by Certbot
dns_cloudflare_api_token = {{ cfapi['content'] | b64decode | trim }}
dns_cloudflare_api_token = {{ proxy.dns_cloudflare.api_token }}

View File

@@ -28,20 +28,14 @@ server {
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
{% endif %}
{% if item.hsts is defined %}
add_header Strict-Transport-Security "max-age={{ item.hsts }}" always;
{% endif %}
{% if item.client_max_body_size is defined %}
client_max_body_size {{ item.client_max_body_size }};
{% endif %}
location / {
{% if item.hsts is defined %}
add_header Strict-Transport-Security "max-age={{ item.hsts }}" always;
{% endif %}
{% if item.allowedips is defined %}
{% for ip in item.allowedips %}
allow {{ ip }};
{% endfor %}
deny all;
{% endif %}
{% if item.restrict is defined and item.restrict %}
{% if item.restrict is defined and item.restrict %}
auth_basic "{{ item.restrict_name | default('Restricted Access') }}";
auth_basic_user_file {{ item.restrict_file | default('/etc/nginx/.htpasswd') }};
proxy_set_header Authorization "";
@@ -49,7 +43,6 @@ server {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass {{ item.proxy_pass }};
{% if item.proxy_ssl_verify is defined and item.proxy_ssl_verify is false %}
proxy_ssl_verify off;