From 40c0d09945fdf21601b5b62af9d16b0c254a92b6 Mon Sep 17 00:00:00 2001 From: Kumar Damani Date: Wed, 4 Jan 2023 15:13:48 -0500 Subject: draft: alpine stuff --- README.md | 111 ++++++++++++++----------- architecture.xml | 1 - group_vars/all/vars.yaml | 24 +++++- group_vars/all/vault | 60 +++++++------ group_vars/all/vault.example | 5 ++ pix/architecture.png | Bin 0 -> 74525 bytes pix/architecture.xml | 1 + pix/board.png | Bin 0 -> 391836 bytes pix/case.png | Bin 0 -> 25664 bytes pix/pcie_sata.png | Bin 0 -> 35151 bytes pix/psu.png | Bin 0 -> 32136 bytes pix/sata_power.png | Bin 0 -> 46595 bytes pix/wd.png | Bin 0 -> 48808 bytes playbooks/deploy.yaml | 65 ++++++++++++--- roles/adguard/defaults/main.yaml | 4 + roles/adguard/handlers/main.yaml | 2 + roles/adguard/tasks/main.yaml | 38 +++++++++ roles/base/defaults/main.yaml | 2 + roles/base/handlers/main.yaml | 2 + roles/base/tasks/base_alpine.yaml | 1 + roles/base/tasks/base_debian.yaml | 62 ++++++++++++++ roles/base/tasks/main.yaml | 9 ++ roles/ddclient/tasks/main.yaml | 9 +- roles/media_downloader/tasks/main.yaml | 16 ++-- roles/monitoring/files/zfs-exporter.service | 13 +++ roles/monitoring/tasks/node.yaml | 15 ++++ roles/monitoring/tasks/zfs.yaml | 31 +++++-- roles/nextcloud/defaults/main.yaml | 4 +- roles/nextcloud/tasks/main.yaml | 2 +- roles/nginx_docker/templates/app.nginx.conf.j2 | 8 +- roles/photoprism/defaults/main.yaml | 4 + roles/photoprism/handlers/main.yaml | 2 + roles/photoprism/tasks/main.yaml | 52 ++++++++++++ roles/plex/defaults/main.yaml | 4 + roles/plex/handlers/main.yaml | 2 + roles/plex/tasks/main.yaml | 22 +++++ roles/transmission/tasks/main.yaml | 4 +- roles/website/tasks/main.yaml | 17 +++- roles/wireguard/tasks/main.yaml | 1 + 39 files changed, 481 insertions(+), 112 deletions(-) delete mode 100644 architecture.xml create mode 100644 pix/architecture.png create mode 100644 pix/architecture.xml create mode 100644 pix/board.png create mode 100644 pix/case.png create mode 100644 pix/pcie_sata.png create mode 100644 pix/psu.png create mode 100644 pix/sata_power.png create mode 100644 pix/wd.png create mode 100644 roles/adguard/defaults/main.yaml create mode 100644 roles/adguard/handlers/main.yaml create mode 100644 roles/adguard/tasks/main.yaml create mode 100644 roles/base/defaults/main.yaml create mode 100644 roles/base/handlers/main.yaml create mode 100644 roles/base/tasks/base_alpine.yaml create mode 100644 roles/base/tasks/base_debian.yaml create mode 100644 roles/base/tasks/main.yaml create mode 100644 roles/monitoring/files/zfs-exporter.service create mode 100644 roles/photoprism/defaults/main.yaml create mode 100644 roles/photoprism/handlers/main.yaml create mode 100644 roles/photoprism/tasks/main.yaml create mode 100644 roles/plex/defaults/main.yaml create mode 100644 roles/plex/handlers/main.yaml create mode 100644 roles/plex/tasks/main.yaml diff --git a/README.md b/README.md index 718cbf6..1d7c194 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,14 @@ My requirements are as follows: | | Email | n/a | | :heavy_check_mark: | Syncing/Sharing files, calender, contacts, tasks etc. | [Nextcloud](https://nextcloud.com/) | | :heavy_check_mark: | Hosting misc. static websites | [Nginx](https://www.nginx.com/) | -| :heavy_check_mark: | Media (pictures, tv, movies) Server | [Jellyfin](https://jellyfin.org/) | +| :heavy_check_mark: | Media (pictures, tv, movies) Server | [Plex](https://plex.tv) or [Jellyfin](https://jellyfin.org/) | | :heavy_check_mark: | Meta Search Engine | [Searxng](https://docs.searxng.org/) | | :heavy_check_mark: | Music Server | [Navidrome](https://www.navidrome.org/) | | :heavy_check_mark: | Network accessible storage for media | [Samba](https://www.samba.org/) | | :heavy_check_mark: | Password Hosting/Share | [Bitwarden](https://bitwarden.com/) | | :heavy_check_mark: | VPN | [Wireguard](https://www.wireguard.com/) | | :heavy_check_mark: | Torrents | [Transmission](https://transmissionbt.com/) | +| :heavy_check_mark: | Photo sharing | [Photoprism](https://photoprism.app) | | :heavy_check_mark: | Media downloader | [Sonarr](https://github.com/Sonarr/Sonarr), [Radarr](https://github.com/Radarr/Radarr), [Prowlarr](https://github.com/Prowlarr/Prowlarr) | > Consider items marked as :heavy_check_mark: above to be implemented in this repo. @@ -32,7 +33,7 @@ I don't want it to have much of an impact on my utility (power) bill, which of c so much heat that it requires advanced cooling. ## Architecture -![Architecture](./architecture.png) +![Architecture](./pix/architecture.png) Notice that this setup requires a very small VPS since we are just running a wireguard client on it. All storage, and compute is being done by the Home Server. This means that my cost went from ~ $13/mo to ~ $1/mo for the VPS service, *while* increasing my SSD storage capacity from 50GB to 2TB (or whatever you have lying around)! And this does not incude the cost savings from self-hosting many of these services in the first place. @@ -46,71 +47,87 @@ There are many cheap VPS providers out there. I use Racknerd now. I have used Vu ## Pre-requisites ### Equipment -1. Raspberry Pi 4B (4GB). -2. USB Hub with **with its own power source**. -3. 2 X TiB external usb SSDs or HDDs for our network-attached-storage (NAS). -4. (optional, but recommended) 1 external usb SSD or HDD as a backup drive. -5. A very cheap VPS - I use Racknerd. +> The equipment I use reflect my current priorities and have changed since this project started and will +continue to change in the future. + +A [ROCKPro64](https://wiki.pine64.org/wiki/ROCKPro64) 4G model. +Alternatively, an RPi4 or similar would also work if you can get your hands on it. +![ROCKPro64](./pix/board.png) + +There are many reasons why this board is awesome: +1. In Stock. +2. Similar price/performance/energy usage as the RPi4. +3. PCIe slot!! + +My main reason for switching to this board is the final point above :) + +Speaking of the PCIe slot, we can get a PCIe SATA adapter to connect to two SATA drives. +![Dual SATA Adapter](./pix/pcie_sata.png) + +To power the drives, Pine64 all sells power cables: +![SATA power cables](./pix/sata_power.png) + +The drives themselves are 4 TiB 3.5in 5400 RPM CMR such as: +![Drive 1](./pix/wd.png) + +> 7200 RPM drives are more expensive and I won't be pushing this hard enough to notice the benefits. +> Note there will be cheaper drives using SMR, but I'd recommend CMR is worth the extra cost. + +Remember to buy drives that are not made as part of the same batch, so that the probabity of them +dying together is the lowest. You can also do this by buying different brands. + +Also remember to buy an extra set so that you save yourself some panic during recovery. + +When using the dual SATA adapter, Pine64 recommends a beefier 12V, 3A power-supply: +![PSU](./pix/psu.png) + +Since this is basically a NAS build, I opted to house all of this in: +![NAS Case](./pix/case.png) +Which comes included with a fan, and the SATA power-cables. + +Optional, but recommended: an external usb SSD or HDD as a backup drive. + +An finally, a very cheap VPS (Virtual Private Server) - I use Racknerd. +This will give you access to a reliable static IP. ### Base Image setup -For numerous reasons, I have switched to using Alpine Linux `aarch64` as the base OS image. -Going forward this repo will primarily be geared towards it. -That being said, all existing roles will continue to work on Raspi OS (debian) based images as well. - -1. Follow instructions from [Alpine wiki](https://wiki.alpinelinux.org/wiki/Raspberry_Pi) to create a bootable SD card. -2. During the `setup-alpine` process, select the **sys** mode for a persistent install. -3. Reboot -4. -```bash -# TODO: Make these tasks part of an Ansible role. -echo "dtoverlay=gpio-fan,gpiopin=14,temp=70000" > /boot/usercfg.txt - -# enable community packages in /etc/apk/repositories -# enable http://dl-cdn.alpinelinux.org/alpine/edge/testing -apk update -apk upgrade -apk add vim nnn htop bmon rsync py3-pip -apk add wireguard-tools docker docker-compose certbot -modprobe wireguard -# add wireguard to /etc/modules # - -# docker stuff -addgroup username docker -rc-update add docker boot -service docker start -``` -5. Continue to the NAS Setup section. +I have switched to using DietPi images (from Alpine) as they support my hardware, as well as RPis. + +1. Follow instructions from [DietPi wiki](https://dietpi.com/docs/install/) to create a bootable SD card and boot up. +2. On first boot, I recommend you change your `root` password, and change the SSH server to use OpenSSH (from Dropbear). +This makes running automation against it easier. +3. Then you can run our playbook with the `base` tag to install all pre-requisite software. +4. You should then setup your drives according to your needs. If you are doing ZFS, the section below might be useful. ### NAS Setup -As a minimum, I recommend setting up two of the external usb drives as a ZFS mirrored pool. +I recommend setting up the two drives as a ZFS mirrored pool. This will allow you to lose up to one drive at a time, and still operate in a degraded state while you replace it. ```bash -# install zfs -apk add udev zfs -modprobe zfs -# add zfs to /etc/modules # +# Install zfs (the base role will do this for you if using a rockpro64) +# Otherwise there are usually two steps: +# 1. Install the kernel headers for your kernel. +# 2. Install the zfs-dkms, and zfsutils-linux packages. + # verify install zfs --version -rc-update add udev sysinit -rc-update add udev-trigger sysinit # assuming your first drive is /dev/sda -zpool create yourpool /dev/sda -zpool export yourpool -zpool import -d /dev/disk/by-id/usb-Samsung_PSSD_T7_Shield_S6SMNS0T701007V-0:0-part1 yourpool -N +# get the ids -> /dev/sdX mapping of your disks by +ls -al /dev/disk/by-id/ +# using ids is recommened because then zpool status will instantly tell you +# which disk in reality is problematic, rather than sda,sdb etc. +zpool create yourpool mirror /dev/disk/by-id/yourdisk1 /dev/disk/by-id/yourdisk2 zfs set mountpoint=/mnt/yourpool yourpool # create datasets zfs create yourpool/media zfs create yourpool/data # for encrypted datasets zfs create -o encryption=on -o keylocation=prompt -o keyformat=passphrase yourpool/priv -# add the second drive to the pool -zpool attach yourpool usb-Samsung_PSSD_T7_Shield_S6SMNS0T701007V-0:0 usb-Samsung_PSSD_T7_S5T3NJ0N907662T-0:0 # zfs useful cmds -zpool scrub yourpool zpool status -v yourpool +zpool scrub yourpool zfs get mountpoint zfs mount -l yourpool/data zfs mount -l yourpool/media diff --git a/architecture.xml b/architecture.xml deleted file mode 100644 index 6a254c4..0000000 --- a/architecture.xml +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/group_vars/all/vars.yaml b/group_vars/all/vars.yaml index 12fd063..7b27440 100644 --- a/group_vars/all/vars.yaml +++ b/group_vars/all/vars.yaml @@ -1,9 +1,21 @@ +# The value in this file correspond to MY SETUP. +# You will need to change these to reflect yours. --- +# This is the secondary user you want to setup. +# Passwords go in the Vault. +username: 'kdam0' + +# This is pretty much only used for the ZFS install step. +# sbc: Currently supported ones are: + # - Rockchip: rockchip64 +# If you don't care about installing ZFS from here, leave this blank. +hardware: 'rockchip64' + # the wildcard domain under which all apps will be hosted. apps_domain: 'kumardamani.net' -# list all the app configs you want to host here. +# list of all the apps you want to run behind nginx. # port: the host port that this service will be available on. # access_domain: external (nginx) domain. # Only include when applicable. @@ -52,6 +64,16 @@ apps_conf_map: port: 31907 status_endpoint: '/system/status' curl_requires_auth: false + photoprism: + port: 31908 + access_domain: 'photos.{{ apps_domain }}' + status_endpoint: '' + curl_requires_auth: false + # adguard: + # port: 31909 + # access_domain: 'adguard.{{ apps_domain }}' + # status_endpoint: '' + # curl_requires_auth: false # list all static websites you plan to host here. # name: the root domain name of the static website. diff --git a/group_vars/all/vault b/group_vars/all/vault index b7497af..328c155 100644 --- a/group_vars/all/vault +++ b/group_vars/all/vault @@ -1,28 +1,34 @@ $ANSIBLE_VAULT;1.1;AES256 -63336336613233616539616164616433666436353761376139336663613032323161616536336332 -3963653737353730383561343463623437353230376561350a633133373035393636363762643066 -30613830346231326161666661643065316439323632633434633836326136303339386236386561 -6462346562313464300a633266363066383138396333656338656432633465353365316635613337 -66336532643561363230346164343636663331333436383536653339306332343731386430636262 -33333638333565306331363866343763353434613230646631386234393762366236343633653431 -33613133623664646135616439616165366531303565616439326330646335326536396634316165 -63656431613766643434383565666262356261373937313961376538353037306236653730643564 -35613564393762366335303532366338393930613936383137363435633331323635383837663864 -32663866366131303263636162303837643161306433346433353361616263376265613934653934 -33336161626137343432633561313631396262626665356633343561636133386630323466383636 -34636434396464386265326638303730656166353663343561313737353130333635356337623639 -35373562613765346339303066323136386139326230633732653437623239386132376165386634 -32613162323931346238303334616137356264326663613362366664396162393033343664306663 -34656435316430373534646636653662303962396130323365643966666461613861343131656633 -32666432616238326338613862623638386338303030323365666237616162306133656136623633 -36343964656333663665373062386664626438303866643533303961346431376331373436376339 -31333131363762316563626164356236343862373533633839666133343337653237343730313965 -64333633336630653935636436323132643861666338613631323433353764306266326333653436 -30333661333834323262366464656166373066343035343335636332346561656463616266333866 -39383464343837656562666565393434663363316639323032333330383334616638393463653863 -37643162626335376666666336633339386434633532343765653334333033393830666630656633 -64383730666662363331663965656139336638343532663030343362623134376661313539313132 -30646437616134616538396464636361646435633130333137386332643931303234653738343531 -63363063333233376334326538393233366436353230613430326562643632313738356333383430 -61343262346531656537313965626532656664396139386331623362333538353561303465303466 -616362393632643064653731333335383438 +61373432623236353766373265633331353163393733366637363333383935386137336464313864 +6165363331303839363837396331353866373264376464660a363364666661613738336536333138 +37383833663765366135366139323531353966663333313938636163643636666638383863353265 +6638363065323261350a343063343932633066313962323763623366333232316262383662393562 +63656138336339373431333033643264393937306137356466343161396362353537323363643834 +64326264326665636633636361386336316235386433326536613263666234363932323766316538 +64306362353236316334653839303636373963343434303435343132326638613162323334663232 +37663932646132613935333030386633343833323532343864616136393737303864343139643366 +61316666346439613762376534663162643030356630646661623037643063306632343861636336 +31663435323362663163616335383264656534363739366461373239396337623234616164366239 +63306530616163633735633062666134393430633733333235373134663763666637323930346130 +66373663653734356665313464633966313835303838323266613331313535353064663431396133 +65616135376163653532356438313331396138653164356362313633633935623435383430663538 +32316162643436333933343537373233343731383164363634373964653537613265633934643235 +65656636643133333735346164373862383161363061306638363763363333653562653334323536 +62323066653462346362323737626436303966393932633132636264623032633530653763636434 +33393966306436396564356563666635666630626661313762336134643232646631353234393864 +63613165396362643963303632636531653939333134363032313533663735613337386236313034 +62653139633861383662356530396638333837613338666563343835346236653036313964643330 +30353063356636643331396635633438313335396133356431613232326630363864393939663962 +38313861356163646665346163613932626662623636333165386535613863363264613666636432 +39326665323563613033663930636631616264626236656265616337383737616466643530653463 +63346538316231313365373866373430623131366561326137653535663437623935626636636338 +38303463666639646166323834353334383831376465363532616330313737393262656666393566 +65336239653861313433386661636339356532623862306238653366373531333833323237623731 +63356466323637343830356164393833323633343234376262313564613861303535613864336531 +37643536333339633366363264303638316266316163343039376537373634626361393163326565 +65373539643461383066306363313165616435633836363336313336396666336232626136636331 +34623434343431646134353734373733343338346432343333316132366566633861373934326434 +65333130633463626364386561636232383138313632626639653063303163646137323336396635 +61363066663465613731373936663337666563616662626234643239396335376363393431306638 +36323665633236376465663662643230313564386561386462326337323533613762663435363763 +33383135636437353363313030663561393235363366323030383166393939333332 diff --git a/group_vars/all/vault.example b/group_vars/all/vault.example index 8ca22bf..e053dda 100644 --- a/group_vars/all/vault.example +++ b/group_vars/all/vault.example @@ -1,5 +1,7 @@ --- +vault_user_password: '' + vault_wireguard_server_priv_key: '' vault_ddclient_user: '' @@ -18,3 +20,6 @@ vault_searxng_secret_key: '' vault_transmission_user: '' vault_transmission_password: '' +vault_photoprism_admin_password: '' + +vault_plex_claim: '' diff --git a/pix/architecture.png b/pix/architecture.png new file mode 100644 index 0000000..e7a092d Binary files /dev/null and b/pix/architecture.png differ diff --git a/pix/architecture.xml b/pix/architecture.xml new file mode 100644 index 0000000..6a254c4 --- /dev/null +++ b/pix/architecture.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/pix/board.png b/pix/board.png new file mode 100644 index 0000000..b02b9f8 Binary files /dev/null and b/pix/board.png differ diff --git a/pix/case.png b/pix/case.png new file mode 100644 index 0000000..122172e Binary files /dev/null and b/pix/case.png differ diff --git a/pix/pcie_sata.png b/pix/pcie_sata.png new file mode 100644 index 0000000..a7cfba9 Binary files /dev/null and b/pix/pcie_sata.png differ diff --git a/pix/psu.png b/pix/psu.png new file mode 100644 index 0000000..7143f87 Binary files /dev/null and b/pix/psu.png differ diff --git a/pix/sata_power.png b/pix/sata_power.png new file mode 100644 index 0000000..cc5450f Binary files /dev/null and b/pix/sata_power.png differ diff --git a/pix/wd.png b/pix/wd.png new file mode 100644 index 0000000..1583750 Binary files /dev/null and b/pix/wd.png differ diff --git a/playbooks/deploy.yaml b/playbooks/deploy.yaml index 08af211..e1e0970 100644 --- a/playbooks/deploy.yaml +++ b/playbooks/deploy.yaml @@ -5,26 +5,33 @@ # make dry-run file=playbooks/deploy.yaml tags="" # # Available tags: -# ddclient, wireguard, nginx, websites, -# samba, nextcloud, bitwarden, searxng, +# base, ddclient, wireguard, websites samba, +# nginx, nextcloud, bitwarden, searxng, # monitoring, transmission, media_downloader +# photoprism, plex # # Install: # make install # -# ASSUMPTIONS: -# You should already have docker installed. -# See the README.md for base image setup section. -# --- ## Non Docker Services ## +- hosts: compute + gather_facts: true + tags: 'base' + become: true + roles: + - role: base + vars: + base_user: '{{ username }}' + base_user_password: '{{ vault_user_password }}' + base_hardware: '{{ hardware }}' + - hosts: compute gather_facts: true tags: 'ddclient' become: true - become_method: 'doas' roles: - role: ddclient vars: @@ -37,7 +44,6 @@ gather_facts: true tags: 'wireguard' become: true - become_method: 'doas' roles: - role: wireguard vars: @@ -47,9 +53,9 @@ wireguard_server_ip: '192.168.10.1/32' wireguard_peers: - peer_ip: '192.168.10.2/32' # my phone - peer_key: '/mFv6y9QA8dhX/A9fFn+mzg/SZq4BZPeNofm1w754y8=' + peer_key: 'QUirl0QsXC3P6D5t5VPlvDgfji1ZI5e0XhppBFLW9TY=' - peer_ip: '192.168.10.3/32' # personal laptop - peer_key: '6+t6FbEHSAOuzBtQwb0bDqfFa5Kvfkb2QIUGpRKA5Eg=' + peer_key: 'pzqY/UxffV8O01K982jlgP1xJQphnglOdqVhOM2IUSc=' - peer_ip: '192.168.10.4/32' # vps peer_key: 'oz2jxeSUWD4r5g3y7XuSItqSiqOOJz8vulYYVXAsKS8=' @@ -70,7 +76,6 @@ gather_facts: true tags: 'samba' become: true - become_method: 'doas' roles: - role: samba vars: @@ -94,6 +99,17 @@ nginx_static_html_root: '{{ vol_data }}/sites' nginx_certs_root: '{{ vol_data }}/letsencrypt' +# - hosts: compute +# gather_facts: false +# tags: 'adguard' +# become: false +# roles: +# - role: adguard +# vars: +# adguard_domain: '{{ apps_conf_map["adguard"]["access_domain"] }}' +# adguard_host_port: '{{ apps_conf_map["adguard"]["port"] }}' +# adguard_data_root: '{{ vol_data }}/adguard' + - hosts: compute gather_facts: false tags: 'nextcloud' @@ -163,3 +179,30 @@ monitoring_root_dir: '{{ vol_data }}/monitoring' monitoring_apps_confs: '{{ apps_conf_map | dict2items(key_name="app", value_name="conf") }}' monitoring_static_sites: '{{ nginx_websites }}' + +- hosts: compute + gather_facts: false + tags: 'photoprism' + become: false + roles: + - role: photoprism + vars: + photoprism_host_port: '{{ apps_conf_map["photoprism"]["port"] }}' + photoprism_admin_password: '{{ vault_photoprism_admin_password }}' + photoprism_data_dir: '{{ vol_data }}/photoprism' + photoprism_pics_root_dir: '{{ vol_media }}/pics' + +- hosts: compute + gather_facts: false + tags: 'plex' + become: false + roles: + - role: plex + vars: + plex_host_port: '{{ apps_conf_map["plex"]["port"] }}' + plex_claim: '{{ vault_plex_claim }}' + plex_library_dir: '{{ vol_media }}/plex' + plex_tv_dir: '{{ vol_media }}/media/tv' + plex_mov_dir: '{{ vol_media }}/media/mov' + plex_pic_dir: '{{ vol_media }}/pics' + plex_music_dir: '{{ vol_media }}/music' diff --git a/roles/adguard/defaults/main.yaml b/roles/adguard/defaults/main.yaml new file mode 100644 index 0000000..91abefa --- /dev/null +++ b/roles/adguard/defaults/main.yaml @@ -0,0 +1,4 @@ +# Default Values +--- + +adguard_docker_network_name: 'adguard_network' diff --git a/roles/adguard/handlers/main.yaml b/roles/adguard/handlers/main.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/roles/adguard/handlers/main.yaml @@ -0,0 +1,2 @@ +--- + diff --git a/roles/adguard/tasks/main.yaml b/roles/adguard/tasks/main.yaml new file mode 100644 index 0000000..018b067 --- /dev/null +++ b/roles/adguard/tasks/main.yaml @@ -0,0 +1,38 @@ +# https://docs.photoprism.app/getting-started/docker-compose/ +--- + +- name: 'Create the AdGuard network' + community.docker.docker_network: + name: '{{ adguard_docker_network_name }}' + state: 'present' + +- name: 'Create the required dirs' + file: + state: 'directory' + path: '{{ item }}' + mode: '755' + loop: + - '{{ adguard_data_root }}' + - '{{ adguard_data_root }}/data' + - '{{ adguard_data_root }}/conf' + +- name: 'Start the AdGuard container' + community.docker.docker_container: + name: 'adguard' + image: 'adguard/adguardhome' + pull: true + state: 'started' + recreate: false + networks: + - name: '{{ adguard_docker_network_name }}' + ports: + # DNS + - '53:53/tcp' + - '53:53/udp' + # Web + - '{{ adguard_host_port }}:3000' + volumes: + - '{{ adguard_data_root }}/data:/opt/adguardhome/work' + - '{{ adguard_data_root }}/conf:/opt/adguardhome/conf' + # restart_policy: 'unless-stopped' + restart_policy: 'no' diff --git a/roles/base/defaults/main.yaml b/roles/base/defaults/main.yaml new file mode 100644 index 0000000..9a163d4 --- /dev/null +++ b/roles/base/defaults/main.yaml @@ -0,0 +1,2 @@ +# Default Values +--- diff --git a/roles/base/handlers/main.yaml b/roles/base/handlers/main.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/roles/base/handlers/main.yaml @@ -0,0 +1,2 @@ +--- + diff --git a/roles/base/tasks/base_alpine.yaml b/roles/base/tasks/base_alpine.yaml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/base/tasks/base_alpine.yaml @@ -0,0 +1 @@ +--- diff --git a/roles/base/tasks/base_debian.yaml b/roles/base/tasks/base_debian.yaml new file mode 100644 index 0000000..9d25ea6 --- /dev/null +++ b/roles/base/tasks/base_debian.yaml @@ -0,0 +1,62 @@ +--- + +- name: 'Install base packages for Debian' + apt: + name: + - '{{ item }}' + state: 'present' + update_cache: true + loop: + - 'less' + - 'vim' + - 'tmux' + - 'neofetch' + - 'iotop-c' + - 'tcpdump' + - 'rsync' + - 'python3-pip' + - 'docker.io' + - 'docker-compose' + +- name: 'Install base packages for Python' + pip: + name: '{{ item }}' + loop: + - 'docker' + - 'pexpect' + +- name: "Create the user '{{ base_user }}'" + user: + name: '{{ base_user }}' + state: 'present' + shell: '/bin/bash' + uid: 1001 + password: '{{ base_user_password | password_hash("sha512") }}' + create_home: true + generate_ssh_key: true + groups: 'sudo, docker' + append: true + +- name: 'Allow passwordless sudo for this {{ base_user }}' + lineinfile: + path: '/etc/sudoers' + state: 'present' + regexp: '^%{{ base_user }}\s+ALL=' + line: '%{{ base_user }} ALL=(ALL) NOPASSWD: ALL' + validate: '/usr/sbin/visudo -cf %s' + +- block: + - name: 'Install kernel headers for currently installed kernel' + apt: + name: 'linux-headers-current-rockchip64' + state: 'present' + + - name: 'Install zfs modules and package' + apt: + name: '{{ item }}' + state: 'present' + default_release: 'bullseye-backports' + loop: + - 'zfs-dkms' + - 'zfsutils-linux' + when: 'base_hardware == "rockchip64"' diff --git a/roles/base/tasks/main.yaml b/roles/base/tasks/main.yaml new file mode 100644 index 0000000..4930d10 --- /dev/null +++ b/roles/base/tasks/main.yaml @@ -0,0 +1,9 @@ +--- + +- name: 'Run base install for Alpine' + import_tasks: 'base_alpine.yaml' + when: 'ansible_os_family == "Alpine"' + +- name: 'Run base install for Debian' + import_tasks: 'base_debian.yaml' + when: 'ansible_os_family == "Debian"' diff --git a/roles/ddclient/tasks/main.yaml b/roles/ddclient/tasks/main.yaml index d780a3f..defcef8 100644 --- a/roles/ddclient/tasks/main.yaml +++ b/roles/ddclient/tasks/main.yaml @@ -15,9 +15,16 @@ update_cache: true when: 'ansible_os_family == "Debian"' +# - name: 'Update ddclient conf' +# template: +# dest: '/etc/ddclient/ddclient.conf' +# src: 'ddclient.conf.j2' +# mode: '644' +# notify: 'restart ddclient' + - name: 'Update ddclient conf' template: - dest: '/etc/ddclient/ddclient.conf' + dest: '/etc/ddclient.conf' src: 'ddclient.conf.j2' mode: '644' notify: 'restart ddclient' diff --git a/roles/media_downloader/tasks/main.yaml b/roles/media_downloader/tasks/main.yaml index d3840a5..5f6c8c8 100644 --- a/roles/media_downloader/tasks/main.yaml +++ b/roles/media_downloader/tasks/main.yaml @@ -15,8 +15,8 @@ state: 'started' recreate: false env: - "PUID": '1000' - "PGID": '1000' + "PUID": '1001' + "PGID": '1001' "TZ": 'America/Toronto' networks: - name: '{{ media_downloader_docker_network_name }}' @@ -36,8 +36,8 @@ state: 'started' recreate: false env: - "PUID": '1000' - "PGID": '1000' + "PUID": '1001' + "PGID": '1001' "TZ": 'America/Toronto' networks: - name: '{{ media_downloader_docker_network_name }}' @@ -57,8 +57,8 @@ state: 'started' recreate: false env: - "PUID": '1000' - "PGID": '1000' + "PUID": '1001' + "PGID": '1001' "TZ": 'America/Toronto' networks: - name: '{{ media_downloader_docker_network_name }}' @@ -76,8 +76,8 @@ state: 'started' recreate: false env: - "PUID": '1000' - "PGID": '1000' + "PUID": '1001' + "PGID": '1001' "TZ": 'America/Toronto' "UMASK": '002' networks: diff --git a/roles/monitoring/files/zfs-exporter.service b/roles/monitoring/files/zfs-exporter.service new file mode 100644 index 0000000..8982723 --- /dev/null +++ b/roles/monitoring/files/zfs-exporter.service @@ -0,0 +1,13 @@ +[Unit] +Description=ZFS Exporter +After=network.target + +[Service] +Type=simple +ExecStart=/usr/bin/zfs_exporter +LimitNOFILE=infinity +User=root +Group=root + +[Install] +WantedBy=multi-user.target diff --git a/roles/monitoring/tasks/node.yaml b/roles/monitoring/tasks/node.yaml index 5d38f1f..632ceb8 100644 --- a/roles/monitoring/tasks/node.yaml +++ b/roles/monitoring/tasks/node.yaml @@ -21,3 +21,18 @@ state: 'started' enabled: true when: 'ansible_os_family == "Alpine"' + +- block: + - name: 'Install node-exporter' + become: true + package: + name: 'prometheus-node-exporter' + state: 'present' + + - name: 'Start and enable node-exporter service' + become: true + service: + name: 'prometheus-node-exporter' + state: 'started' + enabled: true + when: 'ansible_os_family == "Debian"' diff --git a/roles/monitoring/tasks/zfs.yaml b/roles/monitoring/tasks/zfs.yaml index 2f18e32..a30a7ac 100644 --- a/roles/monitoring/tasks/zfs.yaml +++ b/roles/monitoring/tasks/zfs.yaml @@ -17,13 +17,13 @@ mode: '755' - name: 'Extract ZFS exporter to dir' - command: 'tar -xf zfs_exporter-2.2.5.linux-arm64.tar.gz' + command: 'tar -xf zfs_exporter.tar.gz' args: chdir: '{{ monitoring_root_dir }}' - name: 'Copy the executable to /usr/bin' become: true - become_method: 'doas' + # become_method: 'doas' copy: src: '{{ monitoring_root_dir }}/zfs_exporter-2.2.5.linux-arm64/zfs_exporter' dest: '/usr/bin/zfs_exporter' @@ -31,18 +31,31 @@ owner: 'root' remote_src: true -- name: 'Create service file to start zfs_exporter on boot' +# - name: 'Create service file to start zfs_exporter on boot' +# become: true +# # become_method: 'doas' +# copy: +# src: 'zfs-exporter' +# dest: '/etc/init.d/zfs-exporter' +# mode: '0755' +# owner: 'root' +# +- name: 'Create systemd services' become: true - become_method: 'doas' copy: - src: 'zfs-exporter' - dest: '/etc/init.d/zfs-exporter' - mode: '0755' - owner: 'root' + src: 'zfs-exporter.service' + dest: '/etc/systemd/system/zfs-exporter.service' + mode: '644' + # notify: + # - 'zfs-exporter restart' + +- name: 'Reload systemd units' + become: true + systemd: + daemon_reload: true - name: 'Start and enable the zfs-exporter service' become: true - become_method: 'doas' service: name: 'zfs-exporter' state: 'started' diff --git a/roles/nextcloud/defaults/main.yaml b/roles/nextcloud/defaults/main.yaml index cd11c66..b0c20f3 100644 --- a/roles/nextcloud/defaults/main.yaml +++ b/roles/nextcloud/defaults/main.yaml @@ -1,8 +1,8 @@ # Default Values --- -nextcloud_uid: "1000" -nextcloud_gid: "1000" +nextcloud_uid: "1001" +nextcloud_gid: "1001" nextcloud_tz: 'America/Toronto' nextcloud_data_root: '' nextcloud_host_port: '' diff --git a/roles/nextcloud/tasks/main.yaml b/roles/nextcloud/tasks/main.yaml index c1d91aa..2354d4b 100644 --- a/roles/nextcloud/tasks/main.yaml +++ b/roles/nextcloud/tasks/main.yaml @@ -35,7 +35,7 @@ - name: 'Make sure the Nextcloud container is created and running' community.docker.docker_container: name: '{{ nextcloud_container_name }}' - image: 'ghcr.io/linuxserver/nextcloud:php8-24.0.4-ls81' + image: 'lscr.io/linuxserver/nextcloud:25.0.2' pull: true state: 'started' env: diff --git a/roles/nginx_docker/templates/app.nginx.conf.j2 b/roles/nginx_docker/templates/app.nginx.conf.j2 index 82c3610..f6f92de 100644 --- a/roles/nginx_docker/templates/app.nginx.conf.j2 +++ b/roles/nginx_docker/templates/app.nginx.conf.j2 @@ -1,5 +1,6 @@ server { listen 443 ssl; + client_max_body_size 500M; root _; server_name {{ item.conf.access_domain }}; ssl_certificate /etc/letsencrypt/live/{{ nginx_global_apps_domain }}/fullchain.pem; @@ -18,8 +19,13 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; proxy_set_header X-Forwarded-Proto https; +{% if item.app == "photoprism" %} {# Photoprism requires websockets #} + proxy_buffering off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; +{% endif %} proxy_read_timeout 1200s; - client_max_body_size 0; error_log /var/log/nginx/{{ item.app }}.error.log; } } diff --git a/roles/photoprism/defaults/main.yaml b/roles/photoprism/defaults/main.yaml new file mode 100644 index 0000000..29e3605 --- /dev/null +++ b/roles/photoprism/defaults/main.yaml @@ -0,0 +1,4 @@ +# Default Values +--- + +photoprism_docker_network_name: 'photoprism_network' diff --git a/roles/photoprism/handlers/main.yaml b/roles/photoprism/handlers/main.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/roles/photoprism/handlers/main.yaml @@ -0,0 +1,2 @@ +--- + diff --git a/roles/photoprism/tasks/main.yaml b/roles/photoprism/tasks/main.yaml new file mode 100644 index 0000000..73d807c --- /dev/null +++ b/roles/photoprism/tasks/main.yaml @@ -0,0 +1,52 @@ +# https://docs.photoprism.app/getting-started/docker-compose/ +--- + +- name: 'Create the photoprism network' + community.docker.docker_network: + name: '{{ photoprism_docker_network_name }}' + state: 'present' + +- name: 'Install Photoprism' + community.docker.docker_container: + name: 'photoprism' + image: 'photoprism/photoprism:latest' + pull: true + state: 'started' + recreate: false + security_opts: + - 'seccomp:unconfined' + - 'apparmor:unconfined' + env: + PHOTOPRISM_ADMIN_PASSWORD: "{{ photoprism_admin_password }}" # INITIAL PASSWORD FOR "admin" USER, MINIMUM 8 CHARACTERS + PHOTOPRISM_AUTH_MODE: "password" # authentication mode (public, password) + PHOTOPRISM_SITE_URL: "https://photos.kumardamani.net/" # public server URL incl http:// or https:// and /path, :port is optional + PHOTOPRISM_ORIGINALS_LIMIT: "5000" # file size limit for originals in MB (increase for high-res video) + PHOTOPRISM_HTTP_COMPRESSION: "gzip" # improves transfer speed and bandwidth utilization (none or gzip) + PHOTOPRISM_LOG_LEVEL: "info" # log level: trace, debug, info, warning, error, fatal, or panic + PHOTOPRISM_READONLY: "true" # do not modify originals directory (reduced functionality) + PHOTOPRISM_EXPERIMENTAL: "false" # enables experimental features + PHOTOPRISM_DISABLE_CHOWN: "true" # disables updating storage permissions via chmod and chown on startup + PHOTOPRISM_DISABLE_WEBDAV: "true" # disables built-in WebDAV server + PHOTOPRISM_DISABLE_SETTINGS: "false" # disables settings UI and API + PHOTOPRISM_DISABLE_TENSORFLOW: "true" # disables all features depending on TensorFlow + PHOTOPRISM_DISABLE_FACES: "true" # disables face detection and recognition (requires TensorFlow) + PHOTOPRISM_DISABLE_CLASSIFICATION: "true" # disables image classification (requires TensorFlow) + PHOTOPRISM_DISABLE_RAW: "true" # disables indexing and conversion of RAW files + PHOTOPRISM_RAW_PRESETS: "false" # enables applying user presets when converting RAW files (reduces performance) + PHOTOPRISM_JPEG_QUALITY: "85" # a higher value increases the quality and file size of JPEG images and thumbnails (25-100) + PHOTOPRISM_DETECT_NSFW: "false" # automatically flags photos as private that MAY be offensive (requires TensorFlow) + PHOTOPRISM_UPLOAD_NSFW: "false" # allows uploads that MAY be offensive (no effect without TensorFlow) + PHOTOPRISM_DATABASE_DRIVER: "sqlite" # SQLite is an embedded database that doesn't require a server + PHOTOPRISM_SITE_CAPTION: "Photos App" + PHOTOPRISM_SITE_DESCRIPTION: "Some of our pics" # meta site description + PHOTOPRISM_SITE_AUTHOR: "Kumar" # meta site author + PHOTOPRISM_INIT: "gpu tensorflow" + working_dir: "/photoprism" + networks: + - name: '{{ photoprism_docker_network_name }}' + ports: + - '{{ photoprism_host_port }}:2342' + volumes: + - '{{ photoprism_pics_root_dir }}:/photoprism/originals:ro' + - '{{ photoprism_data_dir }}:/photoprism/storage' + restart_policy: "unless-stopped" diff --git a/roles/plex/defaults/main.yaml b/roles/plex/defaults/main.yaml new file mode 100644 index 0000000..57e1fc7 --- /dev/null +++ b/roles/plex/defaults/main.yaml @@ -0,0 +1,4 @@ +# Default Values +--- + +plex_docker_network_name: 'plex_network' diff --git a/roles/plex/handlers/main.yaml b/roles/plex/handlers/main.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/roles/plex/handlers/main.yaml @@ -0,0 +1,2 @@ +--- + diff --git a/roles/plex/tasks/main.yaml b/roles/plex/tasks/main.yaml new file mode 100644 index 0000000..7cbb531 --- /dev/null +++ b/roles/plex/tasks/main.yaml @@ -0,0 +1,22 @@ +--- + +- name: 'Install Plex' + community.docker.docker_container: + name: 'plex' + image: 'lscr.io/linuxserver/plex:latest' + pull: true + state: 'started' + recreate: false + env: + PUID: "1001" + PGID: "1001" + VERSION: "docker" + PLEX_CLAIM: "{{ plex_claim }}" + network_mode: 'host' # will use 32400 + volumes: + - '{{ plex_library_dir }}:/config' + - '{{ plex_tv_dir }}:/tv' + - '{{ plex_mov_dir }}:/movies' + - '{{ plex_pic_dir }}:/pics' + - '{{ plex_music_dir }}:/music' + restart_policy: "unless-stopped" diff --git a/roles/transmission/tasks/main.yaml b/roles/transmission/tasks/main.yaml index 91d3971..229184f 100644 --- a/roles/transmission/tasks/main.yaml +++ b/roles/transmission/tasks/main.yaml @@ -14,8 +14,8 @@ state: 'started' recreate: true env: - "PUID": '1000' - "PGID": '1000' + "PUID": '1001' + "PGID": '1001' "TZ": 'America/Toronto' USER: '{{ transmission_user }}' PASS: '{{ transmission_password }}' diff --git a/roles/website/tasks/main.yaml b/roles/website/tasks/main.yaml index 66bc955..07780b5 100644 --- a/roles/website/tasks/main.yaml +++ b/roles/website/tasks/main.yaml @@ -2,11 +2,19 @@ - name: 'Install git' become: true - become_method: 'doas' + # become_method: 'doas' package: name: 'git' state: 'present' +- name: 'Remove domain level dir' + file: + path: '{{ sites_data_root }}/{{ item.name }}/html' + state: 'absent' + when: 'item.git_url is defined' + loop: '{{ websites }}' + + - name: 'Create domain level dir' file: path: '{{ sites_data_root }}/{{ item.name }}/html' @@ -33,3 +41,10 @@ remote_src: true when: 'item.git_url is defined' loop: '{{ websites }}' + +- name: 'Remove git checkout' + file: + path: '/home/{{ ansible_user }}/{{ item.name }}' + state: 'absent' + when: 'item.git_url is defined' + loop: '{{ websites }}' diff --git a/roles/wireguard/tasks/main.yaml b/roles/wireguard/tasks/main.yaml index c3f0942..aa8b20d 100644 --- a/roles/wireguard/tasks/main.yaml +++ b/roles/wireguard/tasks/main.yaml @@ -9,6 +9,7 @@ loop: - 'iptables' - 'wireguard-tools' + - 'libqrencode' - name: 'Enable iptables' service: -- cgit v1.2.3 From 54087a98772dfc6f0af2a3f6725cc943a75747e4 Mon Sep 17 00:00:00 2001 From: Kumar Damani Date: Wed, 4 Jan 2023 15:16:51 -0500 Subject: more up --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d7c194..b62b369 100644 --- a/README.md +++ b/README.md @@ -60,17 +60,20 @@ There are many reasons why this board is awesome: 3. PCIe slot!! My main reason for switching to this board is the final point above :) - Speaking of the PCIe slot, we can get a PCIe SATA adapter to connect to two SATA drives. + ![Dual SATA Adapter](./pix/pcie_sata.png) To power the drives, Pine64 all sells power cables: + ![SATA power cables](./pix/sata_power.png) The drives themselves are 4 TiB 3.5in 5400 RPM CMR such as: + ![Drive 1](./pix/wd.png) > 7200 RPM drives are more expensive and I won't be pushing this hard enough to notice the benefits. + > Note there will be cheaper drives using SMR, but I'd recommend CMR is worth the extra cost. Remember to buy drives that are not made as part of the same batch, so that the probabity of them @@ -79,10 +82,13 @@ dying together is the lowest. You can also do this by buying different brands. Also remember to buy an extra set so that you save yourself some panic during recovery. When using the dual SATA adapter, Pine64 recommends a beefier 12V, 3A power-supply: + ![PSU](./pix/psu.png) Since this is basically a NAS build, I opted to house all of this in: + ![NAS Case](./pix/case.png) + Which comes included with a fan, and the SATA power-cables. Optional, but recommended: an external usb SSD or HDD as a backup drive. -- cgit v1.2.3 From 5081add0ce307a1632246709f7d9b18f8e9173a2 Mon Sep 17 00:00:00 2001 From: Kumar Damani Date: Wed, 4 Jan 2023 15:26:05 -0500 Subject: more --- README.md | 5 +++-- pix/case.jpg | Bin 0 -> 53958 bytes 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 pix/case.jpg diff --git a/README.md b/README.md index b62b369..ab1c350 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # My Homelab Setup -**This is still very much un-stable, and very much a work-in-progress.** +**This is project is now somewhat stable but still a work-in-progress.** So I decided to migrate *most* of my remote VPS to a self-hosted private server. There are 3 reasons for this: 1. Cost savings. VPS SSD storage can get quite [expensive](https://racknerd.com/kvm-vps) as your storage demands increase. Meanwhile I have a few SSDs lying my house around not being utilized. @@ -81,13 +81,14 @@ dying together is the lowest. You can also do this by buying different brands. Also remember to buy an extra set so that you save yourself some panic during recovery. -When using the dual SATA adapter, Pine64 recommends a beefier 12V, 3A power-supply: +When using the dual SATA adapter, Pine64 recommends a beefier 12V 5A power-supply: ![PSU](./pix/psu.png) Since this is basically a NAS build, I opted to house all of this in: ![NAS Case](./pix/case.png) +![NAS Case](./pix/case.jpg) Which comes included with a fan, and the SATA power-cables. diff --git a/pix/case.jpg b/pix/case.jpg new file mode 100644 index 0000000..f8e3b86 Binary files /dev/null and b/pix/case.jpg differ -- cgit v1.2.3 From 56fc00068916f1a809f5bea38105f394248348f9 Mon Sep 17 00:00:00 2001 From: Kumar Damani Date: Wed, 4 Jan 2023 15:28:15 -0500 Subject: mroe --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ab1c350..e7785b9 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ There are many cheap VPS providers out there. I use Racknerd now. I have used Vu > The equipment I use reflect my current priorities and have changed since this project started and will continue to change in the future. +#### NAS Equipment A [ROCKPro64](https://wiki.pine64.org/wiki/ROCKPro64) 4G model. Alternatively, an RPi4 or similar would also work if you can get your hands on it. ![ROCKPro64](./pix/board.png) @@ -92,10 +93,11 @@ Since this is basically a NAS build, I opted to house all of this in: Which comes included with a fan, and the SATA power-cables. -Optional, but recommended: an external usb SSD or HDD as a backup drive. +#### Backup Equipment +An external USB SSD or HDD as a backup drive. -An finally, a very cheap VPS (Virtual Private Server) - I use Racknerd. -This will give you access to a reliable static IP. +#### VPS +A VPS (Virtual Private Server) - I use Racknerd. This will give you access to a reliable static IP. ### Base Image setup I have switched to using DietPi images (from Alpine) as they support my hardware, as well as RPis. -- cgit v1.2.3 From 1f256dd208e40468a90a51684a940631d07a67d4 Mon Sep 17 00:00:00 2001 From: Kumar Damani Date: Wed, 4 Jan 2023 15:32:24 -0500 Subject: more --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e7785b9..7c87902 100644 --- a/README.md +++ b/README.md @@ -100,12 +100,14 @@ An external USB SSD or HDD as a backup drive. A VPS (Virtual Private Server) - I use Racknerd. This will give you access to a reliable static IP. ### Base Image setup +Once you have a server+storage, and a VPS, you are ready to start. I have switched to using DietPi images (from Alpine) as they support my hardware, as well as RPis. 1. Follow instructions from [DietPi wiki](https://dietpi.com/docs/install/) to create a bootable SD card and boot up. 2. On first boot, I recommend you change your `root` password, and change the SSH server to use OpenSSH (from Dropbear). This makes running automation against it easier. 3. Then you can run our playbook with the `base` tag to install all pre-requisite software. +See the Install section below for getting started with running playbooks from this repo. 4. You should then setup your drives according to your needs. If you are doing ZFS, the section below might be useful. ### NAS Setup -- cgit v1.2.3 From 1ad4354d79086d2813e2cdd6c924223f1bad49b5 Mon Sep 17 00:00:00 2001 From: Kumar Damani Date: Wed, 4 Jan 2023 15:35:18 -0500 Subject: more --- architecture.png | Bin 74525 -> 0 bytes pix/case.jpg | Bin 53958 -> 16000 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 architecture.png diff --git a/architecture.png b/architecture.png deleted file mode 100644 index e7a092d..0000000 Binary files a/architecture.png and /dev/null differ diff --git a/pix/case.jpg b/pix/case.jpg index f8e3b86..1d264a8 100644 Binary files a/pix/case.jpg and b/pix/case.jpg differ -- cgit v1.2.3 From 8aef00bd35d4c84b98ba51e08ad9f4e8f6e58547 Mon Sep 17 00:00:00 2001 From: Kumar Damani Date: Wed, 4 Jan 2023 15:41:11 -0500 Subject: more --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7c87902..989c930 100644 --- a/README.md +++ b/README.md @@ -246,3 +246,4 @@ echo "-------Backup ended-------" ## Why self-host? You can read more about my thoughts on why we should self-host on my [website](https://kumardamani.net). +If this repo has helped you, consider [sending](https://kumardamani.net/#donate) a coffee my way! -- cgit v1.2.3 From 4352c2b692b66119acd1155f150cd3071eb11310 Mon Sep 17 00:00:00 2001 From: Kumar Damani Date: Wed, 4 Jan 2023 15:46:49 -0500 Subject: more --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 989c930..73aad73 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,7 @@ This makes running automation against it easier. 3. Then you can run our playbook with the `base` tag to install all pre-requisite software. See the Install section below for getting started with running playbooks from this repo. 4. You should then setup your drives according to your needs. If you are doing ZFS, the section below might be useful. +4. Then see the Deploy section below to start deploying your apps! ### NAS Setup I recommend setting up the two drives as a ZFS mirrored pool. -- cgit v1.2.3