diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..d50f278 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,3 @@ +[defaults] +callbacks_enabled = timer, profile_tasks +pipelining = True diff --git a/playbooks/apps/all.yaml b/playbooks/apps/all.yaml index 7a0ac54..a33b81f 100644 --- a/playbooks/apps/all.yaml +++ b/playbooks/apps/all.yaml @@ -1,4 +1,5 @@ --- +- import_playbook: bin.yaml # noqa: name[play] - import_playbook: caddy.yaml # noqa: name[play] - import_playbook: ghost-update.yaml # noqa: name[play] - import_playbook: gitea.yaml # noqa: name[play] diff --git a/playbooks/apps/bin.yaml b/playbooks/apps/bin.yaml new file mode 100644 index 0000000..93d3f87 --- /dev/null +++ b/playbooks/apps/bin.yaml @@ -0,0 +1,65 @@ +--- +- name: Bin files & scripts + hosts: servers + gather_facts: false + tasks: + - name: Write bin files + ansible.builtin.copy: + src: "{{ item }}" + dest: /mnt/data/bin/ + mode: preserve + with_fileglob: + - files/bin/* + - name: Template bin files + ansible.builtin.template: + src: "{{ item }}" + dest: /mnt/data/bin/{{ item | basename | regex_replace('\.j2$', '') }} + mode: preserve + with_fileglob: + - templates/bin/*.j2 + vars: + ghost_db_password: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 35343430343439653064613033383830396264306538376535346637613166376663393062353132 + 6537386534656239333731313938653539643165323532380a336162663839303339623266383662 + 39346464306261633239363665666334613064393432663335313431326463376637356437653262 + 3161633364303839300a366135653466313836376361326165303465396438333962386230336133 + 34643963356538356464366433373464316337636337386430373265633336636537 + healthcheck_webhook_token: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 61303433666361376638353034323834623935393834346362623538663936303764363866636164 + 3364306166303430343532623935373838333632323032360a373330376464376438613764326662 + 32653135316361636163356363623364323537396236333233313933336565373530313363303536 + 3339613565313033360a346438376336386638653534356333633439613530396139383635643439 + 33313266373566376162643536386365386132346261623733343762356639396436 + hetrixtools_token: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 38663431333361643538646361353237613930646135633962386639376333366230343131633562 + 6531646235333565656266613236313133653563323737340a643931643366396236393935363038 + 34613661373863623033616431363531633136303830363434393135613365353938656337353936 + 6563353164313363380a613039623761613632306364616365316332333563306636356238636532 + 34333035346534383064346561316665343233373031353238383864386365393234356137396332 + 3363323336613962386638633539393636663461323035333065 + ovh_app_key: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 30646561656638353734373835386238383365393064656439646437326432383663666263623431 + 3639346366646538336333323161656562646266373233320a356136386234646234363732376266 + 33316461326132336534326266636239386532656262353034333434653933333637616332616632 + 6562643965353037660a656631656563633136356565323536363738663461653736303864383630 + 38346637396239316163666661373439656462623861653063393464616530323633 + ovh_app_secret: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 32396331666132363362313331633832303562633932353963636533663132353465636331653134 + 6466613637373933623063623563663331373764393262360a643030663036366335646234646335 + 38393036626139653733313362323866336164343335656635343564366439663264363866336137 + 6464346632396630610a303337316535326633376235383963313865373064363064306134323231 + 39633061336366393563366636656339623134323531613462636334636264353934303963633437 + 6161656465303732373366386134666234363636613832333166 + ovh_consumer_key: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 33623537363436363139346132353336383930333133643535383465373163636266356262306466 + 6563363661353337626462313338633465333865626162350a306332313233356366386236393066 + 66363735386566623335613966353462613963386435636537663235366134336461363837336638 + 3466633264626636620a613634653933333332386365393639343030616234376537373635343237 + 37373364303732343264623239353837613435363363393862383765376435376166343237333664 + 3330623266383462666564376166373032393361653234633863 diff --git a/playbooks/apps/files/bin/clean-old-backups b/playbooks/apps/files/bin/clean-old-backups new file mode 100755 index 0000000..15fff82 --- /dev/null +++ b/playbooks/apps/files/bin/clean-old-backups @@ -0,0 +1,3 @@ +#!/bin/bash +set -euo pipefail +find /mnt/data/backups/hass/* -mtime +5 -delete diff --git a/playbooks/apps/files/bin/cron2bash b/playbooks/apps/files/bin/cron2bash new file mode 100755 index 0000000..ab03a38 --- /dev/null +++ b/playbooks/apps/files/bin/cron2bash @@ -0,0 +1,8 @@ +#!/bin/bash +set -euo pipefail +script_name=$1 +cp .template $script_name +chmod +x $script_name +shift +echo "$@" >> $script_name +echo $(realpath $script_name) diff --git a/playbooks/apps/files/bin/docker-system-prune b/playbooks/apps/files/bin/docker-system-prune new file mode 100755 index 0000000..b0a013e --- /dev/null +++ b/playbooks/apps/files/bin/docker-system-prune @@ -0,0 +1,3 @@ +#!/bin/bash +set -euo pipefail +/usr/bin/docker system prune -af diff --git a/playbooks/apps/files/bin/dump-manuels b/playbooks/apps/files/bin/dump-manuels new file mode 100755 index 0000000..a85e812 --- /dev/null +++ b/playbooks/apps/files/bin/dump-manuels @@ -0,0 +1,3 @@ +#!/bin/bash +set -euo pipefail +/usr/bin/docker compose -f /mnt/data/manuels/docker-compose.yaml exec -T db pg_dump -Fc -U manuels manuels > /mnt/data/manuels/db_export/backup.dump diff --git a/playbooks/apps/files/bin/dump-miniflux b/playbooks/apps/files/bin/dump-miniflux new file mode 100755 index 0000000..6eb2e26 --- /dev/null +++ b/playbooks/apps/files/bin/dump-miniflux @@ -0,0 +1,3 @@ +#!/bin/bash +set -euo pipefail +/usr/bin/docker compose -f /mnt/data/miniflux/docker-compose.yaml exec -T db pg_dump -Fc -U miniflux miniflux > /mnt/data/miniflux/db_export/backup.dump diff --git a/playbooks/apps/files/bin/dump-nextcloud b/playbooks/apps/files/bin/dump-nextcloud new file mode 100755 index 0000000..235edb8 --- /dev/null +++ b/playbooks/apps/files/bin/dump-nextcloud @@ -0,0 +1,4 @@ +#!/bin/bash +set -euo pipefail +/usr/bin/docker compose -f /mnt/data/nextcloud/docker-compose.yaml exec -T db pg_dump -Fc -U nextcloud nextcloud > /mnt/data/nextcloud/db_export/backup.dump +/usr/bin/docker compose -f /mnt/data/nextcloud/docker-compose.yaml exec -T db pg_dumpall --globals-only -U nextcloud > /mnt/data/nextcloud/db_export/roles.sql diff --git a/playbooks/apps/files/bin/failure b/playbooks/apps/files/bin/failure new file mode 100755 index 0000000..ee79367 --- /dev/null +++ b/playbooks/apps/files/bin/failure @@ -0,0 +1,3 @@ +#!/bin/bash +set -euxo pipefail +exit 1 diff --git a/playbooks/apps/files/bin/nextcloud-auto-update b/playbooks/apps/files/bin/nextcloud-auto-update new file mode 100755 index 0000000..06b8594 --- /dev/null +++ b/playbooks/apps/files/bin/nextcloud-auto-update @@ -0,0 +1,3 @@ +#!/bin/bash +set -euo pipefail +/usr/bin/docker compose -f /mnt/data/nextcloud/docker-compose.yaml exec -T --user www-data nextcloud php occ app:update --all diff --git a/playbooks/apps/files/bin/nextcloud-cron b/playbooks/apps/files/bin/nextcloud-cron new file mode 100755 index 0000000..6e5e23e --- /dev/null +++ b/playbooks/apps/files/bin/nextcloud-cron @@ -0,0 +1,3 @@ +#!/bin/bash +set -euo pipefail +/usr/bin/docker compose -f /mnt/data/nextcloud/docker-compose.yaml exec -dT --user www-data nextcloud php cron.php diff --git a/playbooks/apps/files/bin/nextcloud-preview b/playbooks/apps/files/bin/nextcloud-preview new file mode 100755 index 0000000..858e2bd --- /dev/null +++ b/playbooks/apps/files/bin/nextcloud-preview @@ -0,0 +1,3 @@ +#!/bin/bash +set -euo pipefail +/usr/bin/docker compose -f /mnt/data/nextcloud/docker-compose.yaml exec -dT --user www-data nextcloud php occ preview:pre-generate diff --git a/playbooks/apps/files/bin/restic-backup b/playbooks/apps/files/bin/restic-backup new file mode 100755 index 0000000..7303383 --- /dev/null +++ b/playbooks/apps/files/bin/restic-backup @@ -0,0 +1,6 @@ +#!/bin/bash +set -euo pipefail +killall restic || true +source /mnt/data/bin/resticenv +/usr/bin/restic unlock +/usr/bin/restic backup --exclude-file /mnt/data/bin/restic-excludes /mnt/data/ /var/spool/cron/ $@ diff --git a/playbooks/apps/files/bin/restic-check b/playbooks/apps/files/bin/restic-check new file mode 100755 index 0000000..d3e3291 --- /dev/null +++ b/playbooks/apps/files/bin/restic-check @@ -0,0 +1,4 @@ +#!/bin/bash +set -euo pipefail +source /mnt/data/bin/resticenv +/usr/bin/restic check --read-data-subset=700M diff --git a/playbooks/apps/files/bin/restic-excludes b/playbooks/apps/files/bin/restic-excludes new file mode 100644 index 0000000..188e34e --- /dev/null +++ b/playbooks/apps/files/bin/restic-excludes @@ -0,0 +1,24 @@ +db_data +mysql_data +redis_data +*venv* +deluge_data +plex_data +shared_media +media/data +deluge +plex +prowlarr +radarr +sonarr +transmission +nextcloud_data/lib +nextcloud_data/data/appdata_ocw94g5hjk8b/preview +source_code +sources +.cache +.mozilla +prometheus_data +.es_temp_file +timemachine +elastic_data diff --git a/playbooks/apps/files/bin/restic-prune b/playbooks/apps/files/bin/restic-prune new file mode 100755 index 0000000..aad5b2a --- /dev/null +++ b/playbooks/apps/files/bin/restic-prune @@ -0,0 +1,6 @@ +#!/bin/bash +set -euo pipefail +killall restic || true +source /mnt/data/bin/resticenv +/usr/bin/restic unlock +/usr/bin/restic forget --prune --keep-within-hourly 1d --keep-within-daily 7d --keep-within-weekly 1m --keep-within-monthly 6m diff --git a/playbooks/apps/files/bin/resticenv b/playbooks/apps/files/bin/resticenv new file mode 100644 index 0000000..bcff4e6 --- /dev/null +++ b/playbooks/apps/files/bin/resticenv @@ -0,0 +1,18 @@ +$ANSIBLE_VAULT;1.1;AES256 +34643931646634623466323636613561313364633364663034363863353162323266343166363632 +3334363465393362393631356631666161653066663032350a613763383934376138646134313234 +66656436353737333138346133623261356137633066663937646565326439336532616436666336 +3137626464343636650a653064383038363231656136353532396436316363643235653739666631 +33316437333131636434383130376231366562323765343763343164303234386562333962346235 +61333865313138313462613738363231333536386639313433396533636433663432633236366232 +33643137306536626164353338623234393461373339333763356232376431363062373233303762 +38326239306535623237623634363439383838306263343964636637333865346261653639313030 +63353437343237346461313364336461633466383832363637643662633633633665383565623062 +34346338363936336163336431613634616136333163353961653436396332636332323832656338 +37653364366235636663626231636462663836343566343337346461633562663262626135303633 +36333366613033623836623064323238626661323037343266613530306439653535333032636336 +61316133383962353530383133323237333562336463623963613330373762636230616130633738 +31363232353937333536313266346266393233376236373834393232353362646266666336646134 +33323239636464313561646238656337333633366161336266353130343061323963356531356563 +62643136343535346538613738373561313362323833303739636637323366356430376135326132 +6666 diff --git a/playbooks/apps/files/bin/smartlong b/playbooks/apps/files/bin/smartlong new file mode 100755 index 0000000..294f106 --- /dev/null +++ b/playbooks/apps/files/bin/smartlong @@ -0,0 +1,6 @@ +#!/bin/bash + +/usr/sbin/smartctl -t long /dev/sda +/usr/sbin/smartctl -t long /dev/sdb +/usr/sbin/smartctl -t long /dev/sdc +/usr/sbin/smartctl -t long /dev/sdd diff --git a/playbooks/apps/files/bin/smartshort b/playbooks/apps/files/bin/smartshort new file mode 100755 index 0000000..0d06b1a --- /dev/null +++ b/playbooks/apps/files/bin/smartshort @@ -0,0 +1,6 @@ +#!/bin/bash + +/usr/sbin/smartctl -t short /dev/sda +/usr/sbin/smartctl -t short /dev/sdb +/usr/sbin/smartctl -t short /dev/sdc +/usr/sbin/smartctl -t short /dev/sdd diff --git a/playbooks/apps/files/bin/z.sh b/playbooks/apps/files/bin/z.sh new file mode 100644 index 0000000..67f504e --- /dev/null +++ b/playbooks/apps/files/bin/z.sh @@ -0,0 +1,267 @@ +# Copyright (c) 2009 rupa deadwyler. Licensed under the WTFPL license, Version 2 + +# maintains a jump-list of the directories you actually use +# +# INSTALL: +# * put something like this in your .bashrc/.zshrc: +# . /path/to/z.sh +# * cd around for a while to build up the db +# * PROFIT!! +# * optionally: +# set $_Z_CMD in .bashrc/.zshrc to change the command (default z). +# set $_Z_DATA in .bashrc/.zshrc to change the datafile (default ~/.z). +# set $_Z_MAX_SCORE lower to age entries out faster (default 9000). +# set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution. +# set $_Z_NO_PROMPT_COMMAND if you're handling PROMPT_COMMAND yourself. +# set $_Z_EXCLUDE_DIRS to an array of directories to exclude. +# set $_Z_OWNER to your username if you want use z while sudo with $HOME kept +# +# USE: +# * z foo # cd to most frecent dir matching foo +# * z foo bar # cd to most frecent dir matching foo and bar +# * z -r foo # cd to highest ranked dir matching foo +# * z -t foo # cd to most recently accessed dir matching foo +# * z -l foo # list matches instead of cd +# * z -e foo # echo the best match, don't cd +# * z -c foo # restrict matches to subdirs of $PWD +# * z -x # remove the current directory from the datafile +# * z -h # show a brief help message + +[ -d "${_Z_DATA:-$HOME/.z}" ] && { + echo "ERROR: z.sh's datafile (${_Z_DATA:-$HOME/.z}) is a directory." +} + +_z() { + + local datafile="${_Z_DATA:-$HOME/.z}" + + # if symlink, dereference + [ -h "$datafile" ] && datafile=$(readlink "$datafile") + + # bail if we don't own ~/.z and $_Z_OWNER not set + [ -z "$_Z_OWNER" -a -f "$datafile" -a ! -O "$datafile" ] && return + + _z_dirs () { + [ -f "$datafile" ] || return + + local line + while read line; do + # only count directories + [ -d "${line%%\|*}" ] && echo "$line" + done < "$datafile" + return 0 + } + + # add entries + if [ "$1" = "--add" ]; then + shift + + # $HOME and / aren't worth matching + [ "$*" = "$HOME" -o "$*" = '/' ] && return + + # don't track excluded directory trees + if [ ${#_Z_EXCLUDE_DIRS[@]} -gt 0 ]; then + local exclude + for exclude in "${_Z_EXCLUDE_DIRS[@]}"; do + case "$*" in "$exclude"*) return;; esac + done + fi + + # maintain the data file + local tempfile="$datafile.$RANDOM" + local score=${_Z_MAX_SCORE:-9000} + _z_dirs | awk -v path="$*" -v now="$(date +%s)" -v score=$score -F"|" ' + BEGIN { + rank[path] = 1 + time[path] = now + } + $2 >= 1 { + # drop ranks below 1 + if( $1 == path ) { + rank[$1] = $2 + 1 + time[$1] = now + } else { + rank[$1] = $2 + time[$1] = $3 + } + count += $2 + } + END { + if( count > score ) { + # aging + for( x in rank ) print x "|" 0.99*rank[x] "|" time[x] + } else for( x in rank ) print x "|" rank[x] "|" time[x] + } + ' 2>/dev/null >| "$tempfile" + # do our best to avoid clobbering the datafile in a race condition. + if [ $? -ne 0 -a -f "$datafile" ]; then + env rm -f "$tempfile" + else + [ "$_Z_OWNER" ] && chown $_Z_OWNER:"$(id -ng $_Z_OWNER)" "$tempfile" + env mv -f "$tempfile" "$datafile" || env rm -f "$tempfile" + fi + + # tab completion + elif [ "$1" = "--complete" -a -s "$datafile" ]; then + _z_dirs | awk -v q="$2" -F"|" ' + BEGIN { + q = substr(q, 3) + if( q == tolower(q) ) imatch = 1 + gsub(/ /, ".*", q) + } + { + if( imatch ) { + if( tolower($1) ~ q ) print $1 + } else if( $1 ~ q ) print $1 + } + ' 2>/dev/null + + else + # list/go + local echo fnd last list opt typ + while [ "$1" ]; do case "$1" in + --) while [ "$1" ]; do shift; fnd="$fnd${fnd:+ }$1";done;; + -*) opt=${1:1}; while [ "$opt" ]; do case ${opt:0:1} in + c) fnd="^$PWD $fnd";; + e) echo=1;; + h) echo "${_Z_CMD:-z} [-cehlrtx] args" >&2; return;; + l) list=1;; + r) typ="rank";; + t) typ="recent";; + x) sed -i -e "\:^${PWD}|.*:d" "$datafile";; + esac; opt=${opt:1}; done;; + *) fnd="$fnd${fnd:+ }$1";; + esac; last=$1; [ "$#" -gt 0 ] && shift; done + [ "$fnd" -a "$fnd" != "^$PWD " ] || list=1 + + # if we hit enter on a completion just go there + case "$last" in + # completions will always start with / + /*) [ -z "$list" -a -d "$last" ] && builtin cd "$last" && return;; + esac + + # no file yet + [ -f "$datafile" ] || return + + local cd + cd="$( < <( _z_dirs ) awk -v t="$(date +%s)" -v list="$list" -v typ="$typ" -v q="$fnd" -F"|" ' + function frecent(rank, time) { + # relate frequency and time + dx = t - time + return int(10000 * rank * (3.75/((0.0001 * dx + 1) + 0.25))) + } + function output(matches, best_match, common) { + # list or return the desired directory + if( list ) { + if( common ) { + printf "%-10s %s\n", "common:", common > "/dev/stderr" + } + cmd = "sort -n >&2" + for( x in matches ) { + if( matches[x] ) { + printf "%-10s %s\n", matches[x], x | cmd + } + } + } else { + if( common && !typ ) best_match = common + print best_match + } + } + function common(matches) { + # find the common root of a list of matches, if it exists + for( x in matches ) { + if( matches[x] && (!short || length(x) < length(short)) ) { + short = x + } + } + if( short == "/" ) return + for( x in matches ) if( matches[x] && index(x, short) != 1 ) { + return + } + return short + } + BEGIN { + gsub(" ", ".*", q) + hi_rank = ihi_rank = -9999999999 + } + { + if( typ == "rank" ) { + rank = $2 + } else if( typ == "recent" ) { + rank = $3 - t + } else rank = frecent($2, $3) + if( $1 ~ q ) { + matches[$1] = rank + } else if( tolower($1) ~ tolower(q) ) imatches[$1] = rank + if( matches[$1] && matches[$1] > hi_rank ) { + best_match = $1 + hi_rank = matches[$1] + } else if( imatches[$1] && imatches[$1] > ihi_rank ) { + ibest_match = $1 + ihi_rank = imatches[$1] + } + } + END { + # prefer case sensitive + if( best_match ) { + output(matches, best_match, common(matches)) + exit + } else if( ibest_match ) { + output(imatches, ibest_match, common(imatches)) + exit + } + exit(1) + } + ')" + + if [ "$?" -eq 0 ]; then + if [ "$cd" ]; then + if [ "$echo" ]; then echo "$cd"; else builtin cd "$cd"; fi + fi + else + return $? + fi + fi +} + +alias ${_Z_CMD:-z}='_z 2>&1' + +[ "$_Z_NO_RESOLVE_SYMLINKS" ] || _Z_RESOLVE_SYMLINKS="-P" + +if type compctl >/dev/null 2>&1; then + # zsh + [ "$_Z_NO_PROMPT_COMMAND" ] || { + # populate directory list, avoid clobbering any other precmds. + if [ "$_Z_NO_RESOLVE_SYMLINKS" ]; then + _z_precmd() { + (_z --add "${PWD:a}" &) + : $RANDOM + } + else + _z_precmd() { + (_z --add "${PWD:A}" &) + : $RANDOM + } + fi + [[ -n "${precmd_functions[(r)_z_precmd]}" ]] || { + precmd_functions[$(($#precmd_functions+1))]=_z_precmd + } + } + _z_zsh_tab_completion() { + # tab completion + local compl + read -l compl + reply=(${(f)"$(_z --complete "$compl")"}) + } + compctl -U -K _z_zsh_tab_completion _z +elif type complete >/dev/null 2>&1; then + # bash + # tab completion + complete -o filenames -C '_z --complete "$COMP_LINE"' ${_Z_CMD:-z} + [ "$_Z_NO_PROMPT_COMMAND" ] || { + # populate directory list. avoid clobbering other PROMPT_COMMANDs. + grep "_z --add" <<< "$PROMPT_COMMAND" >/dev/null || { + PROMPT_COMMAND="$PROMPT_COMMAND"$'\n''(_z --add "$(command pwd '$_Z_RESOLVE_SYMLINKS' 2>/dev/null)" 2>/dev/null &);' + } + } +fi diff --git a/playbooks/apps/templates/bin/dump-gabnotes.org.j2 b/playbooks/apps/templates/bin/dump-gabnotes.org.j2 new file mode 100755 index 0000000..0538df0 --- /dev/null +++ b/playbooks/apps/templates/bin/dump-gabnotes.org.j2 @@ -0,0 +1,3 @@ +#!/bin/bash +set -euo pipefail +/usr/bin/mysqldump --no-tablespaces -u root --password={{ ghost_db_password }} gabnotes_org_prod > /mnt/data/gabnotes.org/db_export/backup.sql diff --git a/playbooks/apps/templates/bin/dump-voyages.coccomagnard.fr.j2 b/playbooks/apps/templates/bin/dump-voyages.coccomagnard.fr.j2 new file mode 100755 index 0000000..aa2e308 --- /dev/null +++ b/playbooks/apps/templates/bin/dump-voyages.coccomagnard.fr.j2 @@ -0,0 +1,3 @@ +#!/bin/bash +set -euo pipefail +/usr/bin/mysqldump --no-tablespaces -u root --password={{ ghost_db_password }} voyages_coccomagnard_fr_prod > /mnt/data/voyages.coccomagnard.fr/db_export/backup.sql diff --git a/playbooks/apps/templates/bin/healthcheck.j2 b/playbooks/apps/templates/bin/healthcheck.j2 new file mode 100755 index 0000000..8929d2b --- /dev/null +++ b/playbooks/apps/templates/bin/healthcheck.j2 @@ -0,0 +1,11 @@ +#!/bin/bash +set -uo pipefail +RID=`uuidgen` +BASE_URL="https://hc-ping.com/{{ healthcheck_webhook_token }}/$1" +START_URL="$BASE_URL/start?rid=$RID" +shift + +curl -A "ubuntu-vm" -fsS --retry 5 -o /dev/null $START_URL +logs=$($@ 2>&1) +status=$? +curl -A "ubuntu-vm" -fsS --retry 5 --data-raw "$logs" -o /dev/null "$BASE_URL/$status?rid=$RID" diff --git a/playbooks/apps/templates/bin/maintenance.j2 b/playbooks/apps/templates/bin/maintenance.j2 new file mode 100755 index 0000000..5068b89 --- /dev/null +++ b/playbooks/apps/templates/bin/maintenance.j2 @@ -0,0 +1,30 @@ +#!/bin/bash +set -euo pipefail + +# https://api.hetrixtools.com/v2//maintenance/// +# Modify the maintenance status of any of your Uptime Monitors. +# - Your API Access Token, in your particular case it's: {{ hetrixtools_token }} +# - You can find the ID of any of your Uptime Monitors by using the API Call 'v1 List Uptime Monitors', it is listed for every uptime monitor as 'ID' +# - The type of maintenance. Accepted values (numbers): 1, 2, or 3. +# 1 - no maintenance mode (normal) - use this to exit maintenance mode +# 2 - maintenance mode with notifications +# 3 - maintenance mode without notifications + +API_TOKEN="{{ hetrixtools_token }}" +mode=$1 +if [ "$mode" == "on" ]; then + mode=3 +elif [ "$mode" == "off" ]; then + mode=1 +else + echo "usage $0 " + exit 1 +fi + +ids=$(curl -sSL https://api.hetrixtools.com/v1/$API_TOKEN/uptime/monitors/0/5000/ | jq -r '.[0][] | .ID') + +for id in $ids; do + curl -sSL https://api.hetrixtools.com/v2/$API_TOKEN/maintenance/$id/$mode/ > /dev/null +done + +echo "Done" diff --git a/playbooks/apps/templates/bin/new_domain.py.j2 b/playbooks/apps/templates/bin/new_domain.py.j2 new file mode 100755 index 0000000..baebf27 --- /dev/null +++ b/playbooks/apps/templates/bin/new_domain.py.j2 @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 + +import json +import sys + +import ovh + +# Instantiate an OVH Client. +# You can generate new credentials with full access to your account on +# the token creation page (https://api.ovh.com/createToken/index.cgi?GET=/*&PUT=/*&POST=/*&DELETE=/*) +# List of available endpoints: https://github.com/ovh/python-ovh#2-configure-your-application +client = ovh.Client( + endpoint='ovh-eu', + application_key='{{ ovh_app_key }}', + application_secret='{{ ovh_app_secret }}', + consumer_key='{{ ovh_consumer_key }}', +) + +if len(sys.argv) != 2: + print(f"usage: {sys.argv[0]} ") + print(f"example: {sys.argv[0]} testing") + print("no need to include '.augendre.info'") + sys.exit(1) + +subdomain = sys.argv[1].removesuffix(".augendre.info") +res = client.get("/domain/zone/augendre.info/record", fieldType="CNAME", subDomain=subdomain) +if len(res) > 0: + print("CNAME already exists") + sys.exit(0) + +print("creating domain:") +res = client.post("/domain/zone/augendre.info/record", + fieldType="CNAME", + subDomain=subdomain, + target="nginx.augendre.info.", + ttl=86400, +) +print(json.dumps(res, indent=4)) + +print("refreshing zone:") +res = client.post("/domain/zone/augendre.info/refresh") +print(json.dumps(res, indent=4))