547 lines
13 KiB
Org Mode
547 lines
13 KiB
Org Mode
#+TITLE: =systemd= services and timers
|
|
#+SETUPFILE: ./setup/org-setup-file.org
|
|
|
|
https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units
|
|
|
|
* =braingit= - Automatic commit and push new brain pages
|
|
** Service
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/braingit.service
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+BEGIN_SRC conf
|
|
[Unit]
|
|
Description=Sync Brain Website everyday
|
|
RefuseManualStart=no
|
|
RefuseManualStop=yes
|
|
OnFailure=notify-via-gotify@%i.service
|
|
|
|
[Service]
|
|
Environment="PASSWORD_STORE_DIR=/home/thomas/.local/share/pass"
|
|
Environment="GNUPGHOME=/home/thomas/.local/share/gnupg"
|
|
Type=oneshot
|
|
ExecStart=%h/.local/bin/brain_git_push
|
|
#+END_SRC
|
|
|
|
** Timer
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/braingit.timer
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+BEGIN_SRC conf
|
|
[Unit]
|
|
Description=Sync Brain Website everyday
|
|
RefuseManualStart=no
|
|
RefuseManualStop=no
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Timer]
|
|
Persistent=false
|
|
OnBootSec=30min
|
|
OnUnitActiveSec=1d
|
|
Unit=braingit.service
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
#+END_SRC
|
|
|
|
** Script
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.local/bin/brain_git_push
|
|
:header-args+: :comments both :mkdirp yes
|
|
:header-args+: :shebang "#!/usr/bin/env bash"
|
|
:END:
|
|
|
|
#+begin_src bash
|
|
cd /home/thomas/Cloud/programming/brain-website/
|
|
|
|
if [[ ! -z $(git status -s content/) ]]
|
|
then
|
|
git add content static && \
|
|
git commit -m "Update Content - $(date +%F)" && \
|
|
git push
|
|
exit
|
|
fi
|
|
#+end_src
|
|
|
|
* =notify-via-gotify= - Notify
|
|
** Service
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/notify-via-gotify@.service
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+begin_src conf
|
|
[Unit]
|
|
Description=%i failure notification over gotify
|
|
|
|
[Service]
|
|
Environment="PASSWORD_STORE_DIR=/home/thomas/.local/share/pass"
|
|
Environment="GNUPGHOME=/home/thomas/.local/share/gnupg"
|
|
Type=oneshot
|
|
ExecStart=/bin/bash -c "systemctl status -n10 %i | ~/.local/bin/create-gotify-notification-for-systemd --unit %i --host %H | curl -XPOST \"https://gotify.tdehaeze.xyz/message?token=$(pass nas/gotify_notif_token | sed -n 1p)\" -H \"Content-Type: application/json\" --data-binary @-"
|
|
#+end_src
|
|
|
|
** Script
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.local/bin/create-gotify-notification-for-systemd
|
|
:header-args+: :comments both :mkdirp yes
|
|
:header-args+: :shebang "#!/usr/bin/env python3"
|
|
:END:
|
|
#+begin_src python
|
|
import json
|
|
import argparse
|
|
import sys
|
|
|
|
|
|
TITLE_TEMPLATE = "Systemd unit failed"
|
|
|
|
MESSAGE_TEMPLATE = "Systemd unit {unit} failed on host {host}."
|
|
|
|
|
|
def main():
|
|
arguments = parse_arguments()
|
|
status = "\n".join(" " + line.rstrip() for line in sys.stdin.readlines())
|
|
message = MESSAGE_TEMPLATE.format(unit=arguments.unit, host=arguments.host, status=status)
|
|
title = TITLE_TEMPLATE.format(unit=arguments.unit, host=arguments.host)
|
|
output = create_gotify_json(title, message, arguments.priority)
|
|
print(output)
|
|
|
|
|
|
def parse_arguments():
|
|
parser = argparse.ArgumentParser(
|
|
description="Create Gotify notification for failing systemd unit",
|
|
)
|
|
parser.add_argument(
|
|
"--unit",
|
|
default="unknown",
|
|
help="the failing systemd unit name",
|
|
)
|
|
parser.add_argument(
|
|
"--host",
|
|
default="unknown",
|
|
help="the failing systemd unit host",
|
|
)
|
|
parser.add_argument(
|
|
"--priority",
|
|
default="5",
|
|
type=int,
|
|
help="the notification priority",
|
|
)
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def create_gotify_json(title, message, priority):
|
|
data = {
|
|
"title": title,
|
|
"message": message,
|
|
"priority": priority,
|
|
"extras": {
|
|
"client::display": {
|
|
"contentType": "text/markdown"
|
|
},
|
|
},
|
|
}
|
|
|
|
return json.dumps(data)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
#+end_src
|
|
|
|
* =checkmail= - Check new mails
|
|
** Service
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/checkmail.service
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+BEGIN_SRC conf
|
|
[Unit]
|
|
Description=Check new mails
|
|
RefuseManualStart=no
|
|
RefuseManualStop=yes
|
|
OnFailure=notify-via-gotify@%i.service
|
|
|
|
[Service]
|
|
Environment="PASSWORD_STORE_DIR=/home/thomas/.local/share/pass"
|
|
Environment="GNUPGHOME=/home/thomas/.local/share/gnupg"
|
|
Type=oneshot
|
|
ExecStart=%h/.local/bin/checkmail -q
|
|
#+END_SRC
|
|
|
|
** Timer
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/checkmail.timer
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+BEGIN_SRC conf
|
|
[Unit]
|
|
Description=Check Mail every x minutes
|
|
RefuseManualStart=no
|
|
RefuseManualStop=no
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Timer]
|
|
Persistent=false
|
|
OnBootSec=2min
|
|
OnUnitActiveSec=5min
|
|
AccuracySec=2min
|
|
Unit=checkmail.service
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
#+END_SRC
|
|
|
|
** Script
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.local/bin/checkmail
|
|
:header-args+: :comments both :mkdirp yes
|
|
:header-args+: :shebang "#!/usr/bin/env bash"
|
|
:END:
|
|
|
|
#+begin_src bash
|
|
while [ -n "$1" ]; do # while loop starts
|
|
case "$1" in
|
|
-a) opt_all='--all' ;; # Check All inboxes
|
|
-v) opt_verbose='--verbose' ;; # Verbose
|
|
-q) opt_quiet='--quiet' ;; # Quiet
|
|
,*) echo "Option $1 not recognized" ;; # In case you typed a different option
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# Count number of new mails before retreiving mails
|
|
gmail_old="$(ls ~/.local/share/mails/gmail/Inbox/new | wc -l)"
|
|
esrf_old="$(ls ~/.local/share/mails/esrf/Inbox/new | wc -l)"
|
|
|
|
# Retreive mails
|
|
mbsync -c /home/thomas/.config/isync/mbsyncrc $opt_all $opt_verbose gmail-Home esrf-Home 2>/tmp/mbsync.log
|
|
|
|
# Count number of new mails after retreiving mails
|
|
gmail_new="$(ls ~/.local/share/mails/gmail/Inbox/new | wc -l)"
|
|
esrf_new="$(ls ~/.local/share/mails/esrf/Inbox/new | wc -l)"
|
|
|
|
# Notification if there are new retreive mails
|
|
if [ "$(($esrf_new+$gmail_new))" -gt "$(($esrf_old+$gmail_old))" ]; then
|
|
dunstify --replace=98465 'Mails ' "$(($gmail_new+$esrf_new)) new mail(s)"
|
|
fi
|
|
|
|
# Indexation and Tags
|
|
mu index $opt_verbose $opt_quiet
|
|
#+end_src
|
|
|
|
* =syncmail= - Synchronize all mails
|
|
** Service
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/syncmail.service
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+BEGIN_SRC conf
|
|
[Unit]
|
|
Description=Sync all mails
|
|
RefuseManualStart=no
|
|
RefuseManualStop=yes
|
|
OnFailure=notify-via-gotify@%i.service
|
|
|
|
[Service]
|
|
Environment="PASSWORD_STORE_DIR=/home/thomas/.local/share/pass"
|
|
Environment="GNUPGHOME=/home/thomas/.local/share/gnupg"
|
|
Type=oneshot
|
|
ExecStart=%h/.local/bin/checkmail -a -q
|
|
#+END_SRC
|
|
|
|
** Timer
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/syncmail.timer
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+BEGIN_SRC conf
|
|
[Unit]
|
|
Description=Sync All Mails every x hours
|
|
RefuseManualStart=no
|
|
RefuseManualStop=no
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Timer]
|
|
Persistent=false
|
|
OnBootSec=30min
|
|
OnUnitActiveSec=300min
|
|
AccuracySec=10min
|
|
Unit=syncmail.service
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
#+END_SRC
|
|
|
|
* =vdirsyncer= - Synchronize calendar and contacts
|
|
** Service
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/vdirsyncer.service
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+begin_src conf
|
|
[Unit]
|
|
Description=Synchronize calendars and contacts
|
|
Documentation=https://vdirsyncer.readthedocs.org/
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
OnFailure=notify-via-gotify@%i.service
|
|
|
|
[Service]
|
|
Environment="PASSWORD_STORE_DIR=/home/thomas/.local/share/pass"
|
|
Environment="GNUPGHOME=/home/thomas/.local/share/gnupg"
|
|
ExecStart=/usr/bin/vdirsyncer --verbosity "ERROR" sync
|
|
Type=oneshot
|
|
#+end_src
|
|
|
|
** Timer
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/vdirsyncer.timer
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+begin_src conf
|
|
[Unit]
|
|
Description=Synchronize vdirs
|
|
|
|
[Timer]
|
|
OnBootSec=5m
|
|
OnUnitActiveSec=15m
|
|
AccuracySec=5m
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
#+end_src
|
|
|
|
* =syncthing= - Synchronize =Cloud= directory
|
|
** Service
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/syncthing.service
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+begin_src conf
|
|
[Unit]
|
|
Description=Syncthing - Open Source Continuous File Synchronization for %I
|
|
Documentation=man:syncthing(1)
|
|
After=network.target
|
|
|
|
[Service]
|
|
Environment="all_proxy=socks5://localhost:8080"
|
|
ExecStart=/usr/bin/syncthing -no-browser -gui-address="0.0.0.0:8384" -no-restart -logflags=0
|
|
Restart=on-failure
|
|
SuccessExitStatus=3 4
|
|
RestartForceExitStatus=3 4
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
#+end_src
|
|
|
|
* =restic-backup= - Backup Home Directory
|
|
** Backup
|
|
*** Service
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/restic-backup.service
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+BEGIN_SRC conf
|
|
[Unit]
|
|
Description=Backup Home Directory
|
|
RefuseManualStart=no
|
|
RefuseManualStop=no
|
|
OnFailure=notify-via-gotify@%i.service
|
|
|
|
[Service]
|
|
Environment="PASSWORD_STORE_DIR=/home/thomas/.local/share/pass"
|
|
Environment="GNUPGHOME=/home/thomas/.local/share/gnupg"
|
|
Type=oneshot
|
|
ExecStart=%h/.local/bin/restic-backup
|
|
ExecStartPost=/bin/sleep 30
|
|
ExecStartPost=%h/.local/bin/restic-forget
|
|
#+END_SRC
|
|
|
|
*** Timer
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/restic-backup.timer
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+BEGIN_SRC conf
|
|
[Unit]
|
|
Description=Backup Home Directory Everyday
|
|
RefuseManualStart=no
|
|
RefuseManualStop=no
|
|
Wants=network-online.target
|
|
|
|
[Timer]
|
|
Persistent=true
|
|
OnCalendar=daily
|
|
Unit=restic-backup.service
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
#+END_SRC
|
|
|
|
*** Script - Backup
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.local/bin/restic-backup
|
|
:header-args+: :comments both :mkdirp yes
|
|
:header-args+: :shebang "#!/usr/bin/env bash"
|
|
:END:
|
|
|
|
#+begin_src bash
|
|
restic backup \
|
|
-r sftp:thomas@homelab:/srv/storage/Backups/esrf-laptop \
|
|
--password-command "pass show restic" \
|
|
--verbose --one-file-system --tag systemd.timer \
|
|
--exclude "/home/thomas/.cache" \
|
|
--exclude "/home/thomas/Cloud" \
|
|
--exclude "/home/thomas/mnt" \
|
|
--exclude "/home/thomas/perl5" \
|
|
--exclude "/home/thomas/.local/soft" \
|
|
/home/thomas
|
|
#+end_src
|
|
|
|
*** Script - Forget
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.local/bin/restic-forget
|
|
:header-args+: :comments both :mkdirp yes
|
|
:header-args+: :shebang "#!/usr/bin/env bash"
|
|
:END:
|
|
|
|
#+begin_src bash
|
|
restic unlock \
|
|
-r sftp:thomas@homelab:/srv/storage/Backups/esrf-laptop \
|
|
--password-command "pass show restic" && \
|
|
restic forget \
|
|
-r sftp:thomas@homelab:/srv/storage/Backups/esrf-laptop \
|
|
--password-command "pass show restic" \
|
|
--verbose --tag systemd.timer \
|
|
--group-by "paths,tags" \
|
|
--keep-daily 7 \
|
|
--keep-weekly 4 \
|
|
--keep-monthly 1 \
|
|
--keep-yearly 1
|
|
#+end_src
|
|
|
|
** Prune
|
|
*** Service
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/restic-prune.service
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+BEGIN_SRC conf
|
|
[Unit]
|
|
Description=Prune restic backup
|
|
RefuseManualStart=no
|
|
RefuseManualStop=no
|
|
OnFailure=notify-via-gotify@%i.service
|
|
|
|
[Service]
|
|
Environment="PASSWORD_STORE_DIR=/home/thomas/.local/share/pass"
|
|
Environment="GNUPGHOME=/home/thomas/.local/share/gnupg"
|
|
Type=oneshot
|
|
ExecStart=%h/.local/bin/restic-prune
|
|
#+END_SRC
|
|
|
|
*** Timer
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/restic-prune.timer
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+BEGIN_SRC conf
|
|
[Unit]
|
|
Description=Prune Restic Backup
|
|
RefuseManualStart=no
|
|
RefuseManualStop=no
|
|
Wants=network-online.target
|
|
|
|
[Timer]
|
|
Persistent=true
|
|
OnCalendar=monthly
|
|
Unit=restic-prune.service
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
#+END_SRC
|
|
|
|
*** Script
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.local/bin/restic-prune
|
|
:header-args+: :comments both :mkdirp yes
|
|
:header-args+: :shebang "#!/usr/bin/env bash"
|
|
:END:
|
|
|
|
#+begin_src bash
|
|
restic prune \
|
|
-r sftp:thomas@homelab:/srv/storage/Backups/esrf-laptop \
|
|
--password-command "pass show restic" \
|
|
#+end_src
|
|
|
|
* =homelab-tunnel= - SSH Tunnel
|
|
Useful to bypass firewalls.
|
|
This can we used on the browser:
|
|
- for =qutebrowser=, use =:set content.proxy socks5://localhost:8080= (can setup a shortcut for that)
|
|
|
|
This is also used for Syncthing.
|
|
|
|
** Service
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/homelab-tunnel.service
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+begin_src conf
|
|
[Unit]
|
|
Description=Setup a secure tunnel with homelab
|
|
After=network.target
|
|
|
|
[Service]
|
|
ExecStart=/usr/bin/ssh -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -D 8080 -q -N -T homelab
|
|
|
|
# Restart every >2 seconds to avoid StartLimitInterval failure
|
|
RestartSec=5
|
|
Restart=always
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
#+end_src
|
|
|
|
* =esrf-tunnel= - SSH Tunnel
|
|
** Service
|
|
:PROPERTIES:
|
|
:header-args: :tangle ~/.config/systemd/user/esrf-tunnel.service
|
|
:header-args+: :comments both :mkdirp yes
|
|
:END:
|
|
|
|
#+begin_src conf
|
|
[Unit]
|
|
Description=Setup a secure tunnel with ESRF
|
|
After=network.target
|
|
|
|
[Service]
|
|
ExecStart=/usr/bin/ssh -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -D 8081 -q -N -T firewall.esrf.fr
|
|
|
|
# Restart every >2 seconds to avoid StartLimitInterval failure
|
|
RestartSec=5
|
|
Restart=always
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
#+end_src
|