Initial Commit
All checks were successful
Deploy / Prepare Build (push) Successful in 13s

This commit is contained in:
2025-09-08 18:29:40 +10:00
commit 12444311a4
59 changed files with 2931 additions and 0 deletions

224
tasks/base.yml Normal file
View File

@ -0,0 +1,224 @@
---
- name: Ensure facts are gathered
setup:
- name: Ensure debian-archive-keyring is installed
apt:
name: debian-archive-keyring
state: present
update_cache: yes
become: yes
- name: Update cache
apt:
force_apt_get: yes
update_cache: yes
when: ansible_distribution in ['Debian', 'Ubuntu']
- name: Update all packages to their latest version
apt:
name: "*"
force_apt_get: yes
state: latest
when: ansible_distribution in ['Debian', 'Ubuntu']
register: upgrade_result
- name: Upgrade all packages on servers
apt:
upgrade: dist
force_apt_get: yes
when: ansible_distribution in ['Debian', 'Ubuntu']
register: dist_upgrade_result
- name: Install required packages
package:
name: "{{ install_packages }}"
state: present
become: yes
register: install_result
when: ansible_distribution in ['Debian', 'Ubuntu']
- name: Reboot if required after updates
reboot:
reboot_timeout: 600
test_command: whoami
when:
- upgrade_result.changed or dist_upgrade_result.changed or install_result.changed
- ansible_virtualization_type != "lxc"
become: yes
- name: Gather facts after reboot
setup:
# --- Upgrade Bookworm to Trixie ---
- name: Upgrade Bookworm -> Trixie
block:
- name: Replace sources.list entries for Trixie
lineinfile:
path: /etc/apt/sources.list
regexp: "^deb "
line: "deb https://deb.debian.org/debian trixie main"
become: yes
- name: Update cache for Trixie
apt:
update_cache: yes
force_apt_get: yes
- name: Dist-upgrade to Trixie
apt:
upgrade: dist
force_apt_get: yes
register: trixie_upgrade
- name: Reboot to apply Trixie
reboot:
reboot_timeout: 600
test_command: whoami
when:
- trixie_upgrade.changed
- ansible_virtualization_type != "lxc"
when: ansible_distribution_release == "bookworm"
become: yes
# --- Move to Trixie sources.list.d layout ---
- name: Remove old sources.list.d
file:
path: /etc/apt/sources.list.d
state: absent
become: yes
- name: Remove old sources.list
file:
path: /etc/apt/sources.list
state: absent
become: yes
- name: Ensure sources.list.d directory exists
file:
path: /etc/apt/sources.list.d
state: directory
mode: 0755
become: yes
- name: Create Trixie sources.list.d
copy:
dest: /etc/apt/sources.list.d/debian.sources
content: |
Types: deb deb-src
URIs: https://deb.debian.org/debian
Suites: trixie trixie-updates trixie-backports
Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb deb-src
URIs: https://deb.debian.org/debian-security
Suites: trixie-security
Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
owner: root
group: root
mode: 0644
become: yes
- name: Update APT cache after moving to sources.list.d layout
apt:
update_cache: yes
force_apt_get: yes
become: yes
- name: Find all EXTERNALLY-MANAGED files under /usr/lib/python*
find:
paths: /usr/lib
patterns: "EXTERNALLY-MANAGED"
file_type: file
recurse: yes
register: externally_managed_files
become: yes
- name: Delete EXTERNALLY-MANAGED files
file:
path: "{{ item.path }}"
state: absent
loop: "{{ externally_managed_files.files }}"
when: externally_managed_files.matched > 0
become: yes
# - name: Download Oh My Zsh installation script
# get_url:
# url: https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh
# dest: /tmp/install_ohmyzsh.sh
# - name: Run Oh My Zsh installation script
# become: no
# command: sh /tmp/install_ohmyzsh.sh --unattended
# register: ohmyzsh_result
# failed_when: "'FAILED' in ohmyzsh_result.stderr"
# - name: Download zsh Dracula Theme
# become: no
# unarchive:
# src: https://github.com/dracula/zsh/archive/refs/heads/master.zip
# dest: "/tmp"
# remote_src: yes
# - name: Download moe theme for zsh
# become: no
# get_url:
# url: https://git.comprofix.com/mmckinnon/dotfiles/raw/branch/master/oh-my-zsh/moe.zsh-theme
# dest: "/home/{{ ansible_user }}/.oh-my-zsh/themes"
# force: true
# - name: Move zsh theme to correct folder
# become: no
# copy:
# src: /tmp/zsh-master/
# dest: /home/{{ ansible_user }}/.oh-my-zsh/themes
# remote_src: yes
# - name: Create vim config paths
# become: no
# file:
# path: "/home/{{ ansible_user }}/.vim/pack/themes/start/dracula"
# state: directory
# - name: Download vim Dracula Theme
# become: no
# unarchive:
# src: https://github.com/dracula/vim/archive/refs/heads/master.zip
# dest: "/tmp"
# remote_src: yes
# - name: Move vim theme to correct folder
# become: no
# copy:
# src: /tmp/vim-master/
# dest: /home/{{ ansible_user }}/.vim/pack/themes/start/dracula
# remote_src: yes
# - name: Get zsh config
# become: no
# get_url:
# url: https://git.comprofix.com/mmckinnon/dotfiles/raw/branch/master/zsh/zshrc
# dest: "/home/{{ ansible_user }}/.zshrc"
# force: true
# - name: Get vim config
# become: no
# get_url:
# url: https://git.comprofix.com/mmckinnon/dotfiles/raw/branch/master/vim/vimrc
# dest: "/home/{{ ansible_user }}/.vimrc"
# force: true
# - name: Set shell zsh
# user:
# name: "{{ ansible_user }}"
# shell: /bin/zsh
# - name: Set moe theme for zsh
# become: no
# ansible.builtin.lineinfile:
# path: "/home/{{ansible_user}}/.zshrc"
# regexp: '^ZSH_THEME="dracula"'
# line: 'ZSH_THEME="moe"'

14
tasks/comprofix.com.yml Normal file
View File

@ -0,0 +1,14 @@
- name: Create the comprofix.com container
docker_container:
name: comprofix.com
image: git.comprofix.com/mmckinnon/comprofix.com:latest
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
labels:
traefik.enable: "true"
traefik.http.routers.comprofix.rule: "Host(`comprofix.com`)"
traefik.http.routers.comprofix.entrypoints: "https"
traefik.http.routers.comprofix.tls: "true"
traefik.http.services.comprofix.loadbalancer.server.port: "80"

12
tasks/dozzle-agent.yml Normal file
View File

@ -0,0 +1,12 @@
---
- name: Create the dozzle container
docker_container:
name: dozzle_agent
image: amir20/dozzle:v8.13.12
restart_policy: unless-stopped
command: agent
recreate: true
ports:
- 7007:7007
volumes:
- /var/run/docker.sock:/var/run/docker.sock

29
tasks/dozzle.yml Normal file
View File

@ -0,0 +1,29 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/dozzle"
- "{{ data_folder }}/dozzle/config"
- name: Create the dozzle container
docker_container:
name: dozzle
image: amir20/dozzle:v8.13.12
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
env:
DOZZLE_LEVEL: "trace"
DOZZLE_REMOTE_AGENT: "omada-lxc.comprofix.xyz:7007"
labels:
traefik.enable: "true"
traefik.http.routers.dozzle.rule: "Host(`dozzle.comprofix.xyz`)"
traefik.http.routers.dozzle.entrypoints: "https"
traefik.http.routers.dozzle.tls: "true"
traefik.http.services.dozzle.loadbalancer.server.port: "8080"
traefik.http.services.dozzle.loadbalancer.server.scheme: "http"

View File

@ -0,0 +1,42 @@
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/gitea-runner"
- "{{ data_folder }}/gitea-runner/config"
- name: Check that config.yaml exists
stat:
path: "{{ data_folder }}/gitea-runner/config/config.yaml"
register: configyaml
- name: Create config.yaml file
file:
path: "{{ data_folder }}/gitea-runner/config/config.yaml"
state: touch
mode: "0600"
access_time: preserve
modification_time: preserve
when: configyaml.stat.exists == False
- name: Create the gitea-runner container
docker_container:
name: gitea-runner
image: gitea/act_runner:0.2.13
restart_policy: unless-stopped
recreate: true
# dns_servers:a
# - 10.10.10.1
# - 127.0.0.11
volumes:
- "/etc/resolv.conf:/etc/resolv.conf:ro"
- /var/run/docker.sock:/var/run/docker.sock
- "{{ data_folder }}/gitea-runner/config/config.yaml:/config.yaml"
- "/etc/hosts:/etc/hosts:ro"
env:
CONFIG_FILE: "/config.yaml"
GITEA_INSTANCE_URL: "https://git.comprofix.com"
GITEA_RUNNER_REGISTRATION_TOKEN: "{{ GITEA_RUNNER_TOKEN }}"
GITEA_RUNNER_NAME: "homelab-runner"
GITEA_RUNNER_LABELS: "alpine-latest:docker://alpine:latest,ubuntu-latest:docker://node:22-trixie,homelab-latest:docker://git.comprofix.com/mmckinnon/debian-latest:2025.08.31-093853"

134
tasks/gitea.yml Normal file
View File

@ -0,0 +1,134 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/gitea"
- "{{ data_folder }}/gitea/data"
- "{{ data_folder }}/gitea/db"
- name: Create MySQL DB for Gitea
docker_container:
name: gitea_db
image: mysql:9
restart_policy: unless-stopped
networks:
- name: proxy
env:
MYSQL_ROOT_PASSWORD: "{{ gitea_db_root_password }}"
MYSQL_USER: "{{ gitea_db_user }}"
MYSQL_PASSWORD: "{{ gitea_db_password }}"
MYSQL_DATABASE: gitea
volumes:
- "{{ data_folder }}/gitea/db:/var/lib/mysql"
- name: Create the Gitea container
docker_container:
name: gitea
image: gitea/gitea:1.24
restart_policy: unless-stopped
recreate: true
# dns_servers:
# - 10.10.10.1
# - 127.0.0.11
networks:
- name: proxy
ports:
- "2222:22"
env:
PUID: "1001"
PGID: "1001"
TZ: "Australia/Brisbane"
volumes:
- "{{ data_folder }}/gitea/data:/data"
- "/etc/timezone:/etc/timezone:ro"
- "/etc/localtime:/etc/localtime:ro"
labels:
traefik.enable: "true"
traefik.http.routers.gitea.rule: "Host(`git.comprofix.com`)"
traefik.http.routers.gitea.entrypoints: "https"
traefik.http.routers.gitea.tls: "true"
traefik.http.routers.gitea.service: "gitea"
traefik.http.services.gitea.loadbalancer.server.port: "3000"
register: container_gitea
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/gitea-runner"
- "{{ data_folder }}/gitea-runner/config"
- name: Check that config.yaml exists
stat:
path: "{{ data_folder }}/gitea-runner/config/config.yaml"
register: configyaml
- name: Create config.yaml file
file:
path: "{{ data_folder }}/gitea-runner/config/config.yaml"
state: touch
mode: "0600"
access_time: preserve
modification_time: preserve
when: configyaml.stat.exists == False
- name: Create the gitea-runner container
docker_container:
name: gitea-runner
image: gitea/act_runner:0.2.13
restart_policy: unless-stopped
recreate: true
# dns_servers:
# - 10.10.10.1
# - 127.0.0.11
volumes:
- "/etc/resolv.conf:/etc/resolv.conf:ro"
- /var/run/docker.sock:/var/run/docker.sock
- "{{ data_folder }}/gitea-runner/config/config.yaml:/config.yaml"
- "/etc/hosts:/etc/hosts:ro"
env:
CONFIG_FILE: "/config.yaml"
GITEA_INSTANCE_URL: "https://git.comprofix.com"
GITEA_RUNNER_REGISTRATION_TOKEN: "{{ GITEA_RUNNER_TOKEN }}"
GITEA_RUNNER_NAME: "gitea-runner"
GITEA_RUNNER_LABELS: "alpine-latest:docker://alpine:latest,ubuntu-latest:docker://node:22-trixie,vps-latest:docker://git.comprofix.com/mmckinnon/debian-latest:2025.08.31-093853"
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/opengist"
- name: Create the opengist container
docker_container:
name: opengist
image: ghcr.io/thomiceli/opengist:1.10
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
# dns_servers:
# - 10.10.10.1
# - 127.0.0.11
volumes:
- "{{ data_folder }}/opengist:/opengist"
env:
OG_GITEA_CLIENT_KEY: "{{ OG_GITEA_KEY }}"
OG_GITEA_SECRET: "{{ OG_GITEA_SECRET }}"
# URL of the Gitea instance. Default: https://gitea.com/
OG_GITEA_URL: "https://git.comprofix.com"
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"
labels:
traefik.enable: "true"
traefik.http.routers.opengist.rule: "Host(`gist.comprofix.com`)"
traefik.http.routers.opengist.entrypoints: "https"
traefik.http.routers.opengist.tls: "true"
traefik.http.routers.opengist.service: "opengist"
traefik.http.services.opengist.loadbalancer.server.port: "6157"
register: container

26
tasks/gotify.yml Normal file
View File

@ -0,0 +1,26 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/gotify"
- "{{ data_folder }}/gotify/data"
- name: Create the gotify container
docker_container:
name: gotify
image: gotify/server:2.6.3
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
volumes:
- /data/gotify/data:/app/data
labels:
traefik.enable: "true"
traefik.http.routers.gotify.rule: "Host(`gotify.comprofix.com`)"
traefik.http.routers.gotify.entrypoints: "https"
traefik.http.routers.gotify.tls: "true"
traefik.http.routers.gotify.service: "gotify"
traefik.http.services.gotify.loadbalancer.server.port: "80"

40
tasks/homepage.yml Normal file
View File

@ -0,0 +1,40 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/homepage"
- "{{ data_folder }}/homepage/config"
- name: Get dashboard-icons
git:
repo: https://github.com/walkxcode/dashboard-icons.git
dest: /data/dashboard-icons
update: yes
- name: Create the homepage container
docker_container:
name: homepage
image: ghcr.io/gethomepage/homepage:v1.4.6
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
dns_servers:
- 10.10.10.1
env:
LOG_LEVEL: debug
HOMEPAGE_ALLOWED_HOSTS: homepage.comprofix.xyz
volumes:
- "{{ data_folder }}/homepage/config:/app/config"
- "{{ data_folder }}/dashboard-icons:/app/public/icons"
- /var/run/docker.sock:/var/run/docker.sock
labels:
traefik.enable: "true"
traefik.http.routers.homepage.rule: "Host(`homepage.comprofix.xyz`)"
traefik.http.routers.homepage.entrypoints: "https"
traefik.http.routers.homepage.tls: "true"
traefik.http.routers.homepage.service: "homepage"
traefik.http.services.homepage.loadbalancer.server.port: "3000"
register: container_homepage

15
tasks/idrac.yml Normal file
View File

@ -0,0 +1,15 @@
---
- name: Create the Dell_R730xd Fan Contoller container
docker_container:
name: Dell_R730xd
image: ghcr.io/tigerblue77/dell_idrac_fan_controller:latest@sha256:eda09016a4acbee8883996f3b8cd4832a723200999bd037934675e75e2f00908
restart_policy: unless-stopped
recreate: true
env:
IDRAC_HOST: "10.10.10.105"
IDRAC_USERNAME: "root"
IDRAC_PASSWORD: "calvin"
FAN_SPEED: "40"
CPU_TEMPERATURE_THRESHOLD: "80"
CHECK_INTERVAL: "60"
DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE: "true"

95
tasks/invoiceninja.yml Normal file
View File

@ -0,0 +1,95 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/invoiceninja/"
- "{{ data_folder }}/invoiceninja/config"
- "{{ data_folder }}/invoiceninja/db"
- name: "create stack.env"
copy:
dest: "{{ data_folder }}/invoiceninja/stack.env"
content: |
APP_NAME="Invoice Ninja"
APP_ENV=production
APP_KEY="{{ IN_APP_KEY }}"
APP_DEBUG=false
APP_URL="{{ IN_APP_URL }}"
REQUIRE_HTTPS=true
TRUSTED_PROXIES='*'
SESSION_ENCRYPT=false
SESSION_SECURE=false
DB_CONNECTION="mysql"
MULTI_DB_ENABLED=false
DB_HOST="{{MYSQL_HOST}}"
DB_DATABASE="{{IN_DB_DATABASE}}"
DB_USERNAME="{{IN_DB_USERNAME}}"
DB_PASSWORD="{{IN_DB_PASSWORD}}"
DB_PORT="3306"
DEMO_MODE=false
BROADCAST_DRIVER=log
LOG_CHANNEL=stack
CACHE_DRIVER=file
#QUEUE_CONNECTION=sync
QUEUE_CONNECTION=database
SESSION_DRIVER=file
SESSION_LIFETIME=120
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER="smtp"
MAIL_HOST="{{MAIL_HOST}}"
MAIL_PORT="{{MAIL_PORT}}"
MAIL_ENCRYPTION="tls"
MAIL_FROM_ADDRESS="{{MAIL_FROM}}"
MAIL_FROM_NAME="{{MAIL_FROM_NAME}}"
POSTMARK_API_TOKEN=
GOOGLE_MAPS_API_KEY=
ERROR_EMAIL=
NINJA_ENVIRONMENT="selfhost"
#options - snappdf / phantom / hosted_ninja
PDF_GENERATOR=hosted_ninja
PHANTOMJS_KEY='a-demo-key-with-low-quota-per-ip-address'
PHANTOMJS_SECRET=secret
UPDATE_SECRET=secret
SENTRY_LARAVEL_DSN=https://32f01ea994744fa08a0f688769cef78a@sentry.invoicing.co/
- name: Create the invoiceninja-app container
docker_container:
name: invoiceninja-app
image: invoiceninja/invoiceninja:5
env_file: "{{ data_folder }}/invoiceninja/stack.env"
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
volumes:
- "{{ data_folder }}/invoiceninja/config/hosts:/etc/hosts"
- "{{ data_folder }}/invoiceninja/docker/app/public:/var/www/app/public"
- "{{ data_folder }}/invoiceninja/docker/app/storage:/var/www/app/storage"
- name: Create the invoiceninja-nginx container
docker_container:
name: invoiceninja-nginx
image: nginx:1.29.1
env_file: "{{ data_folder }}/invoiceninja/stack.env"
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
volumes:
- "{{ data_folder }}/invoiceninja/config/nginx/in-vhost.conf:/etc/nginx/conf.d/in-vhost.conf"
- "{{ data_folder }}/invoiceninja/docker/app/public:/var/www/app/public"
- "{{ data_folder }}/invoiceninja/docker/app/storage:/var/www/app/storage"
labels:
traefik.enable: "true"
traefik.http.routers.invoiceninja.rule: "Host(`invoice.comprofix.com`)"
traefik.http.routers.invoiceninja.entrypoints: "https"
traefik.http.routers.invoiceninja.tls: "true"
traefik.http.services.invoiceninja.loadbalancer.server.port: "80"
traefik.http.services.invoiceninja.loadbalancer.server.scheme: "http"

88
tasks/iscsi.yml Normal file
View File

@ -0,0 +1,88 @@
---
- name: Ensure open-iscsi is installed
package:
name: open-iscsi
state: present
- name: Ensure parted is installed
package:
name: parted
state: present
- name: Discover iSCSI targets
command: sudo iscsiadm -m discovery -t sendtargets -p "10.10.10.2"
register: iscsi_discovery
- name: Set target_iqn variable based on discovery
set_fact:
target_iqn: "{{ item.split(' ')[1] }}"
loop: "{{ iscsi_discovery.stdout_lines }}"
when: item.startswith("10.10.10.2")
- name: Check if iSCSI target is already connected
command: iscsiadm -m session
register: iscsi_sessions
changed_when: false
failed_when: iscsi_sessions.rc not in [0, 21] # Allow success if the return code is 0 or 21
- name: Connect to iSCSI target
command: sudo iscsiadm -m node -T "{{ target_iqn }}" -p "10.10.10.2" --login
when: target_iqn is defined and target_iqn not in iscsi_sessions.stdout
- name: Set iSCSI target for automatic login
command: sudo iscsiadm -m node -T "{{ target_iqn }}" -p "10.10.10.2" --op update --name node.startup --value automatic
when: target_iqn is defined
- name: Fail if no target_iqn found
fail:
msg: "No target IQN found for iSCSI server IP 10.10.10.2"
when: target_iqn is not defined
- name: List all block devices
command: lsblk -o NAME,SIZE,TYPE,MODEL
register: lsblk_output
- name: Set iSCSI device variable
set_fact:
iscsi_device: "/dev/{{ item.split()[0] }}"
loop: "{{ lsblk_output.stdout_lines }}"
when: item.split()[2] == 'disk' and 'iSCSI' in item # Adjust based on the MODEL you observe
- name: Fail if no iSCSI device found
fail:
msg: "No iSCSI device found!"
when: iscsi_device is not defined
- name: Create a partition on iSCSI device using parted
parted:
device: "{{ iscsi_device }}"
number: 1
state: present
part_type: primary
fs_type: ext4
part_start: 0% # Start at the beginning of the device
part_end: 100% # Use the entire available space
- name: Create filesystem on new partition
filesystem:
fstype: ext4
dev: "{{ iscsi_device }}1" # Format the partition
- name: Create mount point
file:
path: /data
state: directory
- name: Mount iSCSI target
mount:
path: /data
src: "{{ iscsi_device }}1" # Mount the new partition
fstype: ext4
opts: defaults,_netdev
state: mounted
# - name: Ensure iSCSI target is mounted at boot
# lineinfile:
# path: /etc/fstab
# line: "{{ iscsi_device }}1 /data ext4 _netdev 0 0"
# state: present

29
tasks/jellyseerr.yml Normal file
View File

@ -0,0 +1,29 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/jellyseerr"
- "{{ data_folder }}/jellyseerr/config"
- name: Create the jellyseerr container
docker_container:
name: jellyseerr
image: fallenbagel/jellyseerr:2.7.3
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
env:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"
volumes:
- "{{ data_folder }}/jellyseerr/config:/app/config"
labels:
traefik.enable: "true"
traefik.http.routers.jellyseerr.rule: "Host(`jellyseerr.comprofix.xyz`)"
traefik.http.routers.jellyseerr.entrypoints: "https"
traefik.http.routers.jellyseerr.tls: "true"
traefik.http.services.jellyseerr.loadbalancer.server.port: "5055"

36
tasks/lidarr.yml Normal file
View File

@ -0,0 +1,36 @@
---
- name: Set Facts
set_fact:
container_name: 'lidarr'
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/lidarr"
- "{{ data_folder }}/lidarr/config"
- name: Create the lidarr container
docker_container:
name: lidarr
image: ghcr.io/linuxserver/lidarr:latest@sha256:186bc4d3f22bd6a71c235c1c7f57f90a8473f766278d9c929398fb5ce90eae7e
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
env:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"
AUTO_UPDATE: "true" #optional
DOCKER_MODS: "ghcr.io/themepark-dev/theme.park:lidarr"
volumes:
- "{{ data_folder }}/lidarr/config:/config"
- /mnt/nfs/data:/data
labels:
traefik.enable: "true"
traefik.http.routers.lidarr.rule: "Host(`lidarr.comprofix.xyz`)"
traefik.http.routers.lidarr.entrypoints: "https"
traefik.http.routers.lidarr.tls: "true"
traefik.http.services.lidarr.loadbalancer.server.port: "8686"

29
tasks/mariadb.yml Normal file
View File

@ -0,0 +1,29 @@
---
- name: Set Facts
set_fact:
container_name: 'mariadb'
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/mariadb"
- "{{ data_folder }}/mariadb/config"
- name: Create the mariadb container
docker_container:
name: "mariadb"
image: ghcr.io/linuxserver/mariadb:11.4.8
restart_policy: unless-stopped
recreate: true
ports:
- 3306:3306
env:
PUID: "0"
PGID: "0"
MYSQL_ROOT_PASSWORD: "{{MYSQL_ROOT_PASSWORD}}"
TZ: "Australia/Brisbane"
volumes:
- "{{ data_folder }}/mariadb/config:/config"

36
tasks/mealie.yml Normal file
View File

@ -0,0 +1,36 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/mealie"
- "{{ data_folder }}/mealie/config"
- name: Create the mealie container
docker_container:
name: mealie
image: ghcr.io/mealie-recipes/mealie:v3.1.2
restart_policy: unless-stopped
networks:
- name: proxy
env:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"
RECIPE_PUBLIC: "true"
RECIPE_SHOW_NUTRITION: "false"
RECIPE_SHOW_ASSETS: "true"
RECIPE_LANDSCAPE_VIEW: "true"
RECIPE_DISABLE_COMMENTS: "true"
RECIPE_DISABLE_AMOUNT: "true"
BASE_URL: "mealie.comprofix.xyz"
SMTP_HOST: "{{MAIL_HOST}}"
volumes:
- "{{ data_folder }}/mealie/data/:/app/data"
labels:
traefik.enable: "true"
traefik.http.routers.mealie.rule: "Host(`mealie.comprofix.xyz`)"
traefik.http.routers.mealie.entrypoints: "https"
traefik.http.routers.mealie.tls: "true"
traefik.http.services.mealie.loadbalancer.server.port: "9000"

29
tasks/mediawiki.yml Normal file
View File

@ -0,0 +1,29 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/mediawiki"
- name: Create the wiki container
docker_container:
name: mediawiki
image: mediawiki:1.44.0
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
env:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"
volumes:
- "{{ data_folder }}/mediawiki/images:/var/www/html/images"
- "{{ data_folder }}/mediawiki/LocalSettings.php:/var/www/html/LocalSettings.php"
labels:
traefik.enable: "true"
traefik.http.routers.wiki.rule: "Host(`wiki.comprofix.xyz`)"
traefik.http.routers.wiki.entrypoints: "https"
traefik.http.routers.wiki.tls: "true"
traefik.http.services.wiki.loadbalancer.server.port: "80"

24
tasks/omada.yml Normal file
View File

@ -0,0 +1,24 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/omada"
- "{{ data_folder }}/omada/data"
- "{{ data_folder }}/omada/logs"
- name: Create the omada container
docker_container:
name: omada
image: mbentley/omada-controller:5.15
restart_policy: unless-stopped
recreate: true
network_mode: host
volumes:
- "{{ data_folder }}/omada/data:/opt/tplink/EAPController/data"
- "{{ data_folder }}/omada/logs:/opt/tplink/EAPController/logs"
env:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"

61
tasks/osticket.yml Normal file
View File

@ -0,0 +1,61 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/osticket"
- "{{ data_folder }}/osticket/config"
- name: Create the osticket container
docker_container:
name: osticket
image: devinsolutions/osticket:1.17.5
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
env:
SMTP_HOST: "{{MAIL_HOST}}"
MYSQL_HOST: "{{MYSQL_HOST}}"
MYSQL_DATABASE: "{{OST_DATABASE}}"
MYSQL_USER: "{{OST_DB_USER}}"
MYSQL_PASSWORD: "{{OST_DB_PASSWORD}}"
INSTALL_SECRET: "{{OST_SIRI}}"
labels:
traefik.enable: "true"
traefik.http.routers.osticket.rule: "Host(`helpdesk.comprofix.com`)"
traefik.http.routers.osticket.entrypoints: "https"
traefik.http.routers.osticket.tls: "true"
traefik.http.services.osticket.loadbalancer.server.port: "80"
traefik.http.services.osticket.loadbalancer.server.scheme: "http"
- name: Add tzdata to osTicket container
community.docker.docker_container_exec:
container: osticket
command: apk add tzdata
- name: Set container Timezone
community.docker.docker_container_exec:
container: osticket
command: "ln -s /usr/share/zoneinfo/Australia/Brisbane /etc/localtime"
- name: Set PHP Timezone
community.docker.docker_container_exec:
container: osticket
command: "sed -i 's|UTC|Australia/Brisbane|g' /usr/local/etc/php/conf.d/php-osticket.ini"
- name: Patch mysqli.php for timezone
community.docker.docker_container_exec:
container: osticket
command: "sed -i 's|system_time_zone|time_zone|g' /var/www/html/include/mysqli.php"
- name: Clear ost_sessions table
mysql_query:
login_host: "{{MYSQL_HOST}}"
login_user: "{{OST_DB_USER}}"
login_password: "{{OST_DB_PASSWORD}}"
login_db: "{{OST_DATABASE}}"
query:
- USE comprofix_ost;
- TRUNCATE TABLE ost_session;

22
tasks/postgres.yml Normal file
View File

@ -0,0 +1,22 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "/mnt/nfs/docker/postgres"
- "/mnt/nfs/docker/postgres/config"
- name: Create the postgres container
docker_container:
name: postgres
image: postgres:16-alpine
restart_policy: unless-stopped
recreate: true
ports:
- 5432:5432
env:
POSTGRES_PASSWORD: "{{POSTGRES_PASSWORD}}"
volumes:
- /mnt/nfs/docker/postgres/db-data:/var/lib/postgresql/data

31
tasks/prowlarr.yml Normal file
View File

@ -0,0 +1,31 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/prowlarr"
- "{{ data_folder }}/prowlarr/config"
- name: Create the prowlarr container
docker_container:
name: prowlarr
image: linuxserver/prowlarr:2.0.5
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
env:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"
AUTO_UPDATE: "true" #optional
DOCKER_MODS: "ghcr.io/themepark-dev/theme.park:prowlarr"
volumes:
- "{{ data_folder }}/prowlarr/config:/config"
labels:
traefik.enable: "true"
traefik.http.routers.prowlarr.rule: "Host(`prowlarr.comprofix.xyz`)"
traefik.http.routers.prowlarr.entrypoints: "https"
traefik.http.routers.prowlarr.tls: "true"
traefik.http.services.prowlarr.loadbalancer.server.port: "9696"

26
tasks/pykms.yml Normal file
View File

@ -0,0 +1,26 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/pykms"
- "{{ data_folder }}/pykms/db"
- name: Create the pykms container
docker_container:
name: pykms
image: ghcr.io/py-kms-organization/py-kms:latest
restart_policy: unless-stopped
recreate: true
ports:
- "1688:1688"
env:
IP: "0.0.0.0"
SQLITE: "true"
HWID: "RANDOM"
LOGLEVEL: "INFO"
volumes:
- "{{ data_folder }}/pykms/db:/home/py-kms/db"
- /etc/localtime:/etc/localtime:ro

31
tasks/radarr.yml Normal file
View File

@ -0,0 +1,31 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/radarr"
- "{{ data_folder }}/radarr/config"
- name: Create the radarr container
docker_container:
name: radarr
image: linuxserver/radarr:5.27.5
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
env:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"
DOCKER_MODS: "ghcr.io/themepark-dev/theme.park:radarr"
volumes:
- "{{ data_folder }}/radarr/config:/config"
- /mnt/nfs/data:/data
labels:
traefik.enable: "true"
traefik.http.routers.radarr.rule: "Host(`radarr.comprofix.xyz`)"
traefik.http.routers.radarr.entrypoints: "https"
traefik.http.routers.radarr.tls: "true"
traefik.http.services.radarr.loadbalancer.server.port: "7878"

33
tasks/readarr.yml Normal file
View File

@ -0,0 +1,33 @@
# Readarr has been archived/retired.
# Keeping this for history
# ---
# - name: Create directories
# file:
# path: "{{ item }}"
# state: directory
# with_items:
# - "{{ data_folder }}/readarr"
# - "{{ data_folder }}/readarr/config"
# - name: Create the readarr container
# docker_container:
# name: readarr
# image: linuxserver/readarr:develop@sha256:eb37f58646a901dc7727cf448cae36daaefaba79de33b5058dab79aa4c04aefb
# restart_policy: unless-stopped
# recreate: true
# networks:
# - name: proxy
# env:
# PUID: "1000"
# PGID: "1000"
# TZ: "Australia/Brisbane"
# DOCKER_MODS: "ghcr.io/themepark-dev/theme.park:readarr"
# volumes:
# - "{{ data_folder }}/readarr/config/:/config"
# - /mnt/nfs/data/:/data
# labels:
# traefik.enable: "true"
# traefik.http.routers.readarr.rule: "Host(`readarr.comprofix.xyz`)"
# traefik.http.routers.readarr.entrypoints: "https"
# traefik.http.routers.readarr.tls: "true"
# traefik.http.services.readarr.loadbalancer.server.port: "8787"

32
tasks/sabnzbd.yml Normal file
View File

@ -0,0 +1,32 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/sabnzbd"
- "{{ data_folder }}/sabnzbd/config"
- name: Create the sabnzbd container
docker_container:
name: sabnzbd
image: linuxserver/sabnzbd:4.5.3
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
env:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"
HOSTNAME: "sabnzbd.comprofix.xyz"
DOCKER_MODS: "ghcr.io/themepark-dev/theme.park:sabnzbd"
volumes:
- "{{ data_folder }}/sabnzbd/config:/config"
- /mnt/nfs/data:/data
labels:
traefik.enable: "true"
traefik.http.routers.sabnzbd.rule: "Host(`sabnzbd.comprofix.xyz`)"
traefik.http.routers.sabnzbd.entrypoints: "https"
traefik.http.routers.sabnzbd.tls: "true"
traefik.http.services.sabnzbd.loadbalancer.server.port: "8080"

31
tasks/sonarr.yml Normal file
View File

@ -0,0 +1,31 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/sonarr"
- "{{ data_folder }}/sonarr/config"
- name: Create the sonarr container
docker_container:
name: sonarr
image: linuxserver/sonarr:4.0.15
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
env:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"
DOCKER_MODS: "ghcr.io/themepark-dev/theme.park:sonarr"
volumes:
- "{{ data_folder }}/sonarr/config/:/config"
- /mnt/nfs/data:/data
labels:
traefik.enable: "true"
traefik.http.routers.sonarr.rule: "Host(`sonarr.comprofix.xyz`)"
traefik.http.routers.sonarr.entrypoints: "https"
traefik.http.routers.sonarr.tls: "true"
traefik.http.services.sonarr.loadbalancer.server.port: "8989"

41
tasks/speedtest.yml Normal file
View File

@ -0,0 +1,41 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/speedtest"
- "{{ data_folder }}/speedtest/config"
- "{{ data_folder }}/speedtest/web"
- name: Create the speedtest container
docker_container:
name: speedtest
image: lscr.io/linuxserver/speedtest-tracker:1.6.6
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
env:
APP_KEY: "base64:ViJcK7rSIwGC+TAW7pRWnczB43zPPVHH2Hx80t7eVm0="
PUID: "1000"
PGID: "1000"
DB_CONNECTION: "mysql"
DB_HOST: "{{ MYSQL_HOST }}"
DB_PORT: "3306"
DB_DATABASE: "{{ST_DATABASE}}"
DB_USERNAME: "{{ST_DB_USERNAME}}"
DB_PASSWORD: "{{ST_DB_PASSWORD}}"
TZ: "Australia/Brisbane"
SPEEDTEST_SCHEDULE: "0 * * * *"
DISPLAY_TIMEZONE: "Australia/Brisbane"
volumes:
- "{{ data_folder }}/speedtest/config:/config"
- "{{ data_folder }}/speedtest/web:/etc/ssl/web"
labels:
traefik.enable: "true"
traefik.http.routers.speedtest.rule: "Host(`speedtest.comprofix.xyz`)"
traefik.http.routers.speedtest.entrypoints: "https"
traefik.http.routers.speedtest.tls: "true"
traefik.http.services.speedtest.loadbalancer.server.port: "80"
traefik.http.services.speedtest.loadbalancer.server.scheme: "http"

26
tasks/traggo.yml Normal file
View File

@ -0,0 +1,26 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/traggo"
- "{{ data_folder }}/traggo/data"
- name: Create the traggo container
docker_container:
name: traggo
image: traggo/server:0.7.1
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
volumes:
- /data/traggo/data:/opt/traggo/data
labels:
traefik.enable: "true"
traefik.http.routers.traggo.rule: "Host(`traggo.comprofix.xyz`)"
traefik.http.routers.traggo.entrypoints: "https"
traefik.http.routers.traggo.tls: "true"
traefik.http.services.traggo.loadbalancer.server.port: "3030"
traefik.http.services.traggo.loadbalancer.server.scheme: "http"

64
tasks/vaultwarden.yml Normal file
View File

@ -0,0 +1,64 @@
---
- name: Create directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ data_folder }}/vaultwarden"
- "{{ data_folder }}/vaultwarden/config"
- "{{ data_folder }}/vaultwardenbackup"
- "{{ data_folder }}/vaultwardenbackup/config"
- "{{ data_folder }}/vaultwardenbackup/config/rclone"
- name: Create the vaultwarden container
docker_container:
name: vaultwarden
image: vaultwarden/server:1.34.3
restart_policy: unless-stopped
recreate: true
networks:
- name: proxy
env:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"
volumes:
- "{{ data_folder }}/vaultwarden/data:/data"
labels:
traefik.enable: "true"
traefik.http.routers.vaultwarden.rule: "Host(`vault.comprofix.com`)"
traefik.http.routers.vaultwarden.entrypoints: "https"
traefik.http.routers.vaultwarden.tls: "true"
traefik.http.routers.vaultwarden.service: "vaultwarden"
traefik.http.services.vaultwarden.loadbalancer.server.port: "80"
register: container
- name: Copy rclone config
copy:
src: scripts/rclone.conf
dest: "{{ data_folder }}/vaultwardenbackup/config/rclone/rclone.conf"
decrypt: yes
mode: "0600"
- name: Create the vaultwarden container
docker_container:
name: vaultwardenbackup
image: ttionya/vaultwarden-backup:1.25.1
restart_policy: unless-stopped
recreate: true
env:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Brisbane"
CRON: "0 4 * * *"
BACKUP_KEEP_DAYS: "14"
ZIP_PASSWORD: "{{ VAULTWARDEN_BACKUP_ZIP_PASSWORD }}"
volumes:
- "{{ data_folder }}/vaultwarden/data:/bitwarden/data"
- "{{ data_folder }}/vaultwardenbackup/config:/config"
register: container