Compare commits

...

21 commits

Author SHA1 Message Date
d3e86f6b50 replace 'syncthing' with 'immich' 2025-04-14 17:04:49 +02:00
2860c9d7c3 create standalone script(s) and service files for hdparm 2025-03-20 17:02:13 +01:00
6ee602d0b9 remove unsafe powertop options for host 'j5040' 2024-11-05 14:04:35 +01:00
d4e38fe9dd merge remote changes 2024-11-05 14:03:21 +01:00
87c8a5a49c remove unsafe powertop options for host 'n100' 2024-11-05 13:59:48 +01:00
ef798d84aa update powertop script for host 'j5040' 2024-10-28 14:16:12 +01:00
cfba2b2031 fix restic update 2024-10-28 13:38:30 +01:00
5142021197 add powertop script 2024-10-01 16:49:48 +02:00
d5d91679cd remove powertop report 2024-10-01 15:58:50 +02:00
cf352f1062 add script(s) and service for powertop 2024-10-01 15:57:03 +02:00
88ef0ad3ac add cpupower service to set governor on boot 2024-10-01 14:38:07 +02:00
832627cfc9 share zsh history 2024-09-19 17:44:43 +02:00
0379d33d8d add script to merge folders 2024-08-30 15:38:16 +02:00
3af34b0064 fix sudo usage 2024-08-30 10:21:15 +02:00
6be503b700 use sudo to run actions with a different user, check for subshell 2024-08-30 10:18:26 +02:00
82d32ec30a fix path 2024-08-29 18:32:34 +02:00
f4ec62e83e restructure restic scripts 2024-08-29 15:53:24 +02:00
7b735afaca change notify channel 2024-08-28 15:47:52 +02:00
5b5e1bf1cf exit on error 2024-08-28 15:35:53 +02:00
5784b7e9e5 remove 'ExecStartPost' from service 2024-08-28 15:31:46 +02:00
f1d24e6d07 remove debug statement 2024-08-28 15:30:12 +02:00
23 changed files with 268 additions and 70 deletions

18
scripts/hdparm/hdparm.sh Executable file
View file

@ -0,0 +1,18 @@
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
# exit on error
set -e
# check permissions
[[ "$EUID" != 0 ]] && printf "error: permission denied!\n" >&2 && exit 1
# check if script exists
script="$(dirname $(realpath "$0"))/$(hostname).sh"
[[ ! -x "$script" ]] && printf "error: script '"$script"' does not exist or is not executable!\n" >&2 && exit 1
# execute script
printf ">> executing script '"$script"'...\n"
. "$script"

7
scripts/hdparm/j5040.sh Executable file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
hdparm -S 1 -y /dev/sdc
hdparm -S 1 -y /dev/sdd

22
scripts/merge.sh Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
# merge files from two folders and cleanup the source
# get and check variables
[[ -z "$1" ]] && printf "error: no source directory specified!\n" >&2 && exit 1
[[ -z "$2" ]] && printf "error: no destination directory specified!\n" >&2 && exit 1
source="$(realpath $1)"
destination="$(realpath $2)"
[[ ! -d "$source" ]] && printf "error: source '"$source"' is not a valid or existing directory!\n" >&2 && exit 1
[[ ! -d "$destination" ]] && printf "error: destination '"$destination"' is not a valid or existing directory!\n" >&2 && exit 1
printf ">> merging directory '"$source"' into '"$destination"' with rsync...\n"
rsync -avh --remove-source-files --progress "$source/" "$destination"
find "$source" -mindepth 1 -type d -empty -delete
printf ">> merge finished after "$SECONDS" seconds!\n"

View file

@ -55,4 +55,4 @@ echo "pw: $password"
echo "url: $url"
echo "args: ${args[@]}"
curl -u $user:$password "${args[@]}" $url
curl -s -u $user:$password "${args[@]}" $url

9
scripts/powertop/j5040.sh Executable file
View file

@ -0,0 +1,9 @@
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
echo '0' > '/proc/sys/kernel/nmi_watchdog';
echo '1500' > '/proc/sys/vm/dirty_writeback_centisecs';
echo 'disabled' > '/sys/bus/usb/devices/2-3/power/wakeup';
echo 'disabled' > '/sys/bus/usb/devices/2-4/power/wakeup';

8
scripts/powertop/n100.sh Executable file
View file

@ -0,0 +1,8 @@
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
echo '0' > '/proc/sys/kernel/nmi_watchdog';
echo '1500' > '/proc/sys/vm/dirty_writeback_centisecs';
echo 'auto' > '/sys/bus/usb/devices/3-7.3/power/control';

18
scripts/powertop/powertop.sh Executable file
View file

@ -0,0 +1,18 @@
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
# exit on error
set -e
# check permissions
[[ "$EUID" != 0 ]] && printf "error: permission denied!\n" >&2 && exit 1
# check if script exists
script="$(dirname $(realpath "$0"))/$(hostname).sh"
[[ ! -x "$script" ]] && printf "error: script '"$script"' does not exist or is not executable!\n" >&2 && exit 1
# execute script
printf ">> executing script '"$script"'...\n"
. "$script"

35
scripts/restic/backup.sh Executable file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
# check if we're running in a subshell, forbid direct execution
[[ "$ZSH_EVAL_CONTEXT" == "toplevel" ]] && printf "error: direct execution of this script is forbidden!\n" >&2 && exit 1
# get the "home" directory
home="$(dirname $(realpath "$0"))"
# check if .env file exists and source it
env="$home/$(hostname).env"
[[ ! -r "$env" ]] && printf "error: config file '"$env"' does not exist!\n" >&2 && exit 1
source "$env"
# check if backup directories are defined
[[ -z "$RESTIC_DIRECTORIES" ]] && printf "error: config file '"$env"' does not define any backup directories!\n" >&2 && exit 1
printf ">> starting restic backup to repository '"$RESTIC_REPOSITORY"'...\n"
# execute "pre" action if defined
[[ -n "$RESTIC_BACKUP_PRE" ]] && eval "$RESTIC_BACKUP_PRE"
for directory in ${RESTIC_DIRECTORIES[@]}; do
seconds="$SECONDS"
printf "\n> backing up '"$directory"'...\n"
sudo --preserve-env -u "$RESTIC_USER" restic backup --verbose --no-scan --retry-lock 3h "$directory"
printf "> backup of '"$directory"' finished after "$(( $SECONDS - $seconds ))" seconds!\n"
done
# execute "post" action if defined
[[ -n "$RESTIC_BACKUP_POST" ]] && eval "$RESTIC_BACKUP_POST"
printf "\n>> restic backup finished after "$SECONDS" seconds!\n"

15
scripts/restic/j5040.env Normal file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
# define title and icon for the notification
export RESTIC_NTFY_TITLE="$(hostname)"
export RESTIC_NTFY_ICON="green_circle"
# define directories to backup
export RESTIC_DIRECTORIES=(
"/etc"
"/root"
"/home/velvettear"
)

View file

@ -1,21 +0,0 @@
#!/usr/bin/env bash
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
[[ "$EUID" != 0 ]] && printf "error: permission denied!\n" >&2 && exit 1
directories=(
"/etc"
)
printf ">> starting restic backup...\n"
for directory in ${directories[@]}; do
seconds="$SECONDS"
printf "> backing up '"$directory"'...\n"
restic backup --verbose --no-scan --retry-lock 3h "$directory"
printf "> backup of '"$directory"' finished after "$(( $SECONDS - $seconds ))" seconds!\n"
done
printf ">> restic backup finished after "$SECONDS" seconds!\n"

15
scripts/restic/n100.env Normal file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
# define title and icon for the notification
export RESTIC_NTFY_TITLE="$(hostname)"
export RESTIC_NTFY_ICON="green_circle"
# define directories to backup
export RESTIC_DIRECTORIES=(
"/etc"
"/root"
"/home/velvettear"
)

View file

@ -1,30 +0,0 @@
#!/usr/bin/env bash
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
[[ "$EUID" != 0 ]] && printf "error: permission denied!\n" >&2 && exit 1
directories=(
"/etc"
"/mnt/storage/audiobooks"
"/mnt/storage/comics"
"/mnt/storage/documents"
"/mnt/storage/ebooks"
"/mnt/storage/images"
"/mnt/storage/music"
"/mnt/storage/software"
"/mnt/storage/syncthing"
"/mnt/storage/videos"
)
printf ">> starting restic backup...\n"
for directory in ${directories[@]}; do
seconds="$SECONDS"
printf "\n> backing up '"$directory"'...\n"
restic backup --verbose --no-scan --retry-lock 3h "$directory"
printf "> backup of '"$directory"' finished after "$(( $SECONDS - $seconds ))" seconds!\n"
done
printf ">> restic backup finished after "$SECONDS" seconds!\n"

23
scripts/restic/prune.sh Executable file
View file

@ -0,0 +1,23 @@
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
# check if we're running in a subshell, forbid direct execution
[[ "$ZSH_EVAL_CONTEXT" == "toplevel" ]] && printf "error: direct execution of this script is forbidden!\n" >&2 && exit 1
# define title and icon for the notification
export RESTIC_NTFY_TITLE="prune"
export RESTIC_NTFY_ICON="red_circle"
printf ">> pruning repository '"$RESTIC_REPOSITORY"'...\n\n"
# execute "pre" action if defined
[[ -n "$RESTIC_PRUNE_PRE" ]] && eval "$RESTIC_PRUNE_PRE"
sudo --preserve-env -u "$RESTIC_USER" restic forget --keep-daily 7 --keep-weekly 1 --keep-monthly 1 --prune --retry-lock 3h
# execute "post" action if defined
[[ -n "$RESTIC_PRUNE_POST" ]] && eval "$RESTIC_PRUNE_POST"
printf "\n>> repository pruned after "$SECONDS" seconds!\n"

35
scripts/restic/restic.env Normal file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
# define user
export RESTIC_USER="restic"
# override default repository
export RESTIC_REPOSITORY="/mnt/restic"
# define pre and post backup actions
export RESTIC_BACKUP_PRE="printf '\n> mounting remote storage...\n' && mount -t nfs -o vers=4,soft,noatime,nolock,retrans=1,timeo=10 192.168.100.1:/mnt/storage /mnt/n100"
export RESTIC_BACKUP_POST="printf '\n> unmounting remote storage...\n' && umount /mnt/n100"
# define pre and post prune actions
export RESTIC_PRUNE_PRE=""
export RESTIC_PRUNE_POST="printf '\n> fixing ownership of repository...\n' && chown -R restic:restic $RESTIC_REPOSITORY"
# define title and icon for the notification
export RESTIC_NTFY_TITLE="storage"
export RESTIC_NTFY_ICON="yellow_circle"
# define backup directories
export RESTIC_DIRECTORIES=(
"/mnt/n100/audiobooks"
"/mnt/n100/comics"
"/mnt/n100/documents"
"/mnt/n100/ebooks"
"/mnt/n100/images"
"/mnt/n100/music"
"/mnt/n100/software"
"/mnt/n100/immich"
"/mnt/n100/videos"
)

View file

@ -1,32 +1,48 @@
#!/usr/bin/env bash
#!/usr/bin/env zsh
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
# exit on error
set -e
# check permissions
[[ "$EUID" != 0 ]] && printf "error: permission denied!\n" >&2 && exit 1
# check which action to execute
[[ -n "$1" ]] && action="$1" || action="backup"
# check if script exists
script="$(dirname $(realpath "$0"))/$(hostname).sh"
script="$(dirname $(realpath "$0"))/$action.sh"
[[ ! -x "$script" ]] && printf "error: script '"$script"' does not exist or is not executable!\n" >&2 && exit 1
# get hostname
host="$(hostname)"
[[ -z "$host" ]] && host="$HOST"
# get the "home" directory
home="$(dirname $(realpath "$0"))"
# setup restic
export RESTIC_USER="$(whoami)"
export RESTIC_REPOSITORY="rest:http://192.168.100.101:8000"
export RESTIC_PASSWORD="\$Velvet90"
export RESTIC_COMPRESSION="max"
export RESTIC_CACHE_DIR="/var/cache/restic"
export RESTIC_LOG="/var/log/restic-$action.log"
# setup log file
log="/var/log/restic-"$(hostname)".log"
# check if .env file exists and source it
env="$home/$(hostname).env"
[[ -r "$env" ]] && source "$env"
# set default values for the notification if undefined
[[ -z "$RESTIC_NTFY_TITLE" ]] && RESTIC_NTFY_TITLE="$(hostname)"
[[ -z "$RESTIC_NTFY_ICON" ]] && RESTIC_NTFY_ICON="white_circle"
# execute "pre" action if defined
[[ -n "$RESTIC_ACTION_PRE" ]] && eval "$RESTIC_ACTION_PRE"
# source / execute restic script
source "$script" 2>&1 | tee "$log"
source "$script" > >(tee "$RESTIC_LOG") 2>&1
# send a notification when finished
/home/velvettear/.dots/scripts/notify.sh "backups" "$log" --title "$host" --icon "green_circle"
# execute "post" action if defined
[[ -n "$RESTIC_ACTION_POST" ]] && eval "$RESTIC_ACTION_POST"
# send a notification
/home/velvettear/.dots/scripts/notify.sh "restic" "$RESTIC_LOG" --title "$RESTIC_NTFY_TITLE" --icon "$RESTIC_NTFY_ICON" > /dev/null

View file

@ -42,11 +42,10 @@ printf ""$font_colored"> removing orphaned packages..."$font_default"\n"
printf ""$font_colored"> removing \"no valid subscription\" message..."$font_default"\n"
sed -i.bak "s/data.status.* !== 'ACTIVE'/false/I" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
if [[ "$(which restic &> /dev/null)" ]]; then
printf ""$font_colored"> updating restic..."$font_default"\n"
restic self-update
#printf ""$font_colored"> installing dark theme..."$font_default"\n"
#bash <(curl -s https://raw.githubusercontent.com/Weilbyte/PVEDiscordDark/master/PVEDiscordDark.sh ) install
fi
printf ""$font_colored_bold">> system updated finished after "$SECONDS" seconds!"$font_default"\n"

View file

@ -0,0 +1,9 @@
[Unit]
Description=set cpu governor to %i
[Service]
Type=oneshot
ExecStart=cpupower frequency-set -g %i
[Install]
WantedBy=multi-user.target

9
systemd/hdparm.service Normal file
View file

@ -0,0 +1,9 @@
[Unit]
Description=put various drives in standby mode and set their spin-down timer
[Service]
Type=oneshot
ExecStart=/home/velvettear/.dots/scripts/hdparm/hdparm.sh
[Install]
WantedBy=multi-user.target

9
systemd/powertop.service Normal file
View file

@ -0,0 +1,9 @@
[Unit]
Description=enable various powersaving modes
[Service]
Type=oneshot
ExecStart=/home/velvettear/.dots/scripts/powertop/powertop.sh
[Install]
WantedBy=multi-user.target

View file

@ -5,7 +5,7 @@ Before=nginx.service
[Service]
Type=oneshot
ExecStart=/etc/velvettear/scripts/prepare-fs.sh
ExecStart=/home/velvettear/.dots/scripts/prepare-fs.sh
[Install]
WantedBy=multi-user.target

View file

@ -4,7 +4,6 @@ Description=restic backup
[Service]
Type=oneshot
ExecStart=/home/velvettear/.dots/scripts/restic/restic.sh
ExecStartPost=/home/velvettear/.dots/scripts/notify.sh "backups" "/var/log/restic-%i.log" --title "%i" --icon "green_circle"
[Install]
WantedBy=multi-user.target

View file

@ -69,3 +69,4 @@ alias vim="nvim"
# scripts
alias update="sudo $VELVETTEAR_DOTS/scripts/update.sh"
alias merge="$VELVETTEAR_DOTS/scripts/merge.sh"

View file

@ -3,6 +3,8 @@
# author: Daniel Sommer <daniel.sommer@velvettear.de>
# license: MIT
# share zsh history
setopt SHARE_HISTORY
# exit if user is not root
[[ "$EUID" != "0" ]] && return
echo "LOGIN AS ROOT"