diff --git a/internal/hook/hook.go b/internal/hook/hook.go
index 0510095..0347f26 100644
--- a/internal/hook/hook.go
+++ b/internal/hook/hook.go
@@ -13,12 +13,12 @@ import (
 	"errors"
 	"fmt"
 	"hash"
-	"io/ioutil"
 	"log"
 	"math"
 	"net"
 	"net/textproto"
 	"os"
+	"path"
 	"reflect"
 	"regexp"
 	"strconv"
@@ -750,14 +750,18 @@ func (h *Hooks) LoadFromFile(path string, asTemplate bool) error {
 	}
 
 	// parse hook file for hooks
-	file, e := ioutil.ReadFile(path)
+	file, e := os.ReadFile(path)
 
 	if e != nil {
 		return e
 	}
 
 	if asTemplate {
-		funcMap := template.FuncMap{"getenv": getenv}
+		funcMap := template.FuncMap{
+			"cat":        cat,
+			"credential": credential,
+			"getenv":     getenv,
+		}
 
 		tmpl, err := template.New("hooks").Funcs(funcMap).Parse(string(file))
 		if err != nil {
@@ -956,3 +960,27 @@ func compare(a, b string) bool {
 func getenv(s string) string {
 	return os.Getenv(s)
 }
+
+// cat provides a template function to retrieve content of files
+// Similarly to getenv, if no file is found, it returns the empty string
+func cat(s string) string {
+	data, e := os.ReadFile(s)
+
+	if e != nil {
+		return ""
+	}
+
+	return strings.TrimSuffix(string(data), "\n")
+}
+
+// credential provides a template function to retreive secrets using systemd's LoadCredential mechanism
+func credential(s string) string {
+	dir := getenv("CREDENTIALS_DIRECTORY")
+
+	// If no credential directory is found, fallback to the env variable
+	if dir == "" {
+		return getenv(s)
+	}
+
+	return cat(path.Join(dir, s))
+}