43 Commits

Author SHA1 Message Date
ef780275e7 Infisical no longer needs pinning
Some checks failed
Infrastructure / Check and run Ansbile playbooks (pull_request) Failing after 3m30s
2024-03-29 16:24:22 +00:00
87df3eb334 Merge branch 'main' into cleanup-playbooks 2024-03-29 16:23:17 +00:00
9f51ce02d6 Fix #50: Remove custom network *completely* from Infisical docker-compose (#52)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 3m14s
Reviewed-on: #52
2024-03-29 15:57:07 +00:00
719640a98d Fix #50: Trigger all secrets playbooks (#51)
Some checks failed
Infrastructure / Check and run Ansbile playbooks (push) Failing after 5m46s
Keep forgetting this :/

Reviewed-on: #51
2024-03-29 15:48:14 +00:00
20b72f085f Secrets VM: v2 (#50)
Some checks failed
Infrastructure / Check and run Ansbile playbooks (push) Failing after 4m34s
Closes #44. We'll do a manual migration for stability and simplicity.

Reviewed-on: #50
2024-03-29 15:24:57 +00:00
da90d463de Fix Infisical Gitea Actions (#43)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m6s
For some reason secrets are failing: https://git.koval.net/cyclane/kovalhome/actions/runs/193

Reviewed-on: #43
2024-03-01 00:37:04 +00:00
68259cb3cf Upgrade Immich to 1.95 (#42)
Some checks failed
Infrastructure / Check and run Ansbile playbooks (push) Failing after 2m4s
And again...

https://github.com/immich-app/immich/releases/tag/v1.95.0

Reviewed-on: #42
2024-02-29 22:53:28 +00:00
202abc79e3 Use requirements.yml for galaxy
Some checks failed
Infrastructure / Check and run Ansbile playbooks (pull_request) Failing after 2m57s
2024-01-30 17:50:13 +00:00
8ab4968371 Remove ansible-lint from requirements
Some checks failed
Infrastructure / Check and run Ansbile playbooks (pull_request) Failing after 3m6s
2024-01-30 17:32:13 +00:00
5ac073fc11 use ansible-lint action
Some checks failed
Infrastructure / Check and run Ansbile playbooks (pull_request) Failing after 3m34s
2024-01-30 17:31:29 +00:00
2834642cb7 Use strict linting
All checks were successful
Infrastructure / Check and run Ansbile playbooks (pull_request) Successful in 2m1s
2024-01-30 13:01:28 +00:00
594c97f4dc Add ansible-lint dependancy
All checks were successful
Infrastructure / Check and run Ansbile playbooks (pull_request) Successful in 2m8s
2024-01-30 12:46:27 +00:00
9689da7d11 Add ansible-lint to github actions
Some checks failed
Infrastructure / Check and run Ansbile playbooks (pull_request) Failing after 1m36s
2024-01-30 12:42:41 +00:00
e1375aeb72 ansible-lint 2024-01-30 12:40:46 +00:00
2aa297e901 docker_compose_v2 ansible (instead of shell) 2024-01-30 12:37:37 +00:00
1a0114fa34 nextcloud aio:
- remove immich decommision (it's fine(tm))
- use ansible to create container, instead of bash script
2024-01-29 22:42:27 +00:00
e807abb376 Fix name of install docker playbooks 2024-01-29 22:41:33 +00:00
334276e654 proxmox playbooks
- use handler for initial boot & wait
2024-01-29 22:28:02 +00:00
b9d0c5d55d Fix #36: Update samba file permissions in playbook (#40)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m50s
Reviewed-on: #40
2024-01-27 18:25:40 +00:00
7eff8a43ef Fix #36: Fix mounts and trigger CI (#39)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m48s
We need to create each samba folder manually - do it with docker-compose I guess.

Reviewed-on: #39
2024-01-27 18:16:23 +00:00
7916f12e73 Fix #36: Trigger all CI for samba (#38)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 7m48s
Reviewed-on: #38
2024-01-27 18:04:29 +00:00
aa78f334bd Fix #36: Samba VM - SRV NIC (#37)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m21s
Add SRV NIC back because Ansible uses it :/

Reviewed-on: #37
2024-01-27 17:54:59 +00:00
47556c3a8c Samba VM (#36)
Some checks failed
Infrastructure / Check and run Ansbile playbooks (push) Failing after 9m37s
Initialise new samba service. Currently will only be used for local network backups.

Reviewed-on: #36
2024-01-27 17:41:57 +00:00
1a8fe73bf2 Fix #32: Format environment: properly. (#33)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m55s
Reviewed-on: #33
2024-01-07 00:03:40 +00:00
3685590a58 Music VM: Set Navidrome to use LastFM for coverart before embedded images (#32)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m46s
Default is embedded before LastFM, but since we're downloading from YouTube embedded always exists, and is often not great. So use LastFM before embedded.

Reviewed-on: #32
2024-01-06 23:54:55 +00:00
40410b2dff Fix #28: Do not use user: for metube and picard (#31)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m46s
Reviewed-on: #31
2024-01-06 18:31:05 +00:00
5bfc02d3ae Fix #28: Need to become for permission changes (#30)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m37s
Reviewed-on: #30
2024-01-06 18:19:07 +00:00
54cf382710 Fix #28: Set directory permissions (#29)
Some checks failed
Infrastructure / Check and run Ansbile playbooks (push) Failing after 2m23s
Since we are using `user:` in docker-compose, we need to set the directory permissions so that everything doesn't crash immediately.

Reviewed-on: #29
2024-01-06 18:14:56 +00:00
d4d5511b78 Music VM (#28)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 8m20s
Provision a VM with Navidrome and some tools for downloading stuff from YouTube.

Reviewed-on: #28
2024-01-06 17:36:06 +00:00
f47ad0a125 Fix #25: Get value from Infisical result (#27)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m20s
Fixes #25 (again).

Reviewed-on: #27
2024-01-04 16:03:11 +00:00
773b73f579 Fix #25: Use correct lookup name (#26)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m11s
Fixes #25

Reviewed-on: #26
2024-01-04 13:13:31 +00:00
8529d56c44 Migrate Photos VM to read secrets from Infisical (#25)
Some checks failed
Infrastructure / Check and run Ansbile playbooks (push) Failing after 2m3s
#21 provisioned an Infisical service (https://secrets.koval.net/). We can use this instead of the hacky solution that can explode.

Contributes to and closes #16.

Reviewed-on: #25
2024-01-04 13:09:16 +00:00
a8b7b1df4a Fix Infisical SMTP settings (#24)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m4s
Add SMTP_FROM_ADDRESS to infisical

Reviewed-on: #24
2024-01-04 12:50:41 +00:00
ed07a8ef71 Upgrade secrets VM CPU (#23)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 2m13s
Mongo requires AVX https://jira.mongodb.org/browse/SERVER-54407.

Otherwise logs:
```
infisical-mongo-1    | WARNING: MongoDB 5.0+ requires a CPU with AVX support, and your current system does not appear to have that!
infisical-mongo-1    |   see https://jira.mongodb.org/browse/SERVER-54407
infisical-mongo-1    |   see also https://www.mongodb.com/community/forums/t/mongodb-5-0-cpu-intel-g4650-compatibility/116610/2
infisical-mongo-1    |   see also https://github.com/docker-library/mongo/issues/485#issuecomment-891991814
infisical-mongo-1    |
infisical-mongo-1    | /usr/local/bin/docker-entrypoint.sh: line 416:    26 Illegal instruction     "${mongodHackedArgs[@]}" --fork
```

Reviewed-on: https://git.koval.net/cyclane/kovalhome/pulls/23
2024-01-04 11:58:27 +00:00
82fee4eb19 Secrets VM (#21)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 5m29s
Setup Infiscal according to https://infisical.com/docs/self-hosting/deployment-options/docker-compose .

Contributes to #16.

Reviewed-on: #21
2024-01-04 11:22:21 +00:00
89c5e1ea36 Upgrade Immich to 1.91 (#18)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 4m31s
Yet again Immich is introducing breaking changes.

Reviewed-on: #18
2023-12-16 22:57:15 +00:00
6c8bab5748 Fix immich/0004 name
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 3m57s
2023-11-21 12:28:05 +00:00
34fa3d2ba3 Upgrade Immich to 1.88 (#15)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 1m27s
Immich 1.87 → 1.88 [has breaking changes](https://github.com/immich-app/immich/discussions/5086), so we need an Ansible migration.

Reviewed-on: #15
2023-11-21 11:34:40 +00:00
05a730ea52 Immich VM: Initial provision and decommission Immich from Cloud VM (#11)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 7m26s
Reviewed-on: #11
2023-09-28 12:44:24 +00:00
e39f826597 Cloud VM: Fix media deployment (#10)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 3m21s
Reviewed-on: #10
2023-09-27 21:31:32 +00:00
47335e40f6 Cloud VM: Add immich & prepare for Nextcloud memories (#9)
Some checks failed
Infrastructure / Check and run Ansbile playbooks (push) Failing after 2m50s
We want to test out what is better - Immich or Nextcloud memories.

Reviewed-on: #9
2023-09-27 21:18:49 +00:00
21c6b627a8 Cloud VM: mount data to /var/lib/docker (#8)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 1m31s
Since Nextcloud AIO manages itself and uses docker volumes, the easiest way to persisty all data in a separate disk is to just mount it to `/var/lib/docker`. This is still an easier long-term solution than managing the entire stack manually - we can always migrate (relatively) easily in the future anyway.

Reviewed-on: #8
2023-09-26 23:24:07 +00:00
68aff49459 Cloud VM (#7)
All checks were successful
Infrastructure / Check and run Ansbile playbooks (push) Successful in 6m42s
- Nextcloud & potentially other "cloud" stuff VM

Reviewed-on: #7
2023-09-26 19:50:11 +00:00
38 changed files with 1563 additions and 59 deletions

4
.ansible-lint Normal file
View File

@@ -0,0 +1,4 @@
strict: true
use_default_rules: true
skip_list:
- args[module]

View File

@@ -11,8 +11,8 @@ on:
- main - main
env: env:
# DEPLOY: ${{ github.ref == 'refs/heads/main' && ((startsWith(github.event.head_commit.message, '[deploy-all]') && 'all') || ('some')) || 'none' }} DEPLOY: ${{ github.ref == 'refs/heads/main' && ((startsWith(github.event.head_commit.message, '[deploy-all]') && 'all') || ('some')) || 'none' }}
DEPLOY: all # DEPLOY: all
jobs: jobs:
ansible-playbooks: ansible-playbooks:
@@ -29,13 +29,14 @@ jobs:
apt update apt update
apt install -y python3-pip apt install -y python3-pip
pip3 install -r requirements.txt pip3 install -r requirements.txt
ansible-galaxy collection install community.general ansible-galaxy collection install -r requirements.yml --force
- name: Run ansible-lint
uses: ansible/ansible-lint@v6
- name: Check playbooks - name: Check playbooks
run: | run: |
for file in $(find . -wholename "*/infra/*playbook.yaml" -type f); do ansible-playbook --inventory ./inventory --syntax-check infra/**/*playbook.yaml
ansible-playbook --inventory ./inventory --syntax-check "$file"
done
- name: Get changed playbooks - name: Get changed playbooks
id: files id: files
@@ -72,4 +73,9 @@ jobs:
PROXMOX_TOKEN_ID: ${{ secrets.PROXMOX_TOKEN_ID }} PROXMOX_TOKEN_ID: ${{ secrets.PROXMOX_TOKEN_ID }}
PROXMOX_TOKEN_SECRET: ${{ secrets.PROXMOX_TOKEN_SECRET }} PROXMOX_TOKEN_SECRET: ${{ secrets.PROXMOX_TOKEN_SECRET }}
SSH_PUBLIC: ${{ secrets.SSH_PUBLIC }} SSH_PUBLIC: ${{ secrets.SSH_PUBLIC }}
run: ansible-playbook --inventory ./inventory ${{ steps.playbooks.outputs.to_run }} SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
INFISICAL_ENCRYPTION_KEY: ${{ secrets.INFISICAL_ENCRYPTION_KEY }}
INFISICAL_AUTH_SECRET: ${{ secrets.INFISICAL_AUTH_SECRET }}
INFISICAL_TOKEN: ${{ secrets.INFISICAL_TOKEN }}
INFISICAL_URL: https://secrets.koval.net
run: ansible-playbook --inventory ./inventory ${{ steps.playbooks.outputs.to_run }} -vv

View File

@@ -1,5 +1,5 @@
- name: Provision joplin Proxmox VM - name: Provision cloud Proxmox VM
hosts: joplin hosts: cloud
connection: ansible.builtin.local connection: ansible.builtin.local
gather_facts: false gather_facts: false
vars: vars:
@@ -36,7 +36,7 @@
community.general.proxmox_kvm: community.general.proxmox_kvm:
clone: "{{ node }}-debian-12" clone: "{{ node }}-debian-12"
storage: nvme storage: nvme
register: create notify: Initial boot
- name: Wait for status - name: Wait for status
community.general.proxmox_kvm: community.general.proxmox_kvm:
state: current state: current
@@ -46,11 +46,11 @@
until: vm.status is defined until: vm.status is defined
# Networking and initial config # Networking and initial config
- name: Add HOME NIC - name: Add PUB NIC
community.general.proxmox_nic: community.general.proxmox_nic:
interface: net0 interface: net0
firewall: false firewall: false
bridge: HOME bridge: PUB
- name: Add SRV NIC - name: Add SRV NIC
community.general.proxmox_nic: community.general.proxmox_nic:
interface: net1 interface: net1
@@ -60,34 +60,26 @@
community.general.proxmox_kvm: community.general.proxmox_kvm:
update: true update: true
ciuser: debian ciuser: debian
cipassword: thisIsSafe
sshkeys: "{{ ssh_public }}" sshkeys: "{{ ssh_public }}"
ipconfig: ipconfig:
ipconfig0: ip=dhcp,ip6=auto ipconfig0: ip=dhcp,ip6=auto
ipconfig1: ip=dhcp ipconfig1: ip=dhcp
# Initial boot - name: Force all notified handlers to run
# For some reason debian cloud images don't use ansible.builtin.meta: flush_handlers
# cloud-init for networking on first boot (cloud-init files
# are regenerated AFTER networking starts). But we need the
# hostname to be registered with DHCP later on so ¯\_(ツ)_/¯
- name: Initial boot
when: create.changed is true
block:
- name: Start
community.general.proxmox_kvm:
state: started
register: start
- name: Wait 3 min # Initial apt update, apt upgrade, cloud-init
ansible.builtin.wait_for:
timeout: 180
# VM Configuration # VM Configuration
- name: Resize disk - name: Resize root disk
community.general.proxmox_disk: community.general.proxmox_disk:
disk: scsi0 disk: scsi0
size: 64G size: 16G
state: resized state: resized
- name: Create data disk
community.general.proxmox_disk:
disk: scsi1
backup: true
storage: nvme
size: 2048
- name: Update VM - name: Update VM
community.general.proxmox_kvm: community.general.proxmox_kvm:
update: true update: true
@@ -96,10 +88,25 @@
- debian-12 - debian-12
- managed - managed
onboot: true onboot: true
cores: 2 cores: 8
memory: 2048 memory: 16384
- name: Retart VM - name: Retart VM
community.general.proxmox_kvm: community.general.proxmox_kvm:
state: restarted state: restarted
timeout: 60 timeout: 60
handlers:
# Initial boot
# For some reason debian cloud images don't use
# cloud-init for networking on first boot (cloud-init files
# are regenerated AFTER networking starts). But we need the
# hostname to be registered with DHCP later on so ¯\_(ツ)_/¯
- name: Initial boot
block:
- name: Start
community.general.proxmox_kvm:
state: started
register: start
- name: Wait 1.5 min # Initial apt update, apt upgrade, cloud-init
ansible.builtin.wait_for:
timeout: 90

View File

@@ -0,0 +1,42 @@
- name: Initialise VM
hosts: cloud
gather_facts: false
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Install system packages
ansible.builtin.apt:
update_cache: true
pkg:
- qemu-guest-agent
- parted
become: true
- name: Enable qemu-guest-agent
ansible.builtin.systemd:
name: qemu-guest-agent
state: started
enabled: true
become: true
- name: Create data partition
community.general.parted:
device: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1
label: gpt
name: data
number: 1
state: present
become: true
- name: Create data filesystem
community.general.filesystem:
dev: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1
fstype: ext4
become: true
- name: Mount data partition
ansible.posix.mount:
src: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1
path: /var/lib/docker
fstype: ext4
opts: rw,errors=remount-ro,x-systemd.growfs
state: mounted
become: true

View File

@@ -0,0 +1,47 @@
- name: Install docker
hosts: cloud
gather_facts: false
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Install dependencies
ansible.builtin.apt:
update_cache: true
pkg:
- curl
- python3-apt
- gpg
become: true
- name: Add docker key
ansible.builtin.apt_key:
url: https://download.docker.com/linux/debian/gpg
keyring: /etc/apt/keyrings/docker.gpg
become: true
- name: Add docker repo
ansible.builtin.apt_repository:
repo: deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable
become: true
- name: Install docker
ansible.builtin.apt:
update_cache: true
pkg:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-buildx-plugin
- docker-compose-plugin
become: true
- name: Add user to docker group
ansible.builtin.user:
user: debian
groups:
- docker
append: true
become: true
- name: Enable docker
ansible.builtin.systemd:
name: docker
state: started
enabled: true
become: true

View File

@@ -0,0 +1,13 @@
- name: Cleanup old ~/nextcloud directory
hosts: cloud
gather_facts: false
vars:
app: nextcloud
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Delete nextcloud directory
ansible.builtin.file:
path: "$HOME/{{ app }}"
state: absent

View File

@@ -0,0 +1,30 @@
- name: Deploy app
hosts: cloud
gather_facts: false
vars:
container: nextcloud-aio-mastercontainer
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Deploy master container
community.docker.docker_container:
image: nextcloud/all-in-one:latest
recreate: true
state: started
restart_policy: unless-stopped
init: true
name: "{{ container }}"
published_ports:
- 8080:8080
env:
NEXTCLOUD_UPLOAD_LIMIT: 16G
NEXTCLOUD_MAX_TIME: "7200"
NEXTCLOUD_ADDITIONAL_APKS: imagemagick ffmpeg
APACHE_PORT: "11000"
APACHE_IP_BINDING: "0.0.0.0"
TZ: Europe/London
AIO_DISABLE_BACKUP_SECTION: "true"
volumes:
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config
- /var/run/docker.sock:/var/run/docker.sock:ro

View File

@@ -1,25 +0,0 @@
- name: Setup Software
hosts: joplin
gather_facts: false
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Test some stuff
ansible.builtin.shell: |
touch ~/hmm
echo test > ~/test
echo test2 >> ~/test
mkdir ~/dir
touch ~/dir/testing
- name: Install some stuff
ansible.builtin.apt:
update_cache: true
name: qemu-guest-agent
become: true
- name: Enable some stuff
ansible.builtin.systemd:
name: qemu-guest-agent
state: started
enabled: true
become: true

View File

@@ -0,0 +1,118 @@
- name: Provision music Proxmox VM
hosts: music
connection: ansible.builtin.local
gather_facts: false
vars:
api_user: "{{ lookup('ansible.builtin.env', 'PROXMOX_USER') }}"
api_host: "{{ lookup('ansible.builtin.env', 'PROXMOX_HOST' ) }}"
api_token_id: "{{ lookup('ansible.builtin.env', 'PROXMOX_TOKEN_ID') }}"
api_token_secret: "{{ lookup('ansible.builtin.env', 'PROXMOX_TOKEN_SECRET') }}"
ssh_public: "{{ lookup('ansible.builtin.env', 'SSH_PUBLIC') }}"
vmname: "{{ inventory_hostname | regex_replace('^([^\\.]+)\\..+$', '\\1') }}"
node: pve2
module_defaults:
community.general.proxmox_kvm:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
node: "{{ node }}"
community.general.proxmox_nic:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
community.general.proxmox_disk:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
tasks:
# Initial setup
- name: Create VM
community.general.proxmox_kvm:
clone: "{{ node }}-debian-12"
storage: nvme
notify: Initial boot
- name: Wait for status
community.general.proxmox_kvm:
state: current
register: vm
retries: 30
delay: 10
until: vm.status is defined
# Networking and initial config
- name: Add PUB NIC
community.general.proxmox_nic:
interface: net0
firewall: false
bridge: PUB
- name: Add SRV NIC
community.general.proxmox_nic:
interface: net1
firewall: false
bridge: SRV
- name: Configure cloud-init
community.general.proxmox_kvm:
update: true
ciuser: debian
sshkeys: "{{ ssh_public }}"
ipconfig:
ipconfig0: ip=dhcp,ip6=auto
ipconfig1: ip=dhcp
- name: Force all notified handlers to run
ansible.builtin.meta: flush_handlers
# VM Configuration
- name: Resize root disk
community.general.proxmox_disk:
disk: scsi0
size: 16G
state: resized
- name: Create data disk
community.general.proxmox_disk:
disk: scsi1
backup: true
storage: nvme
size: 64
- name: Create media disk
community.general.proxmox_disk:
disk: scsi2
backup: false
storage: nvme
size: 1024
- name: Update VM
community.general.proxmox_kvm:
update: true
agent: enabled=1
tags:
- debian-12
- managed
onboot: true
cores: 8
memory: 16384
- name: Retart VM
community.general.proxmox_kvm:
state: restarted
timeout: 60
handlers:
# Initial boot
# For some reason debian cloud images don't use
# cloud-init for networking on first boot (cloud-init files
# are regenerated AFTER networking starts). But we need the
# hostname to be registered with DHCP later on so ¯\_(ツ)_/¯
- name: Initial boot
block:
- name: Start
community.general.proxmox_kvm:
state: started
register: start
- name: Wait 1.5 min # Initial apt update, apt upgrade, cloud-init
ansible.builtin.wait_for:
timeout: 90

View File

@@ -0,0 +1,64 @@
- name: Initialise VM
hosts: music
gather_facts: false
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Install system packages
ansible.builtin.apt:
update_cache: true
pkg:
- qemu-guest-agent
- parted
become: true
- name: Enable qemu-guest-agent
ansible.builtin.systemd:
name: qemu-guest-agent
state: started
enabled: true
become: true
- name: Create data partition
community.general.parted:
device: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1
label: gpt
name: data
number: 1
state: present
become: true
- name: Create data filesystem
community.general.filesystem:
dev: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1
fstype: ext4
become: true
- name: Mount data partition
ansible.posix.mount:
src: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1
path: /var/lib/docker
fstype: ext4
opts: rw,errors=remount-ro,x-systemd.growfs
state: mounted
become: true
- name: Create media partition
community.general.parted:
device: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:2
label: gpt
name: media
number: 1
state: present
become: true
- name: Create media filesystem
community.general.filesystem:
dev: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:2-part1
fstype: ext4
become: true
- name: Mount media partition
ansible.posix.mount:
src: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:2-part1
path: /mnt/media
fstype: ext4
opts: rw,errors=remount-ro,x-systemd.growfs
state: mounted
become: true

View File

@@ -0,0 +1,47 @@
- name: Install docker
hosts: music
gather_facts: false
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Install dependencies
ansible.builtin.apt:
update_cache: true
pkg:
- curl
- python3-apt
- gpg
become: true
- name: Add docker key
ansible.builtin.apt_key:
url: https://download.docker.com/linux/debian/gpg
keyring: /etc/apt/keyrings/docker.gpg
become: true
- name: Add docker repo
ansible.builtin.apt_repository:
repo: deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable
become: true
- name: Install docker
ansible.builtin.apt:
update_cache: true
pkg:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-buildx-plugin
- docker-compose-plugin
become: true
- name: Add user to docker group
ansible.builtin.user:
user: debian
groups:
- docker
append: true
become: true
- name: Enable docker
ansible.builtin.systemd:
name: docker
state: started
enabled: true
become: true

View File

@@ -0,0 +1,60 @@
- name: Deploy app
hosts: music
gather_facts: false
vars:
app: music
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Docker compose down
community.docker.docker_compose_v2:
project_src: "$HOME/{{ app }}"
state: absent
- name: Copy project
ansible.builtin.copy:
src: "./{{ app }}"
dest: "$HOME"
mode: "0744"
- name: Replace LastFM API key secret
ansible.builtin.replace:
path: "$HOME/{{ app }}/.env"
regexp: "LASTFM_APIKEY_VALUE"
replace: "{{ lookup('infisical.vault.read_secrets', env_slug='prod', path='/music', secret_name='LASTFM_APIKEY')['value'] }}"
- name: Replace LastFM secret
ansible.builtin.replace:
path: "$HOME/{{ app }}/.env"
regexp: "LASTFM_SECRET_VALUE"
replace: "{{ lookup('infisical.vault.read_secrets', env_slug='prod', path='/music', secret_name='LASTFM_SECRET')['value'] }}"
- name: Replace Mongo Password secret
ansible.builtin.replace:
path: "$HOME/{{ app }}/.env"
regexp: "SPOTIFY_ID_VALUE"
replace: "{{ lookup('infisical.vault.read_secrets', env_slug='prod', path='/music', secret_name='SPOTIFY_ID')['value'] }}"
- name: Replace SMTP Password secret
ansible.builtin.replace:
path: "$HOME/{{ app }}/.env"
regexp: "SPOTIFY_SECRET_VALUE"
replace: "{{ lookup('infisical.vault.read_secrets', env_slug='prod', path='/music', secret_name='SPOTIFY_SECRET')['value'] }}"
- name: Docker compose up
community.docker.docker_compose_v2:
project_src: "$HOME/{{ app }}"
- name: Update data permissions
ansible.builtin.file:
path: /mnt/nvme
state: directory
recurse: true
owner: debian
group: debian
become: true
- name: Update media permissions
ansible.builtin.file:
path: /mnt/media
state: directory
recurse: true
owner: debian
group: debian
become: true

4
infra/music/music/.env Normal file
View File

@@ -0,0 +1,4 @@
LASTFM_APIKEY=LASTFM_APIKEY_VALUE
LASTFM_SECRET=LASTFM_SECRET_VALUE
SPOTIFY_ID=SPOTIFY_ID_VALUE
SPOTIFY_SECRET=SPOTIFY_SECRET_VALUE

1
infra/music/music/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
!.env

View File

@@ -0,0 +1,52 @@
version: "3"
services:
navidrome:
image: deluan/navidrome:latest
restart: unless-stopped
user: 1000:1000
ports:
- 4533:4533
env_file: .env
environment:
- ND_BASEURL=https://music.koval.net
- ND_LASTFM_APIKEY=${LASTFM_APIKEY}
- ND_LASTFM_SECRET=${LASTFM_SECRET}
- ND_SPOTIFY_ID=${SPOTIFY_ID}
- ND_SPOTIFY_SECRET=${SPOTIFY_SECRET}
- ND_COVERARTPRIORITY=cover.*, folder.*, front.*, external, embedded
volumes:
- /mnt/nvme/navidrome:/data
- /mnt/media/music:/music:ro
metube:
image: ghcr.io/alexta69/metube
restart: unless-stopped
ports:
- 8081:8081
environment:
- STATE_DIR=/data/.metube
- TEMP_DIR=/data/downloads
volumes:
- /mnt/nvme/metube:/data
- /mnt/media/downloads:/downloads
picard:
image: mikenye/picard:latest
restart: unless-stopped
ports:
- 5800:5800
volumes:
- /mnt/nvme/picard:/config:rw
- /mnt/media/music:/storage/music:rw
- /mnt/media/downloads:/storage/downloads:rw
filebrowser:
image: filebrowser/filebrowser
restart: unless-stopped
user: 1000:1000
ports:
- 8080:80
environment:
- FB_DATABASE=/config/database.db
volumes:
- /mnt/nvme/filebrowser:/config
- /mnt/media/downloads:/srv/downloads
- /mnt/media/music:/srv/music

View File

@@ -0,0 +1,118 @@
- name: Provision photos Proxmox VM
hosts: photos
connection: ansible.builtin.local
gather_facts: false
vars:
api_user: "{{ lookup('ansible.builtin.env', 'PROXMOX_USER') }}"
api_host: "{{ lookup('ansible.builtin.env', 'PROXMOX_HOST' ) }}"
api_token_id: "{{ lookup('ansible.builtin.env', 'PROXMOX_TOKEN_ID') }}"
api_token_secret: "{{ lookup('ansible.builtin.env', 'PROXMOX_TOKEN_SECRET') }}"
ssh_public: "{{ lookup('ansible.builtin.env', 'SSH_PUBLIC') }}"
vmname: "{{ inventory_hostname | regex_replace('^([^\\.]+)\\..+$', '\\1') }}"
node: pve
module_defaults:
community.general.proxmox_kvm:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
node: "{{ node }}"
community.general.proxmox_nic:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
community.general.proxmox_disk:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
tasks:
# Initial setup
- name: Create VM
community.general.proxmox_kvm:
clone: "{{ node }}-debian-12"
storage: nvme
notify: Initial boot
- name: Wait for status
community.general.proxmox_kvm:
state: current
register: vm
retries: 30
delay: 10
until: vm.status is defined
# Networking and initial config
- name: Add PUB NIC
community.general.proxmox_nic:
interface: net0
firewall: false
bridge: PUB
- name: Add SRV NIC
community.general.proxmox_nic:
interface: net1
firewall: false
bridge: SRV
- name: Configure cloud-init
community.general.proxmox_kvm:
update: true
ciuser: debian
sshkeys: "{{ ssh_public }}"
ipconfig:
ipconfig0: ip=dhcp,ip6=auto
ipconfig1: ip=dhcp
- name: Force all notified handlers to run
ansible.builtin.meta: flush_handlers
# VM Configuration
- name: Resize root disk
community.general.proxmox_disk:
disk: scsi0
size: 16G
state: resized
- name: Create data disk
community.general.proxmox_disk:
disk: scsi1
backup: true
storage: nvme
size: 64
- name: Create media disk
community.general.proxmox_disk:
disk: scsi2
backup: true
storage: nvme
size: 2048
- name: Update VM
community.general.proxmox_kvm:
update: true
agent: enabled=1
tags:
- debian-12
- managed
onboot: true
cores: 8
memory: 16384
- name: Retart VM
community.general.proxmox_kvm:
state: restarted
timeout: 60
handlers:
# Initial boot
# For some reason debian cloud images don't use
# cloud-init for networking on first boot (cloud-init files
# are regenerated AFTER networking starts). But we need the
# hostname to be registered with DHCP later on so ¯\_(ツ)_/¯
- name: Initial boot
block:
- name: Start
community.general.proxmox_kvm:
state: started
register: start
- name: Wait 1.5 min # Initial apt update, apt upgrade, cloud-init
ansible.builtin.wait_for:
timeout: 90

View File

@@ -0,0 +1,64 @@
- name: Initialise VM
hosts: photos
gather_facts: false
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Install system packages
ansible.builtin.apt:
update_cache: true
pkg:
- qemu-guest-agent
- parted
become: true
- name: Enable qemu-guest-agent
ansible.builtin.systemd:
name: qemu-guest-agent
state: started
enabled: true
become: true
- name: Create data partition
community.general.parted:
device: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1
label: gpt
name: data
number: 1
state: present
become: true
- name: Create data filesystem
community.general.filesystem:
dev: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1
fstype: ext4
become: true
- name: Mount data partition
ansible.posix.mount:
src: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1
path: /var/lib/docker
fstype: ext4
opts: rw,errors=remount-ro,x-systemd.growfs
state: mounted
become: true
- name: Create media partition
community.general.parted:
device: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:2
label: gpt
name: media
number: 1
state: present
become: true
- name: Create media filesystem
community.general.filesystem:
dev: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:2-part1
fstype: ext4
become: true
- name: Mount media partition
ansible.posix.mount:
src: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:2-part1
path: /mnt/media
fstype: ext4
opts: rw,errors=remount-ro,x-systemd.growfs
state: mounted
become: true

View File

@@ -0,0 +1,47 @@
- name: Install docker
hosts: photos
gather_facts: false
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Install dependencies
ansible.builtin.apt:
update_cache: true
pkg:
- curl
- python3-apt
- gpg
become: true
- name: Add docker key
ansible.builtin.apt_key:
url: https://download.docker.com/linux/debian/gpg
keyring: /etc/apt/keyrings/docker.gpg
become: true
- name: Add docker repo
ansible.builtin.apt_repository:
repo: deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable
become: true
- name: Install docker
ansible.builtin.apt:
update_cache: true
pkg:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-buildx-plugin
- docker-compose-plugin
become: true
- name: Add user to docker group
ansible.builtin.user:
user: debian
groups:
- docker
append: true
become: true
- name: Enable docker
ansible.builtin.systemd:
name: docker
state: started
enabled: true
become: true

View File

@@ -0,0 +1,31 @@
- name: Deploy app
hosts: photos
gather_facts: false
vars:
app: immich
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Docker compose down
community.docker.docker_compose_v2:
project_src: "$HOME/{{ app }}"
state: absent
- name: Copy project
ansible.builtin.copy:
src: "./{{ app }}"
dest: "$HOME"
mode: "0744"
- name: Replace Typesense secret
ansible.builtin.replace:
path: "$HOME/{{ app }}/.env"
regexp: "TYPESENSE_API_KEY_VALUE"
replace: "{{ lookup('infisical.vault.read_secrets', env_slug='prod', path='/photos', secret_name='TYPESENSE_API_KEY')['value'] }}"
- name: Replace DB secret
ansible.builtin.replace:
path: "$HOME/{{ app }}/.env"
regexp: "DB_PASSWORD_VALUE"
replace: "{{ lookup('infisical.vault.read_secrets', env_slug='prod', path='/photos', secret_name='DB_PASSWORD')['value'] }}"
- name: Docker compose up -d
community.docker.docker_compose_v2:
project_src: "$HOME/{{ app }}"

22
infra/photos/immich/.env Normal file
View File

@@ -0,0 +1,22 @@
# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables
# The location where your uploaded files are stored
UPLOAD_LOCATION=/mnt/media/immich
# The Immich version to use. You can pin this to a specific version like "v1.71.0"
IMMICH_VERSION=release
# Connection secrets for postgres and typesense. You should change these to random passwords
TYPESENSE_API_KEY=TYPESENSE_API_KEY_VALUE
DB_PASSWORD=DB_PASSWORD_VALUE
# Other
PUBLIC_LOGIN_PAGE_MESSAGE="KovalHome Photos & Videos"
# The values below this line do not need to be changed
###################################################################################
DB_HOSTNAME=immich_postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
REDIS_HOSTNAME=immich_redis

1
infra/photos/immich/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
!.env

View File

@@ -0,0 +1,64 @@
version: "3.8"
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
command: ["start.sh", "immich"]
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
env_file:
- .env
ports:
- 2283:3001
depends_on:
- redis
- database
restart: always
immich-microservices:
container_name: immich_microservices
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
# extends:
# file: hwaccel.yml
# service: hwaccel
command: ["start.sh", "microservices"]
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
env_file:
- .env
depends_on:
- redis
- database
restart: always
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
volumes:
- model-cache:/cache
env_file:
- .env
restart: always
redis:
container_name: immich_redis
image: redis:6.2-alpine@sha256:70a7a5b641117670beae0d80658430853896b5ef269ccf00d1827427e3263fa3
restart: always
database:
container_name: immich_postgres
image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0
env_file:
- .env
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
volumes:
- pgdata:/var/lib/postgresql/data
restart: always
volumes:
pgdata:
model-cache:

View File

@@ -0,0 +1,117 @@
- name: Provision samba Proxmox VM
hosts: samba
connection: ansible.builtin.local
gather_facts: false
vars:
api_user: "{{ lookup('ansible.builtin.env', 'PROXMOX_USER') }}"
api_host: "{{ lookup('ansible.builtin.env', 'PROXMOX_HOST' ) }}"
api_token_id: "{{ lookup('ansible.builtin.env', 'PROXMOX_TOKEN_ID') }}"
api_token_secret: "{{ lookup('ansible.builtin.env', 'PROXMOX_TOKEN_SECRET') }}"
ssh_public: "{{ lookup('ansible.builtin.env', 'SSH_PUBLIC') }}"
vmname: "{{ inventory_hostname | regex_replace('^([^\\.]+)\\..+$', '\\1') }}"
node: pve
module_defaults:
community.general.proxmox_kvm:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
node: "{{ node }}"
community.general.proxmox_nic:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
community.general.proxmox_disk:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
tasks:
# Initial setup
- name: Create VM
community.general.proxmox_kvm:
clone: "{{ node }}-debian-12"
storage: nvme
notify: Initial boot
- name: Wait for status
community.general.proxmox_kvm:
state: current
register: vm
retries: 30
delay: 10
until: vm.status is defined
# Networking and initial config
- name: Add PUB NIC
community.general.proxmox_nic:
interface: net0
firewall: false
bridge: PUB
- name: Add SRV NIC
community.general.proxmox_nic:
interface: net1
firewall: false
bridge: SRV
- name: Configure cloud-init
community.general.proxmox_kvm:
update: true
ciuser: debian
sshkeys: "{{ ssh_public }}"
ipconfig:
ipconfig0: ip=dhcp,ip6=auto
ipconfig1: ip=dhcp
- name: Force all notified handlers to run
ansible.builtin.meta: flush_handlers
# VM Configuration
- name: Resize root disk
community.general.proxmox_disk:
disk: scsi0
size: 16G
state: resized
- name: Create data disk
community.general.proxmox_disk:
disk: scsi1
backup: true
storage: nvme
size: 64
- name: Create share disk
community.general.proxmox_disk:
disk: scsi2
backup: false
storage: zfs
size: 2048
- name: Update VM
community.general.proxmox_kvm:
update: true
agent: enabled=1
tags:
- debian-12
- managed
onboot: true
cores: 4
memory: 8192
- name: Retart VM
community.general.proxmox_kvm:
state: restarted
timeout: 60
handlers:
# Initial boot
# For some reason debian cloud images don't use
# cloud-init for networking on first boot (cloud-init files
# are regenerated AFTER networking starts). But we need the
# hostname to be registered with DHCP later on so ¯\_(ツ)_/¯
- name: Initial boot
block:
- name: Start
community.general.proxmox_kvm:
state: started
register: start
- name: Wait 1.5 min # Initial apt update, apt upgrade, cloud-init
ansible.builtin.wait_for:
timeout: 90

View File

@@ -0,0 +1,65 @@
- name: Initialise VM
hosts: samba
gather_facts: false
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Install system packages
ansible.builtin.apt:
update_cache: true
pkg:
- qemu-guest-agent
- parted
become: true
- name: Enable qemu-guest-agent
ansible.builtin.systemd:
name: qemu-guest-agent
state: started
enabled: true
become: true
- name: Create data partition
community.general.parted:
device: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1
label: gpt
name: data
number: 1
state: present
become: true
- name: Create data filesystem
community.general.filesystem:
dev: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1
fstype: ext4
become: true
- name: Mount data partition
ansible.posix.mount:
src: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1
path: /var/lib/docker/volumes
fstype: ext4
opts: rw,errors=remount-ro,x-systemd.growfs
state: mounted
become: true
- name: Create share partition
community.general.parted:
device: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:2
label: gpt
name: data
number: 1
state: present
become: true
- name: Create share filesystem
community.general.filesystem:
dev: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:2-part1
fstype: ext4
become: true
- name: Mount data partition
ansible.posix.mount:
src: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:2-part1
path: /mnt/share
fstype: ext4
opts: rw,errors=remount-ro,x-systemd.growfs
state: mounted
become: true

View File

@@ -0,0 +1,48 @@
- name: Install docker
hosts: samba
gather_facts: false
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Install dependencies
ansible.builtin.apt:
update_cache: true
pkg:
- curl
- python3-apt
- gpg
become: true
- name: Add docker key
ansible.builtin.apt_key:
url: https://download.docker.com/linux/debian/gpg
keyring: /etc/apt/keyrings/docker.gpg
become: true
- name: Add docker repo
ansible.builtin.apt_repository:
repo: deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable
become: true
- name: Install docker
ansible.builtin.apt:
update_cache: true
pkg:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-buildx-plugin
- docker-compose-plugin
become: true
- name: Add user to docker group
ansible.builtin.user:
user: debian
groups:
- docker
append: true
become: true
- name: Enable docker
ansible.builtin.systemd:
name: docker
state: started
enabled: true
become: true

View File

@@ -0,0 +1,37 @@
- name: Deploy app
hosts: samba
gather_facts: false
vars:
app: samba
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Docker compose down
community.docker.docker_compose_v2:
project_src: "$HOME/{{ app }}"
state: absent
- name: Copy project
ansible.builtin.copy:
src: "./{{ app }}"
dest: "$HOME"
mode: "0744"
- name: Replace KVK Password secret
ansible.builtin.replace:
path: "$HOME/{{ app }}/config.yml"
regexp: "KVK_PASSWORD"
replace: "{{ lookup('infisical.vault.read_secrets', env_slug='prod', path='/samba', secret_name='KVK_PASSWORD')['value'] }}"
- name: Docker compose up
community.docker.docker_compose_v2:
project_src: "$HOME/{{ app }}"
- name: Update samba permissions
ansible.builtin.file:
path: /mnt/share/samba
state: directory
recurse: true
owner: debian
group: debian
become: true

View File

@@ -0,0 +1,26 @@
auth:
- user: debian
group: debian
uid: 1000
gid: 1000
- user: kvk
group: kvk
uid: 1001
gid: 1001
password: KVK_PASSWORD
global:
- "force user = debian"
- "force group = debian"
share:
- name: kvkbackups
comment: KVK Backups
path: /samba/kvkbackups
validusers: kvk
writelist: kvk
browsable: true
readonly: false
guestok: false
veto: false

View File

@@ -0,0 +1,16 @@
version: "3"
services:
samba:
image: crazymax/samba
restart: unless-stopped
network_mode: host
volumes:
- samba-data:/data
- ./config.yml:/data/config.yml
- /mnt/share/samba/kvkbackups:/samba/kvkbackups
environment:
- TZ=Europe/London
volumes:
samba-data:

View File

@@ -0,0 +1,112 @@
- name: Provision secrets Proxmox VM
hosts: secrets
connection: ansible.builtin.local
gather_facts: false
vars:
api_user: "{{ lookup('ansible.builtin.env', 'PROXMOX_USER') }}"
api_host: "{{ lookup('ansible.builtin.env', 'PROXMOX_HOST' ) }}"
api_token_id: "{{ lookup('ansible.builtin.env', 'PROXMOX_TOKEN_ID') }}"
api_token_secret: "{{ lookup('ansible.builtin.env', 'PROXMOX_TOKEN_SECRET') }}"
ssh_public: "{{ lookup('ansible.builtin.env', 'SSH_PUBLIC') }}"
vmname: "{{ inventory_hostname | regex_replace('^([^\\.]+)\\..+$', '\\1') }}"
node: pve2
module_defaults:
community.general.proxmox_kvm:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
node: "{{ node }}"
community.general.proxmox_nic:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
community.general.proxmox_disk:
api_user: "{{ api_user }}"
api_host: "{{ api_host }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ api_token_secret }}"
name: "{{ vmname }}"
tasks:
# Initial setup
- name: Create VM
community.general.proxmox_kvm:
clone: "{{ node }}-debian-12"
storage: nvme
notify: Initial boot
- name: Wait for status
community.general.proxmox_kvm:
state: current
register: vm
retries: 30
delay: 10
until: vm.status is defined
# Networking and initial config
- name: Add PUB NIC
community.general.proxmox_nic:
interface: net0
firewall: false
bridge: PUB
- name: Add SRV NIC
community.general.proxmox_nic:
interface: net1
firewall: false
bridge: SRV
- name: Configure cloud-init
community.general.proxmox_kvm:
update: true
ciuser: debian
sshkeys: "{{ ssh_public }}"
ipconfig:
ipconfig0: ip=dhcp,ip6=auto
ipconfig1: ip=dhcp
- name: Force all notified handlers to run
ansible.builtin.meta: flush_handlers
# VM Configuration
- name: Resize root disk
community.general.proxmox_disk:
disk: scsi0
size: 16G
state: resized
- name: Create data disk
community.general.proxmox_disk:
disk: scsi1
backup: true
storage: nvme
size: 64
- name: Update VM
community.general.proxmox_kvm:
update: true
agent: enabled=1
tags:
- debian-12
- managed
onboot: true
cores: 4
memory: 4096
cpu: x86-64-v3,flags=+spec-ctrl;+aes
- name: Retart VM
community.general.proxmox_kvm:
state: restarted
timeout: 60
handlers:
# Initial boot
# For some reason debian cloud images don't use
# cloud-init for networking on first boot (cloud-init files
# are regenerated AFTER networking starts). But we need the
# hostname to be registered with DHCP later on so ¯\_(ツ)_/¯
- name: Initial boot
block:
- name: Start
community.general.proxmox_kvm:
state: started
register: start
- name: Wait 1.5 min # Initial apt update, apt upgrade, cloud-init
ansible.builtin.wait_for:
timeout: 90

View File

@@ -0,0 +1,42 @@
- name: Initialise VM
hosts: secrets
gather_facts: false
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Install system packages
ansible.builtin.apt:
update_cache: true
pkg:
- qemu-guest-agent
- parted
become: true
- name: Enable qemu-guest-agent
ansible.builtin.systemd:
name: qemu-guest-agent
state: started
enabled: true
become: true
- name: Create data partition
community.general.parted:
device: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1
label: gpt
name: data
number: 1
state: present
become: true
- name: Create data filesystem
community.general.filesystem:
dev: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1
fstype: ext4
become: true
- name: Mount data partition
ansible.posix.mount:
src: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1
path: /var/lib/docker
fstype: ext4
opts: rw,errors=remount-ro,x-systemd.growfs
state: mounted
become: true

View File

@@ -0,0 +1,48 @@
- name: Install docker
hosts: secrets
gather_facts: false
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Install dependencies
ansible.builtin.apt:
update_cache: true
pkg:
- curl
- python3-apt
- gpg
become: true
- name: Add docker key
ansible.builtin.apt_key:
url: https://download.docker.com/linux/debian/gpg
keyring: /etc/apt/keyrings/docker.gpg
become: true
- name: Add docker repo
ansible.builtin.apt_repository:
repo: deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable
become: true
- name: Install docker
ansible.builtin.apt:
update_cache: true
pkg:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-buildx-plugin
- docker-compose-plugin
become: true
- name: Add user to docker group
ansible.builtin.user:
user: debian
groups:
- docker
append: true
become: true
- name: Enable docker
ansible.builtin.systemd:
name: docker
state: started
enabled: true
become: true

View File

@@ -0,0 +1,37 @@
- name: Deploy app
hosts: secrets
gather_facts: false
vars:
app: infisical
tasks:
- name: Wait for connection
ansible.builtin.wait_for_connection:
timeout: 300
- name: Docker compose down
community.docker.docker_compose_v2:
project_src: "$HOME/{{ app }}"
state: absent
- name: Copy project
ansible.builtin.copy:
src: "./{{ app }}"
dest: "$HOME"
mode: "0744"
- name: Replace Encryption Key secret
ansible.builtin.replace:
path: "$HOME/{{ app }}/.env"
regexp: "ENCRYPTION_KEY_VALUE"
replace: "{{ lookup('ansible.builtin.env', 'INFISICAL_ENCRYPTION_KEY') }}"
- name: Replace Auth secret
ansible.builtin.replace:
path: "$HOME/{{ app }}/.env"
regexp: "AUTH_SECRET_VALUE"
replace: "{{ lookup('ansible.builtin.env', 'INFISICAL_AUTH_SECRET') }}"
- name: Replace SMTP Password secret
ansible.builtin.replace:
path: "$HOME/{{ app }}/.env"
regexp: "SMTP_PASSWORD_VALUE"
replace: "{{ lookup('ansible.builtin.env', 'SMTP_PASSWORD') }}"
- name: Docker compose up -d
community.docker.docker_compose_v2:
project_src: "$HOME/{{ app }}"

View File

@@ -0,0 +1,71 @@
# Keys
# Required key for platform encryption/decryption ops
# THIS IS A SAMPLE ENCRYPTION KEY AND SHOULD NEVER BE USED FOR PRODUCTION
ENCRYPTION_KEY=ENCRYPTION_KEY_VALUE
# JWT
# Required secrets to sign JWT tokens
# THIS IS A SAMPLE AUTH_SECRET KEY AND SHOULD NEVER BE USED FOR PRODUCTION
AUTH_SECRET=AUTH_SECRET_VALUE
# Postgres creds
POSTGRES_PASSWORD=infisical
POSTGRES_USER=infisical
POSTGRES_DB=infisical
# Required
DB_CONNECTION_URI=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
# Redis
REDIS_URL=redis://redis:6379
# Website URL
# Required
SITE_URL=https://secrets.koval.net
# Mail/SMTP
SMTP_HOST=mx.koval.net
SMTP_PORT=465
SMTP_SECURE=true
SMTP_USERNAME=no-reply@koval.net
SMTP_PASSWORD=SMTP_PASSWORD_VALUE
SMTP_FROM_NAME=KovalHome Infisical
SMTP_FROM_ADDRESS=no-reply@koval.net
# Integration
# Optional only if integration is used
CLIENT_ID_HEROKU=
CLIENT_ID_VERCEL=
CLIENT_ID_NETLIFY=
CLIENT_ID_GITHUB=
CLIENT_ID_GITLAB=
CLIENT_ID_BITBUCKET=
CLIENT_SECRET_HEROKU=
CLIENT_SECRET_VERCEL=
CLIENT_SECRET_NETLIFY=
CLIENT_SECRET_GITHUB=
CLIENT_SECRET_GITLAB=
CLIENT_SECRET_BITBUCKET=
CLIENT_SLUG_VERCEL=
# Sentry (optional) for monitoring errors
SENTRY_DSN=
# Infisical Cloud-specific configs
# Ignore - Not applicable for self-hosted version
POSTHOG_HOST=
POSTHOG_PROJECT_API_KEY=
# SSO-specific variables
CLIENT_ID_GOOGLE_LOGIN=
CLIENT_SECRET_GOOGLE_LOGIN=
CLIENT_ID_GITHUB_LOGIN=
CLIENT_SECRET_GITHUB_LOGIN=
CLIENT_ID_GITLAB_LOGIN=
CLIENT_SECRET_GITLAB_LOGIN=
# Other
INVITE_ONLY_SIGNUP=true
TELEMETRY_ENABLED=false

1
infra/secrets/infisical/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
!.env

View File

@@ -0,0 +1,50 @@
version: "3"
services:
db-migration:
depends_on:
db:
condition: service_healthy
image: infisical/infisical:latest-postgres
env_file: .env
command: npm run migration:latest
pull_policy: always
backend:
restart: unless-stopped
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db-migration:
condition: service_completed_successfully
image: infisical/infisical:latest-postgres
pull_policy: always
env_file: .env
ports:
- 80:8080
environment:
- NODE_ENV=production
redis:
image: redis
env_file: .env
environment:
- ALLOW_EMPTY_PASSWORD=yes
ports:
- 6379:6379
volumes:
- /mnt/nvme/redis_data:/data
db:
image: postgres:14-alpine
restart: always
env_file: .env
volumes:
- /mnt/nvme/pg_data:/var/lib/postgresql/data
healthcheck:
test: "pg_isready --username=${POSTGRES_USER} && psql --username=${POSTGRES_USER} --list"
interval: 5s
timeout: 10s
retries: 10

View File

@@ -8,9 +8,21 @@ proxmox:
pve2.mgmt.home.local.koval.net: pve2.mgmt.home.local.koval.net:
managed: managed:
children: children:
joplin: cloud:
hosts: hosts:
joplin2.srv.home.local.koval.net: cloud.srv.home.local.koval.net:
photos:
hosts:
photos.srv.home.local.koval.net:
secrets:
hosts:
secrets.srv.home.local.koval.net:
music:
hosts:
music.srv.home.local.koval.net:
samba:
hosts:
samba.srv.home.local.koval.net:
vars: vars:
ansible_user: debian ansible_user: debian
ansible_ssh_private_key_file: ~/.ssh/id_rsa ansible_ssh_private_key_file: ~/.ssh/id_rsa

View File

@@ -1,3 +1,4 @@
ansible ansible
proxmoxer proxmoxer
requests requests
infisical

4
requirements.yml Normal file
View File

@@ -0,0 +1,4 @@
collections:
- name: community.general
- name: community.docker
- name: infisical.vault