mirror of
https://github.com/auricom/home-cluster.git
synced 2025-09-17 18:24:14 +02:00
feat: rework ansible & secrets
This commit is contained in:
14
.sops.yaml
14
.sops.yaml
@@ -1,5 +1,11 @@
|
||||
creation_rules:
|
||||
- encrypted_regex: "^(data|stringData)$"
|
||||
pgp: >-
|
||||
19B850FBA7685A526CF11E5F9BBE834259976EE8,
|
||||
5749D0AE39445C1CCA6006DF8913091C690BDD69
|
||||
- path_regex: cluster/.*\.sops\.ya?ml
|
||||
encrypted_regex: "^(data|stringData)$"
|
||||
key_groups:
|
||||
- age:
|
||||
- age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
- path_regex: ansible/.*\.sops\.ya?ml
|
||||
unencrypted_regex: "^(kind)$"
|
||||
key_groups:
|
||||
- age:
|
||||
- age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
|
19
README.md
19
README.md
@@ -27,25 +27,20 @@ flux bootstrap github \
|
||||
--network-policy=false
|
||||
```
|
||||
|
||||
## SOPS secret from GPG key
|
||||
## SOPS secret from age key
|
||||
|
||||
```bash
|
||||
gpg \
|
||||
--export-secret-keys \
|
||||
--armor <GPG_KEY_ID> | \
|
||||
kubectl create secret generic sops-gpg \
|
||||
--namespace=flux-system \
|
||||
--from-file=sops.asc=/dev/stdin
|
||||
age-keygen -o $HOME/sops/age/key.txt
|
||||
cat $HOME/sops/age/key.txt |
|
||||
kubectl create secret generic sops-age \
|
||||
--namespace=flux-system \
|
||||
--from-file=$HOME/sops/age/key.txt=/dev/stdin
|
||||
```
|
||||
|
||||
## Encrypt kubernetes resources with sops binary
|
||||
|
||||
```bash
|
||||
sops \
|
||||
--encrypt \
|
||||
--pgp=<GPG_KEY_ID> \
|
||||
--encrypted-regex '^(data|stringData)$' \
|
||||
--in-place <FILE_PATH>
|
||||
sops --encrypt --in-place <FILE_PATH>
|
||||
```
|
||||
|
||||
## Install pre-commit hooks
|
||||
|
2
ansible/.envrc
Normal file
2
ansible/.envrc
Normal file
@@ -0,0 +1,2 @@
|
||||
#shellcheck disable=SC2148,SC2155
|
||||
export ANSIBLE_CONFIG=$(expand_path ./ansible.cfg)
|
35
ansible/ansible.cfg
Normal file
35
ansible/ansible.cfg
Normal file
@@ -0,0 +1,35 @@
|
||||
[defaults]
|
||||
# General settings
|
||||
nocows = True
|
||||
executable = /bin/bash
|
||||
stdout_callback = yaml
|
||||
force_valid_group_names = ignore
|
||||
# File/Directory settings
|
||||
log_path = ~/.ansible/ansible.log
|
||||
inventory = ./inventory
|
||||
roles_path = ~/.ansible/roles:./roles
|
||||
collections_path = ~/.ansible/collections
|
||||
remote_tmp = ~/.ansible/tmp
|
||||
local_tmp = ~/.ansible/tmp
|
||||
# Fact Caching settings
|
||||
fact_caching = jsonfile
|
||||
fact_caching_connection = ~/.ansible/facts_cache
|
||||
# SSH settings
|
||||
remote_port = 22
|
||||
timeout = 60
|
||||
host_key_checking = False
|
||||
# Plugin settings
|
||||
vars_plugins_enabled = host_group_vars,community.sops.sops
|
||||
|
||||
[inventory]
|
||||
unparsed_is_failed = true
|
||||
|
||||
[privilege_escalation]
|
||||
become = True
|
||||
|
||||
[ssh_connection]
|
||||
scp_if_ssh = smart
|
||||
retries = 3
|
||||
ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o Compression=yes -o ServerAliveInterval=15s
|
||||
pipelining = True
|
||||
control_path = %(directory)s/%%h-%%r
|
24
ansible/inventory/group_vars/all/all.sops.yml
Normal file
24
ansible/inventory/group_vars/all/all.sops.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
kind: Secret
|
||||
SECRET_DOMAIN: ENC[AES256_GCM,data:n+Lk4Mw+/akb1XA=,iv:5kXTjxflpwZM3vlkZde4S8O9RM8V0Ij5zHhmt67IKXg=,tag:AXQguN0ZVM89qpNQDXDKXA==,type:str]
|
||||
SECRET_CLUSTER_DOMAIN: ENC[AES256_GCM,data:nzhB4YHDYvQwTjRdTUGj,iv:emxp70PPzGPJP2x3LlCRRzh0gTNohnvI9Nr+f+PFZwo=,tag:m44ScVH/9hNxiYRdVx2xrA==,type:str]
|
||||
SECRET_EMAIL_DOMAIN: ENC[AES256_GCM,data:Xu0RNCdH+AUHpoq2c9Q=,iv:RxBNXZU2tXqv78Orkf/aWTrKVTHVDurnX/YldvNRl/o=,tag:DJZk/5QAnUUzeEwsRidUCQ==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0dGgya0lVNUtvMEhmWFpm
|
||||
dE8wdkppSEZiMjVteS9pZkxFaUltQ0VlUzNFCk1oVzVHTVIxVnIvL21YemtZVmJz
|
||||
a3lmMnJaNGI2NXlUKzduS1ZVa1o5amcKLS0tICtLS2pRZjk4U285TzJnV0J3MUkw
|
||||
c3JkOFZzYnpINjQ5QnNkaE9IYUdXL3MKsBelDv/z5nTYC6/1Zm8kmzqEoLBVPnhy
|
||||
v0v/6n1GksmzslbNdKhy+xtxHYrqouhc2P4hNi0R8p8u76RXERN5fg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-07-03T14:39:29Z"
|
||||
mac: ENC[AES256_GCM,data:Ny+6wcVbhfKt3lrB8mJTH29VS0ikuTBvU4Rf7dSXVWx/8y/RB+NlhY8Ul9frxH9J0QxCB3sKw0ur3OLg5FS+cuDa8QjO0MLgSDLcleHDwF7t2uiKX1RPMR1uvAlJzD/c9Meord+xfHv1XSjs80mPXuApr03o+pV1pSpf/0XgntY=,iv:Uq3+LEvQAoH1O0EYFX/gxuaIEjycPbik/Etdhpz8h2k=,tag:Btvd9va/CmOY6ruYXvdPVQ==,type:str]
|
||||
pgp: []
|
||||
unencrypted_regex: ^(kind)$
|
||||
version: 3.7.3
|
34
ansible/inventory/group_vars/all/k3s.yml
Normal file
34
ansible/inventory/group_vars/all/k3s.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
timezone: Europe/Paris
|
||||
|
||||
public_ssh_keys:
|
||||
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL+GMHgvbtf6f7xUMAQR+vZFfD/mIIfIDNX5iP8tDRXZ claude@claude-thinkpad-fedora"
|
||||
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINo7E0oAOzaq0XvUHkWvZSC8u1XxX8dDCq3bSyK2BCen claude@claude-fixe-fedora"
|
||||
|
||||
packages:
|
||||
- "https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-{{ ansible_distribution_major_version }}.noarch.rpm"
|
||||
- "https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-{{ ansible_distribution_major_version }}.noarch.rpm"
|
||||
- dnf-automatic
|
||||
- dnf-utils
|
||||
- fish
|
||||
- hdparm
|
||||
- htop
|
||||
- intel-gpu-tools
|
||||
- ipvsadm
|
||||
# TODO(ansible): Might be required for newer Intel CPU generations
|
||||
# https://ask.fedoraproject.org/t/intel-graphics-best-practices-and-settings-for-hardware-acceleration/21119
|
||||
# - intel-media-driver
|
||||
# - mesa-dri-drivers
|
||||
# - libva-intel-driver
|
||||
# - libva-intel-hybrid-driver
|
||||
# - libva-utils
|
||||
# - libva-vdpau-driver
|
||||
# - libvdpau-va-gl
|
||||
- lm_sensors
|
||||
- nano
|
||||
- nvme-cli
|
||||
- socat
|
||||
- cockpit-pcp
|
||||
|
||||
k3s_registration_address: 192.168.9.100
|
||||
k3s_become: true
|
71
ansible/inventory/group_vars/master/k3s.yml
Normal file
71
ansible/inventory/group_vars/master/k3s.yml
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
# https://rancher.com/docs/k3s/latest/en/installation/install-options/server-config/
|
||||
# https://github.com/PyratLabs/ansible-role-k3s#server-control-plane-configuration
|
||||
|
||||
# Define the host as control plane nodes
|
||||
k3s_control_node: true
|
||||
|
||||
k3s_etcd_datastore: false
|
||||
|
||||
# k3s settings for all control-plane nodes
|
||||
k3s_server:
|
||||
node-ip: "{{ ansible_host }}"
|
||||
tls-san:
|
||||
# # kube-vip
|
||||
# - "{{ kubevip_address }}"
|
||||
# haproxy
|
||||
- "{{ k3s_registration_address }}"
|
||||
docker: false
|
||||
flannel-backend: "none" # This needs to be in quotes
|
||||
disable:
|
||||
- flannel
|
||||
- traefik
|
||||
- servicelb
|
||||
- metrics-server
|
||||
- local-storage
|
||||
disable-network-policy: true
|
||||
disable-cloud-controller: true
|
||||
# Network CIDR to use for pod IPs
|
||||
cluster-cidr: "10.95.0.0/16"
|
||||
# Network CIDR to use for service IPs
|
||||
service-cidr: "10.96.0.0/16"
|
||||
# Required to monitor component with kube-prometheus-stack
|
||||
#etcd-expose-metrics: true
|
||||
kubelet-arg:
|
||||
# Enable Alpha/Beta features
|
||||
- "feature-gates=EphemeralContainers=true,MixedProtocolLBService=true,ReadWriteOncePod=true"
|
||||
# Allow pods to be rescheduled quicker in the case of a node failure
|
||||
# https://github.com/k3s-io/k3s/issues/1264
|
||||
- "node-status-update-frequency=4s"
|
||||
kube-controller-manager-arg:
|
||||
# Enable Alpha/Beta features
|
||||
- "feature-gates=EphemeralContainers=true,MixedProtocolLBService=true,ReadWriteOncePod=true"
|
||||
# Required to monitor component with kube-prometheus-stack
|
||||
- "bind-address=0.0.0.0"
|
||||
# Allow pods to be rescheduled quicker in the case of a node failure
|
||||
# https://github.com/k3s-io/k3s/issues/1264
|
||||
- "node-monitor-period=4s"
|
||||
- "node-monitor-grace-period=16s"
|
||||
- "pod-eviction-timeout=20s"
|
||||
kube-proxy-arg:
|
||||
# Enable Alpha/Beta features
|
||||
- "feature-gates=EphemeralContainers=true,MixedProtocolLBService=true,ReadWriteOncePod=true"
|
||||
# Required to monitor component with kube-prometheus-stack
|
||||
- "metrics-bind-address=0.0.0.0"
|
||||
kube-scheduler-arg:
|
||||
# Enable Alpha/Beta features
|
||||
- "feature-gates=EphemeralContainers=true,MixedProtocolLBService=true,ReadWriteOncePod=true"
|
||||
# Required to monitor component with kube-prometheus-stack
|
||||
- "bind-address=0.0.0.0"
|
||||
kube-apiserver-arg:
|
||||
# Enable Alpha/Beta features
|
||||
- "feature-gates=EphemeralContainers=true,MixedProtocolLBService=true,ReadWriteOncePod=true"
|
||||
# Required for HAProxy health-checks
|
||||
- "anonymous-auth=true"
|
||||
# Allow pods to be rescheduled quicker in the case of a node failure
|
||||
# https://github.com/k3s-io/k3s/issues/1264
|
||||
- "default-not-ready-toleration-seconds=20"
|
||||
- "default-unreachable-toleration-seconds=20"
|
||||
# Stop k3s control plane having workloads scheduled on them
|
||||
node-taint:
|
||||
- "node-role.kubernetes.io/control-plane:NoSchedule"
|
@@ -8,6 +8,9 @@ k3s_control_node: false
|
||||
# k3s settings for all worker nodes
|
||||
k3s_agent:
|
||||
node-ip: "{{ ansible_host }}"
|
||||
node-label:
|
||||
#- "kubernetes.io/role=worker"
|
||||
- "k3s-upgrade=true"
|
||||
kubelet-arg:
|
||||
# Enable Alpha/Beta features
|
||||
- "feature-gates=EphemeralContainers=true,MixedProtocolLBService=true,ReadWriteOncePod=true"
|
||||
# Allow pods to be rescheduled quicker in the case of a node failure
|
||||
# https://github.com/k3s-io/k3s/issues/1264
|
||||
- "node-status-update-frequency=4s"
|
23
ansible/inventory/host_vars/k3s-master.sops.yaml
Normal file
23
ansible/inventory/host_vars/k3s-master.sops.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
kind: Secret
|
||||
ansible_password: ENC[AES256_GCM,data:NTaCi8mqE7kAQA==,iv:yfHBgrBCf2CqWPyuVTKSwH/WUy6bkgiSoyL4hWQHG7s=,tag:e3311IReXe0RHGgttNg3pg==,type:str]
|
||||
ansible_become_pass: ENC[AES256_GCM,data:ChsZxKZ1qvICFA==,iv:vuc4eZG4Ls2CiSP/vLazCy/sZkiPjjpGPZr97CvIoX4=,tag:onYhcvFkmAMN6PTFSp0Ikg==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5azdoWUV2SWdxaDl1NXVF
|
||||
U1pvRjBncEpzM2E4TEs1MGlRbTRseG1zS0dNCnF6QmRmNU1iZ0J5K28rSlB4emFF
|
||||
ODlnU1lXVFZrTHlyTEg5VlFXUERJNGcKLS0tIGhMQUhsa0xaUVU0RTRpbkx0Vk5r
|
||||
NjJBcHVOSmUvNkt3b3I3dmJwTlJWS3MKw/hRA/oh1fiWts2aqbzTV3TTTcnSk3mi
|
||||
fsw9jQF3QRL5PGbdT6iz7j58IokV32ilJubQHtfrxus29hd/qAn0yQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-07-03T14:40:36Z"
|
||||
mac: ENC[AES256_GCM,data:c5yyBdFVs1wqDe8nsQOLeSzFv4QJ2n+VbrSf0dP5oW8593WBcdI8fXn9Q8fdY+wN2BOLn5vRdXBx7btlw0OrEIOOZ/Wz9tUxqIEUFZU6tT4TIB9g5jEqMgs2eKJmgLUoW/fcPC6QJ8ATApF6y8lI4RIV2LOItqK4AUpiVy4E2SU=,iv:kfrYGRaKY37OEl8ilrFFkRkItHpz/1VuAgWimjhujGA=,tag:STGaUOdwNlOAMcbU3Po1HQ==,type:str]
|
||||
pgp: []
|
||||
unencrypted_regex: ^(kind)$
|
||||
version: 3.7.3
|
23
ansible/inventory/host_vars/k3s-worker1.sops.yaml
Normal file
23
ansible/inventory/host_vars/k3s-worker1.sops.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
kind: Secret
|
||||
ansible_password: ENC[AES256_GCM,data:AihMvIUjgEpCjg==,iv:Bk9uFrbhOvlQvoYaJz+JhtMJTAiQ0u9TcaS8eKO0+fE=,tag:R2sLCjH/my9kcsu4Ddg9jg==,type:str]
|
||||
ansible_become_pass: ENC[AES256_GCM,data:nR/Wkn8NqM3vaA==,iv:iV8c6Qg59qKtHoaQReUTX+KDB+iSboxpSM/K8+gcZvQ=,tag://89MQ4jmQPib/D595YTbA==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlZSs4aVZ5VGdyVllEMXl3
|
||||
c2NGS2d0dkd4NVZlSVlBd2V3RVEzQ2FiaHlrCld0SkNKUjcvRHNEQ1dZZFUzM014
|
||||
ejd5QW5uUzJmMERLR2h4R2M3UmdKWU0KLS0tIFdYOStkVG40TXIzVjRkK0RzZStj
|
||||
UmhGcmVidTVKbWQ5VVpHSklYN2NyWGMKsfv/KG02qk3EJoNJQ9HNl1iyfyic6Puf
|
||||
5owrc62PfohWnLVQby9SaVK80PJVaMRU/kcHIJvbt1Iv2f47qpKczg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-07-03T14:40:40Z"
|
||||
mac: ENC[AES256_GCM,data:6BqgWJTOzQKwu6Mr7/2WemzOmFNnIilSLH9LPG01UtvaO7FnOQXV1ezgYntKdSXGJWza/pvvqDURaBT7O7Rwv5kR25B6Fo3XWdVSuTLf+N4fGnWKiINaa6UjZhosm5KLs7VB0I3eiBTcHrxqb9jupgPkUErwy0H0LT8yLYRGpe8=,iv:kXeAB7zUoZoZPgEntWV80DNKSEiFiH4xQtbYpStO36U=,tag:gWusG9MGl+bYcjYfQGMbWA==,type:str]
|
||||
pgp: []
|
||||
unencrypted_regex: ^(kind)$
|
||||
version: 3.7.3
|
23
ansible/inventory/host_vars/k3s-worker2.sops.yaml
Normal file
23
ansible/inventory/host_vars/k3s-worker2.sops.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
kind: Secret
|
||||
ansible_password: ENC[AES256_GCM,data:495JSVNY5Rn0hg==,iv:ZvJb1M4Ys8FkQpekm5jnGWKE5q63Z44OUhhtYWsJUvQ=,tag:KxgvJbsEMsdYu59yCOCjMg==,type:str]
|
||||
ansible_become_pass: ENC[AES256_GCM,data:O8lTma7A2n6+5g==,iv:ggmSecFPtTI9vy81of5I6AHnRX2YWOw0VtVldv4PZmo=,tag:IfIuN8xcKHBF6Ojlmki5Tw==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0d21nNHZQRkloNnd1M2xF
|
||||
RlJCUzBZK04rQ1RSa0hFSXUrVTlzK0V1dEdjCkg0ZnVJNGJOZjN3RlZ2RGRmRFdV
|
||||
akRPQzhwN3NqNHJlK0o1VVFncDVnd1kKLS0tIDhhRGlhNXJmanM5amR6eHZERElj
|
||||
RndiYkJFaWZuUmVIU3JwSWYzTFZlS3cKHFe4yce/091eEvtrSBYggNgyO88eHA4s
|
||||
3TvjHmS7tLv7BnBAT9LLcQVSIW0UOszzF3PvVWIqFqzB/wn0j370kw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-07-03T14:40:42Z"
|
||||
mac: ENC[AES256_GCM,data:qFIsrbqI+c3fe88H40KkWhwOnZ2aePoorpfxeTjhBtPviT4jBMvIGYZKULCehcdULNMxe7QWuPWsdYY/o5ruqZC49/OrV9qI0XVU6gdiCsM1jcXXiyFkVFfMoMhj5c5yAIMoUKRWbZe2kFtJxaG7ng8VusMgCc9f7LofWiFToVo=,iv:BI2hEL/AsaZoZ4RL7QNy4vins877XgZwxCdJ0ciFEUo=,tag:7tOEfmkFEApTy5wIgJLEBA==,type:str]
|
||||
pgp: []
|
||||
unencrypted_regex: ^(kind)$
|
||||
version: 3.7.3
|
23
ansible/inventory/host_vars/k3s-worker3.sops.yaml
Normal file
23
ansible/inventory/host_vars/k3s-worker3.sops.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
kind: Secret
|
||||
ansible_password: ENC[AES256_GCM,data:n0ASYgah4hAFvw==,iv:P0OPjAGh4AWkw0HUpBNEom6twa3sAXsh0Ei+2UDj/qo=,tag:GNcmaw2BQr5TV755NL/0vw==,type:str]
|
||||
ansible_become_pass: ENC[AES256_GCM,data:a2wZnzPgf91HvQ==,iv:8wIjFmwSkYZIZmLLhvZTG1EnMmNffuSoPkpao6Kk9wI=,tag:gta1yPH1tRzBdViIO9WOAg==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQL2pJWVRDU0lBVVgxNkd6
|
||||
MStqdFRFNGdwTEpUWUxEaVVMUVBkY2RXWFUwCmJmbGZnMzVPZjhQMWh0eWhybXdi
|
||||
K1FIa1YrNDZjMnhONDBiSEFtTW80WlkKLS0tIHJJTFpINUowclNUZXVsa2I1Vjdw
|
||||
NkhyZm5SVnlBYWxlajh6NjV0OVBCSE0Kl6ovgsGkzq4XetwG5b77mvztpa3bD5ej
|
||||
mWlPbSV66yw4eENVuDtZRX5/lrnbW7EqkwjfGoEJ9YGA7ya0G6IVQw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-07-03T14:40:44Z"
|
||||
mac: ENC[AES256_GCM,data:/AA8sbAxsYhGAad8/ymYq0YgzwmNvnnwK+p9J7+NUpFC9YGWwuR/dV8oxKzqOs/zEzFTwyBTvOrGeQ59xyJ/Id/xSt5Av0FTmrOXQxFwIOsMUsH5RP8khQpp9yO1c2cvxwNLi1oWGzLLE63Zl2JwutQdTVH0KgibPhtdL0sV8eQ=,iv:rTpWgrMAZrCymFqKGcEGOyQJdPAw/SmeW8vdVNX/Ptg=,tag:rlg3dcQhVwcXUKkEc4Jdww==,type:str]
|
||||
pgp: []
|
||||
unencrypted_regex: ^(kind)$
|
||||
version: 3.7.3
|
23
ansible/inventory/host_vars/truenas-remote.sops.yaml
Normal file
23
ansible/inventory/host_vars/truenas-remote.sops.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
kind: Secret
|
||||
root_api_key: ENC[AES256_GCM,data:e+g6jvxD9kBSYVbzGXR0QZZMAnxndPu04Dhs3UjNsjHyq+GQRlapPJDQmnTWFa11KaEK3lOiSmU4yxcRjbgG2t3a,iv:mLG+dFHrmndRm5fT4KU+TIOMiAg/urQ4Zv3YaRaoVlg=,tag:DXTWollNdF4o2Pe2qdyufw==,type:str]
|
||||
ansible_host: ENC[AES256_GCM,data:ldsDTnydWPMnAnOiSlVrkiiL6w==,iv:luNgXdV3uBRaGzBIlw4E5UrZqKBaakgwc+9YC9xXInM=,tag:MldHmJpsOqe7oJMA83Xm9g==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPVy9DRjhqOW05Wm4rNXZo
|
||||
bFJxem9UZjNSQW5UaTRZaWQ1clZQSHJrNHpVCmo3Y0RPd1BRRC9ZZHJ0SndSUXJv
|
||||
UkpPWTNOUWFPL1hCUGJrTFBPZml5QncKLS0tIGI5UUJKMXR0d1d3ZzRDSURuWVFl
|
||||
ZFlyQ1lGbnVPaSs4cytQYzNwRnJabmcKP0ogZqsaoD6heCqmObwttBgE039aLqe2
|
||||
R55NPkQJJyFSbDbdDmPApE4IwtXay54QGw2RR4AxOZW4G2dWhdzP3w==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-07-04T18:20:37Z"
|
||||
mac: ENC[AES256_GCM,data:IzuN61G8NkZwqNDkIQQPNVODoxgPQieRlSTcInajbBUdHHdVkFRlyLI2INoGd1RDDV06NsmJPM3Yj6fRlWlF4iRCO60cEHgnSyq3FRcFa6oKe9f5p5hmIBin8KMIAQOinNf8/4kqUpkZOFeY/fViBayin1cYgJ2MlMYtZRFVt0A=,iv:2DNQdjHRbtTlTgSVOrS/UTeSaVOhldbf+ek2e1gNv5s=,tag:ef/4Xtbf/021Z5NHv8Up9A==,type:str]
|
||||
pgp: []
|
||||
unencrypted_regex: ^(kind)$
|
||||
version: 3.7.3
|
3
ansible/inventory/host_vars/truenas-remote.yaml
Normal file
3
ansible/inventory/host_vars/truenas-remote.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
main_nas: false
|
||||
pool_name: vol1
|
||||
snapshots_interval: "daily:14,weekly:12,monthly:12,yearly:3"
|
22
ansible/inventory/host_vars/truenas.sops.yaml
Normal file
22
ansible/inventory/host_vars/truenas.sops.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
kind: Secret
|
||||
root_api_key: ENC[AES256_GCM,data:Fhj1MGeHxe/A6O7uVjMrCEu7J4rsiWrhbXgbAenb5CunoRPu0XLV/227WAFc4wFkboFNnt3bjzugvdvM5w/0JSry,iv:7uuHkrSKGShhIso8RgIJsOSYOxBiyyM/D5Dg+IGDh1Y=,tag:dP4gfIIUAEBUm91h5IHSug==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtVllLOFcwWXVoNXZobFF1
|
||||
VGJmczlkL1V3blhvcnFzN2V6S1B1Ui81alRNClVEUWFmSWxKbENBRVZJN01PSWM5
|
||||
d2M3OHFhOGpadEdrWUIxZGpMNTR2aVkKLS0tIE84ZkxzTlBpZVlqR2xQRmM0V0ZR
|
||||
aG5zWW1XclBOS2cxMkwzZ3c1R1psNGsKzeSHHV7AYXCUNiiXJlBRFVWMZtfK3naj
|
||||
VRtF22+DYfjumQuwam2ZzhdLQ//1ciHnkJc58dKeTbYUHzC+fWpaZQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-07-03T14:40:48Z"
|
||||
mac: ENC[AES256_GCM,data:ple3qtcoOwSBg0AbkZSFAwySlvBYvk5/6jx3rsj1lptNDNGQyGd+X9oYqtAN+f58Q8y2Wbn+KwVWpKTvFzX6lEedv6iR0rFpPW6mMTX8Py8vboD2hCp96hpBMtNqf4JLIzPQoc5WG5kK88KDc17/M2HaQFPX56YSCHn0ABnH8Vg=,iv:o5WZqE3doTnpbFmBP77U6yKRvmCPgXVCjYQ0Z2VaR0I=,tag:e72lHlzwLX90pz36RJXsuw==,type:str]
|
||||
pgp: []
|
||||
unencrypted_regex: ^(kind)$
|
||||
version: 3.7.3
|
4
ansible/inventory/host_vars/truenas.yaml
Normal file
4
ansible/inventory/host_vars/truenas.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
main_nas: true
|
||||
pool_name: storage
|
||||
service_s3: true
|
||||
snapshots_interval: "daily:14,weekly:12,monthly:3"
|
40
ansible/inventory/hosts.yml
Normal file
40
ansible/inventory/hosts.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
all:
|
||||
hosts:
|
||||
localhost:
|
||||
ansible_connection: local
|
||||
ansible_python_interpreter: /usr/bin/python3
|
||||
coreelec:
|
||||
ansible_user: root
|
||||
children:
|
||||
truenas-instances:
|
||||
hosts:
|
||||
truenas:
|
||||
truenas-remote:
|
||||
ansible_port: 35875
|
||||
vars:
|
||||
ansible_user: homelab
|
||||
kubernetes:
|
||||
children:
|
||||
master:
|
||||
hosts:
|
||||
k3s-master:
|
||||
ansible_host: 192.168.9.100
|
||||
ansible_user: fedora
|
||||
ansible_ssh_port: 22
|
||||
worker:
|
||||
hosts:
|
||||
k3s-worker1:
|
||||
ansible_host: 192.168.9.105
|
||||
rook_devices:
|
||||
- /dev/nvme0n1
|
||||
k3s-worker2:
|
||||
ansible_host: 192.168.9.106
|
||||
rook_devices:
|
||||
- /dev/nvme0n1
|
||||
k3s-worker3:
|
||||
ansible_host: 192.168.9.107
|
||||
rook_devices:
|
||||
- /dev/nvme0n1
|
||||
vars:
|
||||
ansible_user: fedora
|
17
ansible/playbooks/bootstrap_ansible.yml
Normal file
17
ansible/playbooks/bootstrap_ansible.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
- name: Boostrap host to enable Ansible playbooks
|
||||
hosts: all
|
||||
become: true
|
||||
become_user: root
|
||||
vars:
|
||||
python_pwd: /usr/bin/python
|
||||
python_package: python3
|
||||
tasks:
|
||||
- name: Check for Python
|
||||
raw: test -e {{ python_pwd }}
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
register: check_python
|
||||
- name: Install Python
|
||||
raw: pkg install -y {{ python_package }}
|
||||
when: check_python.rc != 0
|
@@ -1,13 +1,13 @@
|
||||
---
|
||||
- hosts:
|
||||
- server-nodes
|
||||
- worker-nodes
|
||||
- master
|
||||
- worker
|
||||
become: true
|
||||
gather_facts: true
|
||||
any_errors_fatal: true
|
||||
pre_tasks:
|
||||
- name: Pausing for 5 seconds...
|
||||
- name: Pausing for 2 seconds...
|
||||
pause:
|
||||
seconds: 5
|
||||
seconds: 2
|
||||
roles:
|
||||
- ubuntu
|
||||
- installation.k3s
|
29
ansible/playbooks/cluster-nuke.yml
Normal file
29
ansible/playbooks/cluster-nuke.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
- hosts:
|
||||
- master
|
||||
- worker
|
||||
become: true
|
||||
gather_facts: true
|
||||
any_errors_fatal: true
|
||||
pre_tasks:
|
||||
- name: Pausing for 2 seconds...
|
||||
pause:
|
||||
seconds: 2
|
||||
- name: Uninstall k3s
|
||||
include_role:
|
||||
name: xanmanning.k3s
|
||||
public: true
|
||||
vars:
|
||||
k3s_state: uninstalled
|
||||
tasks:
|
||||
- name: Gather list of CNI files
|
||||
ansible.builtin.find:
|
||||
paths: /etc/cni/net.d
|
||||
patterns: "*"
|
||||
hidden: true
|
||||
register: directory_contents
|
||||
- name: Delete CNI files
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.path }}"
|
||||
state: absent
|
||||
loop: "{{ directory_contents.files }}"
|
167
ansible/playbooks/cluster-prepare.yml
Normal file
167
ansible/playbooks/cluster-prepare.yml
Normal file
@@ -0,0 +1,167 @@
|
||||
---
|
||||
- hosts:
|
||||
- master
|
||||
- worker
|
||||
become: true
|
||||
gather_facts: true
|
||||
any_errors_fatal: true
|
||||
pre_tasks:
|
||||
- name: Pausing for 2 seconds...
|
||||
pause:
|
||||
seconds: 2
|
||||
tasks:
|
||||
- name: Locale
|
||||
block:
|
||||
- name: Locale | Set timezone
|
||||
community.general.timezone:
|
||||
name: "{{ timezone | default('America/New_York') }}"
|
||||
- name: Networking
|
||||
block:
|
||||
- name: Networking | Set hostname to inventory hostname
|
||||
ansible.builtin.hostname:
|
||||
name: "{{ inventory_hostname }}"
|
||||
when:
|
||||
- ansible_hostname != inventory_hostname
|
||||
- name: Networking | Update /etc/hosts to include inventory hostname
|
||||
ansible.builtin.blockinfile:
|
||||
path: /etc/hosts
|
||||
block: |
|
||||
127.0.1.1 {{ inventory_hostname }}
|
||||
- name: Packages
|
||||
block:
|
||||
- name: Packages | Improve dnf performance
|
||||
ansible.builtin.blockinfile:
|
||||
path: /etc/dnf/dnf.conf
|
||||
block: |
|
||||
defaultyes=True
|
||||
deltarpm=True
|
||||
install_weak_deps=False
|
||||
max_parallel_downloads={{ ansible_processor_vcpus | default('8') }}
|
||||
- name: Packages | Import rpmfusion keys
|
||||
ansible.builtin.rpm_key:
|
||||
state: present
|
||||
key: "{{ item }}"
|
||||
loop:
|
||||
- https://rpmfusion.org/keys?action=AttachFile&do=get&target=RPM-GPG-KEY-rpmfusion-free-fedora-2020
|
||||
- https://rpmfusion.org/keys?action=AttachFile&do=get&target=RPM-GPG-KEY-rpmfusion-nonfree-fedora-2020
|
||||
- name: Packages | Install required packages
|
||||
ansible.builtin.dnf:
|
||||
name: "{{ packages | default([]) }}"
|
||||
state: present
|
||||
update_cache: true
|
||||
- name: Packages | Remove leaf packages
|
||||
ansible.builtin.dnf:
|
||||
autoremove: true
|
||||
- name: Packages | Enable automatic downloads of updates
|
||||
ansible.builtin.systemd:
|
||||
service: dnf-automatic-download.timer
|
||||
enabled: true
|
||||
state: started
|
||||
- name: User Configuration
|
||||
block:
|
||||
- name: User Configuration | Change shell to fish
|
||||
ansible.builtin.user:
|
||||
name: "{{ item }}"
|
||||
shell: /usr/bin/fish
|
||||
loop:
|
||||
- root
|
||||
- fedora
|
||||
- name: User Configuration | Disable password sudo
|
||||
ansible.builtin.lineinfile:
|
||||
dest: /etc/sudoers
|
||||
state: present
|
||||
regexp: "^%wheel"
|
||||
line: "%wheel ALL=(ALL) NOPASSWD: ALL"
|
||||
validate: visudo -cf %s
|
||||
become: true
|
||||
- name: User Configuration | Add additional SSH public keys
|
||||
ansible.posix.authorized_key:
|
||||
user: "{{ ansible_user }}"
|
||||
key: "{{ item }}"
|
||||
loop: "{{ public_ssh_keys | default([]) }}"
|
||||
- name: System Configuration (1)
|
||||
block:
|
||||
- name: System Configuration (1) | Configure smartd
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/smartd.conf
|
||||
mode: 0644
|
||||
content: DEVICESCAN -a -o on -S on -n standby,q -s (S/../.././02|L/../../6/03) -W 4,35,40
|
||||
notify: Restart smartd
|
||||
- name: System Configuration (1) | Disable firewalld
|
||||
ansible.builtin.systemd:
|
||||
service: firewalld.service
|
||||
enabled: false
|
||||
masked: true
|
||||
state: stopped
|
||||
- name: System Configuration (1) | Enable fstrim
|
||||
ansible.builtin.systemd:
|
||||
service: fstrim.timer
|
||||
enabled: true
|
||||
- name: System Configuration (1) | Enable chronyd
|
||||
ansible.builtin.systemd:
|
||||
service: chronyd
|
||||
enabled: true
|
||||
- name: System Configuration (2)
|
||||
block:
|
||||
- name: System Configuration (2) | Enable kernel modules now
|
||||
community.general.modprobe:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
loop: [br_netfilter, overlay, rbd]
|
||||
- name: System Configuration (2) | Enable kernel modules on boot
|
||||
ansible.builtin.copy:
|
||||
mode: 0644
|
||||
content: "{{ item }}"
|
||||
dest: "/etc/modules-load.d/{{ item }}.conf"
|
||||
loop: [br_netfilter, overlay, rbd]
|
||||
- name: System Configuration (2) | Set sysctls
|
||||
ansible.posix.sysctl:
|
||||
name: "{{ item.key }}"
|
||||
value: "{{ item.value }}"
|
||||
sysctl_file: /etc/sysctl.d/99-kubernetes.conf
|
||||
reload: true
|
||||
with_dict: "{{ sysctl_config }}"
|
||||
vars:
|
||||
sysctl_config:
|
||||
net.ipv4.ip_forward: 1
|
||||
net.ipv4.conf.all.forwarding: 1
|
||||
net.ipv4.conf.all.rp_filter: 0
|
||||
net.ipv4.conf.default.rp_filter: 0
|
||||
net.ipv6.conf.all.forwarding: 1
|
||||
net.bridge.bridge-nf-call-iptables: 1
|
||||
net.bridge.bridge-nf-call-ip6tables: 1
|
||||
fs.inotify.max_user_watches: 524288
|
||||
fs.inotify.max_user_instances: 512
|
||||
- name: System Configuration (2) | Disable swap
|
||||
ansible.builtin.dnf:
|
||||
name: zram-generator-defaults
|
||||
state: absent
|
||||
- name: System Configuration (2) | Disable SELinux
|
||||
ansible.posix.selinux:
|
||||
state: disabled
|
||||
- name: System Configuration (2) | Disable mitigations
|
||||
ansible.builtin.replace:
|
||||
path: /etc/default/grub
|
||||
regexp: '^(GRUB_CMDLINE_LINUX=(?:(?![" ]{{ item.key | regex_escape }}=).)*)(?:[" ]{{ item.key | regex_escape }}=\S+)?(.*")$'
|
||||
replace: '\1 {{ item.key }}={{ item.value }}\2'
|
||||
with_dict: "{{ grub_config }}"
|
||||
vars:
|
||||
grub_config:
|
||||
mitigations: "off"
|
||||
register: grub_status
|
||||
- name: System Configuration (2) | Reconfigure grub and initramfs
|
||||
ansible.builtin.command: "{{ item }}"
|
||||
loop:
|
||||
- grub2-mkconfig -o /boot/grub2/grub.cfg
|
||||
- dracut --force --regenerate-all -v
|
||||
when: grub_status.changed
|
||||
notify: Reboot
|
||||
|
||||
handlers:
|
||||
- name: Reboot
|
||||
ansible.builtin.reboot:
|
||||
- name: Restart smartd
|
||||
ansible.builtin.service:
|
||||
name: smartd.service
|
||||
enabled: true
|
||||
state: restarted
|
7
ansible/playbooks/coreelec.yml
Normal file
7
ansible/playbooks/coreelec.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- hosts: coreelec
|
||||
become: true
|
||||
gather_facts: true
|
||||
any_errors_fatal: true
|
||||
roles:
|
||||
- role: coreelec
|
33
ansible/playbooks/rook-nuke.yml
Normal file
33
ansible/playbooks/rook-nuke.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
- hosts:
|
||||
- worker
|
||||
become: true
|
||||
gather_facts: true
|
||||
any_errors_fatal: true
|
||||
pre_tasks:
|
||||
- name: Pausing for 5 seconds...
|
||||
pause:
|
||||
seconds: 5
|
||||
tasks:
|
||||
- name: Reset disks
|
||||
block:
|
||||
- name: Remove /var/lib/rook
|
||||
ansible.builtin.file:
|
||||
state: absent
|
||||
path: "/var/lib/rook"
|
||||
- name: Zap the drives
|
||||
ansible.builtin.shell: >
|
||||
sgdisk --zap-all {{ item }} || true
|
||||
loop:
|
||||
- "{{ rook_devices | default([]) }}"
|
||||
- name: Remove lvm partitions
|
||||
ansible.builtin.shell: "{{ item }}"
|
||||
loop:
|
||||
- ls /dev/mapper/ceph--* | xargs -I% -- fuser --kill %
|
||||
- ls /dev/mapper/ceph--* | xargs -I% -- dmsetup clear %
|
||||
- ls /dev/mapper/ceph--* | xargs -I% -- dmsetup remove -f %
|
||||
- ls /dev/mapper/ceph--* | xargs -I% -- rm -rf %
|
||||
- name: Wipe the block device
|
||||
ansible.builtin.command: "wipefs -af {{ item }}"
|
||||
with_items:
|
||||
- "{{ rook_devices | default([]) }}"
|
7
ansible/playbooks/truenas.yml
Normal file
7
ansible/playbooks/truenas.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- hosts: truenas-instances
|
||||
become: false
|
||||
gather_facts: true
|
||||
any_errors_fatal: true
|
||||
roles:
|
||||
- role: truenas
|
7
ansible/playbooks/workstation.yml
Normal file
7
ansible/playbooks/workstation.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- hosts: localhost
|
||||
become: false
|
||||
gather_facts: true
|
||||
any_errors_fatal: true
|
||||
roles:
|
||||
- role: workstation
|
13
ansible/requirements.yml
Normal file
13
ansible/requirements.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
collections:
|
||||
- name: ansible.posix
|
||||
version: 1.4.0
|
||||
- name: community.general
|
||||
version: 5.2.0
|
||||
- name: kubernetes.core
|
||||
version: 2.3.2
|
||||
- name: community.sops
|
||||
version: 1.2.3
|
||||
roles:
|
||||
- src: xanmanning.k3s
|
||||
version: v3.2.0
|
6
ansible/roles/coreelec/defaults/main.yml
Normal file
6
ansible/roles/coreelec/defaults/main.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
root_path: /storage
|
||||
nfs_shares:
|
||||
- music
|
||||
- photo
|
||||
- video
|
16
ansible/roles/coreelec/files/backup.bash
Normal file
16
ansible/roles/coreelec/files/backup.bash
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Variables
|
||||
FLAG_NOTIF=false
|
||||
|
||||
DATE=`date +%Y%m%d%H%M`
|
||||
BACKUP_PATH="/storage/backup"
|
||||
|
||||
cd /
|
||||
|
||||
tar cvf ${BACKUP_PATH}/${DATE}.tar \
|
||||
storage/.kodi storage/.config storage/.cache storage/.ssh \
|
||||
--exclude=storage/.kodi/userdata/Thumbnails
|
||||
|
||||
# Keep the last 5 backups on disk
|
||||
find ${BACKUP_PATH}/*.tar -mtime +5 -type f -delete
|
13
ansible/roles/coreelec/tasks/backup.yml
Normal file
13
ansible/roles/coreelec/tasks/backup.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: backup | copy script
|
||||
ansible.builtin.copy:
|
||||
src: backup.bash
|
||||
dest: /storage/backup.bash
|
||||
mode: 0755
|
||||
|
||||
- name: backup | crontab
|
||||
ansible.builtin.cron:
|
||||
name: "daily backup"
|
||||
minute: "14"
|
||||
hour: "4"
|
||||
job: "/storage/backup.bash && curl -fsS -m 10 --retry 5 -o /dev/null https://healthchecks.{{ SECRET_CLUSTER_DOMAIN }}/ping/aae30879-cfdf-4b90-889f-d4ff69dd8aad"
|
8
ansible/roles/coreelec/tasks/main.yml
Normal file
8
ansible/roles/coreelec/tasks/main.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- ansible.builtin.include_tasks: backup.yml
|
||||
tags:
|
||||
- backup
|
||||
|
||||
- ansible.builtin.include_tasks: nfs.yml
|
||||
tags:
|
||||
- nfs
|
19
ansible/roles/coreelec/tasks/nfs.yml
Normal file
19
ansible/roles/coreelec/tasks/nfs.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
- name: nfs | create directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ root_path }}/mnt/{{ item }}"
|
||||
state: directory
|
||||
loop: "{{ nfs_shares }}"
|
||||
|
||||
- name: nfs | create system.d services
|
||||
ansible.builtin.template:
|
||||
src: "storage-nfs.mount"
|
||||
dest: "/storage/.config/system.d/storage-mnt-{{ item }}.mount"
|
||||
loop: "{{ nfs_shares }}"
|
||||
|
||||
- name: nfs | activate system.d services
|
||||
ansible.builtin.systemd:
|
||||
name: storage-mnt-{{ item }}.mount
|
||||
state: started
|
||||
enabled: yes
|
||||
loop: "{{ nfs_shares }}"
|
16
ansible/roles/coreelec/templates/storage-nfs.mount
Normal file
16
ansible/roles/coreelec/templates/storage-nfs.mount
Normal file
@@ -0,0 +1,16 @@
|
||||
#====================================================
|
||||
[Unit]
|
||||
Description=TrueNAS nfs share {{ item }}
|
||||
Requires=network-online.service
|
||||
After=network-online.service
|
||||
Before=kodi.service
|
||||
|
||||
[Mount]
|
||||
What=truenas:/mnt/storage/{{ item }}
|
||||
Where=/storage/mnt/{{ item }}
|
||||
Options=
|
||||
Type=nfs
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
#====================================================
|
2
ansible/roles/installation.k3s/defaults/main.yml
Normal file
2
ansible/roles/installation.k3s/defaults/main.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
k3s_etcd_s3: false
|
50
ansible/roles/installation.k3s/tasks/k3s.yml
Normal file
50
ansible/roles/installation.k3s/tasks/k3s.yml
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
- name: Check if cluster is installed
|
||||
ansible.builtin.stat:
|
||||
path: /etc/rancher/k3s/config.yaml
|
||||
register: k3s_check_installed
|
||||
check_mode: false
|
||||
|
||||
- name: Set manifest facts
|
||||
ansible.builtin.set_fact:
|
||||
k3s_server_manifests_templates: []
|
||||
k3s_server_manifests_urls: []
|
||||
when: k3s_check_installed.stat.exists
|
||||
|
||||
- name: Install Kubernetes
|
||||
include_role:
|
||||
name: xanmanning.k3s
|
||||
public: true
|
||||
vars:
|
||||
k3s_state: installed
|
||||
|
||||
- name: Copy kubeconfig to provision folder
|
||||
run_once: true
|
||||
ansible.builtin.fetch:
|
||||
src: "/etc/rancher/k3s/k3s.yaml"
|
||||
dest: "{{ playbook_dir }}/../../../cluster/kubeconfig"
|
||||
flat: true
|
||||
when:
|
||||
- k3s_control_node is defined
|
||||
- k3s_control_node
|
||||
|
||||
- name: Update kubeconfig with the right IPv4 address
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
run_once: true
|
||||
ansible.builtin.replace:
|
||||
path: "{{ playbook_dir }}/../../../cluster/kubeconfig"
|
||||
regexp: "https://127.0.0.1:6443"
|
||||
replace: "https://{{ k3s_registration_address }}:6443"
|
||||
|
||||
- name: Remove deployed manifest templates
|
||||
ansible.builtin.file:
|
||||
path: "{{ k3s_server_manifests_dir }}/{{ item | basename | regex_replace('\\.j2$', '') }}"
|
||||
state: absent
|
||||
loop: "{{ k3s_server_manifests_templates | default([]) }}"
|
||||
|
||||
- name: Remove deployed manifest urls
|
||||
ansible.builtin.file:
|
||||
path: "{{ k3s_server_manifests_dir }}/{{ item.filename }}"
|
||||
state: absent
|
||||
loop: "{{ k3s_server_manifests_urls | default([]) }}"
|
4
ansible/roles/installation.k3s/tasks/main.yml
Normal file
4
ansible/roles/installation.k3s/tasks/main.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
- import_tasks: k3s.yml
|
||||
tags:
|
||||
- k3s
|
@@ -4,5 +4,6 @@ kind: BGPConfiguration
|
||||
metadata:
|
||||
name: default
|
||||
spec:
|
||||
asNumber: {{ calico_bgp_as_number }}
|
||||
serviceExternalIPs:
|
||||
- cidr: {{ calico.bgp.externalIPs }}
|
||||
- cidr: "{{ calico_bgp_external_ips }}"
|
@@ -4,5 +4,5 @@ kind: BGPPeer
|
||||
metadata:
|
||||
name: global
|
||||
spec:
|
||||
peerIP: {{ calico.bgp.peer }}
|
||||
asNumber: {{ calico.bgp.as }}
|
||||
peerIP: {{ calico_bgp_peer_ip }}
|
||||
asNumber: {{ calico_bgp_as_number }}
|
@@ -0,0 +1,18 @@
|
||||
---
|
||||
apiVersion: operator.tigera.io/v1
|
||||
kind: Installation
|
||||
metadata:
|
||||
name: default
|
||||
spec:
|
||||
registry: quay.io
|
||||
imagePath: calico
|
||||
calicoNetwork:
|
||||
# Note: The ipPools section cannot be modified post-install.
|
||||
ipPools:
|
||||
- blockSize: 26
|
||||
cidr: "{{ k3s_server['cluster-cidr'] }}"
|
||||
encapsulation: "{{ calico_encapsulation }}"
|
||||
natOutgoing: Enabled
|
||||
nodeSelector: all()
|
||||
nodeMetricsPort: 9091
|
||||
typhaMetricsPort: 9093
|
14
ansible/roles/installation.k3s/vars/main/calico.yml
Normal file
14
ansible/roles/installation.k3s/vars/main/calico.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
# -- Encapsulation type
|
||||
calico_encapsulation: "None"
|
||||
# -- BGP Peer IP
|
||||
# -- (usually your router IP address)
|
||||
calico_bgp_peer_ip: 192.168.8.1
|
||||
# -- BGP Autonomous System Number
|
||||
# -- (must be the same across all BGP peers)
|
||||
calico_bgp_as_number: 64512
|
||||
# -- BGP Network you want services to consume
|
||||
# -- (this network should not exist or be defined anywhere in your network)
|
||||
calico_bgp_external_ips: 192.168.169.0/24
|
||||
# -- CIDR of the host node interface Calico should use
|
||||
calico_node_cidr: 10.69.0.0/16
|
53
ansible/roles/installation.k3s/vars/main/k3s.yml
Normal file
53
ansible/roles/installation.k3s/vars/main/k3s.yml
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
#
|
||||
# Below vars are for the xanmanning.k3s role
|
||||
# ...see https://github.com/PyratLabs/ansible-role-k3s#globalcluster-variables
|
||||
#
|
||||
|
||||
# Use a specific version of k3s
|
||||
# renovate: datasource=github-releases depName=k3s-io/k3s
|
||||
k3s_release_version: "v1.24.2+k3s1"
|
||||
|
||||
# -- Install using hard links rather than symbolic links.
|
||||
# ...if you are using the system-upgrade-controller you will need to
|
||||
# use hard links rather than symbolic links as the controller will
|
||||
# not be able to follow symbolic links.
|
||||
k3s_install_hard_links: true
|
||||
|
||||
# -- Escalate user privileges for all tasks.
|
||||
k3s_become: true
|
||||
|
||||
# -- Enable debugging
|
||||
k3s_debug: false
|
||||
|
||||
# -- Enabled embedded etcd
|
||||
# k3s_etcd_datastore: false
|
||||
|
||||
# -- Enable for single or even number of masters
|
||||
k3s_use_unsupported_config: false
|
||||
|
||||
# -- /var/lib/rancher/k3s/server/manifests
|
||||
k3s_server_manifests_templates:
|
||||
- "calico/calico-installation.yaml.j2"
|
||||
- "calico/calico-bgpconfiguration.yaml.j2"
|
||||
- "calico/calico-bgppeer.yaml.j2"
|
||||
|
||||
# -- /var/lib/rancher/k3s/server/manifests
|
||||
k3s_server_manifests_urls:
|
||||
- url: https://docs.projectcalico.org/archive/v3.23/manifests/tigera-operator.yaml
|
||||
filename: tigera-operator.yaml
|
||||
|
||||
# -- /etc/rancher/k3s/registries.yaml
|
||||
# k3s_registries:
|
||||
# mirrors:
|
||||
# "docker.io":
|
||||
# endpoint:
|
||||
# - "https://mirror.{{ SECRET_PRIVATE_DOMAIN }}"
|
||||
# "*":
|
||||
# endpoint:
|
||||
# - "https://mirror.{{ SECRET_PRIVATE_DOMAIN }}"
|
||||
# config:
|
||||
# "https://registry.{{ SECRET_PRIVATE_DOMAIN }}":
|
||||
# auth:
|
||||
# username: "{{ SECRET_NEXUS_USERNAME }}"
|
||||
# password: "{{ SECRET_NEXUS_PASSWORD }}"
|
9
ansible/roles/truenas/defaults/main.yml
Normal file
9
ansible/roles/truenas/defaults/main.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
homelab_homedir: "/mnt/{{ pool_name }}/home/homelab"
|
||||
backups_dir: "/mnt/{{ pool_name }}/backups/"
|
||||
telegraf_dir: "{{ homelab_homedir }}/telegraf"
|
||||
scripts_dir: "{{ homelab_homedir }}/scripts"
|
||||
certificates_dir: "{{ homelab_homedir }}/letsencrypt/{{ SECRET_DOMAIN }}"
|
||||
|
||||
ping_ip: 192.168.8.1
|
||||
wg_interface: wg0-client
|
||||
dns_hostname: services.{{ SECRET_DOMAIN }}
|
240
ansible/roles/truenas/files/scripts/certificates_deploy.py
Normal file
240
ansible/roles/truenas/files/scripts/certificates_deploy.py
Normal file
@@ -0,0 +1,240 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Import and activate a SSL/TLS certificate into FreeNAS 11.1 or later
|
||||
Uses the FreeNAS API to make the change, so everything's properly saved in the config
|
||||
database and captured in a backup.
|
||||
|
||||
Requires paths to the cert (including the any intermediate CA certs) and private key,
|
||||
and username, password, and FQDN of your FreeNAS system.
|
||||
|
||||
Your private key should only be readable by root, so this script must run with root
|
||||
privileges. And, since it contains your root password, this script itself should
|
||||
only be readable by root.
|
||||
|
||||
Source: https://github.com/danb35/deploy-freenas
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import requests
|
||||
import time
|
||||
import configparser
|
||||
import socket
|
||||
from datetime import datetime, timedelta
|
||||
from urllib3.exceptions import InsecureRequestWarning
|
||||
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
|
||||
|
||||
parser = argparse.ArgumentParser(description='Import and activate a SSL/TLS certificate into FreeNAS.')
|
||||
parser.add_argument('-c', '--config', default=(os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
||||
'deploy_config')), help='Path to config file, defaults to deploy_config.')
|
||||
args = parser.parse_args()
|
||||
|
||||
if os.path.isfile(args.config):
|
||||
config = configparser.ConfigParser()
|
||||
config.read(args.config)
|
||||
deploy = config['deploy']
|
||||
else:
|
||||
print("Config file", args.config, "does not exist!")
|
||||
exit(1)
|
||||
|
||||
# We'll use the API key if provided
|
||||
API_KEY = deploy.get('api_key')
|
||||
# Otherwise fallback to basic password authentication
|
||||
USER = "root"
|
||||
PASSWORD = deploy.get('password')
|
||||
|
||||
DOMAIN_NAME = deploy.get('cert_fqdn',socket.gethostname())
|
||||
FREENAS_ADDRESS = deploy.get('connect_host','localhost')
|
||||
VERIFY = deploy.getboolean('verify',fallback=False)
|
||||
PRIVATEKEY_PATH = deploy.get('privkey_path',"/root/.acme.sh/" + DOMAIN_NAME + "/" + DOMAIN_NAME + ".key")
|
||||
FULLCHAIN_PATH = deploy.get('fullchain_path',"/root/.acme.sh/" + DOMAIN_NAME + "/fullchain.cer")
|
||||
PROTOCOL = deploy.get('protocol','http://')
|
||||
PORT = deploy.get('port','80')
|
||||
FTP_ENABLED = deploy.getboolean('ftp_enabled',fallback=False)
|
||||
S3_ENABLED = deploy.getboolean('s3_enabled',fallback=False)
|
||||
now = datetime.now()
|
||||
cert = "letsencrypt-%s-%s-%s-%s" %(now.year, now.strftime('%m'), now.strftime('%d'), ''.join(c for c in now.strftime('%X') if
|
||||
c.isdigit()))
|
||||
|
||||
|
||||
# Set some general request params
|
||||
session = requests.Session()
|
||||
session.headers.update({
|
||||
'Content-Type': 'application/json'
|
||||
})
|
||||
if API_KEY:
|
||||
session.headers.update({
|
||||
'Authorization': f'Bearer {API_KEY}'
|
||||
})
|
||||
elif PASSWORD:
|
||||
session.auth = (USER, PASSWORD)
|
||||
else:
|
||||
print ("Unable to authenticate. Specify 'api_key' or 'password' in the config.")
|
||||
exit(1)
|
||||
|
||||
# Load cert/key
|
||||
with open(PRIVATEKEY_PATH, 'r') as file:
|
||||
priv_key = file.read()
|
||||
with open(FULLCHAIN_PATH, 'r') as file:
|
||||
full_chain = file.read()
|
||||
|
||||
# Update or create certificate
|
||||
r = session.post(
|
||||
PROTOCOL + FREENAS_ADDRESS + ':' + PORT + '/api/v2.0/certificate/',
|
||||
verify=VERIFY,
|
||||
data=json.dumps({
|
||||
"create_type": "CERTIFICATE_CREATE_IMPORTED",
|
||||
"name": cert,
|
||||
"certificate": full_chain,
|
||||
"privatekey": priv_key,
|
||||
})
|
||||
)
|
||||
|
||||
if r.status_code == 200:
|
||||
print ("Certificate import successful")
|
||||
else:
|
||||
print ("Error importing certificate!")
|
||||
print (r.text)
|
||||
sys.exit(1)
|
||||
|
||||
# Sleep for a few seconds to let the cert propagate
|
||||
time.sleep(5)
|
||||
|
||||
# Download certificate list
|
||||
limit = {'limit': 0} # set limit to 0 to disable paging in the event of many certificates
|
||||
r = session.get(
|
||||
PROTOCOL + FREENAS_ADDRESS + ':' + PORT + '/api/v2.0/certificate/',
|
||||
verify=VERIFY,
|
||||
params=limit
|
||||
)
|
||||
|
||||
if r.status_code == 200:
|
||||
print ("Certificate list successful")
|
||||
else:
|
||||
print ("Error listing certificates!")
|
||||
print (r.text)
|
||||
sys.exit(1)
|
||||
|
||||
# Parse certificate list to find the id that matches our cert name
|
||||
cert_list = r.json()
|
||||
|
||||
new_cert_data = None
|
||||
for cert_data in cert_list:
|
||||
if cert_data['name'] == cert:
|
||||
new_cert_data = cert_data
|
||||
cert_id = new_cert_data['id']
|
||||
break
|
||||
|
||||
if not new_cert_data:
|
||||
print ("Error searching for newly imported certificate in certificate list.")
|
||||
sys.exit(1)
|
||||
|
||||
# Set our cert as active
|
||||
r = session.put(
|
||||
PROTOCOL + FREENAS_ADDRESS + ':' + PORT + '/api/v2.0/system/general/',
|
||||
verify=VERIFY,
|
||||
data=json.dumps({
|
||||
"ui_certificate": cert_id,
|
||||
})
|
||||
)
|
||||
|
||||
if r.status_code == 200:
|
||||
print ("Setting active certificate successful")
|
||||
else:
|
||||
print ("Error setting active certificate!")
|
||||
print (r.text)
|
||||
sys.exit(1)
|
||||
|
||||
if FTP_ENABLED:
|
||||
# Set our cert as active for FTP plugin
|
||||
r = session.put(
|
||||
PROTOCOL + FREENAS_ADDRESS + ':' + PORT + '/api/v2.0/ftp/',
|
||||
verify=VERIFY,
|
||||
data=json.dumps({
|
||||
"ssltls_certfile": cert,
|
||||
}),
|
||||
)
|
||||
|
||||
if r.status_code == 200:
|
||||
print ("Setting active FTP certificate successful")
|
||||
else:
|
||||
print ("Error setting active FTP certificate!")
|
||||
print (r.text)
|
||||
sys.exit(1)
|
||||
|
||||
if S3_ENABLED:
|
||||
# Set our cert as active for S3 plugin
|
||||
r = session.put(
|
||||
PROTOCOL + FREENAS_ADDRESS + ':' + PORT + '/api/v2.0/s3/',
|
||||
verify=VERIFY,
|
||||
data=json.dumps({
|
||||
"certificate": cert_id,
|
||||
}),
|
||||
)
|
||||
|
||||
if r.status_code == 200:
|
||||
print ("Setting active S3 certificate successful")
|
||||
else:
|
||||
print ("Error setting active S3 certificate!")
|
||||
print (r)
|
||||
sys.exit(1)
|
||||
|
||||
# Get expired and old certs with same SAN
|
||||
cert_ids_same_san = set()
|
||||
cert_ids_expired = set()
|
||||
for cert_data in cert_list:
|
||||
if set(cert_data['san']) == set(new_cert_data['san']):
|
||||
cert_ids_same_san.add(cert_data['id'])
|
||||
|
||||
issued_date = datetime.strptime(cert_data['from'], "%c")
|
||||
lifetime = timedelta(days=cert_data['lifetime'])
|
||||
expiration_date = issued_date + lifetime
|
||||
if expiration_date < now:
|
||||
cert_ids_expired.add(cert_data['id'])
|
||||
|
||||
# Remove new cert_id from lists
|
||||
if cert_id in cert_ids_expired:
|
||||
cert_ids_expired.remove(cert_id)
|
||||
|
||||
if cert_id in cert_ids_same_san:
|
||||
cert_ids_same_san.remove(cert_id)
|
||||
|
||||
# Delete expired and old certificates with same SAN from freenas
|
||||
for cid in (cert_ids_same_san | cert_ids_expired):
|
||||
r = session.delete(
|
||||
PROTOCOL + FREENAS_ADDRESS + ':' + PORT + '/api/v2.0/certificate/id/' + str(cid),
|
||||
verify=VERIFY
|
||||
)
|
||||
|
||||
for c in cert_list:
|
||||
if c['id'] == cid:
|
||||
cert_name = c['name']
|
||||
|
||||
if r.status_code == 200:
|
||||
print ("Deleting certificate " + cert_name + " successful")
|
||||
else:
|
||||
print ("Error deleting certificate " + cert_name + "!")
|
||||
print (r.text)
|
||||
sys.exit(1)
|
||||
|
||||
# Reload nginx with new cert
|
||||
# If everything goes right, the request fails with a ConnectionError
|
||||
try:
|
||||
r = session.post(
|
||||
PROTOCOL + FREENAS_ADDRESS + ':' + PORT + '/api/v2.0/system/general/ui_restart',
|
||||
verify=VERIFY
|
||||
)
|
||||
|
||||
if r.status_code == 200:
|
||||
print ("Reloading WebUI successful")
|
||||
print ("deploy_freenas.py executed successfully")
|
||||
else:
|
||||
print ("Error reloading WebUI!")
|
||||
print ("{}: {}".format(r.status_code, r.text))
|
||||
sys.exit(1)
|
||||
except requests.exceptions.ConnectionError:
|
||||
print ("Error reloading WebUI!")
|
||||
sys.exit(1)
|
107
ansible/roles/truenas/files/scripts/snapshots_clearempty.py
Normal file
107
ansible/roles/truenas/files/scripts/snapshots_clearempty.py
Normal file
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# clearempty.py - Koen Vermeer <k.vermeer@eyehospital.nl>
|
||||
# Inspired by rollup.py by Arno Hautala <arno@alum.wpi.edu>
|
||||
# modifications by Arno Hautala
|
||||
# This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
|
||||
# (CC BY-SA-3.0) http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
# This script removes empty snapshots, based on their 'used' property.
|
||||
# Note that one snapshot's 'used' value may change when another snapshot is
|
||||
# destroyed. This script iteratively destroys the oldest empty snapshot. It
|
||||
# does not remove the latest snapshot of each dataset or manual snapshots
|
||||
|
||||
import subprocess
|
||||
import argparse
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
|
||||
parser = argparse.ArgumentParser(description='Removes empty auto snapshots.')
|
||||
parser.add_argument('datasets', nargs='+', help='the root dataset(s) from which to remove snapshots')
|
||||
parser.add_argument('--test', '-t', action="store_true", default=False, help='only display the snapshots that would be deleted, without actually deleting them. Note that due to dependencies between snapshots, this may not match what would really happen.')
|
||||
parser.add_argument('--recursive', '-r', action="store_true", default=False, help='recursively removes snapshots from nested datasets')
|
||||
parser.add_argument('--prefix', '-p', action='append', help='list of snapshot name prefixes that will be considered')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.prefix:
|
||||
args.prefix = ['auto']
|
||||
|
||||
args.prefix = [prefix+"-" for prefix in set(args.prefix)]
|
||||
|
||||
deleted = defaultdict(lambda : defaultdict(lambda : defaultdict(int)))
|
||||
|
||||
snapshot_was_deleted = True
|
||||
|
||||
while snapshot_was_deleted:
|
||||
snapshot_was_deleted = False
|
||||
snapshots = defaultdict(lambda : defaultdict(lambda : defaultdict(int)))
|
||||
|
||||
# Get properties of all snapshots of the selected datasets
|
||||
for dataset in args.datasets:
|
||||
subp = subprocess.Popen(["zfs", "get", "-Hrpo", "name,property,value", "type,creation,used,freenas:state", dataset], stdout=subprocess.PIPE)
|
||||
zfs_snapshots = subp.communicate()[0]
|
||||
if subp.returncode:
|
||||
print("zfs get failed with RC=%s" % subp.returncode)
|
||||
sys.exit(1)
|
||||
|
||||
for snapshot in zfs_snapshots.splitlines():
|
||||
name,property,value = snapshot.decode().split('\t',3)
|
||||
|
||||
# if the rollup isn't recursive, skip any snapshots from child datasets
|
||||
if not args.recursive and not name.startswith(dataset+"@"):
|
||||
continue
|
||||
|
||||
try:
|
||||
dataset,snapshot = name.split('@',2)
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
snapshots[dataset][snapshot][property] = value
|
||||
|
||||
# Ignore non-snapshots and not-auto-snapshots
|
||||
# Remove already destroyed snapshots
|
||||
for dataset in list(snapshots.keys()):
|
||||
latest = None
|
||||
latestNEW = None
|
||||
for snapshot in sorted(snapshots[dataset], key=lambda snapshot: snapshots[dataset][snapshot]['creation'], reverse=True):
|
||||
if not any(map(snapshot.startswith, args.prefix)) \
|
||||
or snapshots[dataset][snapshot]['type'] != "snapshot":
|
||||
del snapshots[dataset][snapshot]
|
||||
continue
|
||||
if not latest:
|
||||
latest = snapshot
|
||||
del snapshots[dataset][snapshot]
|
||||
continue
|
||||
if not latestNEW and snapshots[dataset][snapshot]['freenas:state'] == 'NEW':
|
||||
latestNEW = snapshot
|
||||
del snapshots[dataset][snapshot]
|
||||
continue
|
||||
if snapshots[dataset][snapshot]['freenas:state'] == 'LATEST':
|
||||
del snapshots[dataset][snapshot]
|
||||
continue
|
||||
if snapshots[dataset][snapshot]['used'] != '0' \
|
||||
or snapshot in list(deleted[dataset].keys()):
|
||||
del snapshots[dataset][snapshot]
|
||||
continue
|
||||
|
||||
# Stop if no snapshots are in the list
|
||||
if not snapshots[dataset]:
|
||||
del snapshots[dataset]
|
||||
continue
|
||||
|
||||
# destroy the most recent empty snapshot
|
||||
snapshot = max(snapshots[dataset], key=lambda snapshot: snapshots[dataset][snapshot]['creation'])
|
||||
if not args.test:
|
||||
# destroy the snapshot
|
||||
subprocess.call(["zfs", "destroy", dataset+"@"+snapshot])
|
||||
|
||||
deleted[dataset][snapshot] = snapshots[dataset][snapshot]
|
||||
snapshot_was_deleted = True
|
||||
|
||||
for dataset in sorted(deleted.keys()):
|
||||
if not deleted[dataset]:
|
||||
continue
|
||||
print(dataset)
|
||||
for snapshot in sorted(deleted[dataset].keys()):
|
||||
print("\t", snapshot, deleted[dataset][snapshot]['used'])
|
262
ansible/roles/truenas/files/scripts/snapshots_prune.py
Normal file
262
ansible/roles/truenas/files/scripts/snapshots_prune.py
Normal file
@@ -0,0 +1,262 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# rollup.py - Arno Hautala <arno@alum.wpi.edu>
|
||||
# This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
|
||||
# (CC BY-SA-3.0) http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
# For the latest version, visit:
|
||||
# https://github.com/fracai/zfs-rollup
|
||||
# https://bitbucket.org/fracai/zfs-rollup
|
||||
|
||||
# A snapshot pruning script, similar in behavior to Apple's TimeMachine
|
||||
# Keep hourly snapshots for the last day, daily for the last week, and weekly thereafter.
|
||||
|
||||
# TODO:
|
||||
# rollup based on local time, not UTC
|
||||
# requires pytz, or manually determining and converting time offsets
|
||||
# improve documentation
|
||||
|
||||
# TEST:
|
||||
|
||||
import datetime
|
||||
import calendar
|
||||
import time
|
||||
import subprocess
|
||||
import argparse
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
|
||||
intervals = {}
|
||||
intervals['hourly'] = { 'max':24, 'abbreviation':'h', 'reference':'%Y-%m-%d %H' }
|
||||
intervals['daily'] = { 'max': 7, 'abbreviation':'d', 'reference':'%Y-%m-%d' }
|
||||
intervals['weekly'] = { 'max': 0, 'abbreviation':'w', 'reference':'%Y-%W' }
|
||||
intervals['monthly'] = { 'max':12, 'abbreviation':'m', 'reference':'%Y-%m' }
|
||||
intervals['yearly'] = { 'max':10, 'abbreviation':'y', 'reference':'%Y' }
|
||||
|
||||
modifiers = {
|
||||
'M' : 1,
|
||||
'H' : 60,
|
||||
'h' : 60,
|
||||
'd' : 60*24,
|
||||
'w' : 60*24*7,
|
||||
'm' : 60*24*28,
|
||||
'y' : 60*24*365,
|
||||
}
|
||||
|
||||
used_intervals = {
|
||||
'hourly': intervals['hourly'],
|
||||
'daily' : intervals['daily'],
|
||||
'weekly': intervals['weekly']
|
||||
}
|
||||
|
||||
parser = argparse.ArgumentParser(description='Prune excess snapshots, keeping hourly for the last day, daily for the last week, and weekly thereafter.')
|
||||
parser.add_argument('datasets', nargs='+', help='The root dataset(s) from which to prune snapshots')
|
||||
parser.add_argument('-t', '--test', action="store_true", default=False, help='Only display the snapshots that would be deleted, without actually deleting them')
|
||||
parser.add_argument('-v', '--verbose', action="store_true", default=False, help='Display verbose information about which snapshots are kept, pruned, and why')
|
||||
parser.add_argument('-r', '--recursive', action="store_true", default=False, help='Recursively prune snapshots from nested datasets')
|
||||
parser.add_argument('--prefix', '-p', action='append', help='list of snapshot name prefixes that will be considered')
|
||||
parser.add_argument('-c', '--clear', action="store_true", default=False, help='remove all snapshots')
|
||||
parser.add_argument('-i', '--intervals',
|
||||
help="Modify and define intervals with which to keep and prune snapshots. Either name existing intervals ("+
|
||||
", ".join(sorted(intervals, key=lambda interval: modifiers[intervals[interval]['abbreviation']]))+"), "+
|
||||
"modify the number of those to store (hourly:12), or define new intervals according to interval:count (2h:12). "+
|
||||
"Multiple intervals may be specified if comma seperated (hourly,daily:30,2h:12). Available modifier abbreviations are: "+
|
||||
", ".join(sorted(modifiers, key=modifiers.get))
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.prefix:
|
||||
args.prefix = ['auto']
|
||||
|
||||
args.prefix = [prefix+"-" for prefix in set(args.prefix)]
|
||||
|
||||
if args.test:
|
||||
args.verbose = True
|
||||
|
||||
if args.intervals:
|
||||
used_intervals = {}
|
||||
|
||||
for interval in args.intervals.split(','):
|
||||
if interval.count(':') == 1:
|
||||
period,count = interval.split(':')
|
||||
|
||||
try:
|
||||
int(count)
|
||||
except ValueError:
|
||||
print("invalid count: "+count)
|
||||
sys.exit(1)
|
||||
|
||||
if period in intervals:
|
||||
used_intervals[period] = intervals[period]
|
||||
used_intervals[period]['max'] = count
|
||||
|
||||
else:
|
||||
try:
|
||||
if period[-1] in modifiers:
|
||||
used_intervals[interval] = { 'max' : count, 'interval' : int(period[:-1]) * modifiers[period[-1]] }
|
||||
else:
|
||||
used_intervals[interval] = { 'max' : count, 'interval' : int(period) }
|
||||
|
||||
except ValueError:
|
||||
print("invalid period: "+period)
|
||||
sys.exit(1)
|
||||
|
||||
elif interval.count(':') == 0 and interval in intervals:
|
||||
used_intervals[interval] = intervals[interval]
|
||||
|
||||
else:
|
||||
print("invalid interval: "+interval)
|
||||
sys.exit(1)
|
||||
|
||||
for interval in used_intervals:
|
||||
if 'abbreviation' not in used_intervals[interval]:
|
||||
used_intervals[interval]['abbreviation'] = interval
|
||||
|
||||
snapshots = defaultdict(lambda : defaultdict(lambda : defaultdict(int)))
|
||||
|
||||
for dataset in args.datasets:
|
||||
subp = subprocess.Popen(["zfs", "get", "-Hrpo", "name,property,value", "creation,type,used,freenas:state", dataset], stdout=subprocess.PIPE)
|
||||
zfs_snapshots = subp.communicate()[0]
|
||||
if subp.returncode:
|
||||
print("zfs get failed with RC=%s" % subp.returncode)
|
||||
sys.exit(1)
|
||||
|
||||
for snapshot in zfs_snapshots.splitlines():
|
||||
name,property,value = snapshot.decode().split('\t',3)
|
||||
|
||||
# if the rollup isn't recursive, skip any snapshots from child datasets
|
||||
if not args.recursive and not name.startswith(dataset+"@"):
|
||||
continue
|
||||
|
||||
try:
|
||||
dataset,snapshot = name.split('@',2)
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
# enforce that this is a snapshot starting with one of the requested prefixes
|
||||
if not any(map(snapshot.startswith, args.prefix)):
|
||||
if property == 'creation':
|
||||
print("will ignore:\t", dataset+"@"+snapshot)
|
||||
|
||||
snapshots[dataset][snapshot][property] = value
|
||||
|
||||
for dataset in list(snapshots.keys()):
|
||||
latestNEW = None
|
||||
latest = None
|
||||
for snapshot in sorted(snapshots[dataset], key=lambda snapshot: snapshots[dataset][snapshot]['creation'], reverse=True):
|
||||
if not latest:
|
||||
latest = snapshot
|
||||
snapshots[dataset][snapshot]['keep'] = 'RECENT'
|
||||
continue
|
||||
if not any(map(snapshot.startswith, args.prefix)) \
|
||||
or snapshots[dataset][snapshot]['type'] != "snapshot":
|
||||
snapshots[dataset][snapshot]['keep'] = '!PREFIX'
|
||||
continue
|
||||
if not latestNEW and snapshots[dataset][snapshot]['freenas:state'] == 'NEW':
|
||||
latestNEW = snapshot
|
||||
snapshots[dataset][snapshot]['keep'] = 'NEW'
|
||||
continue
|
||||
if snapshots[dataset][snapshot]['freenas:state'] == 'LATEST':
|
||||
snapshots[dataset][snapshot]['keep'] = 'LATEST'
|
||||
continue
|
||||
|
||||
if not len(list(snapshots[dataset].keys())):
|
||||
del snapshots[dataset]
|
||||
|
||||
for dataset in sorted(snapshots.keys()):
|
||||
print(dataset)
|
||||
|
||||
sorted_snapshots = sorted(snapshots[dataset], key=lambda snapshot: snapshots[dataset][snapshot]['creation'])
|
||||
most_recent = sorted_snapshots[-1]
|
||||
|
||||
rollup_intervals = defaultdict(lambda : defaultdict(int))
|
||||
|
||||
for snapshot in sorted_snapshots:
|
||||
prune = True
|
||||
|
||||
if args.clear:
|
||||
continue
|
||||
|
||||
epoch = snapshots[dataset][snapshot]['creation']
|
||||
|
||||
for interval in list(used_intervals.keys()):
|
||||
if 'reference' in used_intervals[interval]:
|
||||
reference = time.strftime(used_intervals[interval]['reference'], time.gmtime(float(epoch)))
|
||||
|
||||
if reference not in rollup_intervals[interval]:
|
||||
if int(used_intervals[interval]['max']) != 0 and len(rollup_intervals[interval]) >= int(used_intervals[interval]['max']):
|
||||
rollup_intervals[interval].pop(sorted(rollup_intervals[interval].keys())[0])
|
||||
rollup_intervals[interval][reference] = epoch
|
||||
|
||||
elif 'interval' in used_intervals[interval]:
|
||||
if int(used_intervals[interval]['max']) != 0 and len(rollup_intervals[interval]) >= int(used_intervals[interval]['max']):
|
||||
rollup_intervals[interval].pop(sorted(rollup_intervals[interval].keys())[0])
|
||||
|
||||
if (not rollup_intervals[interval]) or int(sorted(rollup_intervals[interval].keys())[-1]) + (used_intervals[interval]['interval']*60*.9) < int(epoch):
|
||||
rollup_intervals[interval][epoch] = epoch
|
||||
|
||||
ranges = list()
|
||||
ranges.append(list())
|
||||
for snapshot in sorted_snapshots:
|
||||
prune = True
|
||||
|
||||
epoch = snapshots[dataset][snapshot]['creation']
|
||||
|
||||
if 'keep' in snapshots[dataset][snapshot]:
|
||||
prune = False
|
||||
ranges.append(list())
|
||||
|
||||
|
||||
for interval in list(used_intervals.keys()):
|
||||
if 'reference' in used_intervals[interval]:
|
||||
reference = time.strftime(used_intervals[interval]['reference'], time.gmtime(float(epoch)))
|
||||
if reference in rollup_intervals[interval] and rollup_intervals[interval][reference] == epoch:
|
||||
prune = False
|
||||
ranges.append(list())
|
||||
|
||||
elif 'interval' in used_intervals[interval]:
|
||||
if epoch in rollup_intervals[interval]:
|
||||
prune = False
|
||||
ranges.append(list())
|
||||
|
||||
if prune or args.verbose:
|
||||
print("\t","pruning\t" if prune else " \t", "@"+snapshot, end=' ')
|
||||
if args.verbose:
|
||||
for interval in list(used_intervals.keys()):
|
||||
if 'reference' in used_intervals[interval]:
|
||||
reference = time.strftime(used_intervals[interval]['reference'], time.gmtime(float(epoch)))
|
||||
if reference in rollup_intervals[interval] and rollup_intervals[interval][reference] == epoch:
|
||||
print(used_intervals[interval]['abbreviation'], end=' ')
|
||||
else:
|
||||
print('-', end=' ')
|
||||
if 'interval' in used_intervals[interval]:
|
||||
if epoch in rollup_intervals[interval]:
|
||||
print(used_intervals[interval]['abbreviation'], end=' ')
|
||||
else:
|
||||
print('-', end=' ')
|
||||
if 'keep' in snapshots[dataset][snapshot]:
|
||||
print(snapshots[dataset][snapshot]['keep'][0], end=' ')
|
||||
else:
|
||||
print('-', end=' ')
|
||||
print(snapshots[dataset][snapshot]['used'])
|
||||
else:
|
||||
print()
|
||||
|
||||
if prune:
|
||||
ranges[-1].append(snapshot)
|
||||
|
||||
for range in ranges:
|
||||
if not range:
|
||||
continue
|
||||
to_delete = dataset+'@'+range[0]
|
||||
if len(range) > 1:
|
||||
to_delete += '%' + range[-1]
|
||||
to_delete = to_delete.replace(' ', '')
|
||||
if not to_delete:
|
||||
continue
|
||||
if args.verbose:
|
||||
print('zfs destroy ' + to_delete)
|
||||
if not args.test:
|
||||
# destroy the snapshot
|
||||
subprocess.call(['zfs', 'destroy', to_delete])
|
28
ansible/roles/truenas/files/scripts/telegraf_hddtemp.bash
Normal file
28
ansible/roles/truenas/files/scripts/telegraf_hddtemp.bash
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Runs smartctl to report current temperature of all disks.
|
||||
|
||||
JSON="["
|
||||
|
||||
DISKS=$(/sbin/sysctl -n kern.disks | cut -d= -f2)
|
||||
|
||||
for i in ${DISKS}
|
||||
do
|
||||
# Get temperature from smartctl (requires root).
|
||||
[[ "${i}" = *"ada"* ]] && TEMP=$(/usr/local/sbin/smartctl -l scttemp /dev/$i | grep '^Current Temperature:' | awk '{print $3}')
|
||||
[[ "${i}" = *"nvd"* ]] && DEVICE_NUMBER=$(echo ${i} | cut -c 4) && TEMP=$(smartctl -a /dev/nvme${DEVICE_NUMBER} | grep Temperature: | head -1 | awk '{print $2}')
|
||||
|
||||
if [ ${TEMP:-0} -gt 0 ]
|
||||
then
|
||||
JSON=$(echo "${JSON}{")
|
||||
JSON=$(echo "${JSON}\"temperature\":${TEMP},")
|
||||
JSON=$(echo "${JSON}\"disk\":\"${i}\"")
|
||||
JSON=$(echo "${JSON}},")
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
# Remove trailing "," on last field.
|
||||
JSON=$(echo ${JSON} | sed 's/,$//')
|
||||
|
||||
echo -e "${JSON}]"
|
19
ansible/roles/truenas/tasks/directories.yml
Normal file
19
ansible/roles/truenas/tasks/directories.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
- name: directories | create
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: "{{ item }}"
|
||||
loop:
|
||||
- "{{ homelab_homedir }}/letsencrypt"
|
||||
- "{{ telegraf_dir }}"
|
||||
- "{{ backups_dir }}servers/{{ ansible_facts['nodename'] }}"
|
||||
- "{{ scripts_dir }}"
|
||||
|
||||
- name: directories | truenas
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: "{{ item }}"
|
||||
loop:
|
||||
- "{{ backups_dir }}servers/coreelec.{{ SECRET_DOMAIN }}"
|
||||
- "{{ backups_dir }}servers/opnsense.{{ SECRET_DOMAIN }}"
|
||||
when: "main_nas == true"
|
9
ansible/roles/truenas/tasks/main.yml
Normal file
9
ansible/roles/truenas/tasks/main.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
- ansible.builtin.include_tasks: directories.yml
|
||||
|
||||
- ansible.builtin.include_tasks: scripts.yml
|
||||
|
||||
- ansible.builtin.include_tasks: telegraf.yml
|
||||
|
||||
- ansible.builtin.include_tasks: wireguard.yml
|
||||
when: "main_nas == false"
|
25
ansible/roles/truenas/tasks/scripts.yml
Normal file
25
ansible/roles/truenas/tasks/scripts.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
- name: scripts | copy scripts
|
||||
ansible.builtin.copy:
|
||||
src: "scripts/{{ item }}"
|
||||
dest: "{{ scripts_dir }}/{{ item }}"
|
||||
mode: 0755
|
||||
loop:
|
||||
- certificates_deploy.py
|
||||
- snapshots_clearempty.py
|
||||
- snapshots_prune.py
|
||||
- telegraf_hddtemp.bash
|
||||
|
||||
- name: scripts | template scripts
|
||||
ansible.builtin.template:
|
||||
src: "scripts/{{ item.name }}"
|
||||
dest: "{{ scripts_dir }}/{{ item.name }}"
|
||||
mode: "{{ item.mode }}"
|
||||
loop:
|
||||
- { name: "backupconfig_cloudsync_pre.bash", mode: "0775" }
|
||||
- { name: "certificates_deploy.bash", mode: "0775" }
|
||||
- { name: "certificates_deploy.conf", mode: "0664" }
|
||||
- { name: "snapshots_prune.sh", mode: "0775" }
|
||||
- { name: "report_pools.sh", mode: "0775" }
|
||||
- { name: "report_smart.sh", mode: "0775" }
|
||||
- { name: "report_ups.sh", mode: "0775" }
|
10
ansible/roles/truenas/tasks/telegraf.yml
Normal file
10
ansible/roles/truenas/tasks/telegraf.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: telegraf | clone git repository
|
||||
ansible.builtin.git:
|
||||
repo: https://github.com/samuelkadolph/truenas-telegraf
|
||||
dest: "{{ telegraf_dir }}"
|
||||
|
||||
- name: telegraf | copy configuration
|
||||
ansible.builtin.template:
|
||||
src: telegraf/telegraf.conf
|
||||
dest: "{{ telegraf_dir }}/telegraf.conf"
|
17
ansible/roles/truenas/tasks/wireguard.yml
Normal file
17
ansible/roles/truenas/tasks/wireguard.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
- name: wireguard | configuration
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ item.dest }}"
|
||||
mode: "{{ item.mode }}"
|
||||
loop:
|
||||
- {
|
||||
src: "wireguard/{{ ansible_facts['nodename'] }}.conf",
|
||||
dest: "{{ homelab_homedir }}/{{ wg_interface }}.conf",
|
||||
mode: 400,
|
||||
}
|
||||
- {
|
||||
src: "wireguard/ip-check.bash",
|
||||
dest: "{{ homelab_homedir }}/wireguard-ip-check.bash",
|
||||
mode: 700,
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
# DEBUG
|
||||
# set -x
|
||||
|
||||
# Configuration backup Cloud Sync pre-script
|
||||
|
||||
# Variables
|
||||
SOURCE_FOLDER="/var/db/system/configs"
|
||||
BACKUP_FOLDER="{{ backups_dir }}servers/{{ ansible_facts['nodename'] }}"
|
||||
|
||||
cd ${SOURCE_FOLDER}*
|
||||
rsync --archive --delete --human-readable --delete ./ ${BACKUP_FOLDER}
|
||||
test $? -ne 0 && FLAG_NOTIF=true
|
||||
|
||||
chmod -R 775 ${BACKUP_FOLDER}/*
|
||||
chown -R homelab:homelab ${BACKUP_FOLDER}/*
|
||||
|
||||
# Keep the last 90 backups on disk
|
||||
# find ${BACKUP_FOLDER}/* -mtime +90 -type f -delete
|
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# DEBUG
|
||||
# set -x
|
||||
|
||||
# Get certificates from remote server
|
||||
|
||||
# Variables
|
||||
SCRIPT_PATH="{{ scripts_dir }}"
|
||||
CERTIFICATE_PATH="{{ certificates_dir }}"
|
||||
CONFIG_FILE="${SCRIPT_PATH}/certificates_deploy.conf"
|
||||
|
||||
# Check if cert has been uploaded last week
|
||||
result=$(find ${CERTIFICATE_PATH}/cert.pem -mtime -7)
|
||||
|
||||
if [[ "$result" == "${CERTIFICATE_PATH}/cert.pem" ]]; then
|
||||
|
||||
# Deploy certificate
|
||||
python ${SCRIPT_PATH}/certificates_deploy.py -c ${CONFIG_FILE}
|
||||
test $? -ne 0 && FLAG_NOTIF=true
|
||||
|
||||
fi
|
@@ -0,0 +1,48 @@
|
||||
# Configuration file for deploy_certificates.py
|
||||
|
||||
[deploy]
|
||||
# Choose one of the following authentication methods, "api_key" or "password" (comment out the other one).
|
||||
# Auth via API keys is highly recommended, but is only available from TrueNAS (Core) 12.0 up.
|
||||
# You can generate a new API key in the web interface under "Settings" (upper right) > "API Keys".
|
||||
api_key = {{ root_api_key }}
|
||||
# If you are on FreeNAS 11 or lower, set this to your FreeNAS root password
|
||||
# password =
|
||||
|
||||
# Everything below here is optional
|
||||
|
||||
# cert_fqdn specifies the FQDN used for your certificate. Default is your system hostname
|
||||
# cert_fqdn = foo.bar.baz
|
||||
|
||||
# connect_host specifies the hostname the script should attempt to connect to, to deploy the cert.
|
||||
# Default is localhost (assuming the script is running on your FreeNAS box)
|
||||
# connect_host = baz.bar.foo
|
||||
|
||||
# verify sets whether the script will attempt to verify the server's certificate with a HTTPS
|
||||
# connection. Set to true if you're using a HTTPS connection to a remote host. If connect_host
|
||||
# is set to localhost (or is unset), set to false. Default is false.
|
||||
# verify = false
|
||||
|
||||
# privkey_path is the path to the certificate private key on your system. Default
|
||||
# assumes you're using acme.sh:
|
||||
# /root/.acme.sh/cert_fqdn/cert_fqdn.key
|
||||
privkey_path = {{ certificates_dir }}/key.pem
|
||||
|
||||
# fullchain_path is the path to the full chain (leaf cert + intermediate certs)
|
||||
# on your system. Default assumes you're using acme.sh:
|
||||
# /root/.acme.sh/cert_fqdn/fullchain.cer
|
||||
fullchain_path = {{ certificates_dir }}/fullchain.pem
|
||||
|
||||
# protocol sets the connection protocol, http or https. Include '://' at the end.
|
||||
# Default is http
|
||||
# protocol = https://
|
||||
|
||||
# port sets the port to use to connect. Default is 80. If protocol is https,
|
||||
# this MUST be set to your https port.
|
||||
# port = 443
|
||||
|
||||
# set ftp_enabled to true if you have the FTP service enabled on your FreeNAS. Default is false.
|
||||
# ftp_enabled = true
|
||||
|
||||
{% if service_s3 is defined %}
|
||||
s3_enabled = true
|
||||
{% endif %}
|
162
ansible/roles/truenas/templates/scripts/report_pools.sh
Normal file
162
ansible/roles/truenas/templates/scripts/report_pools.sh
Normal file
@@ -0,0 +1,162 @@
|
||||
#!/bin/sh
|
||||
|
||||
### Parameters ###
|
||||
|
||||
# Specify your email address here:
|
||||
email="truenas@{{ SECRET_EMAIL_DOMAIN }}"
|
||||
|
||||
# zpool output changed from FreeNAS version 11.0 to 11.1, breaking
|
||||
# our parsing of the scrubErrors and scrubDate variables. Added a
|
||||
# conditional to test for the FreeNAS version and parse accordingly.
|
||||
# This changed again with the release of TrueNAS. Ironically, back to
|
||||
# the way parsing worked with older versions of FreeNAS.
|
||||
#
|
||||
# We obtain the FreeBSD version using uname, as suggested by user
|
||||
# Chris Moore on the FreeBSD forum.
|
||||
#
|
||||
# 'uname -K' gives 7-digit OS release and version, e.g.:
|
||||
#
|
||||
# FreeBSD 11.0 1100512
|
||||
# FreeBSD 11.1 1101505
|
||||
# FreeBSD 12.2 1202000
|
||||
|
||||
fbsd_relver=$(uname -K)
|
||||
|
||||
freenashost=$(hostname -s | tr '[:lower:]' '[:upper:]')
|
||||
boundary="===== MIME boundary; FreeNAS server ${freenashost} ====="
|
||||
logfile="/tmp/zpool_report.tmp"
|
||||
subject="ZPool Status Report for ${freenashost}"
|
||||
pools=$(zpool list -H -o name)
|
||||
usedWarn=75
|
||||
usedCrit=90
|
||||
scrubAgeWarn=30
|
||||
warnSymbol="?"
|
||||
critSymbol="!"
|
||||
|
||||
### Set email headers ###
|
||||
printf "%s\n" "To: ${email}
|
||||
Subject: ${subject}
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary=\"$boundary\"
|
||||
|
||||
--${boundary}
|
||||
Content-Type: text/html; charset=\"US-ASCII\"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: inline
|
||||
<html><head></head><body><pre style=\"font-size:14px; white-space:pre\">" >> ${logfile}
|
||||
|
||||
###### summary ######
|
||||
(
|
||||
echo "########## ZPool status report summary for all pools on server ${freenashost} ##########"
|
||||
echo ""
|
||||
echo "+--------------+--------+------+------+------+----+----+--------+------+-----+"
|
||||
echo "|Pool Name |Status |Read |Write |Cksum |Used|Frag|Scrub |Scrub |Last |"
|
||||
echo "| | |Errors|Errors|Errors| | |Repaired|Errors|Scrub|"
|
||||
echo "| | | | | | | |Bytes | |Age |"
|
||||
echo "+--------------+--------+------+------+------+----+----+--------+------+-----+"
|
||||
) >> ${logfile}
|
||||
|
||||
for pool in $pools; do
|
||||
if [ "$fbsd_relver" -ge 1101000 ]; then
|
||||
frag="$(zpool list -H -o frag "$pool")"
|
||||
else
|
||||
if [ "${pool}" = "freenas-boot" ] || [ "${pool}" = "boot-pool" ]; then
|
||||
frag=""
|
||||
else
|
||||
frag="$(zpool list -H -o frag "$pool")"
|
||||
fi
|
||||
fi
|
||||
|
||||
status="$(zpool list -H -o health "$pool")"
|
||||
errors="$(zpool status "$pool" | grep -E "(ONLINE|DEGRADED|FAULTED|UNAVAIL|REMOVED)[ \t]+[0-9]+")"
|
||||
readErrors=0
|
||||
for err in $(echo "$errors" | awk '{print $3}'); do
|
||||
if echo "$err" | grep -E -q "[^0-9]+"; then
|
||||
readErrors=1000
|
||||
break
|
||||
fi
|
||||
readErrors=$((readErrors + err))
|
||||
done
|
||||
writeErrors=0
|
||||
for err in $(echo "$errors" | awk '{print $4}'); do
|
||||
if echo "$err" | grep -E -q "[^0-9]+"; then
|
||||
writeErrors=1000
|
||||
break
|
||||
fi
|
||||
writeErrors=$((writeErrors + err))
|
||||
done
|
||||
cksumErrors=0
|
||||
for err in $(echo "$errors" | awk '{print $5}'); do
|
||||
if echo "$err" | grep -E -q "[^0-9]+"; then
|
||||
cksumErrors=1000
|
||||
break
|
||||
fi
|
||||
cksumErrors=$((cksumErrors + err))
|
||||
done
|
||||
if [ "$readErrors" -gt 999 ]; then readErrors=">1K"; fi
|
||||
if [ "$writeErrors" -gt 999 ]; then writeErrors=">1K"; fi
|
||||
if [ "$cksumErrors" -gt 999 ]; then cksumErrors=">1K"; fi
|
||||
used="$(zpool list -H -p -o capacity "$pool")"
|
||||
scrubRepBytes="N/A"
|
||||
scrubErrors="N/A"
|
||||
scrubAge="N/A"
|
||||
if [ "$(zpool status "$pool" | grep "scan" | awk '{print $2}')" = "scrub" ]; then
|
||||
scrubRepBytes="$(zpool status "$pool" | grep "scan" | awk '{print $4}')"
|
||||
if [ "$fbsd_relver" -gt 1101000 ] && [ "$fbsd_relver" -lt 1200000 ]; then
|
||||
scrubErrors="$(zpool status "$pool" | grep "scan" | awk '{print $10}')"
|
||||
scrubDate="$(zpool status "$pool" | grep "scan" | awk '{print $17"-"$14"-"$15"_"$16}')"
|
||||
else
|
||||
scrubErrors="$(zpool status "$pool" | grep "scan" | awk '{print $8}')"
|
||||
scrubDate="$(zpool status "$pool" | grep "scan" | awk '{print $15"-"$12"-"$13"_"$14}')"
|
||||
fi
|
||||
scrubTS="$(date -j -f "%Y-%b-%e_%H:%M:%S" "$scrubDate" "+%s")"
|
||||
currentTS="$(date "+%s")"
|
||||
scrubAge=$((((currentTS - scrubTS) + 43200) / 86400))
|
||||
fi
|
||||
if [ "$status" = "FAULTED" ] || [ "$used" -gt "$usedCrit" ]; then
|
||||
symbol="$critSymbol"
|
||||
elif [ "$scrubErrors" != "N/A" ] && [ "$scrubErrors" != "0" ]; then
|
||||
symbol="$critSymbol"
|
||||
elif [ "$status" != "ONLINE" ] \
|
||||
|| [ "$readErrors" != "0" ] \
|
||||
|| [ "$writeErrors" != "0" ] \
|
||||
|| [ "$cksumErrors" != "0" ] \
|
||||
|| [ "$used" -gt "$usedWarn" ] \
|
||||
|| [ "$(echo "$scrubAge" | awk '{print int($1)}')" -gt "$scrubAgeWarn" ]; then
|
||||
symbol="$warnSymbol"
|
||||
elif [ "$scrubRepBytes" != "0" ] && [ "$scrubRepBytes" != "0B" ] && [ "$scrubRepBytes" != "N/A" ]; then
|
||||
symbol="$warnSymbol"
|
||||
else
|
||||
symbol=" "
|
||||
fi
|
||||
(
|
||||
printf "|%-12s %1s|%-8s|%6s|%6s|%6s|%3s%%|%4s|%8s|%6s|%5s|\n" \
|
||||
"$pool" "$symbol" "$status" "$readErrors" "$writeErrors" "$cksumErrors" \
|
||||
"$used" "$frag" "$scrubRepBytes" "$scrubErrors" "$scrubAge"
|
||||
) >> ${logfile}
|
||||
done
|
||||
|
||||
(
|
||||
echo "+--------------+--------+------+------+------+----+----+--------+------+-----+"
|
||||
) >> ${logfile}
|
||||
|
||||
###### for each pool ######
|
||||
for pool in $pools; do
|
||||
(
|
||||
echo ""
|
||||
echo "########## ZPool status report for ${pool} ##########"
|
||||
echo ""
|
||||
zpool status -v "$pool"
|
||||
) >> ${logfile}
|
||||
done
|
||||
|
||||
printf "%s\n" "</pre></body></html>
|
||||
--${boundary}--" >> ${logfile}
|
||||
|
||||
### Send report ###
|
||||
if [ -z "${email}" ]; then
|
||||
echo "No email address specified, information available in ${logfile}"
|
||||
else
|
||||
sendmail -t -oi < ${logfile}
|
||||
rm ${logfile}
|
||||
fi
|
267
ansible/roles/truenas/templates/scripts/report_smart.sh
Normal file
267
ansible/roles/truenas/templates/scripts/report_smart.sh
Normal file
@@ -0,0 +1,267 @@
|
||||
#!/bin/sh
|
||||
|
||||
### Parameters ###
|
||||
|
||||
# Specify your email address here:
|
||||
email="truenas@{{ SECRET_EMAIL_DOMAIN }}"
|
||||
|
||||
# Full path to 'smartctl' program:
|
||||
smartctl=/usr/local/sbin/smartctl
|
||||
|
||||
freenashost=$(hostname -s | tr '[:lower:]' '[:upper:]')
|
||||
boundary="===== MIME boundary; FreeNAS server ${freenashost} ====="
|
||||
logfile="smart_report.tmp"
|
||||
subject="SMART Status Report for ${freenashost}"
|
||||
tempWarn=40
|
||||
tempCrit=45
|
||||
sectorsCrit=10
|
||||
testAgeWarn=1
|
||||
warnSymbol="?"
|
||||
critSymbol="!"
|
||||
Drive_count=0
|
||||
SATA_count=0
|
||||
SAS_count=0
|
||||
Drive_list=""
|
||||
SATA_list=""
|
||||
SAS_list=""
|
||||
|
||||
# Get list of SMART-enabled drives
|
||||
get_smart_drives()
|
||||
{
|
||||
gs_drives=$("$smartctl" --scan | awk '{print $1}')
|
||||
for gs_drive in $gs_drives; do
|
||||
gs_smart_flag=$("$smartctl" -i "$gs_drive" | grep -E "SMART support is:[[:blank:]]+Enabled" | awk '{print $4}')
|
||||
if [ "$gs_smart_flag" = "Enabled" ]; then
|
||||
Drive_list="$Drive_list $gs_drive"
|
||||
Drive_count=$((Drive_count + 1))
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Get list of SATA disks, including older drives that only report an ATA version
|
||||
get_sata_drives()
|
||||
{
|
||||
for drive in $Drive_list; do
|
||||
lFound=0
|
||||
gsata_smart_flag=$("$smartctl" -i "$drive" | grep -E "SATA Version is:[[:blank:]]" | awk '{print $4}')
|
||||
if [ "$gsata_smart_flag" = "SATA" ]; then
|
||||
lFound=$((lFound + 1))
|
||||
else
|
||||
gsata_smart_flag=$("$smartctl" -i "$drive" | grep -E "ATA Version is:[[:blank:]]" | awk '{print $1}')
|
||||
if [ "$gsata_smart_flag" = "ATA" ]; then
|
||||
lFound=$((lFound + 1))
|
||||
fi
|
||||
fi
|
||||
if [ $lFound -gt 0 ]; then
|
||||
SATA_list="$SATA_list $drive"
|
||||
SATA_count=$((SATA_count + 1))
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Get list of SAS disks
|
||||
get_sas_drives()
|
||||
{
|
||||
for drive in $Drive_list; do
|
||||
gsas_smart_flag=$("$smartctl" -i "$drive" | grep -E "Transport protocol:[[:blank:]]+SAS" | awk '{print $3}')
|
||||
if [ "$gsas_smart_flag" = "SAS" ]; then
|
||||
SAS_list="$SAS_list $drive"
|
||||
SAS_count=$((SAS_count + 1))
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
### Fetch drive lists ###
|
||||
get_smart_drives
|
||||
get_sata_drives
|
||||
get_sas_drives
|
||||
|
||||
### Set email headers ###
|
||||
printf "%s\n" "To: ${email}
|
||||
Subject: ${subject}
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary=\"$boundary\"
|
||||
|
||||
--${boundary}
|
||||
Content-Type: text/html; charset=\"US-ASCII\"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: inline
|
||||
<html><head></head><body><pre style=\"font-size:14px; white-space:pre\">" > ${logfile}
|
||||
|
||||
if [ $Drive_count -eq 0 ]; then
|
||||
echo "##### No SMART-enabled disks found on this system #####" >> "$logfile"
|
||||
fi
|
||||
|
||||
###### Summary for SATA drives ######
|
||||
if [ $SATA_count -gt 0 ]; then
|
||||
(
|
||||
echo "########## SMART status report summary for all SATA drives on server ${freenashost} ##########"
|
||||
echo ""
|
||||
echo "+------+------------------------+----+------+-----+-----+-------+-------+--------+------+----------+------+-----------+----+"
|
||||
echo "|Device|Serial |Temp| Power|Start|Spin |ReAlloc|Current|Offline |Seek |Total |High | Command|Last|"
|
||||
echo "| |Number | | On |Stop |Retry|Sectors|Pending|Uncorrec|Errors|Seeks |Fly | Timeout|Test|"
|
||||
echo "| | | | Hours|Count|Count| |Sectors|Sectors | | |Writes| Count |Age |"
|
||||
echo "+------+------------------------+----+------+-----+-----+-------+-------+--------+------+----------+------+-----------+----+"
|
||||
) >> "$logfile"
|
||||
|
||||
###### Detail information for each SATA drive ######
|
||||
for drive in $SATA_list; do
|
||||
(
|
||||
devid=$(basename "$drive")
|
||||
lastTestHours=$("$smartctl" -l selftest "$drive" | grep "# 1" | awk '{print $9}')
|
||||
"$smartctl" -A -i -v 7,hex48 "$drive" | \
|
||||
awk -v device="$devid" -v tempWarn="$tempWarn" -v tempCrit="$tempCrit" -v sectorsCrit="$sectorsCrit" \
|
||||
-v testAgeWarn="$testAgeWarn" -v warnSymbol="$warnSymbol" -v critSymbol="$critSymbol" \
|
||||
-v lastTestHours="$lastTestHours" '
|
||||
/Serial Number:/{serial=$3}
|
||||
/190 Airflow_Temperature/{temp=$10}
|
||||
/194 Temperature/{temp=$10}
|
||||
/Power_On_Hours/{split($10,a,"+");sub(/h/,"",a[1]);onHours=a[1];}
|
||||
/Start_Stop_Count/{startStop=$10}
|
||||
/Spin_Retry_Count/{spinRetry=$10}
|
||||
/Reallocated_Sector/{reAlloc=$10}
|
||||
/Current_Pending_Sector/{pending=$10}
|
||||
/Offline_Uncorrectable/{offlineUnc=$10}
|
||||
/Seek_Error_Rate/{seekErrors=("0x" substr($10,3,4));totalSeeks=("0x" substr($10,7))}
|
||||
/High_Fly_Writes/{hiFlyWr=$10}
|
||||
/Command_Timeout/{cmdTimeout=$10}
|
||||
END {
|
||||
testAge=sprintf("%.0f", (onHours - lastTestHours) / 24);
|
||||
if (temp > tempCrit || reAlloc > sectorsCrit || pending > sectorsCrit || offlineUnc > sectorsCrit)
|
||||
device=device " " critSymbol;
|
||||
else if (temp > tempWarn || reAlloc > 0 || pending > 0 || offlineUnc > 0 || testAge > testAgeWarn)
|
||||
device=device " " warnSymbol;
|
||||
seekErrors=sprintf("%d", seekErrors);
|
||||
totalSeeks=sprintf("%d", totalSeeks);
|
||||
if (totalSeeks == "0") {
|
||||
seekErrors="N/A";
|
||||
totalSeeks="N/A";
|
||||
}
|
||||
if (temp > tempWarn || temp > tempCrit) temp=temp"*"
|
||||
if (reAlloc > 0 || reAlloc > sectorsCrit) reAlloc=reAlloc"*"
|
||||
if (pending > 0 || pending > sectorsCrit) pending=pending"*"
|
||||
if (offlineUnc > 0 || offlineUnc > sectorsCrit) offlineUnc=offlineUnc"*"
|
||||
if (testAge > testAgeWarn) testAge=testAge"*"
|
||||
if (hiFlyWr == "") hiFlyWr="N/A";
|
||||
if (cmdTimeout == "") cmdTimeout="N/A";
|
||||
printf "|%-6s|%-24s|%-4s|%6s|%5s|%5s|%7s|%7s|%8s|%6s|%10s|%6s|%11s|%4s|\n",
|
||||
device, serial, temp, onHours, startStop, spinRetry, reAlloc, pending, offlineUnc,
|
||||
seekErrors, totalSeeks, hiFlyWr, cmdTimeout, testAge;
|
||||
}'
|
||||
) >> "$logfile"
|
||||
done
|
||||
(
|
||||
echo "+------+------------------------+----+------+-----+-----+-------+-------+--------+------+----------+------+-----------+----+"
|
||||
) >> "$logfile"
|
||||
fi
|
||||
|
||||
###### Summary for SAS drives ######
|
||||
if [ $SAS_count -gt 0 ]; then
|
||||
(
|
||||
if [ $SATA_count -gt 0 ]; then
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "########## SMART status report summary for all SAS drives on server ${freenashost} ##########"
|
||||
echo ""
|
||||
echo "+------+------------------------+----+-----+------+------+------+------+------+------+"
|
||||
echo "|Device|Serial |Temp|Start|Load |Defect|Uncorr|Uncorr|Uncorr|Non |"
|
||||
echo "| |Number | |Stop |Unload|List |Read |Write |Verify|Medium|"
|
||||
echo "| | | |Count|Count |Elems |Errors|Errors|Errors|Errors|"
|
||||
echo "+------+------------------------+----+-----+------+------+------+------+------+------+"
|
||||
) >> "$logfile"
|
||||
|
||||
###### Detail information for each SAS drive ######
|
||||
for drive in $SAS_list; do
|
||||
(
|
||||
devid=$(basename "$drive")
|
||||
"$smartctl" -a "$drive" | \
|
||||
awk -v device="$devid" -v tempWarn="$tempWarn" -v tempCrit="$tempCrit" \
|
||||
-v warnSymbol="$warnSymbol" -v critSymbol="$critSymbol" '\
|
||||
/Serial number:/{serial=$3}
|
||||
/Current Drive Temperature:/{temp=$4} \
|
||||
/start-stop cycles:/{startStop=$4} \
|
||||
/load-unload cycles:/{loadUnload=$4} \
|
||||
/grown defect list:/{defectList=$6} \
|
||||
/read:/{readErrors=$8} \
|
||||
/write:/{writeErrors=$8} \
|
||||
/verify:/{verifyErrors=$8} \
|
||||
/Non-medium error count:/{nonMediumErrors=$4} \
|
||||
END {
|
||||
if (temp > tempCrit)
|
||||
device=device " " critSymbol;
|
||||
else if (temp > tempWarn)
|
||||
device=device " " warnSymbol;
|
||||
printf "|%-6s|%-24s| %3s|%5s|%6s|%6s|%6s|%6s|%6s|%6s|\n",
|
||||
device, serial, temp, startStop, loadUnload, defectList, \
|
||||
readErrors, writeErrors, verifyErrors, nonMediumErrors;
|
||||
}'
|
||||
) >> "$logfile"
|
||||
done
|
||||
(
|
||||
echo "+------+------------------------+----+-----+------+------+------+------+------+------+"
|
||||
) >> "$logfile"
|
||||
fi
|
||||
|
||||
if [ $SATA_count -gt 0 ] || [ $SAS_count -gt 0 ]; then
|
||||
|
||||
###### Emit SATA drive information ######
|
||||
for drive in $SATA_list; do
|
||||
vendor=$("$smartctl" -i "$drive" | grep "Vendor:" | awk '{print $NF}')
|
||||
if [ -z "$vendor" ]; then
|
||||
dfamily=$("$smartctl" -i "$drive" | grep "Model Family" | awk '{print $3, $4, $5, $6, $7}' | sed -e 's/[[:space:]]*$//')
|
||||
dmodel=$("$smartctl" -i "$drive" | grep "Device Model" | awk '{print $3, $4, $5, $6, $7}' | sed -e 's/[[:space:]]*$//')
|
||||
if [ -z "$dfamily" ]; then
|
||||
dinfo=$dmodel
|
||||
else
|
||||
dinfo="$dfamily ($dmodel)"
|
||||
fi
|
||||
else
|
||||
product=$("$smartctl" -i "$drive" | grep "Product:" | awk '{print $NF}')
|
||||
revision=$("$smartctl" -i "$drive" | grep "Revision:" | awk '{print $NF}')
|
||||
dinfo="$vendor $product $revision"
|
||||
fi
|
||||
serial=$("$smartctl" -i "$drive" | grep "Serial Number" | awk '{print $3}')
|
||||
(
|
||||
echo ""
|
||||
echo "########## SATA drive $drive Serial: $serial"
|
||||
echo "########## ${dinfo}"
|
||||
"$smartctl" -n never -H -A -l error "$drive"
|
||||
"$smartctl" -n never -l selftest "$drive" | grep "# 1 \\|Num" | cut -c6-
|
||||
) >> "$logfile"
|
||||
done
|
||||
|
||||
###### Emit SAS drive information ######
|
||||
for drive in $SAS_list; do
|
||||
devid=$(basename "$drive")
|
||||
brand=$("$smartctl" -i "$drive" | grep "Product" | sed "s/^.* //")
|
||||
serial=$("$smartctl" -i "$drive" | grep "Serial number" | sed "s/^.* //")
|
||||
(
|
||||
echo ""
|
||||
echo "########## SMART status for SAS drive $drive $serial (${brand}) ##########"
|
||||
"$smartctl" -n never -H -A -l error "$drive"
|
||||
"$smartctl" -n never -l selftest "$drive" | grep "# 1 \\|Num" | cut -c6-
|
||||
) >> "$logfile"
|
||||
done
|
||||
fi
|
||||
|
||||
sed -i '' -e '/smartctl 7.*/d' "$logfile"
|
||||
sed -i '' -e '/smartctl 6.*/d' "$logfile"
|
||||
sed -i '' -e '/smartctl 5.*/d' "$logfile"
|
||||
sed -i '' -e '/smartctl 4.*/d' "$logfile"
|
||||
sed -i '' -e '/Copyright/d' "$logfile"
|
||||
sed -i '' -e '/=== START OF READ/d' "$logfile"
|
||||
sed -i '' -e '/SMART Attributes Data/d' "$logfile"
|
||||
sed -i '' -e '/Vendor Specific SMART/d' "$logfile"
|
||||
sed -i '' -e '/SMART Error Log Version/d' "$logfile"
|
||||
|
||||
printf "%s\n" "</pre></body></html>
|
||||
--${boundary}--" >> ${logfile}
|
||||
|
||||
### Send report ###
|
||||
if [ -z "${email}" ]; then
|
||||
echo "No email address specified, information available in ${logfile}"
|
||||
else
|
||||
sendmail -t -oi < "$logfile"
|
||||
rm "$logfile"
|
||||
fi
|
93
ansible/roles/truenas/templates/scripts/report_ups.sh
Normal file
93
ansible/roles/truenas/templates/scripts/report_ups.sh
Normal file
@@ -0,0 +1,93 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Send UPS report to designated email address
|
||||
# Reference: http://networkupstools.org/docs/developer-guide.chunked/apas01.html
|
||||
|
||||
### Parameters ###
|
||||
|
||||
# Specify your email address here:
|
||||
email="truenas@{{ SECRET_EMAIL_DOMAIN }}"
|
||||
|
||||
# Set to a value greater than zero to include all available UPSC
|
||||
# variables in the report:
|
||||
senddetail=0
|
||||
|
||||
freenashost=$(hostname -s)
|
||||
freenashostuc=$(hostname -s | tr '[:lower:]' '[:upper:]')
|
||||
boundary="===== MIME boundary; FreeNAS server ${freenashost} ====="
|
||||
logfile="/tmp/ups_report.tmp"
|
||||
subject="UPS Status Report for ${freenashostuc}"
|
||||
|
||||
### Set email headers ###
|
||||
printf "%s\n" "To: ${email}
|
||||
Subject: ${subject}
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary=\"$boundary\"
|
||||
|
||||
--${boundary}
|
||||
Content-Type: text/html; charset=\"US-ASCII\"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: inline
|
||||
<html><head></head><body><pre style=\"font-size:14px; white-space:pre\">" >> ${logfile}
|
||||
|
||||
# Get a list of all ups devices installed on the system:
|
||||
|
||||
upslist=$(upsc -l "${freenashost}")
|
||||
|
||||
### Set email body ###
|
||||
(
|
||||
date "+Time: %Y-%m-%d %H:%M:%S"
|
||||
echo ""
|
||||
for ups in $upslist; do
|
||||
ups_type=$(upsc "${ups}" device.type 2> /dev/null | tr '[:lower:]' '[:upper:]')
|
||||
ups_mfr=$(upsc "${ups}" ups.mfr 2> /dev/null)
|
||||
ups_model=$(upsc "${ups}" ups.model 2> /dev/null)
|
||||
ups_serial=$(upsc "${ups}" ups.serial 2> /dev/null)
|
||||
ups_status=$(upsc "${ups}" ups.status 2> /dev/null)
|
||||
ups_load=$(upsc "${ups}" ups.load 2> /dev/null)
|
||||
ups_realpower=$(upsc "${ups}" ups.realpower 2> /dev/null)
|
||||
ups_realpowernominal=$(upsc "${ups}" ups.realpower.nominal 2> /dev/null)
|
||||
ups_batterycharge=$(upsc "${ups}" battery.charge 2> /dev/null)
|
||||
ups_batteryruntime=$(upsc "${ups}" battery.runtime 2> /dev/null)
|
||||
ups_batteryvoltage=$(upsc "${ups}" battery.voltage 2> /dev/null)
|
||||
ups_inputvoltage=$(upsc "${ups}" input.voltage 2> /dev/null)
|
||||
ups_outputvoltage=$(upsc "${ups}" output.voltage 2> /dev/null)
|
||||
printf "=== %s %s, model %s, serial number %s\n\n" "${ups_mfr}" "${ups_type}" "${ups_model}" "${ups_serial} ==="
|
||||
echo "Name: ${ups}"
|
||||
echo "Status: ${ups_status}"
|
||||
echo "Output Load: ${ups_load}%"
|
||||
if [ ! -z "${ups_realpower}" ]; then
|
||||
echo "Real Power: ${ups_realpower}W"
|
||||
fi
|
||||
if [ ! -z "${ups_realpowernominal}" ]; then
|
||||
echo "Real Power: ${ups_realpowernominal}W (nominal)"
|
||||
fi
|
||||
if [ ! -z "${ups_inputvoltage}" ]; then
|
||||
echo "Input Voltage: ${ups_inputvoltage}V"
|
||||
fi
|
||||
if [ ! -z "${ups_outputvoltage}" ]; then
|
||||
echo "Output Voltage: ${ups_outputvoltage}V"
|
||||
fi
|
||||
echo "Battery Runtime: ${ups_batteryruntime}s"
|
||||
echo "Battery Charge: ${ups_batterycharge}%"
|
||||
echo "Battery Voltage: ${ups_batteryvoltage}V"
|
||||
echo ""
|
||||
if [ $senddetail -gt 0 ]; then
|
||||
echo "=== ALL AVAILABLE UPS VARIABLES ==="
|
||||
upsc "${ups}"
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
) >> ${logfile}
|
||||
|
||||
printf "%s\n" "</pre></body></html>
|
||||
--${boundary}--" >> ${logfile}
|
||||
|
||||
### Send report ###
|
||||
if [ -z "${email}" ]; then
|
||||
echo "No email address specified, information available in ${logfile}"
|
||||
else
|
||||
sendmail -t -oi < ${logfile}
|
||||
rm ${logfile}
|
||||
fi
|
||||
|
17
ansible/roles/truenas/templates/scripts/snapshots_prune.sh
Normal file
17
ansible/roles/truenas/templates/scripts/snapshots_prune.sh
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
# DEBUG
|
||||
# set -x
|
||||
|
||||
# Variables
|
||||
SCRIPT_PATH="{{ scripts_dir }}"
|
||||
INTERVAL="{{ snapshots_interval }}"
|
||||
POOL_NAME="{{ pool_name }}"
|
||||
|
||||
# Prune
|
||||
|
||||
${SCRIPT_PATH}/snapshots_prune.py --recursive --intervals ${INTERVAL} ${POOL_NAME}
|
||||
${SCRIPT_PATH}/snapshots_clearempty.py --recursive ${POOL_NAME}
|
||||
{% if ansible_facts['nodename'] == "truenas.{{ SECRET_DOMAIN }}" %}
|
||||
${SCRIPT_PATH}/snapshots_prune.py --recursive --intervals daily:14 storage/video
|
||||
{% endif %}
|
49
ansible/roles/truenas/templates/telegraf/telegraf.conf
Normal file
49
ansible/roles/truenas/templates/telegraf/telegraf.conf
Normal file
@@ -0,0 +1,49 @@
|
||||
[agent]
|
||||
interval = "20s"
|
||||
round_interval = true
|
||||
metric_batch_size = 1000
|
||||
metric_buffer_limit = 10000
|
||||
collection_jitter = "0s"
|
||||
flush_interval = "30s"
|
||||
flush_jitter = "0s"
|
||||
precision = ""
|
||||
debug = false
|
||||
quiet = false
|
||||
hostname = "{{ ansible_facts['nodename'] }}"
|
||||
omit_hostname = false
|
||||
|
||||
[[outputs.prometheus_client]]
|
||||
listen = ":9273"
|
||||
metric_version = 2
|
||||
path = "/metrics"
|
||||
string_as_label = true
|
||||
expiration_interval = "60m"
|
||||
|
||||
[[inputs.cpu]]
|
||||
percpu = true
|
||||
totalcpu = true
|
||||
|
||||
[[inputs.diskio]]
|
||||
|
||||
[[inputs.exec]]
|
||||
commands = ["{{ telegraf_dir }}/cputemp"]
|
||||
data_format = "influx"
|
||||
|
||||
[[inputs.exec]]
|
||||
commands = ["{{ scripts_dir }}/telegraf_hddtemp.bash"]
|
||||
name_override = "disktemp"
|
||||
timeout = "5s"
|
||||
data_format = "json"
|
||||
tag_keys = ["disk"]
|
||||
|
||||
[[inputs.mem]]
|
||||
|
||||
[[inputs.net]]
|
||||
interfaces = ["em0", "igb0"]
|
||||
|
||||
[[inputs.system]]
|
||||
|
||||
[[inputs.netstat]]
|
||||
|
||||
[[inputs.zfs]]
|
||||
poolMetrics = true
|
24
ansible/roles/truenas/templates/wireguard/ip-check.bash
Normal file
24
ansible/roles/truenas/templates/wireguard/ip-check.bash
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
# Check status of interface
|
||||
# {{ wg_interface }}: name of the interface to check
|
||||
# {{ dns_hostname }}: the name of the peer whose IP should be checked
|
||||
|
||||
cip=$(wg show {{ wg_interface }} endpoints | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}")
|
||||
echo "Wireguard peer IP from Interface: $cip"
|
||||
pingip=$(ping -c 1 {{ ping_ip }} &> /dev/null && echo success || echo fail) #change ip to target server
|
||||
digIP=$(dig +short {{ dns_hostname }}) #the peer address must be set
|
||||
echo "$digIP"
|
||||
if [ "$digIP" != "$cip" ]
|
||||
then
|
||||
echo "IPs doesn't match, restarting wireguard"
|
||||
wg-quick down {{ homelab_homedir }}/{{ wg_interface }}.conf
|
||||
wg-quick up {{ homelab_homedir }}/{{ wg_interface }}.conf
|
||||
elif [ "$pingip" != "success" ]
|
||||
then
|
||||
echo "Ping failed, restarting wireguard..."
|
||||
wg-quick down {{ homelab_homedir }}/{{ wg_interface }}.conf
|
||||
wg-quick up {{ homelab_homedir }}/{{ wg_interface }}.conf
|
||||
else
|
||||
echo "OK"
|
||||
#nothing else todo
|
||||
fi
|
@@ -0,0 +1,11 @@
|
||||
[Interface]
|
||||
Address = 10.10.0.2/32
|
||||
ListenPort = 51820
|
||||
PrivateKey = 8Gw/9MJpo8AwSmEY8W/zgPu6z0Lvn7E2LvRRDpkMhFo=
|
||||
DNS = 192.168.8.1, {{ SECRET_DOMAIN }}
|
||||
|
||||
[Peer]
|
||||
PublicKey = K7kgSuPwH2NA7FeLHwvGMX02kvhD8DxHgL/wflsgx34=
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
Endpoint = services.{{ SECRET_DOMAIN }}:51820
|
||||
PersistentKeepalive = 25
|
42
ansible/roles/workstation/defaults/main.yml
Normal file
42
ansible/roles/workstation/defaults/main.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
fonts_dir: ~/.local/share/fonts
|
||||
icons_dir: ~/.local/share/icons
|
||||
newaita_iconset_url: "https://github.com/cbrnix/Newaita/archive/1.09.20a.tar.gz"
|
||||
nas_hostname: truenas
|
||||
mnt_dir: /mnt
|
||||
nas_dir: ~/NAS
|
||||
nfs_shares:
|
||||
- {
|
||||
src: "{{ nas_hostname }}:/mnt/storage/downloads",
|
||||
path: "{{ mnt_dir }}/downloads",
|
||||
link: "{{ nas_dir }}/downloads",
|
||||
}
|
||||
- {
|
||||
src: "{{ nas_hostname }}:/mnt/storage/shared-documents",
|
||||
path: "{{ mnt_dir }}/shared-documents",
|
||||
link: "{{ nas_dir }}/shared-documents",
|
||||
}
|
||||
- {
|
||||
src: "{{ nas_hostname }}:/mnt/storage/home/claude",
|
||||
path: "{{ mnt_dir }}/home-claude",
|
||||
link: "{{ nas_dir }}/home-claude",
|
||||
}
|
||||
- {
|
||||
src: "{{ nas_hostname }}:/mnt/storage/home/helene",
|
||||
path: "{{ mnt_dir }}/home-helene",
|
||||
link: "{{ nas_dir }}/home-helene",
|
||||
}
|
||||
- {
|
||||
src: "{{ nas_hostname }}:/mnt/storage/photo",
|
||||
path: "{{ mnt_dir }}/photo",
|
||||
link: "{{ nas_dir }}/photo",
|
||||
}
|
||||
- {
|
||||
src: "{{ nas_hostname }}:/mnt/storage/music",
|
||||
path: "{{ mnt_dir }}/music",
|
||||
link: "/home/claude/Music",
|
||||
}
|
||||
- {
|
||||
src: "{{ nas_hostname }}:/mnt/storage/video",
|
||||
path: "{{ mnt_dir }}/video",
|
||||
link: "/home/claude/Videos",
|
||||
}
|
11
ansible/roles/workstation/files/scripts/backup-local-usb-disk-one.bash
Executable file
11
ansible/roles/workstation/files/scripts/backup-local-usb-disk-one.bash
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir -p /run/media/claude/local-backups/{backups,documents,downloads,photo,piracy,jails}
|
||||
|
||||
# Disk one (4TB)
|
||||
sudo rsync -avhP /mnt/backups/ /run/media/claude/local-backups/backups/ --delete
|
||||
sudo rsync -avhP /mnt/documents/ /run/media/claude/local-backups/documents/ --delete
|
||||
sudo rsync -avhP /mnt/downloads/ /run/media/claude/local-backups/downloads/ --delete
|
||||
sudo rsync -avhP /mnt/photo/ /run/media/claude/local-backups/photo/ --delete
|
||||
sudo rsync -avhP /mnt/piracy/ /run/media/claude/local-backups/piracy/ --delete
|
||||
sudo rsync -avhP /mnt/iocage/jails/ /run/media/claude/local-backups/jails/ --delete
|
9
ansible/roles/workstation/files/scripts/backup-local-usb-disk-two.bash
Executable file
9
ansible/roles/workstation/files/scripts/backup-local-usb-disk-two.bash
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Disk two (2.5TB)
|
||||
mkdir -p /run/media/claude/local-backups/music
|
||||
mkdir -p /run/media/claude/local-backups/home/{claude,helene}
|
||||
|
||||
sudo rsync -avhP /mnt/home-claude/ /run/media/claude/local-backups/home/claude/ --delete
|
||||
sudo rsync -avhP /mnt/home-helene/ /run/media/claude/local-backups/home/helene/ --delete
|
||||
sudo rsync -avhP /mnt/music/ /run/media/claude/local-backups/music/ --delete
|
3
ansible/roles/workstation/files/scripts/update-pip.bash
Normal file
3
ansible/roles/workstation/files/scripts/update-pip.bash
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
pip3 list --outdated --user --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip3 install -U --user
|
53
ansible/roles/workstation/files/throttled/throttled.conf
Normal file
53
ansible/roles/workstation/files/throttled/throttled.conf
Normal file
@@ -0,0 +1,53 @@
|
||||
[GENERAL]
|
||||
# Enable or disable the script execution
|
||||
Enabled: True
|
||||
# SYSFS path for checking if the system is running on AC power
|
||||
Sysfs_Power_Path: /sys/class/power_supply/AC*/online
|
||||
|
||||
## Settings to apply while connected to Battery power
|
||||
[BATTERY]
|
||||
# Update the registers every this many seconds
|
||||
Update_Rate_s: 30
|
||||
# Max package power for time window #1
|
||||
PL1_Tdp_W: 29
|
||||
# Time window #1 duration
|
||||
PL1_Duration_s: 28
|
||||
# Max package power for time window #2
|
||||
PL2_Tdp_W: 44
|
||||
# Time window #2 duration
|
||||
PL2_Duration_S: 0.002
|
||||
# Max allowed temperature before throttling
|
||||
Trip_Temp_C: 85
|
||||
# Set cTDP to normal=0, down=1 or up=2 (EXPERIMENTAL)
|
||||
cTDP: 0
|
||||
|
||||
## Settings to apply while connected to AC power
|
||||
[AC]
|
||||
# Update the registers every this many seconds
|
||||
Update_Rate_s: 5
|
||||
# Max package power for time window #1
|
||||
PL1_Tdp_W: 44
|
||||
# Time window #1 duration
|
||||
PL1_Duration_s: 28
|
||||
# Max package power for time window #2
|
||||
PL2_Tdp_W: 44
|
||||
# Time window #2 duration
|
||||
PL2_Duration_S: 0.002
|
||||
# Max allowed temperature before throttling
|
||||
Trip_Temp_C: 95
|
||||
# Set HWP energy performance hints to 'performance' on high load (EXPERIMENTAL)
|
||||
HWP_Mode: False
|
||||
# Set cTDP to normal=0, down=1 or up=2 (EXPERIMENTAL)
|
||||
cTDP: 0
|
||||
|
||||
[UNDERVOLT]
|
||||
# CPU core voltage offset (mV)
|
||||
CORE: -105
|
||||
# Integrated GPU voltage offset (mV)
|
||||
GPU: -85
|
||||
# CPU cache voltage offset (mV)
|
||||
CACHE: -105
|
||||
# System Agent voltage offset (mV)
|
||||
UNCORE: -85
|
||||
# Analog I/O voltage offset (mV)
|
||||
ANALOGIO: 0
|
@@ -0,0 +1,10 @@
|
||||
[Interface]
|
||||
Address = 10.10.0.4/32
|
||||
ListenPort = 51820
|
||||
PrivateKey = kPbM3V+bV74avE/GXFwhOrmaRSf3p34bm/aR3A72GG4=
|
||||
DNS = 10.10.0.1
|
||||
|
||||
[Peer]
|
||||
PublicKey = K7kgSuPwH2NA7FeLHwvGMX02kvhD8DxHgL/wflsgx34=
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
Endpoint = services.{{ SECRET_DOMAIN }}:51820
|
7
ansible/roles/workstation/files/yum/vscodium.repo
Normal file
7
ansible/roles/workstation/files/yum/vscodium.repo
Normal file
@@ -0,0 +1,7 @@
|
||||
[gitlab.com_paulcarroty_vscodium_repo]
|
||||
name=gitlab.com_paulcarroty_vscodium_repo
|
||||
baseurl=https://paulcarroty.gitlab.io/vscodium-deb-rpm-repo/rpms/
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
repo_gpgcheck=1
|
||||
gpgkey=https://gitlab.com/paulcarroty/vscodium-deb-rpm-repo/-/raw/master/pub.gpg
|
2
ansible/roles/workstation/files/yum/yum.conf
Normal file
2
ansible/roles/workstation/files/yum/yum.conf
Normal file
@@ -0,0 +1,2 @@
|
||||
#https://www.2daygeek.com/remove-delete-old-unused-kernels-centos-fedora-rhel/
|
||||
installonly_limit=3
|
15
ansible/roles/workstation/tasks/chezmoi.yml
Normal file
15
ansible/roles/workstation/tasks/chezmoi.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
- name: configuration | include vars
|
||||
ansible.builtin.include_vars:
|
||||
file: vars/{{ ansible_facts['nodename'] }}.yml
|
||||
|
||||
- name: configuration | create chezmoi directory
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: ~/.config/chezmoi
|
||||
|
||||
- name: configuration | templating chezmoi.toml
|
||||
ansible.builtin.template:
|
||||
src: chezmoi.toml.j2
|
||||
dest: ~/.config/chezmoi/chezmoi.toml
|
||||
mode: 0600
|
16
ansible/roles/workstation/tasks/gnome.yml
Normal file
16
ansible/roles/workstation/tasks/gnome.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
- name: gnome | create directories
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: "{{ item }}"
|
||||
loop:
|
||||
- "{{ fonts_dir }}"
|
||||
- "{{ icons_dir }}"
|
||||
|
||||
- name: gnome | download nerd fonts
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ item }}"
|
||||
dest: "{{ fonts_dir }}"
|
||||
loop:
|
||||
- https://github.com/ryanoasis/nerd-fonts/raw/master/patched-fonts/FiraCode/Retina/complete/Fira%20Code%20Retina%20Nerd%20Font%20Complete.ttf
|
||||
- https://github.com/ryanoasis/nerd-fonts/raw/master/patched-fonts/FiraCode/Retina/complete/Fira%20Code%20Retina%20Nerd%20Font%20Complete%20Mono.ttf
|
13
ansible/roles/workstation/tasks/gpg.yml
Normal file
13
ansible/roles/workstation/tasks/gpg.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: gpg | create directory
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: ~/.gnupg
|
||||
mode: 0700
|
||||
|
||||
# https://github.com/drduh/YubiKey-Guide#using-keys
|
||||
- name: gpg | get gpg configuration
|
||||
ansible.builtin.get_url:
|
||||
url: https://raw.githubusercontent.com/drduh/config/master/gpg.conf
|
||||
dest: ~/.gnupg/gpg.conf
|
||||
mode: 0600
|
56
ansible/roles/workstation/tasks/main.yml
Normal file
56
ansible/roles/workstation/tasks/main.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
- ansible.builtin.include_tasks: system.yml
|
||||
tags:
|
||||
- system
|
||||
|
||||
- ansible.builtin.include_tasks: repositories.yml
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- ansible.builtin.include_tasks: packages-prerequisites.yml
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- ansible.builtin.include_tasks: packages-common.yml
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- ansible.builtin.include_tasks: packages-claude-fixe-fedora.yml
|
||||
tags:
|
||||
- packages
|
||||
when: ansible_facts['nodename'] == "claude-fixe-fedora"
|
||||
|
||||
- ansible.builtin.include_tasks: packages-claude-thinkpad-fedora.yml
|
||||
tags:
|
||||
- packages
|
||||
when: ansible_facts['nodename'] == "claude-thinkpad-fedora"
|
||||
|
||||
- ansible.builtin.include_tasks: packages-post.yml
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- ansible.builtin.include_tasks: chezmoi.yml
|
||||
tags:
|
||||
- chezmoi
|
||||
|
||||
- ansible.builtin.include_tasks: gpg.yml
|
||||
tags:
|
||||
- gpg
|
||||
|
||||
- ansible.builtin.include_tasks: shell.yml
|
||||
tags:
|
||||
- shell
|
||||
|
||||
- ansible.builtin.include_tasks: gnome.yml
|
||||
tags:
|
||||
- gnome
|
||||
|
||||
- ansible.builtin.include_tasks: nfs.yml
|
||||
tags:
|
||||
- nfs
|
||||
when: ansible_facts['nodename'] == "claude-fixe-fedora"
|
||||
|
||||
- ansible.builtin.include_tasks: wireguard.yml
|
||||
tags:
|
||||
- wireguard
|
||||
when: ansible_facts['nodename'] == "claude-thinkpad-fedora"
|
63
ansible/roles/workstation/tasks/nfs.yml
Normal file
63
ansible/roles/workstation/tasks/nfs.yml
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
- name: nfs | create root directory
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: "{{ mnt_dir }}"
|
||||
mode: 0777
|
||||
become: true
|
||||
|
||||
- name: nfs | create directories
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: "{{ item.path }}"
|
||||
loop: "{{ nfs_shares }}"
|
||||
become: true
|
||||
|
||||
- name: nfs | mount shares
|
||||
ansible.builtin.mount:
|
||||
state: present
|
||||
path: "{{ item.path }}"
|
||||
src: "{{ item.src }}"
|
||||
fstype: nfs4
|
||||
opts: _netdev
|
||||
with_items: "{{ nfs_shares }}"
|
||||
become: true
|
||||
|
||||
- name: nfs | create links dir
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: "{{ nas_dir }}"
|
||||
|
||||
- name: nfs | stat music folder
|
||||
ansible.builtin.stat:
|
||||
path: ~/Music
|
||||
register: music
|
||||
|
||||
- name: nfs | remove music folder
|
||||
file:
|
||||
path: ~/Music
|
||||
state: absent
|
||||
when: music.stat.isdir is defined and music.stat.isdir
|
||||
|
||||
- name: nfs | stat videos folder
|
||||
ansible.builtin.stat:
|
||||
path: ~/Videos
|
||||
register: videos
|
||||
|
||||
- name: nfs | remove videos folder
|
||||
file:
|
||||
path: ~/Videos
|
||||
state: absent
|
||||
when: videos.stat.isdir is defined and videos.stat.isdir
|
||||
|
||||
- name: nfs | stat music folder
|
||||
ansible.builtin.stat:
|
||||
path: ~/Music
|
||||
register: music
|
||||
|
||||
- name: nfs | create links
|
||||
ansible.builtin.file:
|
||||
state: link
|
||||
src: "{{ item.path }}"
|
||||
dest: "{{ item.link }}"
|
||||
with_items: "{{ nfs_shares }}"
|
@@ -0,0 +1,27 @@
|
||||
---
|
||||
- name: packages-claude-fixe-fedora | dnf
|
||||
ansible.builtin.dnf:
|
||||
name:
|
||||
- akmod-nvidia
|
||||
- libva-utils
|
||||
- libva-vdpau-driver
|
||||
- handbrake
|
||||
- vdpauinfo
|
||||
become: true
|
||||
|
||||
- name: packages-claude-fixe-fedora | flatpak
|
||||
community.general.flatpak:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
loop:
|
||||
- https://dl.flathub.org/repo/appstream/fr.handbrake.ghb.flatpakref
|
||||
- https://dl.flathub.org/repo/appstream/org.bunkus.mkvtoolnix-gui.flatpakref
|
||||
become: true
|
||||
|
||||
- name: packages-claude-fixe-fedora | brew
|
||||
community.general.homebrew:
|
||||
name:
|
||||
- jpeg-archive
|
||||
- parallel
|
||||
path: /home/{{ lookup('env', 'USER') }}/.linuxbrew/bin
|
||||
state: present
|
@@ -0,0 +1,14 @@
|
||||
---
|
||||
- name: packages-claude-thinkpad-fedora | dnf
|
||||
ansible.builtin.dnf:
|
||||
name:
|
||||
- tlp
|
||||
- wireguard-tools
|
||||
become: true
|
||||
|
||||
- name: packages-claude-thinkpad-fedora | tlp-ui
|
||||
ansible.builtin.pip:
|
||||
name:
|
||||
- git+https://github.com/d4nj1/TLPUI.git
|
||||
state: present
|
||||
become: true
|
99
ansible/roles/workstation/tasks/packages-common.yml
Normal file
99
ansible/roles/workstation/tasks/packages-common.yml
Normal file
@@ -0,0 +1,99 @@
|
||||
---
|
||||
- name: packages-common | dnf
|
||||
ansible.builtin.dnf:
|
||||
name:
|
||||
- codium
|
||||
- mpv
|
||||
- resilio-sync
|
||||
- gnome-tweak-tool
|
||||
- la-capitaine-cursor-theme
|
||||
- git
|
||||
- fish
|
||||
- alacritty
|
||||
- redhat-rpm-config
|
||||
- python3-devel
|
||||
- python3-virtualenv
|
||||
- ffmpeg-libs
|
||||
- nano
|
||||
- nfs-utils
|
||||
- libgtop2-devel
|
||||
- fuse-exfat
|
||||
- exfat-utils
|
||||
- openssl
|
||||
- openssl-devel
|
||||
- libacl-devel
|
||||
- gcc-c++
|
||||
- picard
|
||||
- pinta
|
||||
- calibre
|
||||
- mediawriter
|
||||
- hugo
|
||||
- stress
|
||||
- vlc
|
||||
- p7zip
|
||||
- p7zip-plugins
|
||||
- lsd
|
||||
- bat
|
||||
- fzf
|
||||
- fd-find
|
||||
- remmina
|
||||
- yp-tools
|
||||
- ffmpeg
|
||||
- deadbeef
|
||||
- nmap
|
||||
- jq
|
||||
- gnupg
|
||||
- steam
|
||||
- npm
|
||||
- ShellCheck
|
||||
- gnome-extensions-app
|
||||
- neovim
|
||||
- brave-browser
|
||||
- starship
|
||||
- tmux
|
||||
- cawbird
|
||||
- age
|
||||
state: present
|
||||
update_cache: yes
|
||||
become: true
|
||||
|
||||
- name: packages-common | python
|
||||
ansible.builtin.pip:
|
||||
name:
|
||||
- borgbackup
|
||||
- yt-dlp
|
||||
- s-tui
|
||||
- pylint
|
||||
- pre-commit
|
||||
- comictagger
|
||||
state: present
|
||||
extra_args: --user
|
||||
|
||||
- name: packages-common | flatpak
|
||||
community.general.flatpak:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
loop:
|
||||
- https://dl.flathub.org/repo/appstream/com.borgbase.Vorta.flatpakref
|
||||
- https://dl.flathub.org/repo/appstream/com.discordapp.Discord.flatpakref
|
||||
- https://dl.flathub.org/repo/appstream/com.bitwarden.desktop.flatpakref
|
||||
- https://dl.flathub.org/repo/appstream/net.mediaarea.MediaInfo.flatpakref
|
||||
- https://dl.flathub.org/repo/appstream/net.cozic.joplin_desktop.flatpakref
|
||||
- https://dl.flathub.org/repo/appstream/uk.co.ibboard.cawbird.flatpakref
|
||||
become: true
|
||||
|
||||
- name: packages-common | brew
|
||||
community.general.homebrew:
|
||||
name:
|
||||
- minio/stable/mc
|
||||
- kubectl
|
||||
- helm
|
||||
- kustomize
|
||||
- fluxcd/tap/flux
|
||||
- sops
|
||||
- gh
|
||||
- derailed/popeye/popeye
|
||||
- chezmoi
|
||||
path: /home/{{ lookup('env', 'USER') }}/.linuxbrew/bin
|
||||
state: present
|
||||
update_homebrew: yes
|
14
ansible/roles/workstation/tasks/packages-post.yml
Normal file
14
ansible/roles/workstation/tasks/packages-post.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
- name: packages-post | modify resilio-sync service file
|
||||
ansible.builtin.replace:
|
||||
path: /usr/lib/systemd/user/resilio-sync.service
|
||||
regexp: "multi-user"
|
||||
replace: "default"
|
||||
become: true
|
||||
|
||||
- name: packages-post | activate resilio-sync service
|
||||
ansible.builtin.systemd:
|
||||
name: resilio-sync
|
||||
scope: user
|
||||
state: started
|
||||
enabled: yes
|
18
ansible/roles/workstation/tasks/packages-prerequisites.yml
Normal file
18
ansible/roles/workstation/tasks/packages-prerequisites.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
- name: packages-prerequisites | clone homebrew GitHub repo
|
||||
ansible.builtin.git:
|
||||
repo: "https://github.com/Homebrew/brew"
|
||||
dest: "/home/{{ lookup('env', 'USER') }}/.linuxbrew/Homebrew"
|
||||
version: "master"
|
||||
|
||||
|
||||
- name: packages-prerequisites | create bin directory for homebrew
|
||||
ansible.builtin.file:
|
||||
path: "/home/{{ lookup('env', 'USER') }}/.linuxbrew/bin"
|
||||
state: directory
|
||||
|
||||
- name: packages-prerequisites | create a symbolic link for brew
|
||||
ansible.builtin.file:
|
||||
src: "/home/{{ lookup('env', 'USER') }}/.linuxbrew/Homebrew/bin/brew"
|
||||
dest: "/home/{{ lookup('env', 'USER') }}/.linuxbrew/bin/brew"
|
||||
state: link
|
65
ansible/roles/workstation/tasks/repositories.yml
Normal file
65
ansible/roles/workstation/tasks/repositories.yml
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
- name: repositories | enable the RPM Fusion repository
|
||||
ansible.builtin.dnf:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
disable_gpg_check: True
|
||||
loop:
|
||||
- https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-{{ ansible_distribution_major_version }}.noarch.rpm
|
||||
- https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-{{ ansible_distribution_major_version }}.noarch.rpm
|
||||
become: true
|
||||
|
||||
- name: repositories | enable copr repositories
|
||||
ansible.builtin.command:
|
||||
cmd: dnf copr enable -y {{ item.repo }}
|
||||
creates: "{{ item.file }}"
|
||||
loop:
|
||||
- {
|
||||
repo: "tomaszgasior/mushrooms",
|
||||
file: "/etc/yum.repos.d/_copr:copr.fedorainfracloud.org:tomaszgasior:mushrooms.repo",
|
||||
}
|
||||
become: true
|
||||
when: ansible_facts['nodename'] == "claude-fixe-fedora"
|
||||
|
||||
- name: repositories | copy yum repo files
|
||||
ansible.builtin.copy:
|
||||
src: "yum/{{ item }}"
|
||||
dest: "/etc/yum.repos.d/{{ item }}"
|
||||
loop:
|
||||
- vscodium.repo
|
||||
become: true
|
||||
|
||||
- name: repositories | resilio sync - import repository GPG key
|
||||
ansible.builtin.rpm_key:
|
||||
state: present
|
||||
key: https://linux-packages.resilio.com/resilio-sync/key.asc
|
||||
become: true
|
||||
|
||||
- name: repositories | resilio sync - add repository
|
||||
ansible.builtin.yum_repository:
|
||||
name: rslsync
|
||||
description: Resilio Sync Repository
|
||||
baseurl: https://linux-packages.resilio.com/resilio-sync/rpm/$basearch
|
||||
gpgcheck: yes
|
||||
become: true
|
||||
|
||||
- name: repositories | brave - check presence
|
||||
ansible.builtin.stat:
|
||||
path: /etc/yum.repos.d/brave-browser-rpm-release.s3.brave.com_x86_64_.repo
|
||||
register: brave
|
||||
|
||||
- name: repositories | brave - add repository
|
||||
ansible.builtin.command:
|
||||
cmd: dnf config-manager --add-repo https://brave-browser-rpm-release.s3.brave.com/x86_64/
|
||||
warn: false
|
||||
args:
|
||||
creates: /etc/yum.repos.d/brave-browser-rpm-release.s3.brave.com_x86_64_.repo
|
||||
become: true
|
||||
when: brave.stat.exists == False
|
||||
|
||||
- name: repositories | brave - import asc
|
||||
ansible.builtin.command:
|
||||
cmd: rpm --import https://brave-browser-rpm-release.s3.brave.com/brave-core.asc
|
||||
warn: false
|
||||
become: true
|
||||
when: brave.stat.exists == False
|
14
ansible/roles/workstation/tasks/scripts.yml
Normal file
14
ansible/roles/workstation/tasks/scripts.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
- name: scripts | create directory
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: "~/.local/scripts"
|
||||
|
||||
- name: scripts | copy scripts
|
||||
ansible.builtin.copy:
|
||||
src: "scripts/{{ item }}"
|
||||
dest: "~/.local/scripts"
|
||||
mode: 0755
|
||||
with_items:
|
||||
- backup-local-usb-disk-one.bash
|
||||
- backup-local-usb-disk-two.bash
|
6
ansible/roles/workstation/tasks/shell.yml
Normal file
6
ansible/roles/workstation/tasks/shell.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: shell | make Fish default shell
|
||||
ansible.builtin.user:
|
||||
name: claude
|
||||
shell: /usr/bin/fish
|
||||
become: true
|
27
ansible/roles/workstation/tasks/system.yml
Normal file
27
ansible/roles/workstation/tasks/system.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
- name: system | disable password sudo
|
||||
ansible.builtin.lineinfile:
|
||||
dest: /etc/sudoers
|
||||
state: present
|
||||
regexp: "^%wheel"
|
||||
line: "%wheel ALL=(ALL) NOPASSWD: ALL"
|
||||
validate: visudo -cf %s
|
||||
become: true
|
||||
|
||||
- name: system | remove old unused kernels
|
||||
ansible.builtin.lineinfile:
|
||||
dest: /etc/yum.conf
|
||||
state: present
|
||||
line: "installonly_limit=3"
|
||||
create: true
|
||||
become: true
|
||||
|
||||
- name: system | get better download speed with DNF
|
||||
ansible.builtin.blockinfile:
|
||||
path: /etc/dnf/dnf.conf
|
||||
block: |
|
||||
defaultyes=True
|
||||
deltarpm=True
|
||||
install_weak_deps=False
|
||||
max_parallel_downloads={{ ansible_processor_vcpus | default('8') }}
|
||||
become: true
|
6
ansible/roles/workstation/tasks/wireguard.yml
Normal file
6
ansible/roles/workstation/tasks/wireguard.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: wireguard | copy wireguard configuration
|
||||
ansible.builtin.copy:
|
||||
src: wireguard/{{ ansible_facts['nodename'] }}.conf
|
||||
dest: ~/wireguard.conf
|
||||
mode: 0600
|
11
ansible/roles/workstation/templates/chezmoi.toml.j2
Normal file
11
ansible/roles/workstation/templates/chezmoi.toml.j2
Normal file
@@ -0,0 +1,11 @@
|
||||
encryption = "age"
|
||||
|
||||
[age]
|
||||
identity = "/home/claude/.config/sops/age/keys.txt"
|
||||
recipient = "age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg"
|
||||
|
||||
[data]
|
||||
alacritty_font_size = {{ alacritty.font_size }}
|
||||
alacritty_window_columns = {{ alacritty.window_columns }}
|
||||
alacritty_window_lines = {{ alacritty.window_lines }}
|
||||
remmina_font_size = {{ remmina.font_size }}
|
7
ansible/roles/workstation/vars/claude-fixe-fedora.yml
Executable file
7
ansible/roles/workstation/vars/claude-fixe-fedora.yml
Executable file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
alacritty:
|
||||
font_size: 11.0
|
||||
window_columns: 150
|
||||
window_lines: 40
|
||||
remmina:
|
||||
font_size: 11
|
7
ansible/roles/workstation/vars/claude-thinkpad-fedora.yml
Executable file
7
ansible/roles/workstation/vars/claude-thinkpad-fedora.yml
Executable file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
alacritty:
|
||||
font_size: 9.0
|
||||
window_columns: 100
|
||||
window_lines: 28
|
||||
remmina:
|
||||
font_size: 9
|
@@ -1,7 +1,7 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- secrets.yaml
|
||||
- secrets.sops.yaml
|
||||
- volume.yaml
|
||||
- export-job.yaml
|
||||
- helm-release.yaml
|
||||
|
27
cluster/apps/data/bookstack/secrets.sops.yaml
Normal file
27
cluster/apps/data/bookstack/secrets.sops.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: bookstack-secrets
|
||||
namespace: data
|
||||
stringData:
|
||||
deployment_rsa_priv_key: ENC[AES256_GCM,data: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,iv:vMdKKCnWBgTDiqvJdXAN9QJeoBEMucPFQlF634QLV9M=,tag:iJ3dUexqwiEfT/mboY7HZA==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtQUJSSUc3K1hxZ1d1Q3dI
|
||||
SENqMUlaVkJEN3RkMXpsTnUyN05hN0ZuZ0d3CkYvVVdkNDF1WkRMREM1U3FtNzZk
|
||||
NGxtM25oaUMzeEYwNFA4TW4xTG1ENVEKLS0tIG1vY3JQRUplR1VBUzQ5VTR0L3Ro
|
||||
cG5JYXp0cllxTXVnY1ZOL1RlNWRaK2sK76zdi1HuLcoHEc0JTVLsenoa7JQv0DGz
|
||||
y/yDIArOoocUryeb62DuSKQNZmcZLhHbJUWvFIkacDi82CcxuvdDLw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-07-03T14:41:17Z"
|
||||
mac: ENC[AES256_GCM,data:kIa5+mV0ZY9XR/6zb5INz8bUaPCMHSaE0s7R697ogrnYufx971Nr8TVA7X4dgNpvYC6HUgdRbUxWr/TbtJCq+z1hkXdIiFZKJBBy7gcgJRXCleduMi4IikrkW7fAcQZmeHqvd+MNUXBiebGWCpGe0PCij5xnjq/K4pJ4qJX1OdY=,iv:PfuJ+VSxKzhJGGwN+WQ9KGwF2aJITKT4CAmPCP/8DCg=,tag:JCk32OUKBIweJoO9FpwFGA==,type:str]
|
||||
pgp: []
|
||||
encrypted_regex: ^(data|stringData)$
|
||||
version: 3.7.3
|
@@ -1,58 +0,0 @@
|
||||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: bookstack-secrets
|
||||
namespace: data
|
||||
stringData:
|
||||
deployment_rsa_priv_key: ENC[AES256_GCM,data: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,iv:majin48BvzBk04GDahOnaxkDcxLsFKVEtijncxfKkl0=,tag:J7M/IYKppIXG4LDPpY+8Bw==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2022-07-03T12:13:13Z"
|
||||
mac: ENC[AES256_GCM,data:fx1wBJU77yblwu76N5LD2HoAE0dYTEWGIB48cYAPBjRdYMFmL7JQMk6sdT4KmcGZy/0IpVaC9ZwFfVR9VapPpzKnUUY/8V189e1GYu/cRpy3q4W7l6KU0jHLbasBERV4QZI8HF3vrAxNI3zd7TUprqQ8DZCTpX/QZ3sThO5QG1c=,iv:M2wxwzEjxZRxdW6WTsWjMueN8yl3Hi0B++axkNSSqgo=,tag:pfxppxufXeXfvqe2EW+Clw==,type:str]
|
||||
pgp:
|
||||
- created_at: "2021-07-17T21:15:45Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA6nQR2zACjUjAQ//fQ863OpprkOuu7ZzjHoq9ereZ+wu7jYg/rQ/1VbI9QL2
|
||||
WzC8o/Csc2qrN1adnTx9s61HPGkAyqzsSJLmBrVufc+I1sGcJsCg8kzezO0HYau9
|
||||
xV30mazw2sPca80fjbqeUY6hcp4oPcDg8METk9/TZ955UILit2nUWdCTOX+C6yxw
|
||||
R206DfKb/UvQ3zLKpbeSvarf8+pyp7TpEmPnPjC9jYMzftD+lhqwRmaFjeeGjWIJ
|
||||
NyeybL50kFBFJYou7AHxhLT7Ona2IASJCYvUj8kjwMc/MedjjcHdh+CysYlRgt0D
|
||||
Ces7cUI+PVRdvWY2hi/EO/VCaD60bDEfy6zB8KHPRE+E53A4GlMvnvYF7QI5z4qC
|
||||
HdCsQ8v2IOpU0/e/32eiAKtJmMqy+v1hVFavh+5u4epc5iFuJzoTAEdDg45FfQap
|
||||
Kq6tDFWXP30Y3HfOc+7BBz9lep49zJB5cK47WvNM8Tfazb3DpHFXDbFgLyAkWuaq
|
||||
QvZIijHeH2P5advD2gONUY9gDlVV8/HxYHNQVgwWyaVdmXXvzFtgpZQtIvIHA+Di
|
||||
EhNrw8L/qtOW6B/uM+FzvcuGVTF3nnU4g43Y0XkTOd7JxP/l7CC78pcjl4IdgGbK
|
||||
nb+1+/ShzjRJA3n0fvlkrbiMdep9hMQUWJlzsG15rRlvtLTxTZjNHX0kacn/4yTS
|
||||
XgGKX2C4ZX3Pxdq/Mkr7muGZbLZIOHXL0OPouDzs8E64UPR0u8ayDDlsX9SYZ8hq
|
||||
kvAL3ktnKNf1R3shWGKMcra8skjIKIoSmzEXf7RgCoNnewjt8wAqBY3+RGiaBUA=
|
||||
=jwm/
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 19B850FBA7685A526CF11E5F9BBE834259976EE8
|
||||
- created_at: "2021-07-17T21:15:45Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA98IrODHuiZ9ARAAk2hc8IbzfVSagc4qeymEpDBwME2MpzYv7a6RPK7vS/VR
|
||||
8PGYJT4DuJ0op4N/IiTKUeO1DVlqfZvzKBfAKDNdpojzaheNdy/L4nIKMN2klfx+
|
||||
7BAXljRpqzyRjC2lyMFbDWgMMWcJG4PZIuCRQCm6ej0LOFwkoL4EitpfltdHj5tt
|
||||
/qUWGICXSlgN882axw23Z9ZpfKmLLn2tKplFmgKErrPaXQxiqRHjPFzXh1JkGnaG
|
||||
wtxBMdgX4eMDWGcSgiVqPFzMuecIA34u2bSnCrU4xmLGglHgm2oWpL9PZcdWBR1U
|
||||
H9OzDrFNDD2X3Hey5jv5v3h64YwbFnZ89Y51lUbP8fbv65OrVGMQKE0ZQ7ueVwLk
|
||||
H/IM9FnVDfkQ615ykPxUtr0AT47l9mffi6Iy1/XBmrqiCnaKhT5PEbSywmaKzOD9
|
||||
9B7UG4l6kLh9F/bqNRsQWkarYlSmGf8BvAQNFH7ZtzyfRxTAP2wKxvaHA5/sqMO8
|
||||
em0WDxvdeVtHSVYx/Kbu50RW0eDJRDD21P5neb2Jj7rZTVYD+L5Dxne+JXpTbI+8
|
||||
jKesyEk3RYGzpthHHyWPZAo76cidqYVRvENfPFJljaRHpxcQLkYECTvyDmgyRNz0
|
||||
uMHnQ76ZqeyGQ9NrYflcqd3XakTOvAmrwKz0p1zhmTlSgrUmGCUaZT8VXwRjsnDS
|
||||
XgF3B6c9YDZz8f7wmtJqj0DTgxdgWGoQBrJowkyHhTxQetj++7EYaH0hdzrI+5bt
|
||||
ZTM5I8y6zRrCAfvLKzKlMeh0R4XRREmNCyVzRuAfwjnVzXRVtcxRN8IAJR2mCNQ=
|
||||
=vETF
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 5749D0AE39445C1CCA6006DF8913091C690BDD69
|
||||
encrypted_regex: ^(data|stringData)$
|
||||
version: 3.7.3
|
@@ -59,7 +59,7 @@ spec:
|
||||
DISABLE_REGISTRATION: true
|
||||
REQUIRE_SIGNIN_VIEW: true
|
||||
webhook:
|
||||
ALLOWED_HOST_LIST: "drone.k3s.xpander.ovh"
|
||||
ALLOWED_HOST_LIST: "drone.${SECRET_CLUSTER_DOMAIN}"
|
||||
|
||||
postgresql:
|
||||
enabled: false
|
||||
|
@@ -1,7 +1,7 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- secrets.yaml
|
||||
- secrets.sops.yaml
|
||||
- volume.yaml
|
||||
- helm-release.yaml
|
||||
- backup-job.yaml
|
||||
|
27
cluster/apps/development/gitea/secrets.sops.yaml
Normal file
27
cluster/apps/development/gitea/secrets.sops.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: gitea-secrets
|
||||
namespace: development
|
||||
stringData:
|
||||
deployment_rsa_priv_key: ENC[AES256_GCM,data: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,iv:PKmf+mytOTMdVitS5avOAi5yChAx44mG2YNnaDFLTlw=,tag:0ejHj1EpeXqRF686ZsmVmA==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5UnFTTUZTT2dxV1JFY2R0
|
||||
aS9yUWNHeDdnVStyTTV1ZjRXU1hQYVVQRTFvCktjL0VwNjdsczdmcFI2TnhXMHU1
|
||||
RXRhQnhhYjc4ZHNzN0wyN1ErcVkvNXcKLS0tIE1WNTBhV0xwSk9rcklLWkVESElS
|
||||
ZVpwVVRmV2VHU0NJcFptYXJPZnhXT28KIQgCy66P7kb1hc9TxEolPBaP68Pp116Y
|
||||
5cxfpbXZYnsDItjB1FtwrIxFRjDBHrpHoEb2e6AC47pHvai+OflqCg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-07-03T14:41:34Z"
|
||||
mac: ENC[AES256_GCM,data:dQ7zJWFeZboFrR1pbKHoXcnqv6yjZVrHahb79bfdfJiXt7qbnr1w+WSTbcv78zsN9y0pZ6hPyzc8+QzwFH5xbBSdi8TkHifcuvQqTMtmrMnHZM6GMXyiN8BUvPEq8iT5OO0UFwbXitQSavn9Ib52j+HSvyDzLy9MkGbmLHrKA88=,iv:YywQ58kygqVBKQ4BxIVkGMgi8SoL842qsuJ4q7hZikY=,tag:17wpoXBlhOdHnls7uU5IQA==,type:str]
|
||||
pgp: []
|
||||
encrypted_regex: ^(data|stringData)$
|
||||
version: 3.7.3
|
@@ -1,58 +0,0 @@
|
||||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: gitea-secrets
|
||||
namespace: development
|
||||
stringData:
|
||||
deployment_rsa_priv_key: ENC[AES256_GCM,data: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,iv:majin48BvzBk04GDahOnaxkDcxLsFKVEtijncxfKkl0=,tag:J7M/IYKppIXG4LDPpY+8Bw==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2022-07-03T12:11:25Z"
|
||||
mac: ENC[AES256_GCM,data:b0JPukzFNt2KJ4xLiPqZu1jXqPMozJMm7q5mUiPUtiCZTBDz8ixKvYSh0d2fIb7mj33rewCE5oWZT+brK+lwDRiHLshzyxh4/2foPsHzkl2Sf7mbFUsSTtMSPulwZw1geMX2L2//41CpDDhettIlla9obMsrdW8EI2nqGL0nqfQ=,iv:rrTUj9HIPx23+LQ3gtSMTB5/kIXQuvZ/GbPMx6FqBTQ=,tag:EAEV0GEBXpV9IIJOav3qvg==,type:str]
|
||||
pgp:
|
||||
- created_at: "2021-07-17T21:15:45Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA6nQR2zACjUjAQ//fQ863OpprkOuu7ZzjHoq9ereZ+wu7jYg/rQ/1VbI9QL2
|
||||
WzC8o/Csc2qrN1adnTx9s61HPGkAyqzsSJLmBrVufc+I1sGcJsCg8kzezO0HYau9
|
||||
xV30mazw2sPca80fjbqeUY6hcp4oPcDg8METk9/TZ955UILit2nUWdCTOX+C6yxw
|
||||
R206DfKb/UvQ3zLKpbeSvarf8+pyp7TpEmPnPjC9jYMzftD+lhqwRmaFjeeGjWIJ
|
||||
NyeybL50kFBFJYou7AHxhLT7Ona2IASJCYvUj8kjwMc/MedjjcHdh+CysYlRgt0D
|
||||
Ces7cUI+PVRdvWY2hi/EO/VCaD60bDEfy6zB8KHPRE+E53A4GlMvnvYF7QI5z4qC
|
||||
HdCsQ8v2IOpU0/e/32eiAKtJmMqy+v1hVFavh+5u4epc5iFuJzoTAEdDg45FfQap
|
||||
Kq6tDFWXP30Y3HfOc+7BBz9lep49zJB5cK47WvNM8Tfazb3DpHFXDbFgLyAkWuaq
|
||||
QvZIijHeH2P5advD2gONUY9gDlVV8/HxYHNQVgwWyaVdmXXvzFtgpZQtIvIHA+Di
|
||||
EhNrw8L/qtOW6B/uM+FzvcuGVTF3nnU4g43Y0XkTOd7JxP/l7CC78pcjl4IdgGbK
|
||||
nb+1+/ShzjRJA3n0fvlkrbiMdep9hMQUWJlzsG15rRlvtLTxTZjNHX0kacn/4yTS
|
||||
XgGKX2C4ZX3Pxdq/Mkr7muGZbLZIOHXL0OPouDzs8E64UPR0u8ayDDlsX9SYZ8hq
|
||||
kvAL3ktnKNf1R3shWGKMcra8skjIKIoSmzEXf7RgCoNnewjt8wAqBY3+RGiaBUA=
|
||||
=jwm/
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 19B850FBA7685A526CF11E5F9BBE834259976EE8
|
||||
- created_at: "2021-07-17T21:15:45Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA98IrODHuiZ9ARAAk2hc8IbzfVSagc4qeymEpDBwME2MpzYv7a6RPK7vS/VR
|
||||
8PGYJT4DuJ0op4N/IiTKUeO1DVlqfZvzKBfAKDNdpojzaheNdy/L4nIKMN2klfx+
|
||||
7BAXljRpqzyRjC2lyMFbDWgMMWcJG4PZIuCRQCm6ej0LOFwkoL4EitpfltdHj5tt
|
||||
/qUWGICXSlgN882axw23Z9ZpfKmLLn2tKplFmgKErrPaXQxiqRHjPFzXh1JkGnaG
|
||||
wtxBMdgX4eMDWGcSgiVqPFzMuecIA34u2bSnCrU4xmLGglHgm2oWpL9PZcdWBR1U
|
||||
H9OzDrFNDD2X3Hey5jv5v3h64YwbFnZ89Y51lUbP8fbv65OrVGMQKE0ZQ7ueVwLk
|
||||
H/IM9FnVDfkQ615ykPxUtr0AT47l9mffi6Iy1/XBmrqiCnaKhT5PEbSywmaKzOD9
|
||||
9B7UG4l6kLh9F/bqNRsQWkarYlSmGf8BvAQNFH7ZtzyfRxTAP2wKxvaHA5/sqMO8
|
||||
em0WDxvdeVtHSVYx/Kbu50RW0eDJRDD21P5neb2Jj7rZTVYD+L5Dxne+JXpTbI+8
|
||||
jKesyEk3RYGzpthHHyWPZAo76cidqYVRvENfPFJljaRHpxcQLkYECTvyDmgyRNz0
|
||||
uMHnQ76ZqeyGQ9NrYflcqd3XakTOvAmrwKz0p1zhmTlSgrUmGCUaZT8VXwRjsnDS
|
||||
XgF3B6c9YDZz8f7wmtJqj0DTgxdgWGoQBrJowkyHhTxQetj++7EYaH0hdzrI+5bt
|
||||
ZTM5I8y6zRrCAfvLKzKlMeh0R4XRREmNCyVzRuAfwjnVzXRVtcxRN8IAJR2mCNQ=
|
||||
=vETF
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 5749D0AE39445C1CCA6006DF8913091C690BDD69
|
||||
encrypted_regex: ^(data|stringData)$
|
||||
version: 3.7.3
|
@@ -3,5 +3,5 @@ kind: Kustomization
|
||||
resources:
|
||||
- helm-release.yaml
|
||||
- volume.yaml
|
||||
- token.yaml
|
||||
- token.sops.yaml
|
||||
- podmonitor.yaml
|
||||
|
27
cluster/apps/home-automation/home-assistant/token.sops.yaml
Normal file
27
cluster/apps/home-automation/home-assistant/token.sops.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: home-automation
|
||||
namespace: home-automation
|
||||
stringData:
|
||||
prometheus-token: ENC[AES256_GCM,data:XQS2cNao60Cw3oWPBG3qRs69u4ZhBB8qWm5s6z13CDomfcdfA60YSSU7Vtcdb8E7wnI2t/X3Kul8Vlt8evYv/Tkh5UN1oiqa+upFQ/tOlIHFmRfz1snE5XlREc/sB2FN8xUIDRdHObfwz9NcfEcrt0MP+1mXN1IUIA5BDAAFT05TALeUjdY3CTfht6idIFlqs3YN2uvfDYoq5nKIN4J3uN0rWJI46BD+FnmpE243ChM+Cn1NS2sa,iv:lcCmW8TASJHWgOjs9qRh1XaGqPpCHn9HkU+Ma+Iqyv0=,tag:bRNDK8TEyHIMZlixYRDGGw==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQWjZ1RG9QZnBQSUNNSHN4
|
||||
MTdwMDlvaGk4NEVxdmdZOGR1QnpLNFkzOTNZCjhZeEloeWQzemp1cVJrbEpxbWJB
|
||||
T3NXRkRxTU54MGxUbk45YTJoQkl2dWMKLS0tIFkzQ0hvQWdxK2NKQlVlNWhUODQ3
|
||||
RDRiUkRFSVI4S29mdWRMbE9RNFhLQlUKcx+FKlWUqt5YOxIKlvNiexCarLnW3FXU
|
||||
M+lPXuGDvjo2Pg5InhPCheuxSVxea85uRRmROTWWOfjMKNYyfMiXLw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-07-03T14:41:50Z"
|
||||
mac: ENC[AES256_GCM,data:rCAXrXozuI+YJwCDMWQeMvzC3Aoa/Eb89AQEBbLeOQMp7z5p7VCuzaSP52vsW50ii/Rr+VjgDEhoyVSiRAw9IoqcQCjNFZfW6nbXyKZIQGgSfiDKg5DrZLsLOJEg5JUX9u8zzVB2VyIpuDAtDrZHgmvBq+t/gSncSNzb7UW2Aw4=,iv:nkSndVS3YbIGPLMvPWwjgfRL8L5Qac71Jls1OBvX3s8=,tag:nmCKDjXBURMtQpQ5WfjHSg==,type:str]
|
||||
pgp: []
|
||||
encrypted_regex: ^(data|stringData)$
|
||||
version: 3.7.3
|
@@ -1,58 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: home-automation
|
||||
namespace: home-automation
|
||||
stringData:
|
||||
prometheus-token: ENC[AES256_GCM,data:NiP3ioOYLz+DEeo39/Guk1iyxw9eMzHv/x4L/hq+LRDfpPnxlmWixuq2yOmhaW8bZSFDXudr2eGUZwBMXXmTUVTL/RgVg6yDy70kJ53YGLcRCWI3GntlwZqF1xqMkUXk+4Ap663cYFM15pS18s9SaWogJ3N/SXrC3uD0l7aPxlF5O+MNoTiK+CNogXS0/QAAnvaop3Y3MN6i81qp5owHATV2SOorXlatgQxR0pxf0ZEfU36NoIBQ,iv:PSvU8RUnULu5Wm/F8jSLb2ESH2QTx3UZUUJgzUPEyio=,tag:bnSVYptDVsWAfvEvo6nJwg==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2022-02-08T14:42:41Z"
|
||||
mac: ENC[AES256_GCM,data:ZdNG4+tlVJgi7KYQDEJZ01rzjscrgX2Pel/kneV9kZqbukmJi5yWLFdPM9Ll0xO89hLGW/Aa2PCvA5Kwpa8x5itGODiY6LimCWqX1YQ5/nZ4eUMHjXorWcduxHD8qc5zFkDbvUwhCyZ1mmhgN5sI0pFBDWtkVbQd7nfDCnxHwLE=,iv:GH81+X9bbww4o+eAMp6+yosUX3R77SXW8xFlTzOFv34=,tag:pDT+ybsa1UgWRNSFzGtw1g==,type:str]
|
||||
pgp:
|
||||
- created_at: "2021-08-20T16:21:08Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA6nQR2zACjUjAQ/9FbK6Z+2UwtViXJmelHPuttQoNM85U3V4RCoRcalp9z73
|
||||
Y5Jcum3plDPf7E9bsqiJtt4xWvxZWXFtFp6s2mTTRTfy8OBbM+xLpFXrvSXqE3Ug
|
||||
YUBiMWI5QnEqC0eo2NKey53DRxOzqsMoVMwp/2FEAUYwC2pkT7XjMiAn8X54QMjj
|
||||
MlNM8JAfjdEvaZ4Blk5egdvmBNm8Em7DzJ3LGyTfksyWA66W+qbTkEH46n4DZHv/
|
||||
0X8AtjU+dWILW0SA/DUXkmUEccrM40ZfD0Rm70TvvKGeCNM0zaDv+ikeq8muklIn
|
||||
oDSRUQm9aZ7NB5xP8mC7AULHwHN6jvHGymNEJEjl10tmEsI0Y4eEEer3MAEBH93V
|
||||
w0rPOOPVZPYXD/rFQF6f4nvimT0/dlrQYFepIFZbwmQYPcbXAP9OhngMgNM71Oeb
|
||||
qKf0KorRL4VT3K6NPZxu05QhIsTFPM4pZrHA6ZotZ7+JW9pZe1LCE7ROm0AzPp3b
|
||||
btlEr/MKwrkSouBI0aO866pxSpbHjHZU4m8Y7NWelwSy8cY35dXbCudC5ScMT5Y/
|
||||
5dccmaLEfSpu6eiwi6bfrGIpROlbbj1dINJKJOCeoXRtvXyADao4AKfa2c28fqwM
|
||||
Mx9Fn8O76/YfyRqO1dFbd896OwqSRstq1nVB2+xl/7Infch8NkBCIkb4Xe1zSmLS
|
||||
XAG1UPCsQfjt3BI8b+5BmeJHdKAHtZ3w7Bb96AGaWn7wh7c8+QZugPbsxm2+l+8H
|
||||
wEgYrTMvk6BP4zzA15T6iOKh2qw5qlxi+k9zN5rmOsjmP+0SwUr8mfCL/Ze0
|
||||
=9u2m
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 19B850FBA7685A526CF11E5F9BBE834259976EE8
|
||||
- created_at: "2021-08-20T16:21:08Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA98IrODHuiZ9AQ//cs99xtkOc9d9nbiGmirNkUsWZGzhxaLZ7SUDY6mQvtj7
|
||||
ibV7fkG5kf/uNu9mw+DRA8M3PBM5j+y3Hv0xt+1fBAhttra1GU127DwSAHChbWJT
|
||||
BMnx2Bm5zAmeoh4ksMphuggOsLL2x1IYiTk7dnaMuPo/5CUPxXpTpPrJYHf0Pg1b
|
||||
1j8l0N+t2hUWj93Mh392mggf28w+PLD5ty/d6a0Eyky6UG62LbyjhJaJt5nBMvfS
|
||||
jvRW1QXb7iQ7ljbml1X2FHK/vzYtiMh5OUfYCzHRK6u5yTQybghNSVr8L0N2MgvC
|
||||
unNp/PEvfvpzU34hInmi1zdW6BZK3iAvuiKHfgrJy2iZnjGZahBN7tLcKyHrAKpe
|
||||
Q+hMQ1+neHvcgJAl50jRrUAbJJ1ssypwW6+zz3Bj1b+6IvZ/tuV31dZkKozsi4Y4
|
||||
UKyds4IOEMLHv8FOlHfkOrvkTmij+6bqj1UoQIO7qTSuxI6M5jFmJ7vNnpYWS6IC
|
||||
944JPbmX5hzDLrqMICzsetIxXNS0uTbvTo2APVIHjDkgX8ukcNw0YKfIQFgMi8Fc
|
||||
/Sp8wCaUULkotlEb4Bvdq+yTrj1mQCpHaz6m1w/8RnSzLUecD0hVMUUPGctZ5IKl
|
||||
3ZJrdMAJdad2Zjf7GVXwxNXtKaH9gCjZ1n4zqMg3Ob1l5BmUQI4M5IlZlPGAqhDS
|
||||
XAFdxfYkHPbKWXDUPWcj6P+FUqDjdCV++z5kpeIXmtW8eouxIrV3DvwhdO+H3yKc
|
||||
KkdnXPjCzSPf9AzYhgpGXKG70yh4gtMeLeDAPpDjguu6Eskd8VoQBus6tZ4F
|
||||
=6Ilp
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 5749D0AE39445C1CCA6006DF8913091C690BDD69
|
||||
encrypted_regex: ^(data|stringData)$
|
||||
version: 3.7.1
|
@@ -36,9 +36,9 @@ spec:
|
||||
- |
|
||||
#!/bin/bash
|
||||
|
||||
curl --location raw.githubusercontent.com/auricom/home-ops/main/server/scripts/transcode_music/transcode.bash --output /tmp/transcode.bash
|
||||
curl --location raw.githubusercontent.com/auricom/home-ops/main/scripts/transcode_music/transcode.bash --output /tmp/transcode.bash
|
||||
chmod a+x /tmp/transcode.bash
|
||||
curl --location raw.githubusercontent.com/auricom/home-ops/main/server/scripts/transcode_music/transcode_exclude.cfg --output /tmp/transcode_exclude.cfg
|
||||
curl --location raw.githubusercontent.com/auricom/home-ops/main/scripts/transcode_music/transcode_exclude.cfg --output /tmp/transcode_exclude.cfg
|
||||
cd /tmp
|
||||
./transcode.bash -c
|
||||
./transcode.bash -r
|
||||
|
@@ -1,50 +0,0 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: terra-exporter
|
||||
namespace: monitoring
|
||||
labels:
|
||||
app.kubernetes.io/instance: terra-exporter
|
||||
app.kubernetes.io/name: terra-exporter
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: terra-exporter
|
||||
app.kubernetes.io/name: terra-exporter
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: terra-exporter
|
||||
app.kubernetes.io/name: terra-exporter
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: regcred
|
||||
containers:
|
||||
- image: registry.${SECRET_CLUSTER_DOMAIN}/homelab/terra-exporter:develop
|
||||
imagePullPolicy: Always
|
||||
name: terra-exporter
|
||||
ports:
|
||||
- containerPort: 9000
|
||||
name: http
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: terra-exporter
|
||||
app.kubernetes.io/name: terra-exporter
|
||||
name: terra-exporter
|
||||
namespace: monitoring
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 9000
|
||||
protocol: TCP
|
||||
targetPort: 9000
|
||||
selector:
|
||||
app.kubernetes.io/instance: terra-exporter
|
||||
app.kubernetes.io/name: terra-exporter
|
||||
type: ClusterIP
|
||||
---
|
@@ -1,5 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- podmonitor.yaml
|
@@ -1,16 +0,0 @@
|
||||
---
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: PodMonitor
|
||||
metadata:
|
||||
name: terra-exporter
|
||||
namespace: monitoring
|
||||
spec:
|
||||
podMetricsEndpoints:
|
||||
- interval: 5m
|
||||
path: /
|
||||
port: http
|
||||
scrapeTimeout: 30s
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: terra-exporter
|
||||
app.kubernetes.io/name: terra-exporter
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user