Merge branch 'master' of https://git.mvl.sh/vleeuwenmenno/dotfiles
Some checks failed
Ansible Lint Check / check-ansible (push) Failing after 25s
Python Lint Check / check-python (push) Has been cancelled
Nix Format Check / check-format (push) Has been cancelled

This commit is contained in:
2025-07-15 23:50:53 +02:00
16 changed files with 246 additions and 106 deletions

View File

@@ -181,6 +181,6 @@ if [ -f $HOME/.bashrc.local ]; then
fi
# Display a welcome message for interactive shells
if [ -t 1 ] && command -v helloworld &> /dev/null; then
if [ -t 1 ]; then
helloworld
fi

View File

@@ -17,7 +17,7 @@ def get_password():
# Try to get the password
success, output = run_command(
[op_cmd, "read", "op://j7nmhqlsjmp2r6umly5t75hzb4/Dotfiles Secrets/password"]
[op_cmd, "read", "op://Dotfiles/Dotfiles Secrets/password"]
)
if not success:

View File

@@ -19,7 +19,7 @@
- name: Get Caddy email from 1Password
ansible.builtin.set_fact:
caddy_email: "{{ lookup('community.general.onepassword', 'qwvcr4cuumhqh3mschv57xdqka', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='email') }}"
caddy_email: "{{ lookup('community.general.onepassword', 'Caddy (Proxy)', vault='Dotfiles', field='email') }}"
ignore_errors: true
tags:
- caddy

View File

@@ -1,90 +1,94 @@
---
- name: Check if JuiceFS is already installed
ansible.builtin.command: which juicefs
register: juicefs_check
ignore_errors: true
changed_when: false
- name: JuiceFS Installation and Configuration
block:
- name: Check if JuiceFS is already installed
ansible.builtin.command: which juicefs
register: juicefs_check
ignore_errors: true
changed_when: false
- name: Install JuiceFS using the automatic installer
ansible.builtin.shell: curl -sSL https://d.juicefs.com/install | sh -
register: juicefs_installation
when: juicefs_check.rc != 0
become: true
- name: Install JuiceFS using the automatic installer
ansible.builtin.shell: curl -sSL https://d.juicefs.com/install | sh -
register: juicefs_installation
when: juicefs_check.rc != 0
become: true
- name: Verify JuiceFS installation
ansible.builtin.command: juicefs version
register: juicefs_version
changed_when: false
when: juicefs_check.rc != 0 or juicefs_installation.changed
- name: Verify JuiceFS installation
ansible.builtin.command: juicefs version
register: juicefs_version
changed_when: false
when: juicefs_check.rc != 0 or juicefs_installation.changed
- name: Create mount directory
ansible.builtin.file:
path: /mnt/object_storage
state: directory
mode: "0755"
become: true
- name: Create mount directory
ansible.builtin.file:
path: /mnt/object_storage
state: directory
mode: "0755"
become: true
- name: Create cache directory
ansible.builtin.file:
path: /var/jfsCache
state: directory
mode: "0755"
become: true
- name: Create cache directory
ansible.builtin.file:
path: /var/jfsCache
state: directory
mode: "0755"
become: true
- name: Configure JuiceFS network performance optimizations
ansible.builtin.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
state: present
reload: true
become: true
loop:
- { name: "net.core.rmem_max", value: "16777216" }
- { name: "net.core.wmem_max", value: "16777216" }
- { name: "net.ipv4.tcp_rmem", value: "4096 87380 16777216" }
- { name: "net.ipv4.tcp_wmem", value: "4096 65536 16777216" }
- name: Configure JuiceFS network performance optimizations
ansible.builtin.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
state: present
reload: true
become: true
loop:
- { name: "net.core.rmem_max", value: "16777216" }
- { name: "net.core.wmem_max", value: "16777216" }
- { name: "net.ipv4.tcp_rmem", value: "4096 87380 16777216" }
- { name: "net.ipv4.tcp_wmem", value: "4096 65536 16777216" }
- name: Set JuiceFS facts
ansible.builtin.set_fact:
hetzner_access_key: "{{ lookup('community.general.onepassword', 'mfk2qgnaplgtk6xmfc3r6w6neq', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='AWS_ACCESS_KEY_ID') }}"
hetzner_secret_key:
"{{ lookup('community.general.onepassword', 'mfk2qgnaplgtk6xmfc3r6w6neq', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='AWS_SECRET_ACCESS_KEY')
}}"
redis_password: "{{ lookup('community.general.onepassword', '4cioblm633bdkl6put35lk6ql4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='password') }}"
- name: Set JuiceFS facts
ansible.builtin.set_fact:
hetzner_access_key: "{{ lookup('community.general.onepassword', 'Hetzner Object Storage Bucket', vault='Dotfiles', field='AWS_ACCESS_KEY_ID') }}"
hetzner_secret_key:
"{{ lookup('community.general.onepassword', 'Hetzner Object Storage Bucket', vault='Dotfiles', field='AWS_SECRET_ACCESS_KEY')
}}"
redis_password: "{{ lookup('community.general.onepassword', 'JuiceFS (Redis)', vault='Dotfiles', field='password') }}"
- name: Create JuiceFS systemd service file
ansible.builtin.template:
src: templates/juicefs.service.j2
dest: /etc/systemd/system/juicefs.service
owner: root
group: root
mode: "0644"
become: true
- name: Create JuiceFS systemd service file
ansible.builtin.template:
src: templates/juicefs.service.j2
dest: /etc/systemd/system/juicefs.service
owner: root
group: root
mode: "0644"
become: true
- name: Reload systemd daemon
ansible.builtin.systemd:
daemon_reload: true
become: true
- name: Reload systemd daemon
ansible.builtin.systemd:
daemon_reload: true
become: true
- name: Include JuiceFS Redis tasks
ansible.builtin.include_tasks: services/redis/redis.yml
when: inventory_hostname == 'mennos-cloud-server'
- name: Include JuiceFS Redis tasks
ansible.builtin.include_tasks: services/redis/redis.yml
when: inventory_hostname == 'mennos-cloud-server'
- name: Enable and start JuiceFS service
ansible.builtin.systemd:
name: juicefs.service
enabled: true
state: started
become: true
- name: Enable and start JuiceFS service
ansible.builtin.systemd:
name: juicefs.service
enabled: true
state: started
become: true
- name: Check if JuiceFS is mounted
ansible.builtin.shell: df -h | grep /mnt/object_storage
become: true
register: mount_check
ignore_errors: true
changed_when: false
- name: Check if JuiceFS is mounted
ansible.builtin.shell: df -h | grep /mnt/object_storage
become: true
register: mount_check
ignore_errors: true
changed_when: false
- name: Display mount status
ansible.builtin.debug:
msg: "JuiceFS is successfully mounted at /mnt/object_storage"
when: mount_check.rc == 0
- name: Display mount status
ansible.builtin.debug:
msg: "JuiceFS is successfully mounted at /mnt/object_storage"
when: mount_check.rc == 0
tags:
- juicefs

View File

@@ -10,6 +10,8 @@
- name: Include JuiceFS tasks
ansible.builtin.include_tasks: juicefs.yml
tags:
- juicefs
- name: Include service tasks
ansible.builtin.include_tasks: "services/{{ item.name }}/{{ item.name }}.yml"
@@ -88,3 +90,7 @@
enabled: true
hosts:
- mennos-server
- name: unifi-network-application
enabled: true
hosts:
- mennos-cloud-server

View File

@@ -6,7 +6,7 @@
caddy_service_dir: "{{ ansible_env.HOME }}/services/caddy"
caddy_data_dir: "{{ '/mnt/services/caddy' if inventory_hostname == 'mennos-server' else '/mnt/object_storage/services/caddy' }}"
geoip_db_path: "{{ '/mnt/services/echoip' if inventory_hostname == 'mennos-server' else '/mnt/object_storage/services/echoip' }}"
caddy_email: "{{ lookup('community.general.onepassword', 'qwvcr4cuumhqh3mschv57xdqka', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='email') }}"
caddy_email: "{{ lookup('community.general.onepassword', 'Caddy (Proxy)', vault='Dotfiles', field='email') }}"
- name: Create Caddy directory
ansible.builtin.file:

View File

@@ -19,10 +19,10 @@ services:
environment:
- PUID=1000
- PGID=100
- VPN_SERVICE_PROVIDER={{ lookup('community.general.onepassword', 'qm7lxjrv2ctgzsjuwtolxpd5i4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='VPN_SERVICE_PROVIDER') }}
- OPENVPN_USER={{ lookup('community.general.onepassword', 'qm7lxjrv2ctgzsjuwtolxpd5i4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='OPENVPN_USER') }}
- OPENVPN_PASSWORD={{ lookup('community.general.onepassword', 'qm7lxjrv2ctgzsjuwtolxpd5i4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='OPENVPN_PASSWORD') }}
- SERVER_COUNTRIES={{ lookup('community.general.onepassword', 'qm7lxjrv2ctgzsjuwtolxpd5i4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='SERVER_COUNTRIES') }}
- VPN_SERVICE_PROVIDER={{ lookup('community.general.onepassword', 'Gluetun', vault='Dotfiles', field='VPN_SERVICE_PROVIDER') }}
- OPENVPN_USER={{ lookup('community.general.onepassword', 'Gluetun', vault='Dotfiles', field='OPENVPN_USER') }}
- OPENVPN_PASSWORD={{ lookup('community.general.onepassword', 'Gluetun', vault='Dotfiles', field='OPENVPN_PASSWORD') }}
- SERVER_COUNTRIES={{ lookup('community.general.onepassword', 'Gluetun', vault='Dotfiles', field='SERVER_COUNTRIES') }}
restart: always
sabnzbd:

View File

@@ -3,8 +3,6 @@ services:
container_name: 'echoip'
image: 'mpolden/echoip:latest'
restart: unless-stopped
ports:
- "8080:8080"
extra_hosts:
- "host.docker.internal:host-gateway"
networks:

View File

@@ -5,10 +5,10 @@
ansible.builtin.set_fact:
echoip_service_dir: "{{ ansible_env.HOME }}/services/echoip"
echoip_data_dir: "{{ '/mnt/services/echoip' if inventory_hostname == 'mennos-server' else '/mnt/object_storage/services/echoip' }}"
maxmind_account_id: "{{ lookup('community.general.onepassword', 'finpwvqp6evflzjcsnwge74n34',
vault='j7nmhqlsjmp2r6umly5t75hzb4', field='account_id') | regex_replace('\\s+', '') }}"
maxmind_license_key: "{{ lookup('community.general.onepassword', 'finpwvqp6evflzjcsnwge74n34',
vault='j7nmhqlsjmp2r6umly5t75hzb4', field='license_key') | regex_replace('\\s+', '') }}"
maxmind_account_id: "{{ lookup('community.general.onepassword', 'MaxMind',
vault='Dotfiles', field='account_id') | regex_replace('\\s+', '') }}"
maxmind_license_key: "{{ lookup('community.general.onepassword', 'MaxMind',
vault='Dotfiles', field='license_key') | regex_replace('\\s+', '') }}"
- name: Create EchoIP directory
ansible.builtin.file:

View File

@@ -23,7 +23,7 @@ services:
- PUID=1000
- PGID=100
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD={{ lookup('community.general.onepassword', '4gnclyzztfgqq7yxa3ctxs6tey', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='POSTGRES_PASSWORD') }}
- POSTGRES_PASSWORD={{ lookup('community.general.onepassword', 'Gitea', vault='Dotfiles', field='POSTGRES_PASSWORD') }}
- POSTGRES_DB=gitea
volumes:
- {{gitea_data_dir}}/postgres:/var/lib/postgresql/data
@@ -40,7 +40,7 @@ services:
- PUID=1000
- PGID=100
- GITEA_INSTANCE_URL=https://git.mvl.sh
- GITEA_RUNNER_REGISTRATION_TOKEN={{ lookup('community.general.onepassword', '4gnclyzztfgqq7yxa3ctxs6tey', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='GITEA_RUNNER_REGISTRATION_TOKEN') }}
- GITEA_RUNNER_REGISTRATION_TOKEN={{ lookup('community.general.onepassword', 'Gitea', vault='Dotfiles', field='GITEA_RUNNER_REGISTRATION_TOKEN') }}
- GITEA_RUNNER_NAME=act-worker
- CONFIG_FILE=/config.yaml
restart: always

View File

@@ -4,7 +4,7 @@ services:
image: ghcr.io/tailscale/golink:main
user: root
environment:
- TS_AUTHKEY={{ lookup('community.general.onepassword', '4gsgavajnxfpcrjvbkqhoc4drm', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='TS_AUTHKEY') }}
- TS_AUTHKEY={{ lookup('community.general.onepassword', 'GoLink', vault='Dotfiles', field='TS_AUTHKEY') }}
volumes:
- {{ golink_data_dir }}:/home/nonroot
restart: "unless-stopped"

View File

@@ -10,6 +10,6 @@ TZ=Europe/Amsterdam
PUID=1000
PGID=100
NEXTAUTH_SECRET="{{ lookup('community.general.onepassword', 'osnzlfidxonvetmomdgn7vxu5a', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='NEXTAUTH_SECRET') }}"
MEILI_MASTER_KEY="{{ lookup('community.general.onepassword', 'osnzlfidxonvetmomdgn7vxu5a', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='MEILI_MASTER_KEY') }}"
OPENAI_API_KEY="{{ lookup('community.general.onepassword', 'osnzlfidxonvetmomdgn7vxu5a', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='OPENAI_API_KEY') }}"
NEXTAUTH_SECRET="{{ lookup('community.general.onepassword', 'Kara Keep', vault='Dotfiles', field='NEXTAUTH_SECRET') }}"
MEILI_MASTER_KEY="{{ lookup('community.general.onepassword', 'Kara Keep', vault='Dotfiles', field='MEILI_MASTER_KEY') }}"
OPENAI_API_KEY="{{ lookup('community.general.onepassword', 'Kara Keep', vault='Dotfiles', field='OPENAI_API_KEY') }}"

View File

@@ -4,7 +4,7 @@
- name: Set Redis facts
ansible.builtin.set_fact:
redis_service_dir: "{{ ansible_env.HOME }}/services/juicefs-redis"
redis_password: "{{ lookup('community.general.onepassword', '4cioblm633bdkl6put35lk6ql4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='password') }}"
redis_password: "{{ lookup('community.general.onepassword', 'JuiceFS (Redis)', vault='Dotfiles', field='password') }}"
- name: Create Redis service directory
ansible.builtin.file:

View File

@@ -22,26 +22,26 @@
# Database settings
seafile_mysql_db_host: "db"
seafile_mysql_root_password: >
{{ lookup('community.general.onepassword', 'bbzudwdo3byqs4pscd2wy7qsn4',
vault='j7nmhqlsjmp2r6umly5t75hzb4', field='MYSQL_ROOT_PASSWORD') }}
{{ lookup('community.general.onepassword', 'Seafile',
vault='Dotfiles', field='MYSQL_ROOT_PASSWORD') }}
seafile_mysql_db_user: "seafile"
seafile_mysql_db_password: >
{{ lookup('community.general.onepassword', 'bbzudwdo3byqs4pscd2wy7qsn4',
vault='j7nmhqlsjmp2r6umly5t75hzb4', field='MYSQL_PASSWORD') }}
{{ lookup('community.general.onepassword', 'Seafile',
vault='Dotfiles', field='MYSQL_PASSWORD') }}
# Server settings
time_zone: "Europe/Amsterdam"
jwt_private_key: >
{{ lookup('community.general.onepassword', 'bbzudwdo3byqs4pscd2wy7qsn4',
vault='j7nmhqlsjmp2r6umly5t75hzb4', field='jwt_private_key') }}
{{ lookup('community.general.onepassword', 'Seafile',
vault='Dotfiles', field='jwt_private_key') }}
seafile_server_hostname: "sf.mvl.sh"
seafile_server_protocol: "https"
# Admin credentials
seafile_admin_email: "menno@vleeuwen.me"
seafile_admin_password: >
{{ lookup('community.general.onepassword', 'bbzudwdo3byqs4pscd2wy7qsn4',
vault='j7nmhqlsjmp2r6umly5t75hzb4', field='password') }}
{{ lookup('community.general.onepassword', 'Seafile',
vault='Dotfiles', field='password') }}
- name: Create Seafile directories
ansible.builtin.file:

View File

@@ -0,0 +1,54 @@
services:
unifi-controller:
image: linuxserver/unifi-network-application:latest
restart: unless-stopped
ports:
- "8080:8080" # Device communication
- "8443:8443" # Controller GUI / API
- "3478:3478/udp" # STUN
- "10001:10001/udp" # AP discovery
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Amsterdam
- MONGO_USER=unifi
- MONGO_PASS=unifi
- MONGO_HOST=unifi-db
- MONGO_PORT=27017
- MONGO_DBNAME=unifi
- MONGO_AUTHSOURCE=admin
volumes:
- {{ unifi_network_application_data_dir }}/data:/config
depends_on:
- unifi-db
networks:
- unifi-network
- caddy_network
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
unifi-db:
image: mongo:6.0
restart: unless-stopped
volumes:
- {{ unifi_network_application_data_dir }}/db:/data/db
- {{ unifi_network_application_data_dir }}/init-mongo.sh:/docker-entrypoint-initdb.d/init-mongo.sh:ro
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=root
- MONGO_INITDB_DATABASE=unifi
- MONGO_USER=unifi
- MONGO_PASS=unifi
- MONGO_DBNAME=unifi
- MONGO_AUTHSOURCE=admin
networks:
- unifi-network
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
unifi-network:
driver: bridge
caddy_network:
external: true
name: caddy_default

View File

@@ -0,0 +1,78 @@
---
- name: Deploy Unifi Network App service
block:
- name: Set Unifi Network App directories
ansible.builtin.set_fact:
unifi_network_application_data_dir: "/mnt/object_storage/services/unifi_network_application"
unifi_network_application_service_dir: "{{ ansible_env.HOME }}/services/unifi_network_application"
- name: Create Unifi Network App directories
ansible.builtin.file:
path: "{{ unifi_network_application_dir }}"
state: directory
mode: "0755"
loop:
- "{{ unifi_network_application_data_dir }}"
- "{{ unifi_network_application_data_dir }}/data"
- "{{ unifi_network_application_data_dir }}/db"
- "{{ unifi_network_application_service_dir }}"
loop_control:
loop_var: unifi_network_application_dir
- name: Create MongoDB initialization script
ansible.builtin.copy:
content: |
#!/bin/bash
if which mongosh > /dev/null 2>&1; then
mongo_init_bin='mongosh'
else
mongo_init_bin='mongo'
fi
"${mongo_init_bin}" <<EOF
use ${MONGO_AUTHSOURCE}
db.auth("${MONGO_INITDB_ROOT_USERNAME}", "${MONGO_INITDB_ROOT_PASSWORD}")
db.createUser({
user: "${MONGO_USER}",
pwd: "${MONGO_PASS}",
roles: [
{ db: "${MONGO_DBNAME}", role: "dbOwner" },
{ db: "${MONGO_DBNAME}_stat", role: "dbOwner" },
{ db: "${MONGO_DBNAME}_audit", role: "dbOwner" }
]
})
EOF
dest: "{{ unifi_network_application_data_dir }}/init-mongo.sh"
mode: "0755"
register: unifi_mongo_init_script
- name: Deploy Unifi Network App docker-compose.yml
ansible.builtin.template:
src: docker-compose.yml.j2
dest: "{{ unifi_network_application_service_dir }}/docker-compose.yml"
mode: "0644"
register: unifi_network_application_compose
- name: Clean MongoDB database for fresh initialization
ansible.builtin.file:
path: "{{ unifi_network_application_data_dir }}/db"
state: absent
when: unifi_mongo_init_script.changed
- name: Recreate MongoDB database directory
ansible.builtin.file:
path: "{{ unifi_network_application_data_dir }}/db"
state: directory
mode: "0755"
when: unifi_mongo_init_script.changed
- name: Stop Unifi Network App service
ansible.builtin.command: docker compose -f "{{ unifi_network_application_service_dir }}/docker-compose.yml" down --remove-orphans
when: unifi_network_application_compose.changed or unifi_mongo_init_script.changed
- name: Start Unifi Network App service
ansible.builtin.command: docker compose -f "{{ unifi_network_application_service_dir }}/docker-compose.yml" up -d
when: unifi_network_application_compose.changed or unifi_mongo_init_script.changed
tags:
- services
- unifi