├── .gitignore ├── Makefile ├── README.md ├── ansible.cfg ├── cloudflare_tunnel.yml ├── inventory.txt.example ├── playbooks ├── actual │ └── docker-compose.yml ├── add_dokku_domain.yml ├── adguard │ └── docker-compose.yml ├── apt-upgrade.yml ├── bind9 │ ├── chibi.rodeo.zone │ ├── docker-compose.yml │ └── named.conf ├── caddy │ ├── Caddyfile │ ├── Dockerfile │ ├── container-vars.env │ └── docker-compose.yml ├── cloudflare-tunnel │ └── docker-compose.yml ├── create_dokku_app.yml ├── dawarich │ └── backup.sh ├── dokku_setup_certificates.yml ├── flibusta │ └── compose.yml ├── gitea │ └── docker-compose.yml ├── glances │ └── docker-compose.yml ├── healthchecks │ └── docker-compose.yml ├── hoarder │ ├── .env │ └── compose.yml ├── home_assistant │ └── docker-compose.yml ├── homelab_production.yml ├── homepage │ ├── config │ │ ├── docker.yaml │ │ ├── services.yaml │ │ ├── settings.yaml │ │ └── widgets.yaml │ └── docker-compose.yml ├── immich │ ├── backup.sh │ ├── docker-compose.yml │ ├── example.env │ └── rclone.conf ├── install_actual.yml ├── install_adguard.yml ├── install_bind9.yml ├── install_caddy.yml ├── install_dawarich.yml ├── install_docker.yml ├── install_dokku.yml ├── install_gitea.yml ├── install_glances.yml ├── install_go.yml ├── install_healthchecks.yml ├── install_home_assistant.yml ├── install_homepage.yml ├── install_immich.yml ├── install_jellyfin.yml ├── install_lubelogger.yml ├── install_mailrise.yml ├── install_monitoring.yml ├── install_n8n.yml ├── install_nextcloud.yml ├── install_nginx.yml ├── install_ntfy.yml ├── install_owncloud.yml ├── install_owntracks.yml ├── install_photon.yml ├── install_pihole.yml ├── install_portainer.yml ├── install_registry.yml ├── install_runitor.yml ├── install_traefik.yml ├── install_uptimekuma.yml ├── install_vaultwarden.yml ├── install_zfs.yml ├── jellyfin │ └── docker-compose.yml ├── lubelogger │ ├── .env │ └── docker-compose.yml ├── mailrise │ └── docker-compose.yml ├── monitoring │ ├── docker-compose.yml │ └── prometheus.yml ├── n8n │ ├── .env │ └── docker-compose.yml ├── nextcloud │ └── docker-compose.yml ├── nginx │ └── docker-compose.yml ├── ntfy │ └── docker-compose.yml ├── owncloud │ └── compose.yml ├── owntracks │ └── docker-compose.yml ├── paperlessngx.yml ├── paperlessngx │ ├── backup.sh │ └── docker-compose.yml ├── photon │ ├── Dockerfile │ ├── docker-compose.yml │ └── entrypoint.sh ├── pihole │ └── docker-compose.yml ├── registry │ └── docker-compose.yml ├── rename_host.yml ├── sampler │ └── sampler.yml ├── setup_dokku_backups.yml ├── traefik │ ├── docker-compose.yml │ └── traefik.yaml ├── update_caddyfile.yml ├── update_immich.yml ├── uptime-kuma │ └── docker-compose.yml ├── vaultwarden │ └── docker-compose.yml └── whoami │ └── docker-compose.yml ├── rename.yml ├── samba.yml └── tasks ├── apt-upgrade.yml ├── install_rclone.yml └── rename_host.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | inventory.txt 3 | /tmp/**/* 4 | 5 | /playbooks/homepage/app/config/ 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ### 2 | 3 | setup_homelab_production: 4 | ansible-playbook -Kk -i inventory.txt playbooks/homelab_production.yml 5 | 6 | ### 7 | 8 | install_portainer: 9 | ansible-playbook -k -K playbooks/install_portainer.yml 10 | 11 | install_docker: 12 | ansible-playbook -k -K playbooks/install_docker.yml 13 | 14 | install_dokku: 15 | ansible-playbook -k -K playbooks/install_dokku.yml 16 | 17 | create_dokku_app: 18 | ansible-playbook -k -K playbooks/create_dokku_app.yml 19 | 20 | setup_dokku_backups: 21 | ansible-playbook -k -K playbooks/setup_dokku_backups.yml 22 | 23 | add_dokku_domain: 24 | ansible-playbook -k -K playbooks/add_dokku_domain.yml 25 | 26 | add_dokku_ssl: 27 | ansible-playbook -k -K playbooks/dokku_setup_certificates.yml 28 | 29 | octoprint: 30 | ansible-playbook -k -K octoprint.yml 31 | 32 | samba: 33 | ansible-playbook -k -K samba.yml 34 | 35 | backup: 36 | ansible-playbook -k -K backup.yml 37 | 38 | install_immich: 39 | ansible-playbook -k -K playbooks/install_immich.yml -i inventory.txt 40 | 41 | update_immich: 42 | ansible-playbook -k -K playbooks/update_immich.yml -i inventory.txt 43 | 44 | install_paperless: 45 | ansible-playbook -k -K playbooks/paperlessngx.yml -i inventory.txt 46 | 47 | install_go: 48 | ansible-playbook -k -K playbooks/install_go.yml 49 | 50 | install_runitor: 51 | ansible-playbook -k -K playbooks/install_runitor.yml 52 | 53 | install_actual: 54 | ansible-playbook -k -K playbooks/install_actual.yml -i inventory.txt 55 | 56 | install_traefik: 57 | ansible-playbook -k -K playbooks/install_traefik.yml -i inventory.txt 58 | 59 | install_jellyfin: 60 | ansible-playbook -k -K playbooks/install_jellyfin.yml -i inventory.txt 61 | 62 | install_bind9: 63 | ansible-playbook -k -K playbooks/install_bind9.yml -i inventory.txt 64 | 65 | install_home_assistant: 66 | ansible-playbook -k -K playbooks/install_home_assistant.yml -i inventory.txt 67 | 68 | install_nginx: 69 | ansible-playbook -k -K playbooks/install_nginx.yml -i inventory.txt 70 | 71 | install_nextcloud: 72 | ansible-playbook -k -K playbooks/install_nextcloud.yml -i inventory.txt 73 | 74 | install_monitoring: 75 | ansible-playbook -k -K playbooks/install_monitoring.yml -i inventory.txt 76 | 77 | install_glances: 78 | ansible-playbook -k -K playbooks/install_glances.yml -i inventory.txt 79 | 80 | install_owntracks: 81 | ansible-playbook -k -K playbooks/install_owntracks.yml -i inventory.txt 82 | 83 | install_homepage: 84 | ansible-playbook -k -K playbooks/install_homepage.yml -i inventory.txt 85 | 86 | install_gitea: 87 | ansible-playbook -k -K playbooks/install_gitea.yml -i inventory.txt 88 | 89 | install_caddy: 90 | ansible-playbook -k -K playbooks/install_caddy.yml -i inventory.txt 91 | 92 | update_caddyfile: 93 | ansible-playbook -k -K playbooks/update_caddyfile.yml -i inventory.txt 94 | 95 | install_uptimekuma: 96 | ansible-playbook -k -K playbooks/install_uptimekuma.yml -i inventory.txt 97 | 98 | install_healthchecks: 99 | ansible-playbook -k -K playbooks/install_healthchecks.yml -i inventory.txt 100 | 101 | install_pihole: 102 | ansible-playbook -k -K playbooks/install_pihole.yml -i inventory.txt 103 | 104 | install_mailrise: 105 | ansible-playbook -k -K playbooks/install_mailrise.yml -i inventory.txt 106 | 107 | install_ackee: 108 | ansible-playbook -k -K playbooks/install_ackee.yml -i inventory.txt 109 | 110 | install_adguard: 111 | ansible-playbook -k -K playbooks/install_adguard.yml -i inventory.txt 112 | 113 | install_registry: 114 | ansible-playbook -k -K playbooks/install_registry.yml -i inventory.txt 115 | 116 | install_lubelogger: 117 | ansible-playbook -k -K playbooks/install_lubelogger.yml -i inventory.txt 118 | 119 | install_n8n: 120 | ansible-playbook -k -K playbooks/install_n8n.yml -i inventory.txt 121 | 122 | install_vaultwarden: 123 | ansible-playbook -k -K playbooks/install_vaultwarden.yml -i inventory.txt 124 | 125 | install_photon: 126 | ansible-playbook -k -K playbooks/install_photon.yml -i inventory.txt 127 | 128 | install_ntfy: 129 | ansible-playbook -k -K playbooks/install_ntfy.yml -i inventory.txt 130 | 131 | install_owncloud: 132 | ansible-playbook -k -K playbooks/install_owncloud.yml -i inventory.txt 133 | 134 | install_dawarich: 135 | ansible-playbook -k -K playbooks/install_dawarich.yml -i inventory.txt 136 | 137 | install_zfs: 138 | ansible-playbook -k -K playbooks/install_zfs.yml -i inventory.txt 139 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Homelab 2 | 3 | This is a collection of scripts and configuration files that I use to manage my homelab. Some of them might also be used for my personal projects to setup staging and production servers. All variables should be placed in `inventory.txt` file. 4 | 5 | # Disclaimer 6 | 7 | Some of the scripts might be unsafe. I'm aware one is not supposed to operate as `root` user under no circumstances. Use these at your own risk. 8 | 9 | ## Playbooks 10 | 11 | 12 | ### Homelab 13 | 14 | To setup homelab production, run `make setup_homelab_production` 15 | 16 | - `make install_docker` will install Docker on the server. 17 | - `make portainer` will install Portainer on the server. 18 | - `make immich` will install Immich on the server. It will also create an automated config for backups: a cron job that will run once a month. Cron job will create a backup of the immich db and uploaded photos and _sync_ them with Backblaze B2 bucket. 19 | 20 | ### Dokku 21 | 22 | - `make dokku` will install Dokku on the server. It will also add 1GB swap file. 23 | - `make create_dokku_app` will create a new Dokku app on the server. It will also create a postgres database for the app, redis and link them to the app. 24 | - `make setup_dokku_backups` will set up backups for the app. It will create a cron job that will run every day at 3am and will create a backup of the database. The backups will be uploaded to AWS S3. 25 | - `make add_dokku_domain` will add a domain to the app. 26 | - `make add_dokku_ssl` will add SSL to the app. 27 | 28 | ### Production Dokku from strach 29 | 30 | ``` 31 | ansible-galaxy install -p ./roles geerlingguy.pip geerlingguy.docker_arm 32 | ansible-playbook -k -K -v docker-arm.yml 33 | ``` 34 | 35 | #### Adding certificates for dokku deployed apps 36 | 37 | To add certificates to the app, you need to follow some steps before running the `make dokku_add_ssl` command. 38 | 39 | 1. Add your domain to Cloudflare. You need to change the nameservers on your DNS provider (probably just where you have bought your domain). Create an account on Cloudflare and it will show you a step-by-step guide on how to do that (great onboarding by the way). 40 | 2. Create certificates for your domain. On Cloudflare, open SSL/TLS -> Origin Server menu and press Create Certificate. 41 | 3. Create two files in tmp folder: {{domain_name}}.crt and {{domain_name}}.key. Copy the content of the certificate and the private key in the files. 42 | 4. Run `make add_dokku_ssl` command. 43 | 5. Now set your domain SSL/TLS to Full on Cloudflare. 44 | 6. You're beautiful! 45 | 46 | ### Todo: 47 | 48 | - https://ubuntu.com/tutorials/install-and-configure-samba#2-installing-samba 49 | - io.portainer.accesscontrol.public for Immich so we could manage it using Portainer 50 | -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = inventory.txt 3 | host_key_checking = false 4 | -------------------------------------------------------------------------------- /cloudflare_tunnel.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for Cloudflare tunnel installation 2 | 3 | --- 4 | - hosts: thinky01 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for Cloudflare Tunnel 9 | file: 10 | path: "{{ local_cloudflare_tunnel_path }}" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Upload cloudflare tunnel docker-compose.yml 17 | template: 18 | src: "playbooks/cloudflare-tunnel/docker-compose.yml" 19 | dest: "cloudflare-tunnel/docker-compose.yml" 20 | owner: "{{ ansible_user }}" 21 | group: "{{ ansible_user }}" 22 | mode: 0600 23 | 24 | - name: Create and start services 25 | community.docker.docker_compose: 26 | project_src: "{{ local_cloudflare_tunnel_path }}" 27 | register: output 28 | 29 | - name: Install rclone 30 | apt: 31 | name: "{{ packages }}" 32 | state: present 33 | update_cache: yes 34 | vars: 35 | packages: 36 | - rclone 37 | 38 | - name: Upload rclone B2 config 39 | template: 40 | src: "tmp/rclone.conf" 41 | dest: ".config/rclone/rclone.conf" 42 | owner: "{{ ansible_user }}" 43 | group: "{{ ansible_user }}" 44 | mode: 0600 45 | 46 | - name: Schedule Immich DB backup to be done daily 47 | cron: 48 | name: "Dump Immich DB to a local file" 49 | minute: "45" 50 | hour: "5" 51 | job: docker exec -t immich_postgres pg_dumpall -c -U postgres | gzip > "{{ local_backup_path }}/db_dump.sql.gz" 52 | state: present 53 | 54 | - name: Schedule photos backup to be done once a month 55 | cron: 56 | name: "Backup immich files to B2" 57 | minute: "55" 58 | hour: "17" 59 | day: "15" 60 | job: /usr/bin/rclone sync {{ local_backup_path }} {{ backblaze_remote_name }}:{{ backblaze_bucket_name }} --config /home/{{ ansible_user }}/.config/rclone/rclone.conf 61 | state: present 62 | -------------------------------------------------------------------------------- /inventory.txt.example: -------------------------------------------------------------------------------- 1 | [nas] 2 | 127.0.0.1 3 | 4 | [nas:vars] 5 | ansible_user=root 6 | ansible_become=yes 7 | ansible_become_method=sudo 8 | ansible_become_pass='' 9 | 10 | [dokku:vars] 11 | ansible_user=root 12 | ansible_become=yes 13 | ansible_become_method=sudo 14 | ansible_become_pass='' 15 | app_name='appname' 16 | app_domain='example.com' 17 | aws_access_key_id='aws_secret_access_key' 18 | aws_secret_access_key='aws_secret_access_key' 19 | bucket_name='bucket_name' 20 | 21 | [dokku] 22 | 192/168.0.1 23 | 24 | [immich] 25 | 127.0.0.1 26 | 27 | [immich:vars] 28 | ansible_user=root 29 | ansible_become=yes 30 | ansible_become_method=sudo 31 | ansible_become_pass='' 32 | backblaze_app_key_id=123 33 | backblaze_app_key=123 34 | backblaze_hard_delete=true 35 | backblaze_bucket_name=backblaze-bucket-name 36 | backblaze_remote_name=backblaze-remote-name 37 | local_backup_path=/media/hdd/immich 38 | healthchecks_ping_url='http://192/168.0.1:8020/ping/' 39 | hc_paperless_backup_uuid='' 40 | hc_paperless_backup_uploaded_uuid='' 41 | hc_immich_backup_uuid='' 42 | hc_immich_backup_uploaded_uuid='' 43 | 44 | [thinky01] 45 | 192/168.0.1 46 | 47 | [thinky01:vars] 48 | ansible_user=root 49 | ansible_become=yes 50 | ansible_become_method=sudo 51 | ansible_become_pass='' 52 | backblaze_bucket_name: backblaze_bucket_name 53 | backblaze_remote_name: backblaze_bucket_name 54 | -------------------------------------------------------------------------------- /playbooks/actual/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | actual_server: 3 | image: docker.io/actualbudget/actual-server:latest 4 | ports: 5 | # This line makes Actual available at port 5006 of the device you run the server on, 6 | # i.e. http://localhost:5006. You can change the first number to change the port, if you want. 7 | - '5006:5006' 8 | volumes: 9 | # Change './actual-data' below to the path to the folder you want Actual to store its data in on your server. 10 | # '/data' is the path Actual will look for its files in by default, so leave that as-is. 11 | - ./actual-data:/data 12 | restart: unless-stopped 13 | -------------------------------------------------------------------------------- /playbooks/add_dokku_domain.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: dokku 3 | tasks: 4 | - name: add domain app to {{app_name}} 5 | shell: dokku domains:add {{app_name}} {{app_domain}} 6 | -------------------------------------------------------------------------------- /playbooks/adguard/docker-compose.yml: -------------------------------------------------------------------------------- 1 | networks: 2 | caddy_caddynet: 3 | external: true 4 | 5 | services: 6 | adguardhome: 7 | image: adguard/adguardhome 8 | container_name: adguardhome 9 | volumes: 10 | - ./conf:/opt/adguardhome/conf 11 | - ./work:/opt/adguardhome/work 12 | ports: 13 | # DNS 14 | - 53:53 15 | # WebUI 16 | - 3222:3000/tcp 17 | - 848:80/tcp 18 | # # DHCP server 19 | - 67:67/udp 20 | # - 68:68/tcp 21 | # - 68:68/udp 22 | # # HTTPS/DNS-over-HTTPS 23 | # - 443:443/tcp 24 | # # DNS-over-TLS 25 | # - 853:853/tcp 26 | # # DNS-over-QUIC 27 | # - 784:784/udp 28 | # # DNSCrypt 29 | # - 5443:5443/tcp 30 | # - 5443:5443/udp 31 | restart: unless-stopped 32 | networks: 33 | - caddy_caddynet 34 | -------------------------------------------------------------------------------- /playbooks/apt-upgrade.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-prod 3 | tasks: 4 | - import_tasks: ../tasks/apt-upgrade.yml 5 | -------------------------------------------------------------------------------- /playbooks/bind9/chibi.rodeo.zone: -------------------------------------------------------------------------------- 1 | $TTL 2d 2 | 3 | $ORIGIN chibi.rodeo. 4 | 5 | @ IN SOA ns.chibi.rodeo. hey.frey.today. ( 6 | 20231030 ; serial 7 | 12h ; refresh 8 | 15m ; retry 9 | 3w ; expiry 10 | 2h ; minimum TTL 11 | ) 12 | IN NS ns.chibi.rodeo. 13 | 14 | ns IN A 192.168.0.227 15 | 16 | ; Add your own records below this line 17 | 18 | thinky01 IN A 192.168.0.227 19 | nas IN A 192.168.0.20 20 | -------------------------------------------------------------------------------- /playbooks/bind9/docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | bind9: 4 | image: ubuntu/bind9:latest 5 | container_name: bind9 6 | ports: 7 | - "53:53/udp" 8 | - "53:53/tcp" 9 | volumes: 10 | - /home/frey/apps/bind9/bind:/etc/bind/ 11 | - /home/frey/apps/bind9/cache/bind:/var/cache/bind 12 | - /home/frey/apps/bind9/lib/bind:/var/lib/bind 13 | restart: unless-stopped 14 | -------------------------------------------------------------------------------- /playbooks/bind9/named.conf: -------------------------------------------------------------------------------- 1 | acl internal { 2 | 192.168.0.0/16; 3 | }; 4 | 5 | options { 6 | forwarders { 7 | 1.1.1.1; 8 | 1.0.0.1; 9 | 8.8.8.8; 10 | }; 11 | allow-query { 12 | internal; 13 | }; 14 | directory "/var/cache/bind"; 15 | }; 16 | 17 | zone "chibi.rodeo" { 18 | type master; 19 | file "/etc/bind/chibi.rodeo.zone"; 20 | }; 21 | -------------------------------------------------------------------------------- /playbooks/caddy/Caddyfile: -------------------------------------------------------------------------------- 1 | gitea.chibi.rodeo { 2 | reverse_proxy gitea:3000 3 | tls { 4 | dns cloudflare 123 5 | } 6 | } 7 | 8 | immich.chibi.rodeo { 9 | reverse_proxy 10.0.0.227:2284 10 | tls { 11 | dns cloudflare 123 12 | } 13 | } 14 | 15 | chibi.rodeo { 16 | reverse_proxy homepage:3000 17 | tls { 18 | dns cloudflare 123 19 | } 20 | } 21 | 22 | jellyfin.chibi.rodeo { 23 | reverse_proxy localhost:8096 24 | tls { 25 | dns cloudflare 123 26 | } 27 | } 28 | 29 | uptime.chibi.rodeo { 30 | reverse_proxy uptime-kuma:3001 31 | tls { 32 | dns cloudflare 123 33 | } 34 | } 35 | 36 | healthchecks.chibi.rodeo { 37 | reverse_proxy healthchecks:8000 38 | tls { 39 | dns cloudflare 123 40 | } 41 | } 42 | 43 | pihole.chibi.rodeo { 44 | reverse_proxy pihole:80 45 | tls { 46 | dns cloudflare 123 47 | } 48 | } 49 | 50 | pve.chibi.rodeo { 51 | reverse_proxy 10.0.0.201:8006 52 | tls { 53 | dns cloudflare 123 54 | } 55 | } 56 | 57 | docs.chibi.rodeo { 58 | reverse_proxy 10.0.0.200:8010 59 | tls { 60 | dns cloudflare 123 61 | } 62 | } 63 | 64 | registry.chibi.rodeo { 65 | reverse_proxy registry:5000 66 | tls { 67 | dns cloudflare 123 68 | } 69 | } 70 | 71 | dawarich.chibi.rodeo { 72 | reverse_proxy 10.0.0.200:3000 73 | tls { 74 | dns cloudflare 123 75 | } 76 | } 77 | 78 | n8n.chibi.rodeo { 79 | reverse_proxy 10.0.0.200:5678 80 | tls { 81 | dns cloudflare 123 82 | } 83 | } 84 | 85 | actual.chibi.rodeo { 86 | reverse_proxy 10.0.0.200:5006 87 | tls { 88 | dns cloudflare 123 89 | } 90 | } 91 | 92 | vaultwarden.chibi.rodeo { 93 | reverse_proxy 10.0.0.200:8088 94 | tls { 95 | dns cloudflare 123 96 | } 97 | } 98 | 99 | photon.chibi.rodeo { 100 | reverse_proxy 10.0.0.227:2322 101 | tls { 102 | dns cloudflare 123 103 | } 104 | } 105 | 106 | authentik.chibi.rodeo { 107 | reverse_proxy 10.0.0.200:9090 108 | tls { 109 | dns cloudflare 123 110 | } 111 | 112 | } 113 | 114 | ntfy.chibi.rodeo { 115 | reverse_proxy 10.0.0.200:65080 116 | tls { 117 | dns cloudflare 123 118 | } 119 | } 120 | 121 | flibusta.chibi.rodeo { 122 | reverse_proxy 10.0.0.227:12380 123 | tls { 124 | dns cloudflare 123 125 | } 126 | } 127 | 128 | home.chibi.rodeo { 129 | reverse_proxy 10.0.0.200:3015 130 | tls { 131 | dns cloudflare 123 132 | } 133 | } 134 | 135 | owncloud.chibi.rodeo { 136 | reverse_proxy 10.0.0.227:65508 137 | tls { 138 | dns cloudflare 123 139 | } 140 | } 141 | 142 | photon.dawarich.app { 143 | @validHeader { 144 | header X-Api-Key 100500 145 | } 146 | 147 | handle @validHeader { 148 | reverse_proxy photon:2322 149 | } 150 | 151 | handle { 152 | respond "Unauthorized" 401 153 | } 154 | 155 | tls { 156 | dns cloudflare 111 157 | } 158 | } 159 | 160 | monitoring.chibi.rodeo { 161 | reverse_proxy 10.0.0.227:3333 162 | tls { 163 | dns cloudflare 123 164 | } 165 | } 166 | 167 | -------------------------------------------------------------------------------- /playbooks/caddy/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG VERSION=2 2 | 3 | FROM caddy:${VERSION}-builder AS builder 4 | 5 | # caddy-docker-proxy can't get ssl certificate from cloudflare, so we don't use it 6 | # (yet) 7 | 8 | RUN xcaddy build \ 9 | # --with github.com/lucaslorentz/caddy-docker-proxy/v2 \ 10 | --with github.com/caddy-dns/cloudflare 11 | 12 | FROM caddy:${VERSION} 13 | 14 | COPY --from=builder /usr/bin/caddy /usr/bin/caddy 15 | 16 | # CMD ["caddy", "docker-proxy"] 17 | -------------------------------------------------------------------------------- /playbooks/caddy/container-vars.env: -------------------------------------------------------------------------------- 1 | MY_DOMAIN=123 2 | MY_HOST_IP=123 3 | CLOUDFLARE_API_TOKEN=123 4 | -------------------------------------------------------------------------------- /playbooks/caddy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | caddy: 5 | build: . 6 | container_name: caddy 7 | hostname: caddy 8 | restart: unless-stopped 9 | ports: 10 | - "80:80" 11 | - "443:443" 12 | - "443:443/udp" 13 | networks: 14 | - caddynet 15 | - default 16 | env_file: 17 | - container-vars.env 18 | volumes: 19 | - ./Caddyfile:/etc/caddy/Caddyfile:ro 20 | - ./data:/data 21 | - ./config:/config 22 | - /var/run/docker.sock:/var/run/docker.sock 23 | # labels: 24 | # caddy.email: mail@example.com 25 | 26 | networks: 27 | caddynet: 28 | attachable: true 29 | driver: bridge 30 | -------------------------------------------------------------------------------- /playbooks/cloudflare-tunnel/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | 3 | networks: 4 | frontend: 5 | external: true 6 | backend: 7 | external: true 8 | 9 | services: 10 | cloudflaretunnel: 11 | container_name: cloudflaretunnel-home 12 | image: cloudflare/cloudflared:2023.2.1 13 | restart: unless-stopped 14 | environment: 15 | - TUNNEL_TOKEN=$TUNNEL_TOKEN 16 | command: tunnel --no-autoupdate run --token $TUNNEL_TOKEN 17 | -------------------------------------------------------------------------------- /playbooks/create_dokku_app.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: dokku 3 | tasks: 4 | - name: create a new app 5 | shell: dokku apps:exists {{app_name}} || dokku apps:create {{app_name}} 6 | register: app_exists 7 | 8 | - name: create a db 9 | shell: dokku postgres:exists {{app_name}}_db || dokku postgres:create {{app_name}}_db 10 | 11 | - name: link the db to the app 12 | shell: dokku postgres:link {{app_name}}_db {{app_name}} 13 | ignore_errors: true 14 | 15 | - name: add redis 16 | shell: dokku redis:exists {{app_name}}_redis || dokku redis:create {{app_name}}_redis 17 | 18 | - name: link redis to the app 19 | shell: dokku redis:link {{app_name}}_redis {{app_name}} 20 | ignore_errors: true 21 | -------------------------------------------------------------------------------- /playbooks/dawarich/backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Dump the database 4 | docker exec -t dawarich_db pg_dumpall --clean --if-exists --username=postgres | gzip > "{{ local_backups_path }}/dawarich/dawarich_db_dump.sql.gz" 5 | 6 | # Upload the database dump to Backblaze 7 | /usr/bin/rclone copy "{{ local_backups_path }}/dawarich/dawarich_db_dump.sql.gz" {{ backblaze_remote_name }}:{{ backblaze_bucket_name }} --config /home/{{ ansible_user }}/.config/rclone/rclone.conf -P 8 | 9 | curl -X GET {{ hc_ping_url }}/{{ hc_dawarich_backup_uuid }} 10 | -------------------------------------------------------------------------------- /playbooks/dokku_setup_certificates.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: dokku 3 | tasks: 4 | - name: create certs directory 5 | file: 6 | path: /root/certs 7 | state: directory 8 | owner: root 9 | group: root 10 | mode: 0755 11 | 12 | - name: upload certificate files to server 13 | copy: 14 | src: "{{item}}" 15 | dest: "/root/certs" 16 | owner: root 17 | group: root 18 | mode: 0644 19 | with_items: 20 | - "../tmp/{{app_domain}}.crt" 21 | - "../tmp/{{app_domain}}.key" 22 | 23 | - name: tar certificate file 24 | command: tar -cvf /root/certs/{{app_domain}}.tar /root/certs/{{app_domain}}.crt /root/certs/{{app_domain}}.key 25 | 26 | - name: copy certificate file to dokku 27 | shell: 28 | cmd: dokku certs:add {{app_name}} < {{app_domain}}.tar 29 | chdir: /root/certs 30 | 31 | - name: rebuild proxy config 32 | command: dokku proxy:build-config {{app_name}} 33 | -------------------------------------------------------------------------------- /playbooks/flibusta/compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | server: 3 | container_name: inpx-web 4 | network_mode: bridge 5 | ports: 6 | - 12380:12380 7 | volumes: 8 | # путь к папке с рабочими файлами и базой 9 | - /storage-pool/apps/flibusta/data:/data 10 | # путь к библиотеке с zip архивами и inpx файлом 11 | - /storage-pool/backups/fb2.Flibusta.Net:/library:ro 12 | restart: unless-stopped 13 | image: rshmyrev/inpx-web 14 | -------------------------------------------------------------------------------- /playbooks/gitea/docker-compose.yml: -------------------------------------------------------------------------------- 1 | networks: 2 | gitea: 3 | external: false 4 | caddy_caddynet: 5 | external: true 6 | 7 | services: 8 | server: 9 | image: gitea/gitea:1.21.4 10 | container_name: gitea 11 | environment: 12 | - USER_UID=1000 13 | - USER_GID=999 14 | - GITEA__database__DB_TYPE=mysql 15 | - GITEA__database__HOST=db:3306 16 | - GITEA__database__NAME=gitea 17 | - GITEA__database__USER=gitea 18 | - GITEA__database__PASSWD=gitea 19 | - I_AM_BEING_UNSAFE_RUNNING_AS_ROOT=true 20 | - ROOT_URL=https://gitea.chibi.rodeo 21 | restart: always 22 | networks: 23 | - gitea 24 | - caddy_caddynet 25 | volumes: 26 | - /storage-pool/apps/gitea/data:/data 27 | - /etc/timezone:/etc/timezone:ro 28 | - /etc/localtime:/etc/localtime:ro 29 | ports: 30 | - "3040:3000" 31 | - "2234:22" 32 | depends_on: 33 | - db 34 | 35 | db: 36 | image: mysql:8 37 | restart: always 38 | environment: 39 | - MYSQL_ROOT_PASSWORD=gitea 40 | - MYSQL_USER=gitea 41 | - MYSQL_PASSWORD=gitea 42 | - MYSQL_DATABASE=gitea 43 | networks: 44 | - gitea 45 | volumes: 46 | - /storage-pool/apps/gitea/mysql:/var/lib/mysql 47 | -------------------------------------------------------------------------------- /playbooks/glances/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | monitoring: 5 | image: nicolargo/glances:latest-alpine 6 | restart: always 7 | pid: host 8 | volumes: 9 | - /var/run/docker.sock:/var/run/docker.sock 10 | environment: 11 | - "GLANCES_OPT=-w" 12 | ports: 13 | - "61208:61208" 14 | -------------------------------------------------------------------------------- /playbooks/healthchecks/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | healthchecks: 3 | image: healthchecks/healthchecks:latest 4 | container_name: healthchecks 5 | environment: 6 | - ALLOWED_HOSTS=healthchecks.chibi.rodeo,192.168.178.200 7 | - DB=sqlite 8 | - DB_NAME=/data/hc.sqlite 9 | - DEBUG=False 10 | - DEFAULT_FROM_EMAIL=fixme-email-address-here 11 | - EMAIL_HOST=fixme-smtp-host-here 12 | - EMAIL_HOST_PASSWORD=fixme-smtp-password-here 13 | - EMAIL_HOST_USER=fixme-smtp-username-here 14 | - EMAIL_PORT=587 15 | - EMAIL_USE_TLS=True 16 | - SECRET_KEY=--- 17 | - TELEGRAM_BOT_NAME={TELEGRAM_BOT_NAME} 18 | - TELEGRAM_TOKEN={TELEGRAM_BOT_TOKEN} 19 | - SITE_ROOT=https://healthchecks.chibi.rodeo 20 | ports: 21 | - 8020:8000 22 | volumes: 23 | - healthchecks-data:/data 24 | restart: unless-stopped 25 | networks: 26 | - caddy_caddynet 27 | volumes: 28 | healthchecks-data: 29 | 30 | networks: 31 | caddy_caddynet: 32 | external: true 33 | -------------------------------------------------------------------------------- /playbooks/hoarder/.env: -------------------------------------------------------------------------------- 1 | HOARDER_VERSION=release 2 | NEXTAUTH_SECRET=super_random_string 3 | MEILI_MASTER_KEY=another_random_string 4 | NEXTAUTH_URL=http://localhost:3000 5 | -------------------------------------------------------------------------------- /playbooks/hoarder/compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | web: 4 | image: ghcr.io/hoarder-app/hoarder:${HOARDER_VERSION:-release} 5 | restart: unless-stopped 6 | volumes: 7 | - data:/data 8 | ports: 9 | - 3000:3000 10 | env_file: 11 | - .env 12 | environment: 13 | MEILI_ADDR: http://meilisearch:7700 14 | BROWSER_WEB_URL: http://chrome:9222 15 | # OPENAI_API_KEY: ... 16 | DATA_DIR: /data 17 | chrome: 18 | image: gcr.io/zenika-hub/alpine-chrome:123 19 | restart: unless-stopped 20 | command: 21 | - --no-sandbox 22 | - --disable-gpu 23 | - --disable-dev-shm-usage 24 | - --remote-debugging-address=0.0.0.0 25 | - --remote-debugging-port=9222 26 | - --hide-scrollbars 27 | meilisearch: 28 | image: getmeili/meilisearch:v1.11.1 29 | restart: unless-stopped 30 | env_file: 31 | - .env 32 | environment: 33 | MEILI_NO_ANALYTICS: "true" 34 | volumes: 35 | - meilisearch:/meili_data 36 | 37 | volumes: 38 | meilisearch: 39 | data: 40 | -------------------------------------------------------------------------------- /playbooks/home_assistant/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | homeassistant: 4 | container_name: homeassistant 5 | image: "ghcr.io/home-assistant/home-assistant:stable" 6 | volumes: 7 | - /home/frey/apps/home_assistant/config:/config 8 | - /etc/localtime:/etc/localtime:ro 9 | restart: unless-stopped 10 | privileged: true 11 | network_mode: host 12 | -------------------------------------------------------------------------------- /playbooks/homelab_production.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # - name: Rename host 4 | # import_playbook: rename_host.yml 5 | 6 | # - name: Install ZFS 7 | # import_playbook: install_zfs.yml 8 | 9 | # - name: Install Docker 10 | # import_playbook: install_docker.yml 11 | 12 | # - name: Install Portainer 13 | # import_playbook: install_portainer.yml 14 | 15 | - name: Install Caddy 16 | import_playbook: install_caddy.yml 17 | 18 | - name: Install Glances 19 | import_playbook: install_glances.yml 20 | 21 | - name: Install Immich 22 | import_playbook: install_immich.yml 23 | 24 | # - name: Install Jellyfin 25 | # import_playbook: install_jellyfin.yml 26 | 27 | -------------------------------------------------------------------------------- /playbooks/homepage/config/docker.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # For configuration options and examples, please see: 3 | # https://gethomepage.dev/latest/configs/docker/ 4 | 5 | homelab-prod: 6 | socket: /var/run/docker.sock 7 | 8 | homelab-fuji: 9 | host: 10 | - 192.168.178.202 11 | 12 | # nas: 13 | # host: 192.168.178.200 14 | # port: 2375 15 | # my-docker: 16 | -------------------------------------------------------------------------------- /playbooks/homepage/config/services.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # For configuration options and examples, please see: 3 | # https://gethomepage.dev/latest/configs/services 4 | 5 | - Media: 6 | - Immich: 7 | href: https://immich.chibi.rodeo/ 8 | server: homelab-prod 9 | container: immich_server 10 | icon: immich 11 | siteMonitor: https://immich.chibi.rodeo/ 12 | widget: 13 | type: immich 14 | url: https://immich.chibi.rodeo 15 | key: tOScguzDW1MnJp6gvuYf1C9fyDnQCiVwOWKfIdQOZY 16 | - Jellyfin: 17 | href: http://192.168.178.200:8096 18 | server: homelab-prod 19 | icon: jellyfin 20 | container: jellyfin 21 | siteMonitor: http://192.168.178.200:8096 22 | 23 | - Applications: 24 | - Kling: 25 | href: https://kling.frey.today/api/v1/portfolios/9583bafb-28c4-411a-9567-1172a00f6944.json 26 | server: kling.frey.today 27 | siteMonitor: https://kling.frey.today 28 | widget: 29 | type: customapi 30 | url: https://kling.frey.today/api/v1/portfolios/9583bafb-28c4-411a-9567-1172a00f6944.json 31 | refreshInterval: 300000 32 | method: GET 33 | mappings: 34 | - field: total_worth 35 | label: Total Worth 36 | type: text 37 | suffix: "$" 38 | - field: profit_and_loss 39 | label: PNL 40 | type: number 41 | suffix: "$" 42 | - field: percent_change 43 | label: Percent Change 44 | type: text 45 | decimals: 2 46 | suffix: "%" 47 | - PiHole: 48 | href: https://pihole.chibi.rodeo/admin/index.php 49 | server: homelab-prod 50 | container: pihole 51 | siteMonitor: https://pihole.chibi.rodeo/admin/index.php 52 | widget: 53 | type: pihole 54 | url: https://pihole.chibi.rodeo 55 | key: ae88dd40a2413f6063c753382c26cb427f3a4d4d0cb082889d2ca28af70bfa88 56 | - UptimeKuma: 57 | href: https://uptime.chibi.rodeo 58 | widget: 59 | type: uptimekuma 60 | url: https://uptime.chibi.rodeo 61 | slug: everything 62 | siteMonitor: http://192.168.178.200:3000 63 | - Dawarich: 64 | href: http://192.168.178.200:3000 65 | server: homelab-prod 66 | container: dawarich_app 67 | - Gitea: 68 | href: https://gitea.chibi.rodeo 69 | server: homelab-prod 70 | container: gitea 71 | icon: gitea 72 | siteMonitor: https://gitea.chibi.rodeo 73 | - OwnTracks: 74 | href: http://192.168.178.200:8085 75 | server: homelab-prod 76 | container: owntracks-owntracks-frontend-1 77 | siteMonitor: http://192.168.178.200:8085 78 | 79 | - Statistics (Prod): 80 | - CPU Usage: 81 | widget: 82 | type: glances 83 | url: http://192.168.178.200:61208 84 | metric: cpu 85 | chart: false 86 | - Network Usage: 87 | widget: 88 | type: glances 89 | url: http://192.168.178.200:61208 90 | metric: network:eth0 91 | chart: false 92 | - Memory Usage: 93 | widget: 94 | type: glances 95 | url: http://192.168.178.200:61208 96 | metric: memory 97 | chart: false 98 | - Disk Usage: 99 | widget: 100 | type: glances 101 | url: http://192.168.178.200:61208 102 | metric: disk:sda 103 | chart: false 104 | 105 | - Todo: 106 | - Healthchecks: 107 | href: http://192.168.178.200:8020 108 | server: homelab-prod 109 | icon: healthchecks 110 | container: healthchecks 111 | siteMonitor: http://192.168.178.200:8020 112 | widget: 113 | type: healthchecks 114 | url: http://192.168.178.200:8020 115 | key: e50MntPtFuy__n0DvlL7UVsdaDfV4Woq 116 | uuid: e57e334c-fad8-42b2-a9f1-730a09d6d705 117 | - PaperlessNGX: 118 | href: http://192.168.178.200:8010 119 | server: homelab-prod 120 | container: paperlessngx-webserver-1 121 | siteMonitor: http://192.168.178.200:8010 122 | icon: paperless 123 | 124 | -------------------------------------------------------------------------------- /playbooks/homepage/config/settings.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # For configuration options and examples, please see: 3 | # https://gethomepage.dev/latest/configs/settings 4 | 5 | providers: 6 | openweathermap: openweathermapapikey 7 | weatherapi: weatherapiapikey 8 | 9 | layout: 10 | Media: 11 | style: row 12 | columns: 2 13 | Statistics (Prod): 14 | style: row 15 | columns: 4 16 | Applications: 17 | style: row 18 | columns: 4 19 | Todo: 20 | style: row 21 | columns: 4 22 | -------------------------------------------------------------------------------- /playbooks/homepage/config/widgets.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # For configuration options and examples, please see: 3 | # https://gethomepage.dev/latest/configs/service-widgets 4 | 5 | - resources: 6 | label: System 7 | cpu: true 8 | memory: true 9 | cputemp: true 10 | uptime: true 11 | 12 | - resources: 13 | label: Storage 14 | expanded: true 15 | disk: 16 | - /storage-pool 17 | -------------------------------------------------------------------------------- /playbooks/homepage/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | services: 3 | homepage: 4 | image: ghcr.io/gethomepage/homepage:latest 5 | container_name: homepage 6 | environment: 7 | PUID: 1000 8 | PGID: 999 9 | ports: 10 | - 3015:3000 11 | volumes: 12 | # - /storage-pool/apps/homepage/config:/app/config # Make sure your local config directory exists 13 | - ./app/config:/app/config # Make sure your local config directory exists 14 | - /var/run/docker.sock:/var/run/docker.sock:ro # optional, for docker integrations 15 | restart: unless-stopped 16 | -------------------------------------------------------------------------------- /playbooks/immich/backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Dump the database 4 | docker exec -t immich_postgres pg_dumpall -c -U postgres | gzip > "{{ local_backups_path }}/immich/db_dump.sql.gz" 5 | 6 | # Upload the database dump to Backblaze 7 | /usr/bin/rclone copy "{{ local_backups_path }}/immich/db_dump.sql.gz" {{ backblaze_remote_name }}:{{ backblaze_bucket_name }} --config /home/{{ ansible_user }}/.config/rclone/rclone.conf -P 8 | 9 | # Sync the backup to Backblaze 10 | /usr/bin/rclone sync {{ local_apps_path }}/immich {{ backblaze_remote_name }}:{{ backblaze_bucket_name }} --config /home/{{ ansible_user }}/.config/rclone/rclone.conf --include='/app/library/**' --include='/app/upload/**' --include='/app/profile/**' -P 11 | 12 | curl -X GET {{ hc_ping_url }}/{{ hc_immich_backup_uuid }} 13 | -------------------------------------------------------------------------------- /playbooks/immich/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # 2 | # WARNING: Make sure to use the docker-compose.yml of the current release: 3 | # 4 | # https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml 5 | # 6 | # The compose file on main may not be compatible with the latest release. 7 | # 8 | 9 | name: immich 10 | 11 | services: 12 | immich-server: 13 | container_name: immich_server 14 | image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release} 15 | volumes: 16 | - ${UPLOAD_LOCATION}:/usr/src/app/upload 17 | - /storage-pool/apps/immich/app/external-libraries/um_mka:/mnt/media/um_mka:ro 18 | - /etc/localtime:/etc/localtime:ro 19 | env_file: 20 | - .env 21 | ports: 22 | - 2284:2283 23 | depends_on: 24 | - redis 25 | - database 26 | restart: always 27 | networks: 28 | - caddy_caddynet 29 | - default 30 | 31 | immich-machine-learning: 32 | container_name: immich_machine_learning 33 | image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release} 34 | volumes: 35 | - model-cache:/cache 36 | env_file: 37 | - .env 38 | restart: always 39 | networks: 40 | - default 41 | 42 | redis: 43 | container_name: immich_redis 44 | image: redis:6.2-alpine@sha256:c5a607fb6e1bb15d32bbcf14db22787d19e428d59e31a5da67511b49bb0f1ccc 45 | restart: always 46 | networks: 47 | - default 48 | 49 | database: 50 | container_name: immich_postgres 51 | image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0 52 | env_file: 53 | - .env 54 | environment: 55 | POSTGRES_PASSWORD: ${DB_PASSWORD} 56 | POSTGRES_USER: ${DB_USERNAME} 57 | POSTGRES_DB: ${DB_DATABASE_NAME} 58 | volumes: 59 | - pgdata:/var/lib/postgresql/data 60 | restart: always 61 | networks: 62 | - default 63 | 64 | volumes: 65 | pgdata: 66 | model-cache: 67 | 68 | networks: 69 | caddy_caddynet: 70 | external: true 71 | -------------------------------------------------------------------------------- /playbooks/immich/example.env: -------------------------------------------------------------------------------- 1 | # You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables 2 | 3 | # The location where your uploaded files are stored 4 | UPLOAD_LOCATION={{ local_apps_path }}/immich/app 5 | 6 | # The Immich version to use. You can pin this to a specific version like "v1.71.0" 7 | IMMICH_VERSION=release 8 | 9 | # Connection secret for postgres. You should change it to a random password 10 | DB_PASSWORD=postgres 11 | 12 | # The values below this line do not need to be changed 13 | ################################################################################### 14 | DB_HOSTNAME=immich_postgres 15 | DB_USERNAME=postgres 16 | DB_DATABASE_NAME=immich 17 | 18 | REDIS_HOSTNAME=immich_redis 19 | -------------------------------------------------------------------------------- /playbooks/immich/rclone.conf: -------------------------------------------------------------------------------- 1 | [immich-backup] 2 | type = b2 3 | account = {{ backblaze_app_key_id }} 4 | key = {{ backblaze_app_key }} 5 | hard_delete = true 6 | 7 | [homelab-backup] 8 | type = b2 9 | account = {{ homelab_backup_backblaze_app_key_id }} 10 | key = {{ homelab_backup_backblaze_app_key }} 11 | hard_delete = true 12 | -------------------------------------------------------------------------------- /playbooks/install_actual.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for Immich installation 2 | 3 | --- 4 | - hosts: homelab-prod 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for Actual 9 | file: 10 | path: "{{ local_apps_path }}/actual_budget" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Upload Actual docker-compose.yml 17 | template: 18 | src: "actual/docker-compose.yml" 19 | dest: "{{ local_apps_path }}/actual_budget/docker-compose.yml" 20 | owner: "{{ ansible_user }}" 21 | group: "{{ ansible_user }}" 22 | mode: 0600 23 | 24 | - name: Stop existing services 25 | command: docker compose -f {{ local_apps_path }}/actual_budget/docker-compose.yml stop 26 | 27 | - name: Create and start services 28 | command: docker compose -f {{ local_apps_path }}/actual_budget/docker-compose.yml up -d 29 | -------------------------------------------------------------------------------- /playbooks/install_adguard.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for adguard installation 2 | 3 | --- 4 | - hosts: homelab-prod 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for adguard 9 | file: 10 | path: "{{ local_apps_path }}/adguard" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Upload adguard docker-compose.yml 17 | copy: 18 | src: ./adguard/docker-compose.yml 19 | dest: "{{ local_apps_path }}/adguard/docker-compose.yml" 20 | mode: 0644 21 | 22 | - name: Stop systemd-resolved 23 | systemd: 24 | name: systemd-resolved 25 | state: stopped 26 | enabled: no 27 | 28 | - name: Disable systemd-resolved 29 | systemd: 30 | name: systemd-resolved 31 | state: stopped 32 | enabled: no 33 | 34 | - name: Create and start services 35 | command: docker compose -f {{ local_apps_path }}/adguard/docker-compose.yml up -d 36 | 37 | 38 | -------------------------------------------------------------------------------- /playbooks/install_bind9.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for Bind9 installation 2 | 3 | --- 4 | - hosts: thinky01 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: create directory if they don't exist 9 | file: 10 | path: "{{ item }}" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0777 15 | loop: 16 | - /home/{{ ansible_user }}/apps/bind9/bind/ 17 | - /home/{{ ansible_user }}/apps/bind9/cache/bind 18 | - /home/{{ ansible_user }}/apps/bind9/lib/bind 19 | - /home/{{ ansible_user }}/apps/bind9 20 | 21 | - name: Upload docker-compose 22 | template: 23 | src: bind9/docker-compose.yml 24 | dest: /home/{{ ansible_user }}/apps/bind9/docker-compose.yml 25 | owner: "{{ ansible_user }}" 26 | group: "{{ ansible_user }}" 27 | mode: 0644 28 | 29 | - name: Upload conf file 30 | copy: 31 | src: bind9/named.conf 32 | dest: /home/{{ ansible_user }}/apps/bind9/bind/named.conf 33 | owner: "{{ ansible_user }}" 34 | group: "{{ ansible_user }}" 35 | mode: 0644 36 | 37 | - name: Upload zone file 38 | copy: 39 | src: bind9/{{ homelab_domain }}.zone 40 | dest: /home/{{ ansible_user }}/apps/bind9/bind/{{ homelab_domain }}.zone 41 | owner: "{{ ansible_user }}" 42 | group: "{{ ansible_user }}" 43 | mode: 0644 44 | 45 | - name: Create and start services 46 | community.docker.docker_compose: 47 | project_src: /home/{{ ansible_user }}/apps/bind9 48 | register: output 49 | 50 | -------------------------------------------------------------------------------- /playbooks/install_caddy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-fuji 3 | tasks: 4 | - import_tasks: ../tasks/apt-upgrade.yml 5 | 6 | - name: Create directory for caddy 7 | file: 8 | path: "{{ local_apps_path }}/caddy" 9 | state: directory 10 | owner: "{{ ansible_user }}" 11 | group: "{{ ansible_user }}" 12 | mode: 0755 13 | 14 | - name: Copy necessafy files 15 | copy: 16 | src: '{{item}}' 17 | dest: "{{ local_apps_path }}/caddy" 18 | owner: root 19 | group: root 20 | mode: 0644 21 | loop: 22 | - ./caddy/container-vars.env 23 | - ./caddy/Caddyfile 24 | - ./caddy/Dockerfile 25 | - ./caddy/docker-compose.yml 26 | 27 | - name: Replace MY_DOMAIN in container-vars.env file 28 | lineinfile: 29 | path: "{{ local_apps_path }}/caddy/container-vars.env" 30 | regexp: '^MY_DOMAIN=.*$' 31 | line: "MY_DOMAIN={{ homelab_domain }}" 32 | 33 | - name: Replace MY_HOST_IP in container-vars.env file 34 | lineinfile: 35 | path: "{{ local_apps_path }}/caddy/container-vars.env" 36 | regexp: '^MY_HOST_IP=.*$' 37 | line: "MY_HOST_IP={{ homelab_tailscale_ip }}" 38 | 39 | - name: Replace CLOUDFLARE_API_TOKEN in container-vars.env file 40 | lineinfile: 41 | path: "{{ local_apps_path }}/caddy/container-vars.env" 42 | regexp: '^CLOUDFLARE_API_TOKEN=.*$' 43 | line: "CLOUDFLARE_API_TOKEN={{ cf_api_token }}" 44 | 45 | - name: Replace CLOUDFLARE_API_TOKEN in Caddyfile 46 | replace: 47 | path: "{{ local_apps_path }}/caddy/Caddyfile" 48 | regexp: 'dns cloudflare 123' 49 | replace: " dns cloudflare {{ cf_api_token }}" 50 | 51 | - name: Create external network caddy_caddynet 52 | community.docker.docker_network: 53 | name: caddy_caddynet 54 | state: present 55 | 56 | - name: Restart existing services 57 | command: docker compose -f {{ local_apps_path }}/caddy/docker-compose.yml restart 58 | -------------------------------------------------------------------------------- /playbooks/install_dawarich.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for dawarich installation 2 | 3 | --- 4 | - hosts: homelab-prod 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | - import_tasks: ../tasks/install_rclone.yml 8 | 9 | # - name: Create directory for dawarich 10 | # file: 11 | # path: "{{ local_apps_path }}/dawarich" 12 | # state: directory 13 | # owner: "{{ ansible_user }}" 14 | # group: "{{ ansible_user }}" 15 | # mode: 0755 16 | 17 | # - name: Upload dawarich docker-compose.yml 18 | # copy: 19 | # src: ./dawarich/docker-compose.yml 20 | # dest: "{{ local_apps_path }}/dawarich/docker-compose.yml" 21 | # mode: 0644 22 | 23 | # - name: Upload dawarich env vars 24 | # template: 25 | # src: ./dawarich/example.env 26 | # dest: "{{ local_apps_path }}/dawarich/.env" 27 | # owner: "{{ ansible_user }}" 28 | # group: "{{ ansible_user }}" 29 | # mode: 0644 30 | 31 | # - name: Install pipx 32 | # ansible.builtin.apt: 33 | # name: pipx 34 | # state: present 35 | 36 | # - name: Ensure pipx binary is accessible 37 | # ansible.builtin.shell: | 38 | # python3 -m pipx ensurepath 39 | 40 | # - name: Install docker-compose using pipx 41 | # ansible.builtin.shell: | 42 | # pipx install docker-compose 43 | # args: 44 | # creates: /usr/local/bin/docker-compose 45 | 46 | # - name: Stop existing services 47 | # command: docker compose -f {{ local_apps_path }}/dawarich/docker-compose.yml up -d 48 | 49 | # - name: Create and start services 50 | # command: docker compose -f {{ local_apps_path }}/dawarich/docker-compose.yml up -d 51 | 52 | - name: Create directory if they don't exist 53 | file: 54 | path: "{{ item }}" 55 | state: directory 56 | owner: root 57 | group: root 58 | mode: 0775 59 | loop: 60 | - "{{ local_pool_path }}/tasks/dawarich/" 61 | - "{{ local_backups_path }}/dawarich" 62 | 63 | 64 | - name: Upload dawarich backup script 65 | template: 66 | src: "./dawarich/backup.sh" 67 | dest: "{{ local_pool_path }}/tasks/dawarich/backup.sh" 68 | owner: "{{ ansible_user }}" 69 | group: "{{ ansible_user }}" 70 | mode: 0700 71 | 72 | - name: Schedule dawarich DB backup to be done every 3 days 73 | cron: 74 | name: "Dump dawarich DB to a local file" 75 | minute: "45" 76 | hour: "5" 77 | day: "*/3" 78 | job: "{{ local_pool_path }}/tasks/dawarich/backup.sh" 79 | state: present 80 | -------------------------------------------------------------------------------- /playbooks/install_docker.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-rocky 3 | become: yes 4 | vars: 5 | docker_compose_version: "2.29.2" 6 | tasks: 7 | 8 | # # Step 1: Update apt package index 9 | # - name: Update apt cache 10 | # ansible.builtin.apt: 11 | # update_cache: yes 12 | 13 | # # Step 2: Install required packages (ca-certificates, curl, gnupg, lsb-release) 14 | # - name: Install required dependencies 15 | # ansible.builtin.apt: 16 | # name: 17 | # - ca-certificates 18 | # - curl 19 | # - gnupg 20 | # - lsb-release 21 | # state: present 22 | 23 | # # Step 3: Create directory for apt keyrings 24 | # - name: Create directory for Docker apt keyring 25 | # ansible.builtin.file: 26 | # path: /etc/apt/keyrings 27 | # state: directory 28 | # mode: '0755' 29 | 30 | # # Step 4: Add Docker’s official GPG key 31 | # - name: Download Docker GPG key using curl 32 | # ansible.builtin.shell: | 33 | # curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc 34 | # args: 35 | # creates: /etc/apt/keyrings/docker.asc 36 | 37 | # # Step 5: Set permissions on Docker GPG key 38 | # - name: Set permissions for Docker GPG key 39 | # ansible.builtin.file: 40 | # path: /etc/apt/keyrings/docker.asc 41 | # mode: '0644' 42 | 43 | # # Step 6: Add Docker repository to apt sources 44 | # - name: Add Docker APT repository 45 | # ansible.builtin.apt_repository: 46 | # repo: "deb [arch={{ ansible_architecture }} signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable" 47 | # state: present 48 | 49 | # # Step 7: Update apt package index again after adding Docker repo 50 | # - name: Update apt cache again after adding Docker repository 51 | # ansible.builtin.apt: 52 | # update_cache: yes 53 | 54 | # # Step 8: Install Docker Engine 55 | # - name: Install Docker Engine 56 | # ansible.builtin.apt: 57 | # name: 58 | # - docker-ce 59 | # - docker-ce-cli 60 | # - containerd.io 61 | # state: present 62 | 63 | # # Step 9: Ensure Docker service is enabled and running 64 | # - name: Ensure Docker is enabled and running 65 | # ansible.builtin.systemd: 66 | # name: docker 67 | # enabled: yes 68 | # state: started 69 | 70 | # Step 10: Download and install Docker Compose 71 | - name: Download Docker Compose 72 | ansible.builtin.shell: | 73 | curl -fsSL https://github.com/docker/compose/releases/download/v{{ docker_compose_version }}/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose 74 | args: 75 | creates: /usr/local/bin/docker-compose 76 | 77 | # Step 11: Set execute permissions on Docker Compose binary 78 | - name: Set execute permissions on Docker Compose 79 | ansible.builtin.file: 80 | path: /usr/local/bin/docker-compose 81 | mode: '0755' 82 | 83 | # Step 12: Verify Docker Compose installation 84 | - name: Check Docker Compose version 85 | ansible.builtin.command: /usr/local/bin/docker-compose --version 86 | register: docker_compose_version_output 87 | 88 | - name: Display Docker Compose version 89 | debug: 90 | msg: "Docker Compose version: {{ docker_compose_version_output.stdout }}" 91 | 92 | -------------------------------------------------------------------------------- /playbooks/install_dokku.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: dokku 3 | vars: 4 | dokku_version: "0.31.4" 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | - import_tasks: ../tasks/rename_host.yml 8 | vars: 9 | hostname: dokku-hetzner 10 | 11 | # DOKKU INSTALLATION 12 | ## TODO: Add crontask setup for docker system prune -a 13 | - name: Add 3GB of swap 14 | become: true 15 | command: fallocate -l 3G /swapfile 16 | args: 17 | creates: /swapfile 18 | 19 | - name: Download the dokku bootstrap script 20 | get_url: 21 | url: https://dokku.com/install/v{{ dokku_version }}/bootstrap.sh 22 | dest: /tmp/bootstrap.sh 23 | mode: 0755 24 | 25 | - name: Install dokku 26 | command: /tmp/bootstrap.sh 27 | args: 28 | creates: /usr/local/bin/dokku 29 | 30 | - name: Add ssh key to dokku 31 | become: true 32 | command: cat ~/.ssh/authorized_keys | dokku ssh-keys:add admin 33 | args: 34 | creates: /home/dokku/.ssh/authorized_keys 35 | 36 | - name: Get list of dokku plugins 37 | command: dokku plugin:list 38 | register: dokku_plugin_list 39 | 40 | - name: Install dokku postgres plugin 41 | command: dokku plugin:install https://github.com/dokku/dokku-postgres.git 42 | when: "'postgres' not in dokku_plugin_list.stdout" 43 | 44 | - name: Install dokku redis plugin 45 | command: dokku plugin:install https://github.com/dokku/dokku-redis.git redis 46 | when: "'redis' not in dokku_plugin_list.stdout" 47 | -------------------------------------------------------------------------------- /playbooks/install_gitea.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for gitea installation 2 | 3 | --- 4 | - hosts: homelab-prod 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for gitea 9 | file: 10 | path: "{{ local_apps_path }}/gitea" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Create directory for gitea data 17 | file: 18 | path: "{{ local_apps_path }}/gitea/data" 19 | state: directory 20 | owner: "{{ ansible_user }}" 21 | group: "{{ ansible_user }}" 22 | mode: 0755 23 | 24 | - name: Create directory for gitea db 25 | file: 26 | path: "{{ local_apps_path }}/gitea/mysql" 27 | state: directory 28 | owner: "{{ ansible_user }}" 29 | group: "{{ ansible_user }}" 30 | mode: 0755 31 | 32 | - name: Upload gitea docker-compose.yml 33 | copy: 34 | src: ./gitea/docker-compose.yml 35 | dest: "{{ local_apps_path }}/gitea/docker-compose.yml" 36 | mode: 0644 37 | 38 | - name: Stop existing services 39 | command: docker compose -f {{ local_apps_path }}/gitea/docker-compose.yml down 40 | 41 | - name: Create and start services 42 | command: docker compose -f {{ local_apps_path }}/gitea/docker-compose.yml up -d 43 | 44 | # 1. Stop Gitea 45 | # 2. Make backup 46 | # 3. Start Gitea 47 | # 4. Upload backup 48 | 49 | 50 | # - name: Schedule Gitea DB backup to be done daily 51 | # cron: 52 | # name: "Backup Gitea DB" 53 | # minute: "45" 54 | # hour: "5" 55 | # job: docker compose -f {{ local_apps_path }}/gitea/docker-compose.yml down && 56 | 57 | 58 | # docker exec -u {{ ansible_user }} -it -w {{ local_apps_path }}/gitea $(docker ps -qf 'name=^gitea-db-1$') bash -c '/usr/local/bin/gitea dump -c /data/gitea/conf/app.ini 59 | 60 | 61 | 62 | 63 | # exec -T gitea_db mysqldump -u root --password={{ gitea_db_password }} gitea | gzip > "{{ local_backup_path }}/gitea_db_dump.sql.gz" && curl -X GET {{ healthchecks_ping_url }}{{ hc_gitea_backup_uuid }} 64 | # # job: docker exec -t immich_postgres pg_dumpall -c -U postgres | gzip > "{{ local_backup_path }}/db_dump.sql.gz" && curl -X GET {{ healthchecks_ping_url }}{{ hc_immich_backup_uuid }} 65 | # state: present 66 | -------------------------------------------------------------------------------- /playbooks/install_glances.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for Glances installation 2 | 3 | --- 4 | - hosts: homelab-fuji 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for Glances 9 | file: 10 | path: "{{ local_apps_path }}/glances" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Upload Glances docker-compose.yml 17 | copy: 18 | src: ./glances/docker-compose.yml 19 | dest: "{{ local_apps_path }}/glances/docker-compose.yml" 20 | mode: 0644 21 | 22 | - name: Create and start services 23 | command: docker compose -f {{ local_apps_path }}/glances/docker-compose.yml up -d 24 | -------------------------------------------------------------------------------- /playbooks/install_go.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: thinky01 3 | tasks: 4 | - import_tasks: ../tasks/apt-upgrade.yml 5 | 6 | - name: Remove existing go installation 7 | shell: rm -rf /usr/local/go && tar -C /usr/local -xzf go1.21.3.linux-amd64.tar.gz 8 | ignore_errors: true 9 | 10 | - name: Download go archive 11 | get_url: 12 | url: https://golang.org/dl/go1.21.3.linux-amd64.tar.gz 13 | dest: /home/frey/apps/go1.21.3.linux-amd64.tar.gz 14 | mode: 0644 15 | owner: frey 16 | group: frey 17 | 18 | - name: Extract go archive 19 | shell: tar -C /usr/local -xzf /home/frey/apps/go1.21.3.linux-amd64.tar.gz 20 | args: 21 | creates: /usr/local/go 22 | 23 | - name: Set go environment variables 24 | lineinfile: 25 | path: /home/frey/.bashrc 26 | line: | 27 | export PATH=$PATH:/usr/local/go/bin 28 | export GOPATH=/home/frey/go 29 | export PATH=$PATH:$GOPATH/bin 30 | state: present 31 | create: yes 32 | owner: frey 33 | group: frey 34 | mode: 0644 35 | 36 | - name: Check go version 37 | shell: /home/frey/.bashrc && go version 38 | args: 39 | executable: /bin/bash 40 | register: go_version 41 | 42 | - name: Echo go version 43 | debug: 44 | msg: "{{ go_version.stdout }}" 45 | 46 | - name: Remove go archive 47 | file: 48 | path: /home/frey/apps/go1.21.3.linux-amd64.tar.gz 49 | state: absent 50 | -------------------------------------------------------------------------------- /playbooks/install_healthchecks.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-prod 3 | tasks: 4 | - import_tasks: ../tasks/apt-upgrade.yml 5 | 6 | - name: Create directory for healthchecks 7 | file: 8 | path: "{{ local_apps_path }}/healthchecks" 9 | state: directory 10 | owner: "{{ ansible_user }}" 11 | group: "{{ ansible_user }}" 12 | mode: 0755 13 | 14 | - name: Upload healthchecks docker-compose.yml 15 | copy: 16 | src: ./healthchecks/docker-compose.yml 17 | dest: "{{ local_apps_path }}/healthchecks/docker-compose.yml" 18 | owner: frey 19 | group: frey 20 | mode: 0644 21 | 22 | # - name: Replace TELEGRAM_BOT_NAME in docker-compose.yml 23 | # replace: 24 | # path: "{{ local_apps_path }}/healthchecks/docker-compose.yml" 25 | # regexp: '{TELEGRAM_BOT_NAME}' 26 | # replace: "{{ homelab_telegram_bot_name }}" 27 | 28 | # - name: Replace TELEGRAM_BOT_TOKEN in docker-compose.yml 29 | # replace: 30 | # path: "{{ local_apps_path }}/healthchecks/docker-compose.yml" 31 | # regexp: '{TELEGRAM_BOT_TOKEN}' 32 | # replace: "{{ homelab_telegram_bot_token }}" 33 | 34 | - name: Create and start services 35 | command: docker compose -f {{ local_apps_path }}/healthchecks/docker-compose.yml restart 36 | 37 | 38 | # Then create a superuser: 39 | # $ docker compose run healthchecks /opt/healthchecks/manage.py createsuperuser 40 | # Visit https://healthchecks.chibi.rodeo 41 | 42 | 43 | # - name: Install runitor 44 | -------------------------------------------------------------------------------- /playbooks/install_home_assistant.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for HomeAssistant installation 2 | 3 | --- 4 | - hosts: homelab-prod 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: create directory if they don't exist 9 | file: 10 | path: "{{ item }}" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0777 15 | loop: 16 | - /home/{{ ansible_user }}/apps/home_assistant 17 | - /home/{{ ansible_user }}/apps/home_assistant/config 18 | 19 | - name: Upload docker-compose 20 | template: 21 | src: home_assistant/docker-compose.yml 22 | dest: /home/{{ ansible_user }}/apps/home_assistant/docker-compose.yml 23 | owner: "{{ ansible_user }}" 24 | group: "{{ ansible_user }}" 25 | mode: 0644 26 | 27 | - name: Create and start services 28 | community.docker.docker_compose: 29 | project_src: /home/{{ ansible_user }}/apps/home_assistant 30 | register: output 31 | -------------------------------------------------------------------------------- /playbooks/install_homepage.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for homepage installation 2 | 3 | --- 4 | - hosts: homelab-prod 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for homepage 9 | file: 10 | path: "{{ local_apps_path }}/homepage" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Upload homepage docker-compose.yml 17 | copy: 18 | src: ./homepage/docker-compose.yml 19 | dest: "{{ local_apps_path }}/homepage/docker-compose.yml" 20 | mode: 0644 21 | 22 | # First start of homepage will fail because of existing config files 23 | - name: Create and start services 24 | command: docker compose -f {{ local_apps_path }}/homepage/docker-compose.yml up -d 25 | 26 | # Then copy config files 27 | - name: Copy config files 28 | copy: 29 | src: '{{item}}' 30 | dest: "{{ local_apps_path }}/homepage/config" 31 | owner: root 32 | group: root 33 | mode: 0644 34 | loop: 35 | - ./homepage/config/services.yaml 36 | - ./homepage/config/docker.yaml 37 | - ./homepage/config/settings.yaml 38 | - ./homepage/config/widgets.yaml 39 | 40 | # Then restart services to apply config files 41 | - name: Restart services 42 | command: "docker compose -f {{ local_apps_path }}/homepage/docker-compose.yml restart" 43 | -------------------------------------------------------------------------------- /playbooks/install_immich.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for Immich installation 2 | 3 | --- 4 | - hosts: homelab-fuji 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | - import_tasks: ../tasks/install_rclone.yml 8 | 9 | - name: Create directory for Immich 10 | file: 11 | path: "{{ local_apps_path }}/immich" 12 | state: directory 13 | owner: "{{ ansible_user }}" 14 | group: "{{ ansible_user }}" 15 | mode: 0755 16 | 17 | - name: Upload Immich docker-compose.yml 18 | copy: 19 | src: ./immich/docker-compose.yml 20 | dest: "{{ local_apps_path }}/immich/docker-compose.yml" 21 | mode: 0644 22 | 23 | - name: Upload Immich env vars 24 | template: 25 | src: ./immich/example.env 26 | dest: "{{ local_apps_path }}/immich/.env" 27 | owner: "{{ ansible_user }}" 28 | group: "{{ ansible_user }}" 29 | mode: 0644 30 | 31 | - name: Install pipx 32 | ansible.builtin.apt: 33 | name: pipx 34 | state: present 35 | 36 | - name: Ensure pipx binary is accessible 37 | ansible.builtin.shell: | 38 | python3 -m pipx ensurepath 39 | 40 | - name: Install docker-compose using pipx 41 | ansible.builtin.shell: | 42 | pipx install docker-compose 43 | args: 44 | creates: /usr/local/bin/docker-compose 45 | 46 | - name: Stop existing services 47 | command: docker compose -f {{ local_apps_path }}/immich/docker-compose.yml up -d 48 | 49 | - name: Create and start services 50 | command: docker compose -f {{ local_apps_path }}/immich/docker-compose.yml up -d 51 | 52 | - name: Create directory if they don't exist 53 | file: 54 | path: "{{ item }}" 55 | state: directory 56 | owner: root 57 | group: root 58 | mode: 0775 59 | loop: 60 | - "{{ local_pool_path }}/tasks/immich/" 61 | - "{{ local_backups_path }}/immich" 62 | 63 | 64 | - name: Upload Immich backup script 65 | template: 66 | src: "./immich/backup.sh" 67 | dest: "{{ local_pool_path }}/tasks/immich/backup.sh" 68 | owner: "{{ ansible_user }}" 69 | group: "{{ ansible_user }}" 70 | mode: 0700 71 | 72 | - name: Schedule Immich DB backup to be done monthly 73 | cron: 74 | name: "Dump Immich DB to a local file" 75 | minute: "45" 76 | hour: "5" 77 | day: "1" 78 | job: "{{ local_pool_path }}/tasks/immich/backup.sh" 79 | state: present 80 | -------------------------------------------------------------------------------- /playbooks/install_jellyfin.yml: -------------------------------------------------------------------------------- 1 | # https://hub.docker.com/r/linuxserver/jellyfin 2 | 3 | --- 4 | - hosts: homelab-prod 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for Jellyfin 9 | file: 10 | path: "{{ local_apps_path }}/jelly" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Create all necessary directories 17 | file: 18 | path: "{{ local_apps_storage_path }}/jelly/{{ item }}" 19 | state: directory 20 | owner: "{{ ansible_user }}" 21 | group: "{{ ansible_user }}" 22 | mode: 0755 23 | loop: 24 | - library 25 | - tvseries 26 | - movies 27 | 28 | - name: Set recursive permissions for Jellyfin config 29 | file: 30 | path: "{{ local_apps_storage_path }}/jelly" 31 | owner: "{{ ansible_user }}" 32 | group: "{{ ansible_user }}" 33 | mode: 0755 34 | recurse: true 35 | 36 | - name: Upload jellyfin docker-compose 37 | template: 38 | src: "jellyfin/docker-compose.yml" 39 | dest: "{{ local_apps_path }}/jelly/docker-compose.yml" 40 | owner: "{{ ansible_user }}" 41 | group: "{{ ansible_user }}" 42 | mode: 0600 43 | 44 | - name: Stop existing services 45 | command: docker compose -f {{ local_apps_path }}/jelly/docker-compose.yml up -d 46 | 47 | - name: Create and start services 48 | command: docker compose -f {{ local_apps_path }}/jelly/docker-compose.yml up -d 49 | 50 | -------------------------------------------------------------------------------- /playbooks/install_lubelogger.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-prod 3 | tasks: 4 | - import_tasks: ../tasks/apt-upgrade.yml 5 | 6 | - name: Create directory for lubelogger 7 | file: 8 | path: "{{ local_apps_path }}/lubelogger" 9 | state: directory 10 | owner: "{{ ansible_user }}" 11 | group: "{{ ansible_user }}" 12 | mode: 0755 13 | 14 | - name: Copy necessafy files 15 | copy: 16 | src: '{{item}}' 17 | dest: "{{ local_apps_path }}/lubelogger" 18 | owner: root 19 | group: root 20 | mode: 0644 21 | loop: 22 | - ./lubelogger/docker-compose.yml 23 | - ./lubelogger/.env 24 | 25 | - name: Stop existing services 26 | command: docker compose -f {{ local_apps_path }}/lubelogger/docker-compose.yml up -d 27 | 28 | - name: Create and start services 29 | command: docker compose -f {{ local_apps_path }}/lubelogger/docker-compose.yml up -d 30 | 31 | -------------------------------------------------------------------------------- /playbooks/install_mailrise.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-prod 3 | tasks: 4 | - import_tasks: ../tasks/apt-upgrade.yml 5 | 6 | - name: Create directory for mailrise 7 | file: 8 | path: "{{ local_apps_path }}/mailrise" 9 | state: directory 10 | owner: "{{ ansible_user }}" 11 | group: "{{ ansible_user }}" 12 | mode: 0755 13 | 14 | - name: Upload mailrise docker-compose.yml 15 | copy: 16 | src: ./mailrise/docker-compose.yml 17 | dest: "{{ local_apps_path }}/mailrise/docker-compose.yml" 18 | owner: frey 19 | group: frey 20 | mode: 0644 21 | 22 | # - name: Replace TELEGRAM_BOT_NAME in docker-compose.yml 23 | # replace: 24 | # path: "{{ local_apps_path }}/mailrise/docker-compose.yml" 25 | # regexp: '{TELEGRAM_BOT_NAME}' 26 | # replace: "{{ homelab_telegram_bot_name }}" 27 | 28 | # - name: Replace TELEGRAM_BOT_TOKEN in docker-compose.yml 29 | # replace: 30 | # path: "{{ local_apps_path }}/mailrise/docker-compose.yml" 31 | # regexp: '{TELEGRAM_BOT_TOKEN}' 32 | # replace: "{{ homelab_telegram_bot_token }}" 33 | 34 | - name: Stop existing services 35 | command: docker compose -f {{ local_apps_path }}/mailrise/docker-compose.yml down 36 | 37 | - name: Create and start services 38 | command: docker compose -f {{ local_apps_path }}/mailrise/docker-compose.yml up -d 39 | 40 | 41 | # Then create a superuser: 42 | # $ docker-compose run web /opt/mailrise/manage.py createsuperuser 43 | 44 | 45 | # - name: Install runitor 46 | -------------------------------------------------------------------------------- /playbooks/install_monitoring.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for Influxdb-Grafana-Prometheus installation 2 | 3 | --- 4 | - hosts: homelab-rocky 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for Monitoring stack 9 | file: 10 | path: "{{ local_apps_path }}/monitoring" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Upload Monitoring stack docker-compose.yml 17 | template: 18 | src: "monitoring/docker-compose.yml" 19 | dest: "{{ local_apps_path }}/monitoring/docker-compose.yml" 20 | owner: "{{ ansible_user }}" 21 | group: "{{ ansible_user }}" 22 | mode: 0600 23 | 24 | - name: Upload Prometheus configuration 25 | template: 26 | src: "monitoring/prometheus.yml" 27 | dest: "{{ local_apps_path }}/monitoring/prometheus.yml" 28 | owner: "{{ ansible_user }}" 29 | group: "{{ ansible_user }}" 30 | mode: 0600 31 | 32 | - name: Stop existing services 33 | command: docker compose -f {{ local_apps_path }}/monitoring/docker-compose.yml down 34 | 35 | - name: Create and start services 36 | command: docker compose -f {{ local_apps_path }}/monitoring/docker-compose.yml up -d 37 | -------------------------------------------------------------------------------- /playbooks/install_n8n.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-prod 3 | tasks: 4 | - import_tasks: ../tasks/apt-upgrade.yml 5 | 6 | - name: Create directory for n8n 7 | file: 8 | path: "{{ local_apps_path }}/n8n" 9 | state: directory 10 | owner: "{{ ansible_user }}" 11 | group: "{{ ansible_user }}" 12 | mode: 0755 13 | 14 | - name: Copy necessafy files 15 | copy: 16 | src: '{{item}}' 17 | dest: "{{ local_apps_path }}/n8n" 18 | owner: root 19 | group: root 20 | mode: 0644 21 | loop: 22 | - ./n8n/docker-compose.yml 23 | - ./n8n/.env 24 | 25 | - name: Stop existing services 26 | command: docker compose -f {{ local_apps_path }}/n8n/docker-compose.yml up -d 27 | 28 | - name: Create and start services 29 | command: docker compose -f {{ local_apps_path }}/n8n/docker-compose.yml up -d 30 | 31 | -------------------------------------------------------------------------------- /playbooks/install_nextcloud.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for NextCloud installation 2 | 3 | --- 4 | - hosts: thinky01 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: create directory if they don't exist 9 | file: 10 | path: "{{ item }}" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0777 15 | loop: 16 | - /home/{{ ansible_user }}/apps/nextcloud 17 | - /home/{{ ansible_user }}/apps/nextcloud/config 18 | 19 | - name: Upload docker-compose 20 | template: 21 | src: nextcloud/docker-compose.yml 22 | dest: /home/{{ ansible_user }}/apps/nextcloud/docker-compose.yml 23 | owner: "{{ ansible_user }}" 24 | group: "{{ ansible_user }}" 25 | mode: 0644 26 | 27 | - name: Create and start services 28 | community.docker.docker_compose: 29 | project_src: /home/{{ ansible_user }}/apps/nextcloud 30 | register: output 31 | -------------------------------------------------------------------------------- /playbooks/install_nginx.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for nginx installation 2 | 3 | --- 4 | - hosts: racknerd 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Сreate directory if they don't exist 9 | file: 10 | path: "{{ item }}" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0777 15 | loop: 16 | - "{{ local_nginx_path }}" 17 | - "{{ local_nginx_path }}/data/" 18 | - "{{ local_nginx_path }}/letsencrypt" 19 | 20 | - name: Upload nginx docker-compose 21 | template: 22 | src: "nginx/docker-compose.yml" 23 | dest: "{{ local_nginx_path }}/docker-compose.yml" 24 | owner: "{{ ansible_user }}" 25 | group: "{{ ansible_user }}" 26 | mode: 0600 27 | 28 | - name: Install Docker SDK for Python 29 | ansible.builtin.pip: 30 | name: 31 | - "docker==6.1.3" 32 | - "docker-compose" 33 | 34 | - name: Create and start services 35 | community.docker.docker_compose: 36 | project_src: "{{ local_nginx_path }}" 37 | register: output 38 | 39 | 40 | -------------------------------------------------------------------------------- /playbooks/install_ntfy.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for ntfy installation 2 | 3 | --- 4 | - hosts: homelab-prod 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for ntfy 9 | file: 10 | path: "{{ local_apps_path }}/ntfy" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Upload ntfy docker-compose.yml 17 | copy: 18 | src: ./ntfy/docker-compose.yml 19 | dest: "{{ local_apps_path }}/ntfy/docker-compose.yml" 20 | mode: 0644 21 | 22 | # First start of ntfy will fail because of existing config files 23 | - name: Create and start services 24 | command: docker compose -f {{ local_apps_path }}/ntfy/docker-compose.yml up -d 25 | -------------------------------------------------------------------------------- /playbooks/install_owncloud.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for Owncloud installation 2 | --- 3 | - hosts: homelab-fuji 4 | tasks: 5 | - import_tasks: ../tasks/apt-upgrade.yml 6 | 7 | - name: Create directory if they don't exist 8 | file: 9 | path: "{{ item }}" 10 | state: directory 11 | owner: "{{ ansible_user }}" 12 | group: "{{ ansible_user }}" 13 | mode: 0775 14 | loop: 15 | - "{{ local_apps_path }}/owncloud" 16 | - "{{ local_apps_path }}/owncloud/files" 17 | - "{{ local_pool_path }}/tasks/owncloud/" 18 | - "{{ local_backups_path }}/owncloud" 19 | 20 | - name: Upload Owncloud compose.yml 21 | copy: 22 | src: ./owncloud/compose.yml 23 | dest: "{{ local_apps_path }}/owncloud/compose.yml" 24 | mode: 0644 25 | 26 | - name: Stop existing services 27 | command: docker compose -f {{ local_apps_path }}/owncloud/compose.yml up -d 28 | 29 | - name: Create and start services 30 | command: docker compose -f {{ local_apps_path }}/owncloud/compose.yml up -d 31 | 32 | # - name: Upload Owncloud backup script 33 | # template: 34 | # src: "./owncloud/backup.sh" 35 | # dest: "{{ local_pool_path }}/tasks/owncloud/backup.sh" 36 | # owner: "{{ ansible_user }}" 37 | # group: "{{ ansible_user }}" 38 | # mode: 0700 39 | 40 | # - name: Schedule Owncloud DB backup to be done monthly 41 | # cron: 42 | # name: "Dump Owncloud DB to a local file" 43 | # minute: "45" 44 | # hour: "5" 45 | # day: "1" 46 | # job: "{{ local_pool_path }}/tasks/owncloud/backup.sh" 47 | # state: present 48 | -------------------------------------------------------------------------------- /playbooks/install_owntracks.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for OwnTracks installation 2 | 3 | --- 4 | - hosts: homelab-prod 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for owntracks 9 | file: 10 | path: "{{ local_apps_path }}/owntracks" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Upload Owntracks docker-compose.yml 17 | copy: 18 | src: ./owntracks/docker-compose.yml 19 | dest: "{{ local_apps_path }}/owntracks/docker-compose.yml" 20 | mode: 0644 21 | 22 | - name: Create and start services 23 | command: docker compose -f {{ local_apps_path }}/owntracks/docker-compose.yml up -d 24 | 25 | 26 | -------------------------------------------------------------------------------- /playbooks/install_photon.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for photon installation 2 | # https://tonsnoei.nl/en/post/2023/03/20/set-up-your-own-geocoder-api/ 3 | 4 | --- 5 | - hosts: homelab-fuji 6 | tasks: 7 | - import_tasks: ../tasks/apt-upgrade.yml 8 | 9 | - name: Create directory for photon 10 | file: 11 | path: "{{ local_apps_path }}/photon" 12 | state: directory 13 | owner: "{{ ansible_user }}" 14 | group: "{{ ansible_user }}" 15 | mode: 0755 16 | 17 | - name: Create directory for photon data 18 | file: 19 | path: "{{ local_apps_path }}/photon/data" 20 | state: directory 21 | owner: "{{ ansible_user }}" 22 | group: "{{ ansible_user }}" 23 | mode: 0755 24 | 25 | - name: Copy necessafy files 26 | copy: 27 | src: '{{item}}' 28 | dest: "{{ local_apps_path }}/photon" 29 | owner: root 30 | group: root 31 | mode: 0644 32 | loop: 33 | - ./photon/docker-compose.yml 34 | - ./photon/Dockerfile 35 | - ./photon/entrypoint.sh 36 | 37 | - name: Make photon/entrypoint.sh executable 38 | command: chmod +x {{ local_apps_path }}/photon/entrypoint.sh 39 | 40 | - name: Build docker image 41 | command: docker compose -f {{ local_apps_path }}/photon/docker-compose.yml build 42 | 43 | - name: Stop existing services 44 | command: docker compose -f {{ local_apps_path }}/photon/docker-compose.yml stop 45 | 46 | - name: Create and start services 47 | command: docker compose -f {{ local_apps_path }}/photon/docker-compose.yml up -d 48 | 49 | - name: Attach to logs 50 | command: docker compose -f {{ local_apps_path }}/photon/docker-compose.yml logs -f 51 | 52 | -------------------------------------------------------------------------------- /playbooks/install_pihole.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for pihole installation 2 | 3 | --- 4 | - hosts: homelab-prod 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for pihole 9 | file: 10 | path: "{{ local_apps_path }}/pihole" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Upload pihole docker-compose.yml 17 | copy: 18 | src: ./pihole/docker-compose.yml 19 | dest: "{{ local_apps_path }}/pihole/docker-compose.yml" 20 | mode: 0644 21 | 22 | - name: Stop systemd-resolved 23 | systemd: 24 | name: systemd-resolved 25 | state: stopped 26 | enabled: no 27 | 28 | - name: Disable systemd-resolved 29 | systemd: 30 | name: systemd-resolved 31 | state: stopped 32 | enabled: no 33 | 34 | - name: Create and start services 35 | command: docker compose -f {{ local_apps_path }}/pihole/docker-compose.yml up -d 36 | 37 | 38 | -------------------------------------------------------------------------------- /playbooks/install_portainer.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-rocky 3 | 4 | tasks: 5 | - import_tasks: ../tasks/apt-upgrade.yml 6 | 7 | - name: Ensure docker deamon is running 8 | service: 9 | name: docker 10 | state: started 11 | become: true 12 | 13 | # https://docs.ansible.com/ansible/latest/collections/community/docker/docker_container_module.html#ansible-collections-community-docker-docker-container-module 14 | - name: Create portainer container 15 | docker_container: 16 | name: portainer 17 | image: portainer/portainer-ce 18 | state: started 19 | recreate: yes 20 | restart_policy: always 21 | published_ports: 22 | - "8000:8000" 23 | - "9000:9000" 24 | volumes: 25 | - /var/run/docker.sock:/var/run/docker.sock 26 | - portainer_data:/data 27 | 28 | # FIREWALL SETUP 29 | # - name: Disable UFW 30 | # ufw: 31 | # state: disabled 32 | -------------------------------------------------------------------------------- /playbooks/install_registry.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-prod 3 | 4 | tasks: 5 | - import_tasks: ../tasks/apt-upgrade.yml 6 | 7 | - name: Create directory if they don't exist 8 | file: 9 | path: "{{ item }}" 10 | state: directory 11 | owner: root 12 | group: root 13 | mode: 0775 14 | loop: 15 | - "{{ local_apps_path }}/registry" 16 | - "{{ local_apps_path }}/registry/data" 17 | 18 | - name: Copy necessafy files 19 | copy: 20 | src: '{{item}}' 21 | dest: "{{ local_apps_path }}/registry" 22 | owner: root 23 | group: root 24 | mode: 0644 25 | loop: 26 | - ./registry/docker-compose.yml 27 | 28 | - name: Stop existing services 29 | command: docker compose -f {{ local_apps_path }}/registry/docker-compose.yml up -d 30 | 31 | - name: Create and start services 32 | command: docker compose -f {{ local_apps_path }}/registry/docker-compose.yml up -d 33 | -------------------------------------------------------------------------------- /playbooks/install_runitor.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: thinky01 3 | tasks: 4 | - import_tasks: ../tasks/apt-upgrade.yml 5 | 6 | - name: Install runitor 7 | shell: go install bdd.fi/x/runitor/cmd/runitor@latest 8 | -------------------------------------------------------------------------------- /playbooks/install_traefik.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for Traefik installation 2 | 3 | --- 4 | - hosts: thinky01 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for Traefik 9 | file: 10 | path: "{{ local_traefik_path }}" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Create directory for traefik certs 17 | file: 18 | path: "{{ local_traefik_path }}/config/certs" 19 | state: directory 20 | owner: "{{ ansible_user }}" 21 | group: "{{ ansible_user }}" 22 | mode: 0755 23 | 24 | - name: Upload traefik docker-compose 25 | template: 26 | src: "traefik/docker-compose.yml" 27 | dest: "{{ local_traefik_path }}/docker-compose.yml" 28 | owner: "{{ ansible_user }}" 29 | group: "{{ ansible_user }}" 30 | mode: 0600 31 | 32 | - name: Upload traefik config 33 | template: 34 | src: "traefik/traefik.yaml" 35 | dest: "{{ local_traefik_path }}/config/traefik.yaml" 36 | owner: "{{ ansible_user }}" 37 | group: "{{ ansible_user }}" 38 | mode: 0600 39 | 40 | - name: Create and start services 41 | community.docker.docker_compose: 42 | project_src: "{{ local_traefik_path }}" 43 | register: output 44 | 45 | 46 | -------------------------------------------------------------------------------- /playbooks/install_uptimekuma.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for uptime-kuma installation 2 | 3 | --- 4 | - hosts: homelab-prod 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Create directory for uptime-kuma 9 | file: 10 | path: "{{ local_apps_path }}/uptime-kuma" 11 | state: directory 12 | owner: "{{ ansible_user }}" 13 | group: "{{ ansible_user }}" 14 | mode: 0755 15 | 16 | - name: Create data directory for uptime-kuma 17 | file: 18 | path: "{{ local_apps_path }}/uptime-kuma/data" 19 | state: directory 20 | owner: "{{ ansible_user }}" 21 | group: "{{ ansible_user }}" 22 | mode: 0755 23 | 24 | - name: Upload uptime-kuma docker-compose.yml 25 | copy: 26 | src: ./uptime-kuma/docker-compose.yml 27 | dest: "{{ local_apps_path }}/uptime-kuma/docker-compose.yml" 28 | mode: 0644 29 | 30 | - name: Stop existing service 31 | command: docker compose -f {{ local_apps_path }}/uptime-kuma/docker-compose.yml down 32 | 33 | - name: Start service 34 | command: docker compose -f {{ local_apps_path }}/uptime-kuma/docker-compose.yml up -d 35 | -------------------------------------------------------------------------------- /playbooks/install_vaultwarden.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-prod 3 | tasks: 4 | - import_tasks: ../tasks/apt-upgrade.yml 5 | 6 | - name: Create directory for vaultwarden 7 | file: 8 | path: "{{ local_apps_path }}/vaultwarden" 9 | state: directory 10 | owner: "{{ ansible_user }}" 11 | group: "{{ ansible_user }}" 12 | mode: 0755 13 | 14 | - name: Copy necessafy files 15 | copy: 16 | src: '{{item}}' 17 | dest: "{{ local_apps_path }}/vaultwarden" 18 | owner: root 19 | group: root 20 | mode: 0644 21 | loop: 22 | - ./vaultwarden/docker-compose.yml 23 | 24 | - name: Stop existing services 25 | command: docker compose -f {{ local_apps_path }}/vaultwarden/docker-compose.yml up -d 26 | 27 | - name: Create and start services 28 | command: docker compose -f {{ local_apps_path }}/vaultwarden/docker-compose.yml up -d 29 | 30 | -------------------------------------------------------------------------------- /playbooks/install_zfs.yml: -------------------------------------------------------------------------------- 1 | # This script is responsible for ZFS installation 2 | 3 | --- 4 | - hosts: homelab-rocky 5 | tasks: 6 | - import_tasks: ../tasks/apt-upgrade.yml 7 | 8 | - name: Install Zfs 9 | apt: 10 | name: "{{ packages }}" 11 | state: present 12 | update_cache: yes 13 | vars: 14 | packages: 15 | - zfsutils-linux 16 | -------------------------------------------------------------------------------- /playbooks/jellyfin/docker-compose.yml: -------------------------------------------------------------------------------- 1 | networks: 2 | caddy_caddynet: 3 | external: true 4 | services: 5 | jelly: 6 | image: lscr.io/linuxserver/jellyfin:latest 7 | container_name: jelly 8 | environment: 9 | - PUID=1000 10 | - PGID=999 11 | - TZ=Etc/UTC 12 | # - JELLYFIN_PublishedServerUrl=192.168.0.5 #optional 13 | volumes: 14 | - /toshpool/apps/jelly/library:/config 15 | - /toshpool/apps/jelly/tvseries:/data/tvshows 16 | - /toshpool/apps/jelly/movies:/data/movies 17 | ports: 18 | - 8096:8096 19 | - 8920:8920 #optional 20 | - 7359:7359/udp #optional 21 | - 1900:1900/udp #optional 22 | restart: unless-stopped 23 | networks: 24 | - caddy_caddynet 25 | -------------------------------------------------------------------------------- /playbooks/lubelogger/.env: -------------------------------------------------------------------------------- 1 | LC_ALL=en_DE.UTF-8 2 | LANG=en_DE.UTF-8 3 | MailConfig__EmailServer="" 4 | MailConfig__EmailFrom="" 5 | MailConfig__UseSSL="false" 6 | MailConfig__Port=587 7 | MailConfig__Username="" 8 | MailConfig__Password="" 9 | LOGGING__LOGLEVEL__DEFAULT=Error 10 | 11 | # * Uncoment this line if you use postgresSQL as database backend. 12 | # * Check the docker-compose.postgresql.yml file 13 | #POSTGRES_CONNECTION="Host=postgres;Username=lubelogger;Password=lubepass;Database=lubelogger;" 14 | -------------------------------------------------------------------------------- /playbooks/lubelogger/docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: "3.4" 3 | 4 | services: 5 | app: 6 | image: ghcr.io/hargata/lubelogger:latest 7 | build: . 8 | restart: unless-stopped 9 | # volumes used to keep data persistent 10 | volumes: 11 | - config:/App/config 12 | - data:/App/data 13 | - translations:/App/wwwroot/translations 14 | - documents:/App/wwwroot/documents 15 | - images:/App/wwwroot/images 16 | - temp:/App/wwwroot/temp 17 | - log:/App/log 18 | - keys:/root/.aspnet/DataProtection-Keys 19 | # expose port and/or use serving via traefik 20 | ports: 21 | - 8060:8080 22 | env_file: 23 | - .env 24 | 25 | volumes: 26 | config: 27 | data: 28 | translations: 29 | documents: 30 | images: 31 | temp: 32 | log: 33 | keys: 34 | -------------------------------------------------------------------------------- /playbooks/mailrise/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | mailrise: 5 | image: yoryan/mailrise:latest 6 | container_name: mailrise 7 | ports: 8 | - '8025:8025' 9 | restart: unless-stopped 10 | volumes: 11 | - ./mailrise/mailrise.conf:/etc/mailrise.conf:ro 12 | -------------------------------------------------------------------------------- /playbooks/monitoring/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | prometheus: 4 | image: prom/prometheus 5 | ports: 6 | - 9090:9090 7 | volumes: 8 | - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro 9 | user: "0" 10 | grafana: 11 | image: grafana/grafana 12 | ports: 13 | - 3333:3000 14 | -------------------------------------------------------------------------------- /playbooks/monitoring/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | evaluation_interval: 15s 4 | 5 | scrape_configs: 6 | - job_name: 'custom_metrics' 7 | static_configs: 8 | - targets: ['10.0.0.227:9110'] 9 | metrics_path: '/metrics' 10 | scheme: 'http' 11 | scrape_timeout: 10s 12 | -------------------------------------------------------------------------------- /playbooks/n8n/.env: -------------------------------------------------------------------------------- 1 | POSTGRES_USER=someUser 2 | POSTGRES_PASSWORD=somePassword 3 | POSTGRES_DB=n8n 4 | 5 | POSTGRES_NON_ROOT_USER=someUser 6 | POSTGRES_NON_ROOT_PASSWORD=somePassword 7 | -------------------------------------------------------------------------------- /playbooks/n8n/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | volumes: 4 | db_storage: 5 | n8n_storage: 6 | 7 | services: 8 | postgres: 9 | image: postgres:16 10 | restart: always 11 | environment: 12 | - POSTGRES_USER 13 | - POSTGRES_PASSWORD 14 | - POSTGRES_DB 15 | - POSTGRES_NON_ROOT_USER 16 | - POSTGRES_NON_ROOT_PASSWORD 17 | volumes: 18 | - db_storage:/var/lib/postgresql/data 19 | - ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh 20 | healthcheck: 21 | test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}'] 22 | interval: 5s 23 | timeout: 5s 24 | retries: 10 25 | 26 | n8n: 27 | image: docker.n8n.io/n8nio/n8n 28 | restart: always 29 | environment: 30 | - DB_TYPE=postgresdb 31 | - DB_POSTGRESDB_HOST=postgres 32 | - DB_POSTGRESDB_PORT=5432 33 | - DB_POSTGRESDB_DATABASE=${POSTGRES_DB} 34 | - DB_POSTGRESDB_USER=${POSTGRES_NON_ROOT_USER} 35 | - DB_POSTGRESDB_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD} 36 | ports: 37 | - 5678:5678 38 | links: 39 | - postgres 40 | volumes: 41 | - n8n_storage:/home/node/.n8n 42 | networks: 43 | - caddy_caddynet 44 | - default 45 | depends_on: 46 | postgres: 47 | condition: service_healthy 48 | 49 | networks: 50 | caddy_caddynet: 51 | external: true 52 | -------------------------------------------------------------------------------- /playbooks/nextcloud/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | nextcloud-aio-mastercontainer: 3 | image: nextcloud/all-in-one:latest 4 | init: true 5 | restart: always 6 | container_name: nextcloud-aio-mastercontainer # This line is not allowed to be changed as otherwise AIO will not work correctly 7 | volumes: 8 | - nextcloud_aio_mastercontainer:/mnt/docker-aio-config # This line is not allowed to be changed as otherwise the built-in backup solution will not work 9 | - /var/run/docker.sock:/var/run/docker.sock:ro # May be changed on macOS, Windows or docker rootless. See the applicable documentation. If adjusting, don't forget to also set 'WATCHTOWER_DOCKER_SOCKET_PATH'! 10 | ports: 11 | # - 80:80 # Can be removed when running behind a web server or reverse proxy (like Apache, Nginx, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md 12 | - 8080:8080 13 | - 8443:8443 # Can be removed when running behind a web server or reverse proxy (like Apache, Nginx, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md 14 | # environment: # Is needed when using any of the options below 15 | # - AIO_DISABLE_BACKUP_SECTION=false # Setting this to true allows to hide the backup section in the AIO interface. See https://github.com/nextcloud/all-in-one#how-to-disable-the-backup-section 16 | # - APACHE_PORT=11000 # Is needed when running behind a web server or reverse proxy (like Apache, Nginx, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md 17 | # - APACHE_IP_BINDING=127.0.0.1 # Should be set when running behind a web server or reverse proxy (like Apache, Nginx, Cloudflare Tunnel and else) that is running on the same host. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md 18 | # - BORG_RETENTION_POLICY=--keep-within=7d --keep-weekly=4 --keep-monthly=6 # Allows to adjust borgs retention policy. See https://github.com/nextcloud/all-in-one#how-to-adjust-borgs-retention-policy 19 | # - COLLABORA_SECCOMP_DISABLED=false # Setting this to true allows to disable Collabora's Seccomp feature. See https://github.com/nextcloud/all-in-one#how-to-disable-collaboras-seccomp-feature 20 | # - NEXTCLOUD_DATADIR=/mnt/ncdata # Allows to set the host directory for Nextcloud's datadir. ⚠️⚠️⚠️ Warning: do not set or adjust this value after the initial Nextcloud installation is done! See https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir 21 | # - NEXTCLOUD_MOUNT=/mnt/ # Allows the Nextcloud container to access the chosen directory on the host. See https://github.com/nextcloud/all-in-one#how-to-allow-the-nextcloud-container-to-access-directories-on-the-host 22 | # - NEXTCLOUD_UPLOAD_LIMIT=10G # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-upload-limit-for-nextcloud 23 | # - NEXTCLOUD_MAX_TIME=3600 # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-max-execution-time-for-nextcloud 24 | # - NEXTCLOUD_MEMORY_LIMIT=512M # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-php-memory-limit-for-nextcloud 25 | # - NEXTCLOUD_TRUSTED_CACERTS_DIR=/path/to/my/cacerts # CA certificates in this directory will be trusted by the OS of the nexcloud container (Useful e.g. for LDAPS) See See https://github.com/nextcloud/all-in-one#how-to-trust-user-defined-certification-authorities-ca 26 | # - NEXTCLOUD_STARTUP_APPS=deck twofactor_totp tasks calendar contacts notes # Allows to modify the Nextcloud apps that are installed on starting AIO the first time. See https://github.com/nextcloud/all-in-one#how-to-change-the-nextcloud-apps-that-are-installed-on-the-first-startup 27 | # - NEXTCLOUD_ADDITIONAL_APKS=imagemagick # This allows to add additional packages to the Nextcloud container permanently. Default is imagemagick but can be overwritten by modifying this value. See https://github.com/nextcloud/all-in-one#how-to-add-os-packages-permanently-to-the-nextcloud-container 28 | # - NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS=imagick # This allows to add additional php extensions to the Nextcloud container permanently. Default is imagick but can be overwritten by modifying this value. See https://github.com/nextcloud/all-in-one#how-to-add-php-extensions-permanently-to-the-nextcloud-container 29 | # - NEXTCLOUD_ENABLE_DRI_DEVICE=true # This allows to enable the /dev/dri device in the Nextcloud container. ⚠️⚠️⚠️ Warning: this only works if the '/dev/dri' device is present on the host! If it should not exist on your host, don't set this to true as otherwise the Nextcloud container will fail to start! See https://github.com/nextcloud/all-in-one#how-to-enable-hardware-transcoding-for-nextcloud 30 | # - NEXTCLOUD_KEEP_DISABLED_APPS=false # Setting this to true will keep Nextcloud apps that are disabled in the AIO interface and not uninstall them if they should be installed. See https://github.com/nextcloud/all-in-one#how-to-keep-disabled-apps 31 | # - TALK_PORT=3478 # This allows to adjust the port that the talk container is using. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-talk-port 32 | # - WATCHTOWER_DOCKER_SOCKET_PATH=/var/run/docker.sock # Needs to be specified if the docker socket on the host is not located in the default '/var/run/docker.sock'. Otherwise mastercontainer updates will fail. For macos it needs to be '/var/run/docker.sock' 33 | # networks: # Is needed when you want to create the nextcloud-aio network with ipv6-support using this file, see the network config at the bottom of the file 34 | # - nextcloud-aio # Is needed when you want to create the nextcloud-aio network with ipv6-support using this file, see the network config at the bottom of the file 35 | # # Uncomment the following line when using SELinux 36 | # security_opt: ["label:disable"] 37 | 38 | # # Optional: Caddy reverse proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md 39 | # # You can find further examples here: https://github.com/nextcloud/all-in-one/discussions/588 40 | # caddy: 41 | # image: caddy:alpine 42 | # restart: always 43 | # container_name: caddy 44 | # volumes: 45 | # - ./Caddyfile:/etc/caddy/Caddyfile 46 | # - ./certs:/certs 47 | # - ./config:/config 48 | # - ./data:/data 49 | # - ./sites:/srv 50 | # network_mode: "host" 51 | 52 | volumes: # If you want to store the data on a different drive, see https://github.com/nextcloud/all-in-one#how-to-store-the-filesinstallation-on-a-separate-drive 53 | nextcloud_aio_mastercontainer: 54 | name: nextcloud_aio_mastercontainer # This line is not allowed to be changed as otherwise the built-in backup solution will not work 55 | 56 | # # Optional: If you need ipv6, follow step 1 and 2 of https://github.com/nextcloud/all-in-one/blob/main/docker-ipv6-support.md first and then uncomment the below config in order to activate ipv6 for the internal nextcloud-aio network. 57 | # # Please make sure to uncomment also the networking lines of the mastercontainer above in order to actually create the network with docker-compose 58 | # networks: 59 | # nextcloud-aio: 60 | # name: nextcloud-aio # This line is not allowed to be changed as otherwise the created network will not be used by the other containers of AIO 61 | # driver: bridge 62 | # enable_ipv6: true 63 | # ipam: 64 | # driver: default 65 | # config: 66 | # - subnet: fd12:3456:789a:2::/64 # IPv6 subnet to use 67 | -------------------------------------------------------------------------------- /playbooks/nginx/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.2' 2 | services: 3 | nginxproxymanager: 4 | image: 'jc21/nginx-proxy-manager:latest' 5 | container_name: nginxproxymanager 6 | restart: unless-stopped 7 | ports: 8 | # - '80:80' 9 | - '81:81' 10 | - '443:443' 11 | volumes: 12 | - /root/apps/nginx/data:/data 13 | - /root/apps/nginx/letsencrypt:/etc/letsencrypt 14 | -------------------------------------------------------------------------------- /playbooks/ntfy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | ntfy: 3 | image: binwiederhier/ntfy 4 | container_name: ntfy 5 | command: 6 | - serve 7 | environment: 8 | - NTFY_BASE_URL=https://ntfy.chibi.rodeo 9 | - NTFY_UPSTREAM_BASE_URL=https://ntfy.sh 10 | - TZ=CEST # optional: Change to your desired timezone 11 | # user: UID:GID # optional: Set custom user/group or uid/gid 12 | volumes: 13 | - /var/cache/ntfy:/var/cache/ntfy 14 | - /etc/ntfy:/etc/ntfy 15 | ports: 16 | - 65080:80 17 | restart: unless-stopped 18 | networks: 19 | caddy_caddynet: 20 | external: true 21 | -------------------------------------------------------------------------------- /playbooks/owncloud/compose.yml: -------------------------------------------------------------------------------- 1 | volumes: 2 | files: 3 | driver: local 4 | mysql: 5 | driver: local 6 | redis: 7 | driver: local 8 | 9 | services: 10 | owncloud: 11 | image: owncloud/server:10.15 12 | container_name: owncloud_server 13 | restart: always 14 | ports: 15 | - 65508:8080 16 | depends_on: 17 | - mariadb 18 | - redis 19 | environment: 20 | - OWNCLOUD_DOMAIN=10.0.0.202:65508 21 | - OWNCLOUD_TRUSTED_DOMAINS=10.0.0.202,owncloud.chibi.rodeo 22 | - OWNCLOUD_DB_TYPE=mysql 23 | - OWNCLOUD_DB_NAME=owncloud 24 | - OWNCLOUD_DB_USERNAME=owncloud 25 | - OWNCLOUD_DB_PASSWORD=owncloud 26 | - OWNCLOUD_DB_HOST=mariadb 27 | - OWNCLOUD_ADMIN_USERNAME=owncloud 28 | - OWNCLOUD_ADMIN_PASSWORD=owncloud 29 | - OWNCLOUD_MYSQL_UTF8MB4=true 30 | - OWNCLOUD_REDIS_ENABLED=true 31 | - OWNCLOUD_REDIS_HOST=redis 32 | healthcheck: 33 | test: ["CMD", "/usr/bin/healthcheck"] 34 | interval: 30s 35 | timeout: 10s 36 | retries: 5 37 | volumes: 38 | - /storage/apps/owntracks/files:/mnt/data 39 | networks: 40 | - caddy_caddynet 41 | - default 42 | 43 | mariadb: 44 | image: mariadb:10.11 # minimum required ownCloud version is 10.9 45 | container_name: owncloud_mariadb 46 | restart: always 47 | environment: 48 | - MYSQL_ROOT_PASSWORD=owncloud 49 | - MYSQL_USER=owncloud 50 | - MYSQL_PASSWORD=owncloud 51 | - MYSQL_DATABASE=owncloud 52 | - MARIADB_AUTO_UPGRADE=1 53 | command: ["--max-allowed-packet=128M", "--innodb-log-file-size=64M"] 54 | healthcheck: 55 | test: ["CMD", "mysqladmin", "ping", "-u", "root", "--password=owncloud"] 56 | interval: 10s 57 | timeout: 5s 58 | retries: 5 59 | volumes: 60 | - mysql:/var/lib/mysql 61 | networks: 62 | - default 63 | 64 | redis: 65 | image: redis:6 66 | container_name: owncloud_redis 67 | restart: always 68 | command: ["--databases", "1"] 69 | healthcheck: 70 | test: ["CMD", "redis-cli", "ping"] 71 | interval: 10s 72 | timeout: 5s 73 | retries: 5 74 | volumes: 75 | - redis:/data 76 | networks: 77 | - default 78 | 79 | networks: 80 | caddy_caddynet: 81 | external: true 82 | -------------------------------------------------------------------------------- /playbooks/owntracks/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | owntracks-recorder: 3 | container_name: owntracks-recorder 4 | image: owntracks/recorder 5 | # command: "--port 0" # Seems to be needed to disable MQTT # Old method, do not use. 6 | environment: 7 | - OTR_PORT=0 # 0 disables MQTT 8 | volumes: 9 | - /etc/localtime:/etc/localtime:ro 10 | - ./volumes/owntracks-recorder/config:/config 11 | - ./volumes/owntracks-recorder/store:/store 12 | ports: 13 | - 8083:8083 14 | restart: unless-stopped 15 | owntracks-frontend: 16 | image: owntracks/frontend 17 | ports: 18 | - 8085:80 19 | environment: 20 | - SERVER_HOST=192.168.178.200 21 | - SERVER_PORT=8083 22 | restart: unless-stopped 23 | 24 | mosquitto: 25 | image: eclipse-mosquitto 26 | environment: 27 | - OTR_HOST=0.0.0.0 28 | ports: 29 | - 1883:1883 30 | - 8883:8883 31 | volumes: 32 | - mosquitto-data:/mosquitto/data 33 | - mosquitto-logs:/mosquitto/logs 34 | - mosquitto-conf:/mosquitto/config 35 | restart: unless-stopped 36 | 37 | 38 | volumes: 39 | store: 40 | config: 41 | mosquitto-data: 42 | mosquitto-logs: 43 | mosquitto-conf: 44 | -------------------------------------------------------------------------------- /playbooks/paperlessngx.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-prod 3 | vars: 4 | local_backup_path: /home/{{ ansible_user }}/backups/paperlessngx/export 5 | 6 | tasks: 7 | - import_tasks: ../tasks/apt-upgrade.yml 8 | - import_tasks: ../tasks/install_rclone.yml 9 | 10 | - name: Create directory if they don't exist 11 | file: 12 | path: "{{ item }}" 13 | state: directory 14 | owner: root 15 | group: root 16 | mode: 0775 17 | loop: 18 | - "{{ local_apps_path }}/paperlessngx/export" 19 | - "{{ local_pool_path }}/tasks/paperlessngx/" 20 | - "{{ local_backups_path }}/paperlessngx" 21 | 22 | - name: Copy necessafy files 23 | copy: 24 | src: '{{item}}' 25 | dest: "{{ local_apps_path }}/paperlessngx" 26 | owner: root 27 | group: root 28 | mode: 0644 29 | loop: 30 | - ./paperlessngx/docker-compose.yml 31 | 32 | - name: Upload paperlessngx backup script 33 | template: 34 | src: "./paperlessngx/backup.sh" 35 | dest: "{{ local_pool_path }}/tasks/paperlessngx/backup.sh" 36 | owner: "{{ ansible_user }}" 37 | group: "{{ ansible_user }}" 38 | mode: 0700 39 | 40 | - name: Stop existing services 41 | command: docker compose -f {{ local_apps_path }}/paperlessngx/docker-compose.yml up -d 42 | 43 | - name: Create and start services 44 | command: docker compose -f {{ local_apps_path }}/paperlessngx/docker-compose.yml up -d 45 | 46 | - name: Schedule paperlessngx backup to be done monthly 47 | cron: 48 | name: "Dump paperlessngx to a local file" 49 | minute: "45" 50 | hour: "5" 51 | day: "1" 52 | job: "{{ local_pool_path }}/tasks/paperlessngx/backup.sh" 53 | state: present 54 | -------------------------------------------------------------------------------- /playbooks/paperlessngx/backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Dump the files 4 | docker ps --format "{% raw %}{{.Names}}{% endraw %}" | grep paperlessngx-webserver | xargs -I {} docker exec {} document_exporter ../export 5 | 6 | # Sync the backup to Backblaze 7 | /usr/bin/rclone sync {{ local_apps_path }}/paperlessngx {{ homelab_backup_backblaze_remote_name }}:{{ homelab_backup_backblaze_bucket_name }}/paperlessngx --config /home/{{ ansible_user }}/.config/rclone/rclone.conf -P 8 | 9 | curl -X GET {{ hc_ping_url }}/{{ hc_paperless_backup_uuid }} 10 | -------------------------------------------------------------------------------- /playbooks/paperlessngx/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # Docker Compose file for running paperless from the Docker Hub. 2 | # This file contains everything paperless needs to run. 3 | # Paperless supports amd64, arm and arm64 hardware. 4 | # 5 | # All compose files of paperless configure paperless in the following way: 6 | # 7 | # - Paperless is (re)started on system boot, if it was running before shutdown. 8 | # - Docker volumes for storing data are managed by Docker. 9 | # - Folders for importing and exporting files are created in the same directory 10 | # as this file and mounted to the correct folders inside the container. 11 | # - Paperless listens on port 8010. 12 | # 13 | # In addition to that, this Docker Compose file adds the following optional 14 | # configurations: 15 | # 16 | # - Instead of SQLite (default), PostgreSQL is used as the database server. 17 | # 18 | # To install and update paperless with this file, do the following: 19 | # 20 | # - Open portainer Stacks list and click 'Add stack' 21 | # - Paste the contents of this file and assign a name, e.g. 'paperless' 22 | # - Click 'Deploy the stack' and wait for it to be deployed 23 | # - Open the list of containers, select paperless_webserver_1 24 | # - Click 'Console' and then 'Connect' to open the command line inside the container 25 | # - Run 'python3 manage.py createsuperuser' to create a user 26 | # - Exit the console 27 | # 28 | # For more extensive installation and update instructions, refer to the 29 | # documentation. 30 | 31 | version: "3.4" 32 | services: 33 | broker: 34 | image: docker.io/library/redis:7 35 | restart: unless-stopped 36 | volumes: 37 | - redisdata:/data 38 | 39 | db: 40 | image: docker.io/library/postgres:15 41 | restart: unless-stopped 42 | volumes: 43 | - pgdata:/var/lib/postgresql/data 44 | environment: 45 | POSTGRES_DB: paperless 46 | POSTGRES_USER: paperless 47 | POSTGRES_PASSWORD: paperless 48 | 49 | webserver: 50 | image: ghcr.io/paperless-ngx/paperless-ngx:latest 51 | restart: unless-stopped 52 | depends_on: 53 | - db 54 | - broker 55 | ports: 56 | - "8010:8000" 57 | volumes: 58 | - data:/usr/src/paperless/data 59 | - media:/usr/src/paperless/media 60 | - ./export:/usr/src/paperless/export 61 | - ./consume:/usr/src/paperless/consume 62 | environment: 63 | PAPERLESS_REDIS: redis://broker:6379 64 | PAPERLESS_DBHOST: db 65 | PAPERLESS_OCR_USER_ARGS: '{"invalidate_digital_signatures": true}' 66 | # The UID and GID of the user used to run paperless in the container. Set this 67 | # to your UID and GID on the host so that you have write access to the 68 | # consumption directory. 69 | USERMAP_UID: 1000 70 | USERMAP_GID: 999 71 | # Additional languages to install for text recognition, separated by a 72 | # whitespace. Note that this is 73 | # different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines the 74 | # language used for OCR. 75 | # The container installs English, German, Italian, Spanish and French by 76 | # default. 77 | # See https://packages.debian.org/search?keywords=tesseract-ocr-&searchon=names&suite=buster 78 | # for available languages. 79 | #PAPERLESS_OCR_LANGUAGES: tur ces 80 | # Adjust this key if you plan to make paperless available publicly. It should 81 | # be a very long sequence of random characters. You don't need to remember it. 82 | #PAPERLESS_SECRET_KEY: change-me 83 | # Use this variable to set a timezone for the Paperless Docker containers. If not specified, defaults to UTC. 84 | #PAPERLESS_TIME_ZONE: America/Los_Angeles 85 | # The default language to use for OCR. Set this to the language most of your 86 | # documents are written in. 87 | #PAPERLESS_OCR_LANGUAGE: eng 88 | 89 | volumes: 90 | data: 91 | media: 92 | pgdata: 93 | redisdata: 94 | -------------------------------------------------------------------------------- /playbooks/photon/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre 2 | 3 | # Install pbzip2 for parallel extraction 4 | RUN apt-get update \ 5 | && apt-get -y install \ 6 | pbzip2 \ 7 | wget \ 8 | && rm -rf /var/lib/apt/lists/* 9 | 10 | WORKDIR /photon 11 | ADD https://github.com/komoot/photon/releases/download/0.4.2/photon-0.4.2.jar /photon/photon.jar 12 | COPY entrypoint.sh ./entrypoint.sh 13 | 14 | VOLUME /photon/photon_data 15 | EXPOSE 2322 16 | 17 | ENTRYPOINT /photon/entrypoint.sh 18 | -------------------------------------------------------------------------------- /playbooks/photon/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | photon: 3 | build: 4 | context: . 5 | dockerfile: Dockerfile 6 | image: tonsnoei/photon-geocoder:latest 7 | volumes: 8 | - ./data:/photon/photon_data 9 | ports: 10 | - 2322:2322 11 | networks: 12 | - caddy_caddynet 13 | - default 14 | 15 | volumes: 16 | data: 17 | driver: local 18 | 19 | networks: 20 | caddy_caddynet: 21 | external: true 22 | -------------------------------------------------------------------------------- /playbooks/photon/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | # Download elasticsearch index 5 | if [ ! -d "/photon/photon_data/elasticsearch" ]; then 6 | echo "Downloading search index" 7 | 8 | # Let graphhopper know where the traffic is coming from 9 | USER_AGENT="docker: tonsnoei/photon-geocoder" 10 | # If you want to install a specific region only, enable the line below and disable the current 'wget' row. 11 | # Take a look at http://download1.graphhopper.com/public/extracts/by-country-code for your country 12 | # wget --user-agent="$USER_AGENT" -O - http://download1.graphhopper.com/public/extracts/by-country-code/de/photon-db-de-latest.tar.bz2 | bzip2 -cd | tar x 13 | wget --user-agent="$USER_AGENT" -O - http://download1.graphhopper.com/public/photon-db-latest.tar.bz2 | bzip2 -cd | tar x 14 | fi 15 | 16 | # Start photon if elastic index exists 17 | if [ -d "/photon/photon_data/elasticsearch" ]; then 18 | echo "Start photon" 19 | java -jar photon.jar $@ 20 | else 21 | echo "Could not start photon, the search index could not be found" 22 | fi 23 | -------------------------------------------------------------------------------- /playbooks/pihole/docker-compose.yml: -------------------------------------------------------------------------------- 1 | networks: 2 | caddy_caddynet: 3 | external: true 4 | 5 | # More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/ 6 | services: 7 | pihole: 8 | container_name: pihole 9 | image: pihole/pihole:latest 10 | # For DHCP it is recommended to remove these ports and instead add: network_mode: "host" 11 | ports: 12 | - "53:53/tcp" 13 | - "53:53/udp" 14 | - "67:67/udp" # Only required if you are using Pi-hole as your DHCP server 15 | - "8014:80/tcp" 16 | cap_add: 17 | - NET_ADMIN 18 | environment: 19 | TZ: 'Europe/Berlin' 20 | WEBPASSWORD: '100500' 21 | DNSMASQ_USER: root 22 | # Volumes store your data between container upgrades 23 | volumes: 24 | - './etc-pihole:/etc/pihole' 25 | - './etc-dnsmasq.d:/etc/dnsmasq.d' 26 | # https://github.com/pi-hole/docker-pi-hole#note-on-capabilities 27 | # cap_add: 28 | # - NET_ADMIN # Required if you are using Pi-hole as your DHCP server, else not needed 29 | restart: unless-stopped 30 | networks: 31 | - caddy_caddynet 32 | 33 | -------------------------------------------------------------------------------- /playbooks/registry/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | networks: 4 | caddy_caddynet: 5 | external: true 6 | 7 | services: 8 | registry: 9 | image: registry:latest 10 | ports: 11 | - "5000:5000" 12 | environment: 13 | REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data 14 | volumes: 15 | - ./data:/data 16 | networks: 17 | - caddy_caddynet 18 | -------------------------------------------------------------------------------- /playbooks/rename_host.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-prod 3 | tasks: 4 | - import_tasks: ../tasks/rename_host.yml 5 | vars: 6 | hostname: "homelab-production" 7 | -------------------------------------------------------------------------------- /playbooks/sampler/sampler.yml: -------------------------------------------------------------------------------- 1 | sparklines: 2 | - title: Thinky CPU usage 3 | rate-ms: 1000 4 | scale: 0 5 | sample: ps -A -o %cpu | awk '{s+=$1} END {print s}' 6 | - title: Thinky free memory pages 7 | rate-ms: 1000 8 | scale: 0 9 | sample: memory_pressure | grep 'Pages free' | awk '{print $3}' 10 | - title: NAS CPU usage 11 | rate-ms: 1000 12 | scale: 0 13 | sample: ssh frey@192.168.0.20 ps -A -o %cpu | awk '{s+=$1} END {print s}' 14 | - title: NAS free memory pages 15 | rate-ms: 1000 16 | scale: 0 17 | sample: ssh frey@192.168.0.20 memory_pressure | grep 'Pages free' | awk '{print $3}' 18 | 19 | textboxes: 20 | - title: Docker containers stats 21 | rate-ms: 500 22 | sample: docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.PIDs}}" 23 | -------------------------------------------------------------------------------- /playbooks/setup_dokku_backups.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: dokku 3 | tasks: 4 | - name: auth postgres-backup on aws s3 5 | shell: dokku postgres:backup-auth {{app_name}}_db {{aws_access_key_id}} {{aws_secret_access_key}} 6 | ignore_errors: true 7 | # unless backups already authed and setup 8 | 9 | - name: schedule daily postgres backups 10 | shell: dokku postgres:backup-schedule {{app_name}}_db "0 3 * * *" {{bucket_name}} 11 | ignore_errors: true 12 | 13 | - name: show backup crontab for {{app_name}}_db 14 | shell: dokku postgres:backup-schedule-cat {{app_name}}_db 15 | register: backup_schedule 16 | 17 | - name: show backup crontab for {{app_name}}_db 18 | debug: 19 | msg: "{{backup_schedule.stdout}}" 20 | 21 | 22 | -------------------------------------------------------------------------------- /playbooks/traefik/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | networks: 4 | frontend: 5 | external: true 6 | 7 | services: 8 | traefik: 9 | image: traefik:3.0 10 | container_name: traefik 11 | restart: always 12 | command: 13 | - --providers.docker 14 | - --providers.docker.exposedbydefault=false 15 | - --entrypoints.web.address=:80 16 | - --api.insecure 17 | - --api.dashboard 18 | environment: 19 | - CF_DNS_API_TOKEN={{ cloudflare_api_token }} 20 | ports: 21 | - 80:80 22 | - 443:443 23 | - 8080:8080 24 | volumes: 25 | - ./config:/etc/traefik 26 | - /var/run/docker.sock:/var/run/docker.sock:ro 27 | networks: 28 | - frontend 29 | -------------------------------------------------------------------------------- /playbooks/traefik/traefik.yaml: -------------------------------------------------------------------------------- 1 | global: 2 | checkNewVersion: false 3 | sendAnonymousUsage: false 4 | 5 | # -- (Optional) Change Log Level and Format here... 6 | # - loglevels [DEBUG, INFO, WARNING, ERROR, CRITICAL] 7 | # - format [common, json, logfmt] 8 | # log: 9 | # level: ERROR 10 | # format: common 11 | # filePath: /var/log/traefik/traefik.log 12 | 13 | # -- (Optional) Enable Accesslog and change Format here... 14 | # - format [common, json, logfmt] 15 | # accesslog: 16 | # format: common 17 | # filePath: /var/log/traefik/access.log 18 | 19 | # -- (Optional) Enable API and Dashboard here, don't do in production 20 | # api: 21 | # dashboard: true 22 | # insecure: true 23 | 24 | # -- Change EntryPoints here... 25 | entryPoints: 26 | web: 27 | address: :80 28 | # -- (Optional) Redirect all HTTP to HTTPS 29 | # http: 30 | # redirections: 31 | # entryPoint: 32 | # to: websecure 33 | # scheme: https 34 | websecure: 35 | address: :443 36 | # -- (Optional) Add custom Entrypoint 37 | custom: 38 | address: :8080 39 | 40 | # -- Configure your CertificateResolver here... 41 | certificatesResolvers: 42 | # staging: 43 | # acme: 44 | # email: your-email@example.com 45 | # storage: /etc/traefik/certs/acme.json 46 | # caServer: "https://acme-staging-v02.api.letsencrypt.org/directory" 47 | # -- (Optional) Remove this section, when using DNS Challenge 48 | # httpChallenge: 49 | # entryPoint: web 50 | # -- (Optional) Configure DNS Challenge 51 | # dnsChallenge: 52 | # provider: your-resolver (e.g. cloudflare) 53 | # resolvers: 54 | # - "1.1.1.1:53" 55 | # - "8.8.8.8:53" 56 | production: 57 | acme: 58 | email: iamfrey@gmail.com 59 | storage: /etc/traefik/certs/acme.json 60 | caServer: "https://acme-v02.api.letsencrypt.org/directory" 61 | # -- (Optional) Remove this section, when using DNS Challenge 62 | dnsChallenge: 63 | provider: cloudflare 64 | resolvers: 65 | - "1.1.1.1:53" 66 | - "8.8.8.8:53" 67 | 68 | # -- (Optional) Disable TLS Cert verification check 69 | serversTransport: 70 | insecureSkipVerify: true 71 | 72 | # -- (Optional) Overwrite Default Certificates 73 | # tls: 74 | # stores: 75 | # default: 76 | # defaultCertificate: 77 | # certFile: /etc/traefik/certs/cert.pem 78 | # keyFile: /etc/traefik/certs/cert-key.pem 79 | # -- (Optional) Disable TLS version 1.0 and 1.1 80 | # options: 81 | # default: 82 | # minVersion: VersionTLS12 83 | 84 | providers: 85 | docker: 86 | # -- (Optional) Enable this, if you want to expose all containers automatically 87 | exposedByDefault: false 88 | file: 89 | directory: /etc/traefik 90 | watch: true 91 | -------------------------------------------------------------------------------- /playbooks/update_caddyfile.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-prod 3 | tasks: 4 | - name: Copy necessafy files 5 | copy: 6 | src: '{{item}}' 7 | dest: "{{ local_apps_path }}/caddy" 8 | owner: root 9 | group: root 10 | mode: 0644 11 | loop: 12 | - ./caddy/Caddyfile 13 | 14 | - name: Replace CLOUDFLARE_API_TOKEN in Caddyfile 15 | replace: 16 | path: "{{ local_apps_path }}/caddy/Caddyfile" 17 | regexp: 'dns cloudflare 123' 18 | replace: " dns cloudflare {{ cf_api_token }}" 19 | 20 | - name: Restart existing services 21 | command: docker compose -f {{ local_apps_path }}/caddy/docker-compose.yml restart 22 | -------------------------------------------------------------------------------- /playbooks/update_immich.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-rocky 3 | tasks: 4 | - name: Copy necessafy files 5 | copy: 6 | src: '{{item}}' 7 | dest: "{{ local_apps_path }}/immich" 8 | owner: root 9 | group: root 10 | mode: 0644 11 | loop: 12 | - ./immich/docker-compose.yml 13 | 14 | - name: Pull latest images 15 | command: docker compose -f {{ local_apps_path }}/immich/docker-compose.yml pull 16 | 17 | - name: Stop existing services 18 | command: docker compose -f {{ local_apps_path }}/immich/docker-compose.yml stop 19 | 20 | - name: Create and start services 21 | command: docker compose -f {{ local_apps_path }}/immich/docker-compose.yml up -d 22 | -------------------------------------------------------------------------------- /playbooks/uptime-kuma/docker-compose.yml: -------------------------------------------------------------------------------- 1 | networks: 2 | caddy_caddynet: 3 | external: true 4 | 5 | services: 6 | uptime-kuma: 7 | image: louislam/uptime-kuma:1 8 | container_name: uptime-kuma 9 | volumes: 10 | - ./data:/app/data 11 | ports: 12 | - 3101:3001 13 | restart: always 14 | networks: 15 | - caddy_caddynet 16 | -------------------------------------------------------------------------------- /playbooks/vaultwarden/docker-compose.yml: -------------------------------------------------------------------------------- 1 | name: vaultwarden 2 | services: 3 | server: 4 | container_name: vaultwarden 5 | volumes: 6 | - ./vw-data/:/data/ 7 | restart: unless-stopped 8 | ports: 9 | - 8088:80 10 | image: vaultwarden/server:latest 11 | -------------------------------------------------------------------------------- /playbooks/whoami/docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # -- (Optional) When using Traefik, use this section 3 | networks: 4 | frontend: 5 | external: true 6 | services: 7 | whoami: 8 | image: containous/whoami 9 | container_name: whoami 10 | depends_on: 11 | - traefik 12 | # -- (Optional) Traefik example configuration 13 | labels: 14 | - "traefik.enable=true" 15 | - "traefik.http.services.whoami.loadbalancer.server.port=80" 16 | - "traefik.http.services.whoami.loadbalancer.server.scheme=https" 17 | - "traefik.http.routers.whoami-http.entrypoints=web" 18 | - "traefik.http.routers.whoami-http.rule=HostRegexp(`your-server-url`, `{subhost:[a-z]+}.your-server-url`)" 19 | - "traefik.http.routers.whoami-https.entrypoints=websecure" 20 | - "traefik.http.routers.whoami-https.rule=HostRegexp(`your-server-url`, `{subhost:[a-z]+}.your-server-url`)" 21 | - "traefik.http.routers.whoami-https.tls=true" 22 | - "traefik.http.routers.whoami-https.tls.certresolver=production" 23 | - "traefik.http.routers.whoami-https.tls.domains[0].main=your-server-url" 24 | - "traefik.http.routers.whoami-https.tls.domains[0].sans=*.your-server-url" 25 | networks: 26 | - frontend 27 | restart: unless-stopped 28 | -------------------------------------------------------------------------------- /rename.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: homelab-prod 3 | tasks: 4 | - name: "Configure hostname" 5 | ansible.builtin.hostname: 6 | name: "SERVER" 7 | become: true 8 | -------------------------------------------------------------------------------- /samba.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Samba on Ubuntu Server 3 | hosts: nas 4 | become: true 5 | 6 | tasks: 7 | - name: Update apt cache 8 | apt: 9 | update_cache: yes 10 | 11 | - name: Install Samba 12 | apt: 13 | name: samba 14 | state: present 15 | 16 | - name: Upload smb.conf.j2 17 | copy: 18 | src: smb.conf.j2 19 | dest: /smb.conf.j2 20 | 21 | - name: Configure Samba 22 | template: 23 | src: /smb.conf.j2 24 | dest: /etc/samba/smb.conf 25 | notify: restart samba 26 | 27 | handlers: 28 | - name: restart samba 29 | service: 30 | name: smbd 31 | state: restarted 32 | -------------------------------------------------------------------------------- /tasks/apt-upgrade.yml: -------------------------------------------------------------------------------- 1 | - name: Update and upgrade apt packages 2 | become: true 3 | apt: 4 | upgrade: yes 5 | update_cache: yes 6 | cache_valid_time: 86400 # One day 7 | -------------------------------------------------------------------------------- /tasks/install_rclone.yml: -------------------------------------------------------------------------------- 1 | - name: Install rclone 2 | apt: 3 | name: "{{ packages }}" 4 | state: present 5 | update_cache: yes 6 | vars: 7 | packages: 8 | - rclone 9 | 10 | - name: Ensure rclone config directory exists 11 | ansible.builtin.file: 12 | path: "/home/{{ ansible_user }}/.config/rclone" 13 | state: directory 14 | owner: "{{ ansible_user }}" 15 | group: "{{ ansible_user }}" 16 | mode: '0700' 17 | 18 | - name: Upload rclone B2 config 19 | ansible.builtin.template: 20 | src: "./immich/rclone.conf" 21 | dest: "/home/{{ ansible_user }}/.config/rclone/rclone.conf" 22 | owner: "{{ ansible_user }}" 23 | group: "{{ ansible_user }}" 24 | mode: '0600' 25 | 26 | -------------------------------------------------------------------------------- /tasks/rename_host.yml: -------------------------------------------------------------------------------- 1 | - name: "Configure hostname" 2 | ansible.builtin.hostname: 3 | name: "{{ hostname }}" 4 | become: true 5 | --------------------------------------------------------------------------------