diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b5f98037f5a942a893e673927912ac27a86e0a4a
--- /dev/null
+++ b/.github/workflows/security.yml
@@ -0,0 +1,35 @@
+name: 'Run Security Tests'
+on:
+  push:
+    branches:
+      - main
+      - dev
+  pull_request:
+  schedule:
+    - cron: '* * * * 0' # run weekly
+
+permissions:
+  contents: read
+  actions: read
+  checks: write
+  security-events: write
+
+jobs:
+  report:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+
+      - name: Run Trivy vulnerability scanner in repo mode
+        uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 # 0.30.0
+        with:
+          scan-type: 'fs'
+          format: 'sarif'
+          output: 'trivy-results-fs.sarif'
+          severity: 'CRITICAL,HIGH,MEDIUM'
+
+      - name: Upload Trivy scan results to GitHub Security tab
+        uses: github/codeql-action/upload-sarif@45775bd8235c68ba998cffa5171334d58593da47 # v3
+        with:
+          sarif_file: 'trivy-results-fs.sarif'
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5b09289b4011573d42e98624aee55f0116e5ed8a..37625cf3885c382d4a2a57d581c3494c6e1a7cdf 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,14 +1,14 @@
 default_stages:
-- commit
+- pre-commit
 repos:
 - repo: https://github.com/pre-commit/pre-commit-hooks
-  rev: v4.6.0
+  rev: v5.0.0
   hooks:
   - id: trailing-whitespace
   - id: end-of-file-fixer
   - id: check-added-large-files
 - repo: https://github.com/commitizen-tools/commitizen
-  rev: v3.29.0
+  rev: v4.6.0
   hooks:
   - id: commitizen
     stages:
@@ -17,14 +17,14 @@ repos:
   hooks:
   - id: check-useless-excludes
 - repo: https://github.com/hadolint/hadolint
-  rev: v2.13.0-beta
+  rev: v2.13.1-beta
   hooks:
   - id: hadolint-docker
     args:
     - -t
     - warning
 - repo: https://github.com/igorshubovych/markdownlint-cli
-  rev: v0.41.0
+  rev: v0.44.0
   hooks:
   - id: markdownlint-fix
     args:
@@ -35,6 +35,6 @@ repos:
   hooks:
   - id: shellcheck
 - repo: https://github.com/renovatebot/pre-commit-hooks
-  rev: 38.85.1
+  rev: 39.251.0
   hooks:
     - id: renovate-config-validator
diff --git a/Dockerfile b/Dockerfile
index fe56d880e7f310e36028fd6e86536ccec73809fb..35f0409e4b4dea48ebcd7202aac5f0102df03a91 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -60,14 +60,14 @@ ARG BUILD_BASE_VERSION
 
 RUN set -x && \
     apk add --no-cache \
-        pkgconf="${PKG_CONF_VERSION}" \
-        openssl-dev="${OPENSSL_VERSION}" \
-        build-base="${BUILD_BASE_VERSION}" \
-        acl-dev="${ACL_VERSION}" \
-        zstd-dev="${ZSTD_VERSION}" \
-        lz4-dev="${LZ4_VERSION}" \
-        xxhash-dev="${XXHASH_VERSION}" \
-        linux-headers="${LINUX_HEADERS_VERSION}" \
+    pkgconf="${PKG_CONF_VERSION}" \
+    openssl-dev="${OPENSSL_VERSION}" \
+    build-base="${BUILD_BASE_VERSION}" \
+    acl-dev="${ACL_VERSION}" \
+    zstd-dev="${ZSTD_VERSION}" \
+    lz4-dev="${LZ4_VERSION}" \
+    xxhash-dev="${XXHASH_VERSION}" \
+    linux-headers="${LINUX_HEADERS_VERSION}" \
     && mkdir /wheel \
     && pip wheel borgbackup=="${BORGBACKUP_VERSION}" -w /wheel
 
@@ -105,16 +105,16 @@ ENV ENSURE_BACKUP_PERMISSIONS=true
 
 RUN set -x && \
     apk add --no-cache \
-        openssh-server="${OPENSSH_VERSION}" \
-        sed="${SED_VERSION}" \
-        bash="${BASH_VERSION}" \
-        shadow="${SHADOW_VERSION}" \
-        openssl="${OPENSSL_VERSION}" \
-        xxhash="${XXHASH_VERSION}" xxhash-dev="${XXHASH_VERSION}" \
-        acl="${ACL_VERSION}" acl-dev="${ACL_VERSION}" \
-        zstd="${ZSTD_VERSION}" zstd-dev="${ZSTD_VERSION}" \
-        lz4="${LZ4_VERSION}" lz4-dev="${LZ4_VERSION}" \
-        linux-headers="${LINUX_HEADERS_VERSION}" \
+    openssh-server="${OPENSSH_VERSION}" \
+    sed="${SED_VERSION}" \
+    bash="${BASH_VERSION}" \
+    shadow="${SHADOW_VERSION}" \
+    openssl="${OPENSSL_VERSION}" \
+    xxhash="${XXHASH_VERSION}" xxhash-dev="${XXHASH_VERSION}" \
+    acl="${ACL_VERSION}" acl-dev="${ACL_VERSION}" \
+    zstd="${ZSTD_VERSION}" zstd-dev="${ZSTD_VERSION}" \
+    lz4="${LZ4_VERSION}" lz4-dev="${LZ4_VERSION}" \
+    linux-headers="${LINUX_HEADERS_VERSION}" \
     && adduser -D -u 500 borg borg \
     && mkdir -p /var/run/sshd /var/backups/borg /var/lib/docker-borg/ssh \
     && mkdir /home/borg/.ssh \
@@ -122,24 +122,25 @@ RUN set -x && \
     && chmod 700 /home/borg/.ssh
 
 COPY --from=builder /wheel /wheel
-RUN pip --no-cache-dir install /wheel/*.whl
+RUN pip --no-cache-dir install --compile /wheel/*.whl
 
 # Configure SSH
 RUN set -x \
     && sed -i \
-        -e 's/^#PasswordAuthentication yes$/PasswordAuthentication no/g' \
-        -e 's/^PermitRootLogin without-password$/PermitRootLogin no/g' \
-        -e 's/^X11Forwarding yes$/X11Forwarding no/g' \
-        -e 's/^#LogLevel .*$/LogLevel ERROR/g' \
-        /etc/ssh/sshd_config \
-&& echo "ClientAliveInterval 10" >> /etc/ssh/sshd_config \
-&& echo "ClientAliveCountMax 30" >> /etc/ssh/sshd_config \
-&& mkdir -p /var/lib/docker-borg/ssh \
-&& mkdir -p /home/borg/backups
+    -e 's/^#PasswordAuthentication yes$/PasswordAuthentication no/g' \
+    -e 's/^PermitRootLogin without-password$/PermitRootLogin no/g' \
+    -e 's/^X11Forwarding yes$/X11Forwarding no/g' \
+    -e 's/^#LogLevel .*$/LogLevel ERROR/g' \
+    /etc/ssh/sshd_config \
+    && echo "ClientAliveInterval 10" >> /etc/ssh/sshd_config \
+    && echo "ClientAliveCountMax 30" >> /etc/ssh/sshd_config \
+    && mkdir -p /var/lib/docker-borg/ssh \
+    && mkdir -p /home/borg/backups
 
 VOLUME ["/home/borg/backups/", "/var/lib/docker-borg", "/home/borg/.ssh/"]
 
 COPY ./entrypoint.sh /
 
 EXPOSE 22
+
 CMD ["/entrypoint.sh"]
diff --git a/docker-compose.yml b/docker-compose.yml
index dd0479961f4b8e3cfdf12b130dcaad4b3a523f18..f60d766ffb5bd5c78c6b6bca2e006f1f464970be 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,5 +1,3 @@
-version: '3'
-
 services:
   borg:
     #image: ghcr.io/anotherstranger/borg-server:latest
diff --git a/renovate.json b/renovate.json
index ddfe0ab27653073f642e5f3d0515171ea5b2007b..387a93233acc9f456a5c9e678ce76cd860b72e5a 100644
--- a/renovate.json
+++ b/renovate.json
@@ -1,15 +1,32 @@
 {
   "$schema": "https://docs.renovatebot.com/renovate-schema.json",
-  "extends": ["config:best-practices", ":semanticCommitTypeAll(refactor)"],
-  "baseBranches": ["dev"],
+  "extends": [
+    "config:best-practices",
+    ":semanticCommitTypeAll(refactor)",
+    "group:all",
+    "workarounds:all",
+    "automergeDigest",
+    "automergeMinor",
+    ":configMigration"
+  ],
+  "baseBranches": [
+    "dev"
+  ],
   "packageRules": [
     {
-      "matchDatasources": ["docker"],
-      "matchPackageNames": ["python"],
+      "matchDatasources": [
+        "docker"
+      ],
+      "matchPackageNames": [
+        "python"
+      ],
       "versioning": "regex:^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)(?<prerelease>[^.-]+)?(-(?<compatibility>[^0.9]+)(?<build>[0-9.]+))?$"
     },
     {
-      "matchUpdateTypes": ["minor", "patch"],
+      "matchUpdateTypes": [
+        "minor",
+        "patch"
+      ],
       "matchCurrentVersion": "!/^0/",
       "automerge": true
     }
@@ -17,7 +34,9 @@
   "customManagers": [
     {
       "customType": "regex",
-      "fileMatch": ["^Dockerfile$"],
+      "fileMatch": [
+        "^Dockerfile$"
+      ],
       "matchStrings": [
         "#\\s*renovate:\\s*datasource=(?<datasource>.*?) depName=(?<depName>.*?)( versioning=(?<versioning>.*?))?\\sARG .*?_VERSION=\"(?<currentValue>.*)\"\\s"
       ],
@@ -25,7 +44,7 @@
     }
   ],
   "ignorePaths": [
-      "docker-compose.yml"
+    "docker-compose.yml"
   ],
   "ignoreUnstable": true,
   "minimumReleaseAge": "7 days",