diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..f1969cc2
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,43 @@
+# Editor configuration, see http://editorconfig.org
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+charset = utf-8
+indent_style = space
+indent_size = 2
+
+# Ignore diffs/patches
+[*.{diff,patch}]
+end_of_line = unset
+insert_final_newline = unset
+trim_trailing_whitespace = unset
+indent_size = unset
+charset = unset
+indent_style = unset
+indent_size = unset
+
+[{.*,secrets}/**]
+end_of_line = false
+insert_final_newline = false
+trim_trailing_whitespace = unset
+charset = unset
+indent_style = unset
+indent_size = unset
+
+[*.rom]
+end_of_line = unset
+insert_final_newline = unset
+trim_trailing_whitespace = unset
+charset = unset
+indent_style = unset
+indent_size = unset
+
+[*.py]
+indent_size = 4
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/.forgejo/workflows/check.yml b/.forgejo/workflows/check.yml
index 09688329..0a62d115 100644
--- a/.forgejo/workflows/check.yml
+++ b/.forgejo/workflows/check.yml
@@ -1,71 +1,24 @@
 name: Flake checks
 on: [pull_request]
-env:
-  USER: ci
 
 jobs:
   Check:
-    runs-on: ubuntu-latest
+    runs-on: self-hosted
     steps:
       - name: Check out repository code
         uses: https://code.forgejo.org/actions/checkout@v4
 
-      - uses: https://github.com/nixbuild/nix-quick-install-action@v27
-        with:
-          load_nixConfig: false
-          nix_conf: |
-            substituters = https://cache.nixos.org/ https://nix-community.cachix.org
-            trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=
-            keep-outputs = true
-
-      - name: Calculate flake.lock hash
-        id: flake-lock-hash
+      - name: Check formatting
         run: |
-          echo "hash=$(md5sum flake.lock | awk '{print $1}')" >> $GITHUB_OUTPUT
-
-      - name: Restore and cache Nix store
-        uses: https://github.com/nix-community/cache-nix-action@v4.0.3
-        id: nix-store-cache
-        with:
-          key: cache-${{ runner.os }}-nix-store-${{ steps.flake-lock-hash.outputs.hash }}
-          restore-keys: |
-            cache-${{ runner.os }}-nix-store-
-
-          gc-linux: true
-          gc-max-store-size-linux: 10000000000
-
-          purge-caches: true
-          purge-key: cache-${{ runner.os }}-nix-store-
-          purge-created: true
-          purge-created-max-age: 42
-
-      - name: Prepare cachix
-        uses: https://github.com/cachix/cachix-action@v14
-        with:
-          name: pub-solar
-          authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
-          useDaemon: false
+          nix --accept-flake-config --access-tokens '' develop --command treefmt --ci
 
       - name: Run flake checks
         run: |
+          set -exuo pipefail
           # Prevent cache garbage collection by creating GC roots
-          for target in $(nix flake show --json --all-systems | jq '
-            .["nixosConfigurations"] |
-            to_entries[] |
-            .key
-            ' | tr -d '"'
-          ); do
-            nix --print-build-logs --verbose --accept-flake-config --access-tokens '' \
-              build --out-link ./result-$target ".#nixosConfigurations.${target}.config.system.build.toplevel"
-          done
+          mkdir -p /var/lib/gitea-runner/tankstelle/.local/state/nix/results
 
-          nix --print-build-logs --verbose --accept-flake-config --access-tokens '' flake check
-
-          # Add GC roots for flake inputs, too
-          # https://github.com/NixOS/nix/issues/4250#issuecomment-1146878407
-          mkdir --parents "$NIX_USER_PROFILE_DIR"
-          gc_root_prefix="$NIX_USER_PROFILE_DIR"/infra-flake-
-          echo "Adding gcroots flake inputs with prefix $gc_root_prefix ..."
-          nix flake archive --json 2>/dev/null | jq --raw-output '.inputs | to_entries[] | "ln --force --symbolic --no-target-directory "+.value.path+" \"'"$gc_root_prefix"'"+.key+"\""' | while read -r line; do
-            eval "$line"
-          done
+          sed -i 's/virtualisation.cores .*/virtualisation.cores = 16;/' tests/keycloak.nix
+          sed -i 's/virtualisation.memorySize .*/virtualisation.memorySize = 16384;/' tests/keycloak.nix
+          # 1 eval-worker needs about 13GB of memory
+          nix --accept-flake-config --access-tokens '' develop --command nix-fast-build --no-nom --skip-cached --systems "x86_64-linux" --max-jobs 10 --eval-workers 2 --out-link /var/lib/gitea-runner/tankstelle/.local/state/nix/results/nix-fast-build
diff --git a/.forgejo/workflows/update-flake-lock.yml b/.forgejo/workflows/update-flake-lock.yml
new file mode 100644
index 00000000..6c9bce21
--- /dev/null
+++ b/.forgejo/workflows/update-flake-lock.yml
@@ -0,0 +1,19 @@
+name: Update flake lock
+on: 
+  workflow_dispatch:
+  schedule: 
+    - cron: '33 3 * * 6' # “At 03:33 on Saturday.” 
+
+jobs:
+  update_lockfile:
+    runs-on: self-hosted
+    steps:
+      - name: nix flake update
+        uses: https://git.pub.solar/momo/forgejo-action-update-flake@825bba1d03c853ea9aeded656d230db82f9f1216
+        with:
+          forgejo_access_token: ${{ secrets.HAKKONAUT_ACCESS_TOKEN }}
+          gpg_private_key: ${{ secrets.GPG_SIGN_SUBKEY }}
+          gpg_fingerprint: F39BE7813956AB92C3821DFBC02540B6C5BD80EE
+          gpg_passphrase: ${{ secrets.GPG_PASSPHRASE }}
+          git_author: '"hakkonaut" <no-reply@pub.solar>'
+          closure-diff-nixos-configuration: nachtigall
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index a77e8331..e4e7c7b9 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -1,2 +1,4 @@
+# Apply treewide formatting with treefmt
+2ca0bd7c3e743e699edb6e9c09d48b7c9106a64d
 # Apply treewide formatting with nixpkgs-fmt
 815033c764660e1468b1564a02570bad0f84f77a
diff --git a/.gitignore b/.gitignore
index 58b21b78..27fd9e3b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@
 .terraform
 *.plan
 result
+results
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..3adfc158
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,35 @@
+# Contributing guide
+
+Things you'll need:
+
+- To create [Pull Requests](https://forgejo.org/docs/latest/user/pull-requests-and-git-flow/), you will need to register your [pub.solar ID](https://auth.pub.solar) first.
+- For small changes, e.g. to documentation, you can directly edit files in the browser.
+
+### Getting a development shell
+
+First, get a local copy of this repository:
+
+```
+git clone https://git.pub.solar/pub-solar/infra.git
+cd infra
+```
+
+then, install [the package manager nix](https://nixos.org/download).
+
+Finally, run:
+
+```
+nix develop
+```
+
+This will install a development shell (devshell) with all required tools.
+
+### Final checks before creating a Pull Request
+
+Before creating a pull request, it's recommended to check the formatting:
+
+```
+treefmt
+```
+
+If you are a terminal-lover, the [AGit alternative](https://forgejo.org/docs/latest/user/agit-support/) to the web based Pull Request workflow might be interesting.
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 00000000..74c892ae
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,660 @@
+### GNU AFFERO GENERAL PUBLIC LICENSE
+
+Version 3, 19 November 2007
+
+Copyright (C) 2007 Free Software Foundation, Inc.
+<https://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+### Preamble
+
+The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains
+free software for all its users.
+
+When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing
+under this license.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+### TERMS AND CONDITIONS
+
+#### 0. Definitions.
+
+"This License" refers to version 3 of the GNU Affero General Public
+License.
+
+"Copyright" also means copyright-like laws that apply to other kinds
+of works, such as semiconductor masks.
+
+"The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of
+an exact copy. The resulting work is called a "modified version" of
+the earlier work or a work "based on" the earlier work.
+
+A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user
+through a computer network, with no transfer of a copy, is not
+conveying.
+
+An interactive user interface displays "Appropriate Legal Notices" to
+the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+#### 1. Source Code.
+
+The "source code" for a work means the preferred form of the work for
+making modifications to it. "Object code" means any non-source form of
+a work.
+
+A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+The Corresponding Source need not include anything that users can
+regenerate automatically from other parts of the Corresponding Source.
+
+The Corresponding Source for a work in source code form is that same
+work.
+
+#### 2. Basic Permissions.
+
+All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+You may make, run and propagate covered works that you do not convey,
+without conditions so long as your license otherwise remains in force.
+You may convey covered works to others for the sole purpose of having
+them make modifications exclusively for you, or provide you with
+facilities for running those works, provided that you comply with the
+terms of this License in conveying all material for which you do not
+control copyright. Those thus making or running the covered works for
+you must do so exclusively on your behalf, under your direction and
+control, on terms that prohibit them from making any copies of your
+copyrighted material outside their relationship with you.
+
+Conveying under any other circumstances is permitted solely under the
+conditions stated below. Sublicensing is not allowed; section 10 makes
+it unnecessary.
+
+#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such
+circumvention is effected by exercising rights under this License with
+respect to the covered work, and you disclaim any intention to limit
+operation or modification of the work as a means of enforcing, against
+the work's users, your or third parties' legal rights to forbid
+circumvention of technological measures.
+
+#### 4. Conveying Verbatim Copies.
+
+You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+#### 5. Conveying Modified Source Versions.
+
+You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these
+conditions:
+
+- a) The work must carry prominent notices stating that you modified
+  it, and giving a relevant date.
+- b) The work must carry prominent notices stating that it is
+  released under this License and any conditions added under
+  section 7. This requirement modifies the requirement in section 4
+  to "keep intact all notices".
+- c) You must license the entire work, as a whole, under this
+  License to anyone who comes into possession of a copy. This
+  License will therefore apply, along with any applicable section 7
+  additional terms, to the whole of the work, and all its parts,
+  regardless of how they are packaged. This License gives no
+  permission to license the work in any other way, but it does not
+  invalidate such permission if you have separately received it.
+- d) If the work has interactive user interfaces, each must display
+  Appropriate Legal Notices; however, if the Program has interactive
+  interfaces that do not display Appropriate Legal Notices, your
+  work need not make them do so.
+
+A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+#### 6. Conveying Non-Source Forms.
+
+You may convey a covered work in object code form under the terms of
+sections 4 and 5, provided that you also convey the machine-readable
+Corresponding Source under the terms of this License, in one of these
+ways:
+
+- a) Convey the object code in, or embodied in, a physical product
+  (including a physical distribution medium), accompanied by the
+  Corresponding Source fixed on a durable physical medium
+  customarily used for software interchange.
+- b) Convey the object code in, or embodied in, a physical product
+  (including a physical distribution medium), accompanied by a
+  written offer, valid for at least three years and valid for as
+  long as you offer spare parts or customer support for that product
+  model, to give anyone who possesses the object code either (1) a
+  copy of the Corresponding Source for all the software in the
+  product that is covered by this License, on a durable physical
+  medium customarily used for software interchange, for a price no
+  more than your reasonable cost of physically performing this
+  conveying of source, or (2) access to copy the Corresponding
+  Source from a network server at no charge.
+- c) Convey individual copies of the object code with a copy of the
+  written offer to provide the Corresponding Source. This
+  alternative is allowed only occasionally and noncommercially, and
+  only if you received the object code with such an offer, in accord
+  with subsection 6b.
+- d) Convey the object code by offering access from a designated
+  place (gratis or for a charge), and offer equivalent access to the
+  Corresponding Source in the same way through the same place at no
+  further charge. You need not require recipients to copy the
+  Corresponding Source along with the object code. If the place to
+  copy the object code is a network server, the Corresponding Source
+  may be on a different server (operated by you or a third party)
+  that supports equivalent copying facilities, provided you maintain
+  clear directions next to the object code saying where to find the
+  Corresponding Source. Regardless of what server hosts the
+  Corresponding Source, you remain obligated to ensure that it is
+  available for as long as needed to satisfy these requirements.
+- e) Convey the object code using peer-to-peer transmission,
+  provided you inform other peers where the object code and
+  Corresponding Source of the work are being offered to the general
+  public at no charge under subsection 6d.
+
+A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal,
+family, or household purposes, or (2) anything designed or sold for
+incorporation into a dwelling. In determining whether a product is a
+consumer product, doubtful cases shall be resolved in favor of
+coverage. For a particular product received by a particular user,
+"normally used" refers to a typical or common use of that class of
+product, regardless of the status of the particular user or of the way
+in which the particular user actually uses, or expects or is expected
+to use, the product. A product is a consumer product regardless of
+whether the product has substantial commercial, industrial or
+non-consumer uses, unless such uses represent the only significant
+mode of use of the product.
+
+"Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to
+install and execute modified versions of a covered work in that User
+Product from a modified version of its Corresponding Source. The
+information must suffice to ensure that the continued functioning of
+the modified object code is in no case prevented or interfered with
+solely because modification has been made.
+
+If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or
+updates for a work that has been modified or installed by the
+recipient, or for the User Product in which it has been modified or
+installed. Access to a network may be denied when the modification
+itself materially and adversely affects the operation of the network
+or violates the rules and protocols for communication across the
+network.
+
+Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+#### 7. Additional Terms.
+
+"Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders
+of that material) supplement the terms of this License with terms:
+
+- a) Disclaiming warranty or limiting liability differently from the
+  terms of sections 15 and 16 of this License; or
+- b) Requiring preservation of specified reasonable legal notices or
+  author attributions in that material or in the Appropriate Legal
+  Notices displayed by works containing it; or
+- c) Prohibiting misrepresentation of the origin of that material,
+  or requiring that modified versions of such material be marked in
+  reasonable ways as different from the original version; or
+- d) Limiting the use for publicity purposes of names of licensors
+  or authors of the material; or
+- e) Declining to grant rights under trademark law for use of some
+  trade names, trademarks, or service marks; or
+- f) Requiring indemnification of licensors and authors of that
+  material by anyone who conveys the material (or modified versions
+  of it) with contractual assumptions of liability to the recipient,
+  for any liability that these contractual assumptions directly
+  impose on those licensors and authors.
+
+All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions; the
+above requirements apply either way.
+
+#### 8. Termination.
+
+You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+However, if you cease all violation of this License, then your license
+from a particular copyright holder is reinstated (a) provisionally,
+unless and until the copyright holder explicitly and finally
+terminates your license, and (b) permanently, if the copyright holder
+fails to notify you of the violation by some reasonable means prior to
+60 days after the cessation.
+
+Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+#### 9. Acceptance Not Required for Having Copies.
+
+You are not required to accept this License in order to receive or run
+a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+#### 10. Automatic Licensing of Downstream Recipients.
+
+Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+#### 11. Patents.
+
+A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+A contributor's "essential patent claims" are all patent claims owned
+or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+A patent license is "discriminatory" if it does not include within the
+scope of its coverage, prohibits the exercise of, or is conditioned on
+the non-exercise of one or more of the rights that are specifically
+granted under this License. You may not convey a covered work if you
+are a party to an arrangement with a third party that is in the
+business of distributing software, under which you make payment to the
+third party based on the extent of your activity of conveying the
+work, and under which the third party grants, to any of the parties
+who would receive the covered work from you, a discriminatory patent
+license (a) in connection with copies of the covered work conveyed by
+you (or copies made from those copies), or (b) primarily for and in
+connection with specific products or compilations that contain the
+covered work, unless you entered into that arrangement, or that patent
+license was granted, prior to 28 March 2007.
+
+Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+#### 12. No Surrender of Others' Freedom.
+
+If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under
+this License and any other pertinent obligations, then as a
+consequence you may not convey it at all. For example, if you agree to
+terms that obligate you to collect a royalty for further conveying
+from those to whom you convey the Program, the only way you could
+satisfy both those terms and this License would be to refrain entirely
+from conveying the Program.
+
+#### 13. Remote Network Interaction; Use with the GNU General Public License.
+
+Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your
+version supports such interaction) an opportunity to receive the
+Corresponding Source of your version by providing access to the
+Corresponding Source from a network server at no charge, through some
+standard or customary means of facilitating copying of software. This
+Corresponding Source shall include the Corresponding Source for any
+work covered by version 3 of the GNU General Public License that is
+incorporated pursuant to the following paragraph.
+
+Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+#### 14. Revised Versions of this License.
+
+The Free Software Foundation may publish revised and/or new versions
+of the GNU Affero General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever
+published by the Free Software Foundation.
+
+If the Program specifies that a proxy can decide which future versions
+of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+#### 15. Disclaimer of Warranty.
+
+THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
+WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
+DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+#### 16. Limitation of Liability.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
+CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
+NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
+LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
+TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
+PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+#### 17. Interpretation of Sections 15 and 16.
+
+If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+END OF TERMS AND CONDITIONS
+
+### How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively state
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+        <one line to give the program's name and a brief idea of what it does.>
+        Copyright (C) <year>  <name of author>
+
+        This program is free software: you can redistribute it and/or modify
+        it under the terms of the GNU Affero General Public License as
+        published by the Free Software Foundation, either version 3 of the
+        License, or (at your option) any later version.
+
+        This program is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+        GNU Affero General Public License for more details.
+
+        You should have received a copy of the GNU Affero General Public License
+        along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper
+mail.
+
+If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for
+the specific requirements.
+
+You should also get your employer (if you work as a programmer) or
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. For more information on this, and how to apply and follow
+the GNU AGPL, see <https://www.gnu.org/licenses/>.
diff --git a/README.md b/README.md
index 189bf3b6..147936d5 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,6 @@ The architecture we are working towards is a vast simplification of what it was
 
 ## Contributing
 
-If you'd like to contribute, it makes sense to talk to the crew on Matrix via [#hakken](https://matrix.to/#/#hakken:pub.solar?via=chat.pub.solar). We can help figuring out how things work and can make sure your ideas fit the pub.solar philosophy. Of course [popping a pull request](https://docs.gitea.com/next/usage/pull-request#creating-a-pull-request) is always celebrated.
+If you'd like to contribute, it makes sense to talk to the crew on Matrix via [#hakken](https://matrix.to/#/#hakken:pub.solar?via=chat.pub.solar). We can help figuring out how things work and can make sure your ideas fit the pub.solar philosophy. Of course [popping a pull request](https://forgejo.org/docs/latest/user/pull-requests-and-git-flow/) is always celebrated.
 
-To start, see [how to get a development shell](./docs/development-shell.md).
+To start, check our [contributing guide](./CONTRIBUTING.md).
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000..394e838d
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,7 @@
+# pub.solar documentation
+
+This directory holds a collection of notes and documentation for pub.solar admins.
+
+### Systems Overview
+
+To get a first overview of existing pub.solar systems, please see the [pub.solar systems overview](./systems-overview.md).
diff --git a/docs/administrative-access.md b/docs/administrative-access.md
index 6b7faa40..3267a6c1 100644
--- a/docs/administrative-access.md
+++ b/docs/administrative-access.md
@@ -14,7 +14,7 @@ People with admin access to the infrastructure are added to [`logins/admins.nix`
                 publicKey = <pubkey-string>;
                 allowedIPs = [ "10.7.6.<ip-address>/32" "fd00:fae:fae:fae:fae:<ip-address>::/96" ];
             }
-        }];
+        ];
 
         secretEncryptionKeys = {
             <name> = <encryption-key-string>;
@@ -28,7 +28,96 @@ People with admin access to the infrastructure are added to [`logins/admins.nix`
 SSH is not reachable from the open internet. Instead, SSH Port 22 is protected by a wireguard VPN network. Thus, to get root access on the servers, at least two pieces of information have to be added to the admins config:
 
 1. **SSH Public key**: self-explanatory. Add your public key to your user attrset under `sshPubKeys`.
-2. **Wireguard device**: each wireguard device has two parts: the public key and the IP addresses it should have in the wireguard network. The pub.solar wireguard network is spaced under `10.7.6.0/24` and `fd00:fae:fae:fae:fae::/80`. To add your device, it's best to choose a free number between 200 and 255 and use that in both the ipv4 and ipv6 ranges: `10.7.6.<ip-address>/32` `fd00:fae:fae:fae:fae:<ip-address>::/96`. For more information on how to generate keypairs, see [the NixOS Wireguard docs](https://nixos.wiki/wiki/WireGuard#Generate_keypair).
+2. **Wireguard device**: each wireguard device has two parts: the public key and the IP addresses it should have in the wireguard network. The pub.solar wireguard network uses the subnets `10.7.6.0/24` and `fd00:fae:fae:fae:fae::/80`. To add your device, it's best to choose a free number between 200 and 255 and use that in both the ipv4 and ipv6 ranges: `10.7.6.<ip-address>/32` `fd00:fae:fae:fae:fae:<ip-address>::/96`. For more information on how to generate keypairs, see [the NixOS Wireguard docs](https://nixos.wiki/wiki/WireGuard#Generate_keypair).
+
+One can access our hosts using this domain scheme:
+
+```
+ssh <unix-username>@<hostname>.wg.pub.solar
+```
+
+So, for example for `nachtigall`:
+
+```
+ssh teutat3s@nachtigall.wg.pub.solar
+```
+
+Example NixOS snippet for WireGuard client config
+
+```
+{
+  networking = {
+    wireguard.enable = true;
+    wg-quick.interfaces = {
+      wg-pub-solar = {
+        address = ["10.7.6.201/32"];
+        address = ["10.7.6.201/32" "fd00:fae:fae:fae:fae:201::/96"];
+        privateKeyFile = "/etc/wireguard/wg-pub-solar.privatekey";
+
+        peers = [
+          { # nachtigall.pub.solar
+            publicKey = "qzNywKY9RvqTnDO8eLik75/SHveaSk9OObilDzv+xkk=";
+            allowedIPs = [ "10.7.6.1/32" "fd00:fae:fae:fae:fae:1::/96" ];
+            endpoint = "[2a01:4f8:172:1c25::1]:51820";
+            # Use this endpoint in IPv4 only networks
+            #endpoint = "138.201.80.102:51820";
+            persistentKeepalive = 15;
+          }
+          { # metronom.pub.solar
+            publicKey = "zOSYGO7MfnOOUnzaTcWiKRQM0qqxR3JQrwx/gtEtHmo=";
+            allowedIPs = [ "10.7.6.3/32" "fd00:fae:fae:fae:fae:3::/96" ];
+            #endpoint = "[2a01:4f8:c2c:7082::]:51820";
+            # Use this endpoint in IPv4 only networks
+            endpoint = "49.13.236.167:51820";
+            persistentKeepalive = 15;
+          }
+          { # tankstelle.pub.solar
+            publicKey = "iRTlY1lB7nPXf2eXzX8ZZDkfMmXyGjff5/joccbP8Cg=";
+            allowedIPs = [ "10.7.6.4/32" "fd00:fae:fae:fae:fae:4::/96" ];
+            endpoint = "[2001:4d88:1ffa:26::5]:51820";
+            # Use this endpoint in IPv4 only networks
+            #endpoint = "80.244.242.5:51820";
+            persistentKeepalive = 15;
+          }
+          {
+            # trinkgenossin.pub.solar
+            publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4=";
+            allowedIPs = [
+              "10.7.6.5/32"
+              "fd00:fae:fae:fae:fae:5::/96"
+            ];
+            #endpoint = "85.215.152.22:51820";
+            endpoint = "[2a01:239:35d:f500::1]:51820";
+            persistentKeepalive = 15;
+          }
+          {
+            # delite.pub.solar
+            publicKey = "ZT2qGWgMPwHRUOZmTQHWCRX4m14YwOsiszjsA5bpc2k=";
+            allowedIPs = [
+              "10.7.6.6/32"
+              "fd00:fae:fae:fae:fae:6::/96"
+            ];
+            #endpoint = "5.255.119.132:51820";
+            endpoint = "[2a04:52c0:124:9d8c::2]:51820";
+            persistentKeepalive = 15;
+          }
+          {
+            # blue-shell.pub.solar
+            publicKey = "bcrIpWrKc1M+Hq4ds3aN1lTaKE26f2rvXhd+93QrzR8=";
+            allowedIPs = [
+              "10.7.6.7/32"
+              "fd00:fae:fae:fae:fae:7::/96"
+            ];
+            #endpoint = "194.13.83.205:51820";
+            endpoint = "[2a03:4000:43:24e::1]:51820";
+            persistentKeepalive = 15;
+          }
+        ];
+      };
+    };
+  };
+}
+```
 
 # Secret encryption
 
diff --git a/docs/backups.md b/docs/backups.md
new file mode 100644
index 00000000..ccce5f99
--- /dev/null
+++ b/docs/backups.md
@@ -0,0 +1,36 @@
+# Backups
+
+We use [Restic](https://restic.readthedocs.io/en/stable/) to create backups and push them to two repositories.
+Check `./modules/backups.nix` and `./hosts/nachtigall/backups.nix` for working examples.
+
+### Hetzner Storagebox
+
+- Uses SFTP for transfer of backups
+
+Adding a new host SSH public key to the storagebox:
+
+First, [SSH to nachtigall](./administrative-access.md#ssh-access), then become root and add the new SSH public key
+
+```
+sudo -i
+echo '<ssh-public-key>' | ssh -p23 u377325@u377325.your-storagebox.de install-ssh-key
+```
+
+[Link to Hetzner storagebox docs](https://docs.hetzner.com/robot/storage-box/backup-space-ssh-keys).
+
+### Garage S3 buckets
+
+- Uses S3 for transfer of backups
+- One bucket per host, e.g. `nachtigall-backups`, `metronom-backups`
+
+To start transfering backups from a new hosts, this is how to create a new bucket:
+
+First, [SSH to trinkgenossin](./administrative-access.md#ssh-access), then use the `garage` CLI to create a new key and bucket:
+
+```
+export GARAGE_RPC_SECRET=<secret-in-keepass>
+
+garage bucket create <hostname>-backups
+garage key create <hostname>-backups-key
+garage bucket allow <hostname>-backups --read --write --key <hostname>-backups-key
+```
diff --git a/docs/cachix.md b/docs/cachix.md
new file mode 100644
index 00000000..e89d82ae
--- /dev/null
+++ b/docs/cachix.md
@@ -0,0 +1,55 @@
+# Cachix usage
+
+URL: https://pub-solar.cachix.org
+
+Requirements:
+
+- [Install cachix](https://docs.cachix.org/installation)
+- Optional: To push to the cache, you need to set `CACHIX_AUTH_TOKEN` in your environment. To generate one for you, follow the [Getting Started](https://docs.cachix.org/getting-started#authenticating) docs and login with your GitHub account.
+- Add our binary cache [to your nix config](https://docs.cachix.org/faq#cachix-use-effects). To add the pub-solar cache, run:
+
+```
+cachix use pub-solar
+```
+
+Example to build and push a custom package of a host in this flake (e.g. after creating an overlay):
+
+```
+nix build --json -f . '.#nixosConfigurations.nachtigall.pkgs.keycloak^*' \
+  | jq -r '.[].outputs | to_entries[].value' \
+  | cachix push pub-solar
+```
+
+Example to build and push a package in the `nixpkgs` repo:
+
+```
+cd nixpkgs
+nix build --json -f . 'pkgs.lix^*' \
+  | jq -r '.[].outputs | to_entries[].value' \
+  | cachix push pub-solar
+```
+
+Checking if a package has been correctly pushed to the cache:
+
+```
+❯ nix build --json '/nix/store/f76xi83z4xk9sn6pbh38rh97yvqhb5m0-noto-fonts-color-emoji-png-2.042.drv^*' | jq -r '.[].outputs | to_entries[].value'  | cachix push pub-solar
+Pushing 1 paths (0 are already present) using zstd to cache pub-solar ⏳
+
+✓ /nix/store/xpgpi84765dxqja3gd5pldj49xx2v0xl-noto-fonts-color-emoji-png-2.042 (10.30 MiB)
+
+All done.
+
+❯ curl -I https://pub-solar.cachix.org/xpgpi84765dxqja3gd5pldj49xx2v0xl.narinfo
+HTTP/2 200
+date: Mon, 26 Aug 2024 09:31:10 GMT
+content-type: text/x-nix-narinfo
+traceparent: 00-b99db37cc9c2581b8d226cdf81e54507-794fc49193659c03-01
+tracestate:
+cache-control: public, max-age=14400
+last-modified: Mon, 26 Aug 2024 09:31:10 GMT
+cf-cache-status: EXPIRED
+report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=A67KGsCIsYjoFdvndxJ0rkmb7BZ5ztIpm8WUJKAiUPRVWvbYeXU9gU27P7zryiUtArbwrLzHhhMija0yyXk0kwNa3suz8gNzKK6z1CX1FWDZiiP07rnq7zAg8nZbSBiEU%2FZrU9nSrR6mhuL9ihbmW1Hf"}],"group":"cf-nel","max_age":604800}
+nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
+server: cloudflare
+cf-ray: 8b92ceab0d19c80e-DUS
+```
diff --git a/docs/deletion-request.md b/docs/deletion-request.md
index 9af80094..00538269 100644
--- a/docs/deletion-request.md
+++ b/docs/deletion-request.md
@@ -1,13 +1,16 @@
 # Process for handling a deletion request
 
 ### Keycloak
-Required:
-- auth.pub.solar ops user credentials
-- SSH access to host nachtigall
-```
-ssh barkeeper@nachtigall.pub.solar
 
-sudo --user keycloak kcadm.sh config credentials --config /tmp/kcadm.config --server http://localhost:8080 --realm pub.solar --user ops
+Required:
+
+- auth.pub.solar `admin-cli` service user credentials
+- [SSH access to host `nachtigall`](./administrative-access.md#ssh-access)
+
+Run each of the following after SSH'ing to `nachtigall`:
+
+```
+sudo --user keycloak kcadm.sh config credentials --config /tmp/kcadm.config --server http://localhost:8080 --realm pub.solar --client admin-cli
 
 # Take note of user id in response from following command
 sudo --user keycloak kcadm.sh get --config /tmp/kcadm.config users --realm pub.solar --query email=<email-address>
@@ -20,42 +23,78 @@ sudo --user keycloak kcadm.sh update --config /tmp/kcadm.config users/2ec6f173-3
 
 Docs: https://www.keycloak.org/docs/latest/server_admin/index.html#updating-a-user
 
-
 ### Nextcloud
+
 ```
-ssh barkeeper@nachtigall.pub.solar
 nextcloud-occ user:delete <username>
 ```
 
 Docs: https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/occ_command.html#user-commands-label
 
-
 ### Mastodon
+
 ```
-ssh barkeeper@nachtigall.pub.solar
+mkdir /tmp/tootctl
+sudo chown mastodon /tmp/tootctl
+cd /tmp/tootctl
+
 sudo -u mastodon mastodon-tootctl accounts delete --email <mail-address>
+
+rm -r /tmp/tootctl
 ```
 
 Docs: https://docs.joinmastodon.org/admin/tootctl/#accounts-delete
 
-
 ### Forgejo
+
+Make sure you have access to the gitea/forgejo command:
+
+```
+nix shell nixpkgs#forgejo
+```
+
+Then, delete the user:
+
 ```
-ssh barkeeper@nachtigall.pub.solar
 sudo -u gitea gitea admin user delete --config /var/lib/forgejo/custom/conf/app.ini --purge --email <mail-address>
 ```
 
 Docs: https://forgejo.org/docs/latest/admin/command-line/#delete
 
-
 ### Matrix
+
 ```
-ssh bartender@matrix.pub.solar -p 2020
-curl --header "Authorization: Bearer <admin-access-token>" --request POST http://172.18.0.3:8008/_synapse/admin/v1/deactivate/@<username>:pub.solar --data '{"erase": true}'
+curl --header "Authorization: Bearer <admin-access-token>" --request POST http://127.0.0.1:8008/_synapse/admin/v1/deactivate/@<username>:pub.solar --data '{"erase": true}'
 ```
 
-Docs: https://matrix-org.github.io/synapse/latest/admin_api/user_admin_api.html#deactivate-account
+Docs: https://element-hq.github.io/synapse/latest/admin_api/user_admin_api.html#deactivate-account
 
+The authentication token should be in the keepass. If it is expired, you can get a new one by running the following:
+
+```
+# get full path to mas-cli command with current --config flags from
+# sudo systemctl cat matrix-authentication-service
+sudo -u matrix-authentication-service mas-cli --config nix-store-config --config /run/agenix/matrix-authentication-service-secret-config.yml manage issue-compatibility-token --yes-i-want-to-grant-synapse-admin-privileges crew
+```
 
 ### OpenBikeSensor
+
 Not implemented, see: https://github.com/openbikesensor/portal/issues/95
+
+## Notifying the user
+
+Make sure to send an e-mail to the specified address notifying the user of the accounts deletion.
+
+You can use this template:
+
+```
+Hello,
+
+Your pub.solar ID has been deactivated. Associated data in pub.solar services has been deleted.
+
+Please note that the username is now blocked to prevent impersonation attempts.
+
+Best,
+
+@<name> for the pub.solar crew
+```
diff --git a/docs/deploying.md b/docs/deploying.md
index 4c9f7ff3..ffe5b388 100644
--- a/docs/deploying.md
+++ b/docs/deploying.md
@@ -7,14 +7,29 @@ be manually deployed.
 To deploy, make sure you have a [working development shell](./development-shell.md).
 Then, run `deploy-rs` with the hostname of the server you want to deploy:
 
+### Dry-run
+
+Use `--dry-activate` to show a diff of updated packages and all services that
+would be restarted by the update. This will also put all files in place without
+switching to the new generation, enabling a quick switch to the new config at a
+later moment.
+
 For nachtigall.pub.solar:
+
 ```
-deploy --targets '.#nachtigall' --magic-rollback false --auto-rollback false
+deploy --targets '.#nachtigall' --ssh-user <unix-username> --magic-rollback false --auto-rollback false --keep-result --result-path ./results --dry-activate
 ```
 
-For flora-6.pub.solar:
+After reviewing the changes, apply the update with:
+
 ```
-deploy --targets '.#flora-6' --magic-rollback false --auto-rollback false
+deploy --targets '.#nachtigall' --ssh-user <unix-username> --magic-rollback false --auto-rollback false --keep-result --result-path ./results
+```
+
+For metronom.pub.solar (aarch64-linux):
+
+```
+deploy --targets '.#metronom' --ssh-user <unix-username> --magic-rollback false --auto-rollback false --keep-result --result-path ./results --remote-build
 ```
 
 Usually we skip all rollback functionality, but if you want to deploy a change
@@ -23,10 +38,13 @@ that might lock you out, e.g. to SSH, it might make sense to set these to `true`
 To skip flake checks, e.g. because you already ran them manually before
 deployment, add the flag `--skip-checks` at the end of the command.
 
-`--dry-activate` can be used to only put all files in place without switching,
-to enable switching to the new config quickly at a later moment.
+We use `--keep-result --result-path ./results` to keep the last `result`
+symlink of each `deploy` from being garbage collected. That way, we keep builds
+cached in the Nix store. This is optional and both flags can be removed if disk
+space is a scarce resource on your machine.
 
 You'll need to have SSH Access to the boxes to be able to run `deploy`.
 
 ### Getting SSH access
+
 See [administrative-access.md](./administrative-access.md).
diff --git a/docs/development-shell.md b/docs/development-shell.md
deleted file mode 100644
index 2b7d6c66..00000000
--- a/docs/development-shell.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Getting a development shell
-
-Clone this repository:
-
-```
-git clone https://git.pub.solar/pub-solar/infra.git
-cd infra
-```
-
-then, install [the package manager nix](https://nixos.org/download).
-
-Finally, run:
-
-```
-nix develop
-```
-
-This will install a development shell (devshell) with all required tools.
diff --git a/docs/dns.md b/docs/dns.md
index 189ef536..36f0d7da 100644
--- a/docs/dns.md
+++ b/docs/dns.md
@@ -1,58 +1,61 @@
 # Changing DNS entries
 
 Our current DNS provider is [namecheap](https://www.namecheap.com/).
-We use [Terraform](https://www.terraform.io) to declaratively manage our pub.solar DNS records.
+We use [OpenTofu](https://opentofu.org) to declaratively manage our pub.solar DNS records.
 
 ### Initial setup
 
-Skip this step if you already have a `triton` profile setup.
-
-```
-triton profile create
-```
-
-Please follow https://docs.greenbaum.cloud/en/devops/triton-cli.html for the details.
-
 You will need to setup the following [namecheap API credentials](https://www.namecheap.com/support/api/intro),
 look for "namecheap API key" in the pub.solar Keepass database.
+
 ```
 NAMECHEAP_API_KEY
 NAMECHEAP_API_USER
 NAMECHEAP_USER_NAME
 ```
+
 You will probably also need to add your external IP to the [API allow list](https://ap.www.namecheap.com/settings/tools/apiaccess/whitelisted-ips).
+
 ```
 dig -4 ip @dns.toys
 ```
 
-Now, change into the terraform directory and initialize the terraform providers.
+Now, change into the terraform directory and initialize the terraform providers. To decrypt existing state,
+search for "terraform state passphrase" in the pub.solar Keepass database.
 
 ```
 cd terraform
-export TRITON_KEY_ID=$(cat ~/.config/triton/profiles.d/lev-1-pub_solar.json | jq --raw-output .keyId)
+export TF_VAR_state_passphrase=$(secret-tool lookup pub.solar terraform-state-passphrase-dns)
 
-terraform init
+alias tofu="terraform-backend-git --access-logs --tf tofu git terraform"
+tofu init
 ```
 
 Make your changes, e.g. in `dns.tf`.
+
 ```
 $EDITOR dns.tf
 ```
 
 Plan your changes using:
+
 ```
-terraform plan -out pub-solar-infra.plan
+tofu plan -out pub-solar-infra.plan
 ```
 
 After verification, apply your changes with:
+
 ```
-terraform apply "pub-solar-infra.plan"
+tofu apply "pub-solar-infra.plan"
 ```
 
 ### Useful links
 
-We use the Manta remote backend to save the terraform state for collaboration.
-- https://www.terraform.io/language/v1.2.x/settings/backends/manta
+We use terraform-backend-git remote backend with opentofu state encryption for collaboration.
+
+- https://github.com/plumber-cd/terraform-backend-git
+- https://opentofu.org/docs/language/state/encryption
 
 Namecheap Terraform provider docs:
+
 - https://registry.terraform.io/providers/namecheap/namecheap/latest/docs
diff --git a/docs/drone-ci.md b/docs/drone-ci.md
deleted file mode 100644
index 088a777f..00000000
--- a/docs/drone-ci.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Drone CI
-
-We currently use two CI systems, [drone CI](https://drone.io), reachable via
-https://ci.pub.solar and [Forgejo Actions](https://forgejo.org/docs/latest/user/actions/),
-which UI is integrated into https://git.pub.solar, for example
-https://git.pub.solar/pub-solar/infra/actions.
-
-### Signing the `.drone.yml` file
-
-Login to https://ci.pub.solar by clicking on the user icon in the bottom left.
-After logging in, you can view your personal API token by clicking on the same
-icon. If you're using the nix [development-shell](./development-shell.md), the
-`drone` command will already be installed.
-
-```
-export DRONE_TOKEN=<your-drone-api-token>
-
-drone --token $DRONE_TOKEN sign --save pub-solar/os
-```
diff --git a/docs/garage.md b/docs/garage.md
new file mode 100644
index 00000000..59b546f9
--- /dev/null
+++ b/docs/garage.md
@@ -0,0 +1,84 @@
+# Garage
+
+### How-To create a new bucket + keys
+
+Requirements:
+
+- `garage` RPC credentials, in the shared keepass, search for 'garage rpc secret'.
+- [Setup WireGuard](./administrative-access.md#ssh-access) for hosts: `trinkgenossin`, optionally: `delite`, `blue-shell`
+
+```
+ssh <unix-username>@trinkgenossin.wg.pub.solar
+```
+
+```
+# Add a few spaces to avoid leaking the secret to the shell history
+   export GARAGE_RPC_SECRET=<secret-in-keepass>
+```
+
+Now, you can run the following command to check the cluster status:
+
+```
+garage status
+```
+
+Command to list all existing buckets:
+
+```
+garage bucket list
+```
+
+Creating a new bucket and access keys:
+
+```
+garage bucket create <bucket-name>
+garage key create <bucket-name>-key
+garage bucket allow <bucket-name> --read --write --key <bucket-name>-key
+```
+
+Full example for `mastodon` bucket:
+
+```
+garage bucket create mastodon
+
+garage key create mastodon-key
+
+garage bucket allow mastodon --read --write --key mastodon-key
+```
+
+Then [setup your favourite S3 client](https://garagehq.deuxfleurs.fr/documentation/connect/cli/)
+or use the bucket with any [S3 compatible software](https://garagehq.deuxfleurs.fr/documentation/connect/).
+
+Further reading:
+
+- https://garagehq.deuxfleurs.fr/documentation/quick-start/
+- https://garagehq.deuxfleurs.fr/documentation/connect/
+- https://garagehq.deuxfleurs.fr/documentation/connect/apps/#mastodon
+
+### Notes on manual setup steps
+
+```
+ssh <unix-username>@trinkgenossin.wg.pub.solar
+
+# Add a few spaces to avoid leaking the secret to the shell history
+    export GARAGE_RPC_SECRET=<secret-in-keepass>
+
+# Uses the default config /etc/garage.toml
+garage node id
+
+garage node connect <node-id2>
+garage node connect <node-id3>
+
+garage status
+
+#Zones
+#DE-1 DE-2 NL-1
+
+garage layout assign fdaa -z DE-1 -c 800G -t trinkgenossin
+garage layout assign 8835 -z DE-2 -c 800G -t blue-shell
+garage layout assign 73da -z NL-1 -c 800G -t delite
+garage layout show
+garage layout apply --version 1
+```
+
+Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/real-world/#creating-a-cluster-layout
diff --git a/docs/keycloak/delete-unverified-accounts.md b/docs/keycloak/delete-unverified-accounts.md
new file mode 100644
index 00000000..9f237e3e
--- /dev/null
+++ b/docs/keycloak/delete-unverified-accounts.md
@@ -0,0 +1,85 @@
+# Delete accounts without verified email address
+
+### Keycloak
+
+Required:
+
+- auth.pub.solar admin-cli service user credentials
+- [SSH access to host `nachtigall`](../administrative-access.md#ssh-access)
+
+Run following after SSH'ing to `nachtigall`.
+
+Credentials for the following command are in keepass. Create a keycloak
+config/credentials file at `/tmp/kcadm.config`:
+
+```bash
+sudo --user keycloak kcadm.sh config credentials \
+  --config /tmp/kcadm.config \
+  --server https://auth.pub.solar \
+  --realm pub.solar \
+  --client admin-cli
+```
+
+Get list of accounts without a verified email address:
+
+```bash
+sudo --user keycloak kcadm.sh get \
+  --config /tmp/kcadm.config \
+  users \
+  --realm pub.solar \
+  --query emailVerified=false \
+  > /tmp/keycloak-unverified-accounts
+```
+
+Review list of accounts, especially check `createdTimestamp` if any accounts
+were created in the past 2 days. If so, delete those from the
+`/tmp/keycloak-unverified-accounts` file.
+
+```bash
+createdTimestamps=( $( nix run nixpkgs#jq -- -r '.[].createdTimestamp' < /tmp/keycloak-unverified-accounts ) )
+
+# timestamps are in nanoseconds since epoch, so we need to strip the last three digits
+for timestamp in ${createdTimestamps[@]}; do date --date="@${timestamp::-3}"; done
+
+vim /tmp/keycloak-unverified-accounts
+```
+
+Check how many accounts are going to be deleted:
+
+```bash
+jq -r '.[].id' < /tmp/keycloak-unverified-accounts | wc -l
+```
+
+```bash
+jq -r '.[].id' < /tmp/keycloak-unverified-accounts > /tmp/keycloak-unverified-account-ids
+```
+
+Final check before deletion (dry-run):
+
+```bash
+for id in $(cat /tmp/keycloak-unverified-account-ids)
+  do
+    echo sudo --user keycloak kcadm.sh delete \
+      --config /tmp/kcadm.config \
+      users/$id \
+      --realm pub.solar
+  done
+```
+
+THIS WILL DELETE ACCOUNTS:
+
+```bash
+for id in $(cat /tmp/keycloak-unverified-account-ids)
+  do
+    sudo --user keycloak kcadm.sh delete \
+      --config /tmp/kcadm.config \
+      users/$id \
+      --realm pub.solar
+  done
+```
+
+Delete the temp files:
+
+```bash
+sudo rm /tmp/kcadm.config /tmp/keycloak-unverified-accounts /tmp/keycloak-unverified-account-ids
+```
diff --git a/docs/keycloak/keycloak-email-list.md b/docs/keycloak/keycloak-email-list.md
index 5d91c0d5..6331f4d2 100644
--- a/docs/keycloak/keycloak-email-list.md
+++ b/docs/keycloak/keycloak-email-list.md
@@ -1,12 +1,15 @@
 # Process for getting a list of email addresses of all keycloak users
 
 ### Keycloak
-Required:
-- auth.pub.solar ops user credentials
-- SSH access to host nachtigall
-```
-ssh barkeeper@nachtigall.pub.solar
 
+Required:
+
+- auth.pub.solar admin-cli service user credentials
+- [SSH access to host `nachtigall`](../administrative-access.md#ssh-access)
+
+Run following after SSH'ing to `nachtigall`:
+
+```
 sudo --user keycloak kcadm.sh get users \
   -r pub.solar \
   --offset 0 \
diff --git a/docs/keycloak/keycloak-reset-user-password.md b/docs/keycloak/keycloak-reset-user-password.md
index 8f123b38..4fc00bee 100644
--- a/docs/keycloak/keycloak-reset-user-password.md
+++ b/docs/keycloak/keycloak-reset-user-password.md
@@ -1,15 +1,18 @@
 # Process for resetting keycloak user passwords
 
 ### Keycloak
-Required:
-- auth.pub.solar ops user credentials
-- SSH access to host nachtigall
-```
-ssh barkeeper@nachtigall.pub.solar
 
+Required:
+
+- auth.pub.solar admin-cli service user credentials
+- [SSH access to host `nachtigall`](../administrative-access.md#ssh-access)
+
+Run the following after SSH'ing to `nachtigall`:
+
+```
 mkdir /tmp/keycloak-credential-reset
 
-sudo --user keycloak kcadm.sh config credentials --config /tmp/kcadm.config --server http://localhost:8080 --realm pub.solar --user ops
+sudo --user keycloak kcadm.sh config credentials --config /tmp/kcadm.config --server http://localhost:8080 --realm pub.solar --client admin-cli
 
 sudo --user keycloak kcadm.sh get --config /tmp/kcadm.config users --realm pub.solar | jq --raw-output '.[] | .id' > /tmp/keycloak-credential-reset/all-uuids
 
diff --git a/docs/keycloak/keycloak-update-realm.md b/docs/keycloak/keycloak-update-realm.md
index a2cd2f8e..b924c2e1 100644
--- a/docs/keycloak/keycloak-update-realm.md
+++ b/docs/keycloak/keycloak-update-realm.md
@@ -1,12 +1,15 @@
 # Process for updating a keycloak realm via CLI
 
 ### Keycloak
-Required:
-- auth.pub.solar ops user credentials
-- SSH access to host nachtigall
-```
-ssh barkeeper@nachtigall.pub.solar
 
+Required:
+
+- auth.pub.solar admin-cli service user credentials
+- [SSH access to host `nachtigall`](../administrative-access.md#ssh-access)
+
+Run the following after SSH'ing to `nachtigall`:
+
+```
 sudo -u keycloak kcadm.sh config credentials --config /tmp/kcadm.config --server http://localhost:8080 --realm master --user admin
 
 sudo -u keycloak kcadm.sh get --config /tmp/kcadm.config realms/pub.solar
diff --git a/docs/mail.md b/docs/mail.md
new file mode 100644
index 00000000..7719ac6d
--- /dev/null
+++ b/docs/mail.md
@@ -0,0 +1,4 @@
+### Mail
+
+mail.pub.solar aka metronom.pub.solar hosts our internal mails.
+This is a small Hetzner cloud instance on https://console.hetzner.cloud.
diff --git a/docs/matrix-suspend-account.md b/docs/matrix-suspend-account.md
new file mode 100644
index 00000000..70329450
--- /dev/null
+++ b/docs/matrix-suspend-account.md
@@ -0,0 +1,31 @@
+# Matrix account suspension
+
+> Unlike [account locking](https://spec.matrix.org/v1.12/client-server-api/#account-locking),
+> [suspension](https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/3823-code-for-account-suspension.md)
+> allows the user to have a (largely) readonly view of their account.
+> Homeserver administrators and moderators may use this functionality to
+> temporarily deactivate an account, or place conditions on the account's
+> experience. Critically, like locking, account suspension is reversible, unlike
+> the deactivation mechanism currently available in Matrix - a destructive,
+> irreversible, action.
+
+Required:
+
+- `matrix-synapse admin token`
+- [SSH access to host `nachtigall`](./administrative-access.md#ssh-access)
+
+## Suspending an account
+
+```bash
+curl --header "Authorization: Bearer <admin-access-token>" --request PUT http://127.0.0.1:8008/_synapse/admin/v1/suspend/@<username>:pub.solar --data '{"suspend": true}'
+```
+
+## Unsuspending an account
+
+```bash
+curl --header "Authorization: Bearer <admin-access-token>" --request PUT http://127.0.0.1:8008/_synapse/admin/v1/suspend/@<username>:pub.solar --data '{"suspend": false}'
+```
+
+Links:
+
+- [synapse docs Suspend/Unsuspend Account](https://element-hq.github.io/synapse/latest/admin_api/user_admin_api.html#suspendunsuspend-account)
diff --git a/docs/mediawiki-updates.md b/docs/mediawiki-updates.md
index 4f49b6b6..4b4590c8 100644
--- a/docs/mediawiki-updates.md
+++ b/docs/mediawiki-updates.md
@@ -4,28 +4,27 @@ See the [mediawiki-oidc-docker repository](https://git.pub.solar/pub-solar/media
 for instructions on updating our customized mediawiki docker image.
 
 To deploy a new docker image to `nachtigall`, first bump the mediawiki version
-of the docker image tag in `hosts/nachtigall/apps/mediawiki.nix` (search for
+of the docker image tag in `modules/mediawiki/default.nix` (search for
 `image`).
 
 Next, push your changes to https://git.pub.solar and get them reviewed and
 approved.
 
 After approval, create a fresh backup of the database and deploy the changes to
-`nachtigall`:
+`nachtigall`. Run the following after [SSH'ing to `nachtigall`](./administrative-access.md#ssh-access):
 
 ```
-ssh barkeeper@nachtigall.pub.solar
 sudo -u postgres pg_dump --create -Fc mediawiki > mediawiki-db-$(date +%F).dump
 exit
 ```
 
 ```
-deploy --targets '.#nachtigall'
+deploy --targets '.#nachtigall' --magic-rollback false --auto-rollback false --keep-result --result-path ./results
 ```
 
-Then, finalize the update by running the database migration script:
+Then, finalize the update by running the database migration script (in a [SSH](./administrative-access.md#ssh-access) shell on `nachtigall`):
+
 ```
-ssh barkeeper@nachtigall.pub.solar
 docker exec -it mediawiki bash
 php maintenance/run.php update.php
 ```
diff --git a/docs/nachtigall/notes-disk-extension.md b/docs/nachtigall/notes-disk-extension.md
new file mode 100644
index 00000000..8918a181
--- /dev/null
+++ b/docs/nachtigall/notes-disk-extension.md
@@ -0,0 +1,348 @@
+# Notes on adding two disks to server nachtigall
+
+Status after Hetzner support added two additional 1TB NVMe disks:
+
+```
+teutat3s in 🌐 nachtigall in ~
+❯ lsblk -f
+NAME        FSTYPE     FSVER LABEL     UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
+nvme0n1
+├─nvme0n1p1
+├─nvme0n1p2 vfat       FAT16           5494-BA1E                               385M    21% /boot2
+└─nvme0n1p3 zfs_member 5000  root_pool 8287701206764130981
+nvme1n1
+├─nvme1n1p1
+├─nvme1n1p2 vfat       FAT32           5493-EFF5                               1.8G     5% /boot1
+└─nvme1n1p3 zfs_member 5000  root_pool 8287701206764130981
+nvme2n1
+nvme3n1
+
+teutat3s in 🌐 nachtigall in ~
+❯ sudo fdisk -l /dev/nvme0n1
+Disk /dev/nvme0n1: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
+Disk model: KXG60ZNV1T02 TOSHIBA
+Units: sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+Disklabel type: gpt
+Disk identifier: 28F8681A-4559-4801-BF3F-BFEC8058236B
+
+Device          Start        End    Sectors   Size Type
+/dev/nvme0n1p1   2048       4095       2048     1M BIOS boot
+/dev/nvme0n1p2   4096     999423     995328   486M EFI System
+/dev/nvme0n1p3 999424 2000408575 1999409152 953.4G Linux filesystem
+
+teutat3s in 🌐 nachtigall in ~
+❯ sudo fdisk -l /dev/nvme1n1
+Disk /dev/nvme1n1: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
+Disk model: SAMSUNG MZVL21T0HCLR-00B00
+Units: sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+Disklabel type: gpt
+Disk identifier: A143A806-69C5-4EFC-8E34-20C35574D990
+
+Device           Start        End    Sectors  Size Type
+/dev/nvme1n1p1    2048       4095       2048    1M BIOS boot
+/dev/nvme1n1p2    4096    3905535    3901440  1.9G EFI System
+/dev/nvme1n1p3 3905536 2000408575 1996503040  952G Linux filesystem
+
+teutat3s in 🌐 nachtigall in ~
+❯ sudo fdisk -l /dev/nvme2n1
+Disk /dev/nvme2n1: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
+Disk model: SAMSUNG MZVL21T0HDLU-00B07
+Units: sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+
+teutat3s in 🌐 nachtigall in ~
+❯ sudo fdisk -l /dev/nvme3n1
+Disk /dev/nvme3n1: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
+Disk model: SAMSUNG MZVL21T0HCLR-00B00
+Units: sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+```
+
+Partitioning and formatting the new disks `/dev/nvme2n1` and `/dev/nvme3n1`:
+
+```
+teutat3s in 🌐 nachtigall in ~
+❯ sudo fdisk /dev/nvme2n1
+
+Welcome to fdisk (util-linux 2.39.4).
+Changes will remain in memory only, until you decide to write them.
+Be careful before using the write command.
+
+Device does not contain a recognized partition table.
+Created a new DOS (MBR) disklabel with disk identifier 0x0852470c.
+
+Command (m for help): p
+Disk /dev/nvme2n1: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
+Disk model: SAMSUNG MZVL21T0HDLU-00B07
+Units: sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+Disklabel type: dos
+Disk identifier: 0x0852470c
+
+Command (m for help): m
+
+Help:
+
+  DOS (MBR)
+   a   toggle a bootable flag
+   b   edit nested BSD disklabel
+   c   toggle the dos compatibility flag
+
+  Generic
+   d   delete a partition
+   F   list free unpartitioned space
+   l   list known partition types
+   n   add a new partition
+   p   print the partition table
+   t   change a partition type
+   v   verify the partition table
+   i   print information about a partition
+
+  Misc
+   m   print this menu
+   u   change display/entry units
+   x   extra functionality (experts only)
+
+  Script
+   I   load disk layout from sfdisk script file
+   O   dump disk layout to sfdisk script file
+
+  Save & Exit
+   w   write table to disk and exit
+   q   quit without saving changes
+
+  Create a new label
+   g   create a new empty GPT partition table
+   G   create a new empty SGI (IRIX) partition table
+   o   create a new empty MBR (DOS) partition table
+   s   create a new empty Sun partition table
+
+
+Command (m for help): g
+Created a new GPT disklabel (GUID: 8CC98E3F-20A8-4A2D-8D50-9CD769EE4C65).
+
+Command (m for help): p
+Disk /dev/nvme2n1: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
+Disk model: SAMSUNG MZVL21T0HDLU-00B07
+Units: sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+Disklabel type: gpt
+Disk identifier: 8CC98E3F-20A8-4A2D-8D50-9CD769EE4C65
+
+Command (m for help): n
+Partition number (1-128, default 1):
+First sector (2048-2000409230, default 2048):
+Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-2000409230, default 2000408575): 4095
+
+Created a new partition 1 of type 'Linux filesystem' and of size 1 MiB.
+
+Command (m for help): t
+Selected partition 1
+Partition type or alias (type L to list all): L
+  1 EFI System                     C12A7328-F81F-11D2-BA4B-00A0C93EC93B
+  2 MBR partition scheme           024DEE41-33E7-11D3-9D69-0008C781F39F
+  3 Intel Fast Flash               D3BFE2DE-3DAF-11DF-BA40-E3A556D89593
+  4 BIOS boot                      21686148-6449-6E6F-744E-656564454649
+  5 Sony boot partition            F4019732-066E-4E12-8273-346C5641494F
+  6 Lenovo boot partition          BFBFAFE7-A34F-448A-9A5B-6213EB736C22
+  7 PowerPC PReP boot              9E1A2D38-C612-4316-AA26-8B49521E5A8B
+  8 ONIE boot                      7412F7D5-A156-4B13-81DC-867174929325
+  9 ONIE config                    D4E6E2CD-4469-46F3-B5CB-1BFF57AFC149
+ 10 Microsoft reserved             E3C9E316-0B5C-4DB8-817D-F92DF00215AE
+ 11 Microsoft basic data           EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
+ 12 Microsoft LDM metadata         5808C8AA-7E8F-42E0-85D2-E1E90434CFB3
+ 13 Microsoft LDM data             AF9B60A0-1431-4F62-BC68-3311714A69AD
+ 14 Windows recovery environment   DE94BBA4-06D1-4D40-A16A-BFD50179D6AC
+ 15 IBM General Parallel Fs        37AFFC90-EF7D-4E96-91C3-2D7AE055B174
+ 16 Microsoft Storage Spaces       E75CAF8F-F680-4CEE-AFA3-B001E56EFC2D
+ 17 HP-UX data                     75894C1E-3AEB-11D3-B7C1-7B03A0000000
+ 18 HP-UX service                  E2A1E728-32E3-11D6-A682-7B03A0000000
+ 19 Linux swap                     0657FD6D-A4AB-43C4-84E5-0933C84B4F4F
+ 20 Linux filesystem               0FC63DAF-8483-4772-8E79-3D69D8477DE4
+...
+Partition type or alias (type L to list all): 4
+Changed type of partition 'Linux filesystem' to 'BIOS boot'.
+
+Command (m for help): n
+Partition number (2-128, default 2):
+First sector (4096-2000409230, default 4096):
+Last sector, +/-sectors or +/-size{K,M,G,T,P} (4096-2000409230, default 2000408575): 3901440
+
+Created a new partition 2 of type 'Linux filesystem' and of size 1.9 GiB.
+
+Command (m for help): t
+Partition number (1,2, default 2): 2
+Partition type or alias (type L to list all): 1
+
+Changed type of partition 'Linux filesystem' to 'EFI System'.
+
+Command (m for help): n
+Partition number (3-128, default 3):
+First sector (3901441-2000409230, default 3903488):
+Last sector, +/-sectors or +/-size{K,M,G,T,P} (3903488-2000409230, default 2000408575):
+
+Created a new partition 3 of type 'Linux filesystem' and of size 952 GiB.
+
+Command (m for help): p
+Disk /dev/nvme2n1: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
+Disk model: SAMSUNG MZVL21T0HDLU-00B07
+Units: sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+Disklabel type: gpt
+Disk identifier: 8CC98E3F-20A8-4A2D-8D50-9CD769EE4C65
+
+Device           Start        End    Sectors  Size Type
+/dev/nvme2n1p1    2048       4095       2048    1M BIOS boot
+/dev/nvme2n1p2    4096    3901440    3897345  1.9G EFI System
+/dev/nvme2n1p3 3903488 2000408575 1996505088  952G Linux filesystem
+
+Command (m for help): w
+The partition table has been altered.
+Calling ioctl() to re-read partition table.
+Syncing disks.
+
+
+teutat3s in 🌐 nachtigall in ~ took 5m41s
+❯ sudo fdisk /dev/nvme3n1
+
+Welcome to fdisk (util-linux 2.39.4).
+Changes will remain in memory only, until you decide to write them.
+Be careful before using the write command.
+
+Device does not contain a recognized partition table.
+Created a new DOS (MBR) disklabel with disk identifier 0xa77eb504.
+
+Command (m for help): g
+Created a new GPT disklabel (GUID: 56B64CEE-5E0C-4EAA-AE2F-5BF4356183A5).
+
+Command (m for help): n
+Partition number (1-128, default 1):
+First sector (2048-2000409230, default 2048):
+Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-2000409230, default 2000408575): 4095
+
+Created a new partition 1 of type 'Linux filesystem' and of size 1 MiB.
+
+Command (m for help): t
+Selected partition 1
+Partition type or alias (type L to list all): 4
+Changed type of partition 'Linux filesystem' to 'BIOS boot'.
+
+Command (m for help): n
+Partition number (2-128, default 2):
+First sector (4096-2000409230, default 4096):
+Last sector, +/-sectors or +/-size{K,M,G,T,P} (4096-2000409230, default 2000408575): 3901440
+
+Created a new partition 2 of type 'Linux filesystem' and of size 1.9 GiB.
+
+Command (m for help): t
+Partition number (1,2, default 2): 2
+Partition type or alias (type L to list all): 1
+
+Changed type of partition 'Linux filesystem' to 'EFI System'.
+
+Command (m for help): n
+Partition number (3-128, default 3):
+First sector (3901441-2000409230, default 3903488):
+Last sector, +/-sectors or +/-size{K,M,G,T,P} (3903488-2000409230, default 2000408575):
+
+Created a new partition 3 of type 'Linux filesystem' and of size 952 GiB.
+
+Command (m for help): p
+Disk /dev/nvme3n1: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
+Disk model: SAMSUNG MZVL21T0HCLR-00B00
+Units: sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+Disklabel type: gpt
+Disk identifier: 56B64CEE-5E0C-4EAA-AE2F-5BF4356183A5
+
+Device           Start        End    Sectors  Size Type
+/dev/nvme3n1p1    2048       4095       2048    1M BIOS boot
+/dev/nvme3n1p2    4096    3901440    3897345  1.9G EFI System
+/dev/nvme3n1p3 3903488 2000408575 1996505088  952G Linux filesystem
+
+Command (m for help): w
+The partition table has been altered.
+Calling ioctl() to re-read partition table.
+Syncing disks.
+
+teutat3s in 🌐 nachtigall in ~
+❯ sudo mkfs.vfat /dev/nvme2n1p2
+mkfs.fat 4.2 (2021-01-31)
+
+teutat3s in 🌐 nachtigall in ~
+❯ sudo mkfs.vfat /dev/nvme3n1p2
+mkfs.fat 4.2 (2021-01-31)
+
+teutat3s in 🌐 nachtigall in ~
+❯ lsblk -f
+NAME        FSTYPE     FSVER LABEL     UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
+nvme0n1
+├─nvme0n1p1
+├─nvme0n1p2 vfat       FAT16           5494-BA1E                               385M    21% /boot2
+└─nvme0n1p3 zfs_member 5000  root_pool 8287701206764130981
+nvme1n1
+├─nvme1n1p1
+├─nvme1n1p2 vfat       FAT32           5493-EFF5                               1.8G     5% /boot1
+└─nvme1n1p3 zfs_member 5000  root_pool 8287701206764130981
+nvme2n1
+├─nvme2n1p1
+├─nvme2n1p2 vfat       FAT32           E4E4-88C7
+└─nvme2n1p3
+nvme3n1
+├─nvme3n1p1
+├─nvme3n1p2 vfat       FAT32           E76C-A8A0
+└─nvme3n1p3
+```
+
+Finally, adding the new drives to the ZFS zpool `root_pool` to extend available disk space:
+
+```
+teutat3s in 🌐 nachtigall in ~
+❯ sudo zpool status
+  pool: root_pool
+ state: ONLINE
+  scan: scrub repaired 0B in 00:17:47 with 0 errors on Sat Mar  1 03:35:20 2025
+config:
+
+	NAME                                                      STATE     READ WRITE CKSUM
+	root_pool                                                 ONLINE       0     0     0
+	  mirror-0                                                ONLINE       0     0     0
+	    nvme-SAMSUNG_MZVL21T0HCLR-00B00_S676NF0R517371-part3  ONLINE       0     0     0
+	    nvme-KXG60ZNV1T02_TOSHIBA_Z9NF704ZF9ZL-part3          ONLINE       0     0     0
+
+errors: No known data errors
+
+teutat3s in 🌐 nachtigall in ~
+❯ sudo zpool add root_pool mirror nvme-SAMSUNG_MZVL21T0HDLU-00B07_S77WNF0XA01902-part3 nvme-SAMSUNG_MZVL21T0HCLR-00B00_S676NU0W623944-part3
+
+teutat3s in 🌐 nachtigall in ~
+❯ sudo zpool status
+  pool: root_pool
+ state: ONLINE
+  scan: scrub repaired 0B in 00:17:47 with 0 errors on Sat Mar  1 03:35:20 2025
+config:
+
+	NAME                                                      STATE     READ WRITE CKSUM
+	root_pool                                                 ONLINE       0     0     0
+	  mirror-0                                                ONLINE       0     0     0
+	    nvme-SAMSUNG_MZVL21T0HCLR-00B00_S676NF0R517371-part3  ONLINE       0     0     0
+	    nvme-KXG60ZNV1T02_TOSHIBA_Z9NF704ZF9ZL-part3          ONLINE       0     0     0
+	  mirror-1                                                ONLINE       0     0     0
+	    nvme-SAMSUNG_MZVL21T0HDLU-00B07_S77WNF0XA01902-part3  ONLINE       0     0     0
+	    nvme-SAMSUNG_MZVL21T0HCLR-00B00_S676NU0W623944-part3  ONLINE       0     0     0
+
+teutat3s in 🌐 nachtigall in ~
+❯ sudo zfs list root_pool
+NAME        USED  AVAIL  REFER  MOUNTPOINT
+root_pool   782G  1.04T   192K  none
+```
diff --git a/docs/nextcloud.md b/docs/nextcloud.md
new file mode 100644
index 00000000..9c5fa5ea
--- /dev/null
+++ b/docs/nextcloud.md
@@ -0,0 +1,19 @@
+# Nextcloud debugging
+
+Set loglevel to `0` for debug logs:
+
+```nix
+services.nextcloud.settings.loglevel = 0;
+```
+
+Then, logs appear in the `phpfpm-nextcloud.service` and `nextcloud-*.service` logs:
+
+```bash
+sudo journalctl --follow --unit phpfpm-nextcloud --unit nextcloud-*.service
+```
+
+Make sure to set the loglevel back to the default `2` warning after debugging:
+
+```nix
+services.nextcloud.settings.loglevel = 2;
+```
diff --git a/docs/nix-flake-updates.md b/docs/nix-flake-updates.md
index eef1613a..0c6f02f5 100644
--- a/docs/nix-flake-updates.md
+++ b/docs/nix-flake-updates.md
@@ -41,3 +41,7 @@ wrapped-ruby-mastodon-gems: 4.2.1 → 4.2.3
 zfs-kernel: 2.2.1-6.1.64 → 2.2.2-6.1.66
 zfs-user: 2.2.1 → 2.2.2
 ```
+
+### Deploying updates
+
+See [deploying.md](./deploying.md).
diff --git a/docs/nixos-anywhere.md b/docs/nixos-anywhere.md
new file mode 100644
index 00000000..d7becc12
--- /dev/null
+++ b/docs/nixos-anywhere.md
@@ -0,0 +1,29 @@
+# Deploying with nixos-anywhere
+
+## On Target: Enter NixOS from non-NixOS host
+
+In case you cannot boot easily into a nixos-installer image you can download the kexec installer image of NixOS and kexec into it:
+
+```
+curl -L https://github.com/nix-community/nixos-images/releases/download/nixos-unstable/nixos-kexec-installer-noninteractive-x86_64-linux.tar.gz | tar -xzf- -C /root
+/root/kexec/run
+```
+
+## Run Disko
+
+```
+nix run github:nix-community/nixos-anywhere -- --flake .#<hostname> --target-host root@<host> --phases disko
+```
+
+## On Target: Create inital ssh host key used in initrd
+
+```
+mkdir -p /mnt/etc/secrets/initrd
+ssh-keygen -t ed25519 -f /mnt/etc/secrets/initrd/ssh_host_ed25519_key
+```
+
+## Run NixOS Anywhere
+
+```
+nix run github:nix-community/nixos-anywhere -- --flake .#<hostname> --target-host root@<host> --phases install,reboot
+```
diff --git a/docs/obs-portal.md b/docs/obs-portal.md
new file mode 100644
index 00000000..b9d895a6
--- /dev/null
+++ b/docs/obs-portal.md
@@ -0,0 +1,32 @@
+# OpenBikeSensor Portal
+
+## Docker Containers
+
+- portal
+- worker
+- db
+
+## Run database migrations
+
+After an upgrade it is sometimes necessary to run database migrations or regenerate tiles.
+
+```
+docker exec -ti obs-portal tools/upgrade.py
+```
+
+## Dump database
+
+Save database dump to `dump.sql` in the current working directory.
+
+```
+docker exec -ti --user postgres obs-portal-db pg_dump obs > dump.sql
+```
+
+## Restore database
+
+Load database dump from `dump.sql` file.
+`obs` database needs to exist before importing the dump.
+
+```
+cat dump.sql | docker exec -ti --user postgres obs-portal-db psql obs
+```
diff --git a/docs/reverting-version.md b/docs/reverting-version.md
index 83c4ebe2..3ae112f7 100644
--- a/docs/reverting-version.md
+++ b/docs/reverting-version.md
@@ -1,3 +1 @@
 # Reverting to an old version
-
-
diff --git a/docs/systems-overview.md b/docs/systems-overview.md
new file mode 100644
index 00000000..dd5bc706
--- /dev/null
+++ b/docs/systems-overview.md
@@ -0,0 +1,187 @@
+# pub.solar Systems Overview
+
+Last updated: 2025-03-11
+
+Jump to:
+
+1. [Server nachtigall.pub.solar](#server-nachtigall-pub-solar)
+2. [Server metronom.pub.solar](#server-metronom-pub-solar)
+3. [Server trinkgenossin.pub.solar](#server-trinkgenossin-pub-solar)
+4. [Server blue-shell.pub.solar](#server-blue-shell-pub-solar)
+5. [Server delite.pub.solar](#server-delite-pub-solar)
+6. [Server tankstelle.pub.solar](#server-tankstelle-pub-solar)
+7. [Server underground.pub.solar](#server-underground-pub-solar)
+8. [Hetzner 1TB storagebox](#hetzner-1tb-storagebox)
+
+### Server nachtigall.pub.solar
+
+**Specs:**
+
+- AMD Ryzen 7 3700X 8-Core Processor
+- 64 GB RAM
+- 4x 1TB NVMe disks
+
+**Disk layout:**
+
+- Encrypted ZFS mirror vdevs
+
+**Operating System:**
+
+- NixOS 24.11 `x86_64-linux`
+
+**Usage:**
+Main pub.solar server. Hosts the majority of pub.solar services. Non-exhaustive list:
+
+- collabora
+- coturn
+- forgejo
+- keycloak
+- mailman
+- mastodon
+- matrix-synapse (homeserver)
+- mediawiki
+- nextcloud
+- owncast
+- searx
+- tmate
+- tt-rss
+- obs-portal
+
+### Server metronom.pub.solar
+
+**Specs:**
+
+- Hetzner VPS type: CAX11
+- 2 vCPU
+- 4 GB RAM
+- 40GB disk
+
+**Disk layout:**
+
+- Encrypted ZFS single disk (stripe)
+
+**Operating System:**
+
+- NixOS 24.11 `aarch64-linux`
+
+**Usage:**
+pub.solar mail server. Note this is an ARM server.
+
+### Server trinkgenossin.pub.solar
+
+**Specs:**
+
+- Strato VPS type: VPS Linux VC8-32
+- 8 core AMD EPYC-Milan Processor
+- 32 GB RAM
+- 1TB NVMe disk
+
+**Disk layout:**
+
+- Encrypted LUKS single disk
+
+**Operating System:**
+
+- NixOS 24.11 `x86_64-linux`
+
+**Usage:**
+Monitor, garage cluster node. Services:
+
+- grafana
+- loki
+- prometheus
+- garage
+- forgejo-actions-runner (docker)
+
+### Server blue-shell.pub.solar
+
+**Specs:**
+
+- netcup VPS type: VPS 1000 G11
+- 4 core AMD EPYC-Rome Processor
+- 8 GB RAM
+- 256 GB SSD disk
+- 850GB mechanical disk
+
+**Disk layout:**
+
+- Encrypted LVM on LUKS single disk and encrypted LUKS garage data disk
+
+**Operating System:**
+
+- NixOS 24.11 `x86_64-linux`
+
+**Usage:**
+Garage cluster node.
+
+### Server delite.pub.solar
+
+**Specs:**
+
+- liteserver VPS type: HDD Storage VPS - HDD-2G
+- 1 core AMD EPYC 7452
+- 2 GB RAM
+- 1TB mechanical disk
+
+**Disk layout:**
+
+- Encrypted LVM on LUKS single disk
+
+**Operating System:**
+
+- NixOS 24.11 `x86_64-linux`
+
+**Usage:**
+Garage cluster node.
+
+### Server tankstelle.pub.solar
+
+**Specs:**
+
+- 24 core Intel Xeon E5-2670 v2 @ 2.50GHz
+- 40 GB RAM
+- 80GB SSD disk
+
+**Disk layout:**
+
+- LVM
+
+**Operating System:**
+
+- NixOS 24.11 `x86_64-linux`
+
+**Usage:**
+
+- forgejo-actions-runner (selfhosted, NixOS)
+
+### Server underground.pub.solar
+
+**Specs:**
+
+- 8 core Intel Xeon E5-2670 v2 @ 2.50GHz
+- 16 GB RAM
+- 40 GB SSD disk
+
+**Disk layout:**
+
+- LVM on LUKS, single disk
+
+**Operating System:**
+
+- NixOS 24.11 `x86_64-linux`
+
+**Usage:**
+Testing server.
+
+### Hetzner 1TB storagebox
+
+Hostname:
+
+```
+u377325@u377325.your-storagebox.de
+```
+
+**Usage:**
+Backups get pushed to a Hetzner storagebox every night.
+
+### Garage cluster
diff --git a/docs/unlocking-root.md b/docs/unlocking-root.md
deleted file mode 100644
index 2ec0d9a6..00000000
--- a/docs/unlocking-root.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Unlocking the root partition on boot
-
-After a boot, the encrypted root partition will have to be unlocked. This is done by accessing the server via SSH with user root on port 2222.
-
-```
-ssh root@nachtigall.pub.solar -p2222
-```
-
- After connecting, paste the crypt passphrase you can find in the shared keepass. This will disconnect the SSH session right away and the server will keep booting into stage 2.
diff --git a/docs/unlocking-zfs-pool.md b/docs/unlocking-zfs-pool.md
new file mode 100644
index 00000000..5b5d4ea2
--- /dev/null
+++ b/docs/unlocking-zfs-pool.md
@@ -0,0 +1,20 @@
+# Unlocking the ZFS pool on boot
+
+After a reboot, the encrypted ZFS pool will have to be unlocked. This is done by
+accessing the server via SSH as user `root` on port 2222.
+
+Nachtigall:
+
+```
+ssh -4 root@nachtigall.pub.solar -p2222
+```
+
+Metronom:
+
+```
+ssh -4 root@metronom.pub.solar -p2222
+```
+
+After connecting, paste the encryption passphrase you can find in the shared
+keepass. This will disconnect the SSH session immediately and the server will
+continue to boot into stage 2.
diff --git a/docs/zfs-quickstart.md b/docs/zfs-quickstart.md
new file mode 100644
index 00000000..dc007503
--- /dev/null
+++ b/docs/zfs-quickstart.md
@@ -0,0 +1,19 @@
+# ZFS Quick Start
+
+View current status of the ZFS pool (zpool):
+
+```
+sudo zpool status
+```
+
+View available disk space of the pool, replace `<pool-name>` with the pool name from the output above:
+
+```
+sudo zfs list <pool-name>
+```
+
+List all snapshots:
+
+```
+sudo zfs list -t snapshot
+```
diff --git a/flake.lock b/flake.lock
index 7b48c908..0b6250e4 100644
--- a/flake.lock
+++ b/flake.lock
@@ -14,11 +14,11 @@
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1712079060,
-        "narHash": "sha256-/JdiT9t+zzjChc5qQiF+jhrVhRt8figYH29rZO7pFe4=",
+        "lastModified": 1736955230,
+        "narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=",
         "owner": "ryantm",
         "repo": "agenix",
-        "rev": "1381a759b205dff7a6818733118d02253340fd5e",
+        "rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c",
         "type": "github"
       },
       "original": {
@@ -27,6 +27,22 @@
         "type": "github"
       }
     },
+    "blobs": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1604995301,
+        "narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=",
+        "owner": "simple-nixos-mailserver",
+        "repo": "blobs",
+        "rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265",
+        "type": "gitlab"
+      },
+      "original": {
+        "owner": "simple-nixos-mailserver",
+        "repo": "blobs",
+        "type": "gitlab"
+      }
+    },
     "deploy-rs": {
       "inputs": {
         "flake-compat": "flake-compat",
@@ -36,11 +52,11 @@
         "utils": "utils"
       },
       "locked": {
-        "lastModified": 1711973905,
-        "narHash": "sha256-UFKME/N1pbUtn+2Aqnk+agUt8CekbpuqwzljivfIme8=",
+        "lastModified": 1727447169,
+        "narHash": "sha256-3KyjMPUKHkiWhwR91J1YchF6zb6gvckCAY1jOE+ne0U=",
         "owner": "serokell",
         "repo": "deploy-rs",
-        "rev": "88b3059b020da69cbe16526b8d639bd5e0b51c8b",
+        "rev": "aa07eb05537d4cd025e2310397a6adcedfe72c76",
         "type": "github"
       },
       "original": {
@@ -71,14 +87,58 @@
         "type": "github"
       }
     },
+    "disko": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1745502102,
+        "narHash": "sha256-LqhRwzvIVPEjH0TaPgwzqpyhW6DtCrvz7FnUJDoUZh8=",
+        "owner": "nix-community",
+        "repo": "disko",
+        "rev": "ca27b88c88948d96feeee9ed814cbd34f53d0d70",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "disko",
+        "type": "github"
+      }
+    },
+    "element-stickers": {
+      "inputs": {
+        "maunium-stickerpicker": [
+          "maunium-stickerpicker"
+        ],
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1745345582,
+        "narHash": "sha256-T4JHS/iZPMFFbSQJAYKZxRdvUk0y/r0GuaN/b0QD7s8=",
+        "ref": "main",
+        "rev": "5c65f0fef48ce8193767a5d0453e7cf6ad046de4",
+        "revCount": 9,
+        "type": "git",
+        "url": "https://git.pub.solar/pub-solar/maunium-stickerpicker-nix"
+      },
+      "original": {
+        "ref": "main",
+        "type": "git",
+        "url": "https://git.pub.solar/pub-solar/maunium-stickerpicker-nix"
+      }
+    },
     "element-themes": {
       "flake": false,
       "locked": {
-        "lastModified": 1707755689,
-        "narHash": "sha256-pMwrpZwLp7tw0nBbz/ENVJ2LoN9jIxEfjcq7OXoiKEw=",
+        "lastModified": 1718859621,
+        "narHash": "sha256-ZOOm6UFGNSkGrdwbG5saLAYgAPYJ7E80ogA40CaW+E4=",
         "owner": "aaronraimist",
         "repo": "element-themes",
-        "rev": "2368b58c16d2c4aabb82a245f036d228cbb6e5f5",
+        "rev": "3bc82abc3dd468dabc933f0f9d0b443ed97554a6",
         "type": "github"
       },
       "original": {
@@ -104,16 +164,32 @@
         "type": "github"
       }
     },
+    "flake-compat_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1696426674,
+        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
     "flake-parts": {
       "inputs": {
         "nixpkgs-lib": "nixpkgs-lib"
       },
       "locked": {
-        "lastModified": 1712014858,
-        "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
+        "lastModified": 1743550720,
+        "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
+        "rev": "c621e8422220273271f52058f618c94e405bb0f5",
         "type": "github"
       },
       "original": {
@@ -158,18 +234,19 @@
         "type": "github"
       }
     },
-    "flake-utils_3": {
+    "fork": {
       "locked": {
-        "lastModified": 1653893745,
-        "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
+        "lastModified": 1741180627,
+        "narHash": "sha256-NM2X42gtXuYT7EG+zYcvNTZ/6+CTc3fSiIwdcQcp0dk=",
+        "owner": "teutat3s",
+        "repo": "nixpkgs",
+        "rev": "8a43eb74ac149c080d57d8c80d647fef74df84d8",
         "type": "github"
       },
       "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
+        "owner": "teutat3s",
+        "ref": "init-matrix-authentication-service-module-0.13.0",
+        "repo": "nixpkgs",
         "type": "github"
       }
     },
@@ -180,16 +257,16 @@
         ]
       },
       "locked": {
-        "lastModified": 1712386041,
-        "narHash": "sha256-dA82pOMQNnCJMAsPG7AXG35VmCSMZsJHTFlTHizpKWQ=",
+        "lastModified": 1745557122,
+        "narHash": "sha256-eqSo9ugzsqhFgaDFYUZj943nurlX4L6f+AW0skJ4W+M=",
         "owner": "nix-community",
         "repo": "home-manager",
-        "rev": "d6bb9f934f2870e5cbc5b94c79e9db22246141ff",
+        "rev": "dd26f75fb4ec1c731d4b1396eaf4439ce40a91c1",
         "type": "github"
       },
       "original": {
         "owner": "nix-community",
-        "ref": "release-23.11",
+        "ref": "release-24.11",
         "repo": "home-manager",
         "type": "github"
       }
@@ -203,11 +280,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1707424749,
-        "narHash": "sha256-eTvts5E3zmD4/DoAI9KedQjRwica0cg36wwIVp1NWbM=",
+        "lastModified": 1738012343,
+        "narHash": "sha256-agMgWwVxXII+RtCqok8ROjzpKJung/5N5f2BVDmMC5Q=",
         "ref": "main",
-        "rev": "1202a23c205b3c07a5feb5caf6813f21b3c69307",
-        "revCount": 30,
+        "rev": "4ffd7bc8ea032991756c5e8e8a37b039789045bc",
+        "revCount": 38,
         "type": "git",
         "url": "https://git.pub.solar/pub-solar/keycloak-theme"
       },
@@ -217,6 +294,25 @@
         "url": "https://git.pub.solar/pub-solar/keycloak-theme"
       }
     },
+    "maunium-stickerpicker": {
+      "flake": false,
+      "locked": {
+        "dir": "web",
+        "lastModified": 1742926008,
+        "narHash": "sha256-PQ6Qv7VSumLa05Mrnylh1i8maWAHptd4vKwdElE4Tns=",
+        "owner": "maunium",
+        "repo": "stickerpicker",
+        "rev": "4b96d236212b1212976f4c3c60479e7aaed866cb",
+        "type": "github"
+      },
+      "original": {
+        "dir": "web",
+        "owner": "maunium",
+        "ref": "master",
+        "repo": "stickerpicker",
+        "type": "github"
+      }
+    },
     "nix-darwin": {
       "inputs": {
         "nixpkgs": [
@@ -224,11 +320,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1713543876,
-        "narHash": "sha256-olEWxacm1xZhAtpq+ZkEyQgR4zgfE7ddpNtZNvubi3g=",
+        "lastModified": 1744478979,
+        "narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
         "owner": "lnl7",
         "repo": "nix-darwin",
-        "rev": "9e7c20ffd056e406ddd0276ee9d89f09c5e5f4ed",
+        "rev": "43975d782b418ebf4969e9ccba82466728c2851b",
         "type": "github"
       },
       "original": {
@@ -238,68 +334,34 @@
         "type": "github"
       }
     },
-    "nixos-flake": {
-      "locked": {
-        "lastModified": 1711376798,
-        "narHash": "sha256-37wawZGSX/dD1rn7TwFJhUdpozC2VPEQXetpfpK/D+w=",
-        "owner": "srid",
-        "repo": "nixos-flake",
-        "rev": "7b19503e7f8c7cc0884fc2fbd669c0cc2e05aef5",
-        "type": "github"
-      },
-      "original": {
-        "owner": "srid",
-        "repo": "nixos-flake",
-        "type": "github"
-      }
-    },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1713564160,
-        "narHash": "sha256-YguPZpiejgzLEcO36/SZULjJQ55iWcjAmf3lYiyV1Fo=",
+        "lastModified": 1745487689,
+        "narHash": "sha256-FQoi3R0NjQeBAsEOo49b5tbDPcJSMWc3QhhaIi9eddw=",
         "owner": "nixos",
         "repo": "nixpkgs",
-        "rev": "bc194f70731cc5d2b046a6c1b3b15f170f05999c",
+        "rev": "5630cf13cceac06cefe9fc607e8dfa8fb342dde3",
         "type": "github"
       },
       "original": {
         "owner": "nixos",
-        "ref": "nixos-23.11",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs-2205": {
-      "locked": {
-        "lastModified": 1685573264,
-        "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=",
-        "owner": "nixos",
-        "repo": "nixpkgs",
-        "rev": "380be19fbd2d9079f677978361792cb25e8a3635",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nixos",
-        "ref": "nixos-22.05",
+        "ref": "nixos-24.11",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
     "nixpkgs-lib": {
       "locked": {
-        "dir": "lib",
-        "lastModified": 1711703276,
-        "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089",
+        "lastModified": 1743296961,
+        "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
+        "owner": "nix-community",
+        "repo": "nixpkgs.lib",
+        "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
         "type": "github"
       },
       "original": {
-        "dir": "lib",
-        "owner": "NixOS",
-        "ref": "nixos-unstable",
-        "repo": "nixpkgs",
+        "owner": "nix-community",
+        "repo": "nixpkgs.lib",
         "type": "github"
       }
     },
@@ -307,18 +369,46 @@
       "inputs": {
         "agenix": "agenix",
         "deploy-rs": "deploy-rs",
+        "disko": "disko",
+        "element-stickers": "element-stickers",
         "element-themes": "element-themes",
         "flake-parts": "flake-parts",
+        "fork": "fork",
         "home-manager": "home-manager",
         "keycloak-theme-pub-solar": "keycloak-theme-pub-solar",
+        "maunium-stickerpicker": "maunium-stickerpicker",
         "nix-darwin": "nix-darwin",
-        "nixos-flake": "nixos-flake",
         "nixpkgs": "nixpkgs",
-        "nixpkgs-2205": "nixpkgs-2205",
-        "triton-vmtools": "triton-vmtools",
+        "simple-nixos-mailserver": "simple-nixos-mailserver",
         "unstable": "unstable"
       }
     },
+    "simple-nixos-mailserver": {
+      "inputs": {
+        "blobs": "blobs",
+        "flake-compat": "flake-compat_2",
+        "nixpkgs": [
+          "unstable"
+        ],
+        "nixpkgs-24_11": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1734884447,
+        "narHash": "sha256-HA9fAmGNGf0cOYrhgoa+B6BxNVqGAYXfLyx8zIS0ZBY=",
+        "owner": "simple-nixos-mailserver",
+        "repo": "nixos-mailserver",
+        "rev": "63209b1def2c9fc891ad271f474a3464a5833294",
+        "type": "gitlab"
+      },
+      "original": {
+        "owner": "simple-nixos-mailserver",
+        "ref": "nixos-24.11",
+        "repo": "nixos-mailserver",
+        "type": "gitlab"
+      }
+    },
     "systems": {
       "locked": {
         "lastModified": 1681028828,
@@ -379,37 +469,13 @@
         "type": "github"
       }
     },
-    "triton-vmtools": {
-      "inputs": {
-        "flake-utils": "flake-utils_3",
-        "nixpkgs": [
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "dir": "vmtools",
-        "lastModified": 1698443513,
-        "narHash": "sha256-wX2JIJ3JmJn6MAurdyjwZU+FZjLCwBArMrVSeeCb/ZU=",
-        "ref": "main",
-        "rev": "0d039dcf06afb8cbddd7ac54bae4d0d185f3e88e",
-        "revCount": 85,
-        "type": "git",
-        "url": "https://git.pub.solar/pub-solar/infra-vintage?dir=vmtools"
-      },
-      "original": {
-        "dir": "vmtools",
-        "ref": "main",
-        "type": "git",
-        "url": "https://git.pub.solar/pub-solar/infra-vintage?dir=vmtools"
-      }
-    },
     "unstable": {
       "locked": {
-        "lastModified": 1713537308,
-        "narHash": "sha256-XtTSSIB2DA6tOv+l0FhvfDMiyCmhoRbNB+0SeInZkbk=",
+        "lastModified": 1745391562,
+        "narHash": "sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo=",
         "owner": "nixos",
         "repo": "nixpkgs",
-        "rev": "5c24cf2f0a12ad855f444c30b2421d044120c66f",
+        "rev": "8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7",
         "type": "github"
       },
       "original": {
diff --git a/flake.nix b/flake.nix
index 32e9c603..0cc47682 100644
--- a/flake.nix
+++ b/flake.nix
@@ -1,23 +1,24 @@
 {
   inputs = {
     # Track channels with commits tested and built by hydra
-    nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11";
+    nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11";
     unstable.url = "github:nixos/nixpkgs/nixos-unstable";
-
-    nixpkgs-2205.url = "github:nixos/nixpkgs/nixos-22.05";
+    fork.url = "github:teutat3s/nixpkgs/init-matrix-authentication-service-module-0.13.0";
 
     nix-darwin.url = "github:lnl7/nix-darwin/master";
     nix-darwin.inputs.nixpkgs.follows = "nixpkgs";
 
-    home-manager.url = "github:nix-community/home-manager/release-23.11";
+    home-manager.url = "github:nix-community/home-manager/release-24.11";
     home-manager.inputs.nixpkgs.follows = "nixpkgs";
 
     flake-parts.url = "github:hercules-ci/flake-parts";
-    nixos-flake.url = "github:srid/nixos-flake";
 
     deploy-rs.url = "github:serokell/deploy-rs";
     deploy-rs.inputs.nixpkgs.follows = "nixpkgs";
 
+    disko.url = "github:nix-community/disko";
+    disko.inputs.nixpkgs.follows = "nixpkgs";
+
     agenix.url = "github:ryantm/agenix";
     agenix.inputs.nixpkgs.follows = "nixpkgs";
     agenix.inputs.darwin.follows = "nix-darwin";
@@ -26,77 +27,154 @@
     keycloak-theme-pub-solar.url = "git+https://git.pub.solar/pub-solar/keycloak-theme?ref=main";
     keycloak-theme-pub-solar.inputs.nixpkgs.follows = "nixpkgs";
 
-    triton-vmtools.url = "git+https://git.pub.solar/pub-solar/infra-vintage?ref=main&dir=vmtools";
-    triton-vmtools.inputs.nixpkgs.follows = "nixpkgs";
-
     element-themes.url = "github:aaronraimist/element-themes/master";
     element-themes.flake = false;
+
+    maunium-stickerpicker.url = "github:maunium/stickerpicker?ref=master&dir=web";
+    maunium-stickerpicker.flake = false;
+
+    element-stickers.url = "git+https://git.pub.solar/pub-solar/maunium-stickerpicker-nix?ref=main";
+    element-stickers.inputs.maunium-stickerpicker.follows = "maunium-stickerpicker";
+    element-stickers.inputs.nixpkgs.follows = "nixpkgs";
+
+    simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-24.11";
+    simple-nixos-mailserver.inputs.nixpkgs-24_11.follows = "nixpkgs";
+    simple-nixos-mailserver.inputs.nixpkgs.follows = "unstable";
   };
 
-  outputs = inputs@{ self, ... }:
+  outputs =
+    inputs@{ self, ... }:
     inputs.flake-parts.lib.mkFlake { inherit inputs; } {
-      systems = [ "x86_64-linux" "aarch64-linux" ];
+      systems = [
+        "x86_64-linux"
+        "aarch64-linux"
+      ];
 
       imports = [
-        inputs.nixos-flake.flakeModule
         ./logins
         ./lib
         ./overlays
-        ./modules
         ./hosts
       ];
 
-      perSystem = { system, pkgs, config, ... }: {
-        _module.args = {
-          inherit inputs;
-          pkgs = import inputs.nixpkgs {
-            inherit system;
-            overlays = [
-              inputs.agenix.overlays.default
+      perSystem =
+        {
+          system,
+          pkgs,
+          config,
+          lib,
+          ...
+        }:
+        {
+          _module.args = {
+            inherit inputs;
+            pkgs = import inputs.nixpkgs {
+              inherit system;
+              overlays = [ inputs.agenix.overlays.default ];
+            };
+            unstable = import inputs.unstable { inherit system; };
+          };
+
+          checks =
+            let
+              machinesPerSystem = {
+                aarch64-linux = [
+                  "metronom"
+                ];
+                x86_64-linux = [
+                  "blue-shell"
+                  "delite"
+                  "nachtigall"
+                  "tankstelle"
+                  "trinkgenossin"
+                  "underground"
+                ];
+              };
+              nixosMachines = inputs.nixpkgs.lib.mapAttrs' (n: inputs.nixpkgs.lib.nameValuePair "nixos-${n}") (
+                inputs.nixpkgs.lib.genAttrs (machinesPerSystem.${system} or [ ]) (
+                  name: self.nixosConfigurations.${name}.config.system.build.toplevel
+                )
+              );
+              nixos-lib = import (inputs.nixpkgs + "/nixos/lib") { };
+              testDir = builtins.attrNames (builtins.readDir ./tests);
+              testFiles = builtins.filter (n: builtins.match "^.*.nix$" n != null) testDir;
+            in
+            builtins.listToAttrs (
+              map (x: {
+                name = "test-${lib.strings.removeSuffix ".nix" x}";
+                value = nixos-lib.runTest (
+                  import (./tests + "/${x}") {
+                    inherit self;
+                    inherit pkgs;
+                    inherit lib;
+                    inherit config;
+                  }
+                );
+              }) testFiles
+            )
+            // nixosMachines;
+
+          devShells.default = pkgs.mkShell {
+            buildInputs = with pkgs; [
+              deploy-rs
+              nix-fast-build
+              agenix
+              age-plugin-yubikey
+              cachix
+              editorconfig-checker
+              nodePackages.prettier
+              nvfetcher
+              shellcheck
+              shfmt
+              treefmt2
+              nixos-generators
+              opentofu
+              terraform-backend-git
+              terraform-ls
+              jq
             ];
           };
-          unstable = import inputs.unstable { inherit system; };
-          master = import inputs.master { inherit system; };
+
+          devShells.ci = pkgs.mkShell { buildInputs = with pkgs; [ nodejs ]; };
         };
-        devShells.default = pkgs.mkShell {
-          buildInputs = with pkgs; [
-            deploy-rs
-            nixpkgs-fmt
-            agenix
-            age-plugin-yubikey
-            cachix
-            editorconfig-checker
-            nodePackages.prettier
-            nvfetcher
-            shellcheck
-            shfmt
-            treefmt
-            nixos-generators
-            inputs.nixpkgs-2205.legacyPackages.${system}.terraform
-            jq
-          ];
-        };
-      };
 
-      flake =
-        let
-          username = "barkeeper";
-        in
-        {
-          inherit username;
+      flake = {
+        nixosModules = builtins.listToAttrs (
+          map (x: {
+            name = x;
+            value = import (./modules + "/${x}");
+          }) (builtins.attrNames (builtins.readDir ./modules))
+        );
 
-          checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) inputs.deploy-rs.lib;
+        checks = builtins.mapAttrs (
+          system: deployLib: deployLib.deployChecks self.deploy
+        ) inputs.deploy-rs.lib;
 
-          deploy.nodes = self.lib.deploy.mkDeployNodes self.nixosConfigurations {
-            nachtigall = {
-              hostname = "10.7.6.1";
-              sshUser = username;
-            };
-            flora-6 = {
-              hostname = "10.7.6.2";
-              sshUser = username;
-            };
+        formatter."x86_64-linux" = inputs.nixpkgs.legacyPackages."x86_64-linux".nixfmt-rfc-style;
+
+        deploy.nodes = self.lib.deploy.mkDeployNodes self.nixosConfigurations {
+          nachtigall = {
+            hostname = "nachtigall.wg.pub.solar";
+          };
+          metronom = {
+            hostname = "metronom.wg.pub.solar";
+          };
+          tankstelle = {
+            hostname = "tankstelle.wg.pub.solar";
+          };
+          underground = {
+            hostname = "80.244.242.3";
+          };
+          trinkgenossin = {
+            hostname = "trinkgenossin.wg.pub.solar";
+          };
+          delite = {
+            hostname = "delite.wg.pub.solar";
+          };
+          blue-shell = {
+            hostname = "blue-shell.wg.pub.solar";
           };
         };
+      };
     };
 }
diff --git a/hosts/blue-shell/configuration.nix b/hosts/blue-shell/configuration.nix
new file mode 100644
index 00000000..df9424b4
--- /dev/null
+++ b/hosts/blue-shell/configuration.nix
@@ -0,0 +1,33 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+{
+  boot.loader.grub.enable = true;
+
+  boot.kernelParams = [
+    "boot.shell_on_fail=1"
+    "ip=dhcp"
+  ];
+
+  # This option defines the first version of NixOS you have installed on this particular machine,
+  # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
+  #
+  # Most users should NEVER change this value after the initial install, for any reason,
+  # even if you've upgraded your system to a new NixOS release.
+  #
+  # This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
+  # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
+  # to actually do that.
+  #
+  # This value being lower than the current NixOS release does NOT mean your system is
+  # out of date, out of support, or vulnerable.
+  #
+  # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
+  # and migrated your data accordingly.
+  #
+  # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
+  system.stateVersion = "24.05"; # Did you read the comment?
+}
diff --git a/hosts/blue-shell/default.nix b/hosts/blue-shell/default.nix
new file mode 100644
index 00000000..ff8c0cc0
--- /dev/null
+++ b/hosts/blue-shell/default.nix
@@ -0,0 +1,13 @@
+{ flake, ... }:
+
+{
+  imports = [
+    ./hardware-configuration.nix
+    ./configuration.nix
+    ./disk-config.nix
+
+    ./networking.nix
+    ./wireguard.nix
+    #./backups.nix
+  ];
+}
diff --git a/hosts/blue-shell/disk-config.nix b/hosts/blue-shell/disk-config.nix
new file mode 100644
index 00000000..2903130d
--- /dev/null
+++ b/hosts/blue-shell/disk-config.nix
@@ -0,0 +1,101 @@
+{
+  disko.devices = {
+    disk = {
+      main = {
+        type = "disk";
+        device = "/dev/vdb";
+        content = {
+          type = "gpt";
+          partitions = {
+            bios = {
+              size = "1M";
+              type = "EF02"; # for grub MBR
+            };
+            boot = {
+              size = "1G";
+              type = "8300";
+              content = {
+                type = "filesystem";
+                format = "ext4";
+                mountpoint = "/boot";
+                mountOptions = [ "defaults" ];
+              };
+            };
+            luks = {
+              size = "100%";
+              content = {
+                type = "luks";
+                name = "cryptroot";
+                extraOpenArgs = [ ];
+                # if you want to use the key for interactive login be sure there is no trailing newline
+                # for example use `echo -n "password" > /tmp/secret.key`
+                passwordFile = "/tmp/luks-password";
+                content = {
+                  type = "lvm_pv";
+                  vg = "vg0";
+                };
+              };
+            };
+          };
+        };
+      };
+      data = {
+        type = "disk";
+        device = "/dev/vdc";
+        content = {
+          type = "gpt";
+          partitions = {
+            luks = {
+              size = "100%";
+              content = {
+                type = "luks";
+                name = "cryptdata";
+                extraOpenArgs = [ ];
+                # if you want to use the key for interactive login be sure there is no trailing newline
+                # for example use `echo -n "password" > /tmp/secret.key`
+                passwordFile = "/tmp/luks-password";
+                content = {
+                  type = "filesystem";
+                  format = "xfs";
+                  mountpoint = "/var/lib/garage/data";
+                  mountOptions = [ "defaults" ];
+                };
+              };
+            };
+          };
+        };
+      };
+    };
+    lvm_vg = {
+      vg0 = {
+        type = "lvm_vg";
+        lvs = {
+          root = {
+            size = "100G";
+            content = {
+              type = "filesystem";
+              format = "ext4";
+              mountpoint = "/";
+              mountOptions = [ "defaults" ];
+            };
+          };
+          swap = {
+            size = "16G";
+            content = {
+              type = "swap";
+            };
+          };
+          metadata = {
+            size = "50G";
+            content = {
+              type = "filesystem";
+              format = "btrfs";
+              mountpoint = "/var/lib/garage/meta";
+              mountOptions = [ "defaults" ];
+            };
+          };
+        };
+      };
+    };
+  };
+}
diff --git a/hosts/blue-shell/hardware-configuration.nix b/hosts/blue-shell/hardware-configuration.nix
new file mode 100644
index 00000000..86e1e30f
--- /dev/null
+++ b/hosts/blue-shell/hardware-configuration.nix
@@ -0,0 +1,27 @@
+# Do not modify this file!  It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations.  Please make changes
+# to /etc/nixos/configuration.nix instead.
+{
+  config,
+  lib,
+  pkgs,
+  modulesPath,
+  ...
+}:
+
+{
+  imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
+
+  boot.initrd.availableKernelModules = [
+    "ata_piix"
+    "uhci_hcd"
+    "virtio_pci"
+    "sr_mod"
+    "virtio_blk"
+  ];
+  boot.initrd.kernelModules = [ ];
+  boot.kernelModules = [ ];
+  boot.extraModulePackages = [ ];
+
+  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+}
diff --git a/hosts/blue-shell/networking.nix b/hosts/blue-shell/networking.nix
new file mode 100644
index 00000000..8aea3d99
--- /dev/null
+++ b/hosts/blue-shell/networking.nix
@@ -0,0 +1,26 @@
+{
+  config,
+  pkgs,
+  flake,
+  ...
+}:
+{
+  services.garage.settings.rpc_public_addr = "[2a03:4000:43:24e::1]:3901";
+
+  networking.hostName = "blue-shell";
+  networking.hostId = "00000005";
+
+  networking.useDHCP = false;
+  systemd.network.enable = true;
+  systemd.network.networks."10-wan" = {
+    matchConfig.Name = "ens3";
+    address = [
+      "194.13.83.205/22"
+      "2a03:4000:43:24e::1/64"
+    ];
+    gateway = [
+      "194.13.80.1"
+      "fe80::1"
+    ];
+  };
+}
diff --git a/hosts/blue-shell/wireguard.nix b/hosts/blue-shell/wireguard.nix
new file mode 100644
index 00000000..8da6c9d2
--- /dev/null
+++ b/hosts/blue-shell/wireguard.nix
@@ -0,0 +1,51 @@
+{
+  config,
+  pkgs,
+  flake,
+  ...
+}:
+let
+  wireguardIPv4 = "10.7.6.7";
+  wireguardIPv6 = "fd00:fae:fae:fae:fae:7::";
+in
+{
+  networking.firewall.allowedUDPPorts = [ 51820 ];
+
+  age.secrets.wg-private-key.file = "${flake.self}/secrets/blue-shell-wg-private-key.age";
+
+  networking.wireguard.interfaces = {
+    wg-ssh = {
+      listenPort = 51820;
+      mtu = 1300;
+      ips = [
+        "${wireguardIPv4}/32"
+        "${wireguardIPv6}/96"
+      ];
+      privateKeyFile = config.age.secrets.wg-private-key.path;
+      peers = flake.self.logins.wireguardDevices ++ [
+        {
+          # trinkgenossin.pub.solar
+          publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4=";
+          allowedIPs = [
+            "10.7.6.5/32"
+            "fd00:fae:fae:fae:fae:5::/96"
+          ];
+          #endpoint = "85.215.152.22:51820";
+          endpoint = "[2a01:239:35d:f500::1]:51820";
+          persistentKeepalive = 15;
+        }
+      ];
+    };
+  };
+
+  services.openssh.listenAddresses = [
+    {
+      addr = wireguardIPv4;
+      port = 22;
+    }
+    {
+      addr = "[${wireguardIPv6}]";
+      port = 22;
+    }
+  ];
+}
diff --git a/hosts/default.nix b/hosts/default.nix
index 45563ee0..d465b40f 100644
--- a/hosts/default.nix
+++ b/hosts/default.nix
@@ -1,9 +1,35 @@
-{ self, ... }:
+{
+  self,
+  inputs,
+  config,
+  ...
+}:
 {
   flake = {
-    nixosConfigurations = {
-      nachtigall = self.nixos-flake.lib.mkLinuxSystem {
+    nixosModules = {
+      home-manager = {
         imports = [
+          inputs.home-manager.nixosModules.home-manager
+          {
+            home-manager.useGlobalPkgs = true;
+            home-manager.useUserPackages = true;
+            home-manager.extraSpecialArgs = {
+              flake = {
+                inherit self inputs config;
+              };
+            };
+          }
+        ];
+      };
+    };
+    nixosConfigurations = {
+      nachtigall = self.inputs.nixpkgs.lib.nixosSystem {
+        specialArgs = {
+          flake = {
+            inherit self inputs config;
+          };
+        };
+        modules = [
           self.inputs.agenix.nixosModules.default
           self.nixosModules.home-manager
           ./nachtigall
@@ -11,16 +37,172 @@
           self.nixosModules.unlock-zfs-on-boot
           self.nixosModules.core
           self.nixosModules.docker
+          self.nixosModules.backups
+
+          self.nixosModules.nginx
+          self.nixosModules.collabora
+          self.nixosModules.coturn
+          self.nixosModules.forgejo
+          self.nixosModules.keycloak
+          self.nixosModules.mailman
+          self.nixosModules.mastodon
+          self.nixosModules.nginx-mastodon
+          self.nixosModules.nginx-mastodon-files
+          self.nixosModules.mediawiki
+          self.nixosModules.nextcloud
+          self.nixosModules.nginx-website
+          self.nixosModules.nginx-website-miom
+          self.nixosModules.opensearch
+          self.nixosModules.owncast
+          self.nixosModules.postgresql
+          self.nixosModules.prometheus-exporters
+          self.nixosModules.promtail
+          self.nixosModules.searx
+          self.nixosModules.tmate
+          self.nixosModules.tt-rss
+          self.nixosModules.obs-portal
+          self.nixosModules.matrix
+          self.nixosModules.matrix-irc
+          self.nixosModules.matrix-telegram
+          self.nixosModules.nginx-matrix
         ];
       };
 
-      flora-6 = self.nixos-flake.lib.mkLinuxSystem {
-        imports = [
+      metronom = self.inputs.nixpkgs.lib.nixosSystem {
+        specialArgs = {
+          flake = {
+            inherit self inputs config;
+          };
+        };
+        modules = [
           self.inputs.agenix.nixosModules.default
           self.nixosModules.home-manager
-          ./flora-6
+          ./metronom
+          self.nixosModules.overlays
+          self.nixosModules.unlock-zfs-on-boot
+          self.nixosModules.core
+          self.nixosModules.backups
+          self.nixosModules.mail
+          self.nixosModules.prometheus-exporters
+          self.nixosModules.promtail
+
+          self.inputs.simple-nixos-mailserver.nixosModule
+        ];
+      };
+
+      tankstelle = self.inputs.nixpkgs.lib.nixosSystem {
+        specialArgs = {
+          flake = {
+            inherit self inputs config;
+          };
+        };
+        modules = [
+          self.inputs.agenix.nixosModules.default
+          self.nixosModules.home-manager
+          ./tankstelle
           self.nixosModules.overlays
           self.nixosModules.core
+          self.nixosModules.backups
+          self.nixosModules.prometheus-exporters
+          self.nixosModules.promtail
+          self.nixosModules.forgejo-actions-runner
+        ];
+      };
+
+      trinkgenossin = self.inputs.nixpkgs.lib.nixosSystem {
+        specialArgs = {
+          flake = {
+            inherit self inputs config;
+          };
+        };
+        modules = [
+          self.inputs.agenix.nixosModules.default
+          self.nixosModules.home-manager
+          ./trinkgenossin
+          self.nixosModules.backups
+          self.nixosModules.overlays
+          self.nixosModules.unlock-luks-on-boot
+          self.nixosModules.core
+
+          self.nixosModules.garage
+          self.nixosModules.nginx
+
+          # This module is already using options, and those options are used by the grafana module
+          self.nixosModules.keycloak
+          self.nixosModules.grafana
+          self.nixosModules.prometheus
+          self.nixosModules.prometheus-exporters
+          self.nixosModules.loki
+          self.nixosModules.promtail
+          self.nixosModules.forgejo-actions-runner
+        ];
+      };
+
+      delite = self.inputs.nixpkgs.lib.nixosSystem {
+        specialArgs = {
+          flake = {
+            inherit self inputs config;
+          };
+        };
+        modules = [
+          self.inputs.agenix.nixosModules.default
+          self.inputs.disko.nixosModules.disko
+          self.nixosModules.home-manager
+          ./delite
+          self.nixosModules.overlays
+          self.nixosModules.unlock-luks-on-boot
+          self.nixosModules.core
+          self.nixosModules.prometheus-exporters
+          self.nixosModules.promtail
+
+          self.nixosModules.garage
+          self.nixosModules.nginx
+        ];
+      };
+
+      blue-shell = self.inputs.nixpkgs.lib.nixosSystem {
+        specialArgs = {
+          flake = {
+            inherit self inputs config;
+          };
+        };
+        modules = [
+          self.inputs.agenix.nixosModules.default
+          self.inputs.disko.nixosModules.disko
+          self.nixosModules.home-manager
+          ./blue-shell
+          self.nixosModules.overlays
+          self.nixosModules.unlock-luks-on-boot
+          self.nixosModules.core
+          self.nixosModules.prometheus-exporters
+          self.nixosModules.promtail
+
+          self.nixosModules.garage
+          self.nixosModules.nginx
+        ];
+      };
+
+      underground = self.inputs.nixpkgs.lib.nixosSystem {
+        specialArgs = {
+          flake = {
+            inherit self inputs config;
+          };
+        };
+        modules = [
+          self.inputs.agenix.nixosModules.default
+          self.nixosModules.home-manager
+          ./underground
+          self.nixosModules.overlays
+          self.nixosModules.unlock-luks-on-boot
+          self.nixosModules.core
+
+          self.nixosModules.backups
+          self.nixosModules.keycloak
+          self.nixosModules.postgresql
+          self.nixosModules.matrix
+          self.nixosModules.matrix-irc
+          self.nixosModules.nginx
+          self.nixosModules.nginx-matrix
         ];
       };
     };
diff --git a/hosts/delite/configuration.nix b/hosts/delite/configuration.nix
new file mode 100644
index 00000000..e84e8c78
--- /dev/null
+++ b/hosts/delite/configuration.nix
@@ -0,0 +1,33 @@
+{
+  flake,
+  config,
+  pkgs,
+  ...
+}:
+{
+  boot.loader.grub.enable = true;
+
+  boot.kernelParams = [
+    "boot.shell_on_fail=1"
+    "ip=5.255.119.132::5.255.119.1:255.255.255.0:delite::off"
+  ];
+
+  # This option defines the first version of NixOS you have installed on this particular machine,
+  # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
+  #
+  # Most users should NEVER change this value after the initial install, for any reason,
+  # even if you've upgraded your system to a new NixOS release.
+  #
+  # This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
+  # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
+  # to actually do that.
+  #
+  # This value being lower than the current NixOS release does NOT mean your system is
+  # out of date, out of support, or vulnerable.
+  #
+  # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
+  # and migrated your data accordingly.
+  #
+  # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
+  system.stateVersion = "24.05"; # Did you read the comment?
+}
diff --git a/hosts/delite/default.nix b/hosts/delite/default.nix
new file mode 100644
index 00000000..ff8c0cc0
--- /dev/null
+++ b/hosts/delite/default.nix
@@ -0,0 +1,13 @@
+{ flake, ... }:
+
+{
+  imports = [
+    ./hardware-configuration.nix
+    ./configuration.nix
+    ./disk-config.nix
+
+    ./networking.nix
+    ./wireguard.nix
+    #./backups.nix
+  ];
+}
diff --git a/hosts/delite/disk-config.nix b/hosts/delite/disk-config.nix
new file mode 100644
index 00000000..dea45f44
--- /dev/null
+++ b/hosts/delite/disk-config.nix
@@ -0,0 +1,84 @@
+{
+  disko.devices = {
+    disk = {
+      main = {
+        type = "disk";
+        device = "/dev/vda";
+        content = {
+          type = "gpt";
+          partitions = {
+            bios = {
+              size = "1M";
+              type = "EF02"; # for grub MBR
+            };
+            boot = {
+              size = "1G";
+              type = "8300";
+              content = {
+                type = "filesystem";
+                format = "ext4";
+                mountpoint = "/boot";
+                mountOptions = [ "defaults" ];
+              };
+            };
+            luks = {
+              size = "100%";
+              content = {
+                type = "luks";
+                name = "cryptroot";
+                extraOpenArgs = [ ];
+                # if you want to use the key for interactive login be sure there is no trailing newline
+                # for example use `echo -n "password" > /tmp/secret.key`
+                passwordFile = "/tmp/luks-password";
+                content = {
+                  type = "lvm_pv";
+                  vg = "vg0";
+                };
+              };
+            };
+          };
+        };
+      };
+    };
+    lvm_vg = {
+      vg0 = {
+        type = "lvm_vg";
+        lvs = {
+          root = {
+            size = "40G";
+            content = {
+              type = "filesystem";
+              format = "ext4";
+              mountpoint = "/";
+              mountOptions = [ "defaults" ];
+            };
+          };
+          swap = {
+            size = "8G";
+            content = {
+              type = "swap";
+            };
+          };
+          data = {
+            size = "800G";
+            content = {
+              type = "filesystem";
+              format = "xfs";
+              mountpoint = "/var/lib/garage/data";
+              mountOptions = [ "defaults" ];
+            };
+          };
+          metadata = {
+            size = "50G";
+            content = {
+              type = "filesystem";
+              format = "btrfs";
+              mountpoint = "/var/lib/garage/meta";
+              mountOptions = [ "defaults" ];
+            };
+          };
+        };
+      };
+    };
+  };
+}
diff --git a/hosts/delite/hardware-configuration.nix b/hosts/delite/hardware-configuration.nix
new file mode 100644
index 00000000..5fff3303
--- /dev/null
+++ b/hosts/delite/hardware-configuration.nix
@@ -0,0 +1,26 @@
+# Do not modify this file!  It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations.  Please make changes
+# to /etc/nixos/configuration.nix instead.
+{
+  config,
+  lib,
+  pkgs,
+  modulesPath,
+  ...
+}:
+
+{
+  imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
+
+  boot.initrd.availableKernelModules = [
+    "ata_piix"
+    "uhci_hcd"
+    "virtio_pci"
+    "virtio_blk"
+  ];
+  boot.initrd.kernelModules = [ "dm-snapshot" ];
+  boot.kernelModules = [ ];
+  boot.extraModulePackages = [ ];
+
+  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+}
diff --git a/hosts/delite/networking.nix b/hosts/delite/networking.nix
new file mode 100644
index 00000000..357e3b0e
--- /dev/null
+++ b/hosts/delite/networking.nix
@@ -0,0 +1,26 @@
+{
+  config,
+  pkgs,
+  flake,
+  ...
+}:
+{
+  services.garage.settings.rpc_public_addr = "[2a04:52c0:124:9d8c::2]:3901";
+
+  networking.hostName = "delite";
+  networking.hostId = "00000004";
+
+  networking.useDHCP = false;
+  systemd.network.enable = true;
+  systemd.network.networks."10-wan" = {
+    matchConfig.Name = "ens3";
+    address = [
+      "5.255.119.132/24"
+      "2a04:52c0:124:9d8c::2/48"
+    ];
+    gateway = [
+      "5.255.119.1"
+      "2a04:52c0:124::1"
+    ];
+  };
+}
diff --git a/hosts/delite/wireguard.nix b/hosts/delite/wireguard.nix
new file mode 100644
index 00000000..2c5e1a3c
--- /dev/null
+++ b/hosts/delite/wireguard.nix
@@ -0,0 +1,51 @@
+{
+  config,
+  pkgs,
+  flake,
+  ...
+}:
+let
+  wireguardIPv4 = "10.7.6.6";
+  wireguardIPv6 = "fd00:fae:fae:fae:fae:6::";
+in
+{
+  networking.firewall.allowedUDPPorts = [ 51820 ];
+
+  age.secrets.wg-private-key.file = "${flake.self}/secrets/delite-wg-private-key.age";
+
+  networking.wireguard.interfaces = {
+    wg-ssh = {
+      listenPort = 51820;
+      mtu = 1300;
+      ips = [
+        "${wireguardIPv4}/32"
+        "${wireguardIPv6}/96"
+      ];
+      privateKeyFile = config.age.secrets.wg-private-key.path;
+      peers = flake.self.logins.wireguardDevices ++ [
+        {
+          # trinkgenossin.pub.solar
+          publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4=";
+          allowedIPs = [
+            "10.7.6.5/32"
+            "fd00:fae:fae:fae:fae:5::/96"
+          ];
+          #endpoint = "85.215.152.22:51820";
+          endpoint = "[2a01:239:35d:f500::1]:51820";
+          persistentKeepalive = 15;
+        }
+      ];
+    };
+  };
+
+  services.openssh.listenAddresses = [
+    {
+      addr = wireguardIPv4;
+      port = 22;
+    }
+    {
+      addr = "[${wireguardIPv6}]";
+      port = 22;
+    }
+  ];
+}
diff --git a/hosts/flora-6/apps/caddy.nix b/hosts/flora-6/apps/caddy.nix
deleted file mode 100644
index cf70d8d8..00000000
--- a/hosts/flora-6/apps/caddy.nix
+++ /dev/null
@@ -1,59 +0,0 @@
-{ config
-, lib
-, pkgs
-, flake
-, ...
-}:
-{
-  systemd.tmpfiles.rules = [
-    "d '/data/srv/www/os/download/' 0750 hakkonaut hakkonaut - -"
-  ];
-
-  services.caddy = {
-    enable = lib.mkForce true;
-    group = "hakkonaut";
-    email = "admins@pub.solar";
-    enableReload = true;
-    globalConfig = lib.mkForce ''
-      grace_period 60s
-    '';
-    virtualHosts = {
-      "ci.pub.solar" = {
-        logFormat = lib.mkForce ''
-          output discard
-        '';
-        extraConfig = ''
-          reverse_proxy :4000
-        '';
-      };
-      "flora-6.pub.solar" = {
-        logFormat = lib.mkForce ''
-          output discard
-        '';
-        extraConfig = ''
-                    basicauth * {
-          	    hakkonaut $2a$14$mmIAy/Ezm6YGohUtXa2mWeW6Bcw1MQXPhrRbz14jAD2iUu3oob/t.
-                    }
-                    reverse_proxy :${toString config.services.loki.configuration.server.http_listen_port}
-        '';
-      };
-      "grafana.pub.solar" = {
-        logFormat = lib.mkForce ''
-          output discard
-        '';
-        extraConfig = ''
-          reverse_proxy :${toString config.services.grafana.settings.server.http_port}
-        '';
-      };
-      "obs-portal.pub.solar" = {
-        logFormat = lib.mkForce ''
-          output discard
-        '';
-        extraConfig = ''
-          reverse_proxy obs-portal.svc.e5756d08-36fd-424b-f8bc-acdb92ca7b82.lev-1.int.greenbaum.zone:3000
-        '';
-      };
-    };
-  };
-  networking.firewall.allowedTCPPorts = [ 80 443 ];
-}
diff --git a/hosts/flora-6/apps/drone.nix b/hosts/flora-6/apps/drone.nix
deleted file mode 100644
index 9620d2bd..00000000
--- a/hosts/flora-6/apps/drone.nix
+++ /dev/null
@@ -1,119 +0,0 @@
-{ config
-, lib
-, pkgs
-, flake
-, ...
-}: {
-  age.secrets.drone-secrets = {
-    file = "${flake.self}/secrets/drone-secrets.age";
-    mode = "600";
-    owner = "drone";
-  };
-  age.secrets.drone-db-secrets = {
-    file = "${flake.self}/secrets/drone-db-secrets.age";
-    mode = "600";
-    owner = "drone";
-  };
-
-  users.users.drone = {
-    description = "Drone Service";
-    home = "/var/lib/drone";
-    useDefaultShell = true;
-    uid = 994;
-    group = "drone";
-    isSystemUser = true;
-  };
-
-  users.groups.drone = { };
-
-  systemd.tmpfiles.rules = [
-    "d '/var/lib/drone-db' 0750 drone drone - -"
-  ];
-
-  systemd.services."docker-network-drone" =
-    let
-      docker = config.virtualisation.oci-containers.backend;
-      dockerBin = "${pkgs.${docker}}/bin/${docker}";
-    in
-    {
-      serviceConfig.Type = "oneshot";
-      before = [ "docker-drone-server.service" ];
-      script = ''
-        ${dockerBin} network inspect drone-net >/dev/null 2>&1 || ${dockerBin} network create drone-net --subnet 172.20.0.0/24
-      '';
-    };
-
-  virtualisation = {
-    docker = {
-      enable = true; # sadly podman is not supported rightnow
-      extraOptions = ''
-        --data-root /data/docker
-      '';
-    };
-
-    oci-containers = {
-      backend = "docker";
-      containers."drone-db" = {
-        image = "postgres:14";
-        autoStart = true;
-        user = "994";
-        volumes = [
-          "/var/lib/drone-db:/var/lib/postgresql/data"
-        ];
-        extraOptions = [
-          "--network=drone-net"
-        ];
-        environmentFiles = [
-          config.age.secrets.drone-db-secrets.path
-        ];
-      };
-      containers."drone-server" = {
-        image = "drone/drone:2";
-        autoStart = true;
-        user = "994";
-        ports = [
-          "127.0.0.1:4000:80"
-        ];
-        dependsOn = [ "drone-db" ];
-        extraOptions = [
-          "--network=drone-net"
-          "--pull=always"
-          "--add-host=nachtigall.pub.solar:10.7.6.1"
-        ];
-        environment = {
-          DRONE_GITEA_SERVER = "https://git.pub.solar";
-          DRONE_SERVER_HOST = "ci.pub.solar";
-          DRONE_SERVER_PROTO = "https";
-          DRONE_DATABASE_DRIVER = "postgres";
-        };
-        environmentFiles = [
-          config.age.secrets.drone-secrets.path
-        ];
-      };
-      containers."drone-docker-runner" = {
-        image = "drone/drone-runner-docker:1";
-        autoStart = true;
-        # needs to run as root
-        #user = "994";
-        volumes = [
-          "/var/run/docker.sock:/var/run/docker.sock"
-        ];
-        dependsOn = [ "drone-db" ];
-        extraOptions = [
-          "--network=drone-net"
-          "--pull=always"
-          "--add-host=nachtigall.pub.solar:10.7.6.1"
-        ];
-        environment = {
-          DRONE_RPC_HOST = "ci.pub.solar";
-          DRONE_RPC_PROTO = "https";
-          DRONE_RUNNER_CAPACITY = "2";
-          DRONE_RUNNER_NAME = "flora-6-docker-runner";
-        };
-        environmentFiles = [
-          config.age.secrets.drone-secrets.path
-        ];
-      };
-    };
-  };
-}
diff --git a/hosts/flora-6/apps/forgejo-actions-runner.nix b/hosts/flora-6/apps/forgejo-actions-runner.nix
deleted file mode 100644
index 045f0c24..00000000
--- a/hosts/flora-6/apps/forgejo-actions-runner.nix
+++ /dev/null
@@ -1,65 +0,0 @@
-{ config
-, lib
-, pkgs
-, flake
-, ...
-}: {
-  age.secrets.forgejo-actions-runner-token = {
-    file = "${flake.self}/secrets/forgejo-actions-runner-token.age";
-    mode = "644";
-  };
-
-  # Trust docker bridge interface traffic
-  # Needed for the docker runner to communicate with the act_runner cache
-  networking.firewall.trustedInterfaces = [ "br-+" ];
-
-  users.users.gitea-runner = {
-    home = "/var/lib/gitea-runner/flora-6";
-    useDefaultShell = true;
-    group = "gitea-runner";
-    isSystemUser = true;
-  };
-
-  users.groups.gitea-runner = {};
-
-  systemd.services."gitea-runner-flora\\x2d6".serviceConfig = {
-    DynamicUser = lib.mkForce false;
-  };
-
-  systemd.tmpfiles.rules = [
-    "d '/data/gitea-actions-runner' 0750 gitea-runner gitea-runner - -"
-    "d '/var/lib/gitea-runner' 0750 gitea-runner gitea-runner - -"
-  ];
-
-  # forgejo actions runner
-  # https://forgejo.org/docs/latest/admin/actions/
-  # https://docs.gitea.com/usage/actions/quickstart
-  services.gitea-actions-runner = {
-    package = pkgs.forgejo-runner;
-    instances."flora-6" = {
-      enable = true;
-      name = config.networking.hostName;
-      url = "https://git.pub.solar";
-      tokenFile = config.age.secrets.forgejo-actions-runner-token.path;
-      settings = {
-        cache = {
-          enabled = true;
-          dir = "/data/gitea-actions-runner/actcache";
-          host = "";
-          port = 0;
-          external_server = "";
-        };
-      };
-      labels = [
-        # provide a debian 12 bookworm base with Node.js for actions
-        "debian-latest:docker://git.pub.solar/pub-solar/actions-base-image:20-bookworm"
-        # fake the ubuntu name, commonly used in actions examples
-        "ubuntu-latest:docker://git.pub.solar/pub-solar/actions-base-image:20-bookworm"
-        # alpine with Node.js
-        "alpine-latest:docker://node:20-alpine"
-        # nix flakes enabled image with Node.js
-        "nix-flakes:docker://git.pub.solar/pub-solar/nix-flakes-node:latest"
-      ];
-    };
-  };
-}
diff --git a/hosts/flora-6/apps/loki.nix b/hosts/flora-6/apps/loki.nix
deleted file mode 100644
index 5e7a8cc7..00000000
--- a/hosts/flora-6/apps/loki.nix
+++ /dev/null
@@ -1,84 +0,0 @@
-{ config
-, lib
-, pkgs
-, flake
-, ...
-}: {
-  # source: https://gist.github.com/rickhull/895b0cb38fdd537c1078a858cf15d63e
-  # https://grafana.com/docs/loki/latest/configure/examples/#1-local-configuration-exampleyaml
-  services.loki = {
-    enable = true;
-    configuration = {
-      server.http_listen_port = 3100;
-      auth_enabled = false;
-      common = {
-        ring = {
-          instance_addr = "127.0.0.1";
-          kvstore = {
-            store = "inmemory";
-          };
-        };
-        replication_factor = 1;
-        path_prefix = "/var/lib/loki";
-        storage = {
-          filesystem = {
-            chunks_directory = "chunks/";
-            rules_directory = "rules/";
-          };
-        };
-      };
-      # Keep logs for 4 weeks
-      # https://grafana.com/docs/loki/latest/operations/storage/retention/
-      limits_config.retention_period = "4w";
-      compactor = {
-        shared_store = "filesystem";
-        compaction_interval = "10m";
-        retention_enabled = true;
-        retention_delete_delay = "2h";
-        retention_delete_worker_count = 150;
-      };
-      schema_config = {
-        configs = [{
-          from = "2020-05-15";
-          store = "boltdb-shipper";
-          object_store = "filesystem";
-          schema = "v11";
-          index = {
-            prefix = "index_";
-            period = "24h";
-          };
-        }];
-      };
-    };
-  };
-
-  services.promtail = {
-    enable = true;
-    configuration = {
-      server = {
-        http_listen_port = 9080;
-        grpc_listen_port = 0;
-      };
-      positions = {
-        filename = "/tmp/positions.yaml";
-      };
-      clients = [{
-        url = "http://127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}/loki/api/v1/push";
-      }];
-      scrape_configs = [{
-        job_name = "journal";
-        journal = {
-          max_age = "24h";
-          labels = {
-            job = "systemd-journal";
-            host = "flora-6";
-          };
-        };
-        relabel_configs = [{
-          source_labels = [ "__journal__systemd_unit" ];
-          target_label = "unit";
-        }];
-      }];
-    };
-  };
-}
diff --git a/hosts/flora-6/apps/prometheus.nix b/hosts/flora-6/apps/prometheus.nix
deleted file mode 100644
index 11bc0bf0..00000000
--- a/hosts/flora-6/apps/prometheus.nix
+++ /dev/null
@@ -1,69 +0,0 @@
-{ config
-, lib
-, pkgs
-, flake
-, ...
-}: {
-  age.secrets.nachtigall-metrics-prometheus-basic-auth-password = {
-    file = "${flake.self}/secrets/nachtigall-metrics-prometheus-basic-auth-password.age";
-    mode = "600";
-    owner = "prometheus";
-  };
-
-  services.prometheus = {
-    enable = true;
-    port = 9001;
-    exporters = {
-      node = {
-        enable = true;
-        enabledCollectors = [ "systemd" ];
-        port = 9002;
-      };
-    };
-    globalConfig = {
-      scrape_interval = "10s";
-      scrape_timeout = "9s";
-    };
-    scrapeConfigs = [
-      {
-        job_name = "node-exporter-http";
-        static_configs = [{
-          targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.node.port}" ];
-          labels = {
-            instance = "flora-6";
-          };
-        }];
-      }
-      {
-        job_name = "node-exporter-https";
-        scheme = "https";
-        metrics_path = "/metrics";
-        basic_auth = {
-          username = "hakkonaut";
-          password_file = "${config.age.secrets.nachtigall-metrics-prometheus-basic-auth-password.path}";
-        };
-        static_configs = [{
-          targets = [ "nachtigall.pub.solar" ];
-          labels = {
-            instance = "nachtigall";
-          };
-        }];
-      }
-      {
-        job_name = "matrix-synapse";
-        scheme = "https";
-        metrics_path = "/_synapse/metrics";
-        basic_auth = {
-          username = "hakkonaut";
-          password_file = "${config.age.secrets.nachtigall-metrics-prometheus-basic-auth-password.path}";
-        };
-        static_configs = [{
-          targets = [ "nachtigall.pub.solar" ];
-          labels = {
-            instance = "nachtigall";
-          };
-        }];
-      }
-    ];
-  };
-}
diff --git a/hosts/flora-6/configuration.nix b/hosts/flora-6/configuration.nix
deleted file mode 100644
index 6ac9c97f..00000000
--- a/hosts/flora-6/configuration.nix
+++ /dev/null
@@ -1,71 +0,0 @@
-{ config
-, lib
-, pkgs
-, flake
-, ...
-}:
-let
-  psCfg = config.pub-solar;
-in
-{
-  config = {
-    # Override nix.conf for more agressive garbage collection
-    nix.extraOptions = lib.mkForce ''
-      experimental-features = flakes nix-command
-      min-free = 536870912
-      keep-outputs = false
-      keep-derivations = false
-      fallback = true
-    '';
-
-    # # #
-    # # # Triton host specific options
-    # # # DO NOT ALTER below this line, changes might render system unbootable
-    # # #
-
-    # Use the systemd-boot EFI boot loader.
-    boot.loader.systemd-boot.enable = true;
-    boot.loader.efi.canTouchEfiVariables = true;
-
-    # Force getting the hostname from cloud-init
-    networking.hostName = lib.mkDefault "";
-
-    # We use cloud-init to configure networking, this option should fix
-    # systemd-networkd-wait-online timeouts
-    #systemd.services."systemd-networkd".environment.SYSTEMD_LOG_LEVEL = "debug";
-    systemd.network.wait-online.ignoredInterfaces = [
-      "docker0"
-      "wg-ssh"
-    ];
-
-    # List services that you want to enable:
-    services.cloud-init.enable = true;
-    services.cloud-init.ext4.enable = true;
-    services.cloud-init.network.enable = true;
-    # use the default NixOS cloud-init config, but add some SmartOS customization to it
-    environment.etc."cloud/cloud.cfg.d/90_smartos.cfg".text = ''
-      datasource_list: [ SmartOS ]
-
-      # Do not create the centos/ubuntu/debian user
-      users: [ ]
-
-      # mount second disk with label ephemeral0, gets formated by cloud-init
-      # this will fail to get added to /etc/fstab as it's read-only, but should
-      # mount at boot anyway
-      mounts:
-      - [ vdb, /data, auto, "defaults,nofail" ]
-    '';
-
-    # We manage the firewall with nix, too
-    # altough triton can also manage firewall rules via the triton fwrule subcommand
-    networking.firewall.enable = true;
-
-    # This value determines the NixOS release from which the default
-    # settings for stateful data, like file locations and database versions
-    # on your system were taken. It‘s perfectly fine and recommended to leave
-    # this value at the release version of the first install of this system.
-    # Before changing this value read the documentation for this option
-    # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
-    system.stateVersion = "22.05"; # Did you read the comment?
-  };
-}
diff --git a/hosts/flora-6/default.nix b/hosts/flora-6/default.nix
deleted file mode 100644
index 17910211..00000000
--- a/hosts/flora-6/default.nix
+++ /dev/null
@@ -1,20 +0,0 @@
-{ ... }:
-
-{
-  imports =
-    [
-      # Include the results of the hardware scan.
-      ./hardware-configuration.nix
-      ./configuration.nix
-      ./triton-vmtools.nix
-      ./wireguard.nix
-
-      ./apps/caddy.nix
-
-      ./apps/drone.nix
-      ./apps/forgejo-actions-runner.nix
-      ./apps/grafana.nix
-      ./apps/prometheus.nix
-      ./apps/loki.nix
-    ];
-}
diff --git a/hosts/flora-6/hardware-configuration.nix b/hosts/flora-6/hardware-configuration.nix
deleted file mode 100644
index b8375d95..00000000
--- a/hosts/flora-6/hardware-configuration.nix
+++ /dev/null
@@ -1,44 +0,0 @@
-# Do not modify this file!  It was generated by ‘nixos-generate-config’
-# and may be overwritten by future invocations.  Please make changes
-# to /etc/nixos/configuration.nix instead.
-{ config
-, lib
-, pkgs
-, modulesPath
-, ...
-}: {
-  imports = [ ];
-
-  boot.initrd.availableKernelModules = [ "ahci" "virtio_pci" "xhci_pci" "sr_mod" "virtio_blk" ];
-  boot.initrd.kernelModules = [ ];
-  boot.kernelModules = [ ];
-  boot.extraModulePackages = [ ];
-
-  fileSystems."/" = {
-    device = "/dev/disk/by-label/nixos";
-    autoResize = true;
-    fsType = "ext4";
-  };
-
-  fileSystems."/boot" = {
-    device = "/dev/disk/by-label/boot";
-    fsType = "vfat";
-  };
-
-  fileSystems."/data" = {
-    device = "/dev/disk/by-label/ephemeral0";
-    fsType = "ext4";
-    options = [
-      "defaults"
-      "nofail"
-    ];
-  };
-
-  swapDevices = [ ];
-
-  networking.useDHCP = lib.mkDefault false;
-  networking.networkmanager.enable = lib.mkForce false;
-
-  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
-  hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
-}
diff --git a/hosts/flora-6/triton-vmtools.nix b/hosts/flora-6/triton-vmtools.nix
deleted file mode 100644
index 0fc5346c..00000000
--- a/hosts/flora-6/triton-vmtools.nix
+++ /dev/null
@@ -1,8 +0,0 @@
-{ pkgs
-, flake
-, ...
-}: {
-  environment.systemPackages = with pkgs; [
-    flake.inputs.triton-vmtools.packages.${pkgs.system}.default
-  ];
-}
diff --git a/hosts/flora-6/wireguard.nix b/hosts/flora-6/wireguard.nix
deleted file mode 100644
index cc9b6b7e..00000000
--- a/hosts/flora-6/wireguard.nix
+++ /dev/null
@@ -1,40 +0,0 @@
-{
-  config,
-  pkgs,
-  flake,
-  ... }:
-{
-  networking.firewall.allowedUDPPorts = [ 51820 ];
-
-  age.secrets.wg-private-key.file = "${flake.self}/secrets/flora6-wg-private-key.age";
-
-  networking.wireguard.interfaces = {
-    wg-ssh = {
-      listenPort = 51820;
-      mtu = 1300;
-      ips = [
-        "10.7.6.2/32"
-        "fd00:fae:fae:fae:fae:2::/96"
-      ];
-      privateKeyFile = config.age.secrets.wg-private-key.path;
-      peers = flake.self.logins.admins.wireguardDevices ++ [
-        { # nachtigall.pub.solar
-          endpoint = "138.201.80.102:51820";
-          publicKey = "qzNywKY9RvqTnDO8eLik75/SHveaSk9OObilDzv+xkk=";
-          allowedIPs = [ "10.7.6.1/32" "fd00:fae:fae:fae:fae:1::/96" ];
-        }
-      ];
-    };
-  };
-
-  services.openssh.listenAddresses = [ 
-    {
-      addr = "10.7.6.2";
-      port = 22;
-    }
-    {
-      addr = "[fd00:fae:fae:fae:fae:2::]";
-      port = 22;
-    }
-  ];
-}
diff --git a/hosts/metronom/backups.nix b/hosts/metronom/backups.nix
new file mode 100644
index 00000000..3512b7bb
--- /dev/null
+++ b/hosts/metronom/backups.nix
@@ -0,0 +1,29 @@
+{ config, flake, ... }:
+{
+  age.secrets."restic-repo-storagebox-metronom" = {
+    file = "${flake.self}/secrets/restic-repo-storagebox-metronom.age";
+    mode = "400";
+    owner = "root";
+  };
+  age.secrets.restic-repo-garage-metronom = {
+    file = "${flake.self}/secrets/restic-repo-garage-metronom.age";
+    mode = "400";
+    owner = "root";
+  };
+  age.secrets.restic-repo-garage-metronom-env = {
+    file = "${flake.self}/secrets/restic-repo-garage-metronom-env.age";
+    mode = "400";
+    owner = "root";
+  };
+
+  pub-solar-os.backups.repos.storagebox = {
+    passwordFile = config.age.secrets."restic-repo-storagebox-metronom".path;
+    repository = "sftp:u377325@u377325.your-storagebox.de:/metronom-backups";
+  };
+
+  pub-solar-os.backups.repos.garage = {
+    passwordFile = config.age.secrets."restic-repo-garage-metronom".path;
+    environmentFile = config.age.secrets."restic-repo-garage-metronom-env".path;
+    repository = "s3:https://buckets.pub.solar/metronom-backups";
+  };
+}
diff --git a/hosts/metronom/configuration.nix b/hosts/metronom/configuration.nix
new file mode 100644
index 00000000..72037463
--- /dev/null
+++ b/hosts/metronom/configuration.nix
@@ -0,0 +1,47 @@
+{
+  flake,
+  config,
+  pkgs,
+  ...
+}:
+{
+  boot.loader.systemd-boot.enable = true;
+  boot.supportedFilesystems = [ "zfs" ];
+
+  boot.kernelParams = [
+    "boot.shell_on_fail=1"
+    "ip=dhcp"
+  ];
+
+  boot.initrd.availableKernelModules = [ "igb" ];
+
+  # https://nixos.wiki/wiki/ZFS#declarative_mounting_of_ZFS_datasets
+  systemd.services.zfs-mount.enable = false;
+
+  services.zfs.autoScrub = {
+    enable = true;
+    pools = [ "root_pool" ];
+  };
+
+  # Declarative SSH private key
+  age.secrets."metronom-root-ssh-key" = {
+    file = "${flake.self}/secrets/metronom-root-ssh-key.age";
+    path = "/root/.ssh/id_ed25519";
+    mode = "400";
+    owner = "root";
+  };
+
+  # Declarative SSH private key
+  #age.secrets."metronom-root-ssh-key" = {
+  #  file = "${flake.self}/secrets/metronom-root-ssh-key.age";
+  #  path = "/root/.ssh/id_ed25519";
+  #  mode = "400";
+  #  owner = "root";
+  #};
+
+  # This value determines the NixOS release with which your system is to be
+  # compatible, in order to avoid breaking some software such as database
+  # servers. You should change this only after NixOS release notes say you
+  # should.
+  system.stateVersion = "23.11"; # Did you read the comment?
+}
diff --git a/hosts/metronom/default.nix b/hosts/metronom/default.nix
new file mode 100644
index 00000000..581b1517
--- /dev/null
+++ b/hosts/metronom/default.nix
@@ -0,0 +1,12 @@
+{ flake, ... }:
+
+{
+  imports = [
+    ./hardware-configuration.nix
+    ./configuration.nix
+
+    ./networking.nix
+    ./wireguard.nix
+    ./backups.nix
+  ];
+}
diff --git a/hosts/metronom/hardware-configuration.nix b/hosts/metronom/hardware-configuration.nix
new file mode 100644
index 00000000..f891016e
--- /dev/null
+++ b/hosts/metronom/hardware-configuration.nix
@@ -0,0 +1,48 @@
+# Do not modify this file!  It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations.  Please make changes
+# to /etc/nixos/configuration.nix instead.
+{
+  config,
+  lib,
+  pkgs,
+  modulesPath,
+  ...
+}:
+
+{
+  imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
+
+  boot.initrd.availableKernelModules = [
+    "xhci_pci"
+    "virtio_pci"
+    "virtio_scsi"
+    "usbhid"
+    "sr_mod"
+  ];
+  boot.initrd.kernelModules = [ ];
+  boot.kernelModules = [ ];
+  boot.extraModulePackages = [ ];
+
+  fileSystems."/" = {
+    device = "root_pool/root";
+    fsType = "zfs";
+  };
+
+  fileSystems."/boot" = {
+    device = "/dev/disk/by-uuid/2083-C68E";
+    fsType = "vfat";
+  };
+
+  swapDevices = [ ];
+
+  # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
+  # (the default) this is the recommended approach. When using systemd-networkd it's
+  # still possible to use this option, but it's recommended to use it in conjunction
+  # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
+  networking.useDHCP = lib.mkDefault true;
+  # networking.interfaces.eth0.useDHCP = lib.mkDefault true;
+
+  nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
+  powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand";
+  hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
+}
diff --git a/hosts/metronom/networking.nix b/hosts/metronom/networking.nix
new file mode 100644
index 00000000..380c2207
--- /dev/null
+++ b/hosts/metronom/networking.nix
@@ -0,0 +1,19 @@
+{
+  config,
+  pkgs,
+  flake,
+  ...
+}:
+{
+
+  networking.hostName = "metronom";
+  networking.extraHosts = ''
+    127.0.0.2 mail.pub.solar mail
+    ::1 mail.pub.solar mail
+  '';
+  networking.hostId = "00000002";
+
+  networking.enableIPv6 = true;
+  networking.useDHCP = false;
+  networking.interfaces."enp1s0".useDHCP = true;
+}
diff --git a/hosts/metronom/wireguard.nix b/hosts/metronom/wireguard.nix
new file mode 100644
index 00000000..51362d2b
--- /dev/null
+++ b/hosts/metronom/wireguard.nix
@@ -0,0 +1,56 @@
+{
+  config,
+  pkgs,
+  flake,
+  ...
+}:
+{
+  networking.firewall.allowedUDPPorts = [ 51820 ];
+
+  age.secrets.wg-private-key.file = "${flake.self}/secrets/metronom-wg-private-key.age";
+
+  networking.wireguard.interfaces = {
+    wg-ssh = {
+      listenPort = 51820;
+      mtu = 1300;
+      ips = [
+        "10.7.6.3/32"
+        "fd00:fae:fae:fae:fae:3::/96"
+      ];
+      privateKeyFile = config.age.secrets.wg-private-key.path;
+      peers = flake.self.logins.wireguardDevices ++ [
+        {
+          # nachtigall.pub.solar
+          endpoint = "138.201.80.102:51820";
+          publicKey = "qzNywKY9RvqTnDO8eLik75/SHveaSk9OObilDzv+xkk=";
+          allowedIPs = [
+            "10.7.6.1/32"
+            "fd00:fae:fae:fae:fae:1::/96"
+          ];
+        }
+        {
+          # trinkgenossin.pub.solar
+          publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4=";
+          allowedIPs = [
+            "10.7.6.5/32"
+            "fd00:fae:fae:fae:fae:5::/96"
+          ];
+          #endpoint = "85.215.152.22:51820";
+          endpoint = "[2a01:239:35d:f500::1]:51820";
+          persistentKeepalive = 15;
+        }
+      ];
+    };
+  };
+
+  services.openssh.listenAddresses = [
+    {
+      addr = "10.7.6.3";
+      port = 22;
+    }
+    {
+      addr = "[fd00:fae:fae:fae:fae:3::]";
+      port = 22;
+    }
+  ];
+}
diff --git a/hosts/nachtigall/apps/keycloak.nix b/hosts/nachtigall/apps/keycloak.nix
deleted file mode 100644
index 81b46ec5..00000000
--- a/hosts/nachtigall/apps/keycloak.nix
+++ /dev/null
@@ -1,96 +0,0 @@
-{ flake
-, config
-, lib
-, pkgs
-, ...
-}: {
-  age.secrets.keycloak-database-password = {
-    file = "${flake.self}/secrets/keycloak-database-password.age";
-    mode = "600";
-    #owner = "keycloak";
-  };
-
-  services.nginx.virtualHosts."auth.pub.solar" = {
-    enableACME = true;
-    forceSSL = true;
-
-    locations = {
-      "= /" = {
-        extraConfig = ''
-          return 302 /realms/pub.solar/account;
-        '';
-      };
-
-      "/" = {
-        extraConfig = ''
-          proxy_pass http://127.0.0.1:8080;
-          proxy_buffer_size 8k;
-        '';
-      };
-    };
-  };
-
-  # keycloak
-  services.keycloak = {
-    enable = true;
-    database.passwordFile = config.age.secrets.keycloak-database-password.path;
-    settings = {
-      hostname = "auth.pub.solar";
-      http-host = "127.0.0.1";
-      http-port = 8080;
-      proxy = "edge";
-      features = "declarative-user-profile";
-    };
-    themes = {
-      "pub.solar" = flake.inputs.keycloak-theme-pub-solar.legacyPackages.${pkgs.system}.keycloak-theme-pub-solar;
-    };
-  };
-
-  services.restic.backups.keycloak-droppie = {
-    paths = [
-      "/tmp/keycloak-backup.sql"
-    ];
-    timerConfig = {
-      OnCalendar = "*-*-* 02:00:00 Etc/UTC";
-      # droppie will be offline if nachtigall misses the timer
-      Persistent = false;
-    };
-    initialize = true;
-    passwordFile = config.age.secrets."restic-repo-droppie".path;
-    repository = "sftp:yule@droppie.b12f.io:/media/internal/pub.solar";
-    backupPrepareCommand = ''
-      ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d keycloak > /tmp/keycloak-backup.sql
-    '';
-    backupCleanupCommand = ''
-      rm /tmp/keycloak-backup.sql
-    '';
-    pruneOpts = [
-      "--keep-daily 7"
-      "--keep-weekly 4"
-      "--keep-monthly 3"
-    ];
-  };
-
-  services.restic.backups.keycloak-storagebox = {
-    paths = [
-      "/tmp/keycloak-backup.sql"
-    ];
-    timerConfig = {
-      OnCalendar = "*-*-* 04:10:00 Etc/UTC";
-    };
-    initialize = true;
-    passwordFile = config.age.secrets."restic-repo-storagebox".path;
-    repository = "sftp:u377325@u377325.your-storagebox.de:/backups";
-    backupPrepareCommand = ''
-      ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d keycloak > /tmp/keycloak-backup.sql
-    '';
-    backupCleanupCommand = ''
-      rm /tmp/keycloak-backup.sql
-    '';
-    pruneOpts = [
-      "--keep-daily 7"
-      "--keep-weekly 4"
-      "--keep-monthly 3"
-    ];
-  };
-}
diff --git a/hosts/nachtigall/apps/matrix/irc.nix b/hosts/nachtigall/apps/matrix/irc.nix
deleted file mode 100644
index fb2c1e07..00000000
--- a/hosts/nachtigall/apps/matrix/irc.nix
+++ /dev/null
@@ -1,125 +0,0 @@
-{ config, lib, pkgs, ... }:
-let
-  # Find element in list config.services.matrix-synapse.settings.listeners.*.resources
-  # that sets names = "client"
-  nameHasClient = name: name == "client";
-  resourceHasClient = resource: builtins.any nameHasClient resource.names;
-  listenerWithClient = lib.findFirst
-    (listener:
-      builtins.any resourceHasClient listener.resources)
-    (throw "Found no matrix-synapse.settings.listeners.*.resources.*.names containing string client")
-    config.services.matrix-synapse.settings.listeners
-  ;
-  synapseClientPort = "${toString listenerWithClient.port}";
-in
-{
-  systemd.services.matrix-appservice-irc.serviceConfig.SystemCallFilter = lib.mkForce [
-    "@system-service @pkey"
-    "~@privileged @resources"
-    "@chown"
-  ];
-  services.matrix-appservice-irc = {
-    enable = true;
-    localpart = "irc_bot";
-    port = 8010;
-    registrationUrl = "http://localhost:8010";
-    settings = {
-      homeserver = {
-        domain = "pub.solar";
-        url = "http://127.0.0.1:${synapseClientPort}";
-        media_url = "https://matrix.pub.solar";
-        enablePresence = false;
-      };
-      ircService = {
-        ident = {
-          address = "::";
-          enabled = false;
-          port = 1113;
-        };
-        logging = {
-          level = "debug";
-          maxFiles = 5;
-          toCosole = true;
-        };
-        matrixHandler = {
-          eventCacheSize = 4096;
-        };
-        metrics = {
-          enabled = true;
-          remoteUserAgeBuckets = [ "1h" "1d" "1w" ];
-        };
-        provisioning = {
-          enabled = false;
-          requestTimeoutSeconds = 300;
-        };
-        servers =
-          let
-            commonConfig = {
-              allowExpiredCerts = false;
-              botConfig = {
-                enabled = false;
-                joinChannelsIfNoUsers = false;
-                nick = "MatrixBot";
-              };
-              dynamicChannels = {
-                createAlias = true;
-                enabled = true;
-                federate = true;
-                joinRule = "public";
-                published = true;
-              };
-              ircClients = {
-                allowNickChanges = true;
-                concurrentReconnectLimit = 50;
-                idleTimeout = 10800;
-                lineLimit = 3;
-                maxClients = 30;
-                nickTemplate = "$DISPLAY[m]";
-                reconnectIntervalMs = 5000;
-              };
-              matrixClients = {
-                joinAttempts = -1;
-              };
-              membershipLists = {
-                enabled = true;
-                floodDelayMs = 10000;
-                global = {
-                  ircToMatrix = {
-                    incremental = true;
-                    initial = true;
-                  };
-                  matrixToIrc = {
-                    incremental = true;
-                    initial = true;
-                  };
-                };
-              };
-              port = 6697;
-              privateMessages = {
-                enabled = true;
-                federate = true;
-              };
-              sasl = false;
-              sendConnectionMessages = true;
-              ssl = true;
-            };
-          in
-          {
-            "irc.libera.chat" = lib.attrsets.recursiveUpdate commonConfig {
-              name = "libera";
-              dynamicChannels.groupId = "+libera.chat:localhost";
-              dynamicChannels.aliasTemplate = "#_libera_$CHANNEL";
-              matrixClients.displayName = "$NICK (LIBERA-IRC)";
-            };
-            "irc.scratch-network.net" = lib.attrsets.recursiveUpdate commonConfig {
-              name = "scratch";
-              matrixClients.displayName = "$NICK (SCRATCH-IRC)";
-              dynamicChannels.aliasTemplate = "#_scratch_$CHANNEL";
-              dynamicChannels.groupId = "+scratch-network.net:localhost";
-            };
-          };
-      };
-    };
-  };
-}
-
diff --git a/hosts/nachtigall/apps/matrix/matrix-log-config.yaml b/hosts/nachtigall/apps/matrix/matrix-log-config.yaml
deleted file mode 100644
index 555f3aaa..00000000
--- a/hosts/nachtigall/apps/matrix/matrix-log-config.yaml
+++ /dev/null
@@ -1,40 +0,0 @@
-version: 1
-
-formatters:
-  precise:
-    format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s'
-
-filters:
-  context:
-    (): synapse.util.logcontext.LoggingContextFilter
-    request: ""
-
-handlers:
-  console:
-    class: logging.StreamHandler
-    formatter: precise
-    filters: [context]
-
-loggers:
-  synapse:
-    level: WARNING
-
-  synapse.storage.SQL:
-    # beware: increasing this to DEBUG will make synapse log sensitive
-    # information such as access tokens.
-    level: WARNING
-
-  synapse.http.matrixfederationclient:
-    level: CRITICAL
-  synapse.federation.sender.per_destination_queue:
-    level: CRITICAL
-  synapse.handlers.device:
-    level: CRITICAL
-  synapse.replication.tcp.handler:
-    level: CRITICAL
-  shared_secret_authenticator:
-    level: INFO
-
-root:
-  level: WARNING
-  handlers: [console]
diff --git a/hosts/nachtigall/apps/matrix/synapse.nix b/hosts/nachtigall/apps/matrix/synapse.nix
deleted file mode 100644
index dd799100..00000000
--- a/hosts/nachtigall/apps/matrix/synapse.nix
+++ /dev/null
@@ -1,321 +0,0 @@
-{ flake, config, pkgs, ... }:
-let
-  publicDomain = "matrix.pub.solar";
-  serverDomain = "pub.solar";
-in
-{
-  age.secrets."matrix-synapse-signing-key" = {
-    file = "${flake.self}/secrets/matrix-synapse-signing-key.age";
-    mode = "400";
-    owner = "matrix-synapse";
-  };
-
-  age.secrets."matrix-synapse-secret-config.yaml" = {
-    file = "${flake.self}/secrets/matrix-synapse-secret-config.yaml.age";
-    mode = "400";
-    owner = "matrix-synapse";
-  };
-
-  age.secrets."matrix-synapse-sliding-sync-secret" = {
-    file = "${flake.self}/secrets/matrix-synapse-sliding-sync-secret.age";
-    mode = "400";
-    owner = "matrix-synapse";
-  };
-
-  services.matrix-synapse = {
-    enable = true;
-    settings = {
-      server_name = serverDomain;
-      public_baseurl = "https://${publicDomain}/";
-      database = {
-        name = "psycopg2";
-        args = {
-          host = "/run/postgresql";
-          cp_max = 10;
-          cp_min = 5;
-          database = "matrix";
-        };
-        allow_unsafe_locale = false;
-        txn_limit = 0;
-      };
-      listeners = [
-        {
-          bind_addresses = [
-            "127.0.0.1"
-          ];
-          port = 8008;
-          resources = [
-            {
-              compress = true;
-              names = [
-                "client"
-              ];
-            }
-            {
-              compress = false;
-              names = [
-                "federation"
-              ];
-            }
-          ];
-          tls = false;
-          type = "http";
-          x_forwarded = true;
-        }
-        {
-          bind_addresses = [
-            "127.0.0.1"
-          ];
-          port = 8012;
-          resources = [
-            {
-              names = [
-                "metrics"
-              ];
-            }
-          ];
-          tls = false;
-          type = "metrics";
-        }
-      ];
-
-      account_threepid_delegates.msisdn = "";
-      alias_creation_rules = [{
-        action = "allow";
-        alias = "*";
-        room_id = "*";
-        user_id = "*";
-      }];
-      allow_guest_access = false;
-      allow_public_rooms_over_federation = true;
-      allow_public_rooms_without_auth = false;
-      auto_join_rooms = [
-        "#community:${serverDomain}"
-        "#general:${serverDomain}"
-      ];
-
-      autocreate_auto_join_rooms = true;
-      caches.global_factor = 0.5;
-
-      default_room_version = "10";
-      disable_msisdn_registration = true;
-      enable_media_repo = true;
-      enable_metrics = true;
-      mau_stats_only = true;
-      enable_registration = false;
-      enable_registration_captcha = false;
-      enable_registration_without_verification = false;
-      enable_room_list_search = true;
-      encryption_enabled_by_default_for_room_type = "off";
-      event_cache_size = "100K";
-      federation_rr_transactions_per_room_per_second = 50;
-      federation_client_minimum_tls_version = "1.2";
-      forget_rooms_on_leave = true;
-      include_profile_data_on_invite = true;
-      instance_map = { };
-      limit_profile_requests_to_users_who_share_rooms = false;
-
-      log_config = ./matrix-log-config.yaml;
-
-      max_spider_size = "10M";
-      max_upload_size = "50M";
-      media_storage_providers = [ ];
-
-      password_config = {
-        enabled = false;
-        localdb_enabled = false;
-        pepper = "";
-      };
-
-      presence.enabled = true;
-      push.include_content = false;
-
-      rc_admin_redaction = {
-        burst_count = 50;
-        per_second = 1;
-      };
-      rc_federation = {
-        concurrent = 3;
-        reject_limit = 50;
-        sleep_delay = 500;
-        sleep_limit = 10;
-        window_size = 1000;
-      };
-      rc_invites = {
-        per_issuer = {
-          burst_count = 10;
-          per_second = 0.3;
-        };
-        per_room = {
-          burst_count = 10;
-          per_second = 0.3;
-        };
-        per_user = {
-          burst_count = 5;
-          per_second = 0.003;
-        };
-      };
-      rc_joins = {
-        local = {
-          burst_count = 10;
-          per_second = 0.1;
-        };
-        remote = {
-          burst_count = 10;
-          per_second = 0.01;
-        };
-      };
-      rc_login = {
-        account = {
-          burst_count = 3;
-          per_second = 0.17;
-        };
-        address = {
-          burst_count = 3;
-          per_second = 0.17;
-        };
-        failed_attempts = {
-          burst_count = 3;
-          per_second = 0.17;
-        };
-      };
-      rc_message = {
-        burst_count = 10;
-        per_second = 0.2;
-      };
-      rc_registration = {
-        burst_count = 3;
-        per_second = 0.17;
-      };
-      redaction_retention_period = "7d";
-      forgotten_room_retention_period = "7d";
-      redis.enabled = false;
-      registration_requires_token = false;
-      registrations_require_3pid = [ "email" ];
-      report_stats = false;
-      require_auth_for_profile_requests = false;
-      room_list_publication_rules = [{
-        action = "allow";
-        alias = "*";
-        room_id = "*";
-        user_id = "*";
-      }];
-
-      signing_key_path = "/run/agenix/matrix-synapse-signing-key";
-
-      stream_writers = { };
-      trusted_key_servers = [{ server_name = "matrix.org"; }];
-      suppress_key_server_warning = true;
-
-      turn_allow_guests = false;
-      turn_uris = [
-        "turn:${config.services.coturn.realm}:3478?transport=udp"
-        "turn:${config.services.coturn.realm}:3478?transport=tcp"
-      ];
-      turn_user_lifetime = "1h";
-
-      url_preview_accept_language = [
-        "en-US"
-        "en"
-      ];
-      url_preview_enabled = true;
-      url_preview_ip_range_blacklist = [
-        "127.0.0.0/8"
-        "10.0.0.0/8"
-        "172.16.0.0/12"
-        "192.168.0.0/16"
-        "100.64.0.0/10"
-        "192.0.0.0/24"
-        "169.254.0.0/16"
-        "192.88.99.0/24"
-        "198.18.0.0/15"
-        "192.0.2.0/24"
-        "198.51.100.0/24"
-        "203.0.113.0/24"
-        "224.0.0.0/4"
-        "::1/128"
-        "fe80::/10"
-        "fc00::/7"
-        "2001:db8::/32"
-        "ff00::/8"
-        "fec0::/10"
-      ];
-
-      user_directory = {
-        prefer_local_users = false;
-        search_all_users = false;
-      };
-      user_ips_max_age = "28d";
-
-      app_service_config_files = [
-        "/var/lib/matrix-synapse/telegram-registration.yaml"
-        "/var/lib/matrix-appservice-irc/registration.yml"
-        # "/matrix-appservice-slack-registration.yaml"
-        # "/hookshot-registration.yml"
-        # "/matrix-mautrix-signal-registration.yaml"
-        # "/matrix-mautrix-telegram-registration.yaml"
-      ];
-    };
-
-    withJemalloc = true;
-
-    extraConfigFiles = [
-      "/run/agenix/matrix-synapse-secret-config.yaml"
-
-      # The registration file is automatically generated after starting the
-      # appservice for the first time.
-      # cp /var/lib/mautrix-telegram/telegram-registration.yaml \
-      #   /var/lib/matrix-synapse/
-      # chown matrix-synapse:matrix-synapse \
-      #   /var/lib/matrix-synapse/telegram-registration.yaml
-      "/var/lib/matrix-synapse/telegram-registration.yaml"
-    ];
-
-    extras = [
-      "oidc"
-      "redis"
-    ];
-
-    plugins = [
-      config.services.matrix-synapse.package.plugins.matrix-synapse-shared-secret-auth
-    ];
-
-    sliding-sync = {
-      enable = true;
-      settings = {
-        SYNCV3_SERVER = "https://${publicDomain}";
-        SYNCV3_BINDADDR = "127.0.0.1:8011";
-        # The bind addr for Prometheus metrics, which will be accessible at
-        # /metrics at this address
-        SYNCV3_PROM = "127.0.0.1:9100";
-      };
-      environmentFile = config.age.secrets."matrix-synapse-sliding-sync-secret".path;
-    };
-  };
-
-  services.restic.backups.matrix-synapse-storagebox = {
-    paths = [
-      "/var/lib/matrix-synapse"
-      "/var/lib/matrix-appservice-irc"
-      "/var/lib/mautrix-telegram"
-      "/tmp/matrix-synapse-backup.sql"
-    ];
-    timerConfig = {
-      OnCalendar = "*-*-* 05:00:00 Etc/UTC";
-    };
-    initialize = true;
-    passwordFile = config.age.secrets."restic-repo-storagebox".path;
-    repository = "sftp:u377325@u377325.your-storagebox.de:/backups";
-    backupPrepareCommand = ''
-      ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d matrix > /tmp/matrix-synapse-backup.sql
-    '';
-    backupCleanupCommand = ''
-      rm /tmp/matrix-synapse-backup.sql
-    '';
-    pruneOpts = [
-      "--keep-daily 7"
-      "--keep-weekly 4"
-      "--keep-monthly 3"
-    ];
-  };
-}
diff --git a/hosts/nachtigall/apps/nextcloud-skeleton/Documents/Example.odt b/hosts/nachtigall/apps/nextcloud-skeleton/Documents/Example.odt
deleted file mode 100644
index 852646eb..00000000
Binary files a/hosts/nachtigall/apps/nextcloud-skeleton/Documents/Example.odt and /dev/null differ
diff --git a/hosts/nachtigall/apps/nextcloud-skeleton/Pictures/pubsolar.png b/hosts/nachtigall/apps/nextcloud-skeleton/Pictures/pubsolar.png
deleted file mode 100644
index 5b4fe092..00000000
Binary files a/hosts/nachtigall/apps/nextcloud-skeleton/Pictures/pubsolar.png and /dev/null differ
diff --git a/hosts/nachtigall/apps/nextcloud.nix b/hosts/nachtigall/apps/nextcloud.nix
deleted file mode 100644
index bed4c04d..00000000
--- a/hosts/nachtigall/apps/nextcloud.nix
+++ /dev/null
@@ -1,183 +0,0 @@
-{ config
-, pkgs
-, flake
-, ...
-}:
-{
-  age.secrets."nextcloud-secrets" = {
-    file = "${flake.self}/secrets/nextcloud-secrets.age";
-    mode = "400";
-    owner = "nextcloud";
-  };
-
-  age.secrets."nextcloud-admin-pass" = {
-    file = "${flake.self}/secrets/nextcloud-admin-pass.age";
-    mode = "400";
-    owner = "nextcloud";
-  };
-
-  services.nginx.virtualHosts."cloud.pub.solar" = {
-    enableACME = true;
-    forceSSL = true;
-  };
-
-  services.nextcloud = {
-    hostName = "cloud.pub.solar";
-    home = "/var/lib/nextcloud";
-
-    enable = true;
-    package = pkgs.nextcloud28;
-    https = true;
-    secretFile = config.age.secrets."nextcloud-secrets".path; # secret
-    maxUploadSize = "1G";
-    skeletonDirectory = "./nextcloud-skeleton";
-
-    configureRedis = true;
-
-    notify_push = {
-      enable = true;
-      bendDomainToLocalhost = true;
-    };
-
-    config = {
-      adminuser = "admin";
-      adminpassFile = config.age.secrets."nextcloud-admin-pass".path;
-      dbuser = "nextcloud";
-      dbtype = "pgsql";
-      dbname = "nextcloud";
-      dbtableprefix = "oc_";
-      overwriteProtocol = "https";
-    };
-
-    extraOptions = {
-      overwrite.cli.url = "http://cloud.pub.solar";
-
-      installed = true;
-      default_phone_region = "+49";
-      mail_sendmailmode = "smtp";
-      mail_from_address = "nextcloud";
-      mail_smtpmode = "smtp";
-      mail_smtpauthtype = "PLAIN";
-      mail_domain = "pub.solar";
-      mail_smtpname = "admins@pub.solar";
-      mail_smtpsecure = "tls";
-      mail_smtpauth = 1;
-      mail_smtphost = "mail.greenbaum.zone";
-      mail_smtpport = "587";
-
-      # This is to allow connections to collabora and keycloak, among other services
-      # running on the same host
-      #
-      # https://docs.nextcloud.com/server/stable/admin_manual/configuration_server/config_sample_php_parameters.html?highlight=allow_local_remote_servers%20true
-      # https://github.com/ONLYOFFICE/onlyoffice-nextcloud/issues/293
-      allow_local_remote_servers = true;
-
-      enable_previews = true;
-      enabledPreviewProviders = [
-        "OC\\Preview\\PNG"
-        "OC\\Preview\\JPEG"
-        "OC\\Preview\\GIF"
-        "OC\\Preview\\BMP"
-        "OC\\Preview\\XBitmap"
-        "OC\\Preview\\Movie"
-        "OC\\Preview\\PDF"
-        "OC\\Preview\\MP3"
-        "OC\\Preview\\TXT"
-        "OC\\Preview\\MarkDown"
-      ];
-      preview_max_x = "1024";
-      preview_max_y = "768";
-      preview_max_scale_factor = "1";
-
-      auth.bruteforce.protection.enabled = true;
-      trashbin_retention_obligation = "auto,7";
-      skeletondirectory = "";
-      defaultapp = "file";
-      activity_expire_days = "14";
-      integrity.check.disabled = false;
-      updater.release.channel = "stable";
-      loglevel = 0;
-      maintenance_window_start = "1";
-      # maintenance = false;
-      app_install_overwrite = [
-        "pdfdraw"
-        "integration_whiteboard"
-      ];
-      htaccess.RewriteBase = "/";
-      theme = "";
-      simpleSignUpLink.shown = false;
-    };
-
-    phpOptions = {
-      "opcache.interned_strings_buffer" = "32";
-      # https://docs.nextcloud.com/server/latest/admin_manual/installation/server_tuning.html#:~:text=opcache.jit%20%3D%201255%20opcache.jit_buffer_size%20%3D%20128m
-      "opcache.jit" = "1255";
-      "opcache.jit_buffer_size" = "128M";
-    };
-
-    # Calculated with 4GiB RAM, 80MiB process size available on
-    # https://spot13.com/pmcalculator/
-    poolSettings = {
-      pm = "dynamic";
-      "pm.max_children" = "52";
-      "pm.max_requests" = "500";
-      "pm.max_spare_servers" = "39";
-      "pm.min_spare_servers" = "13";
-      "pm.start_servers" = "13";
-    };
-
-    caching.redis = true;
-    autoUpdateApps.enable = true;
-    database.createLocally = true;
-  };
-
-  services.restic.backups.nextcloud-droppie = {
-    paths = [
-      "/var/lib/nextcloud/data"
-      "/tmp/nextcloud-backup.sql"
-    ];
-    timerConfig = {
-      OnCalendar = "*-*-* 02:00:00 Etc/UTC";
-      # droppie will be offline if nachtigall misses the timer
-      Persistent = false;
-    };
-    initialize = true;
-    passwordFile = config.age.secrets."restic-repo-droppie".path;
-    repository = "sftp:yule@droppie.b12f.io:/media/internal/pub.solar";
-    backupPrepareCommand = ''
-      ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d nextcloud > /tmp/nextcloud-backup.sql
-    '';
-    backupCleanupCommand = ''
-      rm /tmp/nextcloud-backup.sql
-    '';
-    pruneOpts = [
-      "--keep-daily 7"
-      "--keep-weekly 4"
-      "--keep-monthly 3"
-    ];
-  };
-
-  services.restic.backups.nextcloud-storagebox = {
-    paths = [
-      "/var/lib/nextcloud/data"
-      "/tmp/nextcloud-backup.sql"
-    ];
-    timerConfig = {
-      OnCalendar = "*-*-* 04:00:00 Etc/UTC";
-    };
-    initialize = true;
-    passwordFile = config.age.secrets."restic-repo-storagebox".path;
-    repository = "sftp:u377325@u377325.your-storagebox.de:/backups";
-    backupPrepareCommand = ''
-      ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d nextcloud > /tmp/nextcloud-backup.sql
-    '';
-    backupCleanupCommand = ''
-      rm /tmp/nextcloud-backup.sql
-    '';
-    pruneOpts = [
-      "--keep-daily 7"
-      "--keep-weekly 4"
-      "--keep-monthly 3"
-    ];
-  };
-}
diff --git a/hosts/nachtigall/apps/nginx-prometheus-exporters.nix b/hosts/nachtigall/apps/nginx-prometheus-exporters.nix
deleted file mode 100644
index af5678c7..00000000
--- a/hosts/nachtigall/apps/nginx-prometheus-exporters.nix
+++ /dev/null
@@ -1,32 +0,0 @@
-{ config, flake, lib, ... }:
-let
-  # Find element in list config.services.matrix-synapse.settings.listeners
-  # that sets type = "metrics"
-  listenerWithMetrics = lib.findFirst
-    (listener:
-      listener.type == "metrics")
-    (throw "Found no matrix-synapse.settings.listeners.*.type containing string metrics")
-    config.services.matrix-synapse.settings.listeners
-  ;
-  synapseMetricsPort = "${toString listenerWithMetrics.port}";
-in
-{
-  age.secrets.nachtigall-metrics-nginx-basic-auth = {
-    file = "${flake.self}/secrets/nachtigall-metrics-nginx-basic-auth.age";
-    mode = "600";
-    owner = "nginx";
-  };
-  services.nginx.virtualHosts = {
-    "nachtigall.pub.solar" = {
-      enableACME = true;
-      addSSL = true;
-      basicAuthFile = "${config.age.secrets.nachtigall-metrics-nginx-basic-auth.path}";
-      locations."/metrics" = {
-        proxyPass = "http://127.0.0.1:${toString(config.services.prometheus.exporters.node.port)}";
-      };
-      locations."/_synapse/metrics" = {
-        proxyPass = "http://127.0.0.1:${synapseMetricsPort}";
-      };
-    };
-  };
-}
diff --git a/hosts/nachtigall/apps/obs-portal.nix b/hosts/nachtigall/apps/obs-portal.nix
deleted file mode 100644
index 0fd680dc..00000000
--- a/hosts/nachtigall/apps/obs-portal.nix
+++ /dev/null
@@ -1,140 +0,0 @@
-{ config
-, lib
-, pkgs
-, self
-, flake
-, ...
-}: let 
-  configPy = pkgs.writeText "obs-portal-config.py" ''
-DEBUG = False
-VERBOSE = DEBUG
-AUTO_RESTART = DEBUG
-LEAN_MODE = False
-FRONTEND_URL = None
-FRONTEND_HTTPS = True
-FRONTEND_DIR = "../frontend/build/"
-FRONTEND_CONFIG = {
-    "imprintUrl": "https://pub.solar/about",
-    "privacyPolicyUrl": "https://pub.solar/privacy",
-    "mapHome": {"zoom": 12, "latitude": 50.93, "longitude": 6.97},
-    "banner": {
-        "text": "This is an installation serving the Cologne/Bonn region run for Team OBSKöln by pub.solar n.e.V.",
-        "style": "info"
-    },
-}
-TILES_FILE = None
-ADDITIONAL_CORS_ORIGINS = None
-  '';
-
-  env = {
-    OBS_KEYCLOAK_URI = "auth.pub.solar";
-    OBS_PORTAL_URI = "obs-portal.pub.solar";
-
-    OBS_POSTGRES_MAX_OVERFLOW = "20";
-    OBS_POSTGRES_POOL_SIZE = "40";
-
-    OBS_HOST = "0.0.0.0";
-    OBS_PORT = "3000";
-    OBS_KEYCLOAK_URL = "https://auth.pub.solar/realms/pub.solar/";
-    OBS_KEYCLOAK_CLIENT_ID = "openbikesensor-portal";
-    OBS_DEDICATED_WORKER = "True";
-    OBS_DATA_DIR = "/data";
-    OBS_PROXIES_COUNT = "1";
-  };
-in {
-  age.secrets.obs-portal-env = {
-    file = "${flake.self}/secrets/obs-portal-env.age";
-    mode = "600";
-  };
-
-  age.secrets.obs-portal-database-env = {
-    file = "${flake.self}/secrets/obs-portal-database-env.age";
-    mode = "600";
-  };
-
-  systemd.services."docker-network-obs-portal" =
-    let
-      docker = config.virtualisation.oci-containers.backend;
-      dockerBin = "${pkgs.${docker}}/bin/${docker}";
-    in
-    {
-      serviceConfig.Type = "oneshot";
-      before = [ "docker-obs-portal.service" ];
-      script = ''
-        ${dockerBin} network inspect obs-portal-net >/dev/null 2>&1 || ${dockerBin} network create obs-portal-net --subnet 172.20.0.0/24
-      '';
-    };
-
-  services.nginx.virtualHosts."obs-portal.pub.solar" = {
-    enableACME = true;
-    forceSSL = true;
-
-    locations."/" = {
-      proxyWebsockets = true;
-      extraConfig = ''
-        proxy_pass http://127.0.0.1:3001;
-        proxy_set_header Host $host;
-      '';
-    };
-  };
-
-  virtualisation = {
-    oci-containers = {
-      backend = "docker";
-
-      containers."obs-portal" = {
-        image = "git.pub.solar/pub-solar/obs-portal:latest";
-        autoStart = true;
-        ports = [ "localhost:3001:${env.OBS_PORT}" ];
-
-        environment = env;
-        environmentFiles = [ config.age.secrets.obs-portal-env.path ];
-
-        volumes = [
-          "${configPy}:/opt/obs/api/config.py"
-          "/var/lib/obs-portal${env.OBS_DATA_DIR}:${env.OBS_DATA_DIR}"
-          "/var/lib/obs-portal/tiles/:/tiles"
-          "/var/lib/obs-portal/pbf/:/pbf"
-        ];
-
-        extraOptions = [
-          "--network=obs-portal-net"
-        ];
-      };
-
-      containers."obs-portal-worker" = {
-        image = "git.pub.solar/pub-solar/obs-portal:latest";
-        autoStart = true;
-
-        cmd = [ "python" "tools/process_track.py" ];
-
-        environment = env;
-        environmentFiles = [ config.age.secrets.obs-portal-env.path ];
-
-        volumes = [
-          "${configPy}:/opt/obs/api/config.py"
-          "/var/lib/obs-portal${env.OBS_DATA_DIR}:${env.OBS_DATA_DIR}"
-        ];
-
-        extraOptions = [
-          "--network=obs-portal-net"
-        ];
-      };
-
-      containers."obs-portal-db" = {
-        image = "openmaptiles/postgis:7.0";
-        autoStart = true;
-
-        environmentFiles = [ config.age.secrets.obs-portal-database-env.path ];
-
-        volumes = [
-          "/var/lib/postgres-obs-portal/data:/var/lib/postgresql/data"
-        ];
-
-        extraOptions = [
-          "--network=obs-portal-net"
-        ];
-      };
-    };
-  };
-}
diff --git a/hosts/nachtigall/apps/postgresql.nix b/hosts/nachtigall/apps/postgresql.nix
deleted file mode 100644
index 5ab56c64..00000000
--- a/hosts/nachtigall/apps/postgresql.nix
+++ /dev/null
@@ -1,17 +0,0 @@
-{ ... }:
-
-{
-  services.postgresql = {
-    enable = true;
-    enableTCPIP = true;
-  };
-
-  systemd.services.postgresql = {
-    after = [
-      "var-lib-postgresql.mount"
-    ];
-    requisite = [
-      "var-lib-postgresql.mount"
-    ];
-  };
-}
diff --git a/hosts/nachtigall/apps/prometheus-exporters.nix b/hosts/nachtigall/apps/prometheus-exporters.nix
deleted file mode 100644
index 585474a1..00000000
--- a/hosts/nachtigall/apps/prometheus-exporters.nix
+++ /dev/null
@@ -1,13 +0,0 @@
-{ config
-, ...
-}: {
-  services.prometheus = {
-    exporters = {
-      node = {
-        enable = true;
-        enabledCollectors = [ "systemd" ];
-        port = 9002;
-      };
-    };
-  };
-}
diff --git a/hosts/nachtigall/apps/promtail.nix b/hosts/nachtigall/apps/promtail.nix
deleted file mode 100644
index 10e641e6..00000000
--- a/hosts/nachtigall/apps/promtail.nix
+++ /dev/null
@@ -1,46 +0,0 @@
-{ config
-, lib
-, pkgs
-, flake
-, ...
-}: {
-  age.secrets.nachtigall-metrics-prometheus-basic-auth-password = {
-    file = "${flake.self}/secrets/nachtigall-metrics-prometheus-basic-auth-password.age";
-    mode = "600";
-    owner = "promtail";
-  };
-
-  services.promtail = {
-    enable = true;
-    configuration = {
-      server = {
-        http_listen_port = 9080;
-        grpc_listen_port = 0;
-      };
-      positions = {
-        filename = "/tmp/positions.yaml";
-      };
-      clients = [{
-        url = "https://flora-6.pub.solar/loki/api/v1/push";
-        basic_auth = {
-          username = "hakkonaut";
-          password_file = "${config.age.secrets.nachtigall-metrics-prometheus-basic-auth-password.path}";
-        };
-      }];
-      scrape_configs = [{
-        job_name = "journal";
-        journal = {
-          max_age = "24h";
-          labels = {
-            job = "systemd-journal";
-            host = "nachtigall";
-          };
-        };
-        relabel_configs = [{
-          source_labels = [ "__journal__systemd_unit" ];
-          target_label = "unit";
-        }];
-      }];
-    };
-  };
-}
diff --git a/hosts/nachtigall/backups.nix b/hosts/nachtigall/backups.nix
index 0e99c14e..e910d0bc 100644
--- a/hosts/nachtigall/backups.nix
+++ b/hosts/nachtigall/backups.nix
@@ -1,12 +1,34 @@
-{ flake, ... }: {
+{ config, flake, ... }:
+{
   age.secrets."restic-repo-droppie" = {
     file = "${flake.self}/secrets/restic-repo-droppie.age";
     mode = "400";
     owner = "root";
   };
-  age.secrets."restic-repo-storagebox" = {
-    file = "${flake.self}/secrets/restic-repo-storagebox.age";
+  age.secrets."restic-repo-storagebox-nachtigall" = {
+    file = "${flake.self}/secrets/restic-repo-storagebox-nachtigall.age";
     mode = "400";
     owner = "root";
   };
+  age.secrets.restic-repo-garage-nachtigall = {
+    file = "${flake.self}/secrets/restic-repo-garage-nachtigall.age";
+    mode = "400";
+    owner = "root";
+  };
+  age.secrets.restic-repo-garage-nachtigall-env = {
+    file = "${flake.self}/secrets/restic-repo-garage-nachtigall-env.age";
+    mode = "400";
+    owner = "root";
+  };
+
+  pub-solar-os.backups.repos.storagebox = {
+    passwordFile = config.age.secrets."restic-repo-storagebox-nachtigall".path;
+    repository = "sftp:u377325@u377325.your-storagebox.de:/backups";
+  };
+
+  pub-solar-os.backups.repos.garage = {
+    passwordFile = config.age.secrets."restic-repo-garage-nachtigall".path;
+    environmentFile = config.age.secrets."restic-repo-garage-nachtigall-env".path;
+    repository = "s3:https://buckets.pub.solar/nachtigall-backups";
+  };
 }
diff --git a/hosts/nachtigall/configuration.nix b/hosts/nachtigall/configuration.nix
index be33b2ba..b3177337 100644
--- a/hosts/nachtigall/configuration.nix
+++ b/hosts/nachtigall/configuration.nix
@@ -1,8 +1,10 @@
-{ flake
-, config
-, pkgs
-, ...
-}: {
+{
+  flake,
+  config,
+  pkgs,
+  ...
+}:
+{
   # Use GRUB2 as the boot loader.
   # We don't use systemd-boot because Hetzner uses BIOS legacy boot.
   boot.loader.systemd-boot.enable = false;
@@ -11,17 +13,21 @@
     efiSupport = false;
     mirroredBoots = [
       {
-        devices = [
-          "/dev/disk/by-id/nvme-SAMSUNG_MZVL21T0HCLR-00B00_S676NF0R517371"
-        ];
+        devices = [ "/dev/disk/by-id/nvme-SAMSUNG_MZVL21T0HCLR-00B00_S676NF0R517371" ];
         path = "/boot1";
       }
       {
-        devices = [
-          "/dev/disk/by-id/nvme-KXG60ZNV1T02_TOSHIBA_Z9NF704ZF9ZL"
-        ];
+        devices = [ "/dev/disk/by-id/nvme-KXG60ZNV1T02_TOSHIBA_Z9NF704ZF9ZL" ];
         path = "/boot2";
       }
+      {
+        devices = [ "/dev/disk/by-id/nvme-SAMSUNG_MZVL21T0HDLU-00B07_S77WNF0XA01902" ];
+        path = "/boot3";
+      }
+      {
+        devices = [ "/dev/disk/by-id/nvme-SAMSUNG_MZVL21T0HCLR-00B00_S676NU0W623944" ];
+        path = "/boot4";
+      }
     ];
     copyKernels = true;
   };
@@ -37,6 +43,11 @@
   # https://nixos.wiki/wiki/ZFS#declarative_mounting_of_ZFS_datasets
   systemd.services.zfs-mount.enable = false;
 
+  services.zfs.autoScrub = {
+    enable = true;
+    pools = [ "root_pool" ];
+  };
+
   # Declarative SSH private key
   age.secrets."nachtigall-root-ssh-key" = {
     file = "${flake.self}/secrets/nachtigall-root-ssh-key.age";
@@ -45,6 +56,80 @@
     owner = "root";
   };
 
+  # keycloak
+  age.secrets.keycloak-database-password = {
+    file = "${flake.self}/secrets/keycloak-database-password.age";
+    mode = "600";
+    #owner = "keycloak";
+  };
+
+  pub-solar-os.auth = {
+    enable = true;
+    database-password-file = config.age.secrets.keycloak-database-password.path;
+  };
+
+  # matrix-synapse
+  age.secrets."matrix-synapse-signing-key" = {
+    file = "${flake.self}/secrets/matrix-synapse-signing-key.age";
+    mode = "400";
+    owner = "matrix-synapse";
+  };
+
+  age.secrets."matrix-synapse-secret-config.yaml" = {
+    file = "${flake.self}/secrets/matrix-synapse-secret-config.yaml.age";
+    mode = "400";
+    owner = "matrix-synapse";
+  };
+
+  age.secrets."matrix-authentication-service-secret-config.yml" = {
+    file = "${flake.self}/secrets/matrix-authentication-service-secret-config.yml.age";
+    mode = "400";
+    owner = "matrix-authentication-service";
+  };
+
+  # matrix-appservice-irc
+  age.secrets."matrix-appservice-irc-mediaproxy-signing-key" = {
+    file = "${flake.self}/secrets/matrix-appservice-irc-mediaproxy-signing-key.jwk.age";
+    mode = "400";
+    owner = "matrix-appservice-irc";
+  };
+
+  pub-solar-os.matrix = {
+    enable = true;
+    appservice-irc.mediaproxy.signingKeyPath =
+      config.age.secrets."matrix-appservice-irc-mediaproxy-signing-key".path;
+    synapse = {
+      signing_key_path = config.age.secrets."matrix-synapse-signing-key".path;
+      extra-config-files = [
+        config.age.secrets."matrix-synapse-secret-config.yaml".path
+
+        # The registration file is automatically generated after starting the
+        # appservice for the first time.
+        # cp /var/lib/mautrix-telegram/telegram-registration.yaml \
+        #   /var/lib/matrix-synapse/
+        # chown matrix-synapse:matrix-synapse \
+        #   /var/lib/matrix-synapse/telegram-registration.yaml
+        "/var/lib/matrix-synapse/telegram-registration.yaml"
+      ];
+      app-service-config-files = [
+        "/var/lib/matrix-synapse/telegram-registration.yaml"
+        "/var/lib/matrix-appservice-irc/registration.yml"
+        # "/matrix-appservice-slack-registration.yaml"
+        # "/hookshot-registration.yml"
+        # "/matrix-mautrix-signal-registration.yaml"
+        # "/matrix-mautrix-telegram-registration.yaml"
+      ];
+    };
+    matrix-authentication-service.extra-config-files = [
+      config.age.secrets."matrix-authentication-service-secret-config.yml".path
+    ];
+  };
+
+  systemd.services.postgresql = {
+    after = [ "var-lib-postgresql.mount" ];
+    requisite = [ "var-lib-postgresql.mount" ];
+  };
+
   # This value determines the NixOS release with which your system is to be
   # compatible, in order to avoid breaking some software such as database
   # servers. You should change this only after NixOS release notes say you
diff --git a/hosts/nachtigall/default.nix b/hosts/nachtigall/default.nix
index 8e1455e0..31f6c373 100644
--- a/hosts/nachtigall/default.nix
+++ b/hosts/nachtigall/default.nix
@@ -1,42 +1,19 @@
 { flake, ... }:
 
 {
-  imports =
-    [
-      # Include the results of the hardware scan.
-      ./hardware-configuration.nix
-      ./configuration.nix
+  imports = [
+    # Include the results of the hardware scan.
+    ./hardware-configuration.nix
+    ./configuration.nix
 
-      ./networking.nix
-      ./wireguard.nix
-      ./backups.nix
-      ./apps/nginx.nix
+    ./networking.nix
+    ./prometheus-exporters.nix
+    ./wireguard.nix
+    ./backups.nix
+    "${flake.inputs.fork}/nixos/modules/services/matrix/matrix-authentication-service.nix"
+  ];
 
-      ./apps/collabora.nix
-      ./apps/coturn.nix
-      ./apps/forgejo.nix
-      ./apps/keycloak.nix
-      ./apps/mailman.nix
-      ./apps/mastodon.nix
-      ./apps/mediawiki.nix
-      ./apps/nextcloud.nix
-      ./apps/nginx-mastodon.nix
-      ./apps/nginx-mastodon-files.nix
-      ./apps/nginx-prometheus-exporters.nix
-      ./apps/nginx-website.nix
-      ./apps/nginx-website-miom.nix
-      ./apps/opensearch.nix
-      ./apps/owncast.nix
-      ./apps/postgresql.nix
-      ./apps/prometheus-exporters.nix
-      ./apps/promtail.nix
-      ./apps/searx.nix
-      ./apps/tmate.nix
-      ./apps/obs-portal.nix
-
-      ./apps/matrix/irc.nix
-      ./apps/matrix/mautrix-telegram.nix
-      ./apps/matrix/synapse.nix
-      ./apps/nginx-matrix.nix
-    ];
+  disabledModules = [
+    "services/matrix/matrix-authentication-service.nix"
+  ];
 }
diff --git a/hosts/nachtigall/hardware-configuration.nix b/hosts/nachtigall/hardware-configuration.nix
index 8fb74b7c..00097a1f 100644
--- a/hosts/nachtigall/hardware-configuration.nix
+++ b/hosts/nachtigall/hardware-configuration.nix
@@ -1,54 +1,64 @@
 # Do not modify this file!  It was generated by ‘nixos-generate-config’
 # and may be overwritten by future invocations.  Please make changes
 # to /etc/nixos/configuration.nix instead.
-{ config, lib, pkgs, modulesPath, ... }:
+{
+  config,
+  lib,
+  pkgs,
+  modulesPath,
+  ...
+}:
 
 {
-  imports =
-    [
-      (modulesPath + "/installer/scan/not-detected.nix")
-    ];
+  imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
 
-  boot.initrd.availableKernelModules = [ "ahci" "nvme" ];
+  boot.initrd.availableKernelModules = [
+    "ahci"
+    "nvme"
+  ];
   boot.initrd.kernelModules = [ ];
   boot.kernelModules = [ "kvm-amd" ];
   boot.extraModulePackages = [ ];
 
-  fileSystems."/" =
-    {
-      device = "root_pool/root";
-      fsType = "zfs";
-    };
+  fileSystems."/" = {
+    device = "root_pool/root";
+    fsType = "zfs";
+  };
 
-  fileSystems."/var/lib" =
-    {
-      device = "root_pool/data";
-      fsType = "zfs";
-    };
+  fileSystems."/var/lib" = {
+    device = "root_pool/data";
+    fsType = "zfs";
+  };
 
-  fileSystems."/var/lib/postgresql" =
-    {
-      device = "root_pool/data/postgresql";
-      fsType = "zfs";
-    };
+  fileSystems."/var/lib/postgresql" = {
+    device = "root_pool/data/postgresql";
+    fsType = "zfs";
+  };
 
-  fileSystems."/var/lib/docker" =
-    {
-      device = "root_pool/data/docker";
-      fsType = "zfs";
-    };
+  fileSystems."/var/lib/docker" = {
+    device = "root_pool/data/docker";
+    fsType = "zfs";
+  };
 
-  fileSystems."/boot1" =
-    {
-      device = "/dev/disk/by-uuid/5493-EFF5";
-      fsType = "vfat";
-    };
+  fileSystems."/boot1" = {
+    device = "/dev/disk/by-uuid/5493-EFF5";
+    fsType = "vfat";
+  };
 
-  fileSystems."/boot2" =
-    {
-      device = "/dev/disk/by-uuid/5494-BA1E";
-      fsType = "vfat";
-    };
+  fileSystems."/boot2" = {
+    device = "/dev/disk/by-uuid/5494-BA1E";
+    fsType = "vfat";
+  };
+
+  fileSystems."/boot3" = {
+    device = "/dev/disk/by-uuid/E4E4-88C7";
+    fsType = "vfat";
+  };
+
+  fileSystems."/boot4" = {
+    device = "/dev/disk/by-uuid/E76C-A8A0";
+    fsType = "vfat";
+  };
 
   swapDevices = [ ];
 
diff --git a/hosts/nachtigall/networking.nix b/hosts/nachtigall/networking.nix
index 91a09475..a27c3fe5 100644
--- a/hosts/nachtigall/networking.nix
+++ b/hosts/nachtigall/networking.nix
@@ -2,11 +2,11 @@
   config,
   pkgs,
   flake,
-  ... }:
+  ...
+}:
 {
 
   networking.hostName = "nachtigall";
-  networking.domain = "pub.solar";
   networking.hostId = "00000001";
 
   # Network (Hetzner uses static IP assignments, and we don't use DHCP here)
@@ -24,5 +24,8 @@
     }
   ];
   networking.defaultGateway = "138.201.80.65";
-  networking.defaultGateway6 = { address = "fe80::1"; interface = "enp35s0"; };
+  networking.defaultGateway6 = {
+    address = "fe80::1";
+    interface = "enp35s0";
+  };
 }
diff --git a/hosts/nachtigall/prometheus-exporters.nix b/hosts/nachtigall/prometheus-exporters.nix
new file mode 100644
index 00000000..ca17d1f5
--- /dev/null
+++ b/hosts/nachtigall/prometheus-exporters.nix
@@ -0,0 +1,53 @@
+{
+  config,
+  lib,
+  flake,
+  ...
+}:
+{
+  age.secrets."nextcloud-serverinfo-token" = {
+    file = "${flake.self}/secrets/nextcloud-serverinfo-token.age";
+    mode = "400";
+    owner = "nextcloud-exporter";
+  };
+
+  services.prometheus = {
+    exporters = {
+      # https://github.com/xperimental/nextcloud-exporter
+      nextcloud = {
+        enable = true;
+        openFirewall = true;
+        firewallFilter = "--in-interface wg-ssh --protocol tcp --match tcp --dport ${toString config.services.prometheus.exporters.nextcloud.port}";
+        url = "https://cloud.pub.solar";
+        tokenFile = config.age.secrets."nextcloud-serverinfo-token".path;
+        port = 9205;
+      };
+      # https://github.com/nginx/nginx-prometheus-exporter
+      nginx = {
+        enable = true;
+        openFirewall = true;
+        firewallFilter = "--in-interface wg-ssh --protocol tcp --match tcp --dport ${toString config.services.prometheus.exporters.nginx.port}";
+        port = 9113;
+      };
+      # https://github.com/hipages/php-fpm_exporter
+      #php-fpm = {
+      #  enable = true;
+      #  extraFlags = [
+      #    "--phpfpm.scrape-uri unix://${config.services.phpfpm.pools.nextcloud.socket};/status"
+      #  ];
+      #  group = "nginx";
+      #  openFirewall = true;
+      #  firewallFilter = "--in-interface wg-ssh --protocol tcp --match tcp --dport ${toString config.services.prometheus.exporters.php-fpm.port}";
+      #  port = 9253;
+      #};
+      # https://github.com/prometheus-community/postgres_exporter
+      postgres = {
+        enable = true;
+        dataSourceName = "user=postgres-exporter database=postgres host=/run/postgresql sslmode=disable";
+        openFirewall = true;
+        firewallFilter = "--in-interface wg-ssh --protocol tcp --match tcp --dport ${toString config.services.prometheus.exporters.postgres.port}";
+        port = 9187;
+      };
+    };
+  };
+}
diff --git a/hosts/nachtigall/wireguard.nix b/hosts/nachtigall/wireguard.nix
index 8544918c..7e9961e2 100644
--- a/hosts/nachtigall/wireguard.nix
+++ b/hosts/nachtigall/wireguard.nix
@@ -2,7 +2,8 @@
   config,
   pkgs,
   flake,
-  ... }:
+  ...
+}:
 {
   networking.firewall.allowedUDPPorts = [ 51820 ];
 
@@ -17,17 +18,32 @@
         "fd00:fae:fae:fae:fae:1::/96"
       ];
       privateKeyFile = config.age.secrets.wg-private-key.path;
-      peers = flake.self.logins.admins.wireguardDevices ++ [
-        { # flora-6.pub.solar
-          endpoint = "80.71.153.210:51820";
-          publicKey = "jtSR5G2P/nm9s8WrVc26Xc/SQLupRxyXE+5eIeqlsTU=";
-          allowedIPs = [ "10.7.6.2/32" "fd00:fae:fae:fae:fae:2::/96" ];
+      peers = flake.self.logins.wireguardDevices ++ [
+        {
+          # tankstelle.pub.solar
+          endpoint = "80.244.242.5:51820";
+          publicKey = "iRTlY1lB7nPXf2eXzX8ZZDkfMmXyGjff5/joccbP8Cg=";
+          allowedIPs = [
+            "10.7.6.4/32"
+            "fd00:fae:fae:fae:fae:4::/96"
+          ];
+        }
+        {
+          # trinkgenossin.pub.solar
+          publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4=";
+          allowedIPs = [
+            "10.7.6.5/32"
+            "fd00:fae:fae:fae:fae:5::/96"
+          ];
+          #endpoint = "85.215.152.22:51820";
+          endpoint = "[2a01:239:35d:f500::1]:51820";
+          persistentKeepalive = 15;
         }
       ];
     };
   };
 
-  services.openssh.listenAddresses = [ 
+  services.openssh.listenAddresses = [
     {
       addr = "10.7.6.1";
       port = 22;
diff --git a/hosts/tankstelle/backups.nix b/hosts/tankstelle/backups.nix
new file mode 100644
index 00000000..ea42f3bf
--- /dev/null
+++ b/hosts/tankstelle/backups.nix
@@ -0,0 +1,13 @@
+{ flake, ... }:
+{
+  age.secrets."restic-repo-droppie" = {
+    file = "${flake.self}/secrets/restic-repo-droppie.age";
+    mode = "400";
+    owner = "root";
+  };
+  age.secrets."restic-repo-storagebox-tankstelle" = {
+    file = "${flake.self}/secrets/restic-repo-storagebox-tankstelle.age";
+    mode = "400";
+    owner = "root";
+  };
+}
diff --git a/hosts/tankstelle/configuration.nix b/hosts/tankstelle/configuration.nix
new file mode 100644
index 00000000..39935440
--- /dev/null
+++ b/hosts/tankstelle/configuration.nix
@@ -0,0 +1,19 @@
+{
+  flake,
+  config,
+  pkgs,
+  ...
+}:
+{
+  imports = [ ./hardware-configuration.nix ];
+
+  boot.loader.systemd-boot.enable = true;
+  boot.loader.efi.canTouchEfiVariables = true;
+
+  # kernel same-page merging
+  hardware.ksm.enable = true;
+
+  boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
+
+  system.stateVersion = "23.11";
+}
diff --git a/hosts/tankstelle/default.nix b/hosts/tankstelle/default.nix
new file mode 100644
index 00000000..a379466b
--- /dev/null
+++ b/hosts/tankstelle/default.nix
@@ -0,0 +1,13 @@
+{ flake, ... }:
+
+{
+  imports = [
+    ./hardware-configuration.nix
+    ./configuration.nix
+
+    ./networking.nix
+    ./forgejo-actions-runner.nix
+    ./wireguard.nix
+    #./backups.nix
+  ];
+}
diff --git a/hosts/tankstelle/forgejo-actions-runner.nix b/hosts/tankstelle/forgejo-actions-runner.nix
new file mode 100644
index 00000000..d96e14f5
--- /dev/null
+++ b/hosts/tankstelle/forgejo-actions-runner.nix
@@ -0,0 +1,26 @@
+{
+  config,
+  flake,
+  ...
+}:
+{
+  age.secrets.tankstelle-forgejo-actions-runner-token = {
+    file = "${flake.self}/secrets/tankstelle-forgejo-actions-runner-token.age";
+    mode = "440";
+  };
+
+  # forgejo actions runner
+  # https://forgejo.org/docs/latest/admin/actions/
+  # https://docs.gitea.com/usage/actions/quickstart
+  services.gitea-actions-runner.instances = {
+    tankstelle = {
+      enable = true;
+      url = "https://git.pub.solar";
+      name = config.networking.hostName;
+      tokenFile = config.age.secrets.tankstelle-forgejo-actions-runner-token.path;
+      labels = [
+        "self-hosted:host://-self-hosted"
+      ];
+    };
+  };
+}
diff --git a/hosts/tankstelle/hardware-configuration.nix b/hosts/tankstelle/hardware-configuration.nix
new file mode 100644
index 00000000..ec9b465e
--- /dev/null
+++ b/hosts/tankstelle/hardware-configuration.nix
@@ -0,0 +1,41 @@
+# Do not modify this file!  It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations.  Please make changes
+# to /etc/nixos/configuration.nix instead.
+{
+  config,
+  lib,
+  pkgs,
+  modulesPath,
+  ...
+}:
+
+{
+  imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
+
+  boot.initrd.availableKernelModules = [
+    "ahci"
+    "xhci_pci"
+    "virtio_pci"
+    "sr_mod"
+    "virtio_blk"
+  ];
+  boot.initrd.kernelModules = [ ];
+  boot.kernelModules = [ "kvm-intel" ];
+  boot.extraModulePackages = [ ];
+
+  fileSystems."/" = {
+    device = "/dev/disk/by-uuid/17531ffc-46bd-4259-8287-2dea73804b5b";
+    fsType = "ext4";
+  };
+
+  fileSystems."/boot" = {
+    device = "/dev/disk/by-uuid/AF98-AA5C";
+    fsType = "vfat";
+  };
+
+  swapDevices = [ { device = "/dev/disk/by-uuid/7aee04b5-1ef9-43de-acb4-70ac1238b58a"; } ];
+
+  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+  powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand";
+  hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
+}
diff --git a/hosts/tankstelle/networking.nix b/hosts/tankstelle/networking.nix
new file mode 100644
index 00000000..8e893923
--- /dev/null
+++ b/hosts/tankstelle/networking.nix
@@ -0,0 +1,38 @@
+{
+  config,
+  pkgs,
+  flake,
+  ...
+}:
+{
+  networking = {
+    hostName = "tankstelle";
+    enableIPv6 = true;
+    defaultGateway = {
+      address = "80.244.242.1";
+      interface = "enp1s0";
+    };
+    defaultGateway6 = {
+      address = "2001:4d88:1ffa:26::1";
+      interface = "enp1s0";
+    };
+    nameservers = [
+      "95.129.51.51"
+      "80.244.244.244"
+    ];
+    interfaces."enp1s0" = {
+      ipv4.addresses = [
+        {
+          address = "80.244.242.5";
+          prefixLength = 29;
+        }
+      ];
+      ipv6.addresses = [
+        {
+          address = "2001:4d88:1ffa:26::5";
+          prefixLength = 64;
+        }
+      ];
+    };
+  };
+}
diff --git a/hosts/tankstelle/wireguard.nix b/hosts/tankstelle/wireguard.nix
new file mode 100644
index 00000000..0222a4b8
--- /dev/null
+++ b/hosts/tankstelle/wireguard.nix
@@ -0,0 +1,56 @@
+{
+  config,
+  pkgs,
+  flake,
+  ...
+}:
+{
+  networking.firewall.allowedUDPPorts = [ 51820 ];
+
+  age.secrets.wg-private-key.file = "${flake.self}/secrets/tankstelle-wg-private-key.age";
+
+  networking.wireguard.interfaces = {
+    wg-ssh = {
+      listenPort = 51820;
+      mtu = 1300;
+      ips = [
+        "10.7.6.4/32"
+        "fd00:fae:fae:fae:fae:4::/96"
+      ];
+      privateKeyFile = config.age.secrets.wg-private-key.path;
+      peers = flake.self.logins.wireguardDevices ++ [
+        {
+          # nachtigall.pub.solar
+          endpoint = "138.201.80.102:51820";
+          publicKey = "qzNywKY9RvqTnDO8eLik75/SHveaSk9OObilDzv+xkk=";
+          allowedIPs = [
+            "10.7.6.1/32"
+            "fd00:fae:fae:fae:fae:1::/96"
+          ];
+        }
+        {
+          # trinkgenossin.pub.solar
+          publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4=";
+          allowedIPs = [
+            "10.7.6.5/32"
+            "fd00:fae:fae:fae:fae:5::/96"
+          ];
+          #endpoint = "85.215.152.22:51820";
+          endpoint = "[2a01:239:35d:f500::1]:51820";
+          persistentKeepalive = 15;
+        }
+      ];
+    };
+  };
+
+  services.openssh.listenAddresses = [
+    {
+      addr = "10.7.6.4";
+      port = 22;
+    }
+    {
+      addr = "[fd00:fae:fae:fae:fae:4::]";
+      port = 22;
+    }
+  ];
+}
diff --git a/hosts/trinkgenossin/configuration.nix b/hosts/trinkgenossin/configuration.nix
new file mode 100644
index 00000000..f6cf06f8
--- /dev/null
+++ b/hosts/trinkgenossin/configuration.nix
@@ -0,0 +1,35 @@
+{
+  flake,
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+{
+  boot.loader.grub.enable = true;
+  boot.loader.grub.devices = [ "/dev/vda" ];
+
+  boot.kernelParams = [
+    "boot.shell_on_fail=1"
+    "ip=dhcp"
+  ];
+
+  # This option defines the first version of NixOS you have installed on this particular machine,
+  # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
+  #
+  # Most users should NEVER change this value after the initial install, for any reason,
+  # even if you've upgraded your system to a new NixOS release.
+  #
+  # This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
+  # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
+  # to actually do that.
+  #
+  # This value being lower than the current NixOS release does NOT mean your system is
+  # out of date, out of support, or vulnerable.
+  #
+  # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
+  # and migrated your data accordingly.
+  #
+  # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
+  system.stateVersion = "24.05"; # Did you read the comment?
+}
diff --git a/hosts/trinkgenossin/default.nix b/hosts/trinkgenossin/default.nix
new file mode 100644
index 00000000..0ef346c2
--- /dev/null
+++ b/hosts/trinkgenossin/default.nix
@@ -0,0 +1,13 @@
+{ flake, ... }:
+
+{
+  imports = [
+    ./hardware-configuration.nix
+    ./configuration.nix
+
+    ./networking.nix
+    ./wireguard.nix
+    ./forgejo-actions-runner.nix
+    #./backups.nix
+  ];
+}
diff --git a/hosts/trinkgenossin/forgejo-actions-runner.nix b/hosts/trinkgenossin/forgejo-actions-runner.nix
new file mode 100644
index 00000000..4e3588a9
--- /dev/null
+++ b/hosts/trinkgenossin/forgejo-actions-runner.nix
@@ -0,0 +1,73 @@
+{
+  config,
+  flake,
+  ...
+}:
+{
+  age.secrets."forgejo-actions-runner-token-miom" = {
+    file = "${flake.self}/secrets/trinkgenossin-forgejo-actions-runner-token-miom.age";
+    owner = "gitea-runner";
+    mode = "440";
+  };
+  age.secrets."forgejo-actions-runner-token-momo" = {
+    file = "${flake.self}/secrets/trinkgenossin-forgejo-actions-runner-token-momo.age";
+    owner = "gitea-runner";
+    mode = "440";
+  };
+  age.secrets."forgejo-actions-runner-token-pub-solar" = {
+    file = "${flake.self}/secrets/trinkgenossin-forgejo-actions-runner-token.age";
+    owner = "gitea-runner";
+    mode = "440";
+  };
+
+  # forgejo actions runner
+  # https://forgejo.org/docs/latest/admin/actions/
+  # https://docs.gitea.com/usage/actions/quickstart
+  services.gitea-actions-runner.instances = {
+    miom = {
+      enable = true;
+      url = "https://git.pub.solar";
+      name = config.networking.hostName;
+      tokenFile = config.age.secrets.forgejo-actions-runner-token-miom.path;
+      labels = [
+        # provide a debian 12 bookworm base with Node.js for actions
+        "debian-latest:docker://git.pub.solar/pub-solar/actions-base-image:20-bookworm"
+        # fake the ubuntu name, commonly used in actions examples
+        "ubuntu-latest:docker://git.pub.solar/pub-solar/actions-base-image:20-bookworm"
+        # alpine with Node.js
+        "alpine-latest:docker://node:20-alpine"
+      ];
+    };
+    momo = {
+      enable = true;
+      url = "https://git.pub.solar";
+      name = config.networking.hostName;
+      tokenFile = config.age.secrets.forgejo-actions-runner-token-momo.path;
+      labels = [
+        "self-hosted:host://-self-hosted"
+
+        # provide a debian 12 bookworm base with Node.js for actions
+        "debian-latest:docker://git.pub.solar/pub-solar/actions-base-image:20-bookworm"
+        # fake the ubuntu name, commonly used in actions examples
+        "ubuntu-latest:docker://git.pub.solar/pub-solar/actions-base-image:20-bookworm"
+        # alpine with Node.js
+        "alpine-latest:docker://node:20-alpine"
+      ];
+    };
+    # systemd does not like dashes in service unit names
+    pubsolar = {
+      enable = true;
+      url = "https://git.pub.solar";
+      name = config.networking.hostName;
+      tokenFile = config.age.secrets.forgejo-actions-runner-token-pub-solar.path;
+      labels = [
+        # provide a debian 12 bookworm base with Node.js for actions
+        "debian-latest:docker://git.pub.solar/pub-solar/actions-base-image:20-bookworm"
+        # fake the ubuntu name, commonly used in actions examples
+        "ubuntu-latest:docker://git.pub.solar/pub-solar/actions-base-image:20-bookworm"
+        # alpine with Node.js
+        "alpine-latest:docker://node:20-alpine"
+      ];
+    };
+  };
+}
diff --git a/hosts/trinkgenossin/hardware-configuration.nix b/hosts/trinkgenossin/hardware-configuration.nix
new file mode 100644
index 00000000..0d8b2d9b
--- /dev/null
+++ b/hosts/trinkgenossin/hardware-configuration.nix
@@ -0,0 +1,54 @@
+# Do not modify this file!  It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations.  Please make changes
+# to /etc/nixos/configuration.nix instead.
+{
+  config,
+  lib,
+  pkgs,
+  modulesPath,
+  ...
+}:
+
+{
+  imports = [ ];
+
+  boot.initrd.availableKernelModules = [
+    "ata_piix"
+    "uhci_hcd"
+    "virtio_pci"
+    "sr_mod"
+    "virtio_blk"
+    "virtio_net"
+  ];
+  boot.initrd.kernelModules = [ "dm-snapshot" ];
+  boot.kernelModules = [ "kvm-amd" ];
+  boot.extraModulePackages = [ ];
+
+  boot.initrd.luks.devices."cryptroot" = {
+    device = "/dev/disk/by-uuid/52a1fd17-63d7-4d0a-b7ff-74aceaf6085a";
+  };
+
+  fileSystems."/" = {
+    device = "/dev/disk/by-label/nixos";
+    fsType = "ext4";
+  };
+
+  fileSystems."/boot" = {
+    device = "/dev/disk/by-label/boot";
+    fsType = "ext4";
+  };
+
+  fileSystems."/var/lib/garage/data" = {
+    device = "/dev/disk/by-label/data";
+    fsType = "xfs";
+  };
+
+  fileSystems."/var/lib/garage/meta" = {
+    device = "/dev/disk/by-label/metadata";
+    fsType = "btrfs";
+  };
+
+  swapDevices = [ { device = "/dev/disk/by-label/swap"; } ];
+
+  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+}
diff --git a/hosts/trinkgenossin/networking.nix b/hosts/trinkgenossin/networking.nix
new file mode 100644
index 00000000..aa9a3780
--- /dev/null
+++ b/hosts/trinkgenossin/networking.nix
@@ -0,0 +1,15 @@
+{
+  config,
+  pkgs,
+  flake,
+  ...
+}:
+{
+  services.garage.settings.rpc_public_addr = "[2a01:239:35d:f500::1]:3901";
+
+  networking.hostName = "trinkgenossin";
+  networking.hostId = "00000003";
+
+  networking.enableIPv6 = true;
+  networking.useDHCP = true;
+}
diff --git a/hosts/trinkgenossin/wireguard.nix b/hosts/trinkgenossin/wireguard.nix
new file mode 100644
index 00000000..e879c5b7
--- /dev/null
+++ b/hosts/trinkgenossin/wireguard.nix
@@ -0,0 +1,86 @@
+{
+  config,
+  pkgs,
+  flake,
+  ...
+}:
+let
+  wireguardIPv4 = "10.7.6.5";
+  wireguardIPv6 = "fd00:fae:fae:fae:fae:5::";
+in
+{
+  networking.firewall.allowedUDPPorts = [ 51820 ];
+
+  age.secrets.wg-private-key.file = "${flake.self}/secrets/trinkgenossin-wg-private-key.age";
+
+  networking.wireguard.interfaces = {
+    wg-ssh = {
+      listenPort = 51820;
+      mtu = 1300;
+      ips = [
+        "${wireguardIPv4}/32"
+        "${wireguardIPv6}/96"
+      ];
+      privateKeyFile = config.age.secrets.wg-private-key.path;
+      peers = flake.self.logins.wireguardDevices ++ [
+        {
+          # nachtigall.pub.solar
+          endpoint = "138.201.80.102:51820";
+          publicKey = "qzNywKY9RvqTnDO8eLik75/SHveaSk9OObilDzv+xkk=";
+          allowedIPs = [
+            "10.7.6.1/32"
+            "fd00:fae:fae:fae:fae:1::/96"
+          ];
+        }
+        {
+          # metronom.pub.solar
+          endpoint = "49.13.236.167:51820";
+          publicKey = "zOSYGO7MfnOOUnzaTcWiKRQM0qqxR3JQrwx/gtEtHmo=";
+          allowedIPs = [
+            "10.7.6.3/32"
+            "fd00:fae:fae:fae:fae:3::/96"
+          ];
+          persistentKeepalive = 15;
+        }
+        {
+          # tankstelle.pub.solar
+          endpoint = "80.244.242.5:51820";
+          publicKey = "iRTlY1lB7nPXf2eXzX8ZZDkfMmXyGjff5/joccbP8Cg=";
+          allowedIPs = [
+            "10.7.6.4/32"
+            "fd00:fae:fae:fae:fae:4::/96"
+          ];
+        }
+        {
+          # delite.pub.solar
+          endpoint = "5.255.119.132:51820";
+          publicKey = "ZT2qGWgMPwHRUOZmTQHWCRX4m14YwOsiszjsA5bpc2k=";
+          allowedIPs = [
+            "10.7.6.6/32"
+            "fd00:fae:fae:fae:fae:6::/96"
+          ];
+        }
+        {
+          # blue-shell.pub.solar
+          endpoint = "194.13.83.205:51820";
+          publicKey = "bcrIpWrKc1M+Hq4ds3aN1lTaKE26f2rvXhd+93QrzR8=";
+          allowedIPs = [
+            "10.7.6.7/32"
+            "fd00:fae:fae:fae:fae:7::/96"
+          ];
+        }
+      ];
+    };
+  };
+
+  services.openssh.listenAddresses = [
+    {
+      addr = wireguardIPv4;
+      port = 22;
+    }
+    {
+      addr = "[${wireguardIPv6}]";
+      port = 22;
+    }
+  ];
+}
diff --git a/hosts/underground/configuration.nix b/hosts/underground/configuration.nix
new file mode 100644
index 00000000..49efdfef
--- /dev/null
+++ b/hosts/underground/configuration.nix
@@ -0,0 +1,81 @@
+{
+  flake,
+  config,
+  pkgs,
+  ...
+}:
+{
+  # Use GRUB2 as the boot loader.
+  boot.loader.grub = {
+    enable = true;
+    devices = [ "/dev/vda" ];
+  };
+
+  pub-solar-os.networking.domain = "test.pub.solar";
+
+  systemd.tmpfiles.rules = [ "f /tmp/dbf 1777 root root 10d password" ];
+
+  # keycloak
+  pub-solar-os.auth = {
+    enable = true;
+    database-password-file = "/tmp/dbf";
+  };
+  services.keycloak.database.createLocally = true;
+
+  # matrix-synapse
+  # test.pub.solar /.well-known is required for federation
+  services.nginx.virtualHosts."${config.pub-solar-os.networking.domain}" = {
+    default = true;
+    enableACME = true;
+    forceSSL = true;
+  };
+
+  age.secrets."staging-matrix-synapse-secret-config.yaml" = {
+    file = "${flake.self}/secrets/staging-matrix-synapse-secret-config.yaml.age";
+    mode = "400";
+    owner = "matrix-synapse";
+  };
+
+  age.secrets."staging-matrix-authentication-service-secret-config.yml" = {
+    file = "${flake.self}/secrets/staging-matrix-authentication-service-secret-config.yml.age";
+    mode = "400";
+    owner = "matrix-authentication-service";
+  };
+
+  # matrix-appservice-irc
+  age.secrets."matrix-appservice-irc-mediaproxy-signing-key" = {
+    file = "${flake.self}/secrets/staging-matrix-appservice-irc-mediaproxy-signing-key.jwk.age";
+    mode = "400";
+    owner = "matrix-appservice-irc";
+  };
+
+  pub-solar-os.matrix = {
+    enable = true;
+    appservice-irc.mediaproxy.signingKeyPath =
+      config.age.secrets."matrix-appservice-irc-mediaproxy-signing-key".path;
+    synapse = {
+      extra-config-files = [
+        config.age.secrets."staging-matrix-synapse-secret-config.yaml".path
+
+        # The registration file is automatically generated after starting the
+        # appservice for the first time.
+        # cp /var/lib/mautrix-telegram/telegram-registration.yaml \
+        #   /var/lib/matrix-synapse/
+        # chown matrix-synapse:matrix-synapse \
+        #   /var/lib/matrix-synapse/telegram-registration.yaml
+        #"/var/lib/matrix-synapse/telegram-registration.yaml"
+      ];
+      app-service-config-files = [
+        "/var/lib/matrix-appservice-irc/registration.yml"
+        #"/var/lib/matrix-synapse/telegram-registration.yaml"
+      ];
+    };
+    matrix-authentication-service.extra-config-files = [
+      config.age.secrets."staging-matrix-authentication-service-secret-config.yml".path
+    ];
+  };
+
+  services.openssh.openFirewall = true;
+
+  system.stateVersion = "24.05";
+}
diff --git a/hosts/underground/default.nix b/hosts/underground/default.nix
new file mode 100644
index 00000000..99fe5f92
--- /dev/null
+++ b/hosts/underground/default.nix
@@ -0,0 +1,16 @@
+{ flake, ... }:
+
+{
+  imports = [
+    # Include the results of the hardware scan.
+    ./hardware-configuration.nix
+    ./configuration.nix
+
+    ./networking.nix
+    "${flake.inputs.fork}/nixos/modules/services/matrix/matrix-authentication-service.nix"
+  ];
+
+  disabledModules = [
+    "services/matrix/matrix-authentication-service.nix"
+  ];
+}
diff --git a/hosts/underground/hardware-configuration.nix b/hosts/underground/hardware-configuration.nix
new file mode 100644
index 00000000..28ab939e
--- /dev/null
+++ b/hosts/underground/hardware-configuration.nix
@@ -0,0 +1,47 @@
+# Do not modify this file!  It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations.  Please make changes
+# to /etc/nixos/configuration.nix instead.
+{
+  config,
+  lib,
+  pkgs,
+  modulesPath,
+  ...
+}:
+
+{
+  imports = [
+    (modulesPath + "/profiles/qemu-guest.nix")
+  ];
+
+  boot.initrd.availableKernelModules = [
+    "ahci"
+    "xhci_pci"
+    "virtio_pci"
+    "virtio_scsi"
+    "sd_mod"
+    "sr_mod"
+  ];
+  boot.kernelModules = [ "kvm-intel" ];
+  boot.extraModulePackages = [ ];
+
+  boot.initrd.luks.devices."cryptroot" = {
+    device = "/dev/disk/by-label/cryptroot";
+  };
+
+  fileSystems."/" = {
+    device = "/dev/disk/by-label/root";
+    fsType = "ext4";
+  };
+
+  fileSystems."/boot" = {
+    device = "/dev/disk/by-label/boot";
+    fsType = "ext4";
+  };
+
+  swapDevices = [
+    { device = "/dev/disk/by-label/swap"; }
+  ];
+
+  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+}
diff --git a/hosts/underground/networking.nix b/hosts/underground/networking.nix
new file mode 100644
index 00000000..0f08a7e5
--- /dev/null
+++ b/hosts/underground/networking.nix
@@ -0,0 +1,30 @@
+{
+  config,
+  pkgs,
+  flake,
+  ...
+}:
+{
+
+  networking.hostName = "underground";
+
+  networking = {
+    defaultGateway = {
+      address = "80.244.242.1";
+      interface = "enp1s0";
+    };
+    nameservers = [
+      "95.129.51.51"
+      "80.244.244.244"
+    ];
+    interfaces.enp1s0 = {
+      useDHCP = false;
+      ipv4.addresses = [
+        {
+          address = "80.244.242.3";
+          prefixLength = 29;
+        }
+      ];
+    };
+  };
+}
diff --git a/lib/compat/default.nix b/lib/compat/default.nix
index 27068efe..b5d6a195 100644
--- a/lib/compat/default.nix
+++ b/lib/compat/default.nix
@@ -1,16 +1,16 @@
 let
-  lock = builtins.fromJSON (builtins.readFile builtins.path {
-    path = ../../flake.lock;
-    name = "lockPath";
-  });
+  lock = builtins.fromJSON (
+    builtins.readFile builtins.path {
+      path = ../../flake.lock;
+      name = "lockPath";
+    }
+  );
   flake =
     import
-      (
-        fetchTarball {
-          url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
-          sha256 = lock.nodes.flake-compat.locked.narHash;
-        }
-      )
+      (fetchTarball {
+        url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
+        sha256 = lock.nodes.flake-compat.locked.narHash;
+      })
       {
         src = builtins.path {
           path = ../../.;
diff --git a/lib/default.nix b/lib/default.nix
index e1b39cb3..3f14bf69 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -1,4 +1,10 @@
-{ self, lib, inputs, ... }: {
+{
+  self,
+  lib,
+  inputs,
+  ...
+}:
+{
   # Configuration common to all Linux systems
   flake = {
     lib =
diff --git a/lib/deploy.nix b/lib/deploy.nix
index 1de2801c..f94c83ee 100644
--- a/lib/deploy.nix
+++ b/lib/deploy.nix
@@ -1,75 +1,80 @@
 /*
- * The contents of this file are adapted from digga
- * https://github.com/divnix/digga
- *
- * Licensed under the MIT license
- */
+  The contents of this file are adapted from digga
+  https://github.com/divnix/digga
+
+  Licensed under the MIT license
+*/
 
 { lib, inputs }:
 let
-  # https://github.com/serokell/deploy-rs#overall-usage
-  system = "x86_64-linux";
-  pkgs = import inputs.nixpkgs { inherit system; };
-  deployPkgs = import inputs.nixpkgs {
-    inherit system;
-    overlays = [
-      inputs.deploy-rs.overlay
-      (self: super: { deploy-rs = { inherit (pkgs) deploy-rs; lib = super.deploy-rs.lib; }; })
-    ];
-  };
-  getFqdn = c:
+  getFqdn =
+    c:
     let
       net = c.config.networking;
       fqdn =
-        if (net ? domain) && (net.domain != null)
-        then "${net.hostName}.${net.domain}"
-        else net.hostName;
+        if (net ? domain) && (net.domain != null) then "${net.hostName}.${net.domain}" else net.hostName;
     in
     fqdn;
 in
 {
-  mkDeployNodes = systemConfigurations: extraConfig:
+  mkDeployNodes =
+    systemConfigurations: extraConfig:
     /*
-     *
-       Synopsis: mkNodes _systemConfigurations_ _extraConfig_
+      *
+        Synopsis: mkNodes _systemConfigurations_ _extraConfig_
 
-       Generate the `nodes` attribute expected by deploy-rs
-       where _systemConfigurations_ are `nodes`.
+        Generate the `nodes` attribute expected by deploy-rs
+        where _systemConfigurations_ are `nodes`.
 
-       _systemConfigurations_ should take the form of a flake's
-       _nixosConfigurations_. Note that deploy-rs does not currently support
-       deploying to darwin hosts.
+        _systemConfigurations_ should take the form of a flake's
+        _nixosConfigurations_. Note that deploy-rs does not currently support
+        deploying to darwin hosts.
 
-       _extraConfig_, if specified, will be merged into each of the
-       nodes' configurations.
+        _extraConfig_, if specified, will be merged into each of the
+        nodes' configurations.
 
-       Example _systemConfigurations_ input:
+        Example _systemConfigurations_ input:
 
-       ```
-       {
-       hostname-1 = {
-       fastConnection = true;
-       sshOpts = [ "-p" "25" ];
-       };
-       hostname-2 = {
-       sshOpts = [ "-p" "19999" ];
-       sshUser = "root";
-       };
-       }
-       ```
-     *
-     */
-    lib.recursiveUpdate
-      (lib.mapAttrs
-        (
-          _: c: {
-            hostname = getFqdn c;
-            profiles.system = {
-              user = "root";
-              path = deployPkgs.deploy-rs.lib.activate.nixos c;
-            };
-          }
-        )
-        systemConfigurations)
-      extraConfig;
+        ```
+        {
+        hostname-1 = {
+        fastConnection = true;
+        sshOpts = [ "-p" "25" ];
+        };
+        hostname-2 = {
+        sshOpts = [ "-p" "19999" ];
+        sshUser = "root";
+        };
+        }
+        ```
+      *
+    */
+    lib.recursiveUpdate (lib.mapAttrs (_: c: {
+      hostname = getFqdn c;
+      profiles.system =
+        let
+          system = c.pkgs.system;
+
+          # Unmodified nixpkgs
+          pkgs = import inputs.nixpkgs { inherit system; };
+
+          # nixpkgs with deploy-rs overlay but force the nixpkgs package
+          deployPkgs = import inputs.nixpkgs {
+            inherit system;
+            overlays = [
+              inputs.deploy-rs.overlay # or deploy-rs.overlays.default
+              (self: super: {
+                deploy-rs = {
+                  inherit (pkgs) deploy-rs;
+                  lib = super.deploy-rs.lib;
+                };
+              })
+            ];
+          };
+        in
+        {
+          user = "root";
+          path = deployPkgs.deploy-rs.lib.activate.nixos c;
+        };
+    }) systemConfigurations) extraConfig;
 }
diff --git a/logins/admins.nix b/logins/admins.nix
index 7bcdffb5..2c318744 100644
--- a/logins/admins.nix
+++ b/logins/admins.nix
@@ -10,7 +10,10 @@
       {
         # tuxnix
         publicKey = "fTvULvdsc92binFaBV+uWwFi33bi8InShcaPnoxUZEA=";
-        allowedIPs = [ "10.7.6.203/32" "fd00:fae:fae:fae:fae:203::/96" ];
+        allowedIPs = [
+          "10.7.6.203/32"
+          "fd00:fae:fae:fae:fae:203::/96"
+        ];
       }
     ];
   };
@@ -27,9 +30,29 @@
     } // sshPubKeys;
 
     wireguardDevices = [
-      { # stroopwafel
+      {
+        # stroopwafel
         publicKey = "NNb7T8Jmn+V2dTZ8T6Fcq7hGomHGDckKoV3kK2oAhSE=";
-        allowedIPs = [ "10.7.6.200/32" "fd00:fae:fae:fae:fae:200::/96" ];
+        allowedIPs = [
+          "10.7.6.200/32"
+          "fd00:fae:fae:fae:fae:200::/96"
+        ];
+      }
+      {
+        # chocolatebar
+        publicKey = "AS9w0zDUFLcH6IiF6T1vsyZPWPJ3p5fKsjIsM2AoZz8=";
+        allowedIPs = [
+          "10.7.6.205/32"
+          "fd00:fae:fae:fae:fae:205::/96"
+        ];
+      }
+      {
+        # biolimo
+        publicKey = "gnLq6KikFVVGxLxPW+3ZnreokEKLDoso+cUepPOZsBA=";
+        allowedIPs = [
+          "10.7.6.206/32"
+          "fd00:fae:fae:fae:fae:206::/96"
+        ];
       }
     ];
   };
@@ -42,9 +65,13 @@
 
     secretEncryptionKeys = sshPubKeys;
     wireguardDevices = [
-      { # judy
+      {
+        # judy
         publicKey = "I+gN7v1VXkAGoSir6L8aebtLbguvy5nAx1QVDTzdckk=";
-        allowedIPs = [ "10.7.6.202/32" "fd00:fae:fae:fae:fae:202::/96" ];
+        allowedIPs = [
+          "10.7.6.202/32"
+          "fd00:fae:fae:fae:fae:202::/96"
+        ];
       }
     ];
   };
@@ -52,20 +79,30 @@
   teutat3s = {
     sshPubKeys = {
       teutat3s-1 = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFro/k4Mgqyh8yV/7Zwjc0dv60ZM7bROBU9JNd99P/4co6fxPt1pJiU/pEz2Dax/HODxgcO+jFZfvPEuLMCeAl0= YubiKey #10593996 PIV Slot 9a";
+      teutat3s-2 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHcU6KPy4b1MQXd6EJhcYwbJu7E+0IrBZF/IP6T7gbMf teutat3s@dumpyourvms";
     };
 
     secretEncryptionKeys = {
       teutat3s-1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHcU6KPy4b1MQXd6EJhcYwbJu7E+0IrBZF/IP6T7gbMf teutat3s@dumpyourvms";
+      teutat3s-2 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPAsRdVYK0077cdtavmrRr6akrI68T1EDY4Hfv4+W86J teutat3s@ryzensun";
     };
 
     wireguardDevices = [
-      { # dumpyourvms
+      {
+        # dumpyourvms
         publicKey = "3UrVLQrwXnPAVXPiTAd7eM3fZYxnFSYgKAGpNMUwnUk=";
-        allowedIPs = [ "10.7.6.201/32" "fd00:fae:fae:fae:fae:201::/96" ];
+        allowedIPs = [
+          "10.7.6.201/32"
+          "fd00:fae:fae:fae:fae:201::/96"
+        ];
       }
-      { # ryzensun
+      {
+        # ryzensun
         publicKey = "oVF2/s7eIxyVjtG0MhKPx5SZ1JllZg+ZFVF2eVYtPGo=";
-        allowedIPs = [ "10.7.6.204/32" "fd00:fae:fae:fae:fae:204::/96" ];
+        allowedIPs = [
+          "10.7.6.204/32"
+          "fd00:fae:fae:fae:fae:204::/96"
+        ];
       }
     ];
   };
diff --git a/logins/default.nix b/logins/default.nix
index 374b513f..0493ca83 100644
--- a/logins/default.nix
+++ b/logins/default.nix
@@ -1,13 +1,21 @@
-{ lib, ... }: let
+{ lib, ... }:
+let
   admins = import ./admins.nix;
   robots = import ./robots.nix;
-in {
+in
+{
   flake = {
     logins = {
-      admins = lib.lists.foldl (logins: adminConfig: {
-        sshPubKeys = logins.sshPubKeys ++ (lib.attrsets.attrValues adminConfig.sshPubKeys);
-        wireguardDevices = logins.wireguardDevices ++ (if adminConfig ? "wireguardDevices" then adminConfig.wireguardDevices else []);
-      }) { sshPubKeys = []; wireguardDevices = []; } (lib.attrsets.attrValues admins);
+      admins = admins;
+      wireguardDevices = lib.lists.foldl (
+        wireguardDevices: adminConfig:
+        wireguardDevices ++ (if adminConfig ? "wireguardDevices" then adminConfig.wireguardDevices else [ ])
+      ) [ ] (lib.attrsets.attrValues admins);
+      sshPubKeys = lib.lists.foldl (
+        sshPubKeys: adminConfig:
+        sshPubKeys
+        ++ (if adminConfig ? "sshPubKeys" then lib.attrsets.attrValues adminConfig.sshPubKeys else [ ])
+      ) [ ] (lib.attrsets.attrValues admins);
       robots.sshPubKeys = lib.attrsets.attrValues robots;
     };
   };
diff --git a/logins/robots.nix b/logins/robots.nix
index 83b6cb89..5ca7311d 100644
--- a/logins/robots.nix
+++ b/logins/robots.nix
@@ -1,7 +1,8 @@
 {
   # Used for restic backups to droppie, a server run by @b12f
-  "root@droppie" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBZQSephFJU0NMbVbhwvVJ2/m6jcPYo1IsWCsoarqKin root@droppie";
+  "root@droppie" =
+    "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBZQSephFJU0NMbVbhwvVJ2/m6jcPYo1IsWCsoarqKin root@droppie";
 
-  # robot user on flora-6
-  "hakkonaut@flora-6" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGP5MvCwNRtCcP1pSDrn0XZTNlpOqYnjHDm9/OI4hECW hakkonaut@flora-6";
+  "hakkonaut" =
+    "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGP5MvCwNRtCcP1pSDrn0XZTNlpOqYnjHDm9/OI4hECW hakkonaut";
 }
diff --git a/modules/backups/default.nix b/modules/backups/default.nix
new file mode 100644
index 00000000..7c0de9b2
--- /dev/null
+++ b/modules/backups/default.nix
@@ -0,0 +1,383 @@
+{
+  flake,
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  utils = import "${flake.inputs.nixpkgs}/nixos/lib/utils.nix" {
+    inherit lib;
+    inherit config;
+    inherit pkgs;
+  };
+  # Type for a valid systemd unit option. Needed for correctly passing "timerConfig" to "systemd.timers"
+  inherit (utils.systemdUtils.unitOptions) unitOption;
+  inherit (lib)
+    literalExpression
+    mkOption
+    mkPackageOption
+    types
+    ;
+in
+{
+  options.pub-solar-os.backups = {
+    repos = mkOption {
+      description = ''
+        Configuration of Restic repositories.
+      '';
+      type = types.attrsOf (
+        types.submodule (
+          { name, ... }:
+          {
+            options = {
+              passwordFile = mkOption {
+                type = types.str;
+                description = ''
+                  Read the repository password from a file.
+                '';
+                example = "/etc/nixos/restic-password";
+              };
+
+              environmentFile = mkOption {
+                type = with types; nullOr str;
+                default = null;
+                description = ''
+                  Read repository secrets as environment variables from a file.
+                '';
+                example = "/etc/nixos/restic-env";
+              };
+
+              repository = mkOption {
+                type = with types; nullOr str;
+                default = null;
+                description = ''
+                  repository to backup to.
+                '';
+                example = "sftp:backup@192.168.1.100:/backups/${name}";
+              };
+            };
+          }
+        )
+      );
+
+      default = { };
+      example = {
+        remotebackup = {
+          repository = "sftp:backup@host:/backups/home";
+          passwordFile = "/etc/nixos/secrets/restic-password";
+          environmentFile = "/etc/nixos/secrets/restic-env";
+        };
+      };
+    };
+
+    resources = mkOption {
+      description = "resources required to exist before starting restic backup archive process";
+      default = { };
+      type = types.attrsOf (
+        types.submodule (
+          { ... }:
+          {
+            options = {
+              resourceCreateCommand = mkOption {
+                type = with types; nullOr str;
+                default = null;
+                description = ''
+                  A script that must run successfully to create the resource. Optional.
+                '';
+              };
+
+              resourceDestroyCommand = mkOption {
+                type = with types; nullOr str;
+                default = null;
+                description = ''
+                  A script that runs when the resource is destroyed. Optional.
+                '';
+              };
+            };
+          }
+        )
+      );
+    };
+
+    restic = mkOption {
+      description = ''
+        Periodic backups to create with Restic.
+      '';
+      type = types.attrsOf (
+        types.submodule (
+          { name, ... }:
+          {
+            options = {
+              resources = mkOption {
+                type = types.listOf types.str;
+                default = [ ];
+              };
+
+              paths = mkOption {
+                # This is nullable for legacy reasons only. We should consider making it a pure listOf
+                # after some time has passed since this comment was added.
+                type = types.nullOr (types.listOf types.str);
+                default = [ ];
+                description = ''
+                  Which paths to backup, in addition to ones specified via
+                  `dynamicFilesFrom`.  If null or an empty array and
+                  `dynamicFilesFrom` is also null, no backup command will be run.
+                   This can be used to create a prune-only job.
+                '';
+                example = [
+                  "/var/lib/postgresql"
+                  "/home/user/backup"
+                ];
+              };
+
+              exclude = mkOption {
+                type = types.listOf types.str;
+                default = [ ];
+                description = ''
+                  Patterns to exclude when backing up. See
+                  https://restic.readthedocs.io/en/latest/040_backup.html#excluding-files for
+                  details on syntax.
+                '';
+                example = [
+                  "/var/cache"
+                  "/home/*/.cache"
+                  ".git"
+                ];
+              };
+
+              timerConfig = mkOption {
+                type = types.nullOr (types.attrsOf unitOption);
+                default = {
+                  OnCalendar = "daily";
+                  Persistent = true;
+                };
+                description = ''
+                  When to run the backup. See {manpage}`systemd.timer(5)` for
+                  details. If null no timer is created and the backup will only
+                  run when explicitly started.
+                '';
+                example = {
+                  OnCalendar = "00:05";
+                  RandomizedDelaySec = "5h";
+                  Persistent = true;
+                };
+              };
+
+              user = mkOption {
+                type = types.str;
+                default = "root";
+                description = ''
+                  As which user the backup should run.
+                '';
+                example = "postgresql";
+              };
+
+              extraBackupArgs = mkOption {
+                type = types.listOf types.str;
+                default = [ ];
+                description = ''
+                  Extra arguments passed to restic backup.
+                '';
+                example = [ "--exclude-file=/etc/nixos/restic-ignore" ];
+              };
+
+              extraOptions = mkOption {
+                type = types.listOf types.str;
+                default = [ ];
+                description = ''
+                  Extra extended options to be passed to the restic --option flag.
+                '';
+                example = [ "sftp.command='ssh backup@192.168.1.100 -i /home/user/.ssh/id_rsa -s sftp'" ];
+              };
+
+              initialize = mkOption {
+                type = types.bool;
+                default = false;
+                description = ''
+                  Create the repository if it doesn't exist.
+                '';
+              };
+
+              pruneOpts = mkOption {
+                type = types.listOf types.str;
+                default = [ ];
+                description = ''
+                  A list of options (--keep-\* et al.) for 'restic forget
+                  --prune', to automatically prune old snapshots.  The
+                  'forget' command is run *after* the 'backup' command, so
+                  keep that in mind when constructing the --keep-\* options.
+                '';
+                example = [
+                  "--keep-daily 7"
+                  "--keep-weekly 5"
+                  "--keep-monthly 12"
+                  "--keep-yearly 75"
+                ];
+              };
+
+              runCheck = mkOption {
+                type = types.bool;
+                default = (builtins.length config.pub-solar-os.backups.restic.${name}.checkOpts > 0);
+                defaultText = literalExpression ''builtins.length config.services.backups.${name}.checkOpts > 0'';
+                description = "Whether to run the `check` command with the provided `checkOpts` options.";
+                example = true;
+              };
+
+              checkOpts = mkOption {
+                type = types.listOf types.str;
+                default = [ ];
+                description = ''
+                  A list of options for 'restic check'.
+                '';
+                example = [ "--with-cache" ];
+              };
+
+              dynamicFilesFrom = mkOption {
+                type = with types; nullOr str;
+                default = null;
+                description = ''
+                  A script that produces a list of files to back up.  The
+                  results of this command are given to the '--files-from'
+                  option. The result is merged with paths specified via `paths`.
+                '';
+                example = "find /home/matt/git -type d -name .git";
+              };
+
+              backupPrepareCommand = mkOption {
+                type = with types; nullOr str;
+                default = null;
+                description = ''
+                  A script that must run before starting the backup process.
+                '';
+              };
+
+              backupCleanupCommand = mkOption {
+                type = with types; nullOr str;
+                default = null;
+                description = ''
+                  A script that must run after finishing the backup process.
+                '';
+              };
+
+              package = mkPackageOption pkgs "restic" { };
+
+              createWrapper = lib.mkOption {
+                type = lib.types.bool;
+                default = true;
+                description = ''
+                  Whether to generate and add a script to the system path, that has the same environment variables set
+                  as the systemd service. This can be used to e.g. mount snapshots or perform other opterations, without
+                  having to manually specify most options.
+                '';
+              };
+            };
+          }
+        )
+      );
+      default = { };
+      example = {
+        localbackup = {
+          paths = [ "/home" ];
+          exclude = [ "/home/*/.cache" ];
+          initialize = true;
+        };
+        remotebackup = {
+          paths = [ "/home" ];
+          extraOptions = [
+            "sftp.command='ssh backup@host -i /etc/nixos/secrets/backup-private-key -s sftp'"
+          ];
+          timerConfig = {
+            OnCalendar = "00:05";
+            RandomizedDelaySec = "5h";
+          };
+        };
+      };
+    };
+  };
+
+  config =
+    let
+      repos = config.pub-solar-os.backups.repos;
+      restic = config.pub-solar-os.backups.restic;
+      resources = config.pub-solar-os.backups.resources;
+
+      repoNames = builtins.attrNames repos;
+      resourceNames = builtins.attrNames resources;
+      backupNames = builtins.attrNames restic;
+
+      createResourceService = resourceName: {
+        name = "restic-backups-resource-${resourceName}";
+        value = {
+          serviceConfig =
+            let
+              createResourceApp = pkgs.writeShellApplication {
+                name = "create-resource-${resourceName}";
+                text = resources."${resourceName}".resourceCreateCommand;
+              };
+              destroyResourceApp = pkgs.writeShellApplication {
+                name = "destroy-resource-${resourceName}";
+                text = resources."${resourceName}".resourceDestroyCommand;
+              };
+
+            in
+            {
+              Type = "oneshot";
+              ExecStart = lib.mkIf (
+                resources."${resourceName}".resourceCreateCommand != null
+              ) "${createResourceApp}/bin/create-resource-${resourceName}";
+              ExecStop = lib.mkIf (
+                resources."${resourceName}".resourceDestroyCommand != null
+              ) "${destroyResourceApp}/bin/destroy-resource-${resourceName}";
+              RemainAfterExit = true;
+            };
+          unitConfig.StopWhenUnneeded = true;
+        };
+      };
+
+      createResourceDependency = resourceName: backupName: repoName: {
+        name = "restic-backups-${backupName}-${repoName}";
+        value = {
+          after = [ "restic-backups-resource-${resourceName}.service" ];
+          requires = [ "restic-backups-resource-${resourceName}.service" ];
+
+          serviceConfig.PrivateTmp = lib.mkForce false;
+          unitConfig = {
+            JoinsNamespaceOf = [ "restic-backups-resource-${resourceName}.service" ];
+          };
+        };
+      };
+
+      createResourceDependencies =
+        backupName:
+        map (
+          repoName:
+          map (resourceName: createResourceDependency resourceName backupName repoName)
+            restic."${backupName}".resources
+        ) repoNames;
+
+      createBackups =
+        backupName:
+        map (repoName: {
+          name = "${backupName}-${repoName}";
+          value = lib.attrsets.filterAttrs (key: val: (key != "resources")) (
+            repos."${repoName}" // restic."${backupName}"
+          );
+        }) repoNames;
+    in
+    {
+      systemd.services =
+        (builtins.listToAttrs (map createResourceService resourceNames))
+        // (builtins.listToAttrs (lib.lists.flatten (map createResourceDependencies backupNames)));
+
+      services.restic.backups = builtins.listToAttrs (lib.lists.flatten (map createBackups backupNames));
+
+      # Used for pub-solar-os.backups.repos.storagebox
+      programs.ssh.knownHosts = {
+        "u377325.your-storagebox.de".publicKey =
+          "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA5EB5p/5Hp3hGW1oHok+PIOH9Pbn7cnUiGmUEBrCVjnAw+HrKyN8bYVV0dIGllswYXwkG/+bgiBlE6IVIBAq+JwVWu1Sss3KarHY3OvFJUXZoZyRRg/Gc/+LRCE7lyKpwWQ70dbelGRyyJFH36eNv6ySXoUYtGkwlU5IVaHPApOxe4LHPZa/qhSRbPo2hwoh0orCtgejRebNtW5nlx00DNFgsvn8Svz2cIYLxsPVzKgUxs8Zxsxgn+Q/UvR7uq4AbAhyBMLxv7DjJ1pc7PJocuTno2Rw9uMZi1gkjbnmiOh6TTXIEWbnroyIhwc8555uto9melEUmWNQ+C+PwAK+MPw==";
+        "[u377325.your-storagebox.de]:23".publicKey =
+          "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIICf9svRenC/PLKIL9nk6K/pxQgoiFC41wTNvoIncOxs";
+      };
+    };
+}
diff --git a/modules/caddy/default.nix b/modules/caddy/default.nix
new file mode 100644
index 00000000..9d3edf40
--- /dev/null
+++ b/modules/caddy/default.nix
@@ -0,0 +1,22 @@
+{
+  config,
+  lib,
+  pkgs,
+  flake,
+  ...
+}:
+{
+  services.caddy = {
+    enable = lib.mkForce true;
+    group = config.pub-solar-os.authentication.robot.username;
+    email = config.pub-solar-os.adminEmail;
+    enableReload = true;
+    globalConfig = lib.mkForce ''
+      grace_period 60s
+    '';
+  };
+  networking.firewall.allowedTCPPorts = [
+    80
+    443
+  ];
+}
diff --git a/hosts/nachtigall/apps/collabora.nix b/modules/collabora/default.nix
similarity index 66%
rename from hosts/nachtigall/apps/collabora.nix
rename to modules/collabora/default.nix
index 1edebee4..6fdc592e 100644
--- a/hosts/nachtigall/apps/collabora.nix
+++ b/modules/collabora/default.nix
@@ -1,10 +1,12 @@
-{ config
-, lib
-, pkgs
-, self
-, ...
-}: {
-  services.nginx.virtualHosts."collabora.pub.solar" = {
+{
+  config,
+  lib,
+  pkgs,
+  self,
+  ...
+}:
+{
+  services.nginx.virtualHosts."collabora.${config.pub-solar-os.networking.domain}" = {
     enableACME = true;
     forceSSL = true;
 
@@ -24,16 +26,14 @@
       containers."collabora" = {
         image = "collabora/code";
         autoStart = true;
-        ports = [
-          "127.0.0.1:9980:9980"
-        ];
+        ports = [ "127.0.0.1:9980:9980" ];
         extraOptions = [
           "--cap-add=MKNOD"
           "--pull=always"
         ];
         environment = {
-          server_name = "collabora.pub.solar";
-          aliasgroup1 = "https://cloud.pub.solar:443";
+          server_name = "collabora.${config.pub-solar-os.networking.domain}";
+          aliasgroup1 = "https://cloud.${config.pub-solar-os.networking.domain}:443";
           DONT_GEN_SSL_CERT = "1";
           extra_params = "--o:ssl.enable=false --o:ssl.termination=true";
           SLEEPFORDEBUGGER = "0";
diff --git a/modules/core/default.nix b/modules/core/default.nix
new file mode 100644
index 00000000..8f921e4c
--- /dev/null
+++ b/modules/core/default.nix
@@ -0,0 +1,59 @@
+{
+  pkgs,
+  config,
+  flake,
+  lib,
+  ...
+}:
+{
+  imports = [
+    ./logging.nix
+    ./nix.nix
+    ./networking.nix
+    ./terminal-tooling.nix
+    ./users.nix
+  ];
+
+  options.pub-solar-os =
+    let
+      inherit (lib) mkOption types;
+    in
+    {
+      adminEmail = mkOption {
+        description = "Email address to use for administrative stuff like ACME";
+        type = types.str;
+        default = "admins@pub.solar";
+      };
+
+      privacyPolicyUrl = mkOption {
+        description = "URL of the privacy policy. Used to link there from applications";
+        type = types.str;
+        default = "https://pub.solar/privacy";
+      };
+
+      imprintUrl = mkOption {
+        description = "URL of the imprint. Used to link there from applications";
+        type = types.str;
+        default = "https://pub.solar/about";
+      };
+    };
+
+  config = {
+    environment = {
+      # Just a couple of global packages to make our lives easier
+      systemPackages = with pkgs; [
+        git
+        vim
+        wget
+      ];
+    };
+
+    # Select internationalization properties
+    console = {
+      font = "Lat2-Terminus16";
+      keyMap = "us";
+    };
+
+    time.timeZone = "Etc/UTC";
+  };
+}
diff --git a/modules/core/logging.nix b/modules/core/logging.nix
new file mode 100644
index 00000000..fddea1f8
--- /dev/null
+++ b/modules/core/logging.nix
@@ -0,0 +1,12 @@
+{
+  config,
+  pkgs,
+  lib,
+  flake,
+  ...
+}:
+{
+  services.journald.extraConfig = ''
+    MaxRetentionSec=3day
+  '';
+}
diff --git a/modules/core/networking.nix b/modules/core/networking.nix
new file mode 100644
index 00000000..27b3b5cb
--- /dev/null
+++ b/modules/core/networking.nix
@@ -0,0 +1,103 @@
+{
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+{
+  options.pub-solar-os.networking =
+    let
+      inherit (lib) mkOption types;
+    in
+    {
+      domain = mkOption {
+        description = "domain on which all services should run. This defaults to pub.solar";
+        type = types.str;
+        default = "pub.solar";
+      };
+
+      defaultInterface = mkOption {
+        description = "Network interface which should be used as the default internet-connected one";
+        type = types.nullOr types.str;
+      };
+    };
+
+  config = {
+
+    # Don't expose SSH via public interfaces
+    networking.firewall.interfaces.wg-ssh.allowedTCPPorts = [ 22 ];
+
+    # Setting this value breaks Matrix -> NextPush integration because
+    # matrix-synapse doesn't like it if nachtigall.pub.solar resolves to localhost.
+    #networking.domain = config.pub-solar-os.networking.domain;
+
+    networking.hosts = {
+      "10.7.6.1" = [ "nachtigall.wg.${config.pub-solar-os.networking.domain}" ];
+      "10.7.6.3" = [ "metronom.wg.${config.pub-solar-os.networking.domain}" ];
+      "10.7.6.4" = [ "tankstelle.wg.${config.pub-solar-os.networking.domain}" ];
+      "10.7.6.5" = [ "trinkgenossin.wg.${config.pub-solar-os.networking.domain}" ];
+      "10.7.6.6" = [ "delite.wg.${config.pub-solar-os.networking.domain}" ];
+      "10.7.6.7" = [ "blue-shell.wg.${config.pub-solar-os.networking.domain}" ];
+      "fd00:fae:fae:fae:fae:1::" = [ "nachtigall.wg.${config.pub-solar-os.networking.domain}" ];
+      "fd00:fae:fae:fae:fae:3::" = [ "metronom.wg.${config.pub-solar-os.networking.domain}" ];
+      "fd00:fae:fae:fae:fae:4::" = [ "tankstelle.wg.${config.pub-solar-os.networking.domain}" ];
+      "fd00:fae:fae:fae:fae:5::" = [ "trinkgenossin.wg.${config.pub-solar-os.networking.domain}" ];
+      "fd00:fae:fae:fae:fae:6::" = [ "delite.wg.${config.pub-solar-os.networking.domain}" ];
+      "fd00:fae:fae:fae:fae:7::" = [ "blue-shell.wg.${config.pub-solar-os.networking.domain}" ];
+    };
+
+    services.openssh = {
+      enable = true;
+      openFirewall = lib.mkDefault false;
+      settings = {
+        PermitRootLogin = "prohibit-password";
+        PasswordAuthentication = false;
+        # Add back openssh MACs that got removed from defaults
+        # for backwards compatibility
+        #
+        # NixOS default openssh MACs have changed to use "encrypt-then-mac" only.
+        # This breaks compatibilty with clients that do not offer these MACs. For
+        # compatibility reasons, we add back the old defaults.
+        # See: https://github.com/NixOS/nixpkgs/pull/231165
+        #
+        # https://blog.stribik.technology/2015/01/04/secure-secure-shell.html
+        # https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67
+        Macs = [
+          "hmac-sha2-512-etm@openssh.com"
+          "hmac-sha2-256-etm@openssh.com"
+          "umac-128-etm@openssh.com"
+          "hmac-sha2-512"
+          "hmac-sha2-256"
+          "umac-128@openssh.com"
+        ];
+      };
+    };
+
+    # These nameservers land in resolved.conf as 'DNS=<list>'
+    networking.nameservers = [
+      "193.110.81.0#dns0.eu"
+      "185.253.5.0#dns0.eu"
+      "9.9.9.9#dns.quad9.net"
+      "149.112.112.112#dns.quad9.net"
+      "2a0f:fc80::#dns0.eu"
+      "2a0f:fc81::#dns0.eu"
+      "2620:fe::fe#dns.quad9.net"
+      "2620:fe::9#dns.quad9.net"
+    ];
+    services.resolved = {
+      enable = true;
+      dnsovertls = "true";
+      # default value in nixos module
+      dnssec = "false";
+      domains = [
+        "~."
+      ];
+      fallbackDns = [
+        "5.1.66.255#dot.ffmuc.net"
+        "185.150.99.255#dot.ffmuc.net"
+        "2001:678:e68:f000::#dot.ffmuc.net"
+        "2001:678:ed0:f000::#dot.ffmuc.net"
+      ];
+    };
+  };
+}
diff --git a/modules/nix.nix b/modules/core/nix.nix
similarity index 60%
rename from modules/nix.nix
rename to modules/core/nix.nix
index 4585a04f..eca6351b 100644
--- a/modules/nix.nix
+++ b/modules/core/nix.nix
@@ -1,11 +1,26 @@
-{ config
-, pkgs
-, lib
-, flake
-, ...
-}: {
-  nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
-  ];
+{
+  config,
+  pkgs,
+  lib,
+  flake,
+  ...
+}:
+{
+  nixpkgs.config = lib.mkDefault {
+    allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ ];
+    permittedInsecurePackages = [ "olm-3.2.16" ];
+  };
+
+  system.activationScripts.diff-closures = {
+    text = ''
+      if [[ -e /run/current-system ]]; then
+        ${config.nix.package}/bin/nix store diff-closures \
+          /run/current-system "$systemConfig" \
+          --extra-experimental-features nix-command
+      fi
+    '';
+    supportsDryActivation = true;
+  };
 
   nix = {
     # Use default version alias for nix package
@@ -25,7 +40,10 @@
       # Prevents impurities in builds
       sandbox = true;
       # Give root and @wheel special privileges with nix
-      trusted-users = [ "root" "@wheel" ];
+      trusted-users = [
+        "root"
+        "@wheel"
+      ];
       # Allow only group wheel to connect to the nix daemon
       allowed-users = [ "@wheel" ];
     };
@@ -41,7 +59,7 @@
 
     nixPath = [
       "nixpkgs=${flake.inputs.nixpkgs}"
-      "nixos-config=${../lib/compat/nixos}"
+      "nixos-config=${../../lib/compat/nixos}"
       "home-manager=${flake.inputs.home-manager}"
     ];
   };
diff --git a/modules/core/terminal-tooling.nix b/modules/core/terminal-tooling.nix
new file mode 100644
index 00000000..7dbb66c6
--- /dev/null
+++ b/modules/core/terminal-tooling.nix
@@ -0,0 +1,33 @@
+{ flake, lib, ... }:
+{
+  home-manager.users = (
+    lib.attrsets.foldlAttrs (
+      acc: name: value:
+      acc
+      // {
+        ${name} = {
+          programs.git.enable = true;
+          programs.starship.enable = true;
+          programs.bash = {
+            enable = true;
+            historyControl = [
+              "ignoredups"
+              "ignorespace"
+            ];
+          };
+          programs.neovim = {
+            enable = true;
+            vimAlias = true;
+            viAlias = true;
+            defaultEditor = true;
+            # configure = {
+            #   packages.myVimPackages = with pkgs.vimPlugins; {
+            #     start = [vim-nix vim-surrund rainbow];
+            #   };
+            # };
+          };
+        };
+      }
+    ) { } flake.self.logins.admins
+  );
+}
diff --git a/modules/core/users.nix b/modules/core/users.nix
new file mode 100644
index 00000000..49ecabe7
--- /dev/null
+++ b/modules/core/users.nix
@@ -0,0 +1,93 @@
+{
+  flake,
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+{
+  options.pub-solar-os.authentication =
+    let
+      inherit (lib) mkOption types;
+    in
+    {
+      root.initialHashedPassword = mkOption {
+        description = "Hashed password of the root account";
+        type = types.str;
+        default = "$y$j9T$bIN6GjQkmPMllOcQsq52K0$q0Z5B5.KW/uxXK9fItB8H6HO79RYAcI/ZZdB0Djke32";
+      };
+
+      robot.username = mkOption {
+        description = "username for the robot user";
+        type = types.str;
+        default = "hakkonaut";
+      };
+
+      robot.sshPubKeys = mkOption {
+        description = "SSH Keys to use for the robot user";
+        type = types.listOf types.str;
+        default = flake.self.logins.robots.sshPubKeys;
+      };
+    };
+
+  config = {
+    users.users =
+      (lib.attrsets.foldlAttrs (
+        acc: name: value:
+        acc
+        // {
+          ${name} = {
+            name = name;
+            group = name;
+            extraGroups = [
+              "wheel"
+              "docker"
+            ];
+            isNormalUser = true;
+            openssh.authorizedKeys.keys = lib.attrsets.attrValues value.sshPubKeys;
+          };
+        }
+      ) { } flake.self.logins.admins)
+      // {
+        # TODO: Remove when we stop locking ourselves out.
+        root.openssh.authorizedKeys.keys = flake.self.logins.sshPubKeys;
+        root.initialHashedPassword = config.pub-solar-os.authentication.root.initialHashedPassword;
+
+        ${config.pub-solar-os.authentication.robot.username} = {
+          description = "CI and automation user";
+          home = "/home/${config.pub-solar-os.authentication.robot.username}";
+          createHome = true;
+          useDefaultShell = true;
+          uid = 1100;
+          group = "${config.pub-solar-os.authentication.robot.username}";
+          isSystemUser = true;
+          openssh.authorizedKeys.keys = config.pub-solar-os.authentication.robot.sshPubKeys;
+        };
+      };
+
+    home-manager.users = (
+      lib.attrsets.foldlAttrs (
+        acc: name: value:
+        acc
+        // {
+          ${name} = {
+            home.stateVersion = "23.05";
+          };
+        }
+      ) { } flake.self.logins.admins
+    );
+
+    users.groups =
+      (lib.attrsets.foldlAttrs (
+        acc: name: value:
+        acc // { "${name}" = { }; }
+      ) { } flake.self.logins.admins)
+      // {
+        ${config.pub-solar-os.authentication.robot.username} = {
+          gid = 1100;
+        };
+      };
+
+    security.sudo.wheelNeedsPassword = false;
+  };
+}
diff --git a/hosts/nachtigall/apps/coturn.nix b/modules/coturn/default.nix
similarity index 72%
rename from hosts/nachtigall/apps/coturn.nix
rename to modules/coturn/default.nix
index 93bea420..b47329ea 100644
--- a/hosts/nachtigall/apps/coturn.nix
+++ b/modules/coturn/default.nix
@@ -1,4 +1,9 @@
-{ flake, config, lib, ... }:
+{
+  flake,
+  config,
+  lib,
+  ...
+}:
 {
   age.secrets."coturn-static-auth-secret" = {
     file = "${flake.self}/secrets/coturn-static-auth-secret.age";
@@ -13,14 +18,18 @@
     min-port = 49000;
     max-port = 50000;
     use-auth-secret = true;
-    static-auth-secret-file = "/run/agenix/coturn-static-auth-secret";
-    realm = "turn.pub.solar";
+    static-auth-secret-file = config.age.secrets."coturn-static-auth-secret".path;
+    realm = "turn.${config.pub-solar-os.networking.domain}";
     cert = "${config.security.acme.certs.${realm}.directory}/full.pem";
     pkey = "${config.security.acme.certs.${realm}.directory}/key.pem";
     extraConfig =
       let
-        externalIPv4s = lib.strings.concatMapStringsSep "\n" ({ address, ... }: "external-ip=${address}") config.networking.interfaces.enp35s0.ipv4.addresses;
-        externalIPv6s = lib.strings.concatMapStringsSep "\n" ({ address, ... }: "external-ip=${address}") config.networking.interfaces.enp35s0.ipv6.addresses;
+        externalIPv4s = lib.strings.concatMapStringsSep "\n" (
+          { address, ... }: "external-ip=${address}"
+        ) config.networking.interfaces.enp35s0.ipv4.addresses;
+        externalIPv6s = lib.strings.concatMapStringsSep "\n" (
+          { address, ... }: "external-ip=${address}"
+        ) config.networking.interfaces.enp35s0.ipv6.addresses;
       in
       ''
         ${externalIPv4s}
@@ -61,35 +70,42 @@
         denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
         denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff
       '';
-
   };
 
   networking.firewall = {
     interfaces.enp35s0 =
       let
-        range = with config.services.coturn; [{
-          from = min-port;
-          to = max-port;
-        }];
+        range = with config.services.coturn; [
+          {
+            from = min-port;
+            to = max-port;
+          }
+        ];
       in
       {
         allowedUDPPortRanges = range;
-        allowedUDPPorts = [ 3478 5349 ];
+        allowedUDPPorts = [
+          3478
+          5349
+        ];
         allowedTCPPortRanges = [ ];
-        allowedTCPPorts = [ 3478 5349 ];
+        allowedTCPPorts = [
+          3478
+          5349
+        ];
       };
   };
 
   # get a certificate
   security.acme.certs.${config.services.coturn.realm} = {
-    /* insert here the right configuration to obtain a certificate */
+    # insert here the right configuration to obtain a certificate
     postRun = "systemctl restart coturn.service";
     group = "turnserver";
   };
   services.nginx.virtualHosts.${config.services.coturn.realm} = {
     enableACME = true;
     addSSL = true;
-    globalRedirect = "pub.solar";
+    globalRedirect = "${config.pub-solar-os.networking.domain}";
   };
 
   users.users.nginx.extraGroups = [ "turnserver" ];
diff --git a/modules/default.nix b/modules/default.nix
deleted file mode 100644
index b8a037db..00000000
--- a/modules/default.nix
+++ /dev/null
@@ -1,39 +0,0 @@
-{ self, ... }:
-{
-  flake = {
-    nixosModules = rec {
-      nix = import ./nix.nix;
-      networking = import ./networking.nix;
-      unlock-zfs-on-boot = import ./unlock-zfs-on-boot.nix;
-      docker = import ./docker.nix;
-      terminal-tooling = import ./terminal-tooling.nix;
-      users = import ./users.nix;
-
-      core = { pkgs, ... }: {
-        imports = [
-          nix
-          networking
-          terminal-tooling
-          users
-        ];
-
-        environment = {
-          # Just a couple of global packages to make our lives easier
-          systemPackages = with pkgs; [ git vim wget ];
-        };
-
-        # Select internationalization properties
-        console = {
-          font = "Lat2-Terminus16";
-          keyMap = "us";
-        };
-
-        time.timeZone = "Etc/UTC";
-
-        home-manager.users.${self.username} = {
-          home.stateVersion = "23.05";
-        };
-      };
-    };
-  };
-}
diff --git a/modules/docker.nix b/modules/docker/default.nix
similarity index 92%
rename from modules/docker.nix
rename to modules/docker/default.nix
index 5cb90230..c7b3fc43 100644
--- a/modules/docker.nix
+++ b/modules/docker/default.nix
@@ -1,4 +1,5 @@
-{ pkgs, ... }: {
+{ pkgs, ... }:
+{
   virtualisation.docker = {
     enable = true;
     extraOptions = ''
diff --git a/modules/forgejo-actions-runner/default.nix b/modules/forgejo-actions-runner/default.nix
new file mode 100644
index 00000000..bbf25e29
--- /dev/null
+++ b/modules/forgejo-actions-runner/default.nix
@@ -0,0 +1,68 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  cfg = config.services.gitea-actions-runner;
+in
+{
+
+  config = lib.mkIf (cfg.instances != { }) {
+    # Label configuration on gitea-actions-runner instance requires either docker or podman
+    virtualisation.docker.enable = true;
+
+    # Trust docker bridge interface traffic
+    # Needed for the docker runner to communicate with the act_runner cache
+    networking.firewall.trustedInterfaces = [ "br-+" ];
+
+    users.users.gitea-runner = {
+      home = "/var/lib/gitea-runner";
+      useDefaultShell = true;
+      group = "gitea-runner";
+      # Required to interact with nix daemon
+      extraGroups = [
+        "wheel"
+        "docker"
+      ];
+      isSystemUser = true;
+    };
+
+    users.groups.gitea-runner = { };
+
+    systemd.tmpfiles.rules =
+      [
+        "d '/var/lib/gitea-runner' 0770 gitea-runner gitea-runner - -"
+      ]
+      ++ lib.mapAttrsToList (
+        name: instance: "d '/var/lib/gitea-runner/${name}' 0770 gitea-runner gitea-runner - -"
+      ) cfg.instances;
+
+    systemd.services = lib.concatMapAttrs (name: instance: {
+      "gitea-runner-${name}" = {
+        serviceConfig.DynamicUser = lib.mkForce false;
+        path = with pkgs; [
+          coreutils
+          openssh
+          gnupg
+          bash
+          curl
+          gawk
+          gitMinimal
+          gnused
+          nodejs_22
+          wget
+          cachix
+          jq
+          nix
+          docker
+        ];
+      };
+    }) cfg.instances;
+
+    services.gitea-actions-runner = {
+      package = pkgs.forgejo-runner;
+    };
+  };
+}
diff --git a/hosts/nachtigall/apps/forgejo.nix b/modules/forgejo/default.nix
similarity index 80%
rename from hosts/nachtigall/apps/forgejo.nix
rename to modules/forgejo/default.nix
index 397503d9..f47c5851 100644
--- a/hosts/nachtigall/apps/forgejo.nix
+++ b/modules/forgejo/default.nix
@@ -1,9 +1,11 @@
-{ config
-, lib
-, pkgs
-, flake
-, ...
-}: {
+{
+  config,
+  lib,
+  pkgs,
+  flake,
+  ...
+}:
+{
   age.secrets.forgejo-database-password = {
     file = "${flake.self}/secrets/forgejo-database-password.age";
     mode = "600";
@@ -29,7 +31,7 @@
     user = "gitea";
   };
 
-  services.nginx.virtualHosts."git.pub.solar" = {
+  services.nginx.virtualHosts."git.${config.pub-solar-os.networking.domain}" = {
     enableACME = true;
     forceSSL = true;
 
@@ -52,7 +54,7 @@
     isSystemUser = true;
   };
 
-  users.groups.gitea = {};
+  users.groups.gitea = { };
 
   # Expose SSH port only for forgejo SSH
   networking.firewall.interfaces.enp35s0.allowedTCPPorts = [ 2223 ];
@@ -63,6 +65,7 @@
 
   services.forgejo = {
     enable = true;
+    package = pkgs.forgejo;
     user = "gitea";
     group = "gitea";
     database = {
@@ -73,13 +76,13 @@
     };
     stateDir = "/var/lib/forgejo";
     lfs.enable = true;
-    mailerPasswordFile = config.age.secrets.forgejo-mailer-password.path;
+    secrets.mailer.PASSWD = config.age.secrets.forgejo-mailer-password.path;
     settings = {
       DEFAULT.APP_NAME = "pub.solar git server";
 
       server = {
-        ROOT_URL = "https://git.pub.solar";
-        DOMAIN = "git.pub.solar";
+        ROOT_URL = "https://git.${config.pub-solar-os.networking.domain}";
+        DOMAIN = "git.${config.pub-solar-os.networking.domain}";
         HTTP_ADDR = "127.0.0.1";
         HTTP_PORT = 3000;
         START_SSH_SERVER = true;
@@ -92,7 +95,7 @@
       mailer = {
         ENABLED = true;
         PROTOCOL = "smtps";
-        SMTP_ADDR = "mail.greenbaum.zone";
+        SMTP_ADDR = "mail.pub.solar";
         SMTP_PORT = 465;
         FROM = ''"pub.solar git server" <forgejo@pub.solar>'';
         USER = "admins@pub.solar";
@@ -123,7 +126,7 @@
 
       # https://forgejo.org/docs/latest/admin/config-cheat-sheet/#webhook-webhook
       webhook = {
-        ALLOWED_HOST_LIST = "loopback,external,*.pub.solar";
+        ALLOWED_HOST_LIST = "loopback,external,*.${config.pub-solar-os.networking.domain}";
       };
 
       # See https://forgejo.org/docs/latest/admin/actions/
@@ -139,6 +142,12 @@
         LOGIN_REMEMBER_DAYS = 365;
       };
 
+      # See https://docs.gitea.com/administration/config-cheat-sheet#migrations-migrations
+      migrations = {
+        # This allows migrations from the same forgejo instance
+        ALLOW_LOCALNETWORKS = true;
+      };
+
       # https://forgejo.org/docs/next/admin/config-cheat-sheet/#indexer-indexer
       indexer = {
         REPO_INDEXER_ENABLED = true;
@@ -161,7 +170,7 @@
   # gitea gitconfig
   programs.gnupg.agent = {
     enable = true;
-    pinentryFlavor = "curses";
+    pinentryPackage = pkgs.pinentry-curses;
   };
   # Required to make gpg work without a graphical environment?
   # otherwise generating a new gpg key fails with this error:
@@ -171,42 +180,16 @@
     GPG_TTY = "$(tty)";
   };
 
-  services.restic.backups.forgejo-droppie = {
-    paths = [
-      "/var/lib/forgejo"
-      "/tmp/forgejo-backup.sql"
-    ];
-    timerConfig = {
-      OnCalendar = "*-*-* 02:00:00 Etc/UTC";
-      # droppie will be offline if nachtigall misses the timer
-      Persistent = false;
-    };
-    initialize = true;
-    passwordFile = config.age.secrets."restic-repo-droppie".path;
-    repository = "sftp:yule@droppie.b12f.io:/media/internal/pub.solar";
-    backupPrepareCommand = ''
-      ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d gitea > /tmp/forgejo-backup.sql
-    '';
-    backupCleanupCommand = ''
-      rm /tmp/forgejo-backup.sql
-    '';
-    pruneOpts = [
-      "--keep-daily 7"
-      "--keep-weekly 4"
-      "--keep-monthly 3"
-    ];
-  };
-
   services.restic.backups.forgejo-storagebox = {
     paths = [
       "/var/lib/forgejo"
       "/tmp/forgejo-backup.sql"
     ];
     timerConfig = {
-      OnCalendar = "*-*-* 04:20:00 Etc/UTC";
+      OnCalendar = "*-*-* 23:00:00 Etc/UTC";
     };
     initialize = true;
-    passwordFile = config.age.secrets."restic-repo-storagebox".path;
+    passwordFile = config.age.secrets."restic-repo-storagebox-nachtigall".path;
     repository = "sftp:u377325@u377325.your-storagebox.de:/backups";
     backupPrepareCommand = ''
       ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d gitea > /tmp/forgejo-backup.sql
@@ -214,10 +197,5 @@
     backupCleanupCommand = ''
       rm /tmp/forgejo-backup.sql
     '';
-    pruneOpts = [
-      "--keep-daily 7"
-      "--keep-weekly 4"
-      "--keep-monthly 3"
-    ];
   };
 }
diff --git a/modules/garage/default.nix b/modules/garage/default.nix
new file mode 100644
index 00000000..57dceee6
--- /dev/null
+++ b/modules/garage/default.nix
@@ -0,0 +1,142 @@
+{
+  config,
+  lib,
+  pkgs,
+  flake,
+  ...
+}:
+{
+  age.secrets."garage-rpc-secret" = {
+    file = "${flake.self}/secrets/garage-rpc-secret.age";
+    mode = "400";
+  };
+
+  age.secrets."garage-admin-token" = {
+    file = "${flake.self}/secrets/garage-admin-token.age";
+    mode = "400";
+  };
+
+  age.secrets."acme-namecheap-env" = {
+    file = "${flake.self}/secrets/acme-namecheap-env.age";
+    mode = "400";
+  };
+
+  networking.firewall.allowedTCPPorts = [
+    3900
+    3901
+    3902
+  ];
+
+  networking.firewall.interfaces.wg-ssh.allowedTCPPorts = [ 3903 ];
+
+  security.acme = {
+    defaults = {
+      # LEGO_DISABLE_CNAME_SUPPORT=true set here to fix issues with CNAME
+      # detection, as we use wildcard DNS for garage
+      environmentFile = config.age.secrets.acme-namecheap-env.path;
+    };
+    certs = {
+      # Wildcard certificate gets created automatically
+      "buckets.${config.pub-solar-os.networking.domain}" = {
+        # disable http challenge
+        webroot = null;
+        # enable dns challenge
+        dnsProvider = "namecheap";
+      };
+      # Wildcard certificate gets created automatically
+      "web.${config.pub-solar-os.networking.domain}" = {
+        # disable http challenge
+        webroot = null;
+        # enable dns challenge
+        dnsProvider = "namecheap";
+      };
+    };
+  };
+
+  services.nginx = {
+    upstreams.s3_backend.servers = {
+      "[::1]:3900" = { };
+    };
+    upstreams.web_backend.servers = {
+      "[::1]:3902" = { };
+    };
+    virtualHosts."buckets.${config.pub-solar-os.networking.domain}" = {
+      serverAliases = [ "*.buckets.${config.pub-solar-os.networking.domain}" ];
+
+      enableACME = true;
+      forceSSL = true;
+
+      locations."/" = {
+        proxyPass = "http://s3_backend";
+        extraConfig = ''
+          client_max_body_size 64m;
+          proxy_max_temp_file_size 0;
+        '';
+      };
+    };
+    virtualHosts."web.${config.pub-solar-os.networking.domain}" = {
+      serverAliases = [ "*.web.${config.pub-solar-os.networking.domain}" ];
+
+      enableACME = true;
+      forceSSL = true;
+
+      locations."/" = {
+        proxyPass = "http://web_backend";
+      };
+    };
+  };
+
+  services.garage = {
+    enable = true;
+    package = pkgs.garage_1_1_0;
+    settings = {
+      data_dir = "/var/lib/garage/data";
+      metadata_dir = "/var/lib/garage/meta";
+      db_engine = "lmdb";
+      replication_factor = 3;
+      compression_level = 2;
+      rpc_bind_addr = "[::]:3901";
+      s3_api = {
+        s3_region = "eu-central";
+        api_bind_addr = "[::]:3900";
+        root_domain = ".buckets.${config.pub-solar-os.networking.domain}";
+      };
+      s3_web = {
+        bind_addr = "[::]:3902";
+        root_domain = ".web.${config.pub-solar-os.networking.domain}";
+        index = "index.html";
+      };
+      admin = {
+        api_bind_addr = "[::]:3903";
+      };
+    };
+  };
+
+  users.users.garage = {
+    isSystemUser = true;
+    home = "/var/lib/garage";
+    group = "garage";
+  };
+
+  users.groups.garage = { };
+
+  # Adapted from https://git.clan.lol/clan/clan-core/src/commit/23a9e35c665ff531fe1193dcc47056432fbbeacf/clanModules/garage/default.nix
+  # Disabled DynamicUser https://github.com/NixOS/nixpkgs/blob/nixos-24.05/nixos/modules/services/web-servers/garage.nix
+  # for mounts + permissions to work
+  systemd.services.garage = {
+    serviceConfig = {
+      user = "garage";
+      group = "garage";
+      DynamicUser = false;
+      LoadCredential = [
+        "rpc_secret_path:${config.age.secrets.garage-rpc-secret.path}"
+        "admin_token_path:${config.age.secrets.garage-admin-token.path}"
+      ];
+      Environment = [
+        "GARAGE_ALLOW_WORLD_READABLE_SECRETS=true"
+        "GARAGE_RPC_SECRET_FILE=%d/rpc_secret_path"
+        "GARAGE_ADMIN_TOKEN_FILE=%d/admin_token_path"
+      ];
+    };
+  };
+}
diff --git a/hosts/flora-6/apps/grafana.nix b/modules/grafana/default.nix
similarity index 50%
rename from hosts/flora-6/apps/grafana.nix
rename to modules/grafana/default.nix
index ceb63773..36095f09 100644
--- a/hosts/flora-6/apps/grafana.nix
+++ b/modules/grafana/default.nix
@@ -1,40 +1,102 @@
-{ config
-, lib
-, pkgs
-, flake
-, ...
-}: {
+{
+  config,
+  lib,
+  pkgs,
+  flake,
+  ...
+}:
+{
   age.secrets.grafana-admin-password = {
     file = "${flake.self}/secrets/grafana-admin-password.age";
-    mode = "644";
+    mode = "440";
     owner = "grafana";
   };
   age.secrets.grafana-smtp-password = {
     file = "${flake.self}/secrets/grafana-smtp-password.age";
-    mode = "644";
+    mode = "440";
     owner = "grafana";
   };
   age.secrets.grafana-keycloak-client-secret = {
     file = "${flake.self}/secrets/grafana-keycloak-client-secret.age";
-    mode = "644";
+    mode = "440";
     owner = "grafana";
   };
 
   environment.etc = {
+    "grafana-dashboards/nextcloud.json" = {
+      source = ./grafana-dashboards/nextcloud.json;
+      group = "grafana";
+      user = "grafana";
+    };
     "grafana-dashboards/node-exporter-full_rev33.json" = {
       source = ./grafana-dashboards/node-exporter-full_rev33.json;
       group = "grafana";
       user = "grafana";
     };
+    "grafana-dashboards/nginx.json" = {
+      source = ./grafana-dashboards/nginx.json;
+      group = "grafana";
+      user = "grafana";
+    };
+    "grafana-dashboards/postgres-overview.json" = {
+      source = ./grafana-dashboards/postgres-overview.json;
+      group = "grafana";
+      user = "grafana";
+    };
     "grafana-dashboards/synapse.json" = {
       source = ./grafana-dashboards/synapse.json;
       group = "grafana";
       user = "grafana";
     };
+    "grafana-dashboards/grafana-garage-dashboard-prometheus.json" = {
+      source = ./grafana-dashboards/grafana-garage-dashboard-prometheus.json;
+      group = "grafana";
+      user = "grafana";
+    };
+    "grafana-dashboards/loki/loki-chunks.json" = {
+      source = ./grafana-dashboards/loki/loki-chunks.json;
+      group = "grafana";
+      user = "grafana";
+    };
+    "grafana-dashboards/loki/loki-deletion.json" = {
+      source = ./grafana-dashboards/loki/loki-deletion.json;
+      group = "grafana";
+      user = "grafana";
+    };
+    "grafana-dashboards/loki/loki-operational.json" = {
+      source = ./grafana-dashboards/loki/loki-operational.json;
+      group = "grafana";
+      user = "grafana";
+    };
+    "grafana-dashboards/loki/loki-reads.json" = {
+      source = ./grafana-dashboards/loki/loki-reads.json;
+      group = "grafana";
+      user = "grafana";
+    };
+    "grafana-dashboards/loki/loki-retention.json" = {
+      source = ./grafana-dashboards/loki/loki-retention.json;
+      group = "grafana";
+      user = "grafana";
+    };
+    "grafana-dashboards/loki/loki-writes.json" = {
+      source = ./grafana-dashboards/loki/loki-writes.json;
+      group = "grafana";
+      user = "grafana";
+    };
+  };
+
+  services.nginx.virtualHosts."grafana.${config.pub-solar-os.networking.domain}" = {
+    enableACME = true;
+    forceSSL = true;
+    locations."/".proxyPass =
+      "http://127.0.0.1:${toString config.services.grafana.settings.server.http_port}";
   };
 
   services.grafana = {
     enable = true;
+    declarativePlugins = with pkgs.grafanaPlugins; [
+      grafana-lokiexplore-app
+    ];
     settings = {
       server = {
         # Listening Address
@@ -42,18 +104,18 @@
         # and Port
         http_port = 3000;
         # Grafana needs to know on which domain and URL it's running
-        domain = "grafana.pub.solar";
-        root_url = "https://grafana.pub.solar";
+        domain = "grafana.${config.pub-solar-os.networking.domain}";
+        root_url = "https://grafana.${config.pub-solar-os.networking.domain}";
         enable_gzip = true;
       };
       smtp = {
         enabled = true;
-        host = "mail.greenbaum.zone:465";
+        host = "mail.pub.solar:465";
         user = "admins@pub.solar";
         password = "\$__file{${config.age.secrets.grafana-smtp-password.path}}";
         from_address = "no-reply@pub.solar";
         from_name = "grafana.pub.solar";
-        ehlo_identity = "flora-6.pub.solar";
+        ehlo_identity = "grafana.pub.solar";
       };
       security = {
         admin_email = "crew@pub.solar";
@@ -69,9 +131,9 @@
         email_attribute_path = "email";
         login_attribute_path = "preferred_username";
         name_attribute_path = "full_name";
-        auth_url = "https://auth.pub.solar/realms/pub.solar/protocol/openid-connect/auth";
-        token_url = "https://auth.pub.solar/realms/pub.solar/protocol/openid-connect/token";
-        api_url = "https://auth.pub.solar/realms/pub.solar/protocol/openid-connect/userinfo";
+        auth_url = "https://auth.${config.pub-solar-os.networking.domain}/realms/${config.pub-solar-os.auth.realm}/protocol/openid-connect/auth";
+        token_url = "https://auth.${config.pub-solar-os.networking.domain}/realms/${config.pub-solar-os.auth.realm}/protocol/openid-connect/token";
+        api_url = "https://auth.${config.pub-solar-os.networking.domain}/realms/${config.pub-solar-os.auth.realm}/protocol/openid-connect/userinfo";
         role_attribute_path = "contains(roles[*], 'admin') && 'GrafanaAdmin' || 'Viewer'";
         allow_assign_grafana_admin = true;
       };
@@ -103,6 +165,7 @@
             {
               name = "pub.solar Dashboards";
               options.path = "/etc/grafana-dashboards";
+              options.foldersFromFilesStructure = true;
             }
           ];
         };
diff --git a/modules/grafana/grafana-dashboards/grafana-garage-dashboard-prometheus.json b/modules/grafana/grafana-dashboards/grafana-garage-dashboard-prometheus.json
new file mode 100644
index 00000000..33ee1635
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/grafana-garage-dashboard-prometheus.json
@@ -0,0 +1,1048 @@
+{
+  "__inputs": [
+    {
+      "name": "DS_PROMETHEUS",
+      "label": "DS_PROMETHEUS",
+      "description": "",
+      "type": "datasource",
+      "pluginId": "prometheus",
+      "pluginName": "Prometheus"
+    }
+  ],
+  "__elements": {},
+  "__requires": [
+    {
+      "type": "grafana",
+      "id": "grafana",
+      "name": "Grafana",
+      "version": "9.2.0"
+    },
+    {
+      "type": "datasource",
+      "id": "prometheus",
+      "name": "Prometheus",
+      "version": "1.0.0"
+    },
+    {
+      "type": "panel",
+      "id": "timeseries",
+      "name": "Time series",
+      "version": ""
+    }
+  ],
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": {
+          "type": "datasource",
+          "uid": "grafana"
+        },
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "target": {
+          "limit": 100,
+          "matchAny": false,
+          "tags": [],
+          "type": "dashboard"
+        },
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": true,
+  "fiscalYearStartMonth": 0,
+  "graphTooltip": 0,
+  "id": null,
+  "links": [],
+  "liveNow": false,
+  "panels": [
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 24,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "Bps"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 9,
+        "w": 8,
+        "x": 0,
+        "y": 0
+      },
+      "id": 10,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "sum(rate(block_bytes_read{job=\"garage\"}[$__rate_interval])    )",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Disk bytes read",
+          "refId": "A"
+        },
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "-sum(rate(block_bytes_written{job=\"garage\"}[$__rate_interval])    )",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Disk bytes written",
+          "refId": "B"
+        }
+      ],
+      "title": "Disk I/O",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "reqps"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 9,
+        "w": 8,
+        "x": 8,
+        "y": 0
+      },
+      "id": 3,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "exemplar": true,
+          "expr": "sum by (api_endpoint) (rate(api_s3_request_counter {job=\"garage\"}[$__rate_interval]))",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "{{api_endpoint}}",
+          "range": true,
+          "refId": "A"
+        }
+      ],
+      "title": "API requests",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "reqps"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 9,
+        "w": 8,
+        "x": 16,
+        "y": 0
+      },
+      "id": 9,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "sum(rate(web_request_counter {job=\"garage\"}[$__rate_interval]))",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Web request rate",
+          "refId": "A"
+        }
+      ],
+      "title": "Web requests",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "reqps"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 8,
+        "x": 0,
+        "y": 9
+      },
+      "id": 2,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "sum by (rpc_endpoint) (rate(rpc_request_counter {job=\"garage\"}[$__rate_interval]))",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "{{rpc_endpoint}}",
+          "refId": "A"
+        }
+      ],
+      "title": "RPC requests",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "reqps"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 8,
+        "x": 8,
+        "y": 9
+      },
+      "id": 4,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "exemplar": true,
+          "expr": "sum by (api_endpoint, status_code) (rate(api_s3_error_counter {job=\"garage\"}[$__rate_interval]))",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "{{api_endpoint}} {{status_code}}",
+          "range": true,
+          "refId": "A"
+        }
+      ],
+      "title": "API errors",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "reqps"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 8,
+        "x": 16,
+        "y": 9
+      },
+      "id": 11,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "sum by(status_code) (rate(web_error_counter {job=\"garage\"}[$__rate_interval]))",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "{{status_code}}",
+          "refId": "A"
+        }
+      ],
+      "title": "Web errors",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 8,
+        "x": 0,
+        "y": 17
+      },
+      "id": 6,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "block_resync_queue_length{job=\"garage\"}",
+          "interval": "",
+          "legendFormat": "{{instance}}",
+          "refId": "A"
+        }
+      ],
+      "title": "Resync queue length",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 8,
+        "x": 8,
+        "y": 17
+      },
+      "id": 7,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "sum by(table_name) (table_gc_todo_queue_length{job=\"garage\"})",
+          "interval": "",
+          "legendFormat": "{{ table_name}}",
+          "refId": "A"
+        }
+      ],
+      "title": "Table GC queue length",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 8,
+        "x": 16,
+        "y": 17
+      },
+      "id": 8,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "sum by(table_name) (table_merkle_updater_todo_queue_length{job=\"garage\"})",
+          "interval": "",
+          "legendFormat": "{{ table_name}}",
+          "refId": "A"
+        }
+      ],
+      "title": "Table Merkle updater queue length",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 8,
+        "x": 0,
+        "y": 25
+      },
+      "id": 12,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "block_resync_errored_blocks{job=\"garage\"}",
+          "interval": "",
+          "legendFormat": "{{instance}}",
+          "refId": "A"
+        }
+      ],
+      "title": "Resync errored blocks",
+      "type": "timeseries"
+    }
+  ],
+  "refresh": "30s",
+  "schemaVersion": 37,
+  "style": "dark",
+  "tags": [],
+  "templating": {
+    "list": [
+      {
+        "current": {
+          "selected": false,
+          "text": "default",
+          "value": "default"
+        },
+        "hide": 0,
+        "includeAll": false,
+        "multi": false,
+        "name": "DS_PROMETHEUS",
+        "label": "Datasource",
+        "options": [],
+        "query": "prometheus",
+        "queryValue": "",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "type": "datasource"
+      }
+    ]
+  },
+  "time": {
+    "from": "now-6h",
+    "to": "now"
+  },
+  "timepicker": {},
+  "timezone": "",
+  "title": "Garage",
+  "uid": "ys3pnpZ4k",
+  "version": 26,
+  "weekStart": ""
+}
diff --git a/modules/grafana/grafana-dashboards/loki/loki-chunks.json b/modules/grafana/grafana-dashboards/loki/loki-chunks.json
new file mode 100644
index 00000000..b9893497
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/loki/loki-chunks.json
@@ -0,0 +1,1187 @@
+{
+      "annotations": {
+         "list": [ ]
+      },
+      "editable": true,
+      "gnetId": null,
+      "graphTooltip": 0,
+      "hideControls": false,
+      "links": [
+         {
+            "asDropdown": true,
+            "icon": "external link",
+            "includeVars": true,
+            "keepTime": true,
+            "tags": [
+               "loki"
+            ],
+            "targetBlank": false,
+            "title": "Loki Dashboards",
+            "type": "dashboards"
+         }
+      ],
+      "refresh": "10s",
+      "rows": [
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 1,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "sum(loki_ingester_memory_chunks{cluster=\"$cluster\", job=~\"$namespace/loki\"})",
+                        "format": "time_series",
+                        "legendFormat": "series",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Series",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 2,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "sum(loki_ingester_memory_chunks{cluster=\"$cluster\", job=~\"$namespace/loki\"}) / sum(loki_ingester_memory_streams{cluster=\"$cluster\", job=~\"$namespace/loki\"})",
+                        "format": "time_series",
+                        "legendFormat": "chunks",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Chunks per series",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Active Series / Chunks",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "percentunit"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 3,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_ingester_chunk_utilization_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le)) * 1",
+                        "format": "time_series",
+                        "legendFormat": "99th Percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum(rate(loki_ingester_chunk_utilization_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le)) * 1",
+                        "format": "time_series",
+                        "legendFormat": "50th Percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "sum(rate(loki_ingester_chunk_utilization_sum{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) * 1 / sum(rate(loki_ingester_chunk_utilization_count{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Utilization",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 4,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_ingester_chunk_age_seconds_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "99th Percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum(rate(loki_ingester_chunk_age_seconds_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "50th Percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "sum(rate(loki_ingester_chunk_age_seconds_sum{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) * 1e3 / sum(rate(loki_ingester_chunk_age_seconds_count{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Age",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Flush Stats",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 5,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_ingester_chunk_entries_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le)) * 1",
+                        "format": "time_series",
+                        "legendFormat": "99th Percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum(rate(loki_ingester_chunk_entries_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le)) * 1",
+                        "format": "time_series",
+                        "legendFormat": "50th Percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "sum(rate(loki_ingester_chunk_entries_sum{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) * 1 / sum(rate(loki_ingester_chunk_entries_count{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Log Entries Per Chunk",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 6,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_chunk_store_index_entries_per_chunk_sum{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) / sum(rate(loki_chunk_store_index_entries_per_chunk_count{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "Index Entries",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Index Entries Per Chunk",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Flush Stats",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 7,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "loki_ingester_flush_queue_length{cluster=\"$cluster\", job=~\"$namespace/loki\"} or cortex_ingester_flush_queue_length{cluster=\"$cluster\", job=~\"$namespace/loki\"}",
+                        "format": "time_series",
+                        "legendFormat": "{{pod}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Queue Length",
+                  "type": "timeseries"
+               },
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 8,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_ingester_chunk_age_seconds_count{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "Flush Rate",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Flush Stats",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 9,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_ingester_chunks_flushed_total{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "{{pod}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Chunks Flushed/Second",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 10,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (reason) (rate(loki_ingester_chunks_flushed_total{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) / ignoring(reason) group_left sum(rate(loki_ingester_chunks_flushed_total{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "{{reason}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Chunk Flush Reason",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": 1,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": 1,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Flush Stats",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "cards": {
+                     "cardPadding": null,
+                     "cardRound": null
+                  },
+                  "color": {
+                     "cardColor": "#b4ff00",
+                     "colorScale": "sqrt",
+                     "colorScheme": "interpolateSpectral",
+                     "exponent": 0.5,
+                     "mode": "spectrum"
+                  },
+                  "dataFormat": "tsbuckets",
+                  "datasource": "$datasource",
+                  "heatmap": { },
+                  "hideZeroBuckets": false,
+                  "highlightCards": true,
+                  "id": 11,
+                  "legend": {
+                     "show": true
+                  },
+                  "span": 12,
+                  "targets": [
+                     {
+                        "expr": "sum by (le) (rate(loki_ingester_chunk_utilization_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval]))",
+                        "format": "heatmap",
+                        "intervalFactor": 2,
+                        "legendFormat": "{{le}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "Chunk Utilization",
+                  "tooltip": {
+                     "show": true,
+                     "showHistogram": true
+                  },
+                  "type": "heatmap",
+                  "xAxis": {
+                     "show": true
+                  },
+                  "xBucketNumber": null,
+                  "xBucketSize": null,
+                  "yAxis": {
+                     "decimals": 0,
+                     "format": "percentunit",
+                     "show": true,
+                     "splitFactor": null
+                  },
+                  "yBucketBound": "auto"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Utilization",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "cards": {
+                     "cardPadding": null,
+                     "cardRound": null
+                  },
+                  "color": {
+                     "cardColor": "#b4ff00",
+                     "colorScale": "sqrt",
+                     "colorScheme": "interpolateSpectral",
+                     "exponent": 0.5,
+                     "mode": "spectrum"
+                  },
+                  "dataFormat": "tsbuckets",
+                  "datasource": "$datasource",
+                  "heatmap": { },
+                  "hideZeroBuckets": false,
+                  "highlightCards": true,
+                  "id": 12,
+                  "legend": {
+                     "show": true
+                  },
+                  "span": 12,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_ingester_chunk_size_bytes_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le)",
+                        "format": "heatmap",
+                        "intervalFactor": 2,
+                        "legendFormat": "{{le}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "Chunk Size Bytes",
+                  "tooltip": {
+                     "show": true,
+                     "showHistogram": true
+                  },
+                  "type": "heatmap",
+                  "xAxis": {
+                     "show": true
+                  },
+                  "xBucketNumber": null,
+                  "xBucketSize": null,
+                  "yAxis": {
+                     "decimals": 0,
+                     "format": "bytes",
+                     "show": true,
+                     "splitFactor": null
+                  },
+                  "yBucketBound": "auto"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Utilization",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "bytes"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 13,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 12,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_ingester_chunk_size_bytes_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le))",
+                        "format": "time_series",
+                        "legendFormat": "p99",
+                        "legendLink": null
+                     },
+                     {
+                        "expr": "histogram_quantile(0.90, sum(rate(loki_ingester_chunk_size_bytes_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le))",
+                        "format": "time_series",
+                        "legendFormat": "p90",
+                        "legendLink": null
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum(rate(loki_ingester_chunk_size_bytes_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le))",
+                        "format": "time_series",
+                        "legendFormat": "p50",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Chunk Size Quantiles",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Utilization",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 14,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 12,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.5, sum(rate(loki_ingester_chunk_bounds_hours_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le))",
+                        "format": "time_series",
+                        "legendFormat": "p50",
+                        "legendLink": null
+                     },
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_ingester_chunk_bounds_hours_bucket{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) by (le))",
+                        "format": "time_series",
+                        "legendFormat": "p99",
+                        "legendLink": null
+                     },
+                     {
+                        "expr": "sum(rate(loki_ingester_chunk_bounds_hours_sum{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval])) / sum(rate(loki_ingester_chunk_bounds_hours_count{cluster=\"$cluster\", job=~\"$namespace/loki\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "avg",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Chunk Duration hours (end-start)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Duration",
+            "titleSize": "h6"
+         }
+      ],
+      "schemaVersion": 14,
+      "style": "dark",
+      "tags": [
+         "loki"
+      ],
+      "templating": {
+         "list": [
+            {
+               "current": {
+                  "text": "default",
+                  "value": "default"
+               },
+               "hide": 0,
+               "label": "Data source",
+               "name": "datasource",
+               "options": [ ],
+               "query": "prometheus",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "cluster",
+               "multi": false,
+               "name": "cluster",
+               "options": [ ],
+               "query": "label_values(loki_build_info, cluster)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "namespace",
+               "multi": false,
+               "name": "namespace",
+               "options": [ ],
+               "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            }
+         ]
+      },
+      "time": {
+         "from": "now-1h",
+         "to": "now"
+      },
+      "timepicker": {
+         "refresh_intervals": [
+            "5s",
+            "10s",
+            "30s",
+            "1m",
+            "5m",
+            "15m",
+            "30m",
+            "1h",
+            "2h",
+            "1d"
+         ],
+         "time_options": [
+            "5m",
+            "15m",
+            "1h",
+            "6h",
+            "12h",
+            "24h",
+            "2d",
+            "7d",
+            "30d"
+         ]
+      },
+      "timezone": "utc",
+      "title": "Loki / Chunks",
+      "uid": "chunks",
+      "version": 0
+   }
\ No newline at end of file
diff --git a/modules/grafana/grafana-dashboards/loki/loki-deletion.json b/modules/grafana/grafana-dashboards/loki/loki-deletion.json
new file mode 100644
index 00000000..99d536b4
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/loki/loki-deletion.json
@@ -0,0 +1,750 @@
+{
+      "annotations": {
+         "list": [ ]
+      },
+      "editable": true,
+      "gnetId": null,
+      "graphTooltip": 0,
+      "hideControls": false,
+      "links": [
+         {
+            "asDropdown": true,
+            "icon": "external link",
+            "includeVars": true,
+            "keepTime": true,
+            "tags": [
+               "loki"
+            ],
+            "targetBlank": false,
+            "title": "Loki Dashboards",
+            "type": "dashboards"
+         }
+      ],
+      "refresh": "10s",
+      "rows": [
+         {
+            "collapse": false,
+            "height": "100px",
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "format": "none",
+                  "id": 1,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "percentage": false,
+                  "pointradius": 5,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "span": 6,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(loki_compactor_pending_delete_requests_count{cluster=~\"$cluster\", namespace=~\"$namespace\"})",
+                        "format": "time_series",
+                        "instant": true,
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": "70,80",
+                  "timeFrom": null,
+                  "timeShift": null,
+                  "title": "Number of Pending Requests",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "singlestat",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "format": "dtdurations",
+                  "id": 2,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "percentage": false,
+                  "pointradius": 5,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "span": 6,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "max(loki_compactor_oldest_pending_delete_request_age_seconds{cluster=~\"$cluster\", namespace=~\"$namespace\"})",
+                        "format": "time_series",
+                        "instant": true,
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": "70,80",
+                  "timeFrom": null,
+                  "timeShift": null,
+                  "title": "Oldest Pending Request Age",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "singlestat",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": false,
+            "title": "Headlines",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 3,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "(loki_compactor_delete_requests_received_total{cluster=~\"$cluster\", namespace=~\"$namespace\"} or on() vector(0)) - on () (loki_compactor_delete_requests_processed_total{cluster=~\"$cluster\", namespace=~\"$namespace\"} or on () vector(0))",
+                        "format": "time_series",
+                        "legendFormat": "in progress",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "# of Delete Requests (received - processed) ",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 4,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "sum(increase(loki_compactor_delete_requests_received_total{cluster=~\"$cluster\", namespace=~\"$namespace\"}[1d]))",
+                        "format": "time_series",
+                        "legendFormat": "received",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Delete Requests Received / Day",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 5,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "sum(increase(loki_compactor_delete_requests_processed_total{cluster=~\"$cluster\", namespace=~\"$namespace\"}[1d]))",
+                        "format": "time_series",
+                        "legendFormat": "processed",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Delete Requests Processed / Day",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Churn",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 6,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"loki.*\"}",
+                        "format": "time_series",
+                        "legendFormat": "{{pod}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Compactor CPU usage",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 7,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "go_memstats_heap_inuse_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"loki.*\"} / 1024 / 1024 ",
+                        "format": "time_series",
+                        "legendFormat": " {{pod}} ",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Compactor memory usage (MiB)",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 8,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "loki_boltdb_shipper_compact_tables_operation_duration_seconds{cluster=~\"$cluster\", namespace=~\"$namespace\"}",
+                        "format": "time_series",
+                        "legendFormat": "{{pod}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Compaction run duration (seconds)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Compactor",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 9,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "sum(increase(loki_compactor_load_pending_requests_attempts_total{status=\"fail\", cluster=~\"$cluster\", namespace=~\"$namespace\"}[1h]))",
+                        "format": "time_series",
+                        "legendFormat": "failures",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Failures in Loading Delete Requests / Hour",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 10,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_compactor_deleted_lines{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"loki.*\"}[$__rate_interval])) by (user)",
+                        "format": "time_series",
+                        "legendFormat": "{{user}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Lines Deleted / Sec",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Deletion metrics",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$loki_datasource",
+                  "id": 11,
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"loki.*\"} |~ \"Started processing delete request|delete request for user marked as processed\" | logfmt | line_format \"{{.ts}} user={{.user}} delete_request_id={{.delete_request_id}} msg={{.msg}}\" ",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "In progress/finished",
+                  "type": "logs"
+               },
+               {
+                  "datasource": "$loki_datasource",
+                  "id": 12,
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"loki.*\"} |~ \"delete request for user added\" | logfmt | line_format \"{{.ts}} user={{.user}} query='{{.query}}'\"",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "Requests",
+                  "type": "logs"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "List of deletion requests",
+            "titleSize": "h6"
+         }
+      ],
+      "schemaVersion": 14,
+      "style": "dark",
+      "tags": [
+         "loki"
+      ],
+      "templating": {
+         "list": [
+            {
+               "current": {
+                  "text": "default",
+                  "value": "default"
+               },
+               "hide": 0,
+               "label": "Data source",
+               "name": "datasource",
+               "options": [ ],
+               "query": "prometheus",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "cluster",
+               "multi": false,
+               "name": "cluster",
+               "options": [ ],
+               "query": "label_values(loki_build_info, cluster)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "namespace",
+               "multi": false,
+               "name": "namespace",
+               "options": [ ],
+               "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "hide": 0,
+               "label": null,
+               "name": "loki_datasource",
+               "options": [ ],
+               "query": "loki",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            }
+         ]
+      },
+      "time": {
+         "from": "now-1h",
+         "to": "now"
+      },
+      "timepicker": {
+         "refresh_intervals": [
+            "5s",
+            "10s",
+            "30s",
+            "1m",
+            "5m",
+            "15m",
+            "30m",
+            "1h",
+            "2h",
+            "1d"
+         ],
+         "time_options": [
+            "5m",
+            "15m",
+            "1h",
+            "6h",
+            "12h",
+            "24h",
+            "2d",
+            "7d",
+            "30d"
+         ]
+      },
+      "timezone": "utc",
+      "title": "Loki / Deletion",
+      "uid": "deletion",
+      "version": 0
+   }
\ No newline at end of file
diff --git a/modules/grafana/grafana-dashboards/loki/loki-logs.json b/modules/grafana/grafana-dashboards/loki/loki-logs.json
new file mode 100644
index 00000000..32b8e52a
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/loki/loki-logs.json
@@ -0,0 +1,1102 @@
+{
+      "annotations": {
+         "list": [ ]
+      },
+      "editable": true,
+      "gnetId": null,
+      "graphTooltip": 0,
+      "hideControls": false,
+      "iteration": 1583185057230,
+      "links": [
+         {
+            "asDropdown": true,
+            "icon": "external link",
+            "includeVars": true,
+            "keepTime": true,
+            "tags": [
+               "loki"
+            ],
+            "targetBlank": false,
+            "title": "Loki Dashboards",
+            "type": "dashboards"
+         }
+      ],
+      "panels": [
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 4,
+               "w": 3,
+               "x": 0,
+               "y": 0
+            },
+            "hiddenSeries": false,
+            "id": 35,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(go_goroutines{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\"})",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "goroutines",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "unit": "s"
+               }
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 4,
+               "w": 3,
+               "x": 3,
+               "y": 0
+            },
+            "hiddenSeries": false,
+            "id": 41,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(go_gc_duration_seconds{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\"}) by (quantile)",
+                  "legendFormat": "{{quantile}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "gc duration",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 4,
+               "w": 3,
+               "x": 6,
+               "y": 0
+            },
+            "hiddenSeries": false,
+            "id": 36,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(rate(container_cpu_usage_seconds_total{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\", container=~\"$container\"}[$__rate_interval]))",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "cpu",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "unit": "bytes"
+               }
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 4,
+               "w": 3,
+               "x": 9,
+               "y": 0
+            },
+            "hiddenSeries": false,
+            "id": 40,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\", container=~\"$container\"})",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "working set",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "bytes",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "unit": "binBps"
+               }
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 4,
+               "w": 3,
+               "x": 12,
+               "y": 0
+            },
+            "hiddenSeries": false,
+            "id": 38,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(rate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\"}[$__rate_interval]))",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "tx",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "bytes",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "unit": "binBps"
+               }
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 4,
+               "w": 3,
+               "x": 15,
+               "y": 0
+            },
+            "hiddenSeries": false,
+            "id": 39,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(rate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\"}[$__rate_interval]))",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "rx",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "decbytes",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 4,
+               "w": 3,
+               "x": 18,
+               "y": 0
+            },
+            "hiddenSeries": false,
+            "id": 37,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "increase(kube_pod_container_status_last_terminated_reason{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\", container=~\"$container\"}[30m]) > 0",
+                  "legendFormat": "{{reason}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "restarts",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "bytes",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "unit": "ops"
+               }
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 4,
+               "w": 3,
+               "x": 21,
+               "y": 0
+            },
+            "hiddenSeries": false,
+            "id": 42,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(rate(promtail_custom_bad_words_total{cluster=\"$cluster\", exported_namespace=\"$namespace\", exported_pod=~\"$deployment.*\", exported_pod=~\"$pod\", container=~\"$container\"}[$__rate_interval])) by (level)",
+                  "legendFormat": "{{level}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "bad words",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "bytes",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$loki_datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "unit": "ops"
+               }
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 7,
+               "w": 24,
+               "x": 0,
+               "y": 4
+            },
+            "hiddenSeries": false,
+            "id": 31,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [
+               {
+                  "alias": "warn",
+                  "color": "#FF780A"
+               },
+               {
+                  "alias": "error",
+                  "color": "#E02F44"
+               },
+               {
+                  "alias": "info",
+                  "color": "#56A64B"
+               },
+               {
+                  "alias": "debug",
+                  "color": "#3274D9"
+               }
+            ],
+            "spaceLength": 10,
+            "stack": true,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(rate({cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\", container=~\"$container\" } |logfmt| level=\"$level\" |= \"$filter\" | __error__=\"\" [$__auto])) by (level)",
+                  "intervalFactor": 3,
+                  "legendFormat": "{{level}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Log Rate",
+            "tooltip": {
+               "shared": true,
+               "sort": 2,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": false,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": false
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "datasource": "$loki_datasource",
+            "gridPos": {
+               "h": 19,
+               "w": 24,
+               "x": 0,
+               "y": 6
+            },
+            "id": 29,
+            "maxDataPoints": "",
+            "options": {
+               "showLabels": false,
+               "showTime": true,
+               "sortOrder": "Descending",
+               "wrapLogMessage": true
+            },
+            "targets": [
+               {
+                  "expr": "{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\", container=~\"$container\"} | logfmt | level=\"$level\" |= \"$filter\"",
+                  "refId": "A"
+               }
+            ],
+            "timeFrom": null,
+            "timeShift": null,
+            "title": "Logs",
+            "type": "logs"
+         }
+      ],
+      "refresh": "10s",
+      "rows": [ ],
+      "schemaVersion": 14,
+      "style": "dark",
+      "tags": [
+         "loki"
+      ],
+      "templating": {
+         "list": [
+            {
+               "current": {
+                  "text": "default",
+                  "value": "default"
+               },
+               "hide": 0,
+               "label": "Data source",
+               "name": "datasource",
+               "options": [ ],
+               "query": "prometheus",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "cluster",
+               "multi": false,
+               "name": "cluster",
+               "options": [ ],
+               "query": "label_values(loki_build_info, cluster)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "namespace",
+               "multi": false,
+               "name": "namespace",
+               "options": [ ],
+               "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "hide": 0,
+               "label": null,
+               "name": "loki_datasource",
+               "options": [ ],
+               "query": "loki",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            },
+            {
+               "allValue": null,
+               "current": { },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": null,
+               "multi": false,
+               "name": "deployment",
+               "options": [ ],
+               "query": "label_values(kube_deployment_created{cluster=\"$cluster\", namespace=\"$namespace\"}, deployment)",
+               "refresh": 0,
+               "regex": "",
+               "sort": 1,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "allValue": null,
+               "current": { },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": null,
+               "multi": false,
+               "name": "pod",
+               "options": [ ],
+               "query": "label_values(kube_pod_container_info{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\"}, pod)",
+               "refresh": 0,
+               "regex": "",
+               "sort": 1,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "allValue": null,
+               "current": { },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": null,
+               "multi": false,
+               "name": "container",
+               "options": [ ],
+               "query": "label_values(kube_pod_container_info{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$pod\", pod=~\"$deployment.*\"}, container)",
+               "refresh": 0,
+               "regex": "",
+               "sort": 1,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "selected": true,
+                  "text": "",
+                  "value": ""
+               },
+               "hide": 0,
+               "includeAll": false,
+               "label": "",
+               "multi": true,
+               "name": "level",
+               "options": [
+                  {
+                     "selected": false,
+                     "text": "debug",
+                     "value": "debug"
+                  },
+                  {
+                     "selected": false,
+                     "text": "info",
+                     "value": "info"
+                  },
+                  {
+                     "selected": false,
+                     "text": "warn",
+                     "value": "warn"
+                  },
+                  {
+                     "selected": false,
+                     "text": "error",
+                     "value": "error"
+                  }
+               ],
+               "query": "debug,info,warn,error",
+               "refresh": 0,
+               "type": "custom"
+            },
+            {
+               "current": {
+                  "selected": false,
+                  "text": "",
+                  "value": ""
+               },
+               "label": "LogQL Filter",
+               "name": "filter",
+               "query": "",
+               "type": "textbox"
+            }
+         ]
+      },
+      "time": {
+         "from": "now-1h",
+         "to": "now"
+      },
+      "timepicker": {
+         "refresh_intervals": [
+            "5s",
+            "10s",
+            "30s",
+            "1m",
+            "5m",
+            "15m",
+            "30m",
+            "1h",
+            "2h",
+            "1d"
+         ],
+         "time_options": [
+            "5m",
+            "15m",
+            "1h",
+            "6h",
+            "12h",
+            "24h",
+            "2d",
+            "7d",
+            "30d"
+         ]
+      },
+      "timezone": "utc",
+      "title": "Loki / Logs",
+      "uid": "logs",
+      "version": 0
+   }
\ No newline at end of file
diff --git a/modules/grafana/grafana-dashboards/loki/loki-mixin-recording-rules.json b/modules/grafana/grafana-dashboards/loki/loki-mixin-recording-rules.json
new file mode 100644
index 00000000..f1f6c215
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/loki/loki-mixin-recording-rules.json
@@ -0,0 +1,724 @@
+{
+      "annotations": {
+         "list": [ ]
+      },
+      "editable": true,
+      "fiscalYearStartMonth": 0,
+      "gnetId": null,
+      "graphTooltip": 0,
+      "hideControls": false,
+      "iteration": 1635347545534,
+      "links": [
+         {
+            "asDropdown": true,
+            "icon": "external link",
+            "includeVars": true,
+            "keepTime": true,
+            "tags": [
+               "loki"
+            ],
+            "targetBlank": false,
+            "title": "Loki Dashboards",
+            "type": "dashboards"
+         }
+      ],
+      "liveNow": false,
+      "panels": [
+         {
+            "datasource": "${datasource}",
+            "fieldConfig": {
+               "defaults": {
+                  "color": {
+                     "mode": "thresholds"
+                  },
+                  "mappings": [ ],
+                  "noValue": "0",
+                  "thresholds": {
+                     "mode": "absolute",
+                     "steps": [
+                        {
+                           "color": "green",
+                           "value": null
+                        },
+                        {
+                           "color": "red",
+                           "value": 1
+                        }
+                     ]
+                  }
+               },
+               "overrides": [ ]
+            },
+            "gridPos": {
+               "h": 10,
+               "w": 2,
+               "x": 0,
+               "y": 0
+            },
+            "id": 2,
+            "options": {
+               "colorMode": "value",
+               "graphMode": "area",
+               "justifyMode": "auto",
+               "orientation": "auto",
+               "reduceOptions": {
+                  "calcs": [
+                     "lastNotNull"
+                  ],
+                  "fields": "",
+                  "values": false
+               },
+               "textMode": "auto"
+            },
+            "pluginVersion": "8.3.0-38205pre",
+            "targets": [
+               {
+                  "datasource": "${datasource}",
+                  "exemplar": false,
+                  "expr": "sum(loki_ruler_wal_appender_ready) by (pod, tenant) == 0",
+                  "instant": true,
+                  "interval": "",
+                  "legendFormat": "",
+                  "refId": "A"
+               }
+            ],
+            "title": "Appenders Not Ready",
+            "type": "stat"
+         },
+         {
+            "datasource": "${datasource}",
+            "description": "",
+            "fieldConfig": {
+               "defaults": {
+                  "color": {
+                     "mode": "palette-classic"
+                  },
+                  "custom": {
+                     "axisLabel": "",
+                     "axisPlacement": "auto",
+                     "barAlignment": 0,
+                     "drawStyle": "line",
+                     "fillOpacity": 0,
+                     "gradientMode": "none",
+                     "hideFrom": {
+                        "legend": false,
+                        "tooltip": false,
+                        "viz": false
+                     },
+                     "lineInterpolation": "linear",
+                     "lineWidth": 1,
+                     "pointSize": 5,
+                     "scaleDistribution": {
+                        "type": "linear"
+                     },
+                     "showPoints": "auto",
+                     "spanNulls": false,
+                     "stacking": {
+                        "group": "A",
+                        "mode": "none"
+                     },
+                     "thresholdsStyle": {
+                        "mode": "off"
+                     }
+                  },
+                  "mappings": [ ],
+                  "thresholds": {
+                     "mode": "absolute",
+                     "steps": [
+                        {
+                           "color": "green",
+                           "value": null
+                        },
+                        {
+                           "color": "red",
+                           "value": 80
+                        }
+                     ]
+                  }
+               },
+               "overrides": [ ]
+            },
+            "gridPos": {
+               "h": 10,
+               "w": 11,
+               "x": 2,
+               "y": 0
+            },
+            "id": 4,
+            "options": {
+               "legend": {
+                  "calcs": [ ],
+                  "displayMode": "list",
+                  "placement": "bottom"
+               },
+               "tooltip": {
+                  "mode": "single"
+               }
+            },
+            "targets": [
+               {
+                  "datasource": "${datasource}",
+                  "exemplar": true,
+                  "expr": "sum(rate(loki_ruler_wal_samples_appended_total{tenant=~\"${tenant}\"}[$__rate_interval])) by (tenant) > 0",
+                  "interval": "",
+                  "legendFormat": "{{tenant}}",
+                  "refId": "A"
+               }
+            ],
+            "title": "Samples Appended to WAL per Second",
+            "type": "timeseries"
+         },
+         {
+            "datasource": "${datasource}",
+            "description": "Series are unique combinations of labels",
+            "fieldConfig": {
+               "defaults": {
+                  "color": {
+                     "mode": "palette-classic"
+                  },
+                  "custom": {
+                     "axisLabel": "",
+                     "axisPlacement": "auto",
+                     "barAlignment": 0,
+                     "drawStyle": "line",
+                     "fillOpacity": 0,
+                     "gradientMode": "none",
+                     "hideFrom": {
+                        "legend": false,
+                        "tooltip": false,
+                        "viz": false
+                     },
+                     "lineInterpolation": "linear",
+                     "lineWidth": 1,
+                     "pointSize": 5,
+                     "scaleDistribution": {
+                        "type": "linear"
+                     },
+                     "showPoints": "auto",
+                     "spanNulls": false,
+                     "stacking": {
+                        "group": "A",
+                        "mode": "none"
+                     },
+                     "thresholdsStyle": {
+                        "mode": "off"
+                     }
+                  },
+                  "mappings": [ ],
+                  "thresholds": {
+                     "mode": "absolute",
+                     "steps": [
+                        {
+                           "color": "green",
+                           "value": null
+                        },
+                        {
+                           "color": "red",
+                           "value": 80
+                        }
+                     ]
+                  }
+               },
+               "overrides": [ ]
+            },
+            "gridPos": {
+               "h": 10,
+               "w": 11,
+               "x": 13,
+               "y": 0
+            },
+            "id": 5,
+            "options": {
+               "legend": {
+                  "calcs": [ ],
+                  "displayMode": "list",
+                  "placement": "bottom"
+               },
+               "tooltip": {
+                  "mode": "single"
+               }
+            },
+            "targets": [
+               {
+                  "datasource": "${datasource}",
+                  "exemplar": true,
+                  "expr": "sum(rate(loki_ruler_wal_storage_created_series_total{tenant=~\"${tenant}\"}[$__rate_interval])) by (tenant) > 0",
+                  "interval": "",
+                  "legendFormat": "{{tenant}}",
+                  "refId": "A"
+               }
+            ],
+            "title": "Series Created per Second",
+            "type": "timeseries"
+         },
+         {
+            "datasource": "${datasource}",
+            "description": "Difference between highest timestamp appended to WAL and highest timestamp successfully written to remote storage",
+            "fieldConfig": {
+               "defaults": {
+                  "color": {
+                     "mode": "palette-classic"
+                  },
+                  "custom": {
+                     "axisLabel": "",
+                     "axisPlacement": "auto",
+                     "barAlignment": 0,
+                     "drawStyle": "line",
+                     "fillOpacity": 0,
+                     "gradientMode": "none",
+                     "hideFrom": {
+                        "legend": false,
+                        "tooltip": false,
+                        "viz": false
+                     },
+                     "lineInterpolation": "linear",
+                     "lineWidth": 1,
+                     "pointSize": 5,
+                     "scaleDistribution": {
+                        "type": "linear"
+                     },
+                     "showPoints": "auto",
+                     "spanNulls": false,
+                     "stacking": {
+                        "group": "A",
+                        "mode": "none"
+                     },
+                     "thresholdsStyle": {
+                        "mode": "off"
+                     }
+                  },
+                  "mappings": [ ],
+                  "thresholds": {
+                     "mode": "absolute",
+                     "steps": [
+                        {
+                           "color": "green",
+                           "value": null
+                        },
+                        {
+                           "color": "red",
+                           "value": 80
+                        }
+                     ]
+                  },
+                  "unit": "s"
+               },
+               "overrides": [ ]
+            },
+            "gridPos": {
+               "h": 10,
+               "w": 12,
+               "x": 0,
+               "y": 10
+            },
+            "id": 6,
+            "options": {
+               "legend": {
+                  "calcs": [ ],
+                  "displayMode": "list",
+                  "placement": "bottom"
+               },
+               "tooltip": {
+                  "mode": "single"
+               }
+            },
+            "targets": [
+               {
+                  "datasource": "${datasource}",
+                  "exemplar": true,
+                  "expr": "loki_ruler_wal_prometheus_remote_storage_highest_timestamp_in_seconds{tenant=~\"${tenant}\"}\n- on (tenant)\n  (\n    loki_ruler_wal_prometheus_remote_storage_queue_highest_sent_timestamp_seconds{tenant=~\"${tenant}\"}\n    or vector(0)\n  )",
+                  "interval": "",
+                  "legendFormat": "{{tenant}}",
+                  "refId": "A"
+               }
+            ],
+            "title": "Write Behind",
+            "type": "timeseries"
+         },
+         {
+            "datasource": "${datasource}",
+            "description": "",
+            "fieldConfig": {
+               "defaults": {
+                  "color": {
+                     "mode": "palette-classic"
+                  },
+                  "custom": {
+                     "axisLabel": "",
+                     "axisPlacement": "auto",
+                     "barAlignment": 0,
+                     "drawStyle": "line",
+                     "fillOpacity": 0,
+                     "gradientMode": "none",
+                     "hideFrom": {
+                        "legend": false,
+                        "tooltip": false,
+                        "viz": false
+                     },
+                     "lineInterpolation": "linear",
+                     "lineWidth": 1,
+                     "pointSize": 5,
+                     "scaleDistribution": {
+                        "type": "linear"
+                     },
+                     "showPoints": "auto",
+                     "spanNulls": false,
+                     "stacking": {
+                        "group": "A",
+                        "mode": "none"
+                     },
+                     "thresholdsStyle": {
+                        "mode": "off"
+                     }
+                  },
+                  "mappings": [ ],
+                  "thresholds": {
+                     "mode": "absolute",
+                     "steps": [
+                        {
+                           "color": "green",
+                           "value": null
+                        },
+                        {
+                           "color": "red",
+                           "value": 80
+                        }
+                     ]
+                  }
+               },
+               "overrides": [ ]
+            },
+            "gridPos": {
+               "h": 10,
+               "w": 12,
+               "x": 12,
+               "y": 10
+            },
+            "id": 7,
+            "options": {
+               "legend": {
+                  "calcs": [ ],
+                  "displayMode": "list",
+                  "placement": "bottom"
+               },
+               "tooltip": {
+                  "mode": "single"
+               }
+            },
+            "targets": [
+               {
+                  "datasource": "${datasource}",
+                  "exemplar": true,
+                  "expr": "sum(rate(loki_ruler_wal_prometheus_remote_storage_samples_total{tenant=~\"${tenant}\"}[$__rate_interval])) by (tenant) > 0",
+                  "interval": "",
+                  "legendFormat": "{{tenant}}",
+                  "refId": "A"
+               }
+            ],
+            "title": "Samples Sent per Second",
+            "type": "timeseries"
+         },
+         {
+            "datasource": "${datasource}",
+            "description": "\n",
+            "fieldConfig": {
+               "defaults": {
+                  "color": {
+                     "mode": "palette-classic"
+                  },
+                  "custom": {
+                     "axisLabel": "",
+                     "axisPlacement": "auto",
+                     "barAlignment": 0,
+                     "drawStyle": "line",
+                     "fillOpacity": 0,
+                     "gradientMode": "none",
+                     "hideFrom": {
+                        "legend": false,
+                        "tooltip": false,
+                        "viz": false
+                     },
+                     "lineInterpolation": "linear",
+                     "lineWidth": 1,
+                     "pointSize": 5,
+                     "scaleDistribution": {
+                        "type": "linear"
+                     },
+                     "showPoints": "auto",
+                     "spanNulls": false,
+                     "stacking": {
+                        "group": "A",
+                        "mode": "none"
+                     },
+                     "thresholdsStyle": {
+                        "mode": "off"
+                     }
+                  },
+                  "mappings": [ ],
+                  "thresholds": {
+                     "mode": "absolute",
+                     "steps": [
+                        {
+                           "color": "green",
+                           "value": null
+                        },
+                        {
+                           "color": "red",
+                           "value": 80
+                        }
+                     ]
+                  },
+                  "unit": "bytes"
+               },
+               "overrides": [ ]
+            },
+            "gridPos": {
+               "h": 10,
+               "w": 12,
+               "x": 0,
+               "y": 20
+            },
+            "id": 8,
+            "options": {
+               "legend": {
+                  "calcs": [ ],
+                  "displayMode": "list",
+                  "placement": "bottom"
+               },
+               "tooltip": {
+                  "mode": "single"
+               }
+            },
+            "targets": [
+               {
+                  "datasource": "${datasource}",
+                  "exemplar": true,
+                  "expr": "sum by (tenant) (loki_ruler_wal_disk_size{tenant=~\"${tenant}\"})",
+                  "interval": "",
+                  "legendFormat": "{{tenant}}",
+                  "refId": "A"
+               }
+            ],
+            "title": "WAL Disk Size",
+            "type": "timeseries"
+         },
+         {
+            "datasource": "${datasource}",
+            "description": "Some number of pending samples is expected, but if remote-write is failing this value will remain high",
+            "fieldConfig": {
+               "defaults": {
+                  "color": {
+                     "mode": "palette-classic"
+                  },
+                  "custom": {
+                     "axisLabel": "",
+                     "axisPlacement": "auto",
+                     "barAlignment": 0,
+                     "drawStyle": "line",
+                     "fillOpacity": 0,
+                     "gradientMode": "none",
+                     "hideFrom": {
+                        "legend": false,
+                        "tooltip": false,
+                        "viz": false
+                     },
+                     "lineInterpolation": "linear",
+                     "lineWidth": 1,
+                     "pointSize": 5,
+                     "scaleDistribution": {
+                        "type": "linear"
+                     },
+                     "showPoints": "auto",
+                     "spanNulls": false,
+                     "stacking": {
+                        "group": "A",
+                        "mode": "none"
+                     },
+                     "thresholdsStyle": {
+                        "mode": "off"
+                     }
+                  },
+                  "mappings": [ ],
+                  "thresholds": {
+                     "mode": "absolute",
+                     "steps": [
+                        {
+                           "color": "green",
+                           "value": null
+                        },
+                        {
+                           "color": "red",
+                           "value": 80
+                        }
+                     ]
+                  }
+               },
+               "overrides": [ ]
+            },
+            "gridPos": {
+               "h": 10,
+               "w": 12,
+               "x": 12,
+               "y": 20
+            },
+            "id": 9,
+            "options": {
+               "legend": {
+                  "calcs": [ ],
+                  "displayMode": "list",
+                  "placement": "bottom"
+               },
+               "tooltip": {
+                  "mode": "single"
+               }
+            },
+            "targets": [
+               {
+                  "datasource": "${datasource}",
+                  "exemplar": true,
+                  "expr": "max(loki_ruler_wal_prometheus_remote_storage_samples_pending{tenant=~\"${tenant}\"}) by (tenant,pod) > 0",
+                  "interval": "",
+                  "legendFormat": "{{tenant}}",
+                  "refId": "A"
+               }
+            ],
+            "title": "Pending Samples",
+            "type": "timeseries"
+         }
+      ],
+      "refresh": "10s",
+      "rows": [ ],
+      "schemaVersion": 14,
+      "style": "dark",
+      "tags": [
+         "loki"
+      ],
+      "templating": {
+         "list": [
+            {
+               "current": {
+                  "text": "default",
+                  "value": "default"
+               },
+               "hide": 0,
+               "label": "Data source",
+               "name": "datasource",
+               "options": [ ],
+               "query": "prometheus",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "cluster",
+               "multi": false,
+               "name": "cluster",
+               "options": [ ],
+               "query": "label_values(loki_build_info, cluster)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "namespace",
+               "multi": false,
+               "name": "namespace",
+               "options": [ ],
+               "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "hide": 0,
+               "label": null,
+               "name": "loki_datasource",
+               "options": [ ],
+               "query": "loki",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            },
+            {
+               "allValue": ".+",
+               "current": { },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": true,
+               "label": null,
+               "multi": false,
+               "name": "tenant",
+               "options": [ ],
+               "query": "query_result(sum by (id) (grafanacloud_logs_instance_info) and sum(label_replace(loki_tenant:active_streams{cluster=\"$cluster\",namespace=\"$namespace\"},\"id\",\"$1\",\"tenant\",\"(.*)\")) by(id))",
+               "refresh": 0,
+               "regex": "/\"([^\"]+)\"/",
+               "sort": 1,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            }
+         ]
+      },
+      "time": {
+         "from": "now-1h",
+         "to": "now"
+      },
+      "timepicker": {
+         "refresh_intervals": [
+            "5s",
+            "10s",
+            "30s",
+            "1m",
+            "5m",
+            "15m",
+            "30m",
+            "1h",
+            "2h",
+            "1d"
+         ],
+         "time_options": [
+            "5m",
+            "15m",
+            "1h",
+            "6h",
+            "12h",
+            "24h",
+            "2d",
+            "7d",
+            "30d"
+         ]
+      },
+      "timezone": "utc",
+      "title": "Loki / Recording Rules",
+      "uid": "recording-rules",
+      "version": 0,
+      "weekStart": ""
+   }
\ No newline at end of file
diff --git a/modules/grafana/grafana-dashboards/loki/loki-operational.json b/modules/grafana/grafana-dashboards/loki/loki-operational.json
new file mode 100644
index 00000000..e0726e50
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/loki/loki-operational.json
@@ -0,0 +1,6733 @@
+{
+      "annotations": {
+         "list": [ ]
+      },
+      "editable": true,
+      "gnetId": null,
+      "graphTooltip": 0,
+      "hideControls": false,
+      "iteration": 1588704280892,
+      "links": [
+         {
+            "asDropdown": true,
+            "icon": "external link",
+            "includeVars": true,
+            "keepTime": true,
+            "tags": [
+               "loki"
+            ],
+            "targetBlank": false,
+            "title": "Loki Dashboards",
+            "type": "dashboards"
+         }
+      ],
+      "panels": [
+         {
+            "collapsed": false,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 0
+            },
+            "id": 17,
+            "panels": [ ],
+            "targets": [ ],
+            "title": "Main",
+            "type": "row"
+         },
+         {
+            "aliasColors": {
+               "5xx": "red"
+            },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { }
+               },
+               "overrides": [ ]
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 4,
+               "x": 0,
+               "y": 1
+            },
+            "hiddenSeries": false,
+            "id": 6,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": true,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum by (status) (\nlabel_replace(\n  label_replace(\n        rate(loki_request_duration_seconds_count{cluster=\"$cluster\", job=~\"($namespace)/loki\", route=~\"api_prom_query|api_prom_label|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n\"status\", \"${1}\", \"status_code\", \"([a-z]+)\")\n)",
+                  "legendFormat": "{{status}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Queries/Second",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 10,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": {
+               "5xx": "red"
+            },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { }
+               },
+               "overrides": [ ]
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 4,
+               "x": 4,
+               "y": 1
+            },
+            "hiddenSeries": false,
+            "id": 7,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": true,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum by (status) (\nlabel_replace(\n  label_replace(\n          rate(loki_request_duration_seconds_count{cluster=\"$cluster\", job=~\"($namespace)/loki\", route=~\"api_prom_push|loki_api_v1_push\"}[$__rate_interval]),\n   \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n\"status\", \"${1}\", \"status_code\", \"([a-z]+)\"))",
+                  "legendFormat": "{{status}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Pushes/Second",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 10,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { }
+               },
+               "overrides": [ ]
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 4,
+               "x": 12,
+               "y": 1
+            },
+            "hiddenSeries": false,
+            "id": 2,
+            "interval": "",
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "topk(10, sum(rate(loki_distributor_lines_received_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (tenant))",
+                  "legendFormat": "{{tenant}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Lines Per Tenant (top 10)",
+            "tooltip": {
+               "shared": false,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { },
+                  "unit": "MBs"
+               },
+               "overrides": [ ]
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 4,
+               "x": 16,
+               "y": 1
+            },
+            "hiddenSeries": false,
+            "id": 4,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "hideEmpty": true,
+               "hideZero": true,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "topk(10, sum(rate(loki_distributor_bytes_received_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (tenant)) / 1024 / 1024",
+                  "legendFormat": "{{tenant}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "MBs Per Tenant (Top 10)",
+            "tooltip": {
+               "shared": false,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { }
+               },
+               "overrides": [ ]
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 4,
+               "x": 20,
+               "y": 1
+            },
+            "hiddenSeries": false,
+            "id": 24,
+            "legend": {
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "increase(kube_pod_container_status_restarts_total{cluster=\"$cluster\", namespace=\"$namespace\"}[10m]) > 0",
+                  "hide": false,
+                  "interval": "",
+                  "legendFormat": "{{container}}-{{pod}}",
+                  "refId": "B"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Container Restarts",
+            "tooltip": {
+               "shared": true,
+               "sort": 2,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { },
+                  "unit": "ms"
+               },
+               "overrides": [ ]
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 10,
+               "w": 12,
+               "x": 0,
+               "y": 6
+            },
+            "hiddenSeries": false,
+            "id": 9,
+            "legend": {
+               "alignAsTable": true,
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "rightSide": true,
+               "show": true,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "histogram_quantile(0.99, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"api_prom_push|loki_api_v1_push\", cluster=~\"$cluster\"})) * 1e3",
+                  "legendFormat": ".99",
+                  "refId": "A"
+               },
+               {
+                  "expr": "histogram_quantile(0.75, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"api_prom_push|loki_api_v1_push\", cluster=~\"$cluster\"})) * 1e3",
+                  "legendFormat": ".9",
+                  "refId": "B"
+               },
+               {
+                  "expr": "histogram_quantile(0.5, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"api_prom_push|loki_api_v1_push\", cluster=~\"$cluster\"})) * 1e3",
+                  "legendFormat": ".5",
+                  "refId": "C"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Push Latency",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { },
+                  "unit": "ms"
+               },
+               "overrides": [ ]
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 6,
+               "x": 12,
+               "y": 6
+            },
+            "hiddenSeries": false,
+            "id": 12,
+            "legend": {
+               "alignAsTable": true,
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "rightSide": true,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "histogram_quantile(0.99, sum by (le) (cluster_job:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", cluster=~\"$cluster\"})) * 1e3",
+                  "legendFormat": ".99",
+                  "refId": "A"
+               },
+               {
+                  "expr": "histogram_quantile(0.9, sum by (le) (cluster_job:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", cluster=~\"$cluster\"})) * 1e3",
+                  "legendFormat": ".9",
+                  "refId": "B"
+               },
+               {
+                  "expr": "histogram_quantile(0.5, sum by (le) (cluster_job:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", cluster=~\"$cluster\"})) * 1e3",
+                  "legendFormat": ".5",
+                  "refId": "C"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Distributor Latency",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { }
+               },
+               "overrides": [ ]
+            },
+            "fill": 0,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 6,
+               "x": 18,
+               "y": 6
+            },
+            "hiddenSeries": false,
+            "id": 71,
+            "legend": {
+               "alignAsTable": true,
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "rightSide": true,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\", status_code!~\"5[0-9]{2}\"}[$__rate_interval])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\"}[$__rate_interval])) by (route) > 0",
+                  "interval": "",
+                  "legendFormat": "{{route}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Distributor Success Rate",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "decimals": null,
+                  "format": "percentunit",
+                  "label": "",
+                  "logBase": 1,
+                  "max": "1",
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { },
+                  "unit": "ms"
+               },
+               "overrides": [ ]
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 6,
+               "x": 12,
+               "y": 11
+            },
+            "hiddenSeries": false,
+            "id": 13,
+            "legend": {
+               "alignAsTable": true,
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "rightSide": true,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "histogram_quantile(0.99, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\", cluster=~\"$cluster\"})) * 1e3",
+                  "legendFormat": ".99",
+                  "refId": "A"
+               },
+               {
+                  "expr": "histogram_quantile(0.9, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\", cluster=~\"$cluster\"})) * 1e3",
+                  "hide": false,
+                  "legendFormat": ".9",
+                  "refId": "B"
+               },
+               {
+                  "expr": "histogram_quantile(0.5, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\", cluster=~\"$cluster\"})) * 1e3",
+                  "hide": false,
+                  "legendFormat": ".5",
+                  "refId": "C"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Ingester Latency Write",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { }
+               },
+               "overrides": [ ]
+            },
+            "fill": 0,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 6,
+               "x": 18,
+               "y": 11
+            },
+            "hiddenSeries": false,
+            "id": 72,
+            "legend": {
+               "alignAsTable": true,
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "rightSide": true,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\", status_code!~\"5[0-9]{2}\", route=\"/logproto.Pusher/Push\"}[$__rate_interval])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"}[$__rate_interval])) by (route) > 0",
+                  "interval": "",
+                  "legendFormat": "{{route}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Ingester Success Rate Write",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "decimals": null,
+                  "format": "percentunit",
+                  "label": "",
+                  "logBase": 1,
+                  "max": "1",
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { },
+                  "unit": "ms"
+               },
+               "overrides": [ ]
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 10,
+               "w": 12,
+               "x": 0,
+               "y": 16
+            },
+            "hiddenSeries": false,
+            "id": 10,
+            "legend": {
+               "alignAsTable": true,
+               "avg": false,
+               "current": false,
+               "hideEmpty": true,
+               "hideZero": false,
+               "max": false,
+               "min": false,
+               "rightSide": true,
+               "show": true,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "histogram_quantile(0.99, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"}))",
+                  "legendFormat": "{{route}}-.99",
+                  "refId": "A"
+               },
+               {
+                  "expr": "histogram_quantile(0.9, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"}))",
+                  "legendFormat": "{{route}}-.9",
+                  "refId": "B"
+               },
+               {
+                  "expr": "histogram_quantile(0.5, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"}))",
+                  "legendFormat": "{{route}}-.5",
+                  "refId": "C"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Query Latency",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { },
+                  "unit": "ms"
+               },
+               "overrides": [ ]
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 6,
+               "x": 12,
+               "y": 16
+            },
+            "hiddenSeries": false,
+            "id": 14,
+            "legend": {
+               "alignAsTable": true,
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "rightSide": true,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "histogram_quantile(0.99, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"})) * 1e3",
+                  "legendFormat": ".99-{{route}}",
+                  "refId": "A"
+               },
+               {
+                  "expr": "histogram_quantile(0.9, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"})) * 1e3",
+                  "legendFormat": ".9-{{route}}",
+                  "refId": "B"
+               },
+               {
+                  "expr": "histogram_quantile(0.5, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"})) * 1e3",
+                  "legendFormat": ".5-{{route}}",
+                  "refId": "C"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Querier Latency",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { }
+               },
+               "overrides": [ ]
+            },
+            "fill": 0,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 6,
+               "x": 18,
+               "y": 16
+            },
+            "hiddenSeries": false,
+            "id": 73,
+            "legend": {
+               "alignAsTable": true,
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "rightSide": true,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\", status_code!~\"5[0-9]{2}\"}[$__rate_interval])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\"}[$__rate_interval])) by (route) > 0",
+                  "interval": "",
+                  "legendFormat": "{{route}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Querier Success Rate",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "decimals": null,
+                  "format": "percentunit",
+                  "label": "",
+                  "logBase": 1,
+                  "max": "1",
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "description": "",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { },
+                  "unit": "ms"
+               },
+               "overrides": [ ]
+            },
+            "fill": 1,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 6,
+               "x": 12,
+               "y": 21
+            },
+            "hiddenSeries": false,
+            "id": 15,
+            "legend": {
+               "alignAsTable": true,
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "rightSide": true,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "histogram_quantile(0.99, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"/logproto.Querier/Query|/logproto.Querier/Label|/logproto.Querier/Series|/logproto.Querier/QuerySample|/logproto.Querier/GetChunkIDs\", cluster=\"$cluster\"})) * 1e3",
+                  "legendFormat": ".99-{{route}}",
+                  "refId": "A"
+               },
+               {
+                  "expr": "histogram_quantile(0.9, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"/logproto.Querier/Query|/logproto.Querier/Label|/logproto.Querier/Series|/logproto.Querier/QuerySample|/logproto.Querier/GetChunkIDs\", cluster=\"$cluster\"})) * 1e3",
+                  "legendFormat": ".9-{{route}}",
+                  "refId": "B"
+               },
+               {
+                  "expr": "histogram_quantile(0.5, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/loki\", route=~\"/logproto.Querier/Query|/logproto.Querier/Label|/logproto.Querier/Series|/logproto.Querier/QuerySample|/logproto.Querier/GetChunkIDs\", cluster=\"$cluster\"})) * 1e3",
+                  "legendFormat": ".5-{{route}}",
+                  "refId": "C"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Ingester Latency Read",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "aliasColors": { },
+            "bars": false,
+            "dashLength": 10,
+            "dashes": false,
+            "datasource": "$datasource",
+            "fieldConfig": {
+               "defaults": {
+                  "custom": { }
+               },
+               "overrides": [ ]
+            },
+            "fill": 0,
+            "fillGradient": 0,
+            "gridPos": {
+               "h": 5,
+               "w": 6,
+               "x": 18,
+               "y": 21
+            },
+            "hiddenSeries": false,
+            "id": 74,
+            "legend": {
+               "alignAsTable": true,
+               "avg": false,
+               "current": false,
+               "max": false,
+               "min": false,
+               "rightSide": true,
+               "show": false,
+               "total": false,
+               "values": false
+            },
+            "lines": true,
+            "linewidth": 1,
+            "nullPointMode": "null",
+            "options": {
+               "dataLinks": [ ]
+            },
+            "panels": [ ],
+            "percentage": false,
+            "pointradius": 2,
+            "points": false,
+            "renderer": "flot",
+            "seriesOverrides": [ ],
+            "spaceLength": 10,
+            "stack": false,
+            "steppedLine": false,
+            "targets": [
+               {
+                  "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\", status_code!~\"5[0-9]{2}\", route=~\"/logproto.Querier/Query|/logproto.Querier/Label|/logproto.Querier/Series|/logproto.Querier/QuerySample|/logproto.Querier/GetChunkIDs\"}[$__rate_interval])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\", route=~\"/logproto.Querier/Query|/logproto.Querier/Label|/logproto.Querier/Series|/logproto.Querier/QuerySample|/logproto.Querier/GetChunkIDs\"}[$__rate_interval])) by (route) > 0",
+                  "interval": "",
+                  "legendFormat": "{{route}}",
+                  "refId": "A"
+               }
+            ],
+            "thresholds": [ ],
+            "timeFrom": null,
+            "timeRegions": [ ],
+            "timeShift": null,
+            "title": "Ingester Success Rate Read",
+            "tooltip": {
+               "shared": true,
+               "sort": 0,
+               "value_type": "individual"
+            },
+            "type": "timeseries",
+            "xaxis": {
+               "buckets": null,
+               "mode": "time",
+               "name": null,
+               "show": true,
+               "values": [ ]
+            },
+            "yaxes": [
+               {
+                  "decimals": null,
+                  "format": "percentunit",
+                  "label": "",
+                  "logBase": 1,
+                  "max": "1",
+                  "min": null,
+                  "show": true
+               },
+               {
+                  "format": "short",
+                  "label": null,
+                  "logBase": 1,
+                  "max": null,
+                  "min": null,
+                  "show": true
+               }
+            ],
+            "yaxis": {
+               "align": false,
+               "alignLevel": null
+            }
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 26
+            },
+            "id": 110,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 12,
+                     "x": 0,
+                     "y": 27
+                  },
+                  "hiddenSeries": false,
+                  "id": 112,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "topk(10,sum by (tenant, reason) (rate(loki_discarded_samples_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])))",
+                        "interval": "",
+                        "legendFormat": "{{ tenant }} - {{ reason }}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Discarded Lines",
+                  "tooltip": {
+                     "shared": false,
+                     "sort": 0,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "color": {
+                           "mode": "thresholds"
+                        },
+                        "custom": {
+                           "align": "right",
+                           "cellOptions": {
+                              "type": "auto"
+                           },
+                           "inspect": false
+                        },
+                        "decimals": 2,
+                        "displayName": "",
+                        "mappings": [ ],
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [
+                              {
+                                 "color": "green",
+                                 "value": null
+                              },
+                              {
+                                 "color": "red",
+                                 "value": 80
+                              }
+                           ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "Time"
+                           },
+                           "properties": [
+                              {
+                                 "id": "displayName",
+                                 "value": "Time"
+                              },
+                              {
+                                 "id": "custom.align"
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "tenant"
+                           },
+                           "properties": [
+                              {
+                                 "id": "unit",
+                                 "value": "short"
+                              },
+                              {
+                                 "id": "decimals",
+                                 "value": 2
+                              },
+                              {
+                                 "id": "custom.align"
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "reason"
+                           },
+                           "properties": [
+                              {
+                                 "id": "unit",
+                                 "value": "short"
+                              },
+                              {
+                                 "id": "decimals",
+                                 "value": 2
+                              },
+                              {
+                                 "id": "custom.align"
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "gridPos": {
+                     "h": 8,
+                     "w": 12,
+                     "x": 12,
+                     "y": 27
+                  },
+                  "id": 113,
+                  "options": {
+                     "cellHeight": "sm",
+                     "footer": {
+                        "countRows": false,
+                        "fields": "",
+                        "reducer": [
+                           "sum"
+                        ],
+                        "show": false
+                     },
+                     "showHeader": true
+                  },
+                  "panels": [ ],
+                  "pluginVersion": "10.4.0",
+                  "targets": [
+                     {
+                        "expr": "topk(10, sum by (tenant, reason) (sum_over_time(increase(loki_discarded_samples_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])[$__range:$__rate_interval])))",
+                        "format": "table",
+                        "instant": true,
+                        "interval": "",
+                        "legendFormat": "{{ tenant }} - {{ reason }}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "Discarded Lines Per Interval",
+                  "transformations": [
+                     {
+                        "id": "merge",
+                        "options": {
+                           "reducers": [ ]
+                        }
+                     }
+                  ],
+                  "type": "table"
+               }
+            ],
+            "targets": [ ],
+            "title": "Limits",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 27
+            },
+            "id": 23,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 0,
+                     "y": 28
+                  },
+                  "hiddenSeries": false,
+                  "id": 26,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": false,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": true,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum by(pod) (rate(container_cpu_usage_seconds_total{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"loki.*\"}[$__rate_interval]))",
+                        "intervalFactor": 3,
+                        "legendFormat": "{{pod}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "CPU Usage",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "binBps"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 6,
+                     "y": 28
+                  },
+                  "hiddenSeries": false,
+                  "id": 27,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "hideEmpty": false,
+                     "hideZero": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": false,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": true,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "go_memstats_heap_inuse_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"loki.*\"}",
+                        "instant": false,
+                        "intervalFactor": 3,
+                        "legendFormat": "{{pod}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Memory Usage",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "bytes",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": true,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$loki_datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 4,
+                     "w": 12,
+                     "x": 12,
+                     "y": 28
+                  },
+                  "hiddenSeries": false,
+                  "id": 31,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": false,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [
+                     {
+                        "alias": "{}",
+                        "color": "#C4162A"
+                     }
+                  ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate({cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\"} | logfmt | level=\"error\"[$__auto]))",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Error Log Rate",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": false,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "datasource": "$loki_datasource",
+                  "gridPos": {
+                     "h": 18,
+                     "w": 12,
+                     "x": 12,
+                     "y": 32
+                  },
+                  "id": 29,
+                  "options": {
+                     "showLabels": false,
+                     "showTime": false,
+                     "sortOrder": "Descending",
+                     "wrapLogMessage": true
+                  },
+                  "panels": [ ],
+                  "targets": [
+                     {
+                        "expr": "{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\"} |= \"level=error\"",
+                        "refId": "A"
+                     }
+                  ],
+                  "timeFrom": null,
+                  "timeShift": null,
+                  "title": "Logs",
+                  "type": "logs"
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 0,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 0,
+                     "y": 35
+                  },
+                  "hiddenSeries": false,
+                  "id": 33,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\", status_code!~\"5[0-9]{2}\"}[$__rate_interval])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\"}[$__rate_interval])) by (route) > 0",
+                        "interval": "",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{route}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Success Rate",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "binBps"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 6,
+                     "y": 35
+                  },
+                  "hiddenSeries": false,
+                  "id": 32,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_distributor_ingester_append_failures_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{pod}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Append Failures By Ingester",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "binBps"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 0,
+                     "y": 42
+                  },
+                  "hiddenSeries": false,
+                  "id": 34,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_distributor_bytes_received_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{pod}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Bytes Received/Second",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "ops"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 6,
+                     "y": 42
+                  },
+                  "hiddenSeries": false,
+                  "id": 35,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_distributor_lines_received_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{pod}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Lines Received/Second",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "Distributor",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 28
+            },
+            "id": 19,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 0,
+                     "y": 29
+                  },
+                  "hiddenSeries": false,
+                  "id": 36,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": false,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": true,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum by(pod) (rate(container_cpu_usage_seconds_total{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"loki.*\"}[$__rate_interval]))",
+                        "intervalFactor": 3,
+                        "legendFormat": "{{pod}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "CPU Usage",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "binBps"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 0,
+                     "y": 36
+                  },
+                  "hiddenSeries": false,
+                  "id": 37,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "hideEmpty": false,
+                     "hideZero": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": false,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": true,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "go_memstats_heap_inuse_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"loki.*\"}",
+                        "instant": false,
+                        "intervalFactor": 3,
+                        "legendFormat": "{{pod}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Memory Usage",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "bytes",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": true,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$loki_datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 3,
+                     "w": 18,
+                     "x": 12,
+                     "y": 29
+                  },
+                  "hiddenSeries": false,
+                  "id": 38,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": false,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [
+                     {
+                        "alias": "{}",
+                        "color": "#F2495C"
+                     }
+                  ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate({cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\"} | logfmt | level=\"error\"[$__auto]))",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Error Log Rate",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": false,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "datasource": "$loki_datasource",
+                  "gridPos": {
+                     "h": 18,
+                     "w": 18,
+                     "x": 12,
+                     "y": 32
+                  },
+                  "id": 39,
+                  "options": {
+                     "showLabels": false,
+                     "showTime": false,
+                     "sortOrder": "Descending",
+                     "wrapLogMessage": true
+                  },
+                  "panels": [ ],
+                  "targets": [
+                     {
+                        "expr": "{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\"} |= \"level=error\"",
+                        "refId": "A"
+                     }
+                  ],
+                  "timeFrom": null,
+                  "timeShift": null,
+                  "title": "Logs",
+                  "type": "logs"
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 0,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 0,
+                     "y": 41
+                  },
+                  "hiddenSeries": false,
+                  "id": 67,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\", status_code!~\"5[0-9]{2}\"}[$__rate_interval])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\"}[$__rate_interval])) by (route) > 0",
+                        "interval": "",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{route}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Success Rate",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "Ingester",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 29
+            },
+            "id": 104,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 12,
+                     "x": 0,
+                     "y": 30
+                  },
+                  "hiddenSeries": false,
+                  "id": 106,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "hideEmpty": true,
+                     "hideZero": true,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "topk(10,sum by (tenant) (loki_ingester_memory_streams{cluster=\"$cluster\",job=~\"($namespace)/loki\"}))",
+                        "interval": "",
+                        "legendFormat": "{{ tenant }}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Active Streams",
+                  "tooltip": {
+                     "shared": false,
+                     "sort": 0,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 12,
+                     "x": 12,
+                     "y": 30
+                  },
+                  "hiddenSeries": false,
+                  "id": 108,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "hideEmpty": true,
+                     "hideZero": true,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "topk(10, sum by (tenant) (rate(loki_ingester_streams_created_total{cluster=\"$cluster\",job=~\"($namespace)/loki\"}[$__rate_interval]) > 0))",
+                        "interval": "",
+                        "legendFormat": "{{ tenant }}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Streams Created/Sec",
+                  "tooltip": {
+                     "shared": false,
+                     "sort": 0,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "Streams",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 30
+            },
+            "id": 94,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 12,
+                     "x": 0,
+                     "y": 31
+                  },
+                  "hiddenSeries": false,
+                  "id": 102,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [
+                     {
+                        "alias": "De-Dupe Ratio",
+                        "yaxis": 2
+                     }
+                  ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_ingester_chunks_flushed_total{cluster=\"$cluster\",job=~\"($namespace)/loki\"}[$__rate_interval]))",
+                        "interval": "",
+                        "legendFormat": "Chunks",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "sum(increase(loki_chunk_store_deduped_chunks_total{cluster=\"$cluster\", job=~\"($namespace)/loki\"}[$__rate_interval]))/sum(increase(loki_ingester_chunks_flushed_total{cluster=\"$cluster\", job=~\"($namespace)/loki\"}[$__rate_interval])) < 1",
+                        "interval": "",
+                        "legendFormat": "De-Dupe Ratio",
+                        "refId": "B"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Chunks Flushed/Sec",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 0,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "cards": {
+                     "cardPadding": null,
+                     "cardRound": null
+                  },
+                  "color": {
+                     "cardColor": "#b4ff00",
+                     "colorScale": "sqrt",
+                     "colorScheme": "interpolateSpectral",
+                     "exponent": 0.5,
+                     "mode": "spectrum"
+                  },
+                  "dataFormat": "tsbuckets",
+                  "datasource": "$datasource",
+                  "gridPos": {
+                     "h": 8,
+                     "w": 12,
+                     "x": 12,
+                     "y": 31
+                  },
+                  "heatmap": { },
+                  "hideZeroBuckets": false,
+                  "highlightCards": true,
+                  "id": 100,
+                  "legend": {
+                     "show": true
+                  },
+                  "panels": [ ],
+                  "reverseYBuckets": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_ingester_chunk_size_bytes_bucket{cluster=\"$cluster\",job=~\"($namespace)/loki\"}[$__rate_interval])) by (le)",
+                        "format": "heatmap",
+                        "instant": false,
+                        "interval": "",
+                        "legendFormat": "{{ le }}",
+                        "refId": "A"
+                     }
+                  ],
+                  "timeFrom": null,
+                  "timeShift": null,
+                  "title": "Chunk Size Bytes",
+                  "tooltip": {
+                     "show": true,
+                     "showHistogram": false
+                  },
+                  "type": "heatmap",
+                  "xAxis": {
+                     "show": true
+                  },
+                  "xBucketNumber": null,
+                  "xBucketSize": null,
+                  "yAxis": {
+                     "decimals": 0,
+                     "format": "bytes",
+                     "logBase": 1,
+                     "max": null,
+                     "min": null,
+                     "show": true,
+                     "splitFactor": null
+                  },
+                  "yBucketBound": "auto",
+                  "yBucketNumber": null,
+                  "yBucketSize": null
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 7,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 9,
+                     "w": 12,
+                     "x": 0,
+                     "y": 39
+                  },
+                  "hiddenSeries": false,
+                  "id": 96,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": true,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum by(reason) (rate(loki_ingester_chunks_flushed_total{cluster=~\"$cluster\",job=~\"($namespace)/loki\", namespace=~\"$namespace\"}[$__rate_interval])) / ignoring(reason) group_left sum(rate(loki_ingester_chunks_flushed_total{cluster=~\"$cluster\",job=~\"($namespace)/loki\", namespace=~\"$namespace\"}[$__rate_interval]))",
+                        "interval": "",
+                        "legendFormat": "{{ reason }}"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Chunk Flush Reason %",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 0,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "percentunit",
+                        "label": null,
+                        "logBase": 1,
+                        "max": "1",
+                        "min": "0",
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "cards": {
+                     "cardPadding": null,
+                     "cardRound": null
+                  },
+                  "color": {
+                     "cardColor": "#b4ff00",
+                     "colorScale": "sqrt",
+                     "colorScheme": "interpolateSpectral",
+                     "exponent": 0.5,
+                     "max": null,
+                     "min": null,
+                     "mode": "spectrum"
+                  },
+                  "dataFormat": "tsbuckets",
+                  "datasource": "$datasource",
+                  "gridPos": {
+                     "h": 9,
+                     "w": 12,
+                     "x": 12,
+                     "y": 39
+                  },
+                  "heatmap": { },
+                  "hideZeroBuckets": true,
+                  "highlightCards": true,
+                  "id": 98,
+                  "legend": {
+                     "show": true
+                  },
+                  "panels": [ ],
+                  "reverseYBuckets": false,
+                  "targets": [
+                     {
+                        "expr": "sum by (le) (rate(loki_ingester_chunk_utilization_bucket{cluster=\"$cluster\", job=~\"($namespace)/loki\"}[$__rate_interval]))",
+                        "format": "heatmap",
+                        "instant": false,
+                        "interval": "",
+                        "legendFormat": "{{ le }}",
+                        "refId": "A"
+                     }
+                  ],
+                  "timeFrom": null,
+                  "timeShift": null,
+                  "title": "Chunk Utilization",
+                  "tooltip": {
+                     "show": true,
+                     "showHistogram": false
+                  },
+                  "type": "heatmap",
+                  "xAxis": {
+                     "show": true
+                  },
+                  "xBucketNumber": null,
+                  "xBucketSize": null,
+                  "yAxis": {
+                     "decimals": 0,
+                     "format": "percentunit",
+                     "logBase": 1,
+                     "max": null,
+                     "min": null,
+                     "show": true,
+                     "splitFactor": null
+                  },
+                  "yBucketBound": "auto",
+                  "yBucketNumber": null,
+                  "yBucketSize": null
+               }
+            ],
+            "targets": [ ],
+            "title": "Chunks",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 31
+            },
+            "id": 64,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 0,
+                     "y": 32
+                  },
+                  "hiddenSeries": false,
+                  "id": 68,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": false,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": true,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum by(pod) (rate(container_cpu_usage_seconds_total{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"loki.*\"}[$__rate_interval]))",
+                        "intervalFactor": 3,
+                        "legendFormat": "{{pod}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "CPU Usage",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "binBps"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 0,
+                     "y": 39
+                  },
+                  "hiddenSeries": false,
+                  "id": 69,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "hideEmpty": false,
+                     "hideZero": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": false,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": true,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "go_memstats_heap_inuse_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"loki.*\"}",
+                        "instant": false,
+                        "intervalFactor": 3,
+                        "legendFormat": "{{pod}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Memory Usage",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "bytes",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": true,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$loki_datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 3,
+                     "w": 18,
+                     "x": 12,
+                     "y": 32
+                  },
+                  "hiddenSeries": false,
+                  "id": 65,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": false,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [
+                     {
+                        "alias": "{}",
+                        "color": "#F2495C"
+                     }
+                  ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate({cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\"} | logfmt |  level=\"error\"[$__auto]))",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Error Log Rate",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": false,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "datasource": "$loki_datasource",
+                  "gridPos": {
+                     "h": 18,
+                     "w": 18,
+                     "x": 12,
+                     "y": 35
+                  },
+                  "id": 66,
+                  "options": {
+                     "showLabels": false,
+                     "showTime": false,
+                     "sortOrder": "Descending",
+                     "wrapLogMessage": true
+                  },
+                  "panels": [ ],
+                  "targets": [
+                     {
+                        "expr": "{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\"} |= \"level=error\"",
+                        "refId": "A"
+                     }
+                  ],
+                  "timeFrom": null,
+                  "timeShift": null,
+                  "title": "Logs",
+                  "type": "logs"
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 0,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 0,
+                     "y": 46
+                  },
+                  "hiddenSeries": false,
+                  "id": 70,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\", status_code!~\"5[0-9]{2}\"}[$__rate_interval])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/loki\"}[$__rate_interval])) by (route) > 0",
+                        "interval": "",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{route}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Success Rate",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "Querier",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 32
+            },
+            "id": 52,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "s"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 30
+                  },
+                  "hiddenSeries": false,
+                  "id": 53,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_memcache_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (method, name, le, container))",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{container}}: .99-{{method}}-{{name}}",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_memcache_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (method, name, le, container))",
+                        "hide": false,
+                        "legendFormat": "{{container}}: .9-{{method}}-{{name}}",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_memcache_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (method, name, le, container))",
+                        "hide": false,
+                        "legendFormat": "{{container}}: .5-{{method}}-{{name}}",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Latency By Method",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 38
+                  },
+                  "hiddenSeries": false,
+                  "id": 54,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_memcache_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (status_code, method, name, container)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{container}}: {{status_code}}-{{method}}-{{name}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Status By Method",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "Memcached",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 33
+            },
+            "id": 57,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "s"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 31
+                  },
+                  "hiddenSeries": false,
+                  "id": 55,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_consul_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "intervalFactor": 1,
+                        "legendFormat": ".99-{{operation}}",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_consul_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".9-{{operation}}",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_consul_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".5-{{operation}}",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Latency By Operation",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "ops"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 39
+                  },
+                  "hiddenSeries": false,
+                  "id": 58,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_consul_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, status_code, method)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{status_code}}-{{operation}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Status By Operation",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "Consul",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 34
+            },
+            "id": 43,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "s"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 0,
+                     "y": 9
+                  },
+                  "hiddenSeries": false,
+                  "id": 41,
+                  "interval": "",
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/MutateRows\"}[$__rate_interval])) by (operation, le))",
+                        "intervalFactor": 1,
+                        "legendFormat": ".9",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/MutateRows\"}[$__rate_interval])) by (operation, le))",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/MutateRows\"}[$__rate_interval])) by (operation, le))",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "MutateRows Latency",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "s"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 6,
+                     "y": 9
+                  },
+                  "hiddenSeries": false,
+                  "id": 46,
+                  "interval": "",
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/ReadRows\"}[$__rate_interval])) by (operation, le))",
+                        "interval": "",
+                        "intervalFactor": 1,
+                        "legendFormat": "99%",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/ReadRows\"}[$__rate_interval])) by (operation, le))",
+                        "interval": "",
+                        "legendFormat": "90%",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/ReadRows\"}[$__rate_interval])) by (operation, le))",
+                        "interval": "",
+                        "legendFormat": "50%",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "ReadRows Latency",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "s"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 12,
+                     "y": 9
+                  },
+                  "hiddenSeries": false,
+                  "id": 44,
+                  "interval": "",
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/GetTable\"}[$__rate_interval])) by (operation, le))",
+                        "interval": "",
+                        "intervalFactor": 1,
+                        "legendFormat": "99%",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/GetTable\"}[$__rate_interval])) by (operation, le))",
+                        "interval": "",
+                        "legendFormat": "90%",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/GetTable\"}[$__rate_interval])) by (operation, le))",
+                        "interval": "",
+                        "legendFormat": "50%",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "GetTable Latency",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "s"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 18,
+                     "y": 9
+                  },
+                  "hiddenSeries": false,
+                  "id": 45,
+                  "interval": "",
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/ListTables\"}[$__rate_interval])) by (operation, le))",
+                        "intervalFactor": 1,
+                        "legendFormat": ".9",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/ListTables\"}[$__rate_interval])) by (operation, le))",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/ListTables\"}[$__rate_interval])) by (operation, le))",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "ListTables Latency",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "ops"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 0,
+                     "y": 16
+                  },
+                  "hiddenSeries": false,
+                  "id": 47,
+                  "interval": "",
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_bigtable_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/MutateRows\"}[$__rate_interval])) by (status_code)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{status_code}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "MutateRows Status",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "ops"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 6,
+                     "y": 16
+                  },
+                  "hiddenSeries": false,
+                  "id": 50,
+                  "interval": "",
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_bigtable_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/ReadRows\"}[$__rate_interval])) by (status_code)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{status_code}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "ReadRows Status",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "ops"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 12,
+                     "y": 16
+                  },
+                  "hiddenSeries": false,
+                  "id": 48,
+                  "interval": "",
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_bigtable_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/GetTable\"}[$__rate_interval])) by (status_code)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{status_code}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "GetTable Status",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "ops"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 7,
+                     "w": 6,
+                     "x": 18,
+                     "y": 16
+                  },
+                  "hiddenSeries": false,
+                  "id": 49,
+                  "interval": "",
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": false,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_bigtable_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/ListTables\"}[$__rate_interval])) by (status_code)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{status_code}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "ListTables Status",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "Big Table",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 35
+            },
+            "id": 60,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "s"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 33
+                  },
+                  "hiddenSeries": false,
+                  "id": 61,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_gcs_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "intervalFactor": 1,
+                        "legendFormat": ".99-{{operation}}",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_gcs_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".9-{{operation}}",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_gcs_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".5-{{operation}}",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Latency By Operation",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 41
+                  },
+                  "hiddenSeries": false,
+                  "id": 62,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_gcs_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (status_code, operation)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{status_code}}-{{operation}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Status By Method",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "GCS",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 36
+            },
+            "id": 76,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": null,
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 6,
+                     "w": 6,
+                     "x": 0,
+                     "y": 9
+                  },
+                  "id": 82,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_dynamo_failures_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]))",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Failure Rate",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 0,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": null,
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 6,
+                     "w": 6,
+                     "x": 6,
+                     "y": 9
+                  },
+                  "id": 83,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_dynamo_consumed_capacity_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]))",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Consumed Capacity Rate",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 0,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": null,
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 6,
+                     "w": 6,
+                     "x": 12,
+                     "y": 9
+                  },
+                  "id": 84,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_dynamo_throttled_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]))",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Throttled Rate",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 0,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": null,
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 6,
+                     "w": 6,
+                     "x": 18,
+                     "y": 9
+                  },
+                  "id": 85,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_dynamo_dropped_requests_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]))",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Dropped Rate",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 0,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": null,
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 6,
+                     "w": 6,
+                     "x": 0,
+                     "y": 15
+                  },
+                  "id": 86,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 2,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_dynamo_query_pages_count{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])))",
+                        "legendFormat": ".99",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_dynamo_query_pages_count{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])))",
+                        "legendFormat": ".9",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_dynamo_query_pages_count{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])))",
+                        "legendFormat": ".5",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Query Pages",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 0,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "s"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 6,
+                     "w": 9,
+                     "x": 6,
+                     "y": 15
+                  },
+                  "id": 87,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_dynamo_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "intervalFactor": 1,
+                        "legendFormat": ".99-{{operation}}",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_dynamo_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".9-{{operation}}",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_dynamo_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".5-{{operation}}",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Latency By Operation",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 6,
+                     "w": 9,
+                     "x": 15,
+                     "y": 15
+                  },
+                  "id": 88,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_dynamo_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (status_code, operation)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{status_code}}-{{operation}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Status By Method",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "Dynamo",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 37
+            },
+            "id": 78,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "s"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 10
+                  },
+                  "id": 79,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_s3_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "intervalFactor": 1,
+                        "legendFormat": ".99-{{operation}}",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_s3_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".9-{{operation}}",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_s3_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".5-{{operation}}",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Latency By Operation",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 18
+                  },
+                  "id": 80,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_s3_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (status_code, operation)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{status_code}}-{{operation}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Status By Method",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "S3",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 37
+            },
+            "id": 78,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "s"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 10
+                  },
+                  "id": 79,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_azure_blob_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "intervalFactor": 1,
+                        "legendFormat": ".99-{{operation}}",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_azure_blob_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".9-{{operation}}",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_azure_blob_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".5-{{operation}}",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Latency By Operation",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 18
+                  },
+                  "id": 80,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_azure_blob_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (status_code, operation)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{status_code}}-{{operation}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Status By Method",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "Azure Blob",
+            "type": "row"
+         },
+         {
+            "collapsed": true,
+            "datasource": null,
+            "gridPos": {
+               "h": 1,
+               "w": 24,
+               "x": 0,
+               "y": 37
+            },
+            "id": 114,
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "unit": "s"
+                     }
+                  },
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 10
+                  },
+                  "id": 115,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(.99, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "intervalFactor": 1,
+                        "legendFormat": ".99-{{operation}}",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(.9, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".9-{{operation}}",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "histogram_quantile(.5, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (operation, le))",
+                        "hide": false,
+                        "legendFormat": ".5-{{operation}}",
+                        "refId": "C"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Latency By Operation",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               },
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fill": 1,
+                  "fillGradient": 0,
+                  "gridPos": {
+                     "h": 8,
+                     "w": 24,
+                     "x": 0,
+                     "y": 18
+                  },
+                  "id": 116,
+                  "interval": "",
+                  "legend": {
+                     "alignAsTable": true,
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "rightSide": true,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "nullPointMode": "null",
+                  "options": {
+                     "dataLinks": [ ]
+                  },
+                  "panels": [ ],
+                  "percentage": false,
+                  "pointradius": 1,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "sum(rate(loki_boltdb_shipper_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (status_code, operation)",
+                        "intervalFactor": 1,
+                        "legendFormat": "{{status_code}}-{{operation}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeRegions": [ ],
+                  "timeShift": null,
+                  "title": "Status By Method",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "timeseries",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": true
+                     }
+                  ],
+                  "yaxis": {
+                     "align": false,
+                     "alignLevel": null
+                  }
+               }
+            ],
+            "targets": [ ],
+            "title": "BoltDB Shipper",
+            "type": "row"
+         }
+      ],
+      "refresh": "10s",
+      "rows": [ ],
+      "schemaVersion": 14,
+      "style": "dark",
+      "tags": [
+         "loki"
+      ],
+      "templating": {
+         "list": [
+            {
+               "current": {
+                  "text": "default",
+                  "value": "default"
+               },
+               "hide": 0,
+               "label": "Data source",
+               "name": "datasource",
+               "options": [ ],
+               "query": "prometheus",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            },
+            {
+               "hide": 0,
+               "label": null,
+               "name": "loki_datasource",
+               "options": [ ],
+               "query": "loki",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "cluster",
+               "multi": false,
+               "name": "cluster",
+               "options": [ ],
+               "query": "label_values(loki_build_info, cluster)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "namespace",
+               "multi": false,
+               "name": "namespace",
+               "options": [ ],
+               "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            }
+         ]
+      },
+      "time": {
+         "from": "now-1h",
+         "to": "now"
+      },
+      "timepicker": {
+         "refresh_intervals": [
+            "5s",
+            "10s",
+            "30s",
+            "1m",
+            "5m",
+            "15m",
+            "30m",
+            "1h",
+            "2h",
+            "1d"
+         ],
+         "time_options": [
+            "5m",
+            "15m",
+            "1h",
+            "6h",
+            "12h",
+            "24h",
+            "2d",
+            "7d",
+            "30d"
+         ]
+      },
+      "timezone": "utc",
+      "title": "Loki / Operational",
+      "uid": "operational",
+      "version": 0
+   }
\ No newline at end of file
diff --git a/modules/grafana/grafana-dashboards/loki/loki-reads.json b/modules/grafana/grafana-dashboards/loki/loki-reads.json
new file mode 100644
index 00000000..59e8053f
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/loki/loki-reads.json
@@ -0,0 +1,2840 @@
+{
+      "annotations": {
+         "list": [ ]
+      },
+      "editable": true,
+      "gnetId": null,
+      "graphTooltip": 0,
+      "hideControls": false,
+      "links": [
+         {
+            "asDropdown": true,
+            "icon": "external link",
+            "includeVars": true,
+            "keepTime": true,
+            "tags": [
+               "loki"
+            ],
+            "targetBlank": false,
+            "title": "Loki Dashboards",
+            "type": "dashboards"
+         }
+      ],
+      "refresh": "10s",
+      "rows": [
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 1,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 2,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 99th percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 50th percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "1e3 * sum(cluster_job_route:loki_request_duration_seconds_sum:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"}) by (route)  / sum(cluster_job_route:loki_request_duration_seconds_count:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"}) by (route) ",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 3,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Frontend (query-frontend)",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 4,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 5,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 99th percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 50th percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "1e3 * sum(cluster_job_route:loki_request_duration_seconds_sum:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"}) by (route)  / sum(cluster_job_route:loki_request_duration_seconds_count:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"}) by (route) ",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 6,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(api_prom_rules|api_prom_rules_namespace_groupname|api_v1_rules|loki_api_v1_delete|loki_api_v1_detected_labels|loki_api_v1_index_stats|loki_api_v1_index_volume|loki_api_v1_index_volume_range|loki_api_v1_label_name_values|loki_api_v1_label_values|loki_api_v1_labels|loki_api_v1_patterns|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_series|prometheus_api_v1_rules)\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Querier",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 7,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 8,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 99th percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 50th percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "1e3 * sum(cluster_job_route:loki_request_duration_seconds_sum:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}) by (route)  / sum(cluster_job_route:loki_request_duration_seconds_count:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}) by (route) ",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 9,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Ingester",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 10,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 11,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 99th percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 50th percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "1e3 * sum(cluster_job_route:loki_request_duration_seconds_sum:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}) by (route)  / sum(cluster_job_route:loki_request_duration_seconds_count:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}) by (route) ",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 12,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Ingester - Zone Aware",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 13,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 14,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 99th percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 50th percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "1e3 * sum(cluster_job_route:loki_request_duration_seconds_sum:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}) by (route)  / sum(cluster_job_route:loki_request_duration_seconds_count:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}) by (route) ",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 15,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Index Gateway",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 16,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 17,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 99th percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum by (le,route) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} 50th percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "1e3 * sum(cluster_job_route:loki_request_duration_seconds_sum:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}) by (route)  / sum(cluster_job_route:loki_request_duration_seconds_count:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}) by (route) ",
+                        "format": "time_series",
+                        "legendFormat": "{{ route }} Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 18,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"(/base.Ruler/Rules|/indexgatewaypb.IndexGateway/GetChunkRef|/indexgatewaypb.IndexGateway/GetSeries|/indexgatewaypb.IndexGateway/GetShards|/indexgatewaypb.IndexGateway/GetStats|/indexgatewaypb.IndexGateway/GetVolume|/indexgatewaypb.IndexGateway/LabelNamesForMetricName|/indexgatewaypb.IndexGateway/LabelValuesForMetricName|/indexgatewaypb.IndexGateway/QueryIndex|/logproto.BloomGateway/FilterChunkRefs|/logproto.Pattern/Query|/logproto.Querier/GetChunkIDs|/logproto.Querier/GetDetectedLabels|/logproto.Querier/GetStats|/logproto.Querier/GetVolume|/logproto.Querier/Label|/logproto.Querier/Query|/logproto.Querier/QuerySample|/logproto.Querier/Series|/logproto.StreamData/GetStreamRates)\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Bloom Gateway",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 19,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_index_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation!=\"index_chunk\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 20,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_index_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation!=\"index_chunk\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "99th Percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum(rate(loki_index_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation!=\"index_chunk\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "50th Percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "sum(rate(loki_index_request_duration_seconds_sum{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation!=\"index_chunk\"}[$__rate_interval])) * 1e3 / sum(rate(loki_index_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation!=\"index_chunk\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 21,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_index_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation!=\"index_chunk\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "TSBD Index",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 22,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_boltdb_shipper_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"Shipper.Query\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 23,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"Shipper.Query\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "99th Percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"Shipper.Query\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "50th Percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "sum(rate(loki_boltdb_shipper_request_duration_seconds_sum{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"Shipper.Query\"}[$__rate_interval])) * 1e3 / sum(rate(loki_boltdb_shipper_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"Shipper.Query\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 24,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"Shipper.Query\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "BoltDB Index",
+            "titleSize": "h6"
+         }
+      ],
+      "schemaVersion": 14,
+      "style": "dark",
+      "tags": [
+         "loki"
+      ],
+      "templating": {
+         "list": [
+            {
+               "current": {
+                  "text": "default",
+                  "value": "default"
+               },
+               "hide": 0,
+               "label": "Data source",
+               "name": "datasource",
+               "options": [ ],
+               "query": "prometheus",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "cluster",
+               "multi": false,
+               "name": "cluster",
+               "options": [ ],
+               "query": "label_values(loki_build_info, cluster)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "namespace",
+               "multi": false,
+               "name": "namespace",
+               "options": [ ],
+               "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            }
+         ]
+      },
+      "time": {
+         "from": "now-1h",
+         "to": "now"
+      },
+      "timepicker": {
+         "refresh_intervals": [
+            "5s",
+            "10s",
+            "30s",
+            "1m",
+            "5m",
+            "15m",
+            "30m",
+            "1h",
+            "2h",
+            "1d"
+         ],
+         "time_options": [
+            "5m",
+            "15m",
+            "1h",
+            "6h",
+            "12h",
+            "24h",
+            "2d",
+            "7d",
+            "30d"
+         ]
+      },
+      "timezone": "utc",
+      "title": "Loki / Reads",
+      "uid": "reads",
+      "version": 0
+   }
\ No newline at end of file
diff --git a/modules/grafana/grafana-dashboards/loki/loki-retention.json b/modules/grafana/grafana-dashboards/loki/loki-retention.json
new file mode 100644
index 00000000..dd9c526d
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/loki/loki-retention.json
@@ -0,0 +1,1498 @@
+{
+      "annotations": {
+         "list": [ ]
+      },
+      "editable": true,
+      "gnetId": null,
+      "graphTooltip": 0,
+      "hideControls": false,
+      "links": [
+         {
+            "asDropdown": true,
+            "icon": "external link",
+            "includeVars": true,
+            "keepTime": true,
+            "tags": [
+               "loki"
+            ],
+            "targetBlank": false,
+            "title": "Loki Dashboards",
+            "type": "dashboards"
+         }
+      ],
+      "refresh": "10s",
+      "rows": [
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "request"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#FFC000",
+                                    "mode": "fixed"
+                                 }
+                              },
+                              {
+                                 "id": "custom.fillOpacity",
+                                 "value": 0
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "limit"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E02F44",
+                                    "mode": "fixed"
+                                 }
+                              },
+                              {
+                                 "id": "custom.fillOpacity",
+                                 "value": 0
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "id": 1,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "sum by(pod) (rate(container_cpu_usage_seconds_total{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"loki.*\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "{{pod}}",
+                        "legendLink": null
+                     },
+                     {
+                        "expr": "min(kube_pod_container_resource_requests{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"loki.*\", resource=\"cpu\"} > 0)",
+                        "format": "time_series",
+                        "legendFormat": "request",
+                        "legendLink": null
+                     },
+                     {
+                        "expr": "min(container_spec_cpu_quota{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"loki.*\"} / container_spec_cpu_period{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"loki.*\"})",
+                        "format": "time_series",
+                        "legendFormat": "limit",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "CPU",
+                  "tooltip": {
+                     "sort": 2
+                  },
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "bytes"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "request"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#FFC000",
+                                    "mode": "fixed"
+                                 }
+                              },
+                              {
+                                 "id": "custom.fillOpacity",
+                                 "value": 0
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "limit"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E02F44",
+                                    "mode": "fixed"
+                                 }
+                              },
+                              {
+                                 "id": "custom.fillOpacity",
+                                 "value": 0
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "id": 2,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "max by(pod) (container_memory_working_set_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"loki.*\"})",
+                        "format": "time_series",
+                        "legendFormat": "{{pod}}",
+                        "legendLink": null
+                     },
+                     {
+                        "expr": "min(kube_pod_container_resource_requests{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"loki.*\", resource=\"memory\"} > 0)",
+                        "format": "time_series",
+                        "legendFormat": "request",
+                        "legendLink": null
+                     },
+                     {
+                        "expr": "min(container_spec_memory_limit_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"loki.*\"} > 0)",
+                        "format": "time_series",
+                        "legendFormat": "limit",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Memory (workingset)",
+                  "tooltip": {
+                     "sort": 2
+                  },
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "bytes"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 3,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "sum by(pod) (go_memstats_heap_inuse_bytes{cluster=~\"$cluster\", job=~\"($namespace)/loki\"})",
+                        "format": "time_series",
+                        "legendFormat": "{{pod}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Memory (go heap inuse)",
+                  "tooltip": {
+                     "sort": 2
+                  },
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Resource Usage",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "color": {
+                           "fixedColor": "blue",
+                           "mode": "fixed"
+                        },
+                        "custom": { },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [
+                              {
+                                 "color": "green",
+                                 "value": null
+                              }
+                           ]
+                        },
+                        "unit": "dateTimeFromNow"
+                     }
+                  },
+                  "fill": 1,
+                  "id": 4,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "colorMode": "value",
+                     "graphMode": "area",
+                     "justifyMode": "auto",
+                     "orientation": "auto",
+                     "reduceOptions": {
+                        "calcs": [
+                           "lastNotNull"
+                        ],
+                        "fields": "",
+                        "values": false
+                     },
+                     "text": { },
+                     "textMode": "auto"
+                  },
+                  "percentage": false,
+                  "pointradius": 5,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "span": 6,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "loki_boltdb_shipper_compact_tables_operation_last_successful_run_timestamp_seconds{cluster=~\"$cluster\", namespace=~\"$namespace\"} * 1e3",
+                        "format": "time_series",
+                        "instant": true,
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeShift": null,
+                  "title": "Last Compact Tables Operation Success",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "stat",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "s"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 5,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "loki_boltdb_shipper_compact_tables_operation_duration_seconds{cluster=~\"$cluster\", namespace=~\"$namespace\"}",
+                        "format": "time_series",
+                        "legendFormat": "duration",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Compact Tables Operations Duration",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Compaction",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 6,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "sum(loki_compactor_locked_table_successive_compaction_skips{cluster=~\"$cluster\", namespace=~\"$namespace\"})",
+                        "format": "time_series",
+                        "legendFormat": "{{table_name}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Number of times Tables were skipped during Compaction",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 7,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "sum by (status)(rate(loki_boltdb_shipper_compact_tables_operation_total{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "{{success}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Compact Tables Operations Per Status",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": { },
+                  "bars": false,
+                  "dashLength": 10,
+                  "dashes": false,
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "color": {
+                           "fixedColor": "blue",
+                           "mode": "fixed"
+                        },
+                        "custom": { },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [
+                              {
+                                 "color": "green",
+                                 "value": null
+                              }
+                           ]
+                        },
+                        "unit": "dateTimeFromNow"
+                     }
+                  },
+                  "fill": 1,
+                  "id": 8,
+                  "legend": {
+                     "avg": false,
+                     "current": false,
+                     "max": false,
+                     "min": false,
+                     "show": true,
+                     "total": false,
+                     "values": false
+                  },
+                  "lines": true,
+                  "linewidth": 1,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "colorMode": "value",
+                     "graphMode": "area",
+                     "justifyMode": "auto",
+                     "orientation": "auto",
+                     "reduceOptions": {
+                        "calcs": [
+                           "lastNotNull"
+                        ],
+                        "fields": "",
+                        "values": false
+                     },
+                     "text": { },
+                     "textMode": "auto"
+                  },
+                  "percentage": false,
+                  "pointradius": 5,
+                  "points": false,
+                  "renderer": "flot",
+                  "seriesOverrides": [ ],
+                  "spaceLength": 10,
+                  "span": 4,
+                  "stack": false,
+                  "steppedLine": false,
+                  "targets": [
+                     {
+                        "expr": "loki_compactor_apply_retention_last_successful_run_timestamp_seconds{cluster=~\"$cluster\", namespace=~\"$namespace\"} * 1e3",
+                        "format": "time_series",
+                        "instant": true,
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": [ ],
+                  "timeFrom": null,
+                  "timeShift": null,
+                  "title": "Last Mark Operation Success",
+                  "tooltip": {
+                     "shared": true,
+                     "sort": 2,
+                     "value_type": "individual"
+                  },
+                  "type": "stat",
+                  "xaxis": {
+                     "buckets": null,
+                     "mode": "time",
+                     "name": null,
+                     "show": true,
+                     "values": [ ]
+                  },
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "s"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 9,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "loki_compactor_apply_retention_operation_duration_seconds{cluster=~\"$cluster\", namespace=~\"$namespace\"}",
+                        "format": "time_series",
+                        "legendFormat": "duration",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Mark Operations Duration",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 10,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "sum by (status)(rate(loki_compactor_apply_retention_operation_total{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "{{success}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Mark Operations Per Status",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Retention",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 11,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "count by(action)(loki_boltdb_shipper_retention_marker_table_processed_total{cluster=~\"$cluster\", namespace=~\"$namespace\"})",
+                        "format": "time_series",
+                        "legendFormat": "{{action}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Processed Tables Per Action",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 12,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "count by(table,action)(loki_boltdb_shipper_retention_marker_table_processed_total{cluster=~\"$cluster\", namespace=~\"$namespace\" , action=~\"modified|deleted\"})",
+                        "format": "time_series",
+                        "legendFormat": "{{table}}-{{action}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Modified Tables",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 13,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "sum by (table)(rate(loki_boltdb_shipper_retention_marker_count_total{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) >0",
+                        "format": "time_series",
+                        "legendFormat": "{{table}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Marks Creation Rate Per Table",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Per Table Marker",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "format": "short",
+                  "id": 14,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "sum (increase(loki_boltdb_shipper_retention_marker_count_total{cluster=~\"$cluster\", namespace=~\"$namespace\"}[24h]))",
+                        "format": "time_series",
+                        "instant": true,
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": "70,80",
+                  "title": "Marked Chunks (24h)",
+                  "type": "singlestat"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 15,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_boltdb_shipper_retention_marker_table_processed_duration_seconds_bucket{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "99th Percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum(rate(loki_boltdb_shipper_retention_marker_table_processed_duration_seconds_bucket{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "50th Percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "sum(rate(loki_boltdb_shipper_retention_marker_table_processed_duration_seconds_sum{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) * 1e3 / sum(rate(loki_boltdb_shipper_retention_marker_table_processed_duration_seconds_count{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Mark Table Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "format": "short",
+                  "id": 16,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "sum (increase(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_count{cluster=~\"$cluster\", namespace=~\"$namespace\"}[24h]))",
+                        "format": "time_series",
+                        "instant": true,
+                        "refId": "A"
+                     }
+                  ],
+                  "thresholds": "70,80",
+                  "title": "Delete Chunks (24h)",
+                  "type": "singlestat"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 17,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_bucket{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "99th Percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum(rate(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_bucket{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "50th Percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "sum(rate(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_sum{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) * 1e3 / sum(rate(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_count{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Delete Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Sweeper",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "s"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 18,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "time() - (loki_boltdb_shipper_retention_sweeper_marker_file_processing_current_time{cluster=~\"$cluster\", namespace=~\"$namespace\"} > 0)",
+                        "format": "time_series",
+                        "legendFormat": "lag",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Sweeper Lag",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 19,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "sum(loki_boltdb_shipper_retention_sweeper_marker_files_current{cluster=~\"$cluster\", namespace=~\"$namespace\"})",
+                        "format": "time_series",
+                        "legendFormat": "count",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Marks Files to Process",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 20,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "sum by (status)(rate(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_count{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Delete Rate Per Status",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$loki_datasource",
+                  "id": 21,
+                  "span": 12,
+                  "targets": [
+                     {
+                        "expr": "{cluster=~\"$cluster\", job=~\"($namespace)/loki\"}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "Compactor Logs",
+                  "type": "logs"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Logs",
+            "titleSize": "h6"
+         }
+      ],
+      "schemaVersion": 14,
+      "style": "dark",
+      "tags": [
+         "loki"
+      ],
+      "templating": {
+         "list": [
+            {
+               "current": {
+                  "text": "default",
+                  "value": "default"
+               },
+               "hide": 0,
+               "label": "Data source",
+               "name": "datasource",
+               "options": [ ],
+               "query": "prometheus",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "cluster",
+               "multi": false,
+               "name": "cluster",
+               "options": [ ],
+               "query": "label_values(loki_build_info, cluster)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "namespace",
+               "multi": false,
+               "name": "namespace",
+               "options": [ ],
+               "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "hide": 0,
+               "label": null,
+               "name": "loki_datasource",
+               "options": [ ],
+               "query": "loki",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            }
+         ]
+      },
+      "time": {
+         "from": "now-1h",
+         "to": "now"
+      },
+      "timepicker": {
+         "refresh_intervals": [
+            "5s",
+            "10s",
+            "30s",
+            "1m",
+            "5m",
+            "15m",
+            "30m",
+            "1h",
+            "2h",
+            "1d"
+         ],
+         "time_options": [
+            "5m",
+            "15m",
+            "1h",
+            "6h",
+            "12h",
+            "24h",
+            "2d",
+            "7d",
+            "30d"
+         ]
+      },
+      "timezone": "utc",
+      "title": "Loki / Retention",
+      "uid": "retention",
+      "version": 0
+   }
\ No newline at end of file
diff --git a/modules/grafana/grafana-dashboards/loki/loki-writes.json b/modules/grafana/grafana-dashboards/loki/loki-writes.json
new file mode 100644
index 00000000..595a50ef
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/loki/loki-writes.json
@@ -0,0 +1,1948 @@
+{
+      "annotations": {
+         "list": [ ]
+      },
+      "editable": true,
+      "gnetId": null,
+      "graphTooltip": 0,
+      "hideControls": false,
+      "links": [
+         {
+            "asDropdown": true,
+            "icon": "external link",
+            "includeVars": true,
+            "keepTime": true,
+            "tags": [
+               "loki"
+            ],
+            "targetBlank": false,
+            "title": "Loki Dashboards",
+            "type": "dashboards"
+         }
+      ],
+      "refresh": "10s",
+      "rows": [
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 1,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", route=~\"api_prom_push|loki_api_v1_push|otlp_v1_logs|/httpgrpc.HTTP/Handle\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 2,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"api_prom_push|loki_api_v1_push|otlp_v1_logs|/httpgrpc.HTTP/Handle\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "99th percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"api_prom_push|loki_api_v1_push|otlp_v1_logs|/httpgrpc.HTTP/Handle\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "50th percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "1e3 * sum(cluster_job_route:loki_request_duration_seconds_sum:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"api_prom_push|loki_api_v1_push|otlp_v1_logs|/httpgrpc.HTTP/Handle\"}) / sum(cluster_job_route:loki_request_duration_seconds_count:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"api_prom_push|loki_api_v1_push|otlp_v1_logs|/httpgrpc.HTTP/Handle\"})",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 3,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=~\"api_prom_push|loki_api_v1_push|otlp_v1_logs|/httpgrpc.HTTP/Handle\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Distributor",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 4,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "targets": [
+                     {
+                        "expr": "sum (rate(loki_distributor_structured_metadata_bytes_received_total{cluster=~\"$cluster\",job=~\"($namespace)/loki\",}[$__rate_interval])) / sum(rate(loki_distributor_bytes_received_total{cluster=~\"$cluster\",job=~\"($namespace)/loki\",}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "bytes",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Per Total Received Bytes",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 5,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 6,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (tenant) (rate(loki_distributor_structured_metadata_bytes_received_total{cluster=~\"$cluster\",job=~\"($namespace)/loki\",}[$__rate_interval])) / ignoring(tenant) group_left sum(rate(loki_distributor_structured_metadata_bytes_received_total{cluster=~\"$cluster\",job=~\"($namespace)/loki\",}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "{{tenant}}",
+                        "legendLink": null
+                     }
+                  ],
+                  "title": "Per Tenant",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": 1,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": 1,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Distributor - Structured Metadata",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 6,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 7,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "99th percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "50th percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "1e3 * sum(cluster_job_route:loki_request_duration_seconds_sum:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"}) / sum(cluster_job_route:loki_request_duration_seconds_count:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"})",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 8,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Ingester - Zone Aware",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 9,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 10,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "99th percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum by (le) (cluster_job_route:loki_request_duration_seconds_bucket:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"})) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "50th percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "1e3 * sum(cluster_job_route:loki_request_duration_seconds_sum:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"}) / sum(cluster_job_route:loki_request_duration_seconds_count:sum_rate{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"})",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 11,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket{cluster=~\"$cluster\", job=~\"($namespace)/loki\", route=\"/logproto.Pusher/Push\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Ingester",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 12,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_index_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"index_chunk\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 13,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_index_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"index_chunk\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "99th Percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum(rate(loki_index_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"index_chunk\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "50th Percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "sum(rate(loki_index_request_duration_seconds_sum{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"index_chunk\"}[$__rate_interval])) * 1e3 / sum(rate(loki_index_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"index_chunk\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 14,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_index_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"index_chunk\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "Index",
+            "titleSize": "h6"
+         },
+         {
+            "collapse": false,
+            "height": "250px",
+            "panels": [
+               {
+                  "aliasColors": {
+                     "1xx": "#EAB839",
+                     "2xx": "#7EB26D",
+                     "3xx": "#6ED0E0",
+                     "4xx": "#EF843C",
+                     "5xx": "#E24D42",
+                     "OK": "#7EB26D",
+                     "cancel": "#A9A9A9",
+                     "error": "#E24D42",
+                     "success": "#7EB26D"
+                  },
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 100,
+                           "lineWidth": 0,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "normal"
+                           }
+                        },
+                        "min": 0,
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "short"
+                     },
+                     "overrides": [
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "1xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EAB839",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "2xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "3xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#6ED0E0",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "4xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#EF843C",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "5xx"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "OK"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "cancel"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#A9A9A9",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "error"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#E24D42",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        },
+                        {
+                           "matcher": {
+                              "id": "byName",
+                              "options": "success"
+                           },
+                           "properties": [
+                              {
+                                 "id": "color",
+                                 "value": {
+                                    "fixedColor": "#7EB26D",
+                                    "mode": "fixed"
+                                 }
+                              }
+                           ]
+                        }
+                     ]
+                  },
+                  "fill": 10,
+                  "id": 15,
+                  "linewidth": 0,
+                  "links": [ ],
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "stack": true,
+                  "targets": [
+                     {
+                        "expr": "sum by (status) (\n  label_replace(label_replace(rate(loki_boltdb_shipper_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"WRITE\"}[$__rate_interval]),\n  \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n  \"status\", \"${1}\", \"status_code\", \"([a-zA-Z]+)\"))\n",
+                        "format": "time_series",
+                        "legendFormat": "{{status}}",
+                        "refId": "A"
+                     }
+                  ],
+                  "title": "QPS",
+                  "type": "timeseries"
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 16,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"WRITE\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "99th Percentile",
+                        "refId": "A"
+                     },
+                     {
+                        "expr": "histogram_quantile(0.50, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"WRITE\"}[$__rate_interval])) by (le)) * 1e3",
+                        "format": "time_series",
+                        "legendFormat": "50th Percentile",
+                        "refId": "B"
+                     },
+                     {
+                        "expr": "sum(rate(loki_boltdb_shipper_request_duration_seconds_sum{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"WRITE\"}[$__rate_interval])) * 1e3 / sum(rate(loki_boltdb_shipper_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"WRITE\"}[$__rate_interval]))",
+                        "format": "time_series",
+                        "legendFormat": "Average",
+                        "refId": "C"
+                     }
+                  ],
+                  "title": "Latency",
+                  "type": "timeseries",
+                  "yaxes": [
+                     {
+                        "format": "ms",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": 0,
+                        "show": true
+                     },
+                     {
+                        "format": "short",
+                        "label": null,
+                        "logBase": 1,
+                        "max": null,
+                        "min": null,
+                        "show": false
+                     }
+                  ]
+               },
+               {
+                  "datasource": "$datasource",
+                  "fieldConfig": {
+                     "defaults": {
+                        "custom": {
+                           "drawStyle": "line",
+                           "fillOpacity": 10,
+                           "lineWidth": 1,
+                           "pointSize": 5,
+                           "showPoints": "never",
+                           "spanNulls": false,
+                           "stacking": {
+                              "group": "A",
+                              "mode": "none"
+                           }
+                        },
+                        "thresholds": {
+                           "mode": "absolute",
+                           "steps": [ ]
+                        },
+                        "unit": "ms"
+                     },
+                     "overrides": [ ]
+                  },
+                  "id": 17,
+                  "links": [ ],
+                  "nullPointMode": "null as zero",
+                  "options": {
+                     "legend": {
+                        "showLegend": true
+                     },
+                     "tooltip": {
+                        "mode": "single",
+                        "sort": "none"
+                     }
+                  },
+                  "span": 4,
+                  "targets": [
+                     {
+                        "expr": "histogram_quantile(0.99, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/loki\", operation=\"WRITE\"}[$__rate_interval])) by (le,pod)) * 1e3",
+                        "format": "time_series",
+                        "interval": "1m",
+                        "intervalFactor": 2,
+                        "legendFormat": "__auto",
+                        "refId": "A",
+                        "step": 10
+                     }
+                  ],
+                  "title": "Per Pod Latency (p99)",
+                  "type": "timeseries"
+               }
+            ],
+            "repeat": null,
+            "repeatIteration": null,
+            "repeatRowId": null,
+            "showTitle": true,
+            "title": "BoltDB Index",
+            "titleSize": "h6"
+         }
+      ],
+      "schemaVersion": 14,
+      "style": "dark",
+      "tags": [
+         "loki"
+      ],
+      "templating": {
+         "list": [
+            {
+               "current": {
+                  "text": "default",
+                  "value": "default"
+               },
+               "hide": 0,
+               "label": "Data source",
+               "name": "datasource",
+               "options": [ ],
+               "query": "prometheus",
+               "refresh": 1,
+               "regex": "",
+               "type": "datasource"
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "cluster",
+               "multi": false,
+               "name": "cluster",
+               "options": [ ],
+               "query": "label_values(loki_build_info, cluster)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            },
+            {
+               "allValue": null,
+               "current": {
+                  "text": "prod",
+                  "value": "prod"
+               },
+               "datasource": "$datasource",
+               "hide": 0,
+               "includeAll": false,
+               "label": "namespace",
+               "multi": false,
+               "name": "namespace",
+               "options": [ ],
+               "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)",
+               "refresh": 1,
+               "regex": "",
+               "sort": 2,
+               "tagValuesQuery": "",
+               "tags": [ ],
+               "tagsQuery": "",
+               "type": "query",
+               "useTags": false
+            }
+         ]
+      },
+      "time": {
+         "from": "now-1h",
+         "to": "now"
+      },
+      "timepicker": {
+         "refresh_intervals": [
+            "5s",
+            "10s",
+            "30s",
+            "1m",
+            "5m",
+            "15m",
+            "30m",
+            "1h",
+            "2h",
+            "1d"
+         ],
+         "time_options": [
+            "5m",
+            "15m",
+            "1h",
+            "6h",
+            "12h",
+            "24h",
+            "2d",
+            "7d",
+            "30d"
+         ]
+      },
+      "timezone": "utc",
+      "title": "Loki / Writes",
+      "uid": "writes",
+      "version": 0
+   }
\ No newline at end of file
diff --git a/modules/grafana/grafana-dashboards/nextcloud.json b/modules/grafana/grafana-dashboards/nextcloud.json
new file mode 100644
index 00000000..77ae828a
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/nextcloud.json
@@ -0,0 +1,1150 @@
+{
+  "annotations": {
+    "list": [
+      {
+        "$$hashKey": "object:405",
+        "builtIn": 1,
+        "datasource": {
+          "type": "datasource",
+          "uid": "grafana"
+        },
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "target": {
+          "limit": 100,
+          "matchAny": false,
+          "tags": [],
+          "type": "dashboard"
+        },
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": true,
+  "fiscalYearStartMonth": 0,
+  "graphTooltip": 2,
+  "id": 17,
+  "links": [],
+  "panels": [
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 5,
+      "panels": [],
+      "title": "Users and Files",
+      "type": "row"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "min": 0,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 4,
+        "x": 0,
+        "y": 1
+      },
+      "id": 12,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "area",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "percentChangeColorMode": "standard",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "showPercentChange": false,
+        "textMode": "auto",
+        "wideLayout": true
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "expr": "sum by(instance) (nextcloud_active_users_daily_total{instance=\"$instance\"})",
+          "instant": false,
+          "legendFormat": "__auto",
+          "range": true,
+          "refId": "A"
+        }
+      ],
+      "title": "Daily Active Users",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisBorderShow": false,
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "barWidthFactor": 0.6,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "insertNulls": false,
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "links": [],
+          "mappings": [],
+          "min": 0,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 4,
+        "y": 1
+      },
+      "id": 1,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": false
+        },
+        "tooltip": {
+          "mode": "multi",
+          "sort": "desc"
+        }
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "expr": "sum by(instance) (nextcloud_users_total{instance=\"$instance\"})",
+          "intervalFactor": 1,
+          "legendFormat": "total ({{instance}})",
+          "metric": "",
+          "range": true,
+          "refId": "A",
+          "step": 900
+        },
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "expr": "sum by(instance) (nextcloud_active_users_total{instance=\"$instance\"})",
+          "hide": false,
+          "intervalFactor": 1,
+          "legendFormat": "active ({{instance}})",
+          "metric": "",
+          "range": true,
+          "refId": "B",
+          "step": 900
+        }
+      ],
+      "title": "Users",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisBorderShow": false,
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "barWidthFactor": 0.6,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "insertNulls": false,
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "links": [],
+          "mappings": [],
+          "min": 0,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 12,
+        "x": 12,
+        "y": 1
+      },
+      "id": 11,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": false
+        },
+        "tooltip": {
+          "mode": "multi",
+          "sort": "desc"
+        }
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "expr": "sum by(instance) (nextcloud_files_total{instance=\"$instance\"})",
+          "intervalFactor": 1,
+          "legendFormat": "__auto",
+          "metric": "",
+          "range": true,
+          "refId": "B",
+          "step": 900
+        }
+      ],
+      "title": "Files",
+      "type": "timeseries"
+    },
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 8
+      },
+      "id": 6,
+      "panels": [],
+      "title": "Shares",
+      "type": "row"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisBorderShow": false,
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "barWidthFactor": 0.6,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "insertNulls": false,
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "links": [],
+          "mappings": [],
+          "min": 0,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 12,
+        "x": 0,
+        "y": 9
+      },
+      "id": 2,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "multi",
+          "sort": "desc"
+        }
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "expr": "sum by(type) (nextcloud_shares_total{instance=\"$instance\"})",
+          "intervalFactor": 1,
+          "legendFormat": "{{type}}",
+          "metric": "",
+          "range": true,
+          "refId": "A",
+          "step": 1800
+        }
+      ],
+      "title": "Shares by Type",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisBorderShow": false,
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "barWidthFactor": 0.6,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "insertNulls": false,
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "links": [],
+          "mappings": [],
+          "min": 0,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 12,
+        "x": 12,
+        "y": 9
+      },
+      "id": 3,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "multi",
+          "sort": "desc"
+        }
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "expr": "sum by(direction) (nextcloud_shares_federated_total{instance=\"$instance\"})",
+          "intervalFactor": 1,
+          "legendFormat": "{{direction}}",
+          "metric": "",
+          "range": true,
+          "refId": "A",
+          "step": 1800
+        }
+      ],
+      "title": "Federated Shares",
+      "type": "timeseries"
+    },
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 16
+      },
+      "id": 7,
+      "panels": [],
+      "title": "Apps",
+      "type": "row"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "min": 0,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 4,
+        "x": 0,
+        "y": 17
+      },
+      "id": 9,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "area",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "percentChangeColorMode": "standard",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "showPercentChange": false,
+        "textMode": "auto",
+        "wideLayout": true
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "expr": "sum by(instance) (nextcloud_apps_installed_total{instance=\"$instance\"})",
+          "instant": false,
+          "legendFormat": "__auto",
+          "range": true,
+          "refId": "A"
+        }
+      ],
+      "title": "Installed Apps",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "min": 0,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "#EAB839",
+                "value": 1
+              }
+            ]
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 4,
+        "x": 4,
+        "y": 17
+      },
+      "id": 10,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "area",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "percentChangeColorMode": "standard",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "showPercentChange": false,
+        "textMode": "auto",
+        "wideLayout": true
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "expr": "sum by(instance) (nextcloud_apps_updates_available_total{instance=\"$instance\"})",
+          "instant": false,
+          "legendFormat": "__auto",
+          "range": true,
+          "refId": "A"
+        }
+      ],
+      "title": "Available Updates",
+      "type": "stat"
+    },
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 24
+      },
+      "id": 8,
+      "panels": [],
+      "title": "System Information",
+      "type": "row"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisBorderShow": false,
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "barWidthFactor": 0.6,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "insertNulls": false,
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "links": [],
+          "mappings": [],
+          "min": 0,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          },
+          "unit": "decbytes"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 12,
+        "x": 0,
+        "y": 25
+      },
+      "id": 4,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": false
+        },
+        "tooltip": {
+          "mode": "multi",
+          "sort": "desc"
+        }
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "expr": "sum by(instance) (nextcloud_free_space_bytes{instance=\"$instance\"})",
+          "interval": "",
+          "intervalFactor": 1,
+          "legendFormat": "",
+          "metric": "",
+          "range": true,
+          "refId": "A",
+          "step": 900
+        }
+      ],
+      "title": "Disk Space Left",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            }
+          },
+          "mappings": []
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 4,
+        "x": 12,
+        "y": 25
+      },
+      "id": 13,
+      "options": {
+        "legend": {
+          "displayMode": "table",
+          "placement": "right",
+          "showLegend": true,
+          "values": [
+            "percent"
+          ]
+        },
+        "pieType": "pie",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "desc"
+        }
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "exemplar": false,
+          "expr": "sum by(version) (nextcloud_system_info)",
+          "instant": true,
+          "legendFormat": "__auto",
+          "range": false,
+          "refId": "A"
+        }
+      ],
+      "title": "Nextcloud Versions (all instances)",
+      "type": "piechart"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            }
+          },
+          "mappings": []
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 4,
+        "x": 16,
+        "y": 25
+      },
+      "id": 17,
+      "options": {
+        "legend": {
+          "displayMode": "table",
+          "placement": "right",
+          "showLegend": true,
+          "values": [
+            "percent"
+          ]
+        },
+        "pieType": "pie",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "desc"
+        }
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "exemplar": false,
+          "expr": "sum by(version) (nextcloud_exporter_info)",
+          "instant": true,
+          "legendFormat": "__auto",
+          "range": false,
+          "refId": "A"
+        }
+      ],
+      "title": "Exporter Versions (all instances)",
+      "type": "piechart"
+    },
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 32
+      },
+      "id": 16,
+      "panels": [],
+      "title": "Environment Information",
+      "type": "row"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            }
+          },
+          "mappings": []
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 4,
+        "x": 0,
+        "y": 33
+      },
+      "id": 14,
+      "options": {
+        "legend": {
+          "displayMode": "table",
+          "placement": "right",
+          "showLegend": true,
+          "values": [
+            "percent"
+          ]
+        },
+        "pieType": "pie",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "desc"
+        }
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "exemplar": false,
+          "expr": "sum by(version) (nextcloud_php_info)",
+          "instant": true,
+          "legendFormat": "__auto",
+          "range": false,
+          "refId": "A"
+        }
+      ],
+      "title": "PHP Versions (all instances)",
+      "type": "piechart"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            }
+          },
+          "mappings": []
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 7,
+        "w": 4,
+        "x": 4,
+        "y": 33
+      },
+      "id": 15,
+      "options": {
+        "legend": {
+          "displayMode": "table",
+          "placement": "right",
+          "showLegend": true,
+          "values": [
+            "percent"
+          ]
+        },
+        "pieType": "pie",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "desc"
+        }
+      },
+      "pluginVersion": "11.3.5",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "editorMode": "code",
+          "exemplar": false,
+          "expr": "sum by(type, version) (nextcloud_database_info)",
+          "instant": true,
+          "legendFormat": "{{type}} {{version}}",
+          "range": false,
+          "refId": "A"
+        }
+      ],
+      "title": "Databases (all instances)",
+      "type": "piechart"
+    }
+  ],
+  "preload": false,
+  "refresh": "5m",
+  "schemaVersion": 40,
+  "tags": [
+    "prometheus",
+    "nextcloud"
+  ],
+  "templating": {
+    "list": [
+      {
+        "current": {
+          "selected": false,
+          "tags": [],
+          "text": "default",
+          "value": "default"
+        },
+        "hide": 0,
+        "includeAll": false,
+        "label": "datasource",
+        "multi": false,
+        "name": "DS_PROMETHEUS",
+        "options": [],
+        "query": "prometheus",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "type": "datasource"
+      },
+      {
+        "current": {},
+        "datasource": {
+          "type": "prometheus",
+          "uid": "${DS_PROMETHEUS}"
+        },
+        "definition": "",
+        "includeAll": false,
+        "label": "Instance",
+        "name": "instance",
+        "options": [],
+        "query": "label_values(nextcloud_up, instance)",
+        "refresh": 2,
+        "regex": "",
+        "type": "query"
+      }
+    ]
+  },
+  "time": {
+    "from": "now-30d",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "1h",
+      "2h",
+      "1d"
+    ]
+  },
+  "timezone": "browser",
+  "title": "Nextcloud",
+  "uid": "cdae9143-9a17-4d37-87da-d34fb9cfd92f",
+  "version": 2,
+  "weekStart": ""
+}
diff --git a/modules/grafana/grafana-dashboards/nginx.json b/modules/grafana/grafana-dashboards/nginx.json
new file mode 100644
index 00000000..4adfb200
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/nginx.json
@@ -0,0 +1,567 @@
+{
+  "__inputs": [
+    {
+      "description": "",
+      "label": "Prometheus",
+      "name": "DS_PROMETHEUS",
+      "pluginId": "prometheus",
+      "pluginName": "Prometheus",
+      "type": "datasource"
+    }
+  ],
+  "__requires": [
+    {
+      "id": "grafana",
+      "name": "Grafana",
+      "type": "grafana",
+      "version": "5.0.0"
+    },
+    {
+      "id": "graph",
+      "name": "Graph",
+      "type": "panel",
+      "version": ""
+    },
+    {
+      "id": "prometheus",
+      "name": "Prometheus",
+      "type": "datasource",
+      "version": "1.0.0"
+    },
+    {
+      "id": "singlestat",
+      "name": "Singlestat",
+      "type": "panel",
+      "version": ""
+    }
+  ],
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "type": "dashboard"
+      }
+    ]
+  },
+  "description": "Official dashboard for NGINX Prometheus exporter",
+  "editable": true,
+  "gnetId": null,
+  "graphTooltip": 0,
+  "id": null,
+  "iteration": 1562682051068,
+  "links": [],
+  "panels": [
+    {
+      "collapsed": false,
+      "datasource": "${DS_PROMETHEUS}",
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 4,
+      "panels": [],
+      "title": "Status",
+      "type": "row"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": true,
+      "colorPostfix": false,
+      "colorPrefix": false,
+      "colorValue": false,
+      "colors": [
+        "#E02F44",
+        "#FF9830",
+        "#299c46"
+      ],
+      "datasource": "${DS_PROMETHEUS}",
+      "decimals": null,
+      "description": "",
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 12,
+        "x": 0,
+        "y": 1
+      },
+      "id": 8,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "options": {},
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "repeat": "instance",
+      "repeatDirection": "h",
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "expr": "nginx_up{instance=~\"$instance\"}",
+          "format": "time_series",
+          "instant": false,
+          "intervalFactor": 1,
+          "refId": "A"
+        }
+      ],
+      "thresholds": "1,1",
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "NGINX Status for $instance",
+      "type": "singlestat",
+      "valueFontSize": "100%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "Down",
+          "value": "0"
+        },
+        {
+          "op": "=",
+          "text": "Up",
+          "value": "1"
+        }
+      ],
+      "valueName": "current"
+    },
+    {
+      "collapsed": false,
+      "datasource": "${DS_PROMETHEUS}",
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 4
+      },
+      "id": 6,
+      "panels": [],
+      "title": "Metrics",
+      "type": "row"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_PROMETHEUS}",
+      "decimals": null,
+      "description": "",
+      "fill": 1,
+      "gridPos": {
+        "h": 10,
+        "w": 12,
+        "x": 0,
+        "y": 5
+      },
+      "id": 10,
+      "legend": {
+        "alignAsTable": false,
+        "avg": false,
+        "current": false,
+        "hideEmpty": false,
+        "max": false,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {},
+      "percentage": false,
+      "pointradius": 2,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "irate(nginx_connections_accepted{instance=~\"$instance\"}[5m])",
+          "format": "time_series",
+          "instant": false,
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}} accepted",
+          "refId": "A"
+        },
+        {
+          "expr": "irate(nginx_connections_handled{instance=~\"$instance\"}[5m])",
+          "format": "time_series",
+          "instant": false,
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}} handled",
+          "refId": "B"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Processed connections",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "decimals": 1,
+          "format": "short",
+          "label": "Connections (rate)",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": "",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_PROMETHEUS}",
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 10,
+        "w": 12,
+        "x": 12,
+        "y": 5
+      },
+      "id": 12,
+      "legend": {
+        "alignAsTable": false,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {},
+      "percentage": false,
+      "pointradius": 2,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "nginx_connections_active{instance=~\"$instance\"}",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}} active",
+          "refId": "A"
+        },
+        {
+          "expr": "nginx_connections_reading{instance=~\"$instance\"}",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}} reading",
+          "refId": "B"
+        },
+        {
+          "expr": "nginx_connections_waiting{instance=~\"$instance\"}",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}} waiting",
+          "refId": "C"
+        },
+        {
+          "expr": "nginx_connections_writing{instance=~\"$instance\"}",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}} writing",
+          "refId": "D"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Active Connections",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "decimals": 0,
+          "format": "short",
+          "label": "Connections",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_PROMETHEUS}",
+      "fill": 1,
+      "gridPos": {
+        "h": 8,
+        "w": 24,
+        "x": 0,
+        "y": 15
+      },
+      "id": 15,
+      "legend": {
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null",
+      "options": {},
+      "percentage": false,
+      "pointradius": 2,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "irate(nginx_http_requests_total{instance=~\"$instance\"}[5m])",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}} total requests",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Total requests",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    }
+  ],
+  "refresh": "5s",
+  "schemaVersion": 18,
+  "style": "dark",
+  "tags": [
+    "nginx",
+    "prometheus",
+    "nginx prometheus exporter"
+  ],
+  "templating": {
+    "list": [
+      {
+        "current": {
+          "selected": false,
+          "tags": [],
+          "text": "default",
+          "value": "default"
+        },
+        "hide": 0,
+        "includeAll": false,
+        "label": "datasource",
+        "multi": false,
+        "name": "DS_PROMETHEUS",
+        "options": [],
+        "query": "prometheus",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "type": "datasource"
+      },
+      {
+        "allValue": null,
+        "current": {},
+        "datasource": "${DS_PROMETHEUS}",
+        "definition": "label_values(nginx_up, instance)",
+        "hide": 0,
+        "includeAll": true,
+        "label": "",
+        "multi": true,
+        "name": "instance",
+        "options": [],
+        "query": "label_values(nginx_up, instance)",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 0,
+        "tagValuesQuery": "",
+        "tags": [],
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      }
+    ]
+  },
+  "time": {
+    "from": "now-15m",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ]
+  },
+  "timezone": "",
+  "title": "NGINX",
+  "uid": "MsjffzSZz",
+  "version": 1
+}
diff --git a/hosts/flora-6/apps/grafana-dashboards/node-exporter-full_rev33.json b/modules/grafana/grafana-dashboards/node-exporter-full_rev33.json
similarity index 97%
rename from hosts/flora-6/apps/grafana-dashboards/node-exporter-full_rev33.json
rename to modules/grafana/grafana-dashboards/node-exporter-full_rev33.json
index c28ea749..a2b7995b 100644
--- a/hosts/flora-6/apps/grafana-dashboards/node-exporter-full_rev33.json
+++ b/modules/grafana/grafana-dashboards/node-exporter-full_rev33.json
@@ -1,47 +1,4 @@
 {
-  "__inputs": [
-    {
-      "name": "DS_PROMETHEUS",
-      "label": "Prometheus",
-      "description": "",
-      "type": "datasource",
-      "pluginId": "prometheus",
-      "pluginName": "Prometheus"
-    }
-  ],
-  "__elements": {},
-  "__requires": [
-    {
-      "type": "panel",
-      "id": "gauge",
-      "name": "Gauge",
-      "version": ""
-    },
-    {
-      "type": "grafana",
-      "id": "grafana",
-      "name": "Grafana",
-      "version": "9.4.3"
-    },
-    {
-      "type": "datasource",
-      "id": "prometheus",
-      "name": "Prometheus",
-      "version": "1.0.0"
-    },
-    {
-      "type": "panel",
-      "id": "stat",
-      "name": "Stat",
-      "version": ""
-    },
-    {
-      "type": "panel",
-      "id": "timeseries",
-      "name": "Time series",
-      "version": ""
-    }
-  ],
   "annotations": {
     "list": [
       {
@@ -69,7 +26,6 @@
   "fiscalYearStartMonth": 0,
   "gnetId": 1860,
   "graphTooltip": 1,
-  "id": null,
   "links": [
     {
       "icon": "external link",
@@ -171,18 +127,19 @@
       "id": 20,
       "links": [],
       "options": {
+        "minVizHeight": 75,
+        "minVizWidth": 75,
         "orientation": "horizontal",
         "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
+          "calcs": ["lastNotNull"],
           "fields": "",
           "values": false
         },
         "showThresholdLabels": false,
-        "showThresholdMarkers": true
+        "showThresholdMarkers": true,
+        "sizing": "auto"
       },
-      "pluginVersion": "9.4.3",
+      "pluginVersion": "10.2.7",
       "targets": [
         {
           "datasource": {
@@ -259,18 +216,19 @@
       "id": 155,
       "links": [],
       "options": {
+        "minVizHeight": 75,
+        "minVizWidth": 75,
         "orientation": "horizontal",
         "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
+          "calcs": ["lastNotNull"],
           "fields": "",
           "values": false
         },
         "showThresholdLabels": false,
-        "showThresholdMarkers": true
+        "showThresholdMarkers": true,
+        "sizing": "auto"
       },
-      "pluginVersion": "9.4.3",
+      "pluginVersion": "10.2.7",
       "targets": [
         {
           "datasource": {
@@ -347,18 +305,19 @@
       "id": 19,
       "links": [],
       "options": {
+        "minVizHeight": 75,
+        "minVizWidth": 75,
         "orientation": "horizontal",
         "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
+          "calcs": ["lastNotNull"],
           "fields": "",
           "values": false
         },
         "showThresholdLabels": false,
-        "showThresholdMarkers": true
+        "showThresholdMarkers": true,
+        "sizing": "auto"
       },
-      "pluginVersion": "9.4.3",
+      "pluginVersion": "10.2.7",
       "targets": [
         {
           "datasource": {
@@ -425,18 +384,19 @@
       "id": 16,
       "links": [],
       "options": {
+        "minVizHeight": 75,
+        "minVizWidth": 75,
         "orientation": "horizontal",
         "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
+          "calcs": ["lastNotNull"],
           "fields": "",
           "values": false
         },
         "showThresholdLabels": false,
-        "showThresholdMarkers": true
+        "showThresholdMarkers": true,
+        "sizing": "auto"
       },
-      "pluginVersion": "9.4.3",
+      "pluginVersion": "10.2.7",
       "targets": [
         {
           "datasource": {
@@ -529,18 +489,19 @@
       "id": 21,
       "links": [],
       "options": {
+        "minVizHeight": 75,
+        "minVizWidth": 75,
         "orientation": "horizontal",
         "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
+          "calcs": ["lastNotNull"],
           "fields": "",
           "values": false
         },
         "showThresholdLabels": false,
-        "showThresholdMarkers": true
+        "showThresholdMarkers": true,
+        "sizing": "auto"
       },
-      "pluginVersion": "9.4.3",
+      "pluginVersion": "10.2.7",
       "targets": [
         {
           "datasource": {
@@ -615,18 +576,19 @@
       "id": 154,
       "links": [],
       "options": {
+        "minVizHeight": 75,
+        "minVizWidth": 75,
         "orientation": "horizontal",
         "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
+          "calcs": ["lastNotNull"],
           "fields": "",
           "values": false
         },
         "showThresholdLabels": false,
-        "showThresholdMarkers": true
+        "showThresholdMarkers": true,
+        "sizing": "auto"
       },
-      "pluginVersion": "9.4.3",
+      "pluginVersion": "10.2.7",
       "targets": [
         {
           "datasource": {
@@ -701,15 +663,14 @@
         "justifyMode": "auto",
         "orientation": "horizontal",
         "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
+          "calcs": ["lastNotNull"],
           "fields": "",
           "values": false
         },
-        "textMode": "auto"
+        "textMode": "auto",
+        "wideLayout": true
       },
-      "pluginVersion": "9.4.3",
+      "pluginVersion": "10.2.7",
       "targets": [
         {
           "datasource": {
@@ -782,15 +743,14 @@
         "justifyMode": "auto",
         "orientation": "horizontal",
         "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
+          "calcs": ["lastNotNull"],
           "fields": "",
           "values": false
         },
-        "textMode": "auto"
+        "textMode": "auto",
+        "wideLayout": true
       },
-      "pluginVersion": "9.4.3",
+      "pluginVersion": "10.2.7",
       "targets": [
         {
           "datasource": {
@@ -869,15 +829,14 @@
         "justifyMode": "auto",
         "orientation": "horizontal",
         "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
+          "calcs": ["lastNotNull"],
           "fields": "",
           "values": false
         },
-        "textMode": "auto"
+        "textMode": "auto",
+        "wideLayout": true
       },
-      "pluginVersion": "9.4.3",
+      "pluginVersion": "10.2.7",
       "targets": [
         {
           "datasource": {
@@ -954,15 +913,14 @@
         "justifyMode": "auto",
         "orientation": "horizontal",
         "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
+          "calcs": ["lastNotNull"],
           "fields": "",
           "values": false
         },
-        "textMode": "auto"
+        "textMode": "auto",
+        "wideLayout": true
       },
-      "pluginVersion": "9.4.3",
+      "pluginVersion": "10.2.7",
       "targets": [
         {
           "datasource": {
@@ -1037,15 +995,14 @@
         "justifyMode": "auto",
         "orientation": "horizontal",
         "reduceOptions": {
-          "calcs": [
-            "lastNotNull"
-          ],
+          "calcs": ["lastNotNull"],
           "fields": "",
           "values": false
         },
-        "textMode": "auto"
+        "textMode": "auto",
+        "wideLayout": true
       },
-      "pluginVersion": "9.4.3",
+      "pluginVersion": "10.2.7",
       "targets": [
         {
           "datasource": {
@@ -1103,6 +1060,7 @@
             "mode": "palette-classic"
           },
           "custom": {
+            "axisBorderShow": false,
             "axisCenteredZero": false,
             "axisColorMode": "text",
             "axisLabel": "",
@@ -1116,6 +1074,7 @@
               "tooltip": false,
               "viz": false
             },
+            "insertNulls": false,
             "lineInterpolation": "smooth",
             "lineWidth": 1,
             "pointSize": 5,
@@ -1383,6 +1342,7 @@
             "mode": "palette-classic"
           },
           "custom": {
+            "axisBorderShow": false,
             "axisCenteredZero": false,
             "axisColorMode": "text",
             "axisLabel": "",
@@ -1396,6 +1356,7 @@
               "tooltip": false,
               "viz": false
             },
+            "insertNulls": false,
             "lineInterpolation": "linear",
             "lineWidth": 1,
             "pointSize": 5,
@@ -1901,6 +1862,7 @@
             "mode": "palette-classic"
           },
           "custom": {
+            "axisBorderShow": false,
             "axisCenteredZero": false,
             "axisColorMode": "text",
             "axisLabel": "",
@@ -1914,6 +1876,7 @@
               "tooltip": false,
               "viz": false
             },
+            "insertNulls": false,
             "lineInterpolation": "linear",
             "lineWidth": 1,
             "pointSize": 5,
@@ -2369,6 +2332,7 @@
             "mode": "palette-classic"
           },
           "custom": {
+            "axisBorderShow": false,
             "axisCenteredZero": false,
             "axisColorMode": "text",
             "axisLabel": "",
@@ -2382,6 +2346,7 @@
               "tooltip": false,
               "viz": false
             },
+            "insertNulls": false,
             "lineInterpolation": "linear",
             "lineWidth": 1,
             "pointSize": 5,
@@ -2662,12 +2627,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -3169,12 +3129,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -3448,12 +3403,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -3563,12 +3513,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -3993,12 +3938,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -4220,12 +4160,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -4365,12 +4300,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -4498,12 +4428,7 @@
           "id": 319,
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -4894,12 +4819,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -5284,12 +5204,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -5655,12 +5570,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -6084,12 +5994,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -6490,12 +6395,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -6917,12 +6817,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -7302,12 +7197,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -7687,12 +7577,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -8073,12 +7958,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -8443,12 +8323,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -8830,11 +8705,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -9226,11 +9097,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -9610,11 +9477,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -9993,12 +9856,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -10394,12 +10252,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -10535,12 +10388,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -10661,12 +10509,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -11050,12 +10893,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -11463,12 +11301,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -11609,12 +11442,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -11741,12 +11569,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -11860,12 +11683,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -11976,12 +11794,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -12119,12 +11932,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -12233,12 +12041,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -12336,12 +12139,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -12452,12 +12250,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -12614,12 +12407,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -12742,12 +12530,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -12878,12 +12661,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -13021,12 +12799,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -13136,12 +12909,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -13240,8 +13008,7 @@
                 "mode": "absolute",
                 "steps": [
                   {
-                    "color": "green",
-                    "value": null
+                    "color": "green"
                   },
                   {
                     "color": "red",
@@ -13261,10 +13028,7 @@
                   {
                     "id": "custom.lineStyle",
                     "value": {
-                      "dash": [
-                        10,
-                        10
-                      ],
+                      "dash": [10, 10],
                       "fill": "dash"
                     }
                   },
@@ -13302,10 +13066,7 @@
                   {
                     "id": "custom.lineStyle",
                     "value": {
-                      "dash": [
-                        10,
-                        10
-                      ],
+                      "dash": [10, 10],
                       "fill": "dash"
                     }
                   },
@@ -13338,12 +13099,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -13456,8 +13212,7 @@
                 "mode": "absolute",
                 "steps": [
                   {
-                    "color": "green",
-                    "value": null
+                    "color": "green"
                   },
                   {
                     "color": "red",
@@ -13540,12 +13295,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -13743,12 +13493,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -13845,12 +13590,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -13948,12 +13688,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -14049,12 +13784,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -14172,12 +13902,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -14352,12 +14077,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -14529,12 +14249,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -14645,12 +14360,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -14776,12 +14486,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -14954,12 +14659,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -15449,12 +15149,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -15874,12 +15569,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -16301,12 +15991,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -16719,12 +16404,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -17134,12 +16814,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -17548,12 +17223,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -17964,12 +17634,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -18367,12 +18032,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -18509,12 +18169,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -18640,12 +18295,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -18744,12 +18394,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -18859,12 +18504,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -18980,12 +18620,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -19194,12 +18829,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -19323,12 +18953,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -19450,12 +19075,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -19577,12 +19197,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -19704,12 +19319,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -19819,12 +19429,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -19946,12 +19551,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -20049,12 +19649,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -20164,12 +19759,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -20287,12 +19877,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -20401,12 +19986,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -20504,12 +20084,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -20607,12 +20182,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -20710,12 +20280,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -20824,12 +20389,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -20940,12 +20500,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -21043,12 +20598,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -21184,12 +20734,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -21341,12 +20886,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -21471,12 +21011,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -21588,12 +21123,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -21716,12 +21246,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -21859,12 +21384,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -21975,12 +21495,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true,
@@ -22091,12 +21606,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -22219,12 +21729,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -22346,12 +21851,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -22461,12 +21961,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -22637,12 +22132,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -22755,12 +22245,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -22936,12 +22421,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -23067,12 +22547,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -23199,12 +22674,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -23312,12 +22782,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -23492,12 +22957,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -23619,12 +23079,7 @@
           "links": [],
           "options": {
             "legend": {
-              "calcs": [
-                "mean",
-                "lastNotNull",
-                "max",
-                "min"
-              ],
+              "calcs": ["mean", "lastNotNull", "max", "min"],
               "displayMode": "table",
               "placement": "bottom",
               "showLegend": true
@@ -23684,11 +23139,8 @@
   ],
   "refresh": "",
   "revision": 1,
-  "schemaVersion": 38,
-  "style": "dark",
-  "tags": [
-    "linux"
-  ],
+  "schemaVersion": 39,
+  "tags": ["linux"],
   "templating": {
     "list": [
       {
@@ -23710,7 +23162,11 @@
         "type": "datasource"
       },
       {
-        "current": {},
+        "current": {
+          "selected": false,
+          "text": "node-exporter",
+          "value": "node-exporter"
+        },
         "datasource": {
           "type": "prometheus",
           "uid": "${DS_PROMETHEUS}"
@@ -23736,7 +23192,11 @@
         "useTags": false
       },
       {
-        "current": {},
+        "current": {
+          "selected": true,
+          "text": "nachtigall",
+          "value": "nachtigall"
+        },
         "datasource": {
           "type": "prometheus",
           "uid": "${DS_PROMETHEUS}"
@@ -23801,21 +23261,11 @@
       "2h",
       "1d"
     ],
-    "time_options": [
-      "5m",
-      "15m",
-      "1h",
-      "6h",
-      "12h",
-      "24h",
-      "2d",
-      "7d",
-      "30d"
-    ]
+    "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
   },
   "timezone": "browser",
   "title": "Node Exporter Full",
   "uid": "rYdddlPWk",
-  "version": 87,
+  "version": 2,
   "weekStart": ""
-}
\ No newline at end of file
+}
diff --git a/modules/grafana/grafana-dashboards/postgres-overview.json b/modules/grafana/grafana-dashboards/postgres-overview.json
new file mode 100644
index 00000000..298e164c
--- /dev/null
+++ b/modules/grafana/grafana-dashboards/postgres-overview.json
@@ -0,0 +1,1412 @@
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "type": "dashboard"
+      }
+    ]
+  },
+  "description": "Performance metrics for Postgres",
+  "editable": true,
+  "gnetId": 455,
+  "graphTooltip": 0,
+  "id": 1,
+  "iteration": 1603191461722,
+  "links": [],
+  "panels": [
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "$datasource",
+      "editable": true,
+      "error": false,
+      "fieldConfig": {
+        "defaults": {
+          "custom": {}
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "grid": {},
+      "gridPos": {
+        "h": 7,
+        "w": 20,
+        "x": 0,
+        "y": 0
+      },
+      "hiddenSeries": false,
+      "id": 1,
+      "isNew": true,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "connected",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "7.2.1",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "fetched",
+          "dsType": "prometheus",
+          "expr": "sum(irate(pg_stat_database_tup_fetched{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "fetched",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tup_fetched"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [
+                  "10s"
+                ],
+                "type": "non_negative_derivative"
+              }
+            ]
+          ],
+          "step": 120,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        },
+        {
+          "alias": "fetched",
+          "dsType": "prometheus",
+          "expr": "sum(irate(pg_stat_database_tup_returned{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "returned",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tup_fetched"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [
+                  "10s"
+                ],
+                "type": "non_negative_derivative"
+              }
+            ]
+          ],
+          "step": 120,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        },
+        {
+          "alias": "fetched",
+          "dsType": "prometheus",
+          "expr": "sum(irate(pg_stat_database_tup_inserted{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "inserted",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "C",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tup_fetched"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [
+                  "10s"
+                ],
+                "type": "non_negative_derivative"
+              }
+            ]
+          ],
+          "step": 120,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        },
+        {
+          "alias": "fetched",
+          "dsType": "prometheus",
+          "expr": "sum(irate(pg_stat_database_tup_updated{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "updated",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "D",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tup_fetched"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [
+                  "10s"
+                ],
+                "type": "non_negative_derivative"
+              }
+            ]
+          ],
+          "step": 120,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        },
+        {
+          "alias": "fetched",
+          "dsType": "prometheus",
+          "expr": "sum(irate(pg_stat_database_tup_deleted{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "deleted",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "E",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tup_fetched"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [
+                  "10s"
+                ],
+                "type": "non_negative_derivative"
+              }
+            ]
+          ],
+          "step": 120,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Rows",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "$datasource",
+      "decimals": 0,
+      "editable": true,
+      "error": false,
+      "fieldConfig": {
+        "defaults": {
+          "custom": {}
+        },
+        "overrides": []
+      },
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 4,
+        "x": 20,
+        "y": 0
+      },
+      "height": "55px",
+      "id": 11,
+      "interval": null,
+      "isNew": true,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": true,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": true
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "prometheus",
+          "expr": "sum(irate(pg_stat_database_xact_commit{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])) + sum(irate(pg_stat_database_xact_rollback{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "xact_commit"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [
+                  "10s"
+                ],
+                "type": "non_negative_derivative"
+              }
+            ]
+          ],
+          "step": 1800,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "QPS",
+      "transparent": true,
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "$datasource",
+      "decimals": 1,
+      "editable": true,
+      "error": false,
+      "fieldConfig": {
+        "defaults": {
+          "custom": {}
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "grid": {},
+      "gridPos": {
+        "h": 7,
+        "w": 12,
+        "x": 0,
+        "y": 7
+      },
+      "hiddenSeries": false,
+      "id": 2,
+      "isNew": true,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "hideZero": true,
+        "max": true,
+        "min": true,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "connected",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "7.2.1",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "Buffers Allocated",
+          "dsType": "prometheus",
+          "expr": "irate(pg_stat_bgwriter_buffers_alloc{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "buffers_alloc",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "buffers_alloc"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [],
+                "type": "difference"
+              }
+            ]
+          ],
+          "step": 240,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        },
+        {
+          "alias": "Buffers Allocated",
+          "dsType": "prometheus",
+          "expr": "irate(pg_stat_bgwriter_buffers_backend_fsync{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "buffers_backend_fsync",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "buffers_alloc"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [],
+                "type": "difference"
+              }
+            ]
+          ],
+          "step": 240,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        },
+        {
+          "alias": "Buffers Allocated",
+          "dsType": "prometheus",
+          "expr": "irate(pg_stat_bgwriter_buffers_backend{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "buffers_backend",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "C",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "buffers_alloc"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [],
+                "type": "difference"
+              }
+            ]
+          ],
+          "step": 240,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        },
+        {
+          "alias": "Buffers Allocated",
+          "dsType": "prometheus",
+          "expr": "irate(pg_stat_bgwriter_buffers_clean{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "buffers_clean",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "D",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "buffers_alloc"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [],
+                "type": "difference"
+              }
+            ]
+          ],
+          "step": 240,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        },
+        {
+          "alias": "Buffers Allocated",
+          "dsType": "prometheus",
+          "expr": "irate(pg_stat_bgwriter_buffers_checkpoint{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "buffers_checkpoint",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "E",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "buffers_alloc"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [],
+                "type": "difference"
+              }
+            ]
+          ],
+          "step": 240,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Buffers",
+      "tooltip": {
+        "msResolution": false,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "$datasource",
+      "editable": true,
+      "error": false,
+      "fieldConfig": {
+        "defaults": {
+          "custom": {}
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "grid": {},
+      "gridPos": {
+        "h": 7,
+        "w": 12,
+        "x": 12,
+        "y": 7
+      },
+      "hiddenSeries": false,
+      "id": 3,
+      "isNew": true,
+      "legend": {
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "7.2.1",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "conflicts",
+          "dsType": "prometheus",
+          "expr": "sum(rate(pg_stat_database_deadlocks{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "deadlocks",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "conflicts"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [],
+                "type": "difference"
+              }
+            ]
+          ],
+          "step": 240,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        },
+        {
+          "alias": "deadlocks",
+          "dsType": "prometheus",
+          "expr": "sum(rate(pg_stat_database_conflicts{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval]))",
+          "format": "time_series",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "intervalFactor": 2,
+          "legendFormat": "conflicts",
+          "measurement": "postgresql",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "deadlocks"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [],
+                "type": "difference"
+              }
+            ]
+          ],
+          "step": 240,
+          "tags": [
+            {
+              "key": "instance",
+              "operator": "=~",
+              "value": "/^$instance$/"
+            }
+          ]
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Conflicts/Deadlocks",
+      "tooltip": {
+        "msResolution": false,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": 0,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "$datasource",
+      "editable": true,
+      "error": false,
+      "fieldConfig": {
+        "defaults": {
+          "custom": {}
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "grid": {},
+      "gridPos": {
+        "h": 7,
+        "w": 12,
+        "x": 0,
+        "y": 14
+      },
+      "hiddenSeries": false,
+      "id": 12,
+      "isNew": true,
+      "legend": {
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": true,
+      "pluginVersion": "7.2.1",
+      "pointradius": 1,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "sum by (datname) (rate(pg_stat_database_blks_hit{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])) / (sum by (datname)(rate(pg_stat_database_blks_hit{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])) + sum by (datname)(rate(pg_stat_database_blks_read{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])))",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{datname}} - cache hit rate",
+          "refId": "A",
+          "step": 240
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Cache hit ratio",
+      "tooltip": {
+        "msResolution": false,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "percentunit",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "$datasource",
+      "editable": true,
+      "error": false,
+      "fieldConfig": {
+        "defaults": {
+          "custom": {}
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "grid": {},
+      "gridPos": {
+        "h": 7,
+        "w": 12,
+        "x": 12,
+        "y": 14
+      },
+      "hiddenSeries": false,
+      "id": 13,
+      "isNew": true,
+      "legend": {
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "7.2.1",
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "pg_stat_database_numbackends{datname=~\"$db\",job=~\"$job\",instance=~\"$instance\"}",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{datname}} - {{__name__}}",
+          "refId": "A",
+          "step": 240
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Number of active connections",
+      "tooltip": {
+        "msResolution": false,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    }
+  ],
+  "refresh": false,
+  "schemaVersion": 26,
+  "style": "dark",
+  "tags": [
+    "postgres"
+  ],
+  "templating": {
+    "list": [
+      {
+        "hide": 0,
+        "includeAll": false,
+        "label": "Data Source",
+        "multi": false,
+        "name": "datasource",
+        "options": [],
+        "query": "prometheus",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "type": "datasource"
+      },
+      {
+        "allValue": ".+",
+        "datasource": "$datasource",
+        "definition": "label_values(pg_up, job)",
+        "hide": 0,
+        "includeAll": true,
+        "label": "job",
+        "multi": true,
+        "name": "job",
+        "options": [],
+        "query": "label_values(pg_up, job)",
+        "refresh": 0,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 0,
+        "tagValuesQuery": "",
+        "tags": [],
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      },
+      {
+        "allValue": ".+",
+        "datasource": "$datasource",
+        "definition": "",
+        "hide": 0,
+        "includeAll": true,
+        "label": "instance",
+        "multi": true,
+        "name": "instance",
+        "options": [],
+        "query": "label_values(up{job=~\"$job\"},instance)",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 0,
+        "tagValuesQuery": "",
+        "tags": [],
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      },
+      {
+        "allValue": ".+",
+        "datasource": "$datasource",
+        "definition": "label_values(pg_stat_database_tup_fetched{instance=~\"$instance\",datname!~\"template.*|postgres\"},datname)",
+        "hide": 0,
+        "includeAll": true,
+        "label": "db",
+        "multi": false,
+        "name": "db",
+        "options": [],
+        "query": "label_values(pg_stat_database_tup_fetched{instance=~\"$instance\",datname!~\"template.*|postgres\"},datname)",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 0,
+        "tagValuesQuery": "",
+        "tags": [],
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      }
+    ]
+  },
+  "time": {
+    "from": "now-1h",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ]
+  },
+  "timezone": "browser",
+  "title": "Postgres Overview",
+  "uid": "wGgaPlciz",
+  "version": 5
+}
diff --git a/hosts/flora-6/apps/grafana-dashboards/synapse.json b/modules/grafana/grafana-dashboards/synapse.json
similarity index 99%
rename from hosts/flora-6/apps/grafana-dashboards/synapse.json
rename to modules/grafana/grafana-dashboards/synapse.json
index 30d6d875..db3c9dc4 100644
--- a/hosts/flora-6/apps/grafana-dashboards/synapse.json
+++ b/modules/grafana/grafana-dashboards/synapse.json
@@ -70,9 +70,7 @@
       "icon": "external link",
       "includeVars": true,
       "keepTime": true,
-      "tags": [
-        "matrix"
-      ],
+      "tags": ["matrix"],
       "title": "Dashboards",
       "type": "dashboards"
     }
@@ -4313,9 +4311,7 @@
                   "id": "byNames",
                   "options": {
                     "mode": "exclude",
-                    "names": [
-                      "libera.chat "
-                    ],
+                    "names": ["libera.chat "],
                     "prefix": "All except:",
                     "readOnly": true
                   }
@@ -4435,9 +4431,7 @@
                   "id": "byNames",
                   "options": {
                     "mode": "exclude",
-                    "names": [
-                      "libera.chat"
-                    ],
+                    "names": ["libera.chat"],
                     "prefix": "All except:",
                     "readOnly": true
                   }
@@ -13266,9 +13260,7 @@
   "refresh": false,
   "schemaVersion": 37,
   "style": "dark",
-  "tags": [
-    "matrix"
-  ],
+  "tags": ["matrix"],
   "templating": {
     "list": [
       {
@@ -13453,17 +13445,7 @@
       "2h",
       "1d"
     ],
-    "time_options": [
-      "5m",
-      "15m",
-      "1h",
-      "6h",
-      "12h",
-      "24h",
-      "2d",
-      "7d",
-      "30d"
-    ]
+    "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
   },
   "timezone": "",
   "title": "Synapse",
diff --git a/modules/keycloak/default.nix b/modules/keycloak/default.nix
new file mode 100644
index 00000000..88458fc4
--- /dev/null
+++ b/modules/keycloak/default.nix
@@ -0,0 +1,76 @@
+{
+  flake,
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+{
+  options.pub-solar-os.auth = with lib; {
+    enable = mkEnableOption "Enable keycloak to run on the node";
+
+    realm = mkOption {
+      description = "Name of the realm";
+      type = types.str;
+      default = config.pub-solar-os.networking.domain;
+    };
+
+    database-password-file = mkOption {
+      description = "Database password file path";
+      type = types.str;
+    };
+  };
+
+  config = lib.mkIf config.pub-solar-os.auth.enable {
+    services.nginx.virtualHosts."auth.${config.pub-solar-os.networking.domain}" = {
+      enableACME = true;
+      forceSSL = true;
+
+      locations = {
+        "= /" = {
+          extraConfig = ''
+            return 302 /realms/${config.pub-solar-os.auth.realm}/account;
+          '';
+        };
+
+        "/" = {
+          extraConfig = ''
+            proxy_pass http://127.0.0.1:8080;
+            proxy_buffer_size 8k;
+          '';
+        };
+      };
+    };
+
+    # keycloak
+    services.keycloak = {
+      enable = true;
+      database.passwordFile = config.pub-solar-os.auth.database-password-file;
+      settings = {
+        hostname = "auth.${config.pub-solar-os.networking.domain}";
+        http-host = "127.0.0.1";
+        http-port = 8080;
+        proxy-headers = "xforwarded";
+        http-enabled = true;
+      };
+      themes = {
+        "pub.solar" =
+          flake.inputs.keycloak-theme-pub-solar.legacyPackages.${pkgs.system}.keycloak-theme-pub-solar;
+      };
+    };
+
+    pub-solar-os.backups = {
+      resources.keycloak-db.resourceCreateCommand = ''
+        ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d keycloak -f /tmp/keycloak-backup.sql
+      '';
+      restic.keycloak = {
+        resources = [ "keycloak-db" ];
+        paths = [ "/tmp/keycloak-backup.sql" ];
+        timerConfig = {
+          OnCalendar = "*-*-* 03:00:00 Etc/UTC";
+        };
+        initialize = true;
+      };
+    };
+  };
+}
diff --git a/modules/loki/default.nix b/modules/loki/default.nix
new file mode 100644
index 00000000..35aa6f3d
--- /dev/null
+++ b/modules/loki/default.nix
@@ -0,0 +1,107 @@
+{
+  config,
+  lib,
+  pkgs,
+  flake,
+  ...
+}:
+{
+  # Only expose loki port via wireguard interface
+  networking.firewall.interfaces.wg-ssh.allowedTCPPorts = [ 3100 ];
+
+  # source: https://gist.github.com/rickhull/895b0cb38fdd537c1078a858cf15d63e
+  # https://grafana.com/docs/loki/latest/configure/examples/#1-local-configuration-exampleyaml
+  services.loki = {
+    enable = true;
+    configuration = {
+      server.http_listen_port = 3100;
+      auth_enabled = false;
+      common = {
+        ring = {
+          instance_interface_names = [ "wg-ssh" ];
+          instance_enable_ipv6 = true;
+          kvstore = {
+            store = "inmemory";
+          };
+        };
+        replication_factor = 1;
+        path_prefix = "/var/lib/loki";
+        storage = {
+          filesystem = {
+            chunks_directory = "chunks/";
+            rules_directory = "rules/";
+          };
+        };
+      };
+      ingester = {
+        chunk_encoding = "snappy";
+        chunk_idle_period = "8h";
+        max_chunk_age = "8h";
+      };
+      pattern_ingester.enabled = true;
+      # 2x CPU cores
+      querier.max_concurrent = 16;
+      query_range = {
+        results_cache = {
+          cache = {
+            embedded_cache = {
+              enabled = true;
+              max_size_mb = 500;
+            };
+          };
+        };
+      };
+      chunk_store_config = {
+        chunk_cache_config = {
+          embedded_cache = {
+            enabled = true;
+            max_size_mb = 500;
+            ttl = "24h";
+          };
+        };
+      };
+      # Keep logs for 1 week
+      # https://grafana.com/docs/loki/latest/operations/storage/retention/
+      limits_config = {
+        allow_structured_metadata = true;
+        ingestion_rate_mb = 8;
+        ingestion_burst_size_mb = 12;
+        retention_period = "1w";
+        split_queries_by_interval = "1h";
+        tsdb_max_query_parallelism = 32;
+        volume_enabled = true;
+      };
+      compactor = {
+        compaction_interval = "10m";
+        delete_request_store = "filesystem";
+        retention_enabled = true;
+        retention_delete_delay = "2h";
+        retention_delete_worker_count = 150;
+      };
+      schema_config = {
+        configs = [
+          {
+            from = "2020-05-15";
+            store = "boltdb-shipper";
+            object_store = "filesystem";
+            schema = "v11";
+            index = {
+              prefix = "index_";
+              period = "24h";
+            };
+          }
+          {
+            from = "2024-05-31";
+            store = "tsdb";
+            object_store = "filesystem";
+            schema = "v13";
+            index = {
+              prefix = "index_";
+              period = "24h";
+            };
+          }
+        ];
+      };
+    };
+  };
+}
diff --git a/modules/mail/default.nix b/modules/mail/default.nix
new file mode 100644
index 00000000..ca261123
--- /dev/null
+++ b/modules/mail/default.nix
@@ -0,0 +1,86 @@
+{ config, flake, ... }:
+
+{
+  age.secrets.mail-hensoko.file = "${flake.self}/secrets/mail/hensoko.age";
+  age.secrets.mail-teutat3s.file = "${flake.self}/secrets/mail/teutat3s.age";
+  age.secrets.mail-admins.file = "${flake.self}/secrets/mail/admins.age";
+  age.secrets.mail-bot.file = "${flake.self}/secrets/mail/bot.age";
+  age.secrets.mail-crew.file = "${flake.self}/secrets/mail/crew.age";
+  age.secrets.mail-erpnext.file = "${flake.self}/secrets/mail/erpnext.age";
+  age.secrets.mail-hakkonaut.file = "${flake.self}/secrets/mail/hakkonaut.age";
+
+  mailserver = {
+    enable = true;
+    fqdn = "mail.pub.solar";
+    domains = [ "pub.solar" ];
+
+    # A list of all login accounts. To create the password hashes, use
+    # nix-shell -p mkpasswd --run 'mkpasswd -R11 -m bcrypt'
+    loginAccounts = {
+      "hensoko@pub.solar" = {
+        hashedPasswordFile = config.age.secrets.mail-hensoko.path;
+        quota = "2G";
+      };
+      "teutat3s@pub.solar" = {
+        hashedPasswordFile = config.age.secrets.mail-teutat3s.path;
+        quota = "2G";
+      };
+      "admins@pub.solar" = {
+        hashedPasswordFile = config.age.secrets.mail-admins.path;
+        quota = "2G";
+        aliases = [
+          "abuse@pub.solar"
+          "alerts@pub.solar"
+          "forgejo@pub.solar"
+          "keycloak@pub.solar"
+          "mastodon-notifications@pub.solar"
+          "matrix@pub.solar"
+          "postmaster@pub.solar"
+          "nextcloud@pub.solar"
+          "no-reply@pub.solar"
+          "security@pub.solar"
+        ];
+      };
+      "bot@pub.solar" = {
+        hashedPasswordFile = config.age.secrets.mail-bot.path;
+        quota = "2G";
+        aliases = [ "hackernews-bot@pub.solar" ];
+      };
+      "crew@pub.solar" = {
+        hashedPasswordFile = config.age.secrets.mail-crew.path;
+        quota = "2G";
+        aliases = [ "moderation@pub.solar" ];
+      };
+      "erpnext@pub.solar" = {
+        hashedPasswordFile = config.age.secrets.mail-erpnext.path;
+        quota = "2G";
+      };
+      "hakkonaut@pub.solar" = {
+        hashedPasswordFile = config.age.secrets.mail-hakkonaut.path;
+        quota = "2G";
+      };
+    };
+
+    # Use Let's Encrypt certificates. Note that this needs to set up a stripped
+    # down nginx and opens port 80.
+    certificateScheme = "acme-nginx";
+  };
+  security.acme.acceptTerms = true;
+  security.acme.defaults.email = "security@pub.solar";
+
+  pub-solar-os.backups.restic.mail = {
+    paths = [
+      "/var/vmail"
+      "/var/dkim"
+    ];
+    timerConfig = {
+      OnCalendar = "*-*-* 02:00:00 Etc/UTC";
+    };
+    initialize = true;
+    pruneOpts = [
+      "--keep-daily 7"
+      "--keep-weekly 4"
+      "--keep-monthly 3"
+    ];
+  };
+}
diff --git a/hosts/nachtigall/apps/mailman.nix b/modules/mailman/default.nix
similarity index 69%
rename from hosts/nachtigall/apps/mailman.nix
rename to modules/mailman/default.nix
index 01ea8cc2..34c685f5 100644
--- a/hosts/nachtigall/apps/mailman.nix
+++ b/modules/mailman/default.nix
@@ -1,15 +1,16 @@
-{ flake
-, config
-, lib
-, pkgs
-, ...
+{
+  flake,
+  config,
+  lib,
+  pkgs,
+  ...
 }:
 {
   networking.firewall.allowedTCPPorts = [ 25 ];
 
   users.users.nginx.extraGroups = [ "mailman" ];
 
-  services.nginx.virtualHosts."list.pub.solar" = {
+  services.nginx.virtualHosts."list.${config.pub-solar-os.networking.domain}" = {
     enableACME = true;
     forceSSL = true;
   };
@@ -24,15 +25,15 @@
     enable = true;
     relayDomains = [ "hash:/var/lib/mailman/data/postfix_domains" ];
     # get TLS certs for list.pub.solar from acme
-    sslCert = "/var/lib/acme/list.pub.solar/fullchain.pem";
-    sslKey = "/var/lib/acme/list.pub.solar/key.pem";
+    sslCert = "/var/lib/acme/list.${config.pub-solar-os.networking.domain}/fullchain.pem";
+    sslKey = "/var/lib/acme/list.${config.pub-solar-os.networking.domain}/key.pem";
     config = {
       transport_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ];
       local_recipient_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ];
     };
     rootAlias = "admins@pub.solar";
     postmasterAlias = "admins@pub.solar";
-    hostname = "list.pub.solar";
+    hostname = "list.${config.pub-solar-os.networking.domain}";
   };
 
   systemd.paths.watcher-acme-ssl-file = {
@@ -40,7 +41,7 @@
     documentation = [ "systemd.path(5)" ];
     partOf = [ "postfix-reload.service" ];
     pathConfig = {
-      PathChanged = "/var/lib/acme/list.pub.solar/fullchain.pem";
+      PathChanged = "/var/lib/acme/list.${config.pub-solar-os.networking.domain}/fullchain.pem";
       Unit = "postfix-reload.service";
     };
     wantedBy = [ "multi-user.target" ];
@@ -64,7 +65,7 @@
     enable = true;
     serve.enable = true;
     hyperkitty.enable = true;
-    webHosts = [ "list.pub.solar" ];
+    webHosts = [ "list.${config.pub-solar-os.networking.domain}" ];
     siteOwner = "admins@pub.solar";
   };
 
@@ -79,28 +80,6 @@
   #  ])
   #'';
 
-  services.restic.backups.mailman-droppie = {
-    paths = [
-      "/var/lib/mailman"
-      "/var/lib/mailman-web/mailman-web.db"
-      "/var/lib/mailman-web/settings_local.json"
-      "/var/lib/postfix/conf/aliases.db"
-    ];
-    timerConfig = {
-      OnCalendar = "*-*-* 02:00:00 Etc/UTC";
-      # droppie will be offline if nachtigall misses the timer
-      Persistent = false;
-    };
-    initialize = true;
-    passwordFile = config.age.secrets."restic-repo-droppie".path;
-    repository = "sftp:yule@droppie.b12f.io:/media/internal/pub.solar";
-    pruneOpts = [
-      "--keep-daily 7"
-      "--keep-weekly 4"
-      "--keep-monthly 3"
-    ];
-  };
-
   services.restic.backups.mailman-storagebox = {
     paths = [
       "/var/lib/mailman"
@@ -109,15 +88,10 @@
       "/var/lib/postfix/conf/aliases.db"
     ];
     timerConfig = {
-      OnCalendar = "*-*-* 04:15:00 Etc/UTC";
+      OnCalendar = "*-*-* 02:00:00 Etc/UTC";
     };
     initialize = true;
-    passwordFile = config.age.secrets."restic-repo-storagebox".path;
+    passwordFile = config.age.secrets."restic-repo-storagebox-nachtigall".path;
     repository = "sftp:u377325@u377325.your-storagebox.de:/backups";
-    pruneOpts = [
-      "--keep-daily 7"
-      "--keep-weekly 4"
-      "--keep-monthly 3"
-    ];
   };
 }
diff --git a/hosts/nachtigall/apps/mastodon.nix b/modules/mastodon/default.nix
similarity index 61%
rename from hosts/nachtigall/apps/mastodon.nix
rename to modules/mastodon/default.nix
index 3df8efd5..4abec9ce 100644
--- a/hosts/nachtigall/apps/mastodon.nix
+++ b/modules/mastodon/default.nix
@@ -1,6 +1,27 @@
-{ config, pkgs, flake, inputs, ... }:
+{
+  config,
+  pkgs,
+  flake,
+  inputs,
+  ...
+}:
 
 {
+  age.secrets."mastodon-active-record-encryption-deterministic-key" = {
+    file = "${flake.self}/secrets//mastodon-active-record-encryption-deterministic-key.age";
+    mode = "400";
+    owner = config.services.mastodon.user;
+  };
+  age.secrets."mastodon-active-record-encryption-key-derivation-salt" = {
+    file = "${flake.self}/secrets//mastodon-active-record-encryption-key-derivation-salt.age";
+    mode = "400";
+    owner = config.services.mastodon.user;
+  };
+  age.secrets."mastodon-active-record-encryption-primary-key" = {
+    file = "${flake.self}/secrets//mastodon-active-record-encryption-primary-key.age";
+    mode = "400";
+    owner = config.services.mastodon.user;
+  };
   age.secrets."mastodon-secret-key-base" = {
     file = "${flake.self}/secrets/mastodon-secret-key-base.age";
     mode = "400";
@@ -38,7 +59,7 @@
   services.mastodon = {
     enable = true;
     # Different from WEB_DOMAIN in our case
-    localDomain = "pub.solar";
+    localDomain = "${config.pub-solar-os.networking.domain}";
     enableUnixSocket = true;
     # Number of processes used by the mastodon-streaming service
     # Recommended is the amount of your CPU cores minus one
@@ -48,36 +69,37 @@
     webProcesses = 2;
     # Threads per process used by the mastodon-web service
     webThreads = 5;
+    activeRecordEncryptionDeterministicKeyFile = "/run/agenix/mastodon-active-record-encryption-deterministic-key";
+    activeRecordEncryptionKeyDerivationSaltFile = "/run/agenix/mastodon-active-record-encryption-key-derivation-salt";
+    activeRecordEncryptionPrimaryKeyFile = "/run/agenix/mastodon-active-record-encryption-primary-key";
     secretKeyBaseFile = "/run/agenix/mastodon-secret-key-base";
     otpSecretFile = "/run/agenix/mastodon-otp-secret";
     vapidPrivateKeyFile = "/run/agenix/mastodon-vapid-private-key";
     vapidPublicKeyFile = "/run/agenix/mastodon-vapid-public-key";
     smtp = {
       createLocally = false;
-      host = "mail.greenbaum.zone";
+      host = "mail.pub.solar";
       port = 587;
       authenticate = true;
       user = "admins@pub.solar";
       passwordFile = "/run/agenix/mastodon-smtp-password";
       fromAddress = "mastodon-notifications@pub.solar";
     };
+    # Defined in ./opensearch.nix
+    elasticsearch.host = "127.0.0.1";
     mediaAutoRemove = {
       olderThanDays = 7;
     };
-    extraEnvFiles = [
-      "/run/agenix/mastodon-extra-env-secrets"
-    ];
+    extraEnvFiles = [ "/run/agenix/mastodon-extra-env-secrets" ];
     extraConfig = {
-      WEB_DOMAIN = "mastodon.pub.solar";
-      # Defined in ./opensearch.nix
-      ES_HOST = "127.0.0.1";
+      WEB_DOMAIN = "mastodon.${config.pub-solar-os.networking.domain}";
       # S3 File storage (optional)
       # -----------------------
       S3_ENABLED = "true";
-      S3_BUCKET = "pub-solar-mastodon";
-      S3_REGION = "europe-west-1";
-      S3_ENDPOINT = "https://gateway.tardigradeshare.io";
-      S3_ALIAS_HOST = "files.pub.solar";
+      S3_BUCKET = "mastodon";
+      S3_REGION = "eu-central";
+      S3_ENDPOINT = "https://buckets.pub.solar";
+      S3_ALIAS_HOST = "files.${config.pub-solar-os.networking.domain}";
       # Translation (optional)
       # -----------------------
       DEEPL_PLAN = "free";
@@ -85,51 +107,24 @@
       # --------------
       OIDC_ENABLED = "true";
       OIDC_DISPLAY_NAME = "pub.solar ID";
-      OIDC_ISSUER = "https://auth.pub.solar/realms/pub.solar";
+      OIDC_ISSUER = "https://auth.${config.pub-solar-os.networking.domain}/realms/${config.pub-solar-os.auth.realm}";
       OIDC_DISCOVERY = "true";
       OIDC_SCOPE = "openid,profile,email";
       OIDC_UID_FIELD = "preferred_username";
-      OIDC_REDIRECT_URI = "https://mastodon.pub.solar/auth/auth/openid_connect/callback";
+      OIDC_REDIRECT_URI = "https://mastodon.${config.pub-solar-os.networking.domain}/auth/auth/openid_connect/callback";
       OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED = "true";
       # only use OIDC for login / registration
       OMNIAUTH_ONLY = "true";
     };
   };
 
-  services.restic.backups.mastodon-droppie = {
-    paths = [
-      "/tmp/mastodon-backup.sql"
-    ];
-    timerConfig = {
-      OnCalendar = "*-*-* 02:00:00 Etc/UTC";
-      # droppie will be offline if nachtigall misses the timer
-      Persistent = false;
-    };
-    initialize = true;
-    passwordFile = config.age.secrets."restic-repo-droppie".path;
-    repository = "sftp:yule@droppie.b12f.io:/media/internal/pub.solar";
-    backupPrepareCommand = ''
-      ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d mastodon > /tmp/mastodon-backup.sql
-    '';
-    backupCleanupCommand = ''
-      rm /tmp/mastodon-backup.sql
-    '';
-    pruneOpts = [
-      "--keep-daily 7"
-      "--keep-weekly 4"
-      "--keep-monthly 3"
-    ];
-  };
-
   services.restic.backups.mastodon-storagebox = {
-    paths = [
-      "/tmp/mastodon-backup.sql"
-    ];
+    paths = [ "/tmp/mastodon-backup.sql" ];
     timerConfig = {
-      OnCalendar = "*-*-* 04:05:00 Etc/UTC";
+      OnCalendar = "*-*-* 04:00:00 Etc/UTC";
     };
     initialize = true;
-    passwordFile = config.age.secrets."restic-repo-storagebox".path;
+    passwordFile = config.age.secrets."restic-repo-storagebox-nachtigall".path;
     repository = "sftp:u377325@u377325.your-storagebox.de:/backups";
     backupPrepareCommand = ''
       ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d mastodon > /tmp/mastodon-backup.sql
@@ -137,10 +132,5 @@
     backupCleanupCommand = ''
       rm /tmp/mastodon-backup.sql
     '';
-    pruneOpts = [
-      "--keep-daily 7"
-      "--keep-weekly 4"
-      "--keep-monthly 3"
-    ];
   };
 }
diff --git a/modules/matrix-irc/default.nix b/modules/matrix-irc/default.nix
new file mode 100644
index 00000000..c026d8c5
--- /dev/null
+++ b/modules/matrix-irc/default.nix
@@ -0,0 +1,144 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  # Find element in list config.services.matrix-synapse.settings.listeners.*.resources
+  # that sets names = "client"
+  nameHasClient = name: name == "client";
+  resourceHasClient = resource: builtins.any nameHasClient resource.names;
+  listenerWithClient =
+    lib.findFirst (listener: builtins.any resourceHasClient listener.resources)
+      (throw "Found no matrix-synapse.settings.listeners.*.resources.*.names containing string client")
+      config.services.matrix-synapse.settings.listeners;
+  synapseClientPort = "${toString listenerWithClient.port}";
+in
+{
+  options.pub-solar-os = {
+    matrix.appservice-irc.mediaproxy = {
+      signingKeyPath = lib.mkOption {
+        description = "Path to file containing the IRC appservice mediaproxy signing key";
+        type = lib.types.str;
+        default = "/var/lib/matrix-appservice-irc/media-signingkey.jwk";
+      };
+    };
+  };
+  config = {
+    services.matrix-appservice-irc = {
+      enable = true;
+      localpart = "irc_bot";
+      port = 8010;
+      registrationUrl = "http://localhost:8010";
+      settings = {
+        homeserver = {
+          domain = "${config.pub-solar-os.networking.domain}";
+          url = "http://127.0.0.1:${synapseClientPort}";
+          enablePresence = false;
+        };
+        ircService = {
+          ident = {
+            address = "::";
+            enabled = false;
+            port = 1113;
+          };
+          logging = {
+            # set to debug for debugging
+            level = "warn";
+            maxFiles = 5;
+            toCosole = true;
+          };
+          matrixHandler = {
+            eventCacheSize = 4096;
+          };
+          mediaProxy = {
+            signingKeyPath = config.pub-solar-os.matrix.appservice-irc.mediaproxy.signingKeyPath;
+            # keep media for 2 weeks
+            ttlSeconds = 1209600;
+            bindPort = 11111;
+            publicUrl = "https:///matrix.${config.pub-solar-os.networking.domain}/media";
+          };
+          metrics = {
+            enabled = true;
+            remoteUserAgeBuckets = [
+              "1h"
+              "1d"
+              "1w"
+            ];
+          };
+          provisioning = {
+            enabled = false;
+            requestTimeoutSeconds = 300;
+          };
+          servers =
+            let
+              commonConfig = {
+                allowExpiredCerts = false;
+                botConfig = {
+                  enabled = false;
+                  joinChannelsIfNoUsers = false;
+                  nick = "MatrixBot";
+                };
+                dynamicChannels = {
+                  createAlias = true;
+                  enabled = true;
+                  federate = true;
+                  joinRule = "public";
+                  published = true;
+                };
+                ircClients = {
+                  allowNickChanges = true;
+                  concurrentReconnectLimit = 50;
+                  idleTimeout = 10800;
+                  lineLimit = 3;
+                  maxClients = 30;
+                  nickTemplate = "$DISPLAY[m]";
+                  reconnectIntervalMs = 5000;
+                };
+                matrixClients = {
+                  joinAttempts = -1;
+                };
+                membershipLists = {
+                  enabled = true;
+                  floodDelayMs = 10000;
+                  global = {
+                    ircToMatrix = {
+                      incremental = true;
+                      initial = true;
+                    };
+                    matrixToIrc = {
+                      incremental = true;
+                      initial = true;
+                    };
+                  };
+                };
+                port = 6697;
+                privateMessages = {
+                  enabled = true;
+                  federate = true;
+                };
+                sasl = false;
+                sendConnectionMessages = true;
+                ssl = true;
+              };
+            in
+            {
+              "irc.libera.chat" = lib.attrsets.recursiveUpdate commonConfig {
+                name = "libera";
+                dynamicChannels.groupId = "+libera.chat:localhost";
+                dynamicChannels.aliasTemplate = "#_libera_$CHANNEL";
+                matrixClients.displayName = "$NICK (LIBERA-IRC)";
+              };
+              "irc.scratch-network.net" = lib.attrsets.recursiveUpdate commonConfig {
+                name = "scratch";
+                matrixClients.displayName = "$NICK (SCRATCH-IRC)";
+                dynamicChannels.aliasTemplate = "#_scratch_$CHANNEL";
+                dynamicChannels.groupId = "+scratch-network.net:localhost";
+              };
+            };
+        };
+      };
+    };
+  };
+}
diff --git a/hosts/nachtigall/apps/matrix/mautrix-telegram.nix b/modules/matrix-telegram/default.nix
similarity index 95%
rename from hosts/nachtigall/apps/matrix/mautrix-telegram.nix
rename to modules/matrix-telegram/default.nix
index 776c8db5..dd2c4a08 100644
--- a/hosts/nachtigall/apps/matrix/mautrix-telegram.nix
+++ b/modules/matrix-telegram/default.nix
@@ -1,4 +1,10 @@
-{ flake, lib, config, pkgs, ... }:
+{
+  flake,
+  lib,
+  config,
+  pkgs,
+  ...
+}:
 {
   age.secrets."matrix-mautrix-telegram-env-file" = {
     file = "${flake.self}/secrets/matrix-mautrix-telegram-env-file.age";
@@ -13,7 +19,7 @@
       homeserver = {
         # TODO: Use the port from synapse config
         address = "http://127.0.0.1:8008";
-        domain = "pub.solar";
+        domain = "${config.pub-solar-os.networking.domain}";
         verify_ssl = true;
       };
       appservice = {
@@ -34,7 +40,7 @@
         };
         public = {
           enabled = true;
-          external = "https://matrix.pub.solar/c3c3f34b-29fb-5feb-86e5-98c75ec8214b";
+          external = "https://matrix.${config.pub-solar-os.networking.domain}/c3c3f34b-29fb-5feb-86e5-98c75ec8214b";
           prefix = "/c3c3f34b-29fb-5feb-86e5-98c75ec8214b";
         };
       };
@@ -140,7 +146,7 @@
         username_template = "telegram_{userid}";
 
         permissions = {
-          "pub.solar" = "full";
+          "${config.pub-solar-os.networking.domain}" = "full";
         };
       };
 
diff --git a/modules/matrix/default.nix b/modules/matrix/default.nix
new file mode 100644
index 00000000..e7de8c16
--- /dev/null
+++ b/modules/matrix/default.nix
@@ -0,0 +1,369 @@
+{
+  flake,
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  publicDomain = "matrix.${config.pub-solar-os.networking.domain}";
+  serverDomain = "${config.pub-solar-os.networking.domain}";
+  # Find element in list config.services.matrix-synapse.settings.listeners
+  # that sets type = "metrics"
+  listenerWithMetrics =
+    lib.findFirst (listener: listener.type == "metrics")
+      (throw "Found no matrix-synapse.settings.listeners.*.type containing string metrics")
+      config.services.matrix-synapse.settings.listeners;
+  synapseMetricsPort = listenerWithMetrics.port;
+in
+{
+  options.pub-solar-os = {
+    matrix = {
+      enable = lib.mkEnableOption "Enable matrix-synapse and matrix-authentication-service to run on the node";
+
+      synapse = {
+        app-service-config-files = lib.mkOption {
+          description = "List of app service config files";
+          type = lib.types.listOf lib.types.str;
+          default = [ ];
+        };
+
+        extra-config-files = lib.mkOption {
+          description = "List of extra synapse config files";
+          type = lib.types.listOf lib.types.str;
+          default = [ ];
+        };
+
+        signing_key_path = lib.mkOption {
+          description = "Path to file containing the signing key";
+          type = lib.types.str;
+          default = "${config.services.matrix-synapse.dataDir}/homeserver.signing.key";
+        };
+      };
+
+      matrix-authentication-service = {
+        extra-config-files = lib.mkOption {
+          description = "List of extra mas config files";
+          type = lib.types.listOf lib.types.str;
+          default = [ ];
+        };
+      };
+    };
+  };
+
+  config = lib.mkIf config.pub-solar-os.matrix.enable {
+    # Only expose matrix-synapse metrics port via wireguard interface
+    networking.firewall.interfaces.wg-ssh.allowedTCPPorts = [ synapseMetricsPort ];
+
+    services.matrix-synapse = {
+      enable = true;
+      log.root.level = "WARNING";
+      settings = {
+        server_name = serverDomain;
+        public_baseurl = "https://${publicDomain}/";
+        database = {
+          name = "psycopg2";
+          args = {
+            host = "/run/postgresql";
+            cp_max = 10;
+            cp_min = 5;
+            database = "matrix";
+          };
+          allow_unsafe_locale = false;
+          txn_limit = 0;
+        };
+        listeners = [
+          {
+            bind_addresses = [ "127.0.0.1" ];
+            port = 8008;
+            resources = [
+              {
+                compress = true;
+                names = [ "client" ];
+              }
+              {
+                compress = false;
+                names = [ "federation" ];
+              }
+            ];
+            tls = false;
+            type = "http";
+            x_forwarded = true;
+          }
+          {
+            bind_addresses = [ "0.0.0.0" ];
+            port = 8012;
+            resources = [ { names = [ "metrics" ]; } ];
+            tls = false;
+            type = "metrics";
+          }
+        ];
+
+        account_threepid_delegates.msisdn = "";
+        alias_creation_rules = [
+          {
+            action = "allow";
+            alias = "*";
+            room_id = "*";
+            user_id = "*";
+          }
+        ];
+        allow_guest_access = false;
+        allow_public_rooms_over_federation = true;
+        allow_public_rooms_without_auth = false;
+        auto_join_rooms = [
+          "#community:${serverDomain}"
+          "#general:${serverDomain}"
+        ];
+
+        autocreate_auto_join_rooms = true;
+        caches.global_factor = 0.5;
+
+        default_room_version = "10";
+        disable_msisdn_registration = true;
+        enable_media_repo = true;
+        enable_metrics = true;
+        mau_stats_only = true;
+        enable_registration = false;
+        enable_registration_captcha = false;
+        enable_registration_without_verification = false;
+        enable_room_list_search = true;
+        encryption_enabled_by_default_for_room_type = "off";
+        event_cache_size = "100K";
+
+        # https://github.com/element-hq/synapse/issues/11203
+        # No YAML deep-merge, so this needs to be in secret extraConfigFiles
+        # together with msc3861
+        #experimental_features = {
+        #  # Room summary API
+        #  msc3266_enabled = true;
+        #  # Rendezvous server for QR Code generation
+        #  msc4108_enabled = true;
+        #};
+
+        federation_rr_transactions_per_room_per_second = 50;
+        federation_client_minimum_tls_version = "1.2";
+        forget_rooms_on_leave = true;
+        include_profile_data_on_invite = true;
+        instance_map = { };
+        limit_profile_requests_to_users_who_share_rooms = false;
+
+        max_spider_size = "10M";
+        max_upload_size = "50M";
+        media_storage_providers = [ ];
+
+        password_config = {
+          enabled = false;
+          localdb_enabled = false;
+          pepper = "";
+        };
+
+        presence.enabled = true;
+        push.include_content = false;
+
+        rc_admin_redaction = {
+          burst_count = 50;
+          per_second = 1;
+        };
+        rc_federation = {
+          concurrent = 3;
+          reject_limit = 50;
+          sleep_delay = 500;
+          sleep_limit = 10;
+          window_size = 1000;
+        };
+        rc_invites = {
+          per_issuer = {
+            burst_count = 10;
+            per_second = 0.3;
+          };
+          per_room = {
+            burst_count = 10;
+            per_second = 0.3;
+          };
+          per_user = {
+            burst_count = 5;
+            per_second = 3.0e-3;
+          };
+        };
+        rc_joins = {
+          local = {
+            burst_count = 10;
+            per_second = 0.1;
+          };
+          remote = {
+            burst_count = 10;
+            per_second = 1.0e-2;
+          };
+        };
+        rc_login = {
+          account = {
+            burst_count = 3;
+            per_second = 0.17;
+          };
+          address = {
+            burst_count = 3;
+            per_second = 0.17;
+          };
+          failed_attempts = {
+            burst_count = 3;
+            per_second = 0.17;
+          };
+        };
+        rc_message = {
+          burst_count = 10;
+          per_second = 0.2;
+        };
+        rc_registration = {
+          burst_count = 3;
+          per_second = 0.17;
+        };
+        redaction_retention_period = "7d";
+        forgotten_room_retention_period = "7d";
+        redis.enabled = false;
+        registration_requires_token = false;
+        registrations_require_3pid = [ "email" ];
+        report_stats = false;
+        require_auth_for_profile_requests = false;
+        room_list_publication_rules = [
+          {
+            action = "allow";
+            alias = "*";
+            room_id = "*";
+            user_id = "*";
+          }
+        ];
+
+        signing_key_path = config.pub-solar-os.matrix.synapse.signing_key_path;
+
+        stream_writers = { };
+        trusted_key_servers = [ { server_name = "matrix.org"; } ];
+        suppress_key_server_warning = true;
+
+        turn_allow_guests = false;
+        turn_uris = [
+          "turn:${config.services.coturn.realm}:3478?transport=udp"
+          "turn:${config.services.coturn.realm}:3478?transport=tcp"
+        ];
+        turn_user_lifetime = "1h";
+
+        url_preview_accept_language = [
+          "en-US"
+          "en"
+        ];
+        url_preview_enabled = true;
+        url_preview_ip_range_blacklist = [
+          "127.0.0.0/8"
+          "10.0.0.0/8"
+          "172.16.0.0/12"
+          "192.168.0.0/16"
+          "100.64.0.0/10"
+          "192.0.0.0/24"
+          "169.254.0.0/16"
+          "192.88.99.0/24"
+          "198.18.0.0/15"
+          "192.0.2.0/24"
+          "198.51.100.0/24"
+          "203.0.113.0/24"
+          "224.0.0.0/4"
+          "::1/128"
+          "fe80::/10"
+          "fc00::/7"
+          "2001:db8::/32"
+          "ff00::/8"
+          "fec0::/10"
+        ];
+
+        user_directory = {
+          prefer_local_users = false;
+          search_all_users = false;
+        };
+        user_ips_max_age = "28d";
+
+        app_service_config_files = config.pub-solar-os.matrix.synapse.app-service-config-files;
+      };
+
+      withJemalloc = true;
+
+      extraConfigFiles = config.pub-solar-os.matrix.synapse.extra-config-files;
+
+      extras = [
+        "oidc"
+        "redis"
+      ];
+
+      plugins = [ config.services.matrix-synapse.package.plugins.matrix-synapse-shared-secret-auth ];
+    };
+
+    services.matrix-authentication-service = {
+      enable = true;
+      createDatabase = true;
+      extraConfigFiles = config.pub-solar-os.matrix.matrix-authentication-service.extra-config-files;
+
+      # https://element-hq.github.io/matrix-authentication-service/reference/configuration.html
+      settings = {
+        account.email_change_allowed = false;
+        http.public_base = "https://mas.${config.pub-solar-os.networking.domain}";
+        http.issuer = "https://mas.${config.pub-solar-os.networking.domain}";
+        http.listeners = [
+          {
+            name = "web";
+            resources = [
+              { name = "discovery"; }
+              { name = "human"; }
+              { name = "oauth"; }
+              { name = "compat"; }
+              { name = "graphql"; }
+              {
+                name = "assets";
+                path = "${config.services.matrix-authentication-service.package}/share/matrix-authentication-service/assets";
+              }
+            ];
+            binds = [
+              {
+                host = "0.0.0.0";
+                port = 8090;
+              }
+            ];
+            proxy_protocol = false;
+          }
+          {
+            name = "internal";
+            resources = [
+              { name = "health"; }
+            ];
+            binds = [
+              {
+                host = "0.0.0.0";
+                port = 8081;
+              }
+            ];
+            proxy_protocol = false;
+          }
+        ];
+        passwords.enabled = false;
+      };
+    };
+
+    pub-solar-os.backups = {
+      resources.matrix-db.resourceCreateCommand = ''
+        ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d matrix -f /tmp/matrix-synapse-backup.sql
+        ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d matrix-authentication-service -f /tmp/matrix-authentication-service-backup.sql
+      '';
+      restic.matrix-synapse = {
+        resources = [ "matrix-db" ];
+        paths = [
+          "/var/lib/matrix-synapse"
+          "/var/lib/matrix-appservice-irc"
+          "/var/lib/mautrix-telegram"
+          "/tmp/matrix-synapse-backup.sql"
+          "/tmp/matrix-authentication-service-backup.sql"
+        ];
+        timerConfig = {
+          OnCalendar = "*-*-* 05:00:00 Etc/UTC";
+        };
+        initialize = true;
+      };
+    };
+  };
+}
diff --git a/hosts/nachtigall/apps/mediawiki.nix b/modules/mediawiki/default.nix
similarity index 83%
rename from hosts/nachtigall/apps/mediawiki.nix
rename to modules/mediawiki/default.nix
index 9011fbaf..daa99ca8 100644
--- a/hosts/nachtigall/apps/mediawiki.nix
+++ b/modules/mediawiki/default.nix
@@ -1,8 +1,9 @@
-{ flake
-, config
-, lib
-, pkgs
-, ...
+{
+  flake,
+  config,
+  lib,
+  pkgs,
+  ...
 }:
 let
   localSettingsPHP = pkgs.writeScript "LocalSettings.php" ''
@@ -26,14 +27,14 @@ let
       ## For more information on customizing the URLs
       ## (like /w/index.php/Page_title to /wiki/Page_title) please see:
       ## https://www.mediawiki.org/wiki/Manual:Short_URL
-      $wgScriptPath = "https://wiki.pub.solar";
+      $wgScriptPath = "https://wiki.${config.pub-solar-os.networking.domain}";
 
       ## https://www.mediawiki.org/wiki/Manual:Short_URL
       ## https://www.mediawiki.org/wiki/Extension:OpenID_Connect#Known_issues
       $wgArticlePath = "/index.php/$1";
 
       ## The protocol and server name to use in fully-qualified URLs
-      $wgServer = "https://wiki.pub.solar";
+      $wgServer = "https://wiki.${config.pub-solar-os.networking.domain}";
 
       ## The URL path to static resources (images, scripts, etc.)
       $wgResourceBasePath = $wgScriptPath;
@@ -69,6 +70,8 @@ let
       $wgUploadDirectory = "/var/www/html/uploads";
       $wgUploadPath = $wgScriptPath . "/uploads";
 
+      $wgFileExtensions = [ 'png', 'gif', 'jpg', 'jpeg', 'webp', 'svg', 'pdf', ];
+
       $wgUseImageMagick = true;
       $wgImageMagickConvertCommand = "/usr/bin/convert";
 
@@ -138,12 +141,16 @@ let
       // https://www.mediawiki.org/wiki/Extension:PluggableAuth#Configuration
       $wgPluggableAuth_EnableAutoLogin = false;
       $wgPluggableAuth_ButtonLabel = 'Login with pub.solar ID';
+      // Avoid getting logged out after 30 minutes
+      // https://www.mediawiki.org/wiki/Topic:W4be4h6t63vf3y8p
+      // https://www.mediawiki.org/wiki/Manual:$wgRememberMe
+      $wgRememberMe = 'always';
 
       // https://www.mediawiki.org/wiki/Extension:OpenID_Connect#Keycloak
       $wgPluggableAuth_Config[] = [
           'plugin' => 'OpenIDConnect',
           'data' => [
-              'providerURL' => 'https://auth.pub.solar/realms/pub.solar',
+              'providerURL' => 'https://auth.${config.pub-solar-os.networking.domain}/realms/${config.pub-solar-os.auth.realm}',
               'clientID' => 'mediawiki',
               'clientsecret' => trim(file_get_contents('/run/mediawiki/oidc-client-secret'))
           ]
@@ -189,7 +196,7 @@ in
     '';
   };
 
-  services.nginx.virtualHosts."wiki.pub.solar" = {
+  services.nginx.virtualHosts."wiki.${config.pub-solar-os.networking.domain}" = {
     enableACME = true;
     forceSSL = true;
 
@@ -201,20 +208,20 @@ in
     group = "mediawiki";
     inherit uid;
   };
-  users.groups.mediawiki = { inherit gid; };
+  users.groups.mediawiki = {
+    inherit gid;
+  };
 
   virtualisation = {
     oci-containers = {
       backend = "docker";
 
       containers."mediawiki" = {
-        image = "git.pub.solar/pub-solar/mediawiki-oidc-docker:1.41.1";
+        image = "git.pub.solar/pub-solar/mediawiki-oidc-docker:1.43.1";
         user = "1000:${builtins.toString gid}";
         autoStart = true;
 
-        ports = [
-          "127.0.0.1:8293:80"
-        ];
+        ports = [ "127.0.0.1:8293:80" ];
 
         extraOptions = [
           "--add-host=host.docker.internal:host-gateway"
@@ -231,4 +238,25 @@ in
       };
     };
   };
+
+  pub-solar-os.backups = {
+    resources.mediawiki-db = {
+      resourceCreateCommand = ''
+        ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d mediawiki -f /tmp/mediawiki-backup.sql
+      '';
+    };
+
+    restic.mediawiki = {
+      resources = [ "mediawiki-db" ];
+      paths = [
+        "/var/lib/mediawiki/images"
+        "/var/lib/mediawiki/uploads"
+        "/tmp/mediawiki-backup.sql"
+      ];
+      timerConfig = {
+        OnCalendar = "*-*-* 00:00:00 Etc/UTC";
+      };
+      initialize = true;
+    };
+  };
 }
diff --git a/modules/networking.nix b/modules/networking.nix
deleted file mode 100644
index 490715b2..00000000
--- a/modules/networking.nix
+++ /dev/null
@@ -1,46 +0,0 @@
-{ pkgs, lib, ... }: {
-  # Don't expose SSH via public interfaces
-  networking.firewall.interfaces.wg-ssh.allowedTCPPorts = [ 22 ];
-
-  networking.hosts = {
-      "10.7.6.1" = ["nachtigall.pub.solar"];
-      "10.7.6.2" = ["flora-6.pub.solar"];
-  };
-
-  services.openssh = {
-    enable = true;
-    openFirewall = lib.mkDefault false;
-    settings = {
-      PermitRootLogin = "prohibit-password";
-      PasswordAuthentication = false;
-      # Add back openssh MACs that got removed from defaults
-      # for backwards compatibility
-      #
-      # NixOS default openssh MACs have changed to use "encrypt-then-mac" only.
-      # This breaks compatibilty with clients that do not offer these MACs. For
-      # compatibility reasons, we add back the old defaults.
-      # See: https://github.com/NixOS/nixpkgs/pull/231165
-      # 
-      # https://blog.stribik.technology/2015/01/04/secure-secure-shell.html
-      # https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67
-      Macs = [
-        "hmac-sha2-512-etm@openssh.com"
-        "hmac-sha2-256-etm@openssh.com"
-        "umac-128-etm@openssh.com"
-        "hmac-sha2-512"
-        "hmac-sha2-256"
-        "umac-128@openssh.com"
-      ];
-    };
-  };
-
-  services.resolved = {
-    enable = true;
-    extraConfig = ''
-      DNS=193.110.81.0#dns0.eu 185.253.5.0#dns0.eu 2a0f:fc80::#dns0.eu 2a0f:fc81::#dns0.eu 9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net
-      FallbackDNS=5.1.66.255#dot.ffmuc.net 185.150.99.255#dot.ffmuc.net 2001:678:e68:f000::#dot.ffmuc.net 2001:678:ed0:f000::#dot.ffmuc.net
-      Domains=~.
-      DNSOverTLS=yes
-    '';
-  };
-}
diff --git a/modules/nextcloud/default.nix b/modules/nextcloud/default.nix
new file mode 100644
index 00000000..5877942a
--- /dev/null
+++ b/modules/nextcloud/default.nix
@@ -0,0 +1,338 @@
+{
+  config,
+  pkgs,
+  flake,
+  lib,
+  ...
+}:
+{
+  age.secrets."nextcloud-secrets" = {
+    file = "${flake.self}/secrets/nextcloud-secrets.age";
+    mode = "400";
+    owner = "nextcloud";
+  };
+
+  age.secrets."nextcloud-admin-pass" = {
+    file = "${flake.self}/secrets/nextcloud-admin-pass.age";
+    mode = "400";
+    owner = "nextcloud";
+  };
+
+  services.nginx.virtualHosts."cloud.${config.pub-solar-os.networking.domain}" = {
+    enableACME = true;
+    forceSSL = true;
+
+    locations = {
+      "=/_matrix/push/v1/notify" = {
+        extraConfig = ''
+          set $custom_request_uri /index.php/apps/uppush/gateway/matrix;
+          rewrite ^.*$ /index.php/apps/uppush/gateway/matrix last;
+        '';
+      };
+
+      # Increase timeouts for unified push
+      "^~ /index.php/apps/uppush/" = {
+        priority = 499;
+        extraConfig = ''
+          # this is copy-pasted from nixpkgs
+          include ${config.services.nginx.package}/conf/fastcgi.conf;
+          fastcgi_split_path_info ^(.+?\.php)(/.*)$;
+          set $path_info $fastcgi_path_info;
+          try_files $fastcgi_script_name =404;
+          fastcgi_param PATH_INFO $path_info;
+          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+          fastcgi_param HTTPS ${if config.services.nextcloud.https then "on" else "off"};
+          fastcgi_param modHeadersAvailable true;
+          fastcgi_param front_controller_active true;
+
+          # Added timeouts for nextpush
+          fastcgi_buffering off;
+          fastcgi_connect_timeout 10m;
+          fastcgi_send_timeout 10m;
+          fastcgi_read_timeout 10m;
+
+          # If custom request is not set (ergo not _matrix push) then just keep request_uri
+          if ($custom_request_uri ~ "^$") {
+              set $custom_request_uri $request_uri;
+          }
+          # Apply our custom uri
+          fastcgi_param REQUEST_URI $custom_request_uri;
+
+          # copied from nixpkgs again
+          fastcgi_pass unix:${config.services.phpfpm.pools.nextcloud.socket};
+          fastcgi_intercept_errors on;
+          fastcgi_request_buffering off;
+        '';
+      };
+    };
+  };
+
+  services.nextcloud =
+    let
+      exiftool_1270 = pkgs.perlPackages.buildPerlPackage rec {
+        # NOTE nextcloud-memories needs this specific version of exiftool
+        # https://github.com/NixOS/nixpkgs/issues/345267
+        pname = "Image-ExifTool";
+        version = "12.70";
+        src = pkgs.fetchFromGitHub {
+          owner = "exiftool";
+          repo = "exiftool";
+          rev = version;
+          hash = "sha256-YMWYPI2SDi3s4KCpSNwovemS5MDj5W9ai0sOkvMa8Zg=";
+        };
+        nativeBuildInputs = lib.optional pkgs.stdenv.hostPlatform.isDarwin pkgs.shortenPerlShebang;
+        postInstall = lib.optionalString pkgs.stdenv.hostPlatform.isDarwin ''
+          shortenPerlShebang $out/bin/exiftool
+        '';
+      };
+    in
+    {
+      hostName = "cloud.${config.pub-solar-os.networking.domain}";
+      home = "/var/lib/nextcloud";
+
+      enable = true;
+      # When updating package, remember to update nextcloud30Packages in
+      # services.nextcloud.extraApps
+      package = pkgs.nextcloud30;
+      https = true;
+      secretFile = config.age.secrets."nextcloud-secrets".path; # secret
+      maxUploadSize = "1G";
+
+      configureRedis = true;
+
+      notify_push = {
+        enable = true;
+        # Setting this to true breaks Matrix -> NextPush integration because
+        # matrix-synapse doesn't like it if cloud.pub.solar resolves to localhost.
+        bendDomainToLocalhost = false;
+      };
+
+      config = {
+        adminuser = "admin";
+        adminpassFile = config.age.secrets."nextcloud-admin-pass".path;
+        dbuser = "nextcloud";
+        dbtype = "pgsql";
+        dbname = "nextcloud";
+      };
+
+      settings = {
+        overwrite.cli.url = "https://cloud.${config.pub-solar-os.networking.domain}";
+        overwriteprotocol = "https";
+
+        installed = true;
+        default_phone_region = "+49";
+        mail_sendmailmode = "smtp";
+        mail_from_address = "nextcloud";
+        mail_smtpmode = "smtp";
+        mail_smtpauthtype = "PLAIN";
+        mail_domain = "pub.solar";
+        mail_smtpname = "admins@pub.solar";
+        mail_smtpsecure = "ssl";
+        mail_smtpauth = true;
+        mail_smtphost = "mail.pub.solar";
+        mail_smtpport = "465";
+
+        # This is to allow connections to collabora and keycloak, among other services
+        # running on the same host
+        #
+        # https://docs.nextcloud.com/server/stable/admin_manual/configuration_server/config_sample_php_parameters.html?highlight=allow_local_remote_servers%20true
+        # https://github.com/ONLYOFFICE/onlyoffice-nextcloud/issues/293
+        allow_local_remote_servers = true;
+
+        enable_previews = true;
+        jpeg_quality = 60;
+        enabledPreviewProviders = [
+          "OC\\Preview\\PNG"
+          "OC\\Preview\\JPEG"
+          "OC\\Preview\\GIF"
+          "OC\\Preview\\BMP"
+          "OC\\Preview\\HEIC"
+          "OC\\Preview\\TIFF"
+          "OC\\Preview\\XBitmap"
+          "OC\\Preview\\SVG"
+          "OC\\Preview\\WebP"
+          "OC\\Preview\\Font"
+          "OC\\Preview\\Movie"
+          "OC\\Preview\\ImaginaryPDF"
+          "OC\\Preview\\MP3"
+          "OC\\Preview\\OpenDocument"
+          "OC\\Preview\\Krita"
+          "OC\\Preview\\TXT"
+          "OC\\Preview\\MarkDown"
+          "OC\\Preview\\Imaginary"
+        ];
+        preview_imaginary_url = "http://127.0.0.1:${toString config.services.imaginary.port}/";
+        preview_max_filesize_image = 128; # MB
+        preview_max_memory = 512; # MB
+        preview_max_x = 2048; # px
+        preview_max_y = 2048; # px
+        preview_max_scale_factor = 1;
+        preview_format = "webp";
+        "preview_ffmpeg_path" = lib.getExe pkgs.ffmpeg-headless;
+
+        "memories.exiftool_no_local" = false;
+        "memories.exiftool" = "${exiftool_1270}/bin/exiftool";
+        "memories.vod.ffmpeg" = lib.getExe pkgs.ffmpeg;
+        "memories.vod.ffprobe" = lib.getExe' pkgs.ffmpeg-headless "ffprobe";
+
+        auth.bruteforce.protection.enabled = true;
+        trashbin_retention_obligation = "auto,7";
+        skeletondirectory = "${pkgs.nextcloud-skeleton}/{lang}";
+        defaultapp = "file";
+        activity_expire_days = "14";
+        integrity.check.disabled = false;
+        updater.release.channel = "stable";
+        loglevel = 2;
+        debug = false;
+        maintenance_window_start = "1";
+        # maintenance = false;
+        app_install_overwrite = [
+          "pdfdraw"
+          "integration_whiteboard"
+        ];
+        htaccess.RewriteBase = "/";
+        theme = "";
+        simpleSignUpLink.shown = false;
+      };
+
+      phpOptions = {
+        "opcache.interned_strings_buffer" = "32";
+        "opcache.max_accelerated_files" = "16229";
+        "opcache.memory_consumption" = "256";
+        # https://docs.nextcloud.com/server/latest/admin_manual/installation/server_tuning.html#:~:text=opcache.jit%20%3D%201255%20opcache.jit_buffer_size%20%3D%20128m
+        "opcache.jit" = "1255";
+        "opcache.jit_buffer_size" = "128M";
+        # Ensure that this matches nextcloud's session_lifetime config
+        # https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/config_sample_php_parameters.html#session-lifetime
+        "session.gc_maxlifetime" = "86400";
+      };
+
+      # Calculated with 4GiB RAM, 80MiB process size available on
+      # https://spot13.com/pmcalculator/
+      poolSettings = {
+        pm = "dynamic";
+        "pm.max_children" = "52";
+        "pm.max_requests" = "500";
+        "pm.max_spare_servers" = "39";
+        "pm.min_spare_servers" = "13";
+        "pm.start_servers" = "13";
+      };
+
+      caching.redis = true;
+      # Don't allow the installation and updating of apps from the Nextcloud appstore,
+      # because we declaratively install them
+      appstoreEnable = false;
+      autoUpdateApps.enable = false;
+      extraApps = {
+        inherit (pkgs.nextcloud30Packages.apps)
+          calendar
+          contacts
+          cospend
+          deck
+          end_to_end_encryption
+          groupfolders
+          integration_deepl
+          mail
+          memories
+          notes
+          notify_push
+          previewgenerator
+          quota_warning
+          recognize
+          richdocuments
+          spreed
+          tasks
+          twofactor_webauthn
+          uppush
+          user_oidc
+          ;
+      };
+      database.createLocally = true;
+    };
+
+  # https://docs.nextcloud.com/server/30/admin_manual/installation/server_tuning.html#previews
+  services.imaginary = {
+    enable = true;
+    address = "127.0.0.1";
+    settings.return-size = true;
+  };
+
+  systemd = {
+    services =
+      let
+        occ = "/run/current-system/sw/bin/nextcloud-occ";
+      in
+      {
+        nextcloud-cron-preview-generator = {
+          environment.NEXTCLOUD_CONFIG_DIR = "${config.services.nextcloud.home}/config";
+          serviceConfig = {
+            ExecStart = "${occ} preview:pre-generate";
+            Type = "oneshot";
+            User = "nextcloud";
+          };
+        };
+
+        nextcloud-preview-generator-setup = {
+          wantedBy = [ "multi-user.target" ];
+          requires = [ "phpfpm-nextcloud.service" ];
+          after = [ "phpfpm-nextcloud.service" ];
+          environment.NEXTCLOUD_CONFIG_DIR = "${config.services.nextcloud.home}/config";
+          script = # bash
+            ''
+              # check with:
+              # for size in squareSizes widthSizes heightSizes; do echo -n "$size: "; nextcloud-occ config:app:get previewgenerator $size; done
+
+              # extra commands run for preview generator:
+              # 32   icon file list
+              # 64   icon file list android app, photos app
+              # 96   nextcloud client VFS windows file preview
+              # 256  file app grid view, many requests
+              # 512  photos app tags
+              ${occ} config:app:set --value="32 64 96 256 512" previewgenerator squareSizes
+
+              # 341 hover in maps app
+              # 1920 files/photos app when viewing picture
+              ${occ} config:app:set --value="341 1920" previewgenerator widthSizes
+
+              # 256 hover in maps app
+              # 1080 files/photos app when viewing picture
+              ${occ} config:app:set --value="256 1080" previewgenerator heightSizes
+            '';
+          serviceConfig = {
+            Type = "oneshot";
+            User = "nextcloud";
+          };
+        };
+      };
+    timers.nextcloud-cron-preview-generator = {
+      after = [ "nextcloud-setup.service" ];
+      timerConfig = {
+        OnCalendar = "*:0/10";
+        OnUnitActiveSec = "9m";
+        Persistent = true;
+        RandomizedDelaySec = 60;
+        Unit = "nextcloud-cron-preview-generator.service";
+      };
+      wantedBy = [ "timers.target" ];
+    };
+  };
+
+  services.restic.backups.nextcloud-storagebox = {
+    paths = [
+      "/var/lib/nextcloud/data"
+      "/tmp/nextcloud-backup.sql"
+    ];
+    timerConfig = {
+      OnCalendar = "*-*-* 01:00:00 Etc/UTC";
+    };
+    initialize = true;
+    passwordFile = config.age.secrets."restic-repo-storagebox-nachtigall".path;
+    repository = "sftp:u377325@u377325.your-storagebox.de:/backups";
+    backupPrepareCommand = ''
+      ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d nextcloud > /tmp/nextcloud-backup.sql
+    '';
+    backupCleanupCommand = ''
+      rm /tmp/nextcloud-backup.sql
+    '';
+  };
+}
diff --git a/hosts/nachtigall/apps/nginx-mastodon-files.nix b/modules/nginx-mastodon-files/default.nix
similarity index 81%
rename from hosts/nachtigall/apps/nginx-mastodon-files.nix
rename to modules/nginx-mastodon-files/default.nix
index 8ca4499f..8a62d359 100644
--- a/hosts/nachtigall/apps/nginx-mastodon-files.nix
+++ b/modules/nginx-mastodon-files/default.nix
@@ -1,15 +1,20 @@
-{ ... }:
+{ config, ... }:
 
 let
-  objStorHost = "link.tardigradeshare.io";
-  objStorBucket = "s/jw24ad6l4a6zxsnd32cmf5hp5nsq/pub-solar-mastodon";
+  objStorHost = "mastodon.web.pub.solar";
 in
 {
   services.nginx.virtualHosts = {
-    "files.pub.solar" = {
+    "files.${config.pub-solar-os.networking.domain}" = {
       enableACME = true;
       forceSSL = true;
 
+      # Use variable to force nginx to perform a DNS resolution on its value,
+      # the IP of the object storage provider may not always remain the same.
+      extraConfig = ''
+        set $s3_backend 'https://${objStorHost}';
+      '';
+
       locations = {
         "= /" = {
           index = "index.html";
@@ -25,7 +30,6 @@ in
               deny all;
             }
 
-            resolver 8.8.8.8;
             proxy_set_header Host ${objStorHost};
             proxy_set_header Connection \'\';
             proxy_set_header Authorization \'\';
@@ -40,7 +44,7 @@ in
             proxy_hide_header x-amz-bucket-region;
             proxy_hide_header x-amzn-requestid;
             proxy_ignore_headers Set-Cookie;
-            proxy_pass https://${objStorHost}/${objStorBucket}$request_uri?download;
+            proxy_pass $s3_backend$request_uri;
             proxy_intercept_errors off;
             proxy_ssl_protocols TLSv1.2 TLSv1.3;
             proxy_ssl_server_name on;
diff --git a/hosts/nachtigall/apps/nginx-mastodon.nix b/modules/nginx-mastodon/default.nix
similarity index 53%
rename from hosts/nachtigall/apps/nginx-mastodon.nix
rename to modules/nginx-mastodon/default.nix
index 5e9f9b02..f8984093 100644
--- a/hosts/nachtigall/apps/nginx-mastodon.nix
+++ b/modules/nginx-mastodon/default.nix
@@ -5,22 +5,25 @@ in
 {
   services.nginx = {
     virtualHosts = {
-      "mastodon.pub.solar" = {
+      "mastodon.${config.pub-solar-os.networking.domain}" = {
         root = "${cfg.package}/public/";
         # mastodon only supports https, but you can override this if you offload tls elsewhere.
         forceSSL = lib.mkDefault true;
         enableACME = lib.mkDefault true;
+        extraConfig = ''
+          client_max_body_size 99m;
+        '';
 
         locations."/auth/sign_up".extraConfig = ''
           return 302 /auth/sign_in;
         '';
 
         locations."/auth/confirmation/new".extraConfig = ''
-          return 302 https://auth.pub.solar/realms/pub.solar/login-actions/reset-credentials?client_id=mastodon;
+          return 302 https://auth.${config.pub-solar-os.networking.domain}/realms/${config.pub-solar-os.auth.realm}/login-actions/reset-credentials?client_id=mastodon;
         '';
 
         locations."/auth/password/new".extraConfig = ''
-          return 302 https://auth.pub.solar/realms/pub.solar/login-actions/reset-credentials?client_id=mastodon;
+          return 302 https://auth.${config.pub-solar-os.networking.domain}/realms/${config.pub-solar-os.auth.realm}/login-actions/reset-credentials?client_id=mastodon;
         '';
 
         locations."/system/".alias = "/var/lib/mastodon/public-system/";
@@ -30,7 +33,12 @@ in
         };
 
         locations."@proxy" = {
-          proxyPass = (if cfg.enableUnixSocket then "http://unix:/run/mastodon-web/web.socket" else "http://127.0.0.1:${toString(cfg.webPort)}");
+          proxyPass = (
+            if cfg.enableUnixSocket then
+              "http://unix:/run/mastodon-web/web.socket"
+            else
+              "http://127.0.0.1:${toString (cfg.webPort)}"
+          );
           proxyWebsockets = true;
         };
 
@@ -45,13 +53,12 @@ in
       extraConfig = ''
         least_conn;
       '';
-      servers = builtins.listToAttrs
-        (map
-          (i: {
-            name = "unix:/run/mastodon-streaming/streaming-${toString i}.socket";
-            value = { };
-          })
-          (lib.range 1 cfg.streamingProcesses));
+      servers = builtins.listToAttrs (
+        map (i: {
+          name = "unix:/run/mastodon-streaming/streaming-${toString i}.socket";
+          value = { };
+        }) (lib.range 1 cfg.streamingProcesses)
+      );
     };
   };
 }
diff --git a/hosts/nachtigall/apps/nginx-matrix.nix b/modules/nginx-matrix/default.nix
similarity index 58%
rename from hosts/nachtigall/apps/nginx-matrix.nix
rename to modules/nginx-matrix/default.nix
index a65a3dce..f6274d8f 100644
--- a/hosts/nachtigall/apps/nginx-matrix.nix
+++ b/modules/nginx-matrix/default.nix
@@ -1,29 +1,29 @@
-{ lib, pkgs, ... }:
+{
+  lib,
+  pkgs,
+  config,
+  ...
+}:
 let
   commonHeaders = ''
     add_header Permissions-Policy interest-cohort=() always;
     add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
     add_header X-XSS-Protection "1; mode=block";
   '';
-  clientConfig = import ./matrix/element-client-config.nix { inherit lib pkgs; };
+  clientConfig = import ./element-client-config.nix { inherit config lib pkgs; };
   wellKnownClient = domain: {
     "m.homeserver".base_url = "https://matrix.${domain}";
     "m.identity_server".base_url = "https://matrix.${domain}";
-    "org.matrix.msc3575.proxy".url = "https://matrix.${domain}";
+    "org.matrix.msc2965.authentication" = {
+      issuer = "https://mas.${domain}/";
+      account = "https://mas.${domain}/account";
+    };
     "im.vector.riot.e2ee".default = true;
     "io.element.e2ee" = {
       default = true;
       secure_backup_required = false;
       secure_backup_setup_methods = [ ];
     };
-    "m.integrations" = {
-      managers = [
-        {
-          api_url = "https://dimension.${domain}/api/v1/scalar";
-          ui_url = "https://dimension.${domain}/element";
-        }
-      ];
-    };
   };
   wellKnownServer = domain: { "m.server" = "matrix.${domain}:8448"; };
   wellKnownSupport = {
@@ -44,7 +44,7 @@ let
         role = "m.role.admin";
       }
     ];
-    support_page = "https://pub.solar/about";
+    support_page = "https://${config.pub-solar-os.networking.domain}/about";
   };
   mkWellKnown = data: ''
     add_header Content-Type application/json;
@@ -64,19 +64,44 @@ in
     # This is already in production use #
     #####################################
 
-    "pub.solar" = {
-      locations = wellKnownLocations "pub.solar";
+    "${config.pub-solar-os.networking.domain}" = {
+      locations = wellKnownLocations "${config.pub-solar-os.networking.domain}";
     };
 
-    "chat.pub.solar" = {
+    "chat.${config.pub-solar-os.networking.domain}" = {
       forceSSL = true;
       enableACME = true;
-      root = pkgs.element-web.override {
-        conf = clientConfig;
+      root = pkgs.element-web.override { conf = clientConfig; };
+    };
+
+    "stickers.chat.${config.pub-solar-os.networking.domain}" = {
+      forceSSL = true;
+      enableACME = true;
+      root = pkgs.element-stickerpicker;
+    };
+
+    "mas.${config.pub-solar-os.networking.domain}" = {
+      root = "/dev/null";
+
+      forceSSL = lib.mkDefault true;
+      enableACME = lib.mkDefault true;
+
+      locations = {
+        "/" = {
+          proxyPass = "http://127.0.0.1:8090";
+
+          extraConfig = ''
+            ${commonHeaders}
+            proxy_http_version 1.1;
+
+            # Forward the client IP address
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+          '';
+        };
       };
     };
 
-    "matrix.pub.solar" = {
+    "matrix.${config.pub-solar-os.networking.domain}" = {
       root = "/dev/null";
 
       forceSSL = lib.mkDefault true;
@@ -90,46 +115,68 @@ in
       locations = {
         # For telegram
         "/c3c3f34b-29fb-5feb-86e5-98c75ec8214b" = {
+          priority = 100;
           proxyPass = "http://127.0.0.1:8009";
           extraConfig = commonHeaders;
         };
 
-        # sliding-sync
-        "~ ^/(client/|_matrix/client/unstable/org.matrix.msc3575/sync)" = {
-          proxyPass = "http://127.0.0.1:8011";
+        # For IRC appservice media proxy
+        "/media" = {
+          priority = 100;
+          proxyPass = "http://127.0.0.1:${toString (config.services.matrix-appservice-irc.settings.ircService.mediaProxy.bindPort)}";
           extraConfig = commonHeaders;
         };
 
-        "~* ^(/_matrix|/_synapse/client|/_synapse/oidc)" = {
+        # Forward to the auth service
+        "~ ^/_matrix/client/(.*)/(login|logout|refresh)" = {
+          priority = 100;
+          proxyPass = "http://127.0.0.1:8090";
+
+          extraConfig = ''
+            ${commonHeaders}
+            proxy_http_version 1.1;
+
+            # Forward the client IP address
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+          '';
+        };
+
+        # Forward to Synapse
+        # as per https://element-hq.github.io/synapse/latest/reverse_proxy.html#nginx
+        "~ ^(/_matrix|/_synapse/client)" = {
+          priority = 200;
           proxyPass = "http://127.0.0.1:8008";
 
           extraConfig = ''
             ${commonHeaders}
+            proxy_set_header X-Forwarded-For $remote_addr;
+            proxy_set_header X-Forwarded-Proto $scheme;
             proxy_set_header Host $host;
-            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
-            proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
 
             client_body_buffer_size 25M;
             client_max_body_size 50M;
             proxy_max_temp_file_size 0;
+            proxy_http_version 1.1;
           '';
         };
       };
     };
-    "matrix.pub.solar-federation" = {
-      serverName = "matrix.pub.solar";
+    "matrix.${config.pub-solar-os.networking.domain}-federation" = {
+      serverName = "matrix.${config.pub-solar-os.networking.domain}";
       forceSSL = lib.mkDefault true;
       enableACME = lib.mkDefault true;
-      listen = [{
-        port = 8448;
-        addr = "0.0.0.0";
-        ssl = true;
-      }
+      listen = [
+        {
+          port = 8448;
+          addr = "0.0.0.0";
+          ssl = true;
+        }
         {
           port = 8448;
           addr = "[::]";
           ssl = true;
-        }];
+        }
+      ];
       root = "/dev/null";
       extraConfig = ''
         server_tokens off;
@@ -153,4 +200,3 @@ in
   };
   networking.firewall.allowedTCPPorts = [ 8448 ];
 }
-
diff --git a/hosts/nachtigall/apps/matrix/element-client-config.nix b/modules/nginx-matrix/element-client-config.nix
similarity index 62%
rename from hosts/nachtigall/apps/matrix/element-client-config.nix
rename to modules/nginx-matrix/element-client-config.nix
index 9c8607f8..192ffc8b 100644
--- a/hosts/nachtigall/apps/matrix/element-client-config.nix
+++ b/modules/nginx-matrix/element-client-config.nix
@@ -1,8 +1,14 @@
-{ pkgs, lib, ... }: {
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+{
   default_server_config = {
     "m.homeserver" = {
-      base_url = "https://matrix.pub.solar";
-      server_name = "pub.solar";
+      base_url = "https://matrix.${config.pub-solar-os.networking.domain}";
+      server_name = "${config.pub-solar-os.networking.domain}";
     };
     "m.identity_server" = {
       base_url = "";
@@ -35,11 +41,24 @@
     homeUrl = "";
   };
   branding = {
-    auth_footer_links = [{
-      text = "Privacy";
-      url = "https://pub.solar/privacy";
-    }];
+    auth_footer_links = [
+      {
+        text = "Privacy";
+        url = "https://pub.solar/privacy";
+      }
+    ];
     # FUTUREWORK: Replace with pub.solar logo
     auth_header_logo_url = "themes/element/img/logos/element-logo.svg";
   };
+  # Enable Element Call Beta
+  features = {
+    feature_video_rooms = true;
+    feature_group_calls = true;
+    feature_element_call_video_rooms = true;
+  };
+  element_call = {
+    url = "https://call.element.io";
+    participant_limit = 50;
+    brand = "Element Call";
+  };
 }
diff --git a/hosts/nachtigall/apps/nginx-website-miom.nix b/modules/nginx-website-miom/default.nix
similarity index 94%
rename from hosts/nachtigall/apps/nginx-website-miom.nix
rename to modules/nginx-website-miom/default.nix
index dd01acd6..5366adfb 100644
--- a/hosts/nachtigall/apps/nginx-website-miom.nix
+++ b/modules/nginx-website-miom/default.nix
@@ -2,6 +2,7 @@
 
 {
   systemd.tmpfiles.rules = [
+    "d '/srv/www' 0750 hakkonaut hakkonaut - -"
     "d '/srv/www/miom.space' 0750 hakkonaut hakkonaut - -"
   ];
 
diff --git a/hosts/nachtigall/apps/nginx-website.nix b/modules/nginx-website/default.nix
similarity index 60%
rename from hosts/nachtigall/apps/nginx-website.nix
rename to modules/nginx-website/default.nix
index 3611d48d..c857f103 100644
--- a/hosts/nachtigall/apps/nginx-website.nix
+++ b/modules/nginx-website/default.nix
@@ -1,12 +1,14 @@
-{ lib, ... }: {
+{ lib, config, ... }:
+{
   systemd.tmpfiles.rules = [
-    "d '/srv/www/pub.solar' 0750 hakkonaut hakkonaut - -"
+    "d '/srv/www' 0750 hakkonaut hakkonaut - -"
+    "d '/srv/www/${config.pub-solar-os.networking.domain}' 0750 hakkonaut hakkonaut - -"
   ];
 
   services.nginx.virtualHosts = {
-    "www.pub.solar" = {
+    "www.${config.pub-solar-os.networking.domain}" = {
       enableACME = true;
-      addSSL = true;
+      forceSSL = true;
 
       extraConfig = ''
         error_log /dev/null;
@@ -15,12 +17,12 @@
 
       locations."/" = {
         extraConfig = ''
-          return 301 https://pub.solar$request_uri;
+          return 301 https://${config.pub-solar-os.networking.domain}$request_uri;
         '';
       };
     };
 
-    "pub.solar" = {
+    "${config.pub-solar-os.networking.domain}" = {
       default = true;
       enableACME = true;
       forceSSL = true;
@@ -35,7 +37,7 @@
         # https://masto.host/mastodon-usernames-different-from-the-domain-used-for-installation/
         "/.well-known/host-meta" = {
           extraConfig = ''
-            return 301 https://mastodon.pub.solar$request_uri;
+            return 301 https://mastodon.${config.pub-solar-os.networking.domain}$request_uri;
           '';
         };
 
@@ -44,38 +46,40 @@
           # Redirect requests that match /.well-known/webfinger?resource=* to Mastodon
           extraConfig = ''
             if ($arg_resource) {
-              return 301 https://mastodon.pub.solar$request_uri;
+              return 301 https://mastodon.${config.pub-solar-os.networking.domain}$request_uri;
             }
 
             add_header Content-Type text/plain;
-            return 200 '{\n  "subject": "acct:admins@pub.solar",\n  "links": [\n    {\n    "rel": "http://openid.net/specs/connect/1.0/issuer",\n    "href": "https://auth.pub.solar/realms/pub.solar"\n    }\n  ]\n}';
+            return 200 '{\n  "subject": "acct:admins@pub.solar",\n  "links": [\n    {\n    "rel": "http://openid.net/specs/connect/1.0/issuer",\n    "href": "https://auth.${config.pub-solar-os.networking.domain}/realms/pub.solar"\n    }\n  ]\n}';
           '';
         };
 
         # Responsible disclosure information https://securitytxt.org/
-        "/.well-known/security.txt" = let
+        "/.well-known/security.txt" =
+          let
             securityTXT = lib.lists.foldr (a: b: a + "\n" + b) "" [
               "Contact: mailto:admins@pub.solar"
               "Expires: 2025-01-04T23:00:00.000Z"
               "Encryption: https://keys.openpgp.org/vks/v1/by-fingerprint/8A8987ADE3736C8CA2EB315A9B809EBBDD62BAE3"
               "Preferred-Languages: en,de"
-              "Canonical: https://pub.solar/.well-known/security.txt"
+              "Canonical: https://${config.pub-solar-os.networking.domain}/.well-known/security.txt"
             ];
-        in {
-          extraConfig = ''
-            add_header Content-Type text/plain;
-            return 200 '${securityTXT}';
-          '';
-        };
+          in
+          {
+            extraConfig = ''
+              add_header Content-Type text/plain;
+              return 200 '${securityTXT}';
+            '';
+          };
 
         "/satzung" = {
           extraConfig = ''
-            return 302 https://cloud.pub.solar/s/iaKqiW25QJpHPYs;
+            return 302 https://cloud.${config.pub-solar-os.networking.domain}/s/iaKqiW25QJpHPYs;
           '';
         };
 
         "/" = {
-          root = "/srv/www/pub.solar";
+          root = "/srv/www/${config.pub-solar-os.networking.domain}";
           index = "index.html";
           tryFiles = "$uri $uri/ =404";
         };
diff --git a/hosts/nachtigall/apps/nginx.nix b/modules/nginx/default.nix
similarity index 64%
rename from hosts/nachtigall/apps/nginx.nix
rename to modules/nginx/default.nix
index 01e933c5..3270a239 100644
--- a/hosts/nachtigall/apps/nginx.nix
+++ b/modules/nginx/default.nix
@@ -1,18 +1,21 @@
-{ config
-, lib
-, pkgs
-, self
-, ...
+{
+  config,
+  lib,
+  pkgs,
+  self,
+  ...
 }:
 let
-  acmeEmailAddress = "admins@pub.solar";
+  acmeEmailAddress = config.pub-solar-os.adminEmail;
   webserverGroup = "hakkonaut";
 in
 {
+  users.users.nginx.extraGroups = [ webserverGroup ];
+
   services.nginx = {
     enable = true;
-    group = webserverGroup;
     enableReload = true;
+    statusPage = true;
     proxyCachePath.cache = {
       enable = true;
     };
@@ -20,6 +23,13 @@ in
     recommendedOptimisation = true;
     recommendedProxySettings = true;
     recommendedTlsSettings = true;
+    resolver.addresses = [
+      # quad9.net
+      "9.9.9.9"
+      "149.112.112.112"
+      "[2620:fe::fe]"
+      "[2620:fe::9]"
+    ];
     appendHttpConfig = ''
       # https://my.f5.com/manage/s/article/K51798430
       proxy_headers_hash_bucket_size 128;
@@ -38,5 +48,8 @@ in
     defaults.email = acmeEmailAddress;
   };
 
-  networking.firewall.allowedTCPPorts = [ 80 443 ];
+  networking.firewall.allowedTCPPorts = [
+    80
+    443
+  ];
 }
diff --git a/modules/obs-portal/default.nix b/modules/obs-portal/default.nix
new file mode 100644
index 00000000..226f45c7
--- /dev/null
+++ b/modules/obs-portal/default.nix
@@ -0,0 +1,172 @@
+{
+  config,
+  lib,
+  pkgs,
+  self,
+  flake,
+  ...
+}:
+let
+  configPy = pkgs.writeText "obs-portal-config.py" ''
+    DEBUG = False
+    VERBOSE = DEBUG
+    AUTO_RESTART = DEBUG
+    LEAN_MODE = False
+    FRONTEND_URL = None
+    FRONTEND_HTTPS = True
+    FRONTEND_DIR = "../frontend/build/"
+    FRONTEND_CONFIG = {
+        "imprintUrl": "${config.pub-solar-os.imprintUrl}",
+        "privacyPolicyUrl": "${config.pub-solar-os.privacyPolicyUrl}",
+        "mapHome": {"zoom": 12, "latitude": 50.93, "longitude": 6.97},
+        "banner": {
+            "text": "This is an installation serving the Cologne/Bonn region run for Team OBSKöln by pub.solar n.e.V.",
+            "style": "info"
+        },
+    }
+    TILES_FILE = None
+    ADDITIONAL_CORS_ORIGINS = None
+  '';
+
+  env = {
+    OBS_KEYCLOAK_URI = "auth.${config.pub-solar-os.networking.domain}";
+    OBS_PORTAL_URI = "obs-portal.${config.pub-solar-os.networking.domain}";
+
+    OBS_POSTGRES_MAX_OVERFLOW = "20";
+    OBS_POSTGRES_POOL_SIZE = "40";
+
+    OBS_HOST = "0.0.0.0";
+    OBS_PORT = "3000";
+    OBS_KEYCLOAK_URL = "https://auth.${config.pub-solar-os.networking.domain}/realms/${config.pub-solar-os.auth.realm}/";
+    OBS_KEYCLOAK_CLIENT_ID = "openbikesensor-portal";
+    OBS_DEDICATED_WORKER = "True";
+    OBS_DATA_DIR = "/data";
+    OBS_PROXIES_COUNT = "1";
+  };
+in
+{
+  age.secrets.obs-portal-env = {
+    file = "${flake.self}/secrets/obs-portal-env.age";
+    mode = "600";
+  };
+
+  age.secrets.obs-portal-database-env = {
+    file = "${flake.self}/secrets/obs-portal-database-env.age";
+    mode = "600";
+  };
+
+  systemd.services."docker-network-obs-portal" =
+    let
+      docker = config.virtualisation.oci-containers.backend;
+      dockerBin = "${pkgs.${docker}}/bin/${docker}";
+    in
+    {
+      serviceConfig.Type = "oneshot";
+      before = [
+        "docker-obs-portal.service"
+        "docker-obs-portal-db.service"
+        "docker-obs-portal-worker.service"
+      ];
+      requiredBy = [
+        "docker-obs-portal.service"
+        "docker-obs-portal-db.service"
+        "docker-obs-portal-worker.service"
+      ];
+      script = ''
+        ${dockerBin} network inspect obs-portal-net >/dev/null 2>&1 || ${dockerBin} network create obs-portal-net --subnet 172.20.0.0/24
+      '';
+    };
+
+  services.nginx.virtualHosts."obs-portal.${config.pub-solar-os.networking.domain}" = {
+    enableACME = true;
+    forceSSL = true;
+
+    locations."/" = {
+      proxyWebsockets = true;
+      extraConfig = ''
+        proxy_pass http://127.0.0.1:3001;
+        proxy_set_header Host $host;
+      '';
+    };
+  };
+
+  virtualisation = {
+    oci-containers = {
+      backend = "docker";
+
+      containers."obs-portal" = {
+        image = "git.pub.solar/pub-solar/obs-portal:latest";
+        autoStart = true;
+        ports = [ "127.0.0.1:3001:${env.OBS_PORT}" ];
+        dependsOn = [
+          "obs-portal-db"
+          "obs-portal-worker"
+        ];
+
+        environment = env;
+        environmentFiles = [ config.age.secrets.obs-portal-env.path ];
+
+        volumes = [
+          "${configPy}:/opt/obs/api/config.py"
+          "/var/lib/obs-portal${env.OBS_DATA_DIR}:${env.OBS_DATA_DIR}"
+          "/var/lib/obs-portal/pbf/:/pbf"
+        ];
+
+        extraOptions = [ "--network=obs-portal-net" ];
+      };
+
+      containers."obs-portal-worker" = {
+        image = "git.pub.solar/pub-solar/obs-portal:latest";
+        autoStart = true;
+
+        cmd = [
+          "python"
+          "tools/process_track.py"
+        ];
+
+        environment = env;
+        environmentFiles = [ config.age.secrets.obs-portal-env.path ];
+
+        volumes = [
+          "${configPy}:/opt/obs/api/config.py"
+          "/var/lib/obs-portal${env.OBS_DATA_DIR}:${env.OBS_DATA_DIR}"
+        ];
+
+        extraOptions = [ "--network=obs-portal-net" ];
+      };
+
+      containers."obs-portal-db" = {
+        image = "openmaptiles/postgis:7.0";
+        autoStart = true;
+
+        environmentFiles = [ config.age.secrets.obs-portal-database-env.path ];
+
+        volumes = [ "/var/lib/postgres-obs-portal/data:/var/lib/postgresql/data" ];
+
+        extraOptions = [ "--network=obs-portal-net" ];
+      };
+    };
+  };
+
+  pub-solar-os.backups = {
+    resources.obs-db.resourceCreateCommand = ''
+      ${pkgs.docker}/bin/docker exec -i --user postgres obs-portal-db pg_dump -d obs -f /tmp/obs-portal-backup.sql
+    '';
+    restic.obs-portal = {
+      resources = [ "obs-db" ];
+      paths = [
+        "/var/lib/obs-portal/data"
+        "/tmp/obs-portal-backup.sql"
+      ];
+      timerConfig = {
+        OnCalendar = "*-*-* 06:30:00 Etc/UTC";
+      };
+      initialize = true;
+      pruneOpts = [
+        "--keep-daily 7"
+        "--keep-weekly 4"
+        "--keep-monthly 3"
+      ];
+    };
+  };
+}
diff --git a/hosts/nachtigall/apps/opensearch.nix b/modules/opensearch/default.nix
similarity index 100%
rename from hosts/nachtigall/apps/opensearch.nix
rename to modules/opensearch/default.nix
diff --git a/hosts/nachtigall/apps/owncast.nix b/modules/owncast/default.nix
similarity index 83%
rename from hosts/nachtigall/apps/owncast.nix
rename to modules/owncast/default.nix
index c5026a41..1752a5e6 100644
--- a/hosts/nachtigall/apps/owncast.nix
+++ b/modules/owncast/default.nix
@@ -1,10 +1,12 @@
-{ flake
-, config
-, lib
-, pkgs
-, ...
-}: {
-  services.nginx.virtualHosts."stream.pub.solar" = {
+{
+  flake,
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+{
+  services.nginx.virtualHosts."stream.${config.pub-solar-os.networking.domain}" = {
     enableACME = true;
     forceSSL = true;
     locations."/" = {
diff --git a/modules/postgresql/default.nix b/modules/postgresql/default.nix
new file mode 100644
index 00000000..fa0550d7
--- /dev/null
+++ b/modules/postgresql/default.nix
@@ -0,0 +1,28 @@
+{ ... }:
+
+{
+  services.postgresql = {
+    enable = true;
+    # Required for MediaWiki, connects via docker network
+    enableTCPIP = true;
+    # https://pgtune.leopard.in.ua/ DB Version: 14 OS Type: linux DB Type: web
+    # Total Memory (RAM): 8 GB Data Storage: ssd
+    settings = {
+      max_connections = 200;
+      shared_buffers = "2GB";
+      effective_cache_size = "6GB";
+      maintenance_work_mem = "512MB";
+      checkpoint_completion_target = 0.9;
+      wal_buffers = "16MB";
+      default_statistics_target = 100;
+      random_page_cost = 1.1;
+      effective_io_concurrency = 200;
+      work_mem = "5242kB";
+      huge_pages = "off";
+      min_wal_size = "1GB";
+      max_wal_size = "4GB";
+      # ZFS is always consistent (Copy-On-Write)
+      full_page_writes = false;
+    };
+  };
+}
diff --git a/modules/prometheus-exporters/default.nix b/modules/prometheus-exporters/default.nix
new file mode 100644
index 00000000..68418ded
--- /dev/null
+++ b/modules/prometheus-exporters/default.nix
@@ -0,0 +1,14 @@
+{ config, ... }:
+{
+  services.prometheus = {
+    exporters = {
+      node = {
+        enable = true;
+        openFirewall = true;
+        firewallFilter = "--in-interface wg-ssh --protocol tcp --match tcp --dport ${toString config.services.prometheus.exporters.node.port}";
+        enabledCollectors = [ "systemd" ];
+        port = 9002;
+      };
+    };
+  };
+}
diff --git a/modules/prometheus/alert-rules.nix b/modules/prometheus/alert-rules.nix
new file mode 100644
index 00000000..556071b8
--- /dev/null
+++ b/modules/prometheus/alert-rules.nix
@@ -0,0 +1,259 @@
+{ lib }:
+
+let
+  # docker's filesystems disappear quickly, leading to false positives
+  deviceFilter = ''path!~"^(/var/lib/docker|/nix/store).*"'';
+in
+lib.mapAttrsToList
+  (name: opts: {
+    alert = name;
+    expr = opts.condition;
+    for = opts.time or "2m";
+    labels = { };
+    annotations.description = opts.description;
+  })
+  ({
+
+    # prometheus_too_many_restarts = {
+    #   condition = ''changes(process_start_time_seconds{job=~"prometheus|alertmanager"}[15m]) > 2'';
+    #   description = "Prometheus has restarted more than twice in the last 15 minutes. It might be crashlooping.";
+    # };
+
+    # alert_manager_config_not_synced = {
+    #   condition = ''count(count_values("config_hash", alertmanager_config_hash)) > 1'';
+    #   description = "Configurations of AlertManager cluster instances are out of sync.";
+    # };
+
+    #alert_manager_e2e_dead_man_switch = {
+    #  condition = "vector(1)";
+    #  description = "Prometheus DeadManSwitch is an always-firing alert. It's used as an end-to-end test of Prometheus through the Alertmanager.";
+    #};
+
+    # prometheus_not_connected_to_alertmanager = {
+    #   condition = "prometheus_notifications_alertmanagers_discovered < 1";
+    #   description = "Prometheus cannot connect the alertmanager\n  VALUE = {{ $value }}\n  LABELS = {{ $labels }}";
+    # };
+
+    # prometheus_rule_evaluation_failures = {
+    #   condition = "increase(prometheus_rule_evaluation_failures_total[3m]) > 0";
+    #   description = "Prometheus encountered {{ $value }} rule evaluation failures, leading to potentially ignored alerts.\n  VALUE = {{ $value }}\n  LABELS = {{ $labels }}";
+    # };
+
+    # prometheus_template_expansion_failures = {
+    #   condition = "increase(prometheus_template_text_expansion_failures_total[3m]) > 0";
+    #   time = "0m";
+    #   description = "Prometheus encountered {{ $value }} template text expansion failures\n  VALUE = {{ $value }}\n  LABELS = {{ $labels }}";
+    # };
+
+    # promtail_file_lagging = {
+    #   condition = ''abs(promtail_file_bytes_total - promtail_read_bytes_total) > 1e6'';
+    #   time = "15m";
+    #   description = ''{{ $labels.instance }} {{ $labels.job }} {{ $labels.path }} has been lagging by more than 1MB for more than 15m.'';
+    # };
+
+    filesystem_root_full_80percent = {
+      condition = ''100 - ((node_filesystem_avail_bytes{fstype!="rootfs",mountpoint="/"} * 100) / node_filesystem_size_bytes{fstype!="rootfs",mountpoint="/"}) > 80'';
+      time = "10m";
+      description = "{{$labels.instance}} device {{$labels.device}} on {{$labels.mountpoint}} got less than 20% space left on its filesystem.";
+    };
+
+    filesystem_data_full_80percent = {
+      condition = ''100 - ((node_filesystem_avail_bytes{fstype!="rootfs",mountpoint="/var/lib"} * 100) / node_filesystem_size_bytes{fstype!="rootfs",mountpoint="/var/lib"}) > 80'';
+      time = "10m";
+      description = "{{$labels.instance}} device {{$labels.device}} on {{$labels.mountpoint}} got less than 20% space left on its filesystem.";
+    };
+
+    # filesystem_inodes_full = {
+    #   condition = ''disk_inodes_free / disk_inodes_total < 0.10'';
+    #   time = "10m";
+    #   description = "{{$labels.instance}} device {{$labels.device}} on {{$labels.mountpoint}} got less than 10% inodes left on its filesystem.";
+    # };
+
+    # daily_task_not_run = {
+    #   # give 6 hours grace period
+    #   condition = ''time() - task_last_run{state="ok",frequency="daily"} > (24 + 6) * 60 * 60'';
+    #   description = "{{$labels.instance}}: {{$labels.name}} was not run in the last 24h";
+    # };
+
+    # daily_task_failed = {
+    #   condition = ''task_last_run{state="fail"}'';
+    #   description = "{{$labels.instance}}: {{$labels.name}} failed to run";
+    # };
+    # } // (lib.genAttrs [
+    #   "borgbackup-turingmachine"
+    #   "borgbackup-eve"
+    #   "borgbackup-datastore"
+    # ]
+    #   (name: {
+    #     condition = ''absent_over_time(task_last_run{name="${name}"}[1d])'';
+    #     description = "status of ${name} is unknown: no data for a day";
+    #   }))
+    # // {
+
+    # borgbackup_matchbox_not_run = {
+    #   # give 6 hours grace period
+    #   condition = ''time() - task_last_run{state="ok",frequency="daily",name="borgbackup-matchbox"} > 7 * 24 * 60 * 60'';
+    #   description = "{{$labels.instance}}: {{$labels.name}} was not run in the last week";
+    # };
+
+    # borgbackup_matchbox = {
+    #   condition = ''absent_over_time(task_last_run{name="borgbackup-matchbox"}[7d])'';
+    #   description = "status of borgbackup-matchbox is unknown: no data for a week";
+    # };
+
+    # homeassistant = {
+    #   condition = ''
+    #     homeassistant_entity_available{domain="persistent_notification", entity!="persistent_notification.http_login"} >= 0'';
+    #   description =
+    #     "homeassistant notification {{$labels.entity}} ({{$labels.friendly_name}}): {{$value}}";
+    # };
+
+    #swap_using_20percent = {
+    #  condition = "node_memory_SwapTotal_bytes - (node_memory_SwapCached_bytes + node_memory_SwapFree_bytes) > node_memory_SwapTotal_bytes * 0.2";
+    #  time = "30m";
+    #  description = "{{$labels.instance}} is using 20% of its swap space for at least 30 minutes.";
+    #};
+
+    systemd_service_failed = {
+      condition = ''node_systemd_unit_state{state="failed"} == 1'';
+      description = "{{$labels.instance}} failed to (re)start service {{$labels.name}}.";
+    };
+
+    restic_backup_too_old = {
+      condition = ''(time() - restic_snapshots_latest_time)/(60*60) > 24'';
+      description = "{{$labels.instance}} not backed up for more than 24 hours. ({{$value}})";
+    };
+
+    #host_down = {
+    #  condition = ''up{job="node-stats", instance!~"ahorn.wireguard:9100|kartoffel.wireguard:9100|mega.wireguard:9100"} == 0'';
+    #  description = "{{$labels.instance}} is down!";
+    #};
+
+    # service_not_running = {
+    #   condition = ''systemd_units_active_code{name=~"teamspeak3-server.service|tt-rss.service", sub!="running"}'';
+    #   description = "{{$labels.instance}} should have a running {{$labels.name}}.";
+    # };
+
+    ram_using_90percent = {
+      condition = "node_memory_Buffers_bytes + node_memory_MemFree_bytes + node_memory_Cached_bytes < node_memory_MemTotal_bytes * 0.1";
+      time = "1h";
+      description = "{{$labels.instance}} is using at least 90% of its RAM for at least 1 hour.";
+    };
+
+    cpu_using_90percent = {
+      condition = ''100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) >= 90'';
+      time = "20m";
+      description = "{{$labels.instance}} is running with cpu usage > 90% for at least 20 minutes: {{$value}}";
+    };
+
+    reboot = {
+      condition = "node_boot_time_seconds < 300";
+      description = "{{$labels.instance}} just rebooted.";
+    };
+
+    uptime = {
+      condition = "(time() - node_boot_time_seconds ) / (60*60*24) > 90";
+      description = "Uptime monster: {{$labels.instance}} has been up for more than 90 days.";
+    };
+
+    flake_nixpkgs_outdated = {
+      condition = ''(time() - flake_input_last_modified{input="nixpkgs"}) / (60*60*24) > 30'';
+      description = "Nixpkgs outdated: Nixpkgs on {{$labels.instance}} has not been updated in 30 days";
+    };
+
+    /*
+      ping = {
+      condition = "ping_result_code{type!='mobile'} != 0";
+      description = "{{$labels.url}}: ping from {{$labels.instance}} has failed!";
+      };
+
+      ping_high_latency = {
+      condition = "ping_average_response_ms{type!='mobile'} > 5000";
+      description = "{{$labels.instance}}: ping probe from {{$labels.source}} is encountering high latency!";
+      };
+    */
+    #http_status = {
+    #  condition = ''probe_http_status_code{instance!~"https://pub.solar"} != 200'';
+    #  description = "http request failed from {{$labels.instance}}: {{$labels.result}}!";
+    #};
+    /*
+      http_match_failed = {
+      condition = "http_response_response_string_match == 0";
+      description = "{{$labels.server}} : http body not as expected; status code: {{$labels.status_code}}!";
+      };
+      dns_query = {
+      condition = "dns_query_result_code != 0";
+      description = "{{$labels.domain}} : could retrieve A record {{$labels.instance}} from server {{$labels.server}}: {{$labels.result}}!";
+      };
+      secure_dns_query = {
+      condition = "secure_dns_state != 0";
+      description = "{{$labels.domain}} : could retrieve A record {{$labels.instance}} from server {{$labels.server}}: {{$labels.result}} for protocol {{$labels.protocol}}!";
+      };
+      connection_failed = {
+      condition = "net_response_result_code != 0";
+      description = "{{$labels.server}}: connection to {{$labels.port}}({{$labels.protocol}}) failed from {{$labels.instance}}";
+      };
+      healthchecks = {
+      condition = "hc_check_up == 0";
+      description = "{{$labels.instance}}: healtcheck {{$labels.job}} fails!";
+      };
+    */
+    #cert_expiry = {
+    #  condition = "(probe_ssl_earliest_cert_expiry - time())/(3600*24) < 30";
+    #  description = "{{$labels.instance}}: The TLS certificate will expire in less than 30 days: {{$value}}s";
+    #};
+
+    # ignore devices that disabled S.M.A.R.T (example if attached via USB)
+
+    # smart_errors = {
+    #   condition = ''smart_device_health_ok{enabled!="Disabled"} != 1'';
+    #   description =
+    #     "{{$labels.instance}}: S.M.A.R.T reports: {{$labels.device}} ({{$labels.model}}) has errors.";
+    # };
+
+    oom_kills = {
+      condition = "increase(node_vmstat_oom_kill[5m]) > 0";
+      description = "{{$labels.instance}}: OOM kill detected";
+    };
+
+    /*
+      unusual_disk_read_latency = {
+      condition =
+      "rate(diskio_read_time[1m]) / rate(diskio_reads[1m]) > 0.1 and rate(diskio_reads[1m]) > 0";
+      description = ''
+      {{$labels.instance}}: Disk latency is growing (read operations > 100ms)
+      '';
+      };
+
+      unusual_disk_write_latency = {
+      condition =
+      "rate(diskio_write_time[1m]) / rate(diskio_write[1m]) > 0.1 and rate(diskio_write[1m]) > 0";
+      description = ''
+      {{$labels.instance}}: Disk latency is growing (write operations > 100ms)
+      '';
+      };
+    */
+
+    #host_memory_under_memory_pressure = {
+    #  condition = "rate(node_vmstat_pgmajfault[1m]) > 1000";
+    #  description = "{{$labels.instance}}: The node is under heavy memory pressure. High rate of major page faults: {{$value}}";
+    #};
+
+    # ext4_errors = {
+    #   condition = "ext4_errors_value > 0";
+    #   description =
+    #     "{{$labels.instance}}: ext4 has reported {{$value}} I/O errors: check /sys/fs/ext4/*/errors_count";
+    # };
+
+    # alerts_silences_changed = {
+    #   condition = ''abs(delta(alertmanager_silences{state="active"}[1h])) >= 1'';
+    #   description =
+    #     "alertmanager: number of active silences has changed: {{$value}}";
+    # };
+
+    garage_cluster_healthy = {
+      condition = "cluster_healthy == 0";
+      time = "15m";
+      description = "garage cluster on {{$labels.instance}} is not healthy: {{$labels.result}}!";
+    };
+  })
diff --git a/modules/prometheus/default.nix b/modules/prometheus/default.nix
new file mode 100644
index 00000000..b43b2f30
--- /dev/null
+++ b/modules/prometheus/default.nix
@@ -0,0 +1,279 @@
+{
+  config,
+  lib,
+  pkgs,
+  flake,
+  ...
+}:
+let
+  # Find element in list config.services.matrix-synapse.settings.listeners
+  # that sets type = "metrics"
+  listenerWithMetrics =
+    lib.findFirst (listener: listener.type == "metrics")
+      (throw "Found no matrix-synapse.settings.listeners.*.type containing string metrics")
+      flake.self.nixosConfigurations.nachtigall.config.services.matrix-synapse.settings.listeners;
+  synapseMetricsPort = "${toString listenerWithMetrics.port}";
+in
+{
+  age.secrets.alertmanager-envfile = {
+    file = "${flake.self}/secrets/alertmanager-envfile.age";
+    mode = "600";
+    owner = "alertmanager";
+  };
+
+  security.acme.certs = {
+    "alerts.${config.pub-solar-os.networking.domain}" = {
+      # disable http challenge
+      webroot = null;
+      # enable dns challenge
+      dnsProvider = "namecheap";
+    };
+  };
+
+  services.nginx.virtualHosts."alerts.${config.pub-solar-os.networking.domain}" = {
+    enableACME = true;
+    forceSSL = true;
+
+    listenAddresses = [
+      "10.7.6.5"
+      "[fd00:fae:fae:fae:fae:5::]"
+    ];
+
+    locations."/" = {
+      proxyPass = "http://127.0.0.1:${toString config.services.prometheus.alertmanager.port}";
+    };
+  };
+
+  services.prometheus = {
+    enable = true;
+    port = 9001;
+    globalConfig = {
+      scrape_interval = "10s";
+      scrape_timeout = "9s";
+    };
+    scrapeConfigs = [
+      {
+        job_name = "node-exporter";
+        static_configs = [
+          {
+            targets = [
+              "nachtigall.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.node.port}"
+            ];
+            labels = {
+              instance = "nachtigall";
+            };
+          }
+          {
+            targets = [
+              "metronom.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.node.port}"
+            ];
+            labels = {
+              instance = "metronom";
+            };
+          }
+          {
+            targets = [
+              "tankstelle.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.node.port}"
+            ];
+            labels = {
+              instance = "tankstelle";
+            };
+          }
+          {
+            targets = [
+              "trinkgenossin.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.node.port}"
+            ];
+            labels = {
+              instance = "trinkgenossin";
+            };
+          }
+          {
+            targets = [
+              "delite.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.node.port}"
+            ];
+            labels = {
+              instance = "delite";
+            };
+          }
+          {
+            targets = [
+              "blue-shell.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.node.port}"
+            ];
+            labels = {
+              instance = "blue-shell";
+            };
+          }
+        ];
+      }
+      {
+        job_name = "matrix-synapse";
+        metrics_path = "/_synapse/metrics";
+        static_configs = [
+          {
+            targets = [ "nachtigall.wg.${config.pub-solar-os.networking.domain}:${synapseMetricsPort}" ];
+            labels = {
+              instance = "nachtigall";
+            };
+          }
+        ];
+      }
+      {
+        job_name = "garage";
+        static_configs = [
+          {
+            targets = [ "trinkgenossin.wg.${config.pub-solar-os.networking.domain}:3903" ];
+            labels = {
+              instance = "trinkgenossin";
+            };
+          }
+          {
+            targets = [ "delite.wg.${config.pub-solar-os.networking.domain}:3903" ];
+            labels = {
+              instance = "delite";
+            };
+          }
+          {
+            targets = [ "blue-shell.wg.${config.pub-solar-os.networking.domain}:3903" ];
+            labels = {
+              instance = "blue-shell";
+            };
+          }
+        ];
+      }
+      {
+        job_name = "pub-solar/loki";
+        static_configs = [
+          {
+            targets = [ "127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}" ];
+            labels = {
+              instance = "trinkgenossin";
+              namespace = "pub-solar";
+              cluster = "prod";
+            };
+          }
+        ];
+      }
+      {
+        job_name = "nextcloud";
+        scrape_interval = "5m";
+        static_configs = [
+          {
+            targets = [
+              "nachtigall.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.nextcloud.port}"
+            ];
+            labels = {
+              instance = "nachtigall";
+            };
+          }
+        ];
+      }
+      {
+        job_name = "nginx";
+        static_configs = [
+          {
+            targets = [
+              "nachtigall.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.nginx.port}"
+            ];
+            labels = {
+              instance = "nachtigall";
+            };
+          }
+        ];
+      }
+      #{
+      #  job_name = "php-fpm";
+      #  static_configs = [
+      #    {
+      #      targets = [
+      #        "nachtigall.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.php-fpm.port}"
+      #      ];
+      #      labels = {
+      #        instance = "nachtigall";
+      #      };
+      #    }
+      #  ];
+      #}
+      {
+        job_name = "postgres";
+        relabel_configs = [
+          {
+            source_labels = [
+              "__address__"
+            ];
+            target_label = "__param_target";
+          }
+          {
+            source_labels = [
+              "__param_target"
+            ];
+            target_label = "instance";
+          }
+          {
+            target_label = "__address__";
+            replacement = "nachtigall.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.postgres.port}";
+          }
+        ];
+        static_configs = [
+          {
+            targets = [
+              "nachtigall.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.postgres.port}"
+            ];
+          }
+        ];
+      }
+    ];
+
+    ruleFiles = [
+      (pkgs.writeText "prometheus-rules.yml" (
+        builtins.toJSON {
+          groups = [
+            {
+              name = "alerting-rules";
+              rules = import ./alert-rules.nix { inherit lib; };
+            }
+          ];
+        }
+      ))
+    ];
+
+    alertmanagers = [ { static_configs = [ { targets = [ "localhost:9093" ]; } ]; } ];
+
+    alertmanager = {
+      enable = true;
+      # port = 9093; # Default
+      webExternalUrl = "https://alerts.pub.solar";
+      environmentFile = "${config.age.secrets.alertmanager-envfile.path}";
+      configuration = {
+
+        route = {
+          receiver = "all";
+          group_by = [ "instance" ];
+          group_wait = "30s";
+          group_interval = "2m";
+          repeat_interval = "24h";
+        };
+
+        receivers = [
+          {
+            name = "all";
+            # Email config documentation: https://prometheus.io/docs/alerting/latest/configuration/#email_config
+            email_configs = [
+              {
+                send_resolved = true;
+                to = "admins@pub.solar";
+                from = "alerts@pub.solar";
+                smarthost = "mail.pub.solar:465";
+                auth_username = "admins@pub.solar";
+                auth_password = "$SMTP_AUTH_PASSWORD";
+                require_tls = false;
+              }
+            ];
+            # TODO:
+            # For matrix notifications, look into: https://github.com/pinpox/matrix-hook and add a webhook
+            #   webhook_configs = [ { url = "http://127.0.0.1:11000/alert"; } ];
+          }
+        ];
+      };
+    };
+  };
+}
diff --git a/modules/promtail/default.nix b/modules/promtail/default.nix
new file mode 100644
index 00000000..ec99c1cd
--- /dev/null
+++ b/modules/promtail/default.nix
@@ -0,0 +1,51 @@
+{
+  config,
+  lib,
+  pkgs,
+  flake,
+  ...
+}:
+{
+  services.promtail = {
+    enable = true;
+    configuration = {
+      server = {
+        http_listen_port = 9080;
+        grpc_listen_port = 0;
+      };
+      positions = {
+        filename = "/tmp/positions.yaml";
+      };
+      clients = [
+        {
+          url = "http://trinkgenossin.wg.pub.solar:${toString flake.self.nixosConfigurations.trinkgenossin.config.services.loki.configuration.server.http_listen_port}/loki/api/v1/push";
+        }
+      ];
+      scrape_configs = [
+        {
+          job_name = "journal";
+          journal = {
+            max_age = "24h";
+            labels = {
+              job = "systemd-journal";
+              host = config.networking.hostName;
+            };
+          };
+          relabel_configs = [
+            {
+              source_labels = [
+                "__journal__systemd_unit"
+                "__journal__systemd_user_unit"
+              ];
+              target_label = "service";
+            }
+            {
+              source_labels = [ "__journal_priority_keyword" ];
+              target_label = "severity";
+            }
+          ];
+        }
+      ];
+    };
+  };
+}
diff --git a/hosts/nachtigall/apps/searx.nix b/modules/searx/default.nix
similarity index 75%
rename from hosts/nachtigall/apps/searx.nix
rename to modules/searx/default.nix
index febe91b2..1c31f156 100644
--- a/hosts/nachtigall/apps/searx.nix
+++ b/modules/searx/default.nix
@@ -1,8 +1,9 @@
-{ flake
-, config
-, lib
-, pkgs
-, ...
+{
+  flake,
+  config,
+  lib,
+  pkgs,
+  ...
 }:
 {
   age.secrets.searx-environment = {
@@ -10,7 +11,7 @@
     mode = "600";
   };
 
-  services.nginx.virtualHosts."search.pub.solar" = {
+  services.nginx.virtualHosts."search.${config.pub-solar-os.networking.domain}" = {
     enableACME = true;
     forceSSL = true;
 
@@ -38,14 +39,14 @@
       use_default_settings = true;
 
       server = {
-        base_url = "https://search.pub.solar";
+        base_url = "https://search.${config.pub-solar-os.networking.domain}";
         secret_key = "@SEARX_SECRET_KEY@";
       };
 
       general = {
         debug = false;
-        instance_name = "search.pub.solar";
-        privacypolicy_url = "https://pub.solar/privacy";
+        instance_name = "search.${config.pub-solar-os.networking.domain}";
+        privacypolicy_url = config.pub-solar-os.privacyPolicyUrl;
         # use true to use your own donation page written in searx/info/en/donate.md
         # use false to disable the donation link
         donation_url = false;
@@ -64,9 +65,18 @@
       };
 
       engine = [
-        { engine = "startpage"; disabled = false; }
-        { engine = "yahoo"; disabled = false; }
-        { engine = "tagesschau"; disabled = false; }
+        {
+          engine = "startpage";
+          disabled = false;
+        }
+        {
+          engine = "yahoo";
+          disabled = false;
+        }
+        {
+          engine = "tagesschau";
+          disabled = false;
+        }
       ];
 
       ui = {
diff --git a/modules/terminal-tooling.nix b/modules/terminal-tooling.nix
deleted file mode 100644
index c0d00505..00000000
--- a/modules/terminal-tooling.nix
+++ /dev/null
@@ -1,18 +0,0 @@
-{ flake, ... }: {
-  home-manager.users.${flake.self.username} = {
-    programs.git.enable = true;
-    programs.starship.enable = true;
-    programs.bash.enable = true;
-    programs.neovim = {
-      enable = true;
-      vimAlias = true;
-      viAlias = true;
-      defaultEditor = true;
-      # configure = {
-      #   packages.myVimPackages = with pkgs.vimPlugins; {
-      #     start = [vim-nix vim-surrund rainbow];
-      #   };
-      # };
-    };
-  };
-}
diff --git a/hosts/nachtigall/apps/tmate.nix b/modules/tmate/default.nix
similarity index 56%
rename from hosts/nachtigall/apps/tmate.nix
rename to modules/tmate/default.nix
index 59018d30..a4784419 100644
--- a/hosts/nachtigall/apps/tmate.nix
+++ b/modules/tmate/default.nix
@@ -1,9 +1,9 @@
-{ ... }:
+{ config, ... }:
 {
   services.tmate-ssh-server = {
     enable = true;
     port = 2222;
     openFirewall = true;
-    host = "tmate.pub.solar";
+    host = "tmate.${config.pub-solar-os.networking.domain}";
   };
 }
diff --git a/modules/tt-rss/default.nix b/modules/tt-rss/default.nix
new file mode 100644
index 00000000..a580b81c
--- /dev/null
+++ b/modules/tt-rss/default.nix
@@ -0,0 +1,82 @@
+{
+  flake,
+  config,
+  pkgs,
+  ...
+}:
+let
+  ttrss-auth-oidc = pkgs.stdenv.mkDerivation {
+    name = "ttrss-auth-oidc";
+    version = "7ebfbc91e92bb133beb907c6bde79279ee5156df";
+    src = pkgs.fetchgit {
+      url = "https://git.tt-rss.org/fox/ttrss-auth-oidc.git";
+      rev = "7ebfbc91e92bb133beb907c6bde79279ee5156df";
+      hash = "sha256-G6vZBvSWms6s6nHZWsxJjMGuubt/imiBvbp6ykwrZbg=";
+    };
+    installPhase = ''
+      mkdir -p $out/auth_oidc
+      cp -r * $out/auth_oidc
+    '';
+  };
+in
+{
+  age.secrets.tt-rss-database-password = {
+    file = "${flake.self}/secrets/tt-rss-database-password.age";
+    owner = "tt_rss";
+    mode = "600";
+  };
+  age.secrets.tt-rss-keycloak-client-secret = {
+    file = "${flake.self}/secrets/tt-rss-keycloak-client-secret.age";
+    owner = "tt_rss";
+    mode = "600";
+  };
+  age.secrets.tt-rss-smtp-password = {
+    file = "${flake.self}/secrets/tt-rss-smtp-password.age";
+    owner = "tt_rss";
+    mode = "600";
+  };
+  age.secrets.tt-rss-feed-crypt-key = {
+    file = "${flake.self}/secrets/tt-rss-feed-crypt-key.age";
+    owner = "tt_rss";
+    mode = "600";
+  };
+
+  services.nginx.virtualHosts."rss.${config.pub-solar-os.networking.domain}" = {
+    enableACME = true;
+    forceSSL = true;
+  };
+
+  services.tt-rss = {
+    enable = true;
+    virtualHost = "rss.${config.pub-solar-os.networking.domain}";
+    selfUrlPath = "https://rss.${config.pub-solar-os.networking.domain}";
+    root = "/var/lib/tt-rss";
+    logDestination = "";
+    plugins = [
+      "auth_internal"
+      "note"
+      "auth_oidc"
+    ];
+    pluginPackages = [ ttrss-auth-oidc ];
+    email = {
+      server = "mail.pub.solar";
+      security = "tls";
+      login = "admins@pub.solar";
+      fromName = "pub.solar RSS server";
+      fromAddress = "rss@pub.solar";
+      digestSubject = "[RSS] New headlines for last 24 hours";
+    };
+    database = {
+      passwordFile = config.age.secrets.tt-rss-database-password.path;
+      createLocally = true;
+    };
+    extraConfig = ''
+      putenv('TTRSS_SMTP_PASSWORD=' . file_get_contents('${config.age.secrets.tt-rss-smtp-password.path}'));
+      putenv('TTRSS_AUTH_OIDC_NAME=pub.solar ID');
+      putenv('TTRSS_AUTH_OIDC_URL=https://auth.${config.pub-solar-os.networking.domain}/realms/${config.pub-solar-os.auth.realm}/');
+      putenv('TTRSS_AUTH_OIDC_CLIENT_ID=tt-rss');
+      putenv('TTRSS_AUTH_OIDC_CLIENT_SECRET=' . file_get_contents('${config.age.secrets.tt-rss-keycloak-client-secret.path}'));
+      putenv('TTRSS_FEED_CRYPT_KEY=' . file_get_contents('${config.age.secrets.tt-rss-feed-crypt-key.path}'));
+    '';
+  };
+}
diff --git a/modules/unlock-luks-on-boot/default.nix b/modules/unlock-luks-on-boot/default.nix
new file mode 100644
index 00000000..fd8c547f
--- /dev/null
+++ b/modules/unlock-luks-on-boot/default.nix
@@ -0,0 +1,20 @@
+{ flake, config, ... }:
+{
+  boot.initrd.network = {
+    enable = true;
+    ssh = {
+      enable = true;
+      # To prevent ssh clients from freaking out because a different host key is used,
+      # a different port for ssh is useful (assuming the same host has also a regular sshd running)
+      port = 2222;
+
+      # Please create this manually the first time.
+      hostKeys = [ "/etc/secrets/initrd/ssh_host_ed25519_key" ];
+      authorizedKeys = flake.self.logins.sshPubKeys;
+    };
+    postCommands = ''
+      # Automatically ask for the password on SSH login
+      echo 'cryptsetup-askpass || echo "Unlock was successful; exiting SSH session" && exit 1' >> /root/.profile
+    '';
+  };
+}
diff --git a/modules/unlock-zfs-on-boot.nix b/modules/unlock-zfs-on-boot/default.nix
similarity index 91%
rename from modules/unlock-zfs-on-boot.nix
rename to modules/unlock-zfs-on-boot/default.nix
index d459b10b..586f9440 100644
--- a/modules/unlock-zfs-on-boot.nix
+++ b/modules/unlock-zfs-on-boot/default.nix
@@ -1,4 +1,5 @@
-{ flake, ... }: {
+{ flake, config, ... }:
+{
   # From https://nixos.wiki/wiki/ZFS#Unlock_encrypted_zfs_via_ssh_on_boot
   boot.initrd.network = {
     enable = true;
@@ -10,7 +11,7 @@
 
       # Please create this manually the first time.
       hostKeys = [ "/etc/secrets/initrd/ssh_host_ed25519_key" ];
-      authorizedKeys = flake.self.logins.admins.sshPubKeys;
+      authorizedKeys = flake.self.logins.sshPubKeys;
     };
     # this will automatically load the zfs password prompt on login
     # and kill the other prompt so boot can continue
diff --git a/modules/users.nix b/modules/users.nix
deleted file mode 100644
index 91b78e0a..00000000
--- a/modules/users.nix
+++ /dev/null
@@ -1,30 +0,0 @@
-{ flake, pkgs, ... }: {
-  users.users.${flake.self.username} = {
-    name = flake.self.username;
-    group = flake.self.username;
-    extraGroups = [ "wheel" "docker" ];
-    isNormalUser = true;
-    openssh.authorizedKeys.keys = flake.self.logins.admins.sshPubKeys;
-  };
-  users.groups.${flake.self.username} = { };
-
-  # TODO: Remove when we stop locking ourselves out.
-  users.users.root.openssh.authorizedKeys.keys = flake.self.logins.admins.sshPubKeys;
-
-  users.users.hakkonaut = {
-    description = "CI and automation user";
-    home = "/home/hakkonaut";
-    createHome = true;
-    useDefaultShell = true;
-    uid = 998;
-    group = "hakkonaut";
-    isSystemUser = true;
-    openssh.authorizedKeys.keys = flake.self.logins.robots.sshPubKeys;
-  };
-
-  users.groups.hakkonaut = { };
-
-  users.users.root.initialHashedPassword = "$y$j9T$bIN6GjQkmPMllOcQsq52K0$q0Z5B5.KW/uxXK9fItB8H6HO79RYAcI/ZZdB0Djke32";
-
-  security.sudo.wheelNeedsPassword = false;
-}
diff --git a/overlays/default.nix b/overlays/default.nix
index 74cf4094..d07f2095 100644
--- a/overlays/default.nix
+++ b/overlays/default.nix
@@ -1,23 +1,27 @@
-{ self
-, inputs
-, ...
-}: {
+{ inputs, ... }:
+{
   flake = {
-    nixosModules = rec {
-      overlays = ({ ... }: {
-        nixpkgs.overlays = [
-          (final: prev:
-            let
-              unstable = import inputs.unstable {
-                system = prev.system;
-              };
-            in
-            {
-              forgejo-runner = unstable.forgejo-runner;
-              element-themes = prev.callPackage ./pkgs/element-themes { inherit (inputs) element-themes; };
-            })
-        ];
-      });
+    nixosModules = {
+      overlays = (
+        { ... }:
+        {
+          nixpkgs.overlays = [
+            (
+              final: prev:
+              let
+                unstable = import inputs.unstable { system = prev.system; };
+              in
+              {
+                element-themes = prev.callPackage ./pkgs/element-themes { inherit (inputs) element-themes; };
+                element-stickerpicker = prev.callPackage ./pkgs/element-stickerpicker {
+                  inherit (inputs) element-stickers maunium-stickerpicker;
+                };
+                nextcloud-skeleton = prev.callPackage ./pkgs/nextcloud-skeleton { };
+              }
+            )
+          ];
+        }
+      );
     };
   };
 }
diff --git a/overlays/pkgs/element-stickerpicker/default.nix b/overlays/pkgs/element-stickerpicker/default.nix
new file mode 100644
index 00000000..403feef7
--- /dev/null
+++ b/overlays/pkgs/element-stickerpicker/default.nix
@@ -0,0 +1,14 @@
+{
+  stdenvNoCC,
+  element-stickers,
+  maunium-stickerpicker,
+}:
+stdenvNoCC.mkDerivation {
+  src = maunium-stickerpicker;
+  name = "element-stickers";
+  buildPhase = ''
+    mv web $out/
+    cp ${element-stickers}/uploaded-packs/*.json $out/packs/
+    cp -r ${element-stickers}/uploaded-packs/thumbnails $out/packs/
+  '';
+}
diff --git a/overlays/pkgs/element-themes/default.nix b/overlays/pkgs/element-themes/default.nix
index c8a1a598..46d49375 100644
--- a/overlays/pkgs/element-themes/default.nix
+++ b/overlays/pkgs/element-themes/default.nix
@@ -1,4 +1,8 @@
-{ stdenvNoCC, jq, element-themes }:
+{
+  stdenvNoCC,
+  jq,
+  element-themes,
+}:
 stdenvNoCC.mkDerivation {
   src = element-themes;
   name = "element-themes";
diff --git a/overlays/pkgs/nextcloud-skeleton/de/Dokumente/Beispiel.odt b/overlays/pkgs/nextcloud-skeleton/de/Dokumente/Beispiel.odt
new file mode 100644
index 00000000..02ccc4bd
Binary files /dev/null and b/overlays/pkgs/nextcloud-skeleton/de/Dokumente/Beispiel.odt differ
diff --git a/overlays/pkgs/nextcloud-skeleton/de/Fotos/pubsolar.png b/overlays/pkgs/nextcloud-skeleton/de/Fotos/pubsolar.png
new file mode 100644
index 00000000..98a1fa45
Binary files /dev/null and b/overlays/pkgs/nextcloud-skeleton/de/Fotos/pubsolar.png differ
diff --git a/hosts/nachtigall/apps/nextcloud-skeleton/Pictures/pubsolar.svg b/overlays/pkgs/nextcloud-skeleton/de/Fotos/pubsolar.svg
similarity index 99%
rename from hosts/nachtigall/apps/nextcloud-skeleton/Pictures/pubsolar.svg
rename to overlays/pkgs/nextcloud-skeleton/de/Fotos/pubsolar.svg
index aa84e458..02b4a136 100644
--- a/hosts/nachtigall/apps/nextcloud-skeleton/Pictures/pubsolar.svg
+++ b/overlays/pkgs/nextcloud-skeleton/de/Fotos/pubsolar.svg
@@ -4,7 +4,7 @@
    data-name="Layer 3"
    viewBox="0 0 275.3 276.37"
    version="1.1"
-   sodipodi:docname="pubsolar.svg"
+   sodipodi:docname="pub.solar.svg"
    inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
diff --git a/overlays/pkgs/nextcloud-skeleton/de/Liesmich.md b/overlays/pkgs/nextcloud-skeleton/de/Liesmich.md
new file mode 100644
index 00000000..f2c38ed5
--- /dev/null
+++ b/overlays/pkgs/nextcloud-skeleton/de/Liesmich.md
@@ -0,0 +1,7 @@
+# Willkommen zu deiner pub.solar Cloud!
+
+Standardmässig ist die Cloud auf 10MB Speicherplatz begrenzt. Wenn Du mehr zur Verfügung haben möchtest, sende uns gerne eine kurze Mail an [crew@pub.solar](mailto:crew@pub.solar).
+
+Zum Download von Nextcloud Desktop Clients, besuche bitte https://nextcloud.com/download. Eine Anleitung zur Einrichtung findest Du hier in unserem [Wiki zu Nextcloud](https://wiki.pub.solar/index.php/Nextcloud).
+
+Du kannst diese Datei bearbeiten, indem Du den Text hier anklickst und zum Beispiel Notizen für dieses Verzeichnis schreiben : )
diff --git a/overlays/pkgs/nextcloud-skeleton/default.nix b/overlays/pkgs/nextcloud-skeleton/default.nix
new file mode 100644
index 00000000..062ac7ce
--- /dev/null
+++ b/overlays/pkgs/nextcloud-skeleton/default.nix
@@ -0,0 +1,29 @@
+# Based on:
+# https://nix.dev/tutorials/working-with-local-files.html#union-explicitly-include-files
+{
+  stdenvNoCC,
+  lib,
+}:
+let
+  fs = lib.fileset;
+  sourceFiles = fs.unions [
+    ./default/Documents/Example.odt
+    ./default/Pictures/pubsolar.png
+    ./default/Pictures/pubsolar.svg
+    ./default/Readme.md
+    ./de/Dokumente/Beispiel.odt
+    ./de/Fotos/pubsolar.png
+    ./de/Fotos/pubsolar.svg
+    ./de/Liesmich.md
+  ];
+in
+stdenvNoCC.mkDerivation {
+  name = "nextcloud-skeleton";
+  src = fs.toSource {
+    root = ./.;
+    fileset = sourceFiles;
+  };
+  postInstall = ''
+    cp -vr . $out
+  '';
+}
diff --git a/overlays/pkgs/nextcloud-skeleton/default/Documents/Example.odt b/overlays/pkgs/nextcloud-skeleton/default/Documents/Example.odt
new file mode 100644
index 00000000..d1878b53
Binary files /dev/null and b/overlays/pkgs/nextcloud-skeleton/default/Documents/Example.odt differ
diff --git a/overlays/pkgs/nextcloud-skeleton/default/Pictures/pubsolar.png b/overlays/pkgs/nextcloud-skeleton/default/Pictures/pubsolar.png
new file mode 100644
index 00000000..98a1fa45
Binary files /dev/null and b/overlays/pkgs/nextcloud-skeleton/default/Pictures/pubsolar.png differ
diff --git a/overlays/pkgs/nextcloud-skeleton/default/Pictures/pubsolar.svg b/overlays/pkgs/nextcloud-skeleton/default/Pictures/pubsolar.svg
new file mode 100644
index 00000000..02b4a136
--- /dev/null
+++ b/overlays/pkgs/nextcloud-skeleton/default/Pictures/pubsolar.svg
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   id="Layer_3"
+   data-name="Layer 3"
+   viewBox="0 0 275.3 276.37"
+   version="1.1"
+   sodipodi:docname="pub.solar.svg"
+   inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <sodipodi:namedview
+     id="namedview226"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="4.3962803"
+     inkscape:cx="95.762774"
+     inkscape:cy="149.33079"
+     inkscape:window-width="2560"
+     inkscape:window-height="1380"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="Layer_3" />
+  <defs
+     id="defs197">
+    <style
+       id="style195">.cls-1,.cls-2{fill:#ed1c24;}.cls-1{stroke:#ed1c24;stroke-width:6.89px;}.cls-1,.cls-2,.cls-4{stroke-miterlimit:10;}.cls-2{stroke:#fff;stroke-width:4.72px;}.cls-3{fill:#fff;}.cls-4{stroke:#000;stroke-width:4.58px;}</style>
+  </defs>
+  <title
+     id="title199">PubSolar logo</title>
+  <path
+     class="cls-1"
+     d="M362.85,272.68v11.78l-4.39,1.84a18.38,18.38,0,0,0-11.24,15.8l-.59,9.43-7.92.61a18.38,18.38,0,0,0-15.53,11.22l-2.47,5.9H309.07a18.38,18.38,0,0,0-14.13,6.63l-6.8,8.17-10.58-3.17a18.38,18.38,0,0,0-14.89,1.95l-9.84,6-8.65-5.75a18.38,18.38,0,0,0-15.75-2.2l-10,3.17-5.88-7a18.38,18.38,0,0,0-15.43-6.51l-10.24.76-4.62-8.75a18.38,18.38,0,0,0-14.22-9.69l-9.7-1.08-1.89-10.65a18.38,18.38,0,0,0-11.06-13.77L134.7,283l.93-11.32a18.38,18.38,0,0,0-7-16l-6.52-5.06,3.55-8.77a18.38,18.38,0,0,0-1.77-17.13l-5.74-8.57,6.06-8a18.38,18.38,0,0,0,2.54-17.63l-3.93-10.34,5.12-2.87a18.38,18.38,0,0,0,9.31-17.78l-1.12-11.75,8.18-2.64a18.38,18.38,0,0,0,12.67-16l.75-9.5h6.44a18.38,18.38,0,0,0,17.59-13L184,99.13l12.19,1.25a18.38,18.38,0,0,0,17.27-8.25l4.11-6.3,8.21,3.79a18.38,18.38,0,0,0,20.12-3.14l5.85-5.36L261,88.21a18.38,18.38,0,0,0,18.23,2.32L287.76,87l6,7.67a18.38,18.38,0,0,0,15.32,7l11.25-.51,3.21,7.56a18.38,18.38,0,0,0,15.29,11.12l9.33.83.48,7.39A18.38,18.38,0,0,0,358.1,143l9.37,5.18-.71,11.41a18.38,18.38,0,0,0,7.43,15.93l7.14,5.26-3.79,10.66a18.38,18.38,0,0,0,2,16.27l5.57,8.45-6.46,10.31a18.38,18.38,0,0,0-2.11,14.77l2.66,9.38-9.63,7.93A18.38,18.38,0,0,0,362.85,272.68Z"
+     transform="translate(-113.88 -76.62)"
+     id="path201" />
+  <circle
+     class="cls-2"
+     cx="137.72"
+     cy="138.48"
+     r="117.79"
+     id="circle203" />
+  <path
+     class="cls-3"
+     d="M326.34,141.78A105.72,105.72,0,0,0,181.56,295.61,105.7,105.7,0,1,1,326.34,141.78Z"
+     transform="translate(-113.88 -76.62)"
+     id="path205" />
+  <path
+     class="cls-3"
+     d="m 180.73,231.12 c 0.57,1.71 6.47,20.7 10,30 3.53,9.3 7.59,16.9 12.87,17.74 5.28,0.84 10.64,-7.56 16.9,-7.78 8.76,-0.31 13.68,-1 18.13,-8.12 3.56,-5.67 9.9,1.76 25.87,-7.49 8.71,-5 26.56,-4.08 43.4,-11.91 20.26,-9.42 6.82,-12 6.83,-24 0,-3.84 3.66,-4.88 9.42,-7.17 3.82,-1.52 9.75,-4.8 8.63,-8.92 -1.24,-4.55 -0.79,-6.28 -5.2,-7.93 -8.95912,-3.35701 -15.41112,0.51436 -20.81894,2.56685 -7.90305,3.13369 -9.25397,-5.78637 -14.68734,-7.38637 -3.84252,-1.13153 -10.81538,-2.53029 -12.21968,-9.01195 C 278.1258,173.18465 270.1,170.58 261.8,170.42 c -4.33,-0.08 -8,1.37 -11,-5.82 -3.38,-8.07 -10.07,-19.35 -16.92,-12 -6.85,7.35 2,17.55 3.13,27 0.19,1.55 -0.08,3 -1.63,3.23 -3.79619,0.48553 -7.30604,2.27403 -9.93,5.06 -4.27,4.41 -8.18,-2.59 -15.09,3.8 -6.32,5.85 -13.27,-0.73 -25.52,-0.41 -20.65,0.56 -4.11,39.84 -4.11,39.84 z"
+     transform="translate(-113.88,-76.62)"
+     id="path207"
+     sodipodi:nodetypes="csscccccccccscccscccccc" />
+  <path
+     class="cls-4"
+     d="M200.74,254.41a27,27,0,0,0,1.31,3c2.16,4.33,1.11,2.86,3.11,6.36,1.22,2.13,4.06,6.21,2.11,6.86-1.68.56-4.06-1-4.75-3.08-.34-1-.59-2.08-.93-3.1-2.72-8.19-6.6-15.8-9.33-24-3-9-5.76-18.25-7.12-27.94-.46-3.57-3.28-10.18-.86-11,1.49-.49,2.14.53,2.48,1.55.74,2.23.09,2.45.5,3.66a1.31,1.31,0,0,0,1.7.78c1.68-.56,1.9-3.63,3.95-4.31,7.36-2.45,15.23,5.38,17.4,11.9,1.48,6-1.4,10.39-6.34,15.14a7.39,7.39,0,0,1-2.86,1.67c-2,.68-4.81.46-6.12.89s-1.61,1.36-1.15,2.76,1.21,2.7,1.67,4.1c.68,2,1.15,4.07,1.83,6.11a13.67,13.67,0,0,0,.71,1.83C198.94,249.94,200,252.18,200.74,254.41Zm-6.45-48.32c-6.52,2.17-4.88,13.31-3,19.08,1.3,3.91,4.19,5.44,8.09,4.14,5.59-1.86,9.23-8.65,7.37-14.24C205.11,211,199.22,204.45,194.29,206.09Z"
+     transform="translate(-113.88 -76.62)"
+     id="path209" />
+  <path
+     class="cls-4"
+     d="M216.34,197.41a.88.88,0,0,1,1.35.45c2.1,3.85,3.09,9.07,5.33,13.18,2.1,3.85,7.1,7,9.45,5.68,2.67-1.46,4.77-8.79,2.56-12.83-.64-1.17-1.64-2.24-2.5-3.8-1.32-2.41-2.15-6.11.13-7.35,1.37-.75,1.92-.2,2.31.52.07.13.08.29.15.43.25.46.59.78.84,1.23,1.1,2,1.14,4.88,1.54,6.86a21.85,21.85,0,0,0,2,6.08,14.16,14.16,0,0,0,4.19,4.74c.38.38,1,.73,1.24,1.18a1.24,1.24,0,0,1-.71,1.66c-.85.46-3.88-1.52-4.84-3.28-.21-.39-.3-.85-.55-1.31a.78.78,0,0,0-1.14-.23c-.65.36-.62,2.12-.83,2.82-.76,2-1.51,4.21-3.33,5.21-4,2.21-9.11-1.63-10.89-4.89-.43-.78-.79-1.6-1.25-2.45C219.43,207.58,215.43,197.91,216.34,197.41Z"
+     transform="translate(-113.88 -76.62)"
+     id="path211" />
+  <path
+     class="cls-4"
+     d="M251.1,184.25c.22.55.06,1.41,1.17,1,.62-.24.83-1.12,1.06-1.77a7.57,7.57,0,0,1,4.54-4.5c6.36-2.5,13.65,1.82,15.88,7.49,2.12,5.39,1,13.9-5.72,16.54a10.23,10.23,0,0,1-5.58.43,4,4,0,0,0-2-.18c-.9.35,0,2.33-1.08,2.74-1.94.76-3.25-.83-4.09-2.74-1.37-3.29-3.11-8.25-4.44-11.64s-2.43-7.19-3.84-10.79c-1.33-3.39-3-6.71-4.39-10.17-.6-1.52-1.13-3.07-1.7-4.52a17.75,17.75,0,0,0-2.25-4.31,1,1,0,0,1-.23-.39,1.46,1.46,0,0,1,1.06-1.77,1.54,1.54,0,0,1,2.14,1l.14.35a75.7,75.7,0,0,0,3.53,10.19c.35.9.8,1.84,1.15,2.74l-.07,0C247.73,177.34,249.77,180.86,251.1,184.25Zm8-3.06c-5.33,2.09-6.44,8.2-4.32,13.59a9.89,9.89,0,0,0,13,5.9c4.36-1.71,5.62-9.07,3.88-13.5C268.24,181.58,263.7,179.37,259.07,181.19Z"
+     transform="translate(-113.88 -76.62)"
+     id="path213" />
+  <path
+     class="cls-4"
+     d="M216.42,242.8c-.49-2.48,2.88-6.17,6.16-6.81,1.83-.36,4.94.47,5.28,2.22a1.91,1.91,0,0,1-1.12,2c-1.38.27-2.88-1.93-4.33-1.65s-3.39,2.41-3.13,3.72c.59,3,7.19,5.79,10.06,8.48a7,7,0,0,1,2.07,3.61,7.5,7.5,0,0,1-5.63,8.37c-5.76,1.13-9.07-3-11.63-6.81a2,2,0,0,1-.39-.83,1.4,1.4,0,0,1,1-1.71c.87-.17,1.43.7,1.86,1.38,1.5,3,4,6.41,8.28,5.57,2.7-.53,4.44-3.22,3.79-6.57C227.21,249.93,217.23,247,216.42,242.8Z"
+     transform="translate(-113.88 -76.62)"
+     id="path215" />
+  <path
+     class="cls-4"
+     d="M244.38,250.12c-6.18-5.9-6.33-14.67-2.63-18.54,2.46-2.58,9.1-4.36,13.13-.51,3.39,3.23,6.36,13.57,1.38,18.78a6.15,6.15,0,0,1-5.21,1.91,7.1,7.1,0,0,0-3.3.34c-.83.33-1,.34-1.85-.43-.27-.26-.59-.67-1.08-1.13Zm8.85-17.44a6.87,6.87,0,0,0-9.3.16c-2.62,2.74-1.09,12.22,1.38,14.58s7.16,2.94,9.68.3C258,244.55,257.58,236.83,253.23,232.67Z"
+     transform="translate(-113.88 -76.62)"
+     id="path217" />
+  <path
+     class="cls-4"
+     d="M269.24,237.75a63.21,63.21,0,0,0-2.83-6.39s-1-2.71-1.6-4.88c-.76-1.94-1.59-3.84-2.35-5.78-2.09-5.33-10.17-21.45-6.49-20.18,1.83.63,2.79.82,3.06,1.52a28.65,28.65,0,0,1,1,4.84c1.23,4.66,4.57,13.94,6.83,19.68.9,2.28,1.89,4.61,2.93,6.83,2,4.46,4.33,9.33,4.18,10.25C273.94,243.64,272.62,248.25,269.24,237.75Z"
+     transform="translate(-113.88 -76.62)"
+     id="path219" />
+  <path
+     class="cls-4"
+     d="M288.05,226.57c1-.37,1.51-1,1.29-2.58-.3-2.13-2.48-6.48-4.62-6.18-1.84.26-3.45,3.78-4.85,4-.59.08-1.23-.73-1.29-1.17-.26-1.84,4.38-4.66,5.92-4.88,5.22-.73,7.52,9.3,9.65,15.91.44,1.52,1,2.41,2.74,2.39.68.06,1.72,0,1.83.72A2.08,2.08,0,0,1,297,237c-1.25.17-2.61-1.51-3.64-1.37-2.06.29-3.5,3.94-6.3,4.33a4.31,4.31,0,0,1-4.94-3.66c0-.22,0-.45,0-.67C281.56,230.56,283.06,228.39,288.05,226.57ZM284.42,235c.21,1.47.62,2.84,2.54,2.57s5.26-4.26,5-6.32c-.33-2.36-2.1-2.71-3.91-2.76C285.44,228.81,284,231.64,284.42,235Z"
+     transform="translate(-113.88 -76.62)"
+     id="path221" />
+  <path
+     class="cls-4"
+     d="M306.07,208c2.38-.87,14.61-5.28,16.95-6.05.86-.23,1.94-.52,2.28.78.92,3.45-22.71,6-20.38,14.81,1.28,4.81,2.85,9.55,4,14.3.25.93.1,1.82-1,2.11-2.08.56-4.25-10.17-4.27-10.24C301.92,216.9,299.43,210.42,306.07,208Z"
+     transform="translate(-113.88 -76.62)"
+     id="path223" />
+  <ellipse
+     style="fill:#000000;fill-rule:evenodd;stroke-width:0.83809"
+     id="path429"
+     cx="172.17104"
+     cy="122.1034"
+     rx="4.5852861"
+     ry="4.9624691" />
+  <metadata
+     id="metadata3053">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:title>PubSolar logo</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/hosts/nachtigall/apps/nextcloud-skeleton/Readme.md b/overlays/pkgs/nextcloud-skeleton/default/Readme.md
similarity index 58%
rename from hosts/nachtigall/apps/nextcloud-skeleton/Readme.md
rename to overlays/pkgs/nextcloud-skeleton/default/Readme.md
index 233693f6..15eb5fef 100644
--- a/hosts/nachtigall/apps/nextcloud-skeleton/Readme.md
+++ b/overlays/pkgs/nextcloud-skeleton/default/Readme.md
@@ -2,6 +2,6 @@
 
 By default, the cloud is limited to 10MB of storage. If you want more, just send a short request to [crew@pub.solar](mailto:crew@pub.solar).
 
-To download a desktop client, go to https://nextcloud.com/download.
+To download a Nextlcoud desktop client, go to https://nextcloud.com/download. You can find instructions on how to set it up on our [Nextcloud wiki page](https://wiki.pub.solar/index.php/Nextcloud).
 
 You can edit this file by clicking here, and put any contents you want as notes for this directory :)
diff --git a/secrets/acme-namecheap-env.age b/secrets/acme-namecheap-env.age
new file mode 100644
index 00000000..684c30fe
--- /dev/null
+++ b/secrets/acme-namecheap-env.age
@@ -0,0 +1,48 @@
+age-encryption.org/v1
+-> ssh-ed25519 NID4eA WtfgDmnK5l9s9DMhWgmk+tel+/uqPx8SHBd0qfWY3jk
+ZS3Qu4v3pnA+lYzJ3kad7T3LhcY7oE8fPsGQ1uQH1AA
+-> ssh-ed25519 9RQHxg SpHG3ijNizTi1YXvZCJS79Uwt4oGkYzqIme+eqQi9AQ
+GqVhyfaTF6tLwuo0vIby0vBv3JufHz59IdNX9ifWtSA
+-> ssh-ed25519 eP5MMw 9uU7tlyOzOxlsW/bfUmzjgicU3i2J5uCGWEVIljnHiM
+tDJdTB1rBJTXVaGFOOmtG5n2Ae0XOCsi41S0EagRmeM
+-> ssh-ed25519 uYcDNw ge+lEVE8+pS/S+eO+6sPqo/czym30CJbQnhTp11NsW4
+jxL7Xhn/7JRylJ/JbeGkmhMMeJ8G2KPEKVVq1icQXKU
+-> ssh-rsa f5THog
+Ybod3f7gvCiBUcNyLV6AXoBchtRGspQah9JwygSGCtBKmWPOUSw3/DVva9nPVwHB
+q4t05bEHINMZIoWy4l3VQ1jw+GTxW+6OeWDHrxHOG2hlu1/OT0tZnsQIjWwT/6Sg
+fzy6X04yD2ADkwHH6VJYjC2Lxa7kEOeCeKOACyyab7rlXk+HauytUDlcF3Nl3nOc
+JQZzfwIORU0XWVy+gDocwVqDaRJXZxhMW8oDjlU8BKgf/DpvExLfuZ9AHHJBU0Y9
+HefbTbGO1s5J0T+HEkuIDce9iPQEe8ufaSVO6tKyHpgguIAiLIkjqrdLNRmXv/y8
+9W653Xqar7fimd/sykb4K/PpdwvQcB9Ogy23t6s3Qxz5yPtC2m8IC3lgR+N+/nJO
+n29QuXFBNUZu/QBXnWMS2QF09MGE2aav/CiwFuNiTf5D4UGGN3Y7XhX/KVOFJTZX
+r1GLtch6rvD9RtfyKxAdbtCqbBEQJmoiut9ia5EzG4TvdPAE4XK3QNTn2BSmfjvI
+3aXiXOFSbdJqkxyI6ZU2mUMMor3OWrXxWizDDYef6iHZxGlWFqA/kVXyZgdwTK9n
+8Re6SYR8roH7T35eILzP4sskElN32UO/A+JyGfP1lOclGTlOrtp4HYTfY0NhhRJT
+L7YIB0pNbaRxMBsxsxwU47j3qMkaO1uzP+DgpUacWJY
+-> ssh-rsa kFDS0A
+GJjiIApapBS6F8pmh6lblCHG3FlVWL+WKN1Gi2u/6Pa1YbkiBCgYFTQBwm5GsBMR
+4tQwRJcQQDGgGddIH4/QcMAl1fTYLm3N1w8rueywgAbOwaWktKnJFYTj7lS6PSNr
+bZyqyiGvgi0oYYSVjRnm7MmCrycuKmhcGHv1ijj5J8yOxe6qFsomsn9QZm1DmR/m
+EZmc5DIYXjhuauzGgqtPVmjHi6hXTN8NX7Fg81aegko79yA12hmyHmaBj4P96Kqv
+RyWZ9Moc3ccyxq74jNzp0eFuPNhUJuNBqrKozCc2Lo3KQAmoqI27THkF/HA8ECGP
+BJDK7JdHBXyHhf/Fc5O5xOxHieIU8tHR0LLJn7VEvQyqTlKmWkZ5J53AqE8UDmm9
+0gY6zFh7h3SjyBwqktzGJ9zXn3bp4fpg0M1+SaYp9Qf6hkJ9k79Zth4s4ggxgvOl
+veib2sg3PCmL1OCMPMtyW3JkKsq0J+PtJdlAC9cmVvfvAMHKy2+aADsLt0H8Cpt2
+cNOxbnU29eLWgG9uzcCXfqqNtmSia6LUMu71GahAuteZUV8RnDOZdCNW4U2Ohnq/
+9znMqERVo0d3LgjaB0P3HXCCqhVFYTTDWg31R6N2RzSh7mb02CFgt7N+vHleQqAo
+G/6Pb+kKYSEbU884z95+o56eQrvPunCN9Vu1CjEBfG4
+-> piv-p256 vRzPNw A2dcPImS0ih5CjePQP5oPrPfwns6zAMP0J72P7fyzD/A
+p46umKyZjbc1MjOQGnJIRu6V99O+/PmVXQvryX/9XW4
+-> piv-p256 zqq/iw A5nBHU2O+bxsFqplf2GV6pK5wQ+hJ9l7tyFIe57QVKzw
+Ik6aUY3t4geZ3yiWPqBGlBem9xNU83x7t3UA7pYB55I
+-> ssh-ed25519 YFSOsg OhynWXlurzqU3ohq1ecH018Ja4wyWazDLv6isajeBUE
+Xnjo8yS9IkMwCGNeLi6BABYxjXDLbpuTrVfwAxjDWdQ
+-> ssh-ed25519 iHV63A 5CVIOtSwima5gIvwoAYExcy1tfOo8942RQ+SsflPbAM
+4HV21GcuyddIjonOZZFgjgpR5smjce7OlMN3DCy0/sU
+-> ssh-ed25519 BVsyTA mkLu2Vpr16bAZWimh6sViq5HlB1+lNOc2WPCxzgfqAg
+cIDgWit139jipd7XmZcT8mTRDKK8rJV9xIxIaPVL9pM
+-> ssh-ed25519 +3V2lQ eqfktAyV2Pia7T7XEfcYiHN9Jd4zivMzJk3in4XOTx0
+gZzO+MTyBOJR1EgGn4Mhh4rnIyr3N9gmlFty83ou+GU
+--- yJrzTzStOkRCNRu3Y+knfqTqHrwW0S0Bsko7oG/s86o
+�,Bgm����f�T���`1�&1�%7Q�(����:?��
+������j���O_rqw��i�O��D��)@0�ZK'��+apU�<�`����ct�.� �����X�N�+��h��=�'�V�n^HH�v�5aa�nK��D�י
\ No newline at end of file
diff --git a/secrets/alertmanager-envfile.age b/secrets/alertmanager-envfile.age
new file mode 100644
index 00000000..a2556196
Binary files /dev/null and b/secrets/alertmanager-envfile.age differ
diff --git a/secrets/blue-shell-wg-private-key.age b/secrets/blue-shell-wg-private-key.age
new file mode 100644
index 00000000..cd2c53cb
--- /dev/null
+++ b/secrets/blue-shell-wg-private-key.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 eP5MMw 3H1XEr/Vt2TOQUvGu3K54CxbigkVpaC6hofMOfFR60U
+hqFTOoMhyhb/Fsywzu4nYXmEACOunenO/4NwPaVdrZs
+-> ssh-ed25519 uYcDNw raghSMdCaiQrfGviMlc9Pwh8cx33IWh+mnsxL8jgTQM
+aOMrh/746UulH7hkOV6XRiwEszgJtrI33mmzY5S2Ipg
+-> ssh-rsa f5THog
+Hm/2fpGDwqKG9K6zLYXuSDwOppDtDfw665ppaVzRvnNppizkilCohBzCrwXTMyeH
+KKZKqaEt+n35wrurfMfqQf1AkamEimjlXCMmr9IwrBHbJeIJuHn6vGSOssQ0Sq4R
+dr002QrKsGDzlL8dCLmaKU6VPTXcSbCOgDnBW/AyU7bvN51jtgm+jOIey7jH9Bm4
+0nU0UNcPiShgSbXLPp0V6O/1zQBOVeFGyGenblAKlqLILPvc04f4703alqSbKwXF
+q6GoS0Dipzr4N8X4Thzgc8H/YQ6cBVGQTebVGHqFEngLQ2C0yZWlDfJsKnKOGUce
+xSxSskfzEv2s9VHDrXeiTAzSYaLoZI0JEDHOSICmZT2wqT1voFokIQV8twORGpOo
+RAlNX0BULPEg5Mi2k3V4ZBcG5EwUjEcHAg+0cQ82D0f4OJEqMVIa3dse/lBbrFzC
+/Gkr8+LPWVv7f+mRr3sdKtZ1nBwz1uTP5qIA9m92UeLVdVjmp20hixmlgftAbTBm
+MtIH2xqkitpb6bhImGIbnxpg7U8IqQZNfavvOM9yqj0uud/Nh8ruUuwxci4RS7yP
+YlIcompHudeirCLPvYx1T6nYRB2GB1tpTcyQN60pb6YC7lH9w/tLhZf8GFcMdIY8
+eLx7FoWfNj2dIp8EpBrRUEaQlea6Eb1r2DYTjmNunnI
+-> ssh-rsa kFDS0A
+SPaIIABa0Wja26CIyeUvrlt+LWJY+Iw2+OouRZkMfi5YxDflb6SATesWh3zMD5+A
+SOiA/oUiRfGRVMmqiEznd2BLyUO7FQDv8tIT38R3m8Nj2Lb/kWtuhPKqrk0PPvr+
+kYR3iyM4klqccCzwOYwWfpO4ZkFACBApTOFYbU4WX50WDRQRco7M8funj10BAIsL
+H7hOKtigx2RJaJDcU3MPHV4beECpKbeH9scICEDmi098UP3850g1lN5AR7NjWvLi
+zr3Z8Up4UjEwH2mvuNnAbvA+0HOu5geIae+VUqy3EN7XFC5HnMHB6eK12Q1VAmF5
+MbgkppMeoqLnxIdLT9xxRNhD50B3QR8MNHgaNWuBqfl86XPfXjxYP5kRaCAraego
+nbE1gItlgIPESpf0ocfIEyXb0tSup8c+99ezgxBMrzNP6UtVGRhZvwLTpBZmrLoc
+5P/hTr0WQE7d/6lmY9VyDsXasPU758tUhM/cJxmmUyZcCOhjAiJdWSYHe7AUjSQy
+rUSKUSYwqM/epFNqdnanj4pmmRkSk/0AiEKikvb5DvWpHrnsL/EuQqtT382IGv6P
+VA6ORv3BmL8IjNnTppZsG8k91WWHLEqxoDKUHg6WHfJ5XqnEM4maFsRZs53QLqLB
+vjAxAeJHjFg13wkfJmo9mZNbw/0WXS/K+xmeOTYuH/8
+-> piv-p256 vRzPNw AwPYD0NiFDZ3/0L0+BEUS0hm7RddL3sPXUshz7XtIQVi
+7rzoQuAQQHxkuYFx5TrLEXZbGsERg78mAXcgQySwHGw
+-> piv-p256 zqq/iw A0Ec624/7FOTPVAbZDjhsBy0i5L1Tw9LwYfH/7DeKHi9
+djfKQINL2LVAAueovp/V1IGyhuy5LGQtOws5Dtih9sw
+-> ssh-ed25519 YFSOsg 6EeEfNtlQ7/a5Rc5iShfSa2ZjIoN6QcLDI0hJgpF8AY
+Tcp4iqFjBTTzSUAZrxRWe8QkvuEoPWVagNL4EiZLMIA
+-> ssh-ed25519 iHV63A P8IDXAspyflmLqtPOqPWE+J9s9e3OccKc5+8s/Wi9H8
+iRZba5723Ux5oo8YA2TDyiaWyGzHlAcvEiD7I99vq4o
+-> ssh-ed25519 BVsyTA LB7gg2/eozH+f9BNC4Q1m6Pl7b6znkO5rPVgvKSjen4
+AjNzM/44dMy7JyUcAT7c4pAFTtOuapiGtiqLdBPGrKA
+-> ssh-ed25519 +3V2lQ NHbovTrC4cTSsqb3AfmVOJ/pL0QQbK9GpMUpQMAW7w8
+iwAoDSQnucAzQPOgZZtl2bnJQ1mU19aoruItkQqJuZ8
+--- itqKtiBSCvkVJ5boq7PeY3uRMemElImzWvSeTwbz3y4
+�ZP38��0��e�8W�j���[��#;�Hj���w�Yœp���6W`�h���s��vbȷ��Wu�ԜxZ5f5� 
\ No newline at end of file
diff --git a/secrets/coturn-static-auth-secret.age b/secrets/coturn-static-auth-secret.age
index b909d6d6..a4f639a9 100644
--- a/secrets/coturn-static-auth-secret.age
+++ b/secrets/coturn-static-auth-secret.age
@@ -1,28 +1,43 @@
 age-encryption.org/v1
--> ssh-ed25519 iDKjwg FkQYu4K7yxWuKQChw28kOJrZqXDelVmzExig/cEmxjI
-apgJOiOv/gLcSRTcAkhzDZyLdiKbnsipnNt6okrZ6os
--> ssh-ed25519 uYcDNw wfyuSGgrFXRAcNSZoBTCz8kJOMeocD1BFwQ1hhO6dD0
-J5hhkK/S+RXjDp/kFGOXP1dDxTyKQx5MqhohgKTP8PQ
+-> ssh-ed25519 iDKjwg vLO2012STCeqJACpBNg5uKyWx/u0Yfvwxek3S+0Q1C4
+6vPjunf0CQeWTwznZXPc5iVL/eiF7SrPqGeuvgcfizM
+-> ssh-ed25519 uYcDNw QwGWHxl6dTO1HEfw7pEtdvb2ne0RiNMb8SkWRIrRJQg
+ffdyTEltr6wlrnA9isU17orFvSRmicPvX+w2t0QBJIY
+-> ssh-rsa f5THog
+XjKRMzLPZlrTQEDJzgCwBbjZwIy6fMYGLuBR8TS15SAIbttLoikF/AV5zqJDaE9j
+RaRJIIQV6LYCm1fHOsoua0XGxicvJkdithrDC4zsEEJ5n2luNj+sQd7h9ruOdkO5
+l+Og+MphPM9naul+MJ/DluzS863DewkCNENEWe5H5MkHujOoqEsRsGdrRPXUbAPW
+oNIr6h7FHCTFTkxfj1aAqDHdK8R4Yqo2K0vnHHfNS3PeN+CQJOrGNzokYybMRxqK
+RXoJD0QKAUCV8cdXGr0XuS/ljv0lFODKhupy5ObYU71052nxo8j7KTq2NpZXqjul
+PWyetcPtH5nLCs2L31XoBk7cEE8g/eSjPky3gSMdjGjdB7qskmuPcAHlHEwQzecG
+D6J1LjrPa8OMVD4AdR0KAXSnSvzt/RhyymiZWtBeKg52rm4KK3PVbJqq05m+PEYA
+a8wFT6fJOqmNr4gj4peIUHca0gYWhfzhLpXsj4/MKTPxzdUem/wbbMJrM7oQpwma
+svN0vvqCUc2wfw2Apr3WwoAnNTIohZOngNkKNWNweXtPOee2qgZO3ko2wpFa+Yh+
+IMonHHVhtdchTidx4RttgDIaW/+i//XGfqPdmanO5wUmm+SwgqkkQkRHzmtbmgsq
+KlrAmjL5biH9f9sBItYMdKafgyQppMAQ3hXt5wgAgj8
 -> ssh-rsa kFDS0A
-arAz7wP/PQBggo5IOFTZrMp/a1eCxCzx5t0QTs07Mfp1mk1h5Xy39VwRB4PIN1Kw
-ASRLnBsUmPznZTWJJ+coAjZiISYx0kW0J5BpKmC6g5orxQJHwEieI/c9JZ1KTjUJ
-G+Rl0BWfJiOk23SiQaCEs5D9OPQiKpQvE2W6ZUTaRVzRelGlmzSHkx5hAz3yX936
-MXdijUFS15sNKDTaoGrql67YRckYHn8ErrvUaSUEdelNOc9ILhCTT+NSM5SG+oh5
-B1GVdHf2hrgmTqhKqxwB/DgXmwsOzX5ffa7kV+KqgYypdjVHlLlkWy6RLVQLEYBM
-ldLIHY4SjpuShqcsuoakZ8jAx/J5aU/SnnRBxIgWcdwwMPbn2dB89wkiK9kVgpVH
-Izj4oO5EJiZr6Fx+iCFnnsuzBrzswRR2zZOJsYo1XY2uP7JEq8F5iClAgN3C7C9V
-3gU4Cf61sr4GftKCBnRUGrtohfL5KeXBX7sTpvF9+cmjQWTBB+fF5Q2I6UmOH08Z
-8OVAkPQsK+zfNaOD5+J8/JoCIXNqZKBq+ShgQoMEPlUFwe3mgy5ji38s8CY09ehY
-DrsWhQw1M9ka8z0hlfP95jQjNlztUn4K/TB7OXUXAKj9/n74b7lmLJ8OMCn4miZ2
-EOV9jVyXrCPQF6RujaYOh52OFz3zIRKEINwWwPNfNJY
--> ssh-ed25519 YFSOsg 5H/taWUdjZcoYSFndLcYZPX8JUtK6BJs2ou1oJnT6k0
-dTOUWXMuaERYbfHo6AaiM4NfPWKxTk95YFpRkxq06jQ
--> ssh-ed25519 iHV63A KFTTfUVH8bb+ebLc3WefjyFt2YGdfD8cQiK+VURRplI
-d75sa9BchGJl1NdVHCZ5s4f/RqV5TE7jBtC02OnOt2E
--> ssh-ed25519 BVsyTA 8BbKlmlVJvPSoZuVazuOyR2YXncwTHAP80hDYpshjz4
-I+u3zwtSecaLeOOR1WJ5+fwWTgn31PvW38kkPgGQ4sM
--> X}64s-grease V7
-U9Gkb6Sn+PV3lgb6Kzl0ATgibtLzSm//Z60gct7j8F2wVosjicXaWpv+LVfdBo86
-JlXZuA
---- zjT2F/dHJX8rxVXgbjZMsToMSPUXPLwbeAhGiNawKlc
-��݈ɩ�֑�ˎ{����H���k�0Z�Y�*����b;��X#��-�Ÿ��ͮ�����&n�/mxl
9�|�c	K$���&���*�$z��1�z�
\ No newline at end of file
+XAY8GSsx8B5q039L14C/t4cGK2sAm9eqO33r//YgpI5nkvw+pZrbJegdCItfHXHd
+9BwBGOowTe5Qmj6RVfz4rwsj57HJbt6ivoIrU3vH+GLsNs4JIg5lwz1/WCsotw6W
+8jQXiiZbA4nvzQzyZjJVKavTCfvbRXdzc+CUZiWgQDXsSFejp3ODeOvUds8YKWiz
+jYILyzUzyAf05HDC2SIUhfA/UoXokfpo6uZuryWXjRBgaRENa9csDnktc8V+61W7
+gUnu6yt/rN6oiBesnUZQK4sPd5YE6EcOT2gtLp1qKxtRuF9TEX25oLHi52kPBu8j
+TNGbCU2ImGW3Z6TkAj+/XQzwEIrbLgb7APMkI3DtWyIIxZn5QJdDOOCseKMKt2Lu
+VH1RF9C26mqcx7+WGCJKylARX8sbT1/ZsCWSUnmenYuGNQQppMwcQGSICs0YmFkH
+XnV19+pt93i5rVFs9IUxFCqFKKjElCiPgIHe0QlGuxifeiMXYuNi8g4ObN5X6GEL
+MPm0+sr19dheOZicyxqJ/jSlEOP8bHgN/VDHjKtsMWQD9r3NfLH7btNjA8HTITDI
+YvLLVCP6OR3ZlMz2HUXDpbaPYSSZvrEtwkqCIe3ij6066Y5cTsYHWEwOvXaKYh9P
+OJtPgLQDV9VfU9hK60E+C5qGQAvHhBgPUfXS8JMJkyw
+-> piv-p256 vRzPNw A2vUnNzWtQNNOU//b3muMZeM1qdO3GyREn73VgdxMX4Q
+6AzSUdoPB4zMbFsf0fr6sxbCsg+5/qmBtkCo3ry88Gc
+-> piv-p256 zqq/iw AwVuYkScYFB1OzvBz9255ebDwPO4o8szD79gPnzgK/t9
+UCm3jzlAPdfGvxO2VrE2DBvcGlaJpMTINJl2qcq+4oA
+-> ssh-ed25519 YFSOsg wUzSRyoZOde45Uv+KaN/ARAxIRt1bPAqN30P6nM9b1o
+pmufkyRBD4BoL4a+dbS321KSdjPRrB09MssNU6N0dtE
+-> ssh-ed25519 iHV63A qyqt+LHR4YGE+P2D2mq7qOS959vLZ9K2yalLvGg3riw
+1oDuGVg7Jn+8MIlsHb8KCDImManVGnlIMoqFt9w9Wjg
+-> ssh-ed25519 BVsyTA skF/Np1FrFUSWJgCw5PN9uSy+bMezPHV7lH4jm67TCc
+QrtBW86S8cB6GLsw6LVGK5jhFQS56MvATcPspGJwmAE
+-> ssh-ed25519 +3V2lQ DPCBFzgin6QTJx0QZ0+52qW+6xXmGA4M+hFEIFAvpC4
+QuuoukU5PC4BW2ieS52rkGcPRPuvrROE37gZpd7cudw
+--- fVPm/8JI93qQmr6bEdb8JEtRpKtsBHnK88A1tptYLIs
+|9�:\����H�(���a-[�f�-Bp�u[�,�bz��'jA��yp`4���lƕ|�Nj�3�
;����)���GȾb���&�W�F/����y��
\ No newline at end of file
diff --git a/secrets/delite-wg-private-key.age b/secrets/delite-wg-private-key.age
new file mode 100644
index 00000000..b8edde1e
--- /dev/null
+++ b/secrets/delite-wg-private-key.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 9RQHxg dVdaiC3H/M+tA/xIW3NdwQax68lkydLDLm6OxTx1lSc
+HRLezYbdAPHNbQm/2WXT16wVX+ZC7GKlVp48aIECsdw
+-> ssh-ed25519 uYcDNw SqHkg361mGpjrcynYld45CU/jfnPp55bt75apCWlADE
+Z55QoOPVt2u1d5Q/96PHfA0MFAaO4y3CWuJNBnVy2IU
+-> ssh-rsa f5THog
+yKfwc4z4mIVfDJW5aEk7O9ddRL0YKOZFV+xKE6OyMGv6luJ+yM3QcPxu9yppCfMA
+AIreVH2/4Tn+WhYv0dQuVeTR7SLqfn+TynkfK6ZZ8NbjSZXnakPqNLtOWi6C8VIH
+MAfTTg1NGOG7E3TGmMqFrQnxYdpIvtfeGaBfiMhGLoWnCzJOzVkZSf1Qx+ibor1T
+ZtJGsAVoAqGlFoWNDNrlemx9/5qxARe/GSSUyKtEb8VtbvN2hgJeg3YAKBANYkUS
+C2Py72R662WBKPSd8vZRaQEJzP78b+LjBPmF98E8EZcHD/L6I6QRirpD8E89nN8b
+/vp/Ze2q5R+9ot2TIO4Q9TJKLs8uMYUNUImrWQM9eBG444dmuTNDDfBFeI0Xwwug
+FrHxS5pE8QzRdla/fIt/Py02F/734pb1LRCBPaLr5F7gFTBtIXe1TCvwfigiYrZ8
+3zD4mpasIz1a7MlOIBIUuNAvAvJIwemenzxoCPTJUIPR9Ja06JUJe0qe/qOOaUAE
+iio/a7XLYAUnTqHQ8efufS7RF8HB61Q5/CEtjE4NnpaiZkG+KQ57xjTwrfKSALxK
+FN5ydIMY2aNg6Hh+n0MlCfpV2N8XYqOF4YWWRKY39516i8QCvvL21k+lt3P0Lpad
+E5fn9FWoLqJw+evJsF/PyTrLT68tQbcY90mIGC6n/Ww
+-> ssh-rsa kFDS0A
+dTkAwE1+eD5KvpKvI0Wja9vV3wgKogv9ADKyf/u6meetXQ0isUnqxhqBbQZKhVqU
+StNE4dSwg9gBwsPmNXJ2Avc9LMIBuhDomPOp8bqdO/r0IyDvJ+TngnJsroK7dfL5
+foIDtakdAOVZM12ytm5hZlUNfXppAJUF1T9w5LIBWAMQQYJs39u+RrLfHoIvXTor
+OvTikrdYfGiWdX3XIGQAfoPct3ZEKmD76ypH8ESw8kKF7ZfRQNDDP3LMbakoFs8K
+Jrh5S9e3b5hdiDsv0DFtMISm8l6ec2mhhkVhSPgJ0mZYimMUg2QW1b61aTbE+LEI
+K9O27ci1UKhxvLnxA3UWrYcm9SX3dvFgH8c+hJDdydHRGtMA3OU6Ut2HuGKaLfys
+P7F7gffBTEeW2na2I00k3/oq9CCT4AP1d/CKlGd8ZtRvv5Axv6ThehCFZ/FLYGCg
+kLBTHCX9qfvltdkKHIZwgxQ7JSGvNf/4bBzUz47o4gBhtnADaPondeLkqRS8sMwF
+gq4UtG13Y2NfVYLtydrZCpUSMXekibZ8Rj2ER1uy1PD32clevgmgbTSyniSbJDa9
+NFAeQS8KiyfvnxtLNNoMflR5yL2O4bX8Eo5ooaxILxga4M7ckcuKz2SMjDjpSBbK
+ndwen9EsZuQwK9Av09h3gZeRy/t1ne6MtZrsTY5W7+Q
+-> piv-p256 vRzPNw AyZQpsc9MqXbooqG+eK5gQQbfe4ka6pG7uixb8ONVGQz
+FWuy/qAQidT6C8YMb3674epUzZw0Rb2NMCK5t9wdnT0
+-> piv-p256 zqq/iw ApTqG55jHkxwd3cT2Hvw84V2DcoHo1M+q9eP2eLxSE2t
++27Dzy6pzGpOwTqUG17QaDC93O3PSJIfy/d4eBnuLw0
+-> ssh-ed25519 YFSOsg mRmdt4AzDKbzKvMPOEHg+jQSRs2RF7f7ev/jzP7SuFE
+VmNGaudQF6R8xDWBz6bFfmk2J8twCUEzcXj2AG5teKI
+-> ssh-ed25519 iHV63A pXrKk8kpTBDxhiio5ZY7krRJIDkxYJZOMqCaW9Q7OGQ
+9/xgfjzsd2JT6FQ2YWELl9jqph3+HTF8jChvbiHceJo
+-> ssh-ed25519 BVsyTA z8nXuz2JOAn8t8OW+AzFRAXb5ulAuderatBFDrb6klY
+Z+7S5aGCCV7f9WwHWr5LrsKW7rnpidImwoiP2dXcxew
+-> ssh-ed25519 +3V2lQ p99nuu5l75p1y3Ea1yRdFBQSxvYRVRJzX1undANyFVk
+QHzKD4WvtnRI0wgiaIYKWwXrG5Qg0vQ+V6eTJUk+A8k
+--- od3JqYVYOFEDzaNHY5oDbfOjhUBsiQFd9pNGSkAw8Dk
+�FJ�Mm�|���>�|�����
��0��:+���U^���Yؼ��/��wʠX+8gtRNP�^\�N}��£
\ No newline at end of file
diff --git a/secrets/drone-db-secrets.age b/secrets/drone-db-secrets.age
deleted file mode 100644
index 9496198c..00000000
--- a/secrets/drone-db-secrets.age
+++ /dev/null
@@ -1,28 +0,0 @@
-age-encryption.org/v1
--> ssh-ed25519 Y0ZZaw FLHjNYq0CIlbPUKpJgrw4Dka33LIBW9p2E93v8RGdl8
-aw0LoWNfjAx1nXK9+SwFMLRxpd/KZL5Y0XJQqIZG0+E
--> ssh-ed25519 uYcDNw dbVXX0Nj5fq5nr/7yaC3ZQnPIk5MQAQpT5RJmz2IMCM
-t9ci+WVCroHprSfoud7LKuaTjk5NeiS/Mp2LqhcOrdI
--> ssh-rsa kFDS0A
-RZaFU9rClM9C7SUyYx4e1dZmntzPxoB60gJU2XUXFwkAp54dXL8fxs2cHcRxUQMo
-HpzCCMiPo2QowUe9O4VQFlOPraub+aTc/nkMmy/spKM50DeVHlK11aoGkJ2j8uj9
-FPAzdI47DFpLWN6ncndtKHvYeV2ip2qv9oOgbl84aQ5DqeACb5BHtGS0edWa8YwM
-8B6GX9ZpDGB6oW17Ko4IIjeBRnwmY+66mzl6cqhYsGWK2vOYBDLmx4JmGH2LqHL7
-+8kQBaq+hNkRlpgLZC7RIrnaW41yMmRZbyr6hPIXaLnlYp6+7+A8krnZKTJXPgBf
-Cpv4SSd+igSSjUGUSrnOM2LqOAOcqBAmnIDAyIsVMPnjOkCFxyEj1ynfiSwM1qb0
-QqTi0TZRHZsfpiGcvHVoBCWBFQ8d391MFQAiija0iW6QR/eRiGC4mcSA/6vP6X9G
-p7BNJoP+mt0pYpVXCA85Rv5K+0JKR2VqlluHl4V2rnwqCGGelG9oYz2D1pQz7Obs
-vVgjJaWxzzLGrCCDwk6LjuXv5UMobwlTw7YEGad7AnKPjtrhLuWm1Xs8STZ5oMJp
-BhYLDuTUtLFvYciITEEWK/46IBI4m8iJmKpHOMXjWhSuBGKj9q9ifwxeLOmkZgt/
-AojO4dtmmfzVNLGIIoUdFYjbp/Kr92p78y8jBIIkcMs
--> ssh-ed25519 YFSOsg TvpVdCtlBkpCBOPgiy8wKZo/0JxzQFDFRh16SXsdm1Q
-SSHyUUNu2S1Sq7c89DZAlx43zoab32mUenqgitqEfXw
--> ssh-ed25519 iHV63A YjDcxJ0Jt1Ifc22kDk5qiPNv333ZVdHizPdc3e0QgGQ
-nqXiCnVH9x7xAlEhIlqD2ThvglFLaHyd5yMzun7m7Xk
--> ssh-ed25519 BVsyTA eZZW8nsBoPJEDgH0tJNKMHyQgyOD5gpuf/gAGfaycj8
-Ss82nrDGaf/ZB4hq9bVYwmTdh7Z1zl10w8bpr5cN3Dg
--> %o-grease g0_~ |]P[H&% }+
-XEDXb/UfDFfY/NGfgrttIHoE0Q/0S2xvBwpy0p1SJb4h1/xOb/E/3uIWT7OlQQgO
-8Q
---- 0DdGRYR7j5NAQX63wD6e4LxW3xHTTiBekFtxYFCcK10
-�U�2J�3fKx����s�x��;1.S��^d�����3�+�r�{Y�1��������&�'�ا�ۮ)��_4�/�u�\T����eF��t�R���s����s��%\�s|���
\ No newline at end of file
diff --git a/secrets/drone-secrets.age b/secrets/drone-secrets.age
deleted file mode 100644
index a612b143..00000000
Binary files a/secrets/drone-secrets.age and /dev/null differ
diff --git a/secrets/flora6-wg-private-key.age b/secrets/flora6-wg-private-key.age
deleted file mode 100644
index a9d21262..00000000
--- a/secrets/flora6-wg-private-key.age
+++ /dev/null
@@ -1,42 +0,0 @@
-age-encryption.org/v1
--> ssh-ed25519 Y0ZZaw FvsdIE/inJoLVSosWXATnFbAAVjVuf7jlEC3nSUF6Ug
-gX84OKgWdfkGBN+NFy11BxIb4WX1z9UkPA4u2Q1uV+g
--> ssh-ed25519 uYcDNw z5Veza0uVwqCqGCGYzGmXPcyaV9HztEN39cWFbSG7yg
-UWZQcDP1vMsYoWwMQlr4YmzWYw2EKm/s5zJVHNf2M0U
--> ssh-rsa f5THog
-v1kqiU+cx65mvTNeuAhK65eBEk1vmkABRYgcmFIrdr4eY3pru+FaQTfMhTI9HjcO
-OTU0YPxxSadbUCaN6Z3QnTv5qowwOQlEsWK+RMsOZgnyRQHa2SIrhfHz7v+n8BTF
-8BYB4UBJpD3aLqM7VED6dYls178HUbiq34ohrG2vY5PHE72xTU60amv9NcJhSJPR
-twZPiSp3I14MlJU4bboS1YBaEmgxvbXru0DwuoQLw3OUrH7xOggVoSJxm8lVyjR2
-oFYS5wdnrhAIEsJ0lTsO5fvq9Dmie7qoL60rbBbue9lPk1nD1NlUe3akd4IIo36R
-kDbthUYluVSJON3o/wenSvJDOw3N3t8bu2+/XfWAd2NL9SPBijMQJtqjK8EAtmz9
-OjBMjJGQzVdBxRP9U3CWYIwaqYQfWhXXY4AXTwIMsfmeV8ZHZsId3Y156p0NaKg6
-NGb7eX/AWmcdNTp8ZCqlb4QexICrVd7XDkNbPHkYPUOdUhaMyS+T7YU8Qs3YWroP
-Bw63QMWbvo1l4HO/3HeIKlzIXTjLEi6PjTiWb7vM4GuoCwjdDg5djMEj4nsvDyea
-B9EBTEcoP2oj47wgsX0nfV5bKAQ4y8AN4ZNWb00vjN9ybBbLK3q//1DrEWmddieF
-t6FyZXvZH0Gf6y5OO56yRp/vmxvKFcvxqUA3P8bPAnw
--> ssh-rsa kFDS0A
-c+0wRUbjzdJiBhdKAVlE8yxt1O3t4oQ438F5HjMPohEXSFLiNFi4Y0JQsw6qn3GP
-hySsyIoj9G+cI9FDPjTFPmE7O1SHrd2LqBZGukyswDXX8CpwmZ7vfqfK2lCgKfos
-SSPiGaYk+HlQF2QfX/xdgQ2PbFXHnDy8LZ9AfZP04PrnK9wqdiEXwmkWZ/Lu1P+V
-Wb/28BYxcfkseAprFr/KSJLoNuD9UphRhQwRklmjADnf0lep3vHccxz1Oo5flu5M
-AD47r+0bLGM+w3epCF1GyR4L2lEBaD8pkVOt3/zIdjn8nFZVNJwjshToazvnVEd3
-Vd9Uas58AyxcT7Dk/QaVO7c5KJDdfSuxnT1zElkM2ZQM4lEueTJYDBJGyfubb30y
-Z7re/MsLOh0jNJbb0r1KOkzwpcdm9iyvi26eaGsX7Q1Gb2pzOYFxD1vSUUC6A6Hp
-W5X6fKsiBPreYLf5MV6p9r2YJPdX4SJiq4XztQi1PL+ndq1h8wskxk3Pyvk9fhle
-iC5owZ8/FikfC/1oEa2KayeLyYB001BUuktevzfH2GmbqLkR9wBGw5vUJzOO4vOW
-o8SVCSUxSrG8S+HQksOSXFWywkdBDhqc8eyRUtb+6iqqMA2Q4GDqktSCB1KeBYD6
-OalH6bo4H1ddV8LPMOKcFtjmTPuum43C7bNge2rxhgg
--> piv-p256 vRzPNw A/utfOjPG1zs1Lf2FOWDHhJIJW1PIHmKFqFvBZZycHPn
-EfGFh9R0PDgskQg00z6thQ1YozT5ZiBhzNN9iTXWDe4
--> piv-p256 zqq/iw A0RjdOkfYmTlYCwM3aFLdXfBimXMGzVh21A5QxZ217xW
-7J9cRYpr1uhQPE0VjvLAwyS7jNSK0+qjA9xUMeRwYos
--> ssh-ed25519 YFSOsg w8ljrS1oRdB9RT8Odi5UOPjEtFL3WBlQUAH9Y7gp3WM
-xcrbEm66K6mNrJ9+877YEgWUdxW85YyS1z8CGMyYxeE
--> ssh-ed25519 iHV63A O0bMGpauAYAuiAtbITj+lQOS0LuFl/BDVxIUTly8tQM
-0Kiu4sNN0joX5D4eB42oQ/iRSntsJI5JNKOmkQeyLGE
--> ssh-ed25519 BVsyTA k/0Rtr9qbFH7V6DyCRtyqdAHU1b7D7DNGV8pPPJmrnk
-dJ29gcfSxaVQ46XbW021PxPotZ8ZG2zjostJme9GUZQ
---- 1V0sJP5JIa9GZ0F0hf1GAFX3LNkPSNsxNhqM9cH7Rgc
-|��#��m��R��5w��Q���f1�
��Z�MU��O�f��:G�^��!�
-g�G29w���_B���d��
\ No newline at end of file
diff --git a/secrets/forgejo-actions-runner-token.age b/secrets/forgejo-actions-runner-token.age
deleted file mode 100644
index bf7e4690..00000000
Binary files a/secrets/forgejo-actions-runner-token.age and /dev/null differ
diff --git a/secrets/forgejo-database-password.age b/secrets/forgejo-database-password.age
index 8624eb01..9a06988a 100644
Binary files a/secrets/forgejo-database-password.age and b/secrets/forgejo-database-password.age differ
diff --git a/secrets/forgejo-mailer-password.age b/secrets/forgejo-mailer-password.age
index f93ee026..a65674dc 100644
--- a/secrets/forgejo-mailer-password.age
+++ b/secrets/forgejo-mailer-password.age
@@ -1,28 +1,43 @@
 age-encryption.org/v1
--> ssh-ed25519 iDKjwg YnMyPihQVexMn+Fo3GFLVdDdovAEGSlhcHtJKYsk2T8
-nGU7ENvUew6N4gzZAfSEqM5el6M4abC4fR535KZsjyY
--> ssh-ed25519 uYcDNw lPE7/R9GhYEinW9LNJ1c8N9oiTmIFesCML6fbom4NQc
-cxwc9AdLwqOtBmb7853LQ8uxWovT9FvpqvOYKS1zbVc
+-> ssh-ed25519 iDKjwg YUx9BsGMd2Ktik7WpwB3De9yJ6LlvjdT4NlQ10cYCkU
+iv1++TiwEXdzUV2kkrOKG7L3PARkK8zhkFTiwz6+7ng
+-> ssh-ed25519 uYcDNw LhnuH/EWh0avSUUJ0KN0R+hnYHb4IHf/IDJ4JRhednU
+TMTsyAql6P1OU/Ul7hmKQxA0tFgvpmpc6rV/t8ED/Us
+-> ssh-rsa f5THog
+aFpnc2pOpKxetwVCbaYICWoQJequV5WRYApzeZsLb5QmizHppsc3aXnOjLXhn/4X
+NgUBk6DftL/IjlaelqlR3MPWHKYLRlhu5r27mkp+2xQHXTsXd1yA8D/qdjNX2CV6
+lydx9nKJ8sEWA2OLgDlyFT7jY8M8cIOxv96ONwvAIm0u+9VOPyVteYiLuUb/LbVI
+rVmxD66Y8mA+/JFtQozGp6Skl5UgzY73gbgSt4ZTOINY+TB1Mi0ntmXGcpJYPnvq
+zxepbi3yhOVjWg0i0JZ7oRrLUU/7LzpRwXFNag0x7DClLhGyWwgY7Sh922fHX0ik
+7Ss4SCzX2XE7cRkUnJztPCrP52TucTVVSmtmT2ik6aGBz6eYcBGOBXUbLKIDZBmA
+KlsJwNFX3IEEB2qpMg4ddnVUX/mq0vqJdoG0vDLcOttZUAY6iWVc45CzM7aHrEN9
+1jPht+END3l3rSZJea+aUhXcLbslCyyd9GUdaKFBd7LfK4cvyx9P3VvNWbpbSgpL
+yI8Qi+5rEl9++Dv4u8iS/uV/O3yTkFi0OMVrjudXRi9wpnnM6xHB1gn5kFFm/Y3h
+Cq9sVgGPy0HzVeivE/PlX/e8FZKThEa3+GofBFgfDCuSrTlKw9AKQRSvx6m6VVki
+w1ejms4bZZY29U32+fFdPPNTLyJVYifSlQLL6bw7hyI
 -> ssh-rsa kFDS0A
-cX8p4DJIRP378pFp9Tk4di4VBTdIQ281PhD8lBF+mOrsdxEphlFJ0dpDdlRNYN2U
-C/ku2yYVDdQjpwV2i16J99swGNR7Ui3g7BewySk2VeA2Zp1iVHYrxUcLHTU4FkTy
-rO654ndMR9nMOF/eMw8q40fdvDR0Dgtz26uqKHqabpHQrmvtRZ+O///4PSLyTpUq
-C0Rej1q9hsq38t1SwjYyyR4jZKi2eqUzNI8ZPriDJFwbOf+bKmFx2yxjN/DwjtTZ
-P2iajSqXj7bTxarWUOlTEbq8CMEpCTk5GU4G6YVJdFRSyw+KOmCbQccH45gsAsn9
-DDhhDC1nc2WRFEBbSCQdzmdEYLQa/vsmdL9Uk2CENAmqJ4s7YeaOltYxIQuIIlhW
-hDRW3MJnjaA3Z5FUyGGEF9G9/puWk+flFqaxdmPImR2MlclMokGFWQrb0LfBTKBN
-OHyLa78pCrskgK7xvRN92jepoO3iiBx1cHDgBzNIkEKt+xSissSexRlTwmc0QOom
-x9wEqBoMLy/CczRQisHRfRvVvbiu9S9ptn7jKfUExMmF5kZ3zMGnhwIKFARKyeRU
-xrJ5xJXOc2jWtK8HyhOObj4JgZYwCgC5yZg0f/0tTwhmD2Rg7l/Z14Qc8z4uSr7a
-ZI44yVR6NrnwvxCZc2VMRpS4BKYWZdor29A2I3Mf6es
--> ssh-ed25519 YFSOsg y7SH3xV54A8jRPDALbUgkI/kfG+7Dim9bQ3RoE9dElQ
-upTzhcltID98iwyIvAV43TNkn1JiPPTZKYQDXs5nVrU
--> ssh-ed25519 iHV63A OvowvvUTzN/ZZMYciY8PL4jNTsFxvdqo0HZGhrKvpQE
-6+vZnlXisJLgHsT973Mv5TW0CNaH7+95u2OLHcNRMTs
--> ssh-ed25519 BVsyTA AXiFtvrUa0SZJIDO128oZ/1EzuQCf/MTXSS8+JXRbBE
-L1aePz98wwpswYTwyIi+qlMG5PKaC8YTQ+yBNURV0o0
--> C-grease Xr"nY_F? L*?+,=6 >>*
-btUoGPkIUxNHjEV0cngeRklh2GEiS3m1v9wMkX8CH2gDeFF2M6TTroCpsqRG191/
-oUAA7nf95TEVqPIENOEh2w+U+Q0AMxUvGdps+w
---- q922LPdFDFgQBvP6ZX4Zr8+bc2Rb2z3Ru45K/bPN6yw
-�Er���G5<�GY�tO�ҝ���Y&d�m|��������.rl���}
\ No newline at end of file
+nEw8pNW6YS7MUCMnKfaJtX8uVGNCcX/X3qwuLnD6GK26QqQBjbLuLc5uQn4staeA
+4z68hJ30Zx5Yncscr+61/Afa3UP/IYTcZbnMLs62D29qeJaNKSDs3r/LpIf8IXq4
+GwdaKFqRRsqVTyAZj0nRdRbzWQqYftQWVdgPTkl6t9cx/3BLAaH9ID2mwgI4H5KQ
+h2tT0ytfvZlXHYkUj2YVdh7e+MDRv/Wzssdm7869vL7vhZH5D3hSrunOrMaat3Io
+VDuGLBf4374bRtREnBwlFlOI5+VwUov8JSP6aakb8P0PfIuCyA8yb+Qde0xxKBkd
+FTVlBx+w5To8gjcakoeVVtBO3fRcW9WuVjXocUYK9/SDeTmUFpxOGNtd128Jefra
+PGOvC62k2NnFuVSJHKDusBjtVIwxbu1+8n6LcEv6yON+6ckUG0KYXGRLFsZ5va2d
+mizsRRMyErJoxMsOpjJfsYuXMo+qP3qelPuC5+OLjakQmS0grnnOJfpmB8k880uY
+ort/J8G/zqw2IjbJt6T8sXRkQpJGb0RtTjtsQUeLIcOYcHhc/zYJFfKXC71/QyJQ
+cZcoMFzrMkTzPR0pQhPOWIWQ4iI53BJ62x4UJWZGyLtISy860R+XO2kN2exgTaoM
+EjyUt8dgMpFv0dUEgp0zV+RYbxQ6igkw+VjgpBQVeUs
+-> piv-p256 vRzPNw A7sx9kkQ3NzJz+d/Ya+g4A3Ix+Qt1vtLh51MD9L/KYAI
+3lcDBl2ASZFtVbm85rWoWhcms4uX2HSclaOA2uI2nsw
+-> piv-p256 zqq/iw A+QlOdyKHPpzJcMfelkjoZAIKH+CaIYEXvjEBqhkK+Fq
+U8jveuLYYD7xZS38Tt+5lXwIivp6mbqoeimmR5YCzc0
+-> ssh-ed25519 YFSOsg pwEdRXKO421mOmY7nXMheQpklLWJIhhyKLiUcDA/qTc
+1ElMMBsK3pGM6ZmQHJiEHmZAz9L8oVBxoNRqA7bouHo
+-> ssh-ed25519 iHV63A FIqGqLEuP8K4GXUXevEIDYGNGhNkK3fOpyLAGcJG3F8
+DHaPjWqKWZPUqEKB2WeYOarVnPv7r9tKqTI6/Dul9m0
+-> ssh-ed25519 BVsyTA xJ4b6U7UEnGcoftf7kIg0kVEbSUXopgQg4Zd4GxPwEw
+k3D/0yg/+u/LrYwHjJC9mHB0CE+zvT9hhDbhNk/5f/8
+-> ssh-ed25519 +3V2lQ b8V94Zy8Zh/4FkFyOkXZtASinRCUetLeDkLXb4Z7nns
+Rg7mEGEE/+la9DePIISQ4HD0U3bnUIfs0SuuGibb4wY
+--- ikxtrZbYSkXtO/KzCj4WNITN7urLK2cXHJ0lVaL0ZO0
+��_P���o*�_B	����It�s_AYU���{�a����z*��8m'�*G�����)
\ No newline at end of file
diff --git a/secrets/forgejo-ssh-private-key.age b/secrets/forgejo-ssh-private-key.age
index 39f42d60..06e5db74 100644
Binary files a/secrets/forgejo-ssh-private-key.age and b/secrets/forgejo-ssh-private-key.age differ
diff --git a/secrets/garage-admin-token.age b/secrets/garage-admin-token.age
new file mode 100644
index 00000000..556199c9
Binary files /dev/null and b/secrets/garage-admin-token.age differ
diff --git a/secrets/garage-rpc-secret.age b/secrets/garage-rpc-secret.age
new file mode 100644
index 00000000..76107966
--- /dev/null
+++ b/secrets/garage-rpc-secret.age
@@ -0,0 +1,47 @@
+age-encryption.org/v1
+-> ssh-ed25519 NID4eA HQEbsh8zoRkgWQHuHLF/iu6GZhCXJ7h0bCbj2z4uyh0
+lhRAIYM2mWCmwT9WGESgQnf1EadGPMZARC+EnVMH4Vg
+-> ssh-ed25519 9RQHxg GIKGKtJTCWVTZdXn+GpWPDTqQjk44ptA7/D2LmREmzU
+WuKeF8IZG70jA9zHaULJ4uXp3sj5MSga21rLOI4st4s
+-> ssh-ed25519 eP5MMw 6rWxeM8wnvSOxIbvQidqr0MREqzEdsWMTibrWmy0hVA
+LkTgGZyJsl4vfq7jUbeFbrL/naaULV9E6yHyVG3hbso
+-> ssh-ed25519 uYcDNw EC2iOzQLOUnt8a+V/zal82jrOBtBQrIWcaDo4tq0cUo
+T3iWlaRzbctnTrBCQ5aOwGND4QxmDnhulq9PcvtoBqA
+-> ssh-rsa f5THog
+NCQjF/OsBHHODFWMhgz0pkyo9YJN4bUsocgEIx+Zag60wR13cmt4dLMU7k9U2LT1
+S7gs0ZVY/7RrA9GaxTyXT9c4UlehJX33+lfR/nNCbWguilcZ8yYV2pa8DQqBRPSm
+Ub6AlkgRos0R3nBfUDiUWuwZ3ZY2qWOp4WWzcrCFej65WBdrQABD07LRUghnEPCM
+eJEOJE5nnScvK8wVmw7OTVjA9ZTOS5/opF0v76Y3kU88/VuovJz7hb2AcANuB7W+
+jT5+hKhpTaBlL/A/AmgQmJJ9GiAvdn9KUNIeqt8Nfgpc4Vs3sHJZ3HZVwC6gL3vR
+dOE0D+eh0bmI1J7t8jpRa1r9tZyKxEwZqUh/O80/d+yZygw2x8ignLpcRhLmrT9d
+c7guE8Y71+mSxeITFN6QY/+5hY4EJ0XR1t4FZHgKgMjtPBPYyx1ogQNTQf4WaNld
+XWh7goRD+w3RhducqRdmhc0RhDpCazvbGXCyBxZOImgis69CQZQlFJhpCt+Z8B+Y
+QJxesMxpvGsV9c5r8SP7UF2juhzsG6cciq8NgF/7zIq7LEbVOgBVSCLCWx+DgaBa
+Fkdnrc8xw89CA6aIwlwptpWn8rOlSiTljiMkogzWwU1QcTcZuMF7/xbDrXaZ+X9C
+JBliKQ8sO/BVEOexJ+WuF9ORyLB9JjbdGdw7LRUhPMI
+-> ssh-rsa kFDS0A
+dp8Sgszmxvk2xJ13SOQQ/ArEiTHr20nbyptGBO8esZmSOWW/7CYz7GzMT1VBNXhC
+vWgK5zknuaWWbj5o8zO3LFLPct9NvuPTSTCWYbGOR5r+I5Py+SNWNGXyZ8MycPqM
+5yNQXdhfpgTGT2I/ZbQVk3QrualTKX/usgDsIkFvkwq2/ACGsVRnfZUenZwc5XKm
+SWAzjbN8OEwtFG33fprOjYkrtfJeyMVSfdPkgg8P4Io4n1DXySZUAzR8z9uD4H5p
+HfaXWGF0JfC5LnS+8Q2lUeoB1nfb/BDMybNhfz0U9S2WyLlnjSpMBugi5bzR3Y6n
+bAHYIPnFbjstGGzBq7u0QYI8nPNrCxYdp0bZ6cgtUQfrUei6SMZcudXJXIK+DRk5
+FoHaTHkJBUTQPeN821KCjlYgV01pg86NNBMxJV9L8zJqtYp7nk7CLrG4JiwgN/+4
+MmEsmkifjOmSHuLSkrcrZdum3nlUkiaoWcjBYFwzXN6kxffefkzcoQK+Uio1m+m6
+cY6MDo5c1JzVNGIaeNJycutb7pG1iYzHGiVh5Xg2piU9Q8a+b445bShx8m9lKrHh
+VD2TeiU/P47LLURNsUpA87B2H6kLlQgj8mT9oxNp/a6rhKjaTWrt8tbApNVuttHs
+C4/N6cWeP+JwYLUSdjehTkS/3m6Gs9wPgx9uiBwi/Fk
+-> piv-p256 vRzPNw A8BVgFdKagBtB82Fbylx71jPgc8f8hVF1N06/HkIZ4oH
+/gxYFwlY4Gx8HbtKjMf9Ba+gxkLTb2ZGcyKEbnke5Ew
+-> piv-p256 zqq/iw Auev9DCuQrWVMFh8ckLgfrN1aOAVrjSsaKl00GNaneg0
+ZdqFFOSTWf1dsEdoponH1j9hXYag2/l6+pJMedYuVvA
+-> ssh-ed25519 YFSOsg GuwGTH0D0YimZksECOmqpsB8S8I/my7fDRGlJyO5oGY
+uyX0FBN3hIF3az8OiP5L+DwgG69eDATVHPaNOsX35Ys
+-> ssh-ed25519 iHV63A pD7q8qdejDfhxTWCvrfmm2oTmSdg0bNKNwPhhXH/fBE
+fVhPi/U/9MFfj2vORYM3gqEZK3dXawIAappo8eo1U94
+-> ssh-ed25519 BVsyTA iwscr5+fZh4ErmdvKJ1ta5ZSEWVHtQEIXTfzYyvTEmo
+7n+41EGr1knWuHScqWF25xZijMIAjvk9iMGZzIr3v8w
+-> ssh-ed25519 +3V2lQ HjPClU7+EumicsRX8wUk6r/W0G5eJOJ01rrunUHpBxM
+fOS+2bO9IgRd7pjZ3gWaFeLb/xBYFcJY/anHXaX6wFg
+--- 7M/9M7Lz3skL2JNpQZtfMcsL/aKutELcIyQtDu8Kies
+�_�"�B�=�&3_�^���k�qw�"�{�+����Aݵe���J���:�[�����,g��2:�r�|��*v��&�"^�ks��K�_�F�K
\ No newline at end of file
diff --git a/secrets/grafana-admin-password.age b/secrets/grafana-admin-password.age
index 9ce754df..c2547192 100644
Binary files a/secrets/grafana-admin-password.age and b/secrets/grafana-admin-password.age differ
diff --git a/secrets/grafana-keycloak-client-secret.age b/secrets/grafana-keycloak-client-secret.age
index b4c01faa..d459f8fc 100644
--- a/secrets/grafana-keycloak-client-secret.age
+++ b/secrets/grafana-keycloak-client-secret.age
@@ -1,28 +1,43 @@
 age-encryption.org/v1
--> ssh-ed25519 Y0ZZaw M6ha3gQ4Oq4PdymYZ5ZG0qGwFlpCYfJdhOBwH9n1gxg
-zCtB0PJanufNdV0ShynDT0Z/2jxMFDRby8xsfv6YPaA
--> ssh-ed25519 uYcDNw V89Ll4HJ3ZkQegiCI6gswz736domVgDGSDCA8bZBwHs
-W7IrEL+1xUXuVdy6A61z6P+pS/ajTGPL+qv+9Jh8UxI
+-> ssh-ed25519 NID4eA M8vj+GPvFph/o7wGQ3tR8HS4qkbNdlKEE5v5cOVE+x4
+gIpKa/ivPM+9JP0E6kUUOk1XXudNPXy1I8exD+SJPGk
+-> ssh-ed25519 uYcDNw evMlmz/v8VFHkiHQn4TKRmCS+KLV59xqrgRXsjzj9wc
+cSN40Oq6RtXaYkgT33oR0J92IczJYJYsKkIeGK2hmIA
+-> ssh-rsa f5THog
+qj0FFtZwAA/vYiFnw+TXK78fPOuhXCLWJSUpMLSmuRCrJK1UVZVPa/mbvWGQODxV
+7ZOI2JlmacnJLZ+OvFLwoAQvicqIOCA4Gi2vWGgWlgaAjF+1k3FOPi2pNugXa2uS
++ZsHtOZQD3mqREBmfLA0z3CjkuFlTGfHYItghCBh05L49OUyPai2pjtj6VYLKdYp
+swYk9l783bYxMtu+emcyHHw4k+YXv6QMFBJBOY5WsCJYA1Tu99uXj6/Jul3e2O4x
+ho8NK7DvpuOuPYG72pS7RVDXA28n8Kg8Mwl706aT4RTjI+KbXYfohR1EmYKrjxQD
+pzBWR8LZS29UKL18PFJQmwq6E/xrNRzOOsjSRjFvXOJUd/Xs9FM8rzE6IykA1Tkq
+6cQZ3szxKF+iK55axYzPUM2loD5McBZbd5LusXke1FtjJMz+xRhFJfcjJrA1AnRv
+3EoSHY/rK5SnSNUspg3CByUbxRNvhG6DI4XAqHNUyaUT/kGrQslcpd6QiP8zgRa4
+ZXpPxgSVxGgSUirDSkmlQxVog83Qwxm7wrO1VTYcWh5smC41blHGIbDxPbAGghHa
+PclirLGpNVH871tJevHz7ZqtHhRlsBz4TFXu89IP62G9s6h6CBc7AkrdaIy4enoP
+hX91hmnoFWCIcOfHJqySjKFv+DqH6JkBEhvv8y38Wrs
 -> ssh-rsa kFDS0A
-SV6QVIW8MCQVB8ABiOGxLTXEMO6rfeG82CktBFtf76WeIYzlkho/IaGgWXoqoIQ0
-KC/ev7vNGnB01AOWe/xkuMZDRvK+qGaOLB7wpZG1cJhqSon9oZtztoDjd/Crp5K0
-nfeHjY9E/jgFr0KYeaLedw5OJuaOw4YiuKyTThVbpRZwbof30nvHXqrYKPZJi1gq
-s5spoWYH2ijZi9mrJojP2ZqK5DJjCteXqP1YHdz3LjxomoDyl5cv/tLNsvrptfxD
-FvZMcPrvrC/IWqJ8qGW+f8ENUGyjXxx6jFQ2WN9IMIdJYk5bz458ip3GKqnAlwi3
-SZbaxRuEYEoy6ikKGRuXMAwpJd3YXcRcaRdetw0a4grdD6hF21bTl2+LnTb1ydnb
-frzeoXaqbBdhEyLpZFAmGLydteIyA/Kl/D/PEJ0MHc0G0EGofMm6YsNJJrP3mQgi
-mXC2Kto6WV/JLVEnURayf12rPR1T/VPIyYZ/Xi9HfPh0p3Y21nadPAcEq/PltWgR
-AqELfBbVpNtcxTP2pjEJqGskJCYKAmMeM+yQ0moKVmuMWicahMqjQRJO1jnvTwwd
-GhJlUO32EuI6Fn6sApthv2FfLrle+x0H4/v9xvHDJIVSmLYtzK+9ueUPn/A1x8X1
-lGeJh+ecEV2r630insGAp8WQzyXhraHrn3lgyacwRmA
--> ssh-ed25519 YFSOsg KKhXh/XW7iF7wMA7JD9fbgmty5yVPaSS1vGdHz0Xh0M
-eLJc+F/yIR1ckZX/npLI+l3I2iB+OrKBkJAQTkbWVF4
--> ssh-ed25519 iHV63A xoJ7Tr8mKgYVPPeJYBnOHLBY5E0i34vEQR3pMVKxbAc
-TKqc9Y/RpnfTP3CNvCearB4FuvNmW0mcGVLh7Ebjzeo
--> ssh-ed25519 BVsyTA LaMK6X/MJyQTQ24p9uHXh75leMcp/akCA2YZACEG03M
-psw6sVlNGT8WsG3L9kbXdrhqxp8hIdSF7s4o60jTYgY
--> vcxmk`-grease 8^p$~+LB -G)+N&$^ P)7#7[wX
-8TyK2RrSHFuMyFy9YY7ZI6RSduF5hw6xZKhiysVkif4Husb1flN8QVmWtoW8laWz
-n8772TmNTcfq5ebUp+UA+S6MVgf75D1GnDumEDH/LbM4LNjRZzyw3nBGu/Q
---- Ouu56e69gTpAY1ouLPlzI/n6geKz1CMmTl8wAVyIDPM
-���5��7W>J@���j����l_�����/����=�ջ�4(���K����ѥ�zS�s�
\ No newline at end of file
+mpXeF3O2oLTU7MAWUUctR3bAPGVIr2Ic/1o1WFhyajP19ppjlIv5lhDdBXSNMrqe
+uoNFfRuqhn7f+mtbj3FkbJN0QogNGMic9YzCfuLD1hIedxAut235majPbHNAjYg7
+a6k0WKtZInIYnMSt++qqLoQw7MIx7Tm7DjM+EG7pJKr6ZT2w4b5sthBAkBDwLSPk
+cwOGZQR5AbyJnZH1QDiXfOhywZMia/quEd7ugGZaLwSV+Iz6DwjMCPYVTP+d1jI3
+pAd3CkWIsCLMvlTvfNbLX7IhAqdg4bOciGJ8d9O/pjfj2/15WpcCBYgvaR/UYKmS
+RhPkWnPiQXVsybgw1+mH7A3wi7YdLvmQRxPZF3pc07Abs5fHMpqE3G6lDk6bq4a2
+UJg7AIqMqxmkIk4s8XIVuUVF6WmydHKIcRUx4fvnqMKyNmvB9ge/jWzy507km6om
+nVitgVmc7BoaiuaJiDB4jNO5gGsbSYm4fH82lSLJy7nhak+BRgg0oombzzh5A96N
+pYbnrZrEHFrlyjpY1MRmUJuubKC7GmljqLCWlxD4YpOg70Ne25Z44Igv+2QhSage
+ipyOwosh0uCgoi2zfOLW6mqFdsWNMDUTtpaWQmH7ICSsKorHM/ySsVw/VY9SxyxO
+J6fkWlCakn27Cd7H39SroN4YdE1JvVA+QO7+7XVha+Q
+-> piv-p256 vRzPNw A4W+Q6MpVn1ZoNHkGmIeTFrteV8IMBj0R90x3bSx6z0q
+F9+cMoBsfUeEN6bI9lPz9IKIaUNjLwJd0JOI6OYsXcs
+-> piv-p256 zqq/iw Are2msR8ZZRaNu5Ab+BTl+AMaj/jPGra5BRBajmczXC/
+DXufB6ivej3Z4YHAvt4AMGtQcbcM69kNnYed3jnfapw
+-> ssh-ed25519 YFSOsg butziA7Ccty3azzh5/LFbClCau2Go2krNjPbm2cGUxc
+x9JyLzPYyhTcvzjmb7w1fcJvcLEEDpSUUv7WCtk2Y9Q
+-> ssh-ed25519 iHV63A hSs50Whtn+NxDOq3G5HhRs9vCh/0HS67bkB4akb9gwo
+CX4pQgasUT7Z7DWjxDz5L03/1+kMCUTiU8HrS4lV7uk
+-> ssh-ed25519 BVsyTA 4Y2EBmTJc7rlFOgVdZrM9MFzes32FsRNlaMmZ1Zlxks
+BwkgIL+1gMpA55vz32iMLXgr+tK3VEe/7+JnKO7xV5Q
+-> ssh-ed25519 +3V2lQ KXNeYb2HqYI/yMSu+0eCs0f9xW4d/t21uB4DcrAAIE4
+VLasUSXqhEU2U4P3IBXhVZ9jE7/OlJ4n3qrfaVH5Gkk
+--- ZfxR44elx3WGfKSTK4+mlWuqLLSA4esg7Ml4/84MROQ
+��T�'7Km�6�n�Kk*s���!���S3�@$)��c?���UU؊c"Ț��Ԣz�W�)�R���
\ No newline at end of file
diff --git a/secrets/grafana-smtp-password.age b/secrets/grafana-smtp-password.age
index 44cf171f..8f5990ef 100644
Binary files a/secrets/grafana-smtp-password.age and b/secrets/grafana-smtp-password.age differ
diff --git a/secrets/keycloak-database-password.age b/secrets/keycloak-database-password.age
index 6f56ee37..5b9de792 100644
Binary files a/secrets/keycloak-database-password.age and b/secrets/keycloak-database-password.age differ
diff --git a/secrets/mail/admins.age b/secrets/mail/admins.age
new file mode 100644
index 00000000..5dc473d7
--- /dev/null
+++ b/secrets/mail/admins.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 UE5Ceg /F0w5batb5Xwb9Uk/ayJ1bki4AY27MgXG+asgrAmvGM
+5faxx7aeLfJyNgjZvZak8G3LSK43LLM6LAWakT9DB1I
+-> ssh-ed25519 uYcDNw bRvonmvcjyAertes4JaGeLrXQgwvI3bmILyDkRgXBnE
+kfmI6HGohHhE3kYLhjz4ZXBSJ8eVr8TncVPQQXr+NNo
+-> ssh-rsa f5THog
+QT6LrOzcJgcYdwEoLwDlgYm1eUAGIbbB5vkFyL4S0qOASGU/dKI20veQhS9DVYp9
+wR6m3E+/lR3h4qpYlFbb3HC4bjeodCpihraC6oDaJeTpQzUh5O4KiDqLn2kJd6Rs
+ZZPq+IdMHL0hTl2Qat4VRXL1qkb5ufnyotK/i4/KdsdmVMVBR5J5PeSggdfw7b9X
+ODUhHbyEvD4OugjpZevgnhF52lC9qLmjJjFsprfC3lZ0XTsXD0XK14loEQut1pmD
+6AMdHI0MgHXjXm03r2/7iPCcHx43lIlXnNZ8RlEy4QjmN3PTHVg1TbLV8UfZs66C
+D0gM6zaDzJ94qGd8Y9X5CXELmSGOIdIHN59cJLF2TnLXmItpqcS53Gu6h8JjD5Sh
+QgzSf/1dchF1RKSX+h9Adtjy6e74xsyJYlVLTDyt01Xv32rcvU+0rvjm3jZuCLf0
+iMUxe2zaniPZWkRhu7EURkLlr+L30CO8V7YQUSeIjmNOCa/HIMCyZFfqc291YziG
+i0Qy5bhrMPsWLTYMVi4Eh4QfF0UgsuiSPeWuffM07bJD3CbCCQgNPgKnq2L7Gawy
+7Gg5BQQLqyYaka0f2EHYYl819z41DXonn6Nms6SsVQyMMYsl1JMiAgVK/UOMvwGM
+kcFjew8Imh1AHDThsiKC+4ogcKaBQL7yQylCT32NEcw
+-> ssh-rsa kFDS0A
+HCbvIBMmGw0uxB5WqSzX5YtGNFB8DeM17U6PIOPailcgBc58NeKWLGy+V7TeM9FI
+2Uyd7ajj4R4UsDaPVzQ5pwU4ndFX7siq6gx2/IMsZmDPXQuSnEEPWGLQ9sWRYP1l
+3l6NcerUgQ9j0n8EMAN7hJIzYrLOqv7E/8wyyLoQfn+sr6ZzV0UNt0LCNEZdrZ9t
+X037HEDINcvmu8ZIhkopSmRUgX7abd3+gYOYE7jhR2Op7NtFMUVBmRodxA3MGYi0
+Xxgvkr+3N4A43DsxMSOv7dXY1wDvsQt6h6A52JqTy9WNXFVuM6qbGVzHRdZuTqLN
+JrB6hFhoYBmlAQQAQ6z+cswWWBnIUW+NRVvWHffP0UOUygW4IvmDJJIxF2tVjccl
+4eo9KCVnKVssu1OdZALCgTCJtZf/qePTDycdVHnYlAPHMhgZ3GabtjopTZj0WL/9
+hUc846TKbAY/wqv266O7m9zkigQ1t8p45FkM12kjHS/FsNl41Y6U2cLBZPBP4FkO
+0L2e4UItl4krM/j5vCjb9Rmu6OD6AVoL3Od41NtsrctHO2OmtQmYLlhNMQujPxA9
+2kc2p2hIXARhaF6RsZPGzo9fmxY8RNj098eHfSIu1LDGXDWh0qn/Ron0wJjrIuf0
+duobybLrn56z0ZbLco8yIlktzaupN/7G21Cd1obv/cw
+-> piv-p256 vRzPNw A4lb3iojebwu1jnystqCo2mu1JcNF/ZJokIHAlq3UVWL
+BmTNumd62GqVHQffMceFTJggcrB5I2xL/o0y7zx06Wo
+-> piv-p256 zqq/iw A1l2dATtpN2hIuBWPFe2pXjE+o4m0jAuBj/XEBeT4ciW
+2pspweRhOy3O/Bp/pIsRfC98nw8jjC6hzK73s33xyk8
+-> ssh-ed25519 YFSOsg FlcT5XKfbbQvL1cYTqGOW3/UlHyjV8Kj+v7i2/nh1Gs
+k6VAESkFmBk7NaBc8srEJVuRxrTuQ8DBnuoHBxUPJ0M
+-> ssh-ed25519 iHV63A ASS2e8h/wzJPbGJ5a0Myk5cq8Bo1CjI+7p0+vpYR+D0
+o8NSe7Ro060AzxOHbTpOeKky8RPJlGy9bqToCa2/+5c
+-> ssh-ed25519 BVsyTA ayvAZlLBX4XOEDo2fN1G5zDfe12UBTS5sy5Uhyy5UUY
+3DktYH9gTayHnC0Fn9bLmLjp4+fm4A0iS4u6oJzyopg
+-> ssh-ed25519 +3V2lQ 9wT3l+ng/VLiE57UvKZufrcgs4XNmvLtO5gh2QxbqXc
+0QF2WGB/I298EA/LGUapNEk1xYzokZqJSVmzhZI31lA
+--- AL0d5/3pSSt2dfoHbha1EJKfSO6Z4PW55d648EvFYZQ
+ś���Đ	�{�L?����q%D�S��N]�W���}9�uޚ�����⑪Yœ�,;�x��Z�e�vlޫ	(f7�T:�f��rNmJDJ���<uD(
\ No newline at end of file
diff --git a/secrets/mail/bot.age b/secrets/mail/bot.age
new file mode 100644
index 00000000..a94a46b2
--- /dev/null
+++ b/secrets/mail/bot.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 UE5Ceg B2ypwlCArbfQlB9f6wCaNfoyigxlZLYPN+G1A0RzAEY
+phfpR0H12yHwNnAFqBs5Al+E0rykpX0JQsOSi21+9dg
+-> ssh-ed25519 uYcDNw 0nP78x89Ug9p2kybjnkl1LdHS1sFHs47Cgx7Y29PvjU
+WDQ0hyddpyWHHUV+xuSees1FAUDE9aq9L9kpt38cuR4
+-> ssh-rsa f5THog
+pzLQg7g9WXNhO2uoujkqlOFNTHjWBrWi6DCNlsJslkq+muOl2Jrnh82+781sc2ZB
+EayFfD0GN6w4qQ2/zknW01EKNNOV70qmx2C9jbKLT6XG7lzJGozIJMD78h8w4JAQ
+u0NTO+zSIzsrvdM3AXlcXvN9clvV3pdQ0ogKlxxAKf8dr7p4qy9dD1r5hvideLjd
+liIitoSZDzuVvlfsP9IAHIFavcLB8sHY+dTSQ0dBMZJQIDDCUSgqsCM48Wto+ePC
+YC+HSLUASKW8SAvWH2eyrGXtnFH20fTOrFiF3WkLvm5nd+H8rBiGQVZWzbyRR0cU
+vjZN/Iu+XefwVoMLEKtHA6NYOL0xuPgsbysU8DP45VjI3ULHX/f6qUJQbUfO82IF
+qSoPhVaWrCOMyc6NjSb5NvQ1ETR9lsvENmXXhQLQwVNozUM6fmXJt9Qf6E6u5xJa
+TJgK+gktDW+CWRSm8wJ3b+Cukx7qMkV+NGKyK2iDRZSmyc7bYgpTxjjYpAVz21UQ
+Djbc7uqsNf4EiwEwkxKK5zAMKgbVQqriy6RdBqjcgVXsPDmv+rbuDtZn7jKw4Btk
+3VganG2/CDzR5wxDdentOd6utHMKlZuTkJtwVh+gL+NO7AmbtWTpJAGJ+2tkyTpg
+Zg6gKsAYhH1hgoNuyWd5807L2BGaLZIN0zOyjT4OHQQ
+-> ssh-rsa kFDS0A
+VcGjofFOsYaE94MqcJGW2UZ99Bf5PIcFbYoWuMoyMlaRnOi145IpIemxwBY79UYx
+bnpgnUq0WjNEMhqgTIG1Us2/7C4es/hF3CTNDYItLiKqy1i/EWUCIiSGPIzoLASq
+tNkFcQCCOd6OhydzhlKm4EINmFfY/fvx1XmHJc1npdMfJt82mTU2ftxelOluEbmz
+wPdNxQCflswFNyEDoCT8FIIRw7RJvCu/wEc+6IH5oDupuZCT9LvD4QEPPSjVOjJo
+1w0BKOHBTHIe6/+DjS6oqb+Va6sy5urDA79/FZDSyO/4LtxoiB//K8xd0EUWu/D5
+e8P3aQVpM7efEDFNq00rNKNnwcwQwY+WnYQP4EZQOcj8auYTxI8YDqF4Lwl2Rlc8
+8+2oJyV2gYtybc0TEyoJIRJJKP3JcTLatAdZgXO39QP3ZQO4Z0ifYAWrRkmOkKRX
+8yaZnCSmumKkPZqNbB//YJyRQS4l/e0UoB0CYdU5ljXUeXc23a/0SiptioWCj0Fc
+dDzpFTQTz9M2d38kPnvC1FOlNolivbgeYJQsL8436LPB2R9EsI8x6CBqhoCYQPnH
+4/Be9NmJhNSFKM8gavQBw6tAuO+o3KUGQoAXO/0reXa4JlO6MMN4+wJ1hroBk6Qz
+LFJtI4dTG0eRiIprIw97azIbt5HRe3OZ+x2tf20Wsws
+-> piv-p256 vRzPNw AwMtcJbTUbO1P+z0l9mHhJGgsA/FNVatPnEYWvHmWjUS
+e8U3q1ZX4uJhjvn5rnkQmulOccEJI1VK5cvS+tan4qA
+-> piv-p256 zqq/iw AsZeadyx4Wyk9OswxgYnfgSbeT9NBaYN4bqAS1jXVKs5
+ahO6BcM6qxHnDYktXnnCuZlZwozprIH/1f6oMF7CrHg
+-> ssh-ed25519 YFSOsg vyX/xUJ85G2lXyGWYl1AfDmuFxEp7HyUlltzYvLFgXY
+7GAV7wgvCPEC9RQkEVYn6t8Ou6STZpXAL9q+8Vm2BFM
+-> ssh-ed25519 iHV63A 0fCn2yOmCXjfRR193mpXR87r4mwy8QjeNfA2n0F3ERA
+dUdVw7q5GCYS0CTyNczOj67MRcWTQfRUwGtEMsAe7tw
+-> ssh-ed25519 BVsyTA fUsiobRR4HsqaYl0hfZfE+++swOV3XkAgSmMsvk5qHU
+txp2qnf62KbrYcV+Yp80WYZRJpj6MhjO0523m9nvbm4
+-> ssh-ed25519 +3V2lQ OwLStSeY1+pJBZ9fXqsZdwjPfYMApi8HXgQMIEAgIXs
+X4eezCXShnn54qHgRJM1mo9FBtVK07XVLSHBn32pY9c
+--- WX7/Z0eRS9Fkwi6s2jSr76HHmWx5oWfCQDqRJj9ovsA
+����t�Ki�Ul>�@Rt�?�y	M
*�W��b���V}�����(�/Bu0��K�pj�+ݛ&�R�
�$�E&��T{SEH84+H�7�
\ No newline at end of file
diff --git a/secrets/mail/crew.age b/secrets/mail/crew.age
new file mode 100644
index 00000000..5d6fad88
--- /dev/null
+++ b/secrets/mail/crew.age
@@ -0,0 +1,44 @@
+age-encryption.org/v1
+-> ssh-ed25519 UE5Ceg VVagFKN67R8OKJNOthRBDK86mwsNhQfuptHfXmBQ/gE
++nodn6RvyxNrMSA/aLAzmYTJVO/YSo6GlcBn0VhWJnI
+-> ssh-ed25519 uYcDNw bVnHlcPbjGibV73krlHfvl4SWe/FnLI63G5mlAdtzXg
+FuswKHdEbwUeugeuSjjE/nu66qMl6EDT8nUsdihmGzc
+-> ssh-rsa f5THog
+BO6DdPxmOSg0eY0ML+rTWOQE+TqrFPFZbeETY75xmP7Cp6q2lWr2ZhOvZEhViMOC
+4U6giC7M428mSp9CPlXQnpk4fHA/4wJlDdWuGlzbMLHPm6hhCPcryfp+JuPjbq5i
+SFxOnvUdnpw12nxCCsLXMQktPMhNsK/A9BFlnjLohfzZpcVxKxA/2mr3Je+3srJR
+IWlOLP17HoDP8UGJDQm/pfa3YdarU8ah9j0AMWOWXMrqLsjsnxdBvqf4Ci72tp2O
+Cp83TkUmHkF8gTKCPSuYVP6aAYkzCb4r/5yqizOdF7YVkv6t3YBarvRi7N6X7EHj
+08/0JiN7pHciyIMs3K++yqYg0J74//I1/TqK7JJqJ145STXhaD3RCDNaC8TUt7E3
+WWa2PEg4ZYS0DXsJhis6iP1abYjiadl89nOp2v2oZOR2PFBLMeFdIZz1yYAxh2bN
+VfI8mSbIZFp3A3Z3xqmmrdPWRB7VVl9e5IpwvysEjbLZ9e4V8q0PXwux7kPI08oZ
+0WfbpHgJ4XL21cBYE2UvSieQ3Pd+M1sgO30tLv6BT3P1z+Y4G2KhpRTlJUE9SlzB
+uW0hiFOnvEPIcNoPUVlnPTiWtEHReHnlEaDOYd3ltyBhA5pxK0z9Bm1oY+jWalVZ
+a2F2OnCBtyYjE/FMJgNN70f1tjxsfAimm6kQ3ca4vmI
+-> ssh-rsa kFDS0A
+cRu4Fw3m7KA7FGrGkC+D0C92Pw3BPcInBXjSlzuAk+/K1zcCTywRwA9RK7O9GRjw
+wDPNcrsu5pQe186PNij4FRldykFBrPwvhqDgfx2lr0E0jZdxMQ//mi5yoKHr6Sex
+95lvFiQpt2+5GJn6PyMebJf+GBVt3gToeCiwwBoUrCva1pibuNXIxEk0E6MCGQ/O
+yJeCeu9Sae0qxNy95XH06WX4CFOYmbxZSBQKfccVjFFwDmmVdpFP8NnuQCB6I+CK
+Ou1RFenqIfj9k/2D6gbis7CE+lK0Ke6SmszQljMvO7pk/EILe1NNwWPw0lMFlG5B
+gJIxjQQW+7aNP6J6jT7R2HEH6NjQu+Bsi4WO7a5b0oIMIXQdeRr00EJG1AynFgtW
+7tzqj+WSBHsvymQt9JyA/ZwlUTn7SfNHIa2Yx0e1Ze15/GNfINXlJgqPqod3aJM6
+9jrmKofvluIFUwA3EXcMzzXVHLDOi6/tp40rq/CIFcH/A9nV6MPrOzRx7Z/Mn8sp
+kmwLcxf/Ps4pEuateFU0ZvZWfxVb4abBDGkHMh53gKTohCP09yFYNaviXnwIRI2S
+OUl6MQxoOM+17ClkX11R7u+q3UxNN1rGKBjXvmLeCw0RS1nknm8lv9AGs/SgaQWz
+ZYQgSs0t8PmvHdZYJotdC6AykkCo6OhWmLd7nzRq0ko
+-> piv-p256 vRzPNw AkURiU3pt8ZyKGLAroxSDAxxabHMWrUzfeze2oc3Cy9T
+l05K5As8wku+X93LG7vTNfHcAK2YeC6nqThSMuV4OSE
+-> piv-p256 zqq/iw A7DcyvRjyVa6cjkEsW70dE8lha6BQAJF+NuN/wRD9/YH
+j8gqPHnpo2ZCyWbsssBZUki7WmGwXUJwFoE6rQB/9qE
+-> ssh-ed25519 YFSOsg 6jKKEapBICrxIIP02TXy7Fn9v1711gUhlNE0C3KSTEs
+p+sGc/8aqd0kYZtLjeOF6QeJDDenALP8h3Gm2UE2eM8
+-> ssh-ed25519 iHV63A FrWXvXyUrX5KHEtRmm6z/upIOO7eq0gruqHkz8uxwSk
+oSe+vJO7xbEb3CiADcnWDk0CSfdsjN44HwZMhwuxpWU
+-> ssh-ed25519 BVsyTA QrTESB1FBYj4t35jhGIv5WXqlawYqPxJCoLJUtDMRgc
+Ghn5PWjiDI7SdjlcjpAfmm2NGE6zXcg2WGwAF9jHYYo
+-> ssh-ed25519 +3V2lQ fsmAPXFR3An/2V0RZ4mCXiiMmKGiwyeTYlsZvVY1cQE
+snqgajEMGwSxghHUXizm1Q2Ifwtxv1/eMqTgNGmaUNE
+--- m3Rt960K96VKVv+7+5F89I3ONU4q0TYT9GKwTbd/PHI
+Ғ
+#㗅o���`S|�&�I���h�E��	^̦��:P�C��m��٘YP9��]n5:��`���'V]�@��{�����~�Cc��i
\ No newline at end of file
diff --git a/secrets/mail/erpnext.age b/secrets/mail/erpnext.age
new file mode 100644
index 00000000..fdb86684
--- /dev/null
+++ b/secrets/mail/erpnext.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 UE5Ceg WmBrIUKZmvKuvQe5//QLMLhw6FEr4+IpAHTd1+10wRw
+ICmqiDEkbDGxoVo5x04MikXD1hxWlwxEcmpOFMt5jcc
+-> ssh-ed25519 uYcDNw n8bLEXW/uX6MaxkdnpRjuXVQ/40uuDsbwGpV63vWJ1k
+TOGsv7neJl8aSFqLFV0iPGjVcxTexJwrMHdVFA4JXds
+-> ssh-rsa f5THog
+m6xyDkEy5SHS00Z08kYbmO/yGXujt7m/QCtQaHbx/Z5pvicipJpBudyiqC/XUY0y
+ACnYda8iKXuzCZ2Ls0xe0RWl1lEtLnb/7A8gsQVvZtlCNBZJe92RrsRARzHD/ah9
+IQ3498bktM7N3LFWq/H5ex1eiIxUhkTyVwYf9iDGkO4ui331ZCPoRLoYEBZLtuhg
+GxjC8ZlyyllcJxYZO1MXCrvKATTG0thgiWO1ozSswYOGUsCohBq29/nPo8iH3ZgQ
+07KQfQ990GjvjyjGDHLz2v8lquP+3d06QYTBUE9K6bJ5iDzEgXXeVnYEoA6nYJBm
+5QqVyrC11FGhzkcOTqTbpPKdsm401xJOajXw9YzjemZd+ba6ao74LEApNst2eYMD
+HVuq8h8TLsMuN1tcQYZy7I1EsXsEhuhEg7iA6PuQyBvDnLh1zdj3KMj6PunvFuCu
+f8df89bJXGNo+m+/qQftKTlgz0Epz9JSTvbXwxjelV7TDyrzRPlmhmSIIp+2JzRM
+VBH5lW4weJWN1XfvFWnX4Dhfn/QeuLnp5I/gjxj8xbO3N0905jVMklBsXS0Ak7Zl
++3BkILIA9mqP/Z0BpNNzbxhIlGkX+AgV0IKuBQIQEUpwwpXjHoAJGZPNpbk6iOZe
+EI882rrAfjlsFQadhz3qnmj3AvLIjWz4EpRYPTYwz+I
+-> ssh-rsa kFDS0A
+f1Wav1leVW0N8QUsqXzhh5CykomCh3VeYE0CYNQU30QbdjgKEDw9fSoUgYEbj/oH
+4r7mjQuUUjKpYOAqAGcV9KWCf0BTwAn/gXHHUnDjtcIDIJ7AC+0CQGm9LHXgmHnW
+AJXJ77PLNRuA+l+Eyy6mSIY4YB+/swA1as9SePMw5gewsYzVzMp5EhocJGj8fQ2k
+CoWp6ombc6Kmh7sFA46pyERWpFzyi6hZErmONctheZjFQqKCIEeuqTvYSn4Z1IjB
+B638M0n2hhQFv+0uCkAouve5TNR32lmcbpnM9TSVz9FWqU9irePdOkU9LqW4IGc/
+LggVDgC/cx7NjKmr26d3lzcPJLuJQvo2KxJ7ALK5REQYOoA4xSsKZTL+qy3Oqqgm
+1rMNL+N9aLBOrComp+p2BvRH23mRE1bm2IwyRQC+Zys9dnIrWw6r0Q+YXWLHHnNz
+4PVz0Q0FaxcAyR+udiAafSqkg1SvXSbC8s5hfLKV+V7hiU38e7sLkRDoYSJNtvDm
+3uhZyOccvPo5ofklvyEGv4Nk8jZlbMJ5l4Rsiq4USQZ7t/wZbrq04AnnpBwCPqmu
+tRP+0n1V1cBFrt3hZ5cSJS17XVL/38plo87O4I+grjpfDggE9NIUXi7y0yMjixFY
+AM5kDhjUukNpqw9brT/3j0M9gTqIV3aifEpq0SUSSMo
+-> piv-p256 vRzPNw AsfnP33A74XRIq1yDvOhL68NPdF5vF6DYwxlwG2bUEmD
+3XAsbW6hVsSqy1ooxhDwakI55b2YqarRJA8PIK8vB7I
+-> piv-p256 zqq/iw Asb1OHUQ12tk6+b//UXPCMnCGzJN9ET5YeL/cDdnespf
+RBflfmjCo17KFF+5MEKwhBEkGURfzqCBkZkPTeT9E7I
+-> ssh-ed25519 YFSOsg tA+ABhYJajeDtrX21fO47/qUw/mpSDod6DO35rQnBik
+BDPGpr/bWqwG85E+s8tTHPgbd2pasvKrqZQfPO+9bOw
+-> ssh-ed25519 iHV63A q3b/7DcjEStfvkOryZIMXUJWVZn1mjco+GcEWlLHDzY
+jIh4VoCoSYLpCGbtsgTyjSoAWqby/EHoMpSt2Mb1iCM
+-> ssh-ed25519 BVsyTA TocNmjSOyr5CJenjOw0gWb+DueDIPPQ0AMIUi+dDL14
+lf3oNdStLp+bzbdhEg3uCsWPpPoqz2OdnRSAAc1rEko
+-> ssh-ed25519 +3V2lQ GXYgAwXZRGGzH4VfodHfig4BVM3GqGQaiihZh+BhkRk
+8ZTn8ymgs28clohAYO4W55RvL9f8Zip0DX5yWpch7gA
+--- 41gdBKYDkcvf0bmpVDejjhb3onORYQyu5ncnnbY5f7o
+���2;��Tw);q���'I��/>�5�!�A0d/��\*z�4�`�q�]�z��}�l���:)�a۴��G������d`���
_�S�
\ No newline at end of file
diff --git a/secrets/mail/hakkonaut.age b/secrets/mail/hakkonaut.age
new file mode 100644
index 00000000..e7a6a6d9
Binary files /dev/null and b/secrets/mail/hakkonaut.age differ
diff --git a/secrets/mail/hensoko.age b/secrets/mail/hensoko.age
new file mode 100644
index 00000000..9142eeb8
--- /dev/null
+++ b/secrets/mail/hensoko.age
@@ -0,0 +1,44 @@
+age-encryption.org/v1
+-> ssh-ed25519 UE5Ceg WMTF3HPhmI8Ins4NRnOWJaYVV5qjVhrQVB3u6pmDHSM
+SIlN9oDn1vvdygr+aT3cpM27K8kCa1U962dpDty3Pvc
+-> ssh-ed25519 uYcDNw Da6Nl91XoUjVSBevH9GQ9rvD2eivl4OkdkJN73nV3DE
+t1Tf2aAEUA2SrH+PUGZP6zVptVuj6N7MGgJOuSH4giw
+-> ssh-rsa f5THog
+i4ljKLG/zVZPdCoUNMVK9jg3zMEMaP1dvtSyekb4ZWX+0Kfd0NHsi1z2bx52NnYp
+utjcXRvuRqd1dtIKe98FKHGvu4M1VzIOAvX2ALyrBtXCwA/G3nlLXlr5IKd90BR+
+2NwH4Sj9SEW3CbHEy4yeOxel/8NeaWYWbVmLv2q6x7J95ta3bwjO3heoskL/5ce2
+k84IrHiDNoSdx/qMyuz0K8wyOopViea4iodevPwL/IXXDzG7OJeoDPN89z+FJ7Em
+biK03qj0ONvD039mRlgGromum7U/FZE/jcbJcAhn/wRJpcfMYk3QRHBNhcxYvLhw
+KBsbQAMJmVYSbuyNHjQsQBPs+6Ujh1iDsxRtJCcQAMaKNfrHDbEIDugcVroyBGLc
+Z27uT6vyqIp/aDBUZMvUsvWNklVKHttnaZlLdrYgcz7GsbdufZx+rtCXklaei/Zk
+oc3+Ar6X12Z1psZx9U+VobBkvlrMzLnh69+vk41mOm0ZGX9miQSAy0k+dyqRDMZg
+5QjkXPZ/5ilsG+QXWIDl07z8OnHcy3nbH5dK/5NABl1NmVgTEpJlq5Jl/2BszwlA
+5dUi2wuC8p4wFXAB45PqQmogRpY0aI86FwjFYU11NNBgW28D4U3CMq69WLPbbL2R
+j2DSBvRQxuaXlUsihOSGmyipvAmuHCukpODgl57y1Hk
+-> ssh-rsa kFDS0A
+lOK5MYqTwCrZG1rs6MVY6v5SaY2slePiZ/NXdWi9w2t8Bm301u4xfVcCaVK8qjWG
+5gvttm/kbgp0J4FfX6egQotZADcHrJe8r08Vzu515C8cY8DuDSfiV8gVyalb734A
+5H1zKFhPuxQn309I4xkvDrrHJRihoJdi0klWWUloDZKQMEAL8onfIOAx8TybgInS
+Mlt143AdsihpXByi+ENcDJ5f3O89jxMPmkU+bqT/VaxzMHmc6pDZOtW8iVbXV+y2
+YJ0SaCR0Ens1Qzghg6UWSyZpEYwN8dNgBye10qh+c1HwxlTnhrpsZVK1WYiB3eZd
+5kAxqwkWULRQq80ip4Xl+Pj4rEFcXQAaY2F1I9xH7eHbtf6YeS/0e19BPUmSnqaw
+yyLGYNIDVat4TCL0ArZkJS7YStZHcz9Dy2UA4ZhsN9Ph0bJyJfHUjwjx/QkQERY0
+I1JJOum96dJxI6Rz4fSp7vZIdJyXC0s19Mqoe9+fcrpRMQs7b1pPsOS9HM/VRCFC
+Cvb43fKnelm2Ma5xrtHTh+xR85bzkfv2MK4k02X4tGoQL3Cfre6HlbmAE3JqbX0A
+iFt2FZ+3JMTx1bYjM+kZ4m8tuW0iDBHrnsOXmNQivY6iSNAX4IWRdbmvJrl41XOt
+/QLLz5vH7aOvhJu5SQK9Mo/CseWJ+wfidRKwG/nTzvg
+-> piv-p256 vRzPNw AxQJlOp7/sGiMhrx5o1dYnzh/NC4Ju3ULKYXaQN4RmP3
+e3DWL3B4oyRdPHdIWgpZC/ag8kj33G7DZriGm7Ag1Vc
+-> piv-p256 zqq/iw AlY9wO734eTOrpqepjPkkjRU4YBaRwk4i2D2c2VE+64Q
+GT21H3jRaU3oa6B/P4v/5yd99DxDlQmk0A6OkXeLIRE
+-> ssh-ed25519 YFSOsg 25usxRcYzCFBNBF+GPMlIl6+2l5WEEhsQsZ2OW9QFVE
+pP5xKthh1N6xMQW8IAaH0IYI7o8x55X8vlGcHHBy6vM
+-> ssh-ed25519 iHV63A 9UKMa4oDS4TFWQAtbbwke62OH9QYkC6n9aoEdNiNOVI
+AQrV4g2AJarp9VDdNKG99ynxSU0u2jGw4xflcSdHDR0
+-> ssh-ed25519 BVsyTA 7ahdvjlCNLLty12q5aFynuixXVGDU8B2ZWoXxeTYXDA
+yKBmqNKibs3B+xovVJIG0g3I2sCRj3xOQ2Y17pkiSUY
+-> ssh-ed25519 +3V2lQ 9wG+kwXvabUdkhCr4DKeZNIgQATgEi94gkB1Za1hqEg
+l0S7WeQUFIPjp19NUn4H1y6l5zAmeVL0kRehF1zTEE8
+--- Lz1ASOnZ6Gi0askjRf2C90AYiVpWZfbWCu1IOMxkdTI
+N���7���ߞ��[�=�9��V�s�%pO��Rd����F�O�$[2�@P��q�w�
+�� ?!@M��i�,@1�֦�{D��@�<2��r�
\ No newline at end of file
diff --git a/secrets/mail/teutat3s.age b/secrets/mail/teutat3s.age
new file mode 100644
index 00000000..1e64c6f1
--- /dev/null
+++ b/secrets/mail/teutat3s.age
@@ -0,0 +1,44 @@
+age-encryption.org/v1
+-> ssh-ed25519 UE5Ceg 5Ycto4bR/WdSMjxm/aaS/5yRjNoZCfYx2qP1OZFtwDg
+BmZST008XM8zx0KvekcyqQmO23FM/kyvEIWUQ0fLTM8
+-> ssh-ed25519 uYcDNw TKRWYnIyipaBLL059gM1RzyrDoSwVgn3fTO4/GZX9wY
+a0W67aDBXQXdNtwx3gS32zqfooaIFbaipaKjWzppC2o
+-> ssh-rsa f5THog
+c74ld2aFWL8NIGcnEbtwIlu39Unqx6Nv/txciv7KL7CGXzYR2tbBEEIcDplGvdzw
+pYyTer4DK3NdSyUIwQP3fONPQZx6IHNApr0nNFjPYjCniA0EpNL3D2eWNx6Ned1k
+zH2pVD4bLC7QQFbHT3XEa6a4bREfD9FJnlSDdjJawJSNxPZEYw8dUoHVrbhgVQam
+izv2MXmy05MLfpdErHHXjFHV9+1N3CYXXR6L/bFJBHyjfTjuXe0opPrrfLp2N1Tz
+8+a6s36h7V8soukGSxH8OLHCtEU8OcRuEymgfbF7/4a9fCPYaGx7hZNhevAArmuA
+0qE0C4FUBcuEGSjbLURe04vTzZcv+SZxmy4y0WTwvS+Vc4AHLppGeJbCSXv0UFAx
+flEJdjww2LODE0729I1ChnDJarCrV+gkvC1j5pAyNIEsMKd+yKAESAy2dR45G13H
+VmG0QeEFfALc2c04atcud6VNcmcb0saCy1jEXvGbcWe+3yEhvOMPIswMUZ6dagOH
+03XXOczo3yQwb94gAX4oMlU74BJRwNSDQcmIG26OfIL/nx00QjHZ6MIQzwLEuX7X
+Hsy/b86ogIxvbk70wdiBNngvBMouffXFyArHoyq/w2pl4Y+YtJxSuD4lv+e9iuRH
+ISBDUcfIkWqI44FFV3CTFuBgNY64o9nw3g9ODYATu5Q
+-> ssh-rsa kFDS0A
+bH6+SkWUpgXdz8r4RyGNJKmjBjcx12xNy6bup4cLsFN0gr2HZ/RJ1fTM6zp7pULa
+LUyE1i/XUe1ZN3cfivCOVdEGuMS3P37v+RJYtQILvH0a7EGUBYjAPSKMhQRp7N0F
+tyNPbh7pGM1m0eK2Ws/V14zodGbDvqSwX/SXBxn8iPO2l5opy7A1K9GMGvvRJFiF
+Ioe0Jtf5rYpaXfyfH8YvPda2cK6dxxEs17BG98RkdkGF3lzfseVlX9btyIi+0899
+VwbGUoWi0/Vf0avuRR06J0ksJfq2AN3zswLEgqyeytSpVU6unoiEE6lN8DsENKrb
+T53NxtyQPgfe+VGp7j7LNdUZQSIC96ivQwJb/QmJDmiFu0M1UuEEUbeDhvJiEuhg
+tnfrSicx2avkpj5mJpAHS3y9Cbfn/wY1kiNW3TWtCqR1CydcK+bE5dMCsbQl2qsl
+txp+Z+y0LWSK8lw0PpjmYE5Tn+p/4/Ir1QPhi+fv/9vr+ari5wqwsUEXBY1ugTKf
+4UyDSKZq4V+sDF75/XXrtBOZGyUUiqjK90YWk2Xw72Xr4XlsAU49qq7wvWGvSmTs
+LfvZbrvaH0SHDvlkowe4kAA3KEEjOUSOnaYlWOAbnFbl2KBOvFMvHyVO/5u2C/UT
+HyH0rsle8xYwNdwNeWBbbVvzx/y7yR0svd2IVQN87kA
+-> piv-p256 vRzPNw AxzTl2axQ+fxapCcHWpvbqX469UMdcbGXBhINRR8SeOP
+4gfX6vY9c/iyotQCLmlCtrs015qRjxT8uGQr49/Y6Fc
+-> piv-p256 zqq/iw A91keTk+gy0p36fc7TN3Lsl/t4Vp/2NPh4uiNekRO/qF
+AUg9OS73eHCWPOvnGfQVkGW76upVxz9+NzzxgQTRBlc
+-> ssh-ed25519 YFSOsg 3BhEY7Bm7qpf1dPcEQ//xZcO7g82PUUyvfliyWeKSRA
+NltHRhBWz9F1dzn3wehVba9KUj1d41s8Z2AMP0lTZmQ
+-> ssh-ed25519 iHV63A 8Vdid3iee/89Vzh0rs11o+WVf+qeav/Y55hAJH3tm28
+Q+4bZRnTBsuBLZJ/bt0XpfHDglztXua3AoMAVqhO/aA
+-> ssh-ed25519 BVsyTA DpMMf/h5/LQzXqtPSPHC28lcROcJQT2D8gHTpn7uGmg
+8mXsjAyqP9DWtOVZVvwZeELeX5Bb7d55XTx3f/UK6PM
+-> ssh-ed25519 +3V2lQ BIZayb0lLr8CWbOKxk4zcCOK4TiKxi3V+kfLHf49XTA
+7R7yfrMuvwpF8rO3OsSFFw+O8C82tjQQf3IqoAB+PLM
+--- k4NkvG9Dz8dQk44w3zf9prh6xzg37EI37XMnjnlmkP0
+V�
+� j6x���Bnx-�
|���	��J|�K:P6��9�b��&O���W��(�	��b��D2\��k쥭i��$ܝ�C�b�!
\ No newline at end of file
diff --git a/secrets/mastodon-active-record-encryption-deterministic-key.age b/secrets/mastodon-active-record-encryption-deterministic-key.age
new file mode 100644
index 00000000..3fa08635
--- /dev/null
+++ b/secrets/mastodon-active-record-encryption-deterministic-key.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 iDKjwg 1hTwlkE1sBAeCz0gf7XU6o0iMX9NXcqs4dFKrmerV1Y
+QTRSr5Ab6redaWHmSkGv3QBDOTCoN+0bqZnWTkUXw+k
+-> ssh-ed25519 uYcDNw FJ3Jxz2Y1uz7cZwYw+IfO3MQjoXkO4OU+CIeMDa9Mk0
+MgTZesZpxk788OBPM1forUuxIYFKkpsnp7NsEzmx9M4
+-> ssh-rsa f5THog
+JH7iLrQWeElqdYWVwQJIVh7KjBx2TmfqUekwkI0FA9ikqaWM9byewNkT+juu7egY
+eZol4fyx9WLVVNI0P+Gc64mi1K3DzW6IzJT5PN24TSOeVggj0buKRLBPZeSroCL8
+mfIRPJF5esA0j2ohGOzZLA1cpeHCkAVU6tGq5iXI7w883AOhZDZHtEJWJHE+QMZG
+9ZaSnGPLeAiC9xFjxxUQRuxUAE7nOjqoflcEPcm1/OkZoauqsJGzvNl2L+b1D1Oz
+wgSTTSVxsNH6MDKmuxZgjPLUpU9rbi1/ylfI+caW8SJ1ygu2yYhTh+KyXiDjtj03
++ZZYBjOw9bR12qiQx1it0OaxJU8YPGAlBIN+PZQIQrV7j1KwGUfsYXFmHGdRehK9
+7bVcDMeIEPYorQWiOL59zolwQ1u0Y5oFPJBiXxDwpVKEwen/VzYCtJwCDb4eIfsS
+AWLARmnRR2KIOJn6SgcoqBl8OfPntPjWr3KjvfXXrH1wo56Ba/5c4her1S/wQNh1
+MuMLE61WgCcR5Pn14gtuzMh4cqt2UN4kHLQi2KluRSa9v02WhWOCyf8AJFInANo5
+tdvM0asCAAE0vTPqk1/gwrsIAdATjC50lCyJsmUZQs6iMuL1voihWfZ154CtRS48
+ji8wKDlOuIalbzq9/kQUa6vM1kaHqq8LoLtw5wHFLJQ
+-> ssh-rsa kFDS0A
+QkIAoXUvfop74tdybgxTC6l4RSJD+QcSnCMadA4fQhfgvxftXXAMERPVmWS8L8Rr
+fnkb7WOsLKe5uFwDBAi/stjNugtjxPE6j4Hbv0LxyMh2KzsczRKQjdcEN4IVjHMi
+EZoePsshDJ1ND/SBhfSqQ/Y3N7g9sEU3K3oTE70hGX+0MOxQYz/vhw5VfjwwfihL
+n4Btjn/kmUALlWtox599tvNfy+Tjq583UdZNQMHakI4bust1FOatIdJEz4qHVb7C
+XJ0QnqlJPqY/V8KF5IOh5at37U2raAp/54RDAAziXjLnbeiCIFGFpPNNH4c1XMRe
+MNcDJQo9VxfDreVAWUEjaQSv0xK3bv64A/RelDCvgQA9+4MBDZO9i9PRkC/dUf1C
+0UzNT0pQPR/8TmAo2S/XcPYGaQif6g+OL0dvNivKNjhpx5AUxR+nImuIRL5c4H/P
+x37O6iZbg38B2g6l4oS9kOEALr3zithv7k/J9tC/5kOtXDcnDo5nuLDV1+maASnk
+a1mKGF+NnJNj9HfN9Tf5v1HYSgOHjH1RXZWaSUqQEaaIJ7jKg/hZroXUDGEZxU0E
+0u9rzeoQNXNLvTJtZjO79EWLlp8C+CryfVgJLBELe6yY4FcLR6TbB9t1bWT3VOnf
+s62sU5fpsgQgQ1Wv4JyEPt1Vy93JNPQGrbnI0euFQhc
+-> piv-p256 vRzPNw AmLneGaB8PWxhNVQakxubRiTfQI8ztGWXsZv+eirFURz
+N5bR+P/vKP0hgnejhIBEMG3c3fbnpTeZOsL4FTQdIiA
+-> piv-p256 zqq/iw AzQcsc5Tdm4R+yYGO0TDiDyEkXlsdqhZm5hp4mAj1CPG
+Nxc2z1uW63Cl3N4cQ2T3g1/fju/bVHc2BwA8VGtL/Z0
+-> ssh-ed25519 YFSOsg iKhgZjb+wldSbt6GK6RXHVOmmHIy/q1kvwR/sirvQ3w
+0IIhK9FhVl6CsdDS6e1oqlha2DfeUZ/Bs9MNooPFTpY
+-> ssh-ed25519 iHV63A u5F2ywZTiWhB19r3ey9JTzho7za06Cq8UISh4G1ApGQ
+NpuI82VTuaZdqGKyftNIrYhr5KAkh56sf84J9aw51+s
+-> ssh-ed25519 BVsyTA kDelsR5/FRuItCOMX6m6H7vyLlZRYyMrb32Eve3lMEY
+sNGS7R6zqSLT7xNJAJWmzWfWL0uj5QnJ+Gbh49YfpKQ
+-> ssh-ed25519 +3V2lQ idYZrubfci3W4Yn+3pEblXOQCf1UoyA7cxKnFmfh3Bc
+OMI1yg67nxUBH1xj9NikqFVeCTqAWa+69DYvB4T4uiQ
+--- 7HlnH19UqRCTjysYSSUJGrdsK4ZduF8+k4nSK/3JDq8
+}s��D�Y��MԎzS��~��…�.Qc��d("�)#����*Hd�Ӆ�%/s�g�h�]�m}
\ No newline at end of file
diff --git a/secrets/mastodon-active-record-encryption-key-derivation-salt.age b/secrets/mastodon-active-record-encryption-key-derivation-salt.age
new file mode 100644
index 00000000..01bb53a6
--- /dev/null
+++ b/secrets/mastodon-active-record-encryption-key-derivation-salt.age
@@ -0,0 +1,44 @@
+age-encryption.org/v1
+-> ssh-ed25519 iDKjwg dNFZ+e+a0AjH6Gs5POmZVl9bSXREvkqx1lSdmOq5IRI
+ZPEuKmVDwWgPL0qfDsMtslNJ7RG55MPTQjlBL2iEJdk
+-> ssh-ed25519 uYcDNw qDCVM6EndKJxZUXOUg0d4ElU9vlMGS9mJxELjezs8H0
+clZ8JJ24IPAd74jKyOcUvKeeanxm/Cy4b3B5mrvg9ds
+-> ssh-rsa f5THog
+rjdgXMdt8KqI1qJA0hWkF3SyjsaDz0f7AwUzcTY7hk5ULa98mCRe26tmWbTiil5D
+gchbehmLRy1JTzahUw+1xLH/iZzo3RqXCvzjrBoPCM/iucHJZPHpLNoOTtL//zXR
+0lZusQaUZ/lQrjCwyMwACJ9DKv4QiCIUfgYBzZGq6oLMYiWpEHfZQ7tWiROAO4/T
+cCCvLtM2LQ5Q5vZ5cCdBQLxrAZz+OnPgXQRAoLqH5WLMIqleUhkoVh8JoIzww+UG
+c2OKazF2dL4djnujrTQfS1uWirfmkpNW+TKrKKq6q0+cLOMjc/eLjOfBvgD+yZuO
+TxnkRRbOGNuc8hA+9FL3A/yfYk/TH78eQ27aiiV6yaX3qK9KcPp1/vUe+m4XguXE
+8LRemmCVazYuYKXzh4jr+ecppVokKep3tzb/eKSjw55xx/PIcG3AV4UjuN3Vvtdx
+BkP4/S/jn7tEBlNc1DmkrgmuUF5iwPR0CTMG1I6gxUkjyxWyPKntq6wegPT4QMRE
+eePq6SjKOOH06u4W1z4HM1ipMOK1VJrozQabnmZnhbE2+Gfy76N+Fe0sjG2iK/pg
+J8v/KT6BrhR0PYvGJirnZD0MvIlSZA+xI/FpKav/Y2195Bb+LEJY+nJoxepdj8ev
+d7N+J6g5Yt6SN9BJS0QTmtatFlTnfsU8nAYCEVB1Uxc
+-> ssh-rsa kFDS0A
+PnAXBG7IsVdWs3TEthQFSDglnQdZlmBzhYWq5er7Q32i06BGw0OJp5c7VNi6zLFd
+EOSYtdZ8SaK/CL7m3LROmv8NraVst2ml7zKeYPZ5/xHLVBb57SWkFYZIalMpZDr3
+IVRxHifZVS6hgdCa5MWUotOsdzbStUSSh6G7TCrP/LnCeh/abOXLkvqLj9NrHeAH
+UOb+Sxay3y5jUc3OBPGWw0LzGFa8S0vKhqGYIIMUcFBoenQ68/WYMMt9Lc5nD9yA
+fiH0ytkhZVkPd1+0MQ99dpCgUOcK7SOG/jUDIOhVJ8OQMoqovaML0Kmz6+Csj8l3
+l+iMd19D8CCK16dLGDi3LdvDaanIHq7H8vOW5ihWgV313aLYWdYJDIKhyn90XO0b
+SjF7dFuPxsIb+8r8/hk8xPdGu1cB3ryfEUaccQF1f0q3jBaM1RZ5Jfu/0fVHDnOj
+9c1lMC2MvwBOFFrNo9GzKjq6ezLBb58i8fV5+LZTVOgMa25BusCpnHW+KerjpGb1
+/2RK8WoXoviGAAaPuIp0ttD21oj7Ba7ZjalzO328cTlK/J6wp6qxoJOC9FuXBZCf
+M91kGWavS8Y941kRZJBD14VhLQeIjzRphnR64r03kv8HyIDSAmNc2sDOoqji1G4Q
+Fxs1oKVnSxmnGWazjmxtOtbDMhJjJlLyVEJOxgHXmz0
+-> piv-p256 vRzPNw A8qqho2hbHfodtF8D4JFu039UlMDhXhIy1lzqOBkIpIB
+CY5cHkLTHhhNIq1s6iFVGyKyIMemO/my/GmnWS2we08
+-> piv-p256 zqq/iw A23triY0bM1tpn20GXCvGCcWny9dkQDY6tP7du/HmJty
+vXVsqP2j6Kf0mwb29jSY/qn1FFnmQLWVEcL002MT6U0
+-> ssh-ed25519 YFSOsg KZ5TnAoRXHKCIEg1eoMO28saKhKmG08lCoCKNnWaOTM
+FOOqg8s2cVDPAiIVmYI2UkmpXWimQE4Sy+gCwH7oYEw
+-> ssh-ed25519 iHV63A mlcNQxplVIGOPIte0u+vibNIQtV1FCzC5IUmz7183SY
+5IlGvhYYU510PkdyzdNGgFfS9f2rkU1dMJ2Spt3RGls
+-> ssh-ed25519 BVsyTA s5BCUQJfI9Oo8XclNEp9ZJxklF/OwVECb7vFReVQ+SA
+0U2S5Y2den/c/5wNt3RI69AaURAZoEIxjoL1cBtomxM
+-> ssh-ed25519 +3V2lQ ot8xMJdVEzGv0W17UMaOvDp5ltMV1t8zrXhkpRjwrEo
+M8ky+nhQo/rgBZ2gzD1rf++MIJXzrkh9RmGOvL4cqV8
+--- 5RnhwI3yXutsCzaH+lUK221P8Drag4a4LWW0vMJKyis
+P�v ^V��]z�;>Ev�-䊽U��}�pb��2��3W?�o�!m���
+�N�	7��"��'��}qk
\ No newline at end of file
diff --git a/secrets/mastodon-active-record-encryption-primary-key.age b/secrets/mastodon-active-record-encryption-primary-key.age
new file mode 100644
index 00000000..dc287344
Binary files /dev/null and b/secrets/mastodon-active-record-encryption-primary-key.age differ
diff --git a/secrets/mastodon-extra-env-secrets.age b/secrets/mastodon-extra-env-secrets.age
index ca219f01..c78b5b57 100644
Binary files a/secrets/mastodon-extra-env-secrets.age and b/secrets/mastodon-extra-env-secrets.age differ
diff --git a/secrets/mastodon-otp-secret.age b/secrets/mastodon-otp-secret.age
index 7d224125..f618f10f 100644
--- a/secrets/mastodon-otp-secret.age
+++ b/secrets/mastodon-otp-secret.age
@@ -1,27 +1,45 @@
 age-encryption.org/v1
--> ssh-ed25519 iDKjwg AEmgV4RMWvoL7IS0h33S86bBpCy1jxuo4Ey8SUakEzs
-N3eK1K1BE2hLGF5qwQH4XVZN7y0s4pikYoxeltP1w4s
--> ssh-ed25519 uYcDNw eZrJo1AE7zcNjOn3YceDtRkumV0rwPOR5bk5s5SF+m0
-n9+J1xLDD6carZMRg05BDmaQG/78O8P8QVscKRHy6+I
+-> ssh-ed25519 iDKjwg KInpfLUhAWIHoCUGACUgWwdHi0W2H+8MVtaU/QfOjxo
+6snIWaEWHq6aylghdaiGH7NETgVqH17fq3cEMIgMV2Q
+-> ssh-ed25519 uYcDNw xGIknP5CTrf3TDFQP2j8OXlDcRS5chAkppgmizHP3mU
+/jUJLtfpsxysuwvwkWR9KAOrcvQRC0YX6kkY/zwt5tM
+-> ssh-rsa f5THog
+QIaZt977+1TAuLqUSSCH1fBGnQ/gIxbxYYxv6AvIZo7mOPljIFVXev40bTSp6kXv
+mhNBcwhDsrBlYjKgvuXjaE16eFQIOI43+JTqmFdsM0XTDjO24hX06xnpGFIasarp
+qIJHZZE8ZLIV2c5SoLtO9jkNTRUZ/HLtN7Oa37nKOvWwQ9GvOTAqnFNBoXwraq+S
+5bPY/zk2kiCpkgs4gEaA+FMhv0TEMiN0VpS7jxkHFwLibEuQj5B0HqXtvSz522PG
+lrOSNk/l+qv5OAPrIgZzY7eenf1FJf/GoC8TUJYihBFsxhS7Uah0Kwv92AP+GVSB
+lYi6uP2TMH8VijHvWuMV1nNxooCioXuIokQL/bTYan6YhmNNkiefM4vYSRyg08eA
+QL14h956ULQRONPYSmtMt+YC9Lrj+xNe8TRqJ60MxjkpTD6CLRiO6FCaL3hGl/qP
+W2EEC2IrhBWxSaNOSjJEwLyN6VPoW83TU7S+8QchIhSLaDbkDkychsuXyQ30FXsQ
+0HpQbz8HfAh649TxmFijJaZUofgtbhOHsbma9AnE6dd/yEWVvBfzeG8zp7tj3p8r
+r0WyG3xfC8Vix+l8u32xTqNdxv//xTjkNTunzb/EifqVokzSL8TsfnCYtVRUjfEZ
+wZAg+jn8u+wnfEU33dL6at3yuhgLqS+q6vZLFUt4mvs
 -> ssh-rsa kFDS0A
-b3klbHjUczTIudayv7wKpiK0IVPUjphuV451U5pEyRXKElJxcAKLae3h4eY30v0N
-sCEu32zw7aBdlQRsJrubOdn2RY7ogDsUirM31xEHx/UcDsFFgm806usYAoZ2dpT9
-XELWPs/ZbPuoHf7aJnDXLTtL0KziichCJx5RwpqmKWTDliIcoGLyNVauOU4jq8rK
-QuwKadE09U+HvxcTuyVog6lFRGqx+Ak2qRLyPnxDSAkiazj3gqop+G2IWD5Q9nQX
-0GFAsoWVdBG/ghEl4A5ruSC/dVgXM7wGkgD8Fim7LgNm0HowmEyLPLYI8PAVp5Vq
-z1/uScM/a/2zeZaY7C9JmRHCDb5weiOliSBHLQSKPiF55bgBQKRBsN2WsxYMArr6
-1YhpfIhs3eDiiTRALtyLOQrUS4xm5634ijEJ2gTzpr6XzmGJM9PPOdgbgyj2QtqG
-3AaSjknieubNWcfa2/nA0dRnvjjvvG8xfMJOOkX545jkyK7BVAC3/EE88XXuRMZL
-u2AkObphlClkW8zzF/2dTFofcjh7Ydvv3ggQBEnsuZO6LWsciuvWR3GA6uUvEAaQ
-EbTFsLdIVxzUo4BtQ3Yk6789MPF6CZ+k3UAvFWHq+842lzPp/SzBWctkXTzixsVW
-RNqqSHo9a/PEJ5FsdeUoCpov2DzQXRNtK+ia88+IDqc
--> ssh-ed25519 YFSOsg +eCKRumOVPPd3GEt1IoGq2We7jMXxfKgD2KM4iyMMj0
-5QOorpolodGux3vMT1XoCqK/0S22kpBUztPmtOF0fzo
--> ssh-ed25519 iHV63A /iWGqn9ON5KWrOiiWw1r693J90gFmkW1mdgq2aF2HUI
-iFzt9DBS5KsmtIjDdiIcS30ysUM2X12NdHuTbD5zvok
--> ssh-ed25519 BVsyTA xcKWN2iiYPQ2pCRML9DYYyyeXgoJ90cupU8gVyRtGxw
-gfLMdWnj42h3iv+zGP7uFRxZFqRmO4npNNMk6WGaQc0
--> #6ut)P5-grease qB$ $ t5c
-JEVAGQ7XDVC6hig+
---- 0yiMTzXw2ijpPVSdSyqxIpu3wM85mYT8cVxDBhn1egw
-�>�S効DF��"UݗC!����-4XOǫ �$U����K!��wy�|���Jk�-tYz��F<�X&�SŌOC�`_T�'NA/�5א�g�$y�,����E�Y�[.�a����"�,�kw�_��˸�����p���Fwp�j��VW{�hx�
\ No newline at end of file
+RtaoOXXVmr4wIZ5670NjdwEGssMtPDHx0zFOZah1vvQhJRZ4OukS7XtUeuAw7eXr
+z14nwwwQ9AsDHytqihR8hfPVm2FNWF/afUgHEir5zjPNwY7dj6qbmZjSdKfj4cq2
+7gn8FlMS84FTbP/7UlVdL9UijErLk7iJUEZ0UoA8nbXj7Rr6ecNFByqyGNrKU9Lu
+8UPly5upqnOyutb/KmhfyPkMPKMBDNY74eiAEbHWPLW+sm03pVLcdu2ADa/CmlKS
+j7GAdZHCU1okDMBPsTwQn2t5SGw9Ml/ijRiB0qcAd3B71f1VaKX49SAncaj2dYJg
+64wrmQiUpHBCxULLqG2UawFMQOg8YYS42qozGllcY05I0XniKWDDpjiK2UecEFwQ
+Y0DfZ01+oXbggaIyzVhFarfcQOk5tlLjlcHwLNkRw8c+zlnLZCmx0wYO8RwAnAKr
+HrCBaq/a9XBRlVNnzkabpZPhAsyNNXdhmCIi3Qf/ZbluISEG7RWSvCM+kAFwNjGG
+LbceGv8JXp2BnzlY0JNJfMOXFzsgtmYioav73mbT55xmkhgbWh6IlnBJSWZ9BU6/
+SAgBoM3AF9/00Vow3w70z02x8v/MwTf9pqOLLv9m2VbdJJK0fO62JkkOu9Z12gj6
+szBxucOaZJ0XJ+V+LK4HjnI1jm5/CBiy86pICcVbouo
+-> piv-p256 vRzPNw AlabLb5NpYhL9A/xCyGIjks43CPOteyn+CZif5IhTN4c
+TEeM2PxvcDGPrNa+1T5aRupYhXe1LnUDtDX3f+3ugUQ
+-> piv-p256 zqq/iw A3LNGN5NJxQe4goGItBcSrmuJQkceBzkHZk23BGC/qJc
+i9etwgttMkRtOFjS9L3tGkOA4nkRkgYRXQkpBbFU66M
+-> ssh-ed25519 YFSOsg nTj7tnPgFuNmhPusz7un4MpYUFvKOsmww5GCyTl3CnQ
+hWMIXaScPoQ7lj7VQrXL+TMXif78QvLG+mqefWBPaHw
+-> ssh-ed25519 iHV63A BjfAnEQq1Xs45iq2R30HGW+RFVKA+tUcGZtJ/1/gCCI
+OKR22LagZv0iYXFqi+yeD2KqxmlNVoUbszzeNUWnclg
+-> ssh-ed25519 BVsyTA 3EhvoVhg2IhrIzc/r+SMu2nVdGFZ7goDCTMtAd53jCg
+JVG9Ems5AVcjthivYL9XC07UC6PY73reK1VHLXZ/8o4
+-> ssh-ed25519 +3V2lQ 4P3w6HUJbfHHaOIhHtt/VjbtdrkW5tOloSV9T9yTgzw
+Rnenelfn2j8iKbOpptyQZnWEJrcmYwBkW3s5hSKvg/M
+--- dTg5lbpg/TeQ10DJt8qkzbg4+bGD7j3893qj8UY9ZU0
+������
+�i�'O:��D�3��㰴4MMk8�~�����,�q�Ӕt��Z��<8x�!ZB���)wE#ΞZ��">�
+�q��X��)|������ħ$��Ī�).��,kiwЪ.��&���{��$.Ú*y��n\>z��<F;��f"��>J
\ No newline at end of file
diff --git a/secrets/mastodon-secret-key-base.age b/secrets/mastodon-secret-key-base.age
index 5410eb0f..706d62d4 100644
--- a/secrets/mastodon-secret-key-base.age
+++ b/secrets/mastodon-secret-key-base.age
@@ -1,28 +1,43 @@
 age-encryption.org/v1
--> ssh-ed25519 iDKjwg ycwObMB/N2ylOd0U58mHULNc7FBfI6D6+DjafoQG9BQ
-DXYakb6Bevbr+ZO2uNWFOJYcXe4QohqyrNhW6oS7GLI
--> ssh-ed25519 uYcDNw PH5y1lhGq6Wh0+bKIyJhWLDKfQQEtQX56k10CzZW5UY
-sOvcq5Va4kOBLHTNJ8mQxaxgQWxSWM7VZ8PLTLD+2jA
+-> ssh-ed25519 iDKjwg daG+pfjWme7/fIsMVx2XGijVIAdq305fB75MbME4IEA
+rOh6NjkaunFlJO68u7XD1v2ClGUBhPjxrObl/dR0hGk
+-> ssh-ed25519 uYcDNw z/SI3gzQKZD5DRLgc2WRHkVmccNY3R7nF2p0gVvvd3I
+iYN7ExPXLuy8AoAqmRFtjiRosW3mG1ZVJk9kfsQBo8U
+-> ssh-rsa f5THog
+xW7zSSoL31tQbQMujEpTc8C5GkJj9O/x/cL6dSxsCC+J2hPKAaXsMgske4Akia4E
+3YmzW6kQSuOGAzWth7Xkms7n/PJTXRNzWEDCf7AYqWaaHHEMGb05DdC6ucwCY90c
+Wr0mAAfBSIWB30hgNfiel+TYjo10P15xcAQdtQ2n073VmNdH07Je+d+/8QgGwyDK
+esXM4g1chWpEtGhGrf87EX1/S5JT2CcPO4UL7TVXh1fxAwM5VZtSnhs65zZJRhPo
+HWV8Dl8f2w7k9WkcoTsS9meAohU1ZWcwmSMfRq9PF+7XmZoEmXMe0Vht+ksdNDMl
+TVYC2A8MRWl10K1rvElAdURISbF9MHid0qGrUycQq8Z2zhZIWxr8DItyDamXXbSv
+bElftfy6ZxHFhsOTFTCEVyPR4MMHXvUt+VBoWUirEVm5eglY4EhRbqm6QLakpTW7
+L9qSI2fYDxUfChr+tW4LtvrBDZRIZeGsJ8hI3WRpnqWcFulYi+0enqVm4SJXcniU
+kF0J5u+Bv0rmhggcYpy2cMXn3Sekc6OjvM2ge2uKfwZ6C/CzbAJs+BqHhE4maGTa
+vQusabgLvBN0MQJBjheIyETxCpRdf2j/rTy8H9S4B1hGbdvEVmv8O1uzEXWLKJYa
+u6jKbmUabCvQvn+mAOc3epkRonRpMUQ8VaVqdfqjjWQ
 -> ssh-rsa kFDS0A
-fI5w3V5O4EHlG7bZGuiNyUPZ4nbl3ZqZjPttUkOMYGjw84Rcxu2Rqg2i53OEG9wC
-mrxUdu744kMSxbP5iwLbnPGIhMbtY/HmggdaFI5JzPUrEE37GkUAFtaXCBjYoBFv
-7UyhgYgwfvsZXL0TiEOA6k0FikfkfPKLheXZcvIRRRXz7QDufzit5M+XieLwYbxS
-uiJYgc7ibuHQolTO6EFJf4+irdlXIWjWXg5M8mnEzDAY11PLYe+2CxguetrJyEmV
-5MQNYNEfGkAa8/IfYe0LtnOiUNr8WcHDHQGoRqrKiN7yxjJZaMR6KCMC4khkhGL9
-e8Q9WphxHxA7Rg4TidyzQNd6dOkIWhcDUYd05rm7CldUr+E81dhB3ojYUUfuQN6O
-26+wraYVb8SWS4l45gJhtNhIDRJ+gBufdQafPFtxZTjlq36y9qqhJ4LKA2/mD/Yj
-tVrjAKJHbwQiulAmBiQPloDU3jGsbFlh70zWvUeFRmKEHQUU46GK1RdvuT29QkaD
-WleEEp5BK8nuc+Zauf7xEqLRK4uoZncYGiw4tZxzhneYEBPbkK99b31c680NVB9R
-gNYlIutc1ApzOlt9eIUnF/K5CudoDsfk90gIcZjpAZ9rCZ6O2z083PJ1YzpFejdc
-hH/u3v21m5zCqGygFUkWs8w8DmhZbmOCjKbIzM8hZ8s
--> ssh-ed25519 YFSOsg LWTJhISwOh1w8Ll3MzCTiQcP+sUbcrwyCIbvTYPoIGE
-gcxCieyITgqnCvRAomzKq+um5lTusjxEt8CPNxkXcDI
--> ssh-ed25519 iHV63A yHjOEwLCaPQu/abuyy8mH9W5wmuNrtoSps4yddnljHc
-Xazda+HQS2mIk3BTP9ZhgpaQQe9BhcLX7VQpCMATjwo
--> ssh-ed25519 BVsyTA lOR29G60mxkWt2tvKaRBUTohXr0byt7WOnEHQajBwy4
-bq0RS0rjmOp/3jm/vJ7/pln+XU5RrpD7wPIRg0pJtME
--> 29Tg,l-grease d{) e6z s
-CqQnPxWIn/038/5/a0duF854yEgjZwNDuKrJwW/V7AkJJ5boEAUZJvwRkQ8giKHT
-db/YoP41cx8Vpqib/pv6Aa4fb+ovwoamkAhFp/NnD1KNJwtl8wTR9WRTFI0A
---- US3xOlecmIleG6Ye/LjcV8CSvsVK4oh8+SXoeK1qUZk
-�K���A���Wj_i㝖��ے(�����?�J����@e{�c�žo-Sܥ��q�y0D�3 �G��)>�6��9��2n��/9�ryĤYK�2���uo�N�g-:��g�Ky!�x�]��fU��i�M!}R��z��E�$Mv�Ѡ�	�x��(����
\ No newline at end of file
+in62rDIm3ga9ntI5A7yeVflE9USLuVxJ47agcKoxDCfPaKyzLdIzLWlKj04E++QB
+iitG9o5qJ7ZOBUYtQYERPR0+3hramxuKR63Z7PPgFaBcSwx/WAY9HxjsA9dHxxtF
+CLud9KW0a3AmmkH7HfAmmS9iWUhHUf1/rosnUPvrPLY3hWYDREkUZv4MGUAYE0Gx
+biZ+7tT7YFzWF31E8i9+4TxO5edlpTgyqIqU2BdXRntrso6iH2WlSjLBpPhJ4OoJ
+cKmHI3KLf0BEEjvgGOtRibSRFL3X8BDyVmNdWlb4idkcbOzGLbpxr8pcCHQ4JetY
+ovwUWdhi6So/krKFGTD1Bx7SzwZrB3+m68viAN9PE8uoTApQiul5EHHAibC3DdWx
+348UpdPN7BVleQ+pR9jmlit/myGqxl9bEbHCm1adEw36ldWSdfIKJs0J1qs8jfLc
+8Syo5DqXvCUBUl3CR8cLe+sal2cZ/4NYcXNbkOhSW/heNdzGN7vQazywJi/Xt2ol
+8hF6N0LI+iVk6FlPthLBGB1lRU4YeyhN10v6e+h4tGhz7gcRf4Ea/ZGeWBp7mGtk
+ogNeWz1ejhzvksnQdrzllTrXfBcaXvD1qD1/VipLzv9/a78LAfQwQPqH8qqFGVgl
+EGzDWYrb6BQ1VfYY4aVy00WywScnwNnEm/rYrNqWUS0
+-> piv-p256 vRzPNw AucA2fZnnEcsWtppo2zNYuoKiG7s8zgP157k7lqhNVSH
+DKm1jIK3Xcb+sQgl2kaSkUTVsuGPdhl3zlZQjnD6d8s
+-> piv-p256 zqq/iw A+OHMqkmTsJpcXDNxtNlUI1Ko/mWLrKbtMNp4amqQTXf
+IccFOIqY3rv1fWh7dDmu608nWXoSUBLNORRX7ZTo0CI
+-> ssh-ed25519 YFSOsg lXvuBojVXSG4+hzefRoCxO8Dg0PJN7MO3myoUNiaUU8
+B+B8m1z5Dn59vhDkXDTuZ9wmeSs/W9zzLtcoCHNnwHA
+-> ssh-ed25519 iHV63A iYPlqA/m4Eh59Tw43N5mijxLm/FXJWGG7+GvyGknkDw
+VZ1JcuyXLXpM9BL3jutXmgFbkUgokfR/twcmXXDgmtg
+-> ssh-ed25519 BVsyTA L3B7twUnx/UML4pMoIi3xf9bHy9Xyh0qMcmvZ20GXUc
+Nci7s4Ox3oqhJkHQRi9KSgm1n5L4HyaV/2XsXRy1sxA
+-> ssh-ed25519 +3V2lQ I01GIP2vCvgwjVEwRD0rRbmWNUubw9MvhNp1fMKuuEw
+SONGPhMHTLb4kHO+qRBngvIheGBnODyQSLfHA/njczA
+--- Bt3Ju25hzpaVmoo0s1+SmSNVMtww4Uf68QsTFSnUXnw
+��Uh����ᖍ�5+�q�,���b�%�냍�VՖ$��6��߿7>fe���*�Ɖ-?�@��L����;��m�x��0���8�5���K��D�U4G����L�@@гv50��Se�ˊ[�b�3��D5�Ϧk߁�'=WW-q�п�?|*��{
\ No newline at end of file
diff --git a/secrets/mastodon-smtp-password.age b/secrets/mastodon-smtp-password.age
index a1671554..5082b91c 100644
--- a/secrets/mastodon-smtp-password.age
+++ b/secrets/mastodon-smtp-password.age
@@ -1,29 +1,44 @@
 age-encryption.org/v1
--> ssh-ed25519 iDKjwg aWTRJDpphzxgZv1CDW/hvv33pubq/nJdCglzFSrgdD0
-XGy9Gdu+GKX53qynTlk3JzwGMJZ+RUgp1xA4xpgNooE
--> ssh-ed25519 uYcDNw QeoiOD6QdRiiBhsr4G6Rl6O/3sqFswDUc4e+/nZOBU8
-zGOMx5Td3JFzsiJzJ/CaiKnNiMg5F/fGGJsdc1KOxtw
+-> ssh-ed25519 iDKjwg /lzZjAYnRnyDSUN/ga+IlKbdHqEIetNRDFboG4zxPzo
+tK88QU+VTR+R/ZPr67TlIn8Ji5Km7eboDrznQCtSx9U
+-> ssh-ed25519 uYcDNw oy1/l0srtDa0g1uop8qWzAuEtvEQL68hk2QpC5uu1jI
+6b1/Z8tdCAqWX0tnYz3TzCsTsGakCGUsafouguOLqEs
+-> ssh-rsa f5THog
+RSDEWuJElPQVR9hh6TmB5zsseFnTwxEgBkpbXSr9rAbjLGWdopfC//jr3A87CUtF
+ka5YiCsTF4q9sgvVp3OoNmgQqSb1bpqn4Grh76XGJlawjKS5O8wv+ZHhReK+wD/x
+1M0WFHjEZ1W4n/vVBzZ7OJJpzqCMtJAnKzRFSFyIsv46qMw5xs8WS7hhHB0ehbWg
+tMpTo/IDFQ1KdgugNIJB91T1EZ1bxBnU0GZdwzqWakdArFh057Cte6y5vyoAihpm
+yuqawfjG6rpS8MqcX704B7+r5OBnbPLmecYEtFBgN/XA/FdwgQWu+SQiO2fKNuWb
+0RzhU+o0o4xnzY5263peOTVhuca9CoDt3fl8jzEvYYyLyjOHBnznW/xrJentr3so
+1uPV7EHigdWP0eo5o/NCWZq98d52GznhFsq8A9PaQgwMa5p2LecgtYfvPEHIOQ9N
+5JoVtawczAPA1BDthtKncteoFWIh7akQc39X0lnhtzboNntEzAwhpU3II5vCJYF0
+GzP8fEXESmfdZYiEqUB7KEvwr01Kn3gjVOAm35WHgGITq2/wMQXRwLT1frNao1M5
+JGUf+/OA9mW5MY8BDkMmZbTavSXXZkfjDk4h2WRINnTf/9mD8y7ewx5td/z3dVBz
+DsaOhg3yRwEDLqOfYUEjNUhSkH3midO8cRpb4k0Q6so
 -> ssh-rsa kFDS0A
-Gj9pRYVjqgl94a4IuozDZq9unJ+BwGFCVJSvsqEvJS0VXgTJ07EZgl8inziCq5Ax
-DkI6y+7C+DboAZm7fhva5yF+xFayHu6drOaegx3zjcCbtPGMbBBi2htUH/amNetz
-vGC08Y2YaLEmee2IeoqOKoImkNVE1cHEslx6Ikw0kBrND2m82coabpFTCDk4B31B
-jkFMMc//GrQPAQCfOLJuxRVBLpat+YefWwG9HAnnAZvSIADSnZGEfW3h8hoHmtJ0
-MhC7i6SZeFuBqm4EPtWm0qj6Q0xPICehks2EIiTiHGGaBIrX9UIuxnrqD8q3HCpf
-ALnErP/GgI1PtbJxlJ9MemwGqFCWB0Qruuz+Wjxv2tHcrb8eAOpt40xqcRC7P8LN
-O+8ZsQFS/aC3KUpU7eLYX8+3h+9yZHHC59YQIBiNMiPkeRvRu+cb4akb0LjdyZD/
-k6zGT4xtSirmCiZuZ9IS9u39KbUcomSFruT0CqaMRUyuOGx9jc3ORSUxvQ5oDh0/
-30QEdvNgwXJqV8TWOBvZ0T7JMCfp/+XORgTWCInL3LwAFe8gfEkzkdi5e8P0YGXf
-pF2PStlt+kmhN13rKv0vui4J/ea/o6ldc7wZ9ijaQo+agWgAOc26t/SWqPXTd//A
-zm7m5UiUA3SQznF1HI4mdSsoeB72A2dfmyAWjdAxoBM
--> ssh-ed25519 YFSOsg 38OsIFk1W0DZTJn7+A9HxvWHrk52NT4wGO7VxQLUkyQ
-k5PHL4x8hhhebjyHqMkJFpvojlyaFnaD0pnC0Dl/PTw
--> ssh-ed25519 iHV63A jqLXZzCQ1qwjsjuY9db/JhiX62vz1QpxIBYrOtGzjHM
-ft4BRNrorkoO6PJfBjKNTT7QLpttNnVdkOx4xBDEhWs
--> ssh-ed25519 BVsyTA Blaa9B9PI5ckQh/NB/V/udeFAdzgFSi93sdaOrsniiI
-nllhKnjHwlyJcGmFDTRYbncMAQYLSorJ0cFYcM6052Q
--> 7gNFA=-grease D 3?;0\> @2<SB15h vpca
-stlxmxakn0RMEPU4ZBfVa1/PUEoeZa+0Uis9r50F+Hxb8ysPrGoiuOiBS01W3+Ff
-59jnN+5xFnjS9rAfsVh/9R768jGCJGpazSdWPr006wWjes1DMdO3
---- MalXGokadvovQkpN8lVn04g50jkhvyvANdNuRxz03o8
-K�
��z�2�B<���꾙
-�^+�Z�O��7��H���	�\9�
\ No newline at end of file
+bR+BGqJ8qQD3Ycci6KstU9b7UYhfm+mDY3PU8L+2DM1a9pDR1wm5oPHdpeV3fTl9
+vDk/rDnsGypfKSBYWyZ9qdvPtyq9L69fpJSvlFw+l3dM7H8uAeK7BqlwGeA9VlM3
+ixBlGDs3qG5mbmDOYapq1WLYsY+gr9nSFtmVt+jG4NDCL4G71/y+yVyLQusq8tKi
+AFqX/1lWG3+mGXtGo4FZUyEsJ6c6qrsyHYQQJneAOg+KmRLNctQ4fZSF8g56wCAC
+CeVz23S/286qxDh1S2erCcXw4dk/HJ4QQ9uVr7+m5+jpGcbEWppJ03728XjUnFle
+zsRJynTK6eyj9/93NuLYEkZvFdFmfuR2T0Mmbw1ummhDNbF+GrvVYBrUPJgBO7MQ
+YkELivZUX07HqEsq0RgvuECwY7s0vlU6Jc1gV6v+DCSrtcogO+ouIJhgLlWzFwG1
+jwsYne+fbZVcI0GyfKvj9k6F71rLKUk/c00YObo5DwaMzolJhiipJw2T0r6Rytaa
+tOB4arjgAcEk9iLQciJJRXYQOkf1i6NpX/baP3nZ5ZUsDiK3pG7Nk/Wpf3rQWf3G
+z4h30uZXqxXQ1SXCPRQVR+T2szpDgEZvPADscred96PzTHhCL/KbbctYRnfATxb4
+MvEwJGHNLSNWpBOXyMGC3g1zMUdCCFL6enbHjnHKKN0
+-> piv-p256 vRzPNw AsX0eqWcgaZnW0ll+SDjGtfSxhLs+7Re75jkZkkf1ejU
+ExwVpIrN223z22zUX7fGHRlU2uLwRsQENy/3vLYoKYk
+-> piv-p256 zqq/iw AiKZsl0ahcMINu7X4Gw/V/lU3bDA9tbBAWi7zActxF06
+K1A8TlSdn5Wy1SU3fx10NYZ65kkZJjnbdFrXqJHKqSQ
+-> ssh-ed25519 YFSOsg NPEvPhLXAMdUS/EdOwsXY3YbWzJaq5FTEYj7zONAREA
+dFpcvXAvJoH0Fo3cjUbkBKYFPU6lHnjAhA4CotsB3Qs
+-> ssh-ed25519 iHV63A txg54W7jhZ1B4tZW8kaB9sfzgEvKZprAqih2gp+qLSM
+XjSxs4SiQ8IVWuluHkTt4FyMhJOZv1r5JZ+EnL8tSjY
+-> ssh-ed25519 BVsyTA p4KN+bojxjVnUu7kw0F5I2lB1e5dvn3WQm/5R7uX7lo
+rU1SkFq9P9tta9nLM5vYkq9DKaSzO7svl6zbnSmiI+Q
+-> ssh-ed25519 +3V2lQ F2f9haPH7DaXkAQxwyQKJiwWuMw9UbD9QgxnU+EC6zE
+G7aRwv+MRWz9eF4fKwi0PMfAkhP5IzEE+xeaWnjdWAI
+--- VotiCmupUOWIWZwJPR//t4Q1stiuYeiJ4b7xUBJocZA
+���%�E�;��G��C���R����P���	�n:�_
+���J�o�9���s�1����^�J`\�d
\ No newline at end of file
diff --git a/secrets/mastodon-vapid-private-key.age b/secrets/mastodon-vapid-private-key.age
index 921e4163..9d69da87 100644
--- a/secrets/mastodon-vapid-private-key.age
+++ b/secrets/mastodon-vapid-private-key.age
@@ -1,28 +1,43 @@
 age-encryption.org/v1
--> ssh-ed25519 iDKjwg j4mJXxXT832flTlqen/GiR4Bi4dgeQ0TYZMf8c9PXyo
-5i3vvA/KRgeTjfVwR5nQz8Omsh7TImmwXcHxPgAswWo
--> ssh-ed25519 uYcDNw fisq80sLXOyFSlItz0QIjyal6Y4nAKSmZbWL8zsp6x0
-xzatpg4g1zkcjn+SKuAcGUsDys2Vb9z6BcBrXOgzE+A
+-> ssh-ed25519 iDKjwg 3u0iaSq4cFvVQPgFhwZbFFYxcLAot+t3B0wtPN1tOjc
+elfHR5qy7s8hdWHAdXaWW3PmnBCmamj6QmMgv98In24
+-> ssh-ed25519 uYcDNw Y8Tnkvyb9b3YqSzAPQTIuo7aFfFlxbj8mvwRR+C5oEs
+cirFZHO4C5iFv9XysGadoR/IKyyhubOKjQjGdM5iNIk
+-> ssh-rsa f5THog
+r1MO5BVEdSKXiQNFfGd0RHx+jQ3xtrxHMnHGgp6h9IvuAbfpJhdtZ1wMKl5BjK/0
+JFQyS/0I4cyf+MvpVPi2hAw7lPKhNX+ad1VB0qS0pDKF07c088NfOLCHVSNAwiTD
+c7Z+OSPk+G+bUJ1xLwc83dVy5tOcF3415SSkyS00xGd8yHv3aew0vKxfynNC27nZ
+yjGwgar+/K3cBExmmMKQDXOxR85gXXyXKxRTQE4HsS/vHAxPBIwo4EhTmw8m1jJc
+tSdVeOKqq1mBlh8ozJ4QqbsXhxg2OPYhpS3QdhMdwQX3h2F0MFKO9G4R1AYQB4ba
+a9F5kvkM8qh9dSr5IQT44q+UzPp//uLw/mAcyy3CDo8bzQu84Z/juxyTwVHavxKe
+Z2Qv722c3QDEJckt75OkmBOTZj9FYZWVuKNztUhWy17P9NxpuCyZsZWUGxwhfqXh
+jbDtGbhuWPr7eGoCGd09AHZ0jM1sIWWWGn0l3QSl0Ab/JKImyoeNddGTlnRdzta0
+HgWh2BB00ySTtEVrF+cot5K9C37RfUWFcy6Hzsf143l3gxT2vHZzULjT75IUrN3X
+3gUs2vSGt1fxxk2vblNUqr8qzIYkc0DlwGxiHvRQPC8Xb5z3XaLdk1If17C3NX4T
+4vDIQwHbPXsVN1sa9pLcS40dF+amytRSAJQRz1jYRb8
 -> ssh-rsa kFDS0A
-jvhA9Vi+Mt9K6O03TOzd3D58BpDCRdJPWEZnLR235j7agQp9a84naxi4vTbb/gyl
-Tor3fwG+Y59VKRZUK4Kr8G3H1JdLDicFz2uAyVO0Ps17ugtmqRXH6MwrZaFSDbrk
-aoSHBcaM0QFE6PsQu2V7ncl2AshUWZPaB/F+Xkw+94WHFWMZSZTwy2l9xgMTUSrM
-2VHuGr9Ci6dGtmc25mYAb0BdVdJpPTwDSN9pZDXDZLbUqh7XCXyfG/DQbLrlHlFF
-ytkI8Eo/AkFnkOykC8Htcwavpgh0s4W0cjZcAciOL3IOi1If8vHFq8wVlgxZidRO
-GKAi2qjI3LWnF54HRGUcYjcCxF3j65jjRh1wBoRH/RSTNn0PVPw9J0hq0kxmBsPb
-kEUEvDtJgUGIfcJHIwC3wc67xWVkn27jHoQfInioX5euZlu6K6bvWOepFjeu9x8H
-j1ZskYkXkEMC+2Kwxytm6keHcWFAbuhJqUMgOutNMQrSMtjQBspxI/0NnCXvgZm6
-ot9XCoZaY+zfdAokYPmfi5ZT6D6l78YmpHrsejG2INuZxi30sogxr/8aZmcD9VK9
-QvG+CSfQQYEuJySHQSvtCH4TMawn9qoI+1Y8gpu0Uk7ZM3xvV6TjPVjVKvHzNKBi
-Wzy20/rI4h/BBwurIDm0S1+6+/3Ne+NhUW9Znu1WxnU
--> ssh-ed25519 YFSOsg h75wz/TG0t712R53ok65khEq/AABK0A+5dw67U4hVzU
-IcCtURo+5TOvqF7KYcLm3eOnKWYubTp2KP8BTYCDfZE
--> ssh-ed25519 iHV63A mtcO2sZ13flUEbWvTXaRw4HQEuPW6yxENLYgLT2cnVQ
-IO1bfNMeReaVzluS1HiGd7EUtwu2eSCmoCmBcAi7OSI
--> ssh-ed25519 BVsyTA b2q1gu6qLf3AMz0GAO+XPGLbBlWvlLDrBRoJt6+BYno
-p01kf2/u87VwU/hdiBPMxc7TxFjtHcmSrPsWxj95oiQ
--> J'Qo)w,R-grease QYcS~7"F m!kV 8
-kklppQkI1CR5yAngqx9UHeaMU5RVeKCeN5Eff78Ieqr3HtJkCos6dF515veac5YN
-VmhzIrFt10+eBA
---- AYe8tqHjRdyxxqj9e7wE+SUbOAuzgue6HbI6SSgVVUw
-=#�����[el�^���>�)�ȋ˖vݠ�N%��"�!�
_�b��|��4»��<�Tq*�}��,�J:L
\ No newline at end of file
+iPsdJ6WUgBNxI6WS3wZrXTVLSiR59X4oWerQOeExPac5dmvnAr0THBP3pkKqRqdt
+W0GZpKMMfWFQw3u9liu0WF8AeoA+RIPvDUJyzM2AtiJfD8VM/nk1TMFzm7pi5irs
+BJwiCM+rMH3/P/EYCjOeuQmcCJeanHbD017lgIQtKojIvLuc8RgwrtY6NkHJKB/M
+B5gAwi/RyuBtoQIJiSh5vZO9bLN4iag5IPZuwpLLFIHSHnTHIgELBi5JLHQIE3Sz
+4UpFquwNtFQ4WTw+D2oCfo0Pg8zjYeEp+GfMnLqENxuZQ7P8t15/dowHYMMjZBnu
+UTTwPOPXJFfQAuoUkqla2gus4awvnbbzJz1/NhsDa6EisTAes14hLl5uC3ozrIOz
+L0wsINtISc2zZ3bpx0tv60B2STeUpwV2H58ofz+9PMz16iitRFYHKwjmOZ8J227x
+qz0TxNW0otkg/XVtoQAho+mzWam718JXikwyui3FXK/M3GtCGPn5q9UlpEMuyBQW
+Ph8o2ZM2JSUuPcw08JJ8DWd9UzMdTasgrvLs7dkjWreHZFNJSQWWTe0KDm+cX0ho
+DoS0NAl4cWlzqkglk6shlGEjah03xwRWuHsh1Vq/vt6GlgzyjFh3FsyHJtpBn+O9
+mL9f0VKM0jG07KRClKPq0iWKK4hxWbLxl1e79o1VyVQ
+-> piv-p256 vRzPNw Aq4I8/XjPfHQbnEUc//SB99zf0flV+oHSLZ93mqFAoLU
+3Zm10nz1puSm7FSeFXhoUs8HeEAoSUXGVIZvTXgZFtc
+-> piv-p256 zqq/iw AqclmiuQgO4c0/VL0mbf02+rPuRrH2lp41DZcTNgehm0
+746h3bCZOucMhqSnxo6MqbIr/txHMC+Dk1KsBipd58Q
+-> ssh-ed25519 YFSOsg 8cTKORy9YKt73HcLk3iR3nrtDPfcNmsURwKs8qzVEUk
+ATqTIcCPqtSYU0NYHZHg1pjBJEsb+qo/Sv0uIfaFG6I
+-> ssh-ed25519 iHV63A e5V+dlrQMd2cV0x1SlSJkf8s7T8hdrffRWg2N5a8VCw
+aVjzBmeAiFwzhrSXC89k6AkfapgFCPeb3+KyNPoxKyg
+-> ssh-ed25519 BVsyTA N2ACpYO/+0MNRcAaq3ai4zXi/NBDNGKY5C6JyQ/Z3wE
+QdhiEmqy3xLqVES/JxXbYGzRP3fI5zjZ60KFX3LuYT4
+-> ssh-ed25519 +3V2lQ HAQOQsYIaXN1z5vOGZwjkL0LqhOlz2epReKPJCQAoUQ
+147oY0GywPE6k6UYThYIc0Sj1Oxcc5Wwggy/g9hp3e8
+--- 3HaNtJerb5Rj+itB/t9RNhymFhARYm+mJjqD/6NIW8Q
+*���g�GA$����q�X�(��k��R�&Os.�W�У��<1e�P��gf�W�.�jΘ��a��`w<(×�6N
\ No newline at end of file
diff --git a/secrets/mastodon-vapid-public-key.age b/secrets/mastodon-vapid-public-key.age
index 50f1b9e1..4c65043e 100644
Binary files a/secrets/mastodon-vapid-public-key.age and b/secrets/mastodon-vapid-public-key.age differ
diff --git a/secrets/matrix-appservice-irc-mediaproxy-signing-key.jwk.age b/secrets/matrix-appservice-irc-mediaproxy-signing-key.jwk.age
new file mode 100644
index 00000000..f38c861d
Binary files /dev/null and b/secrets/matrix-appservice-irc-mediaproxy-signing-key.jwk.age differ
diff --git a/secrets/matrix-authentication-service-secret-config.yml.age b/secrets/matrix-authentication-service-secret-config.yml.age
new file mode 100644
index 00000000..50cd3f21
Binary files /dev/null and b/secrets/matrix-authentication-service-secret-config.yml.age differ
diff --git a/secrets/matrix-mautrix-telegram-env-file.age b/secrets/matrix-mautrix-telegram-env-file.age
index f52fc7c6..b505284a 100644
Binary files a/secrets/matrix-mautrix-telegram-env-file.age and b/secrets/matrix-mautrix-telegram-env-file.age differ
diff --git a/secrets/matrix-synapse-secret-config.yaml.age b/secrets/matrix-synapse-secret-config.yaml.age
index b6c9a22f..7091c15f 100644
Binary files a/secrets/matrix-synapse-secret-config.yaml.age and b/secrets/matrix-synapse-secret-config.yaml.age differ
diff --git a/secrets/matrix-synapse-signing-key.age b/secrets/matrix-synapse-signing-key.age
index f64be4aa..c8a967e0 100644
Binary files a/secrets/matrix-synapse-signing-key.age and b/secrets/matrix-synapse-signing-key.age differ
diff --git a/secrets/matrix-synapse-sliding-sync-secret.age b/secrets/matrix-synapse-sliding-sync-secret.age
deleted file mode 100644
index 966eb280..00000000
--- a/secrets/matrix-synapse-sliding-sync-secret.age
+++ /dev/null
@@ -1,27 +0,0 @@
-age-encryption.org/v1
--> ssh-ed25519 iDKjwg O7ax7BWOp2BEKA9i4WAmI0hsGoRjSzfAbMb4eRLdoRM
-LlddBgKAoFe7qKvq7ixIphiWiO1JzKSyLJ6PSmUd2xA
--> ssh-ed25519 uYcDNw 5gN/+TZa94jPsMsrwXlrb1U8alMnCJq5/EIegIus0SI
-NUTWQw6WCZTpKK4EFBL1lxSSnI9WEAb1MB7iFiezDFg
--> ssh-rsa kFDS0A
-mXTGOqDXWJSVo58aok+GC2v7Xm/lL/QUrA9H4Ywfz1ksK2O1vZFmmrj9YOGMwtz3
-KodmEn8339Oyz0Tw2lSDMJb22OZPxs2q1tYQ33tvj1OXVQygzW1q/RfTPXFtTCVo
-alKl2Dbr8esFN+Cfpdh4zHJFab73m6FUDGF2k4O5Gos8eOUiUx1O8WPMDtKgwTqM
-Wtbnk0iBiTdgjwdFjkdMnx1bxGxa4pEtqtBdw9UiLwPKoPWJzHg7F9uIWH8L0FkQ
-ml7K+pjZMzwWdJwuaLpIB3yCTDiSF4j9Wr74sXjUGQ/atGesIImIGnXEyZ0v6RI2
-uRP4gx4zA9eoYcIWpuitgx9VKDwwJjcAyhffbZvTYF2ogtnWtCBIlY5jAtIV5l9I
-x0k/FMfq0hGvXOJb976zsW83ZaXVPFpUEV75mweVAUbsnRmML1kyYKAFWF58hSoa
-aEmij9hDvPIoQn2f6OTCtWXSJBtJjhxr4uvbKfrvhQojol91cU0w+fDe5rsZzhMk
-CksD3JM+OmCpguvl+4jANxPVY58avIjZArOn/UVyM0LLuKFLfRzqpBup6ifv3Wpk
-gplElrdz4iGHoEnceCGVJXcxXVbMfB4cr8I5BMK65TgN0pkl+VG6vY/TvgUl5a1C
-VjLQxIVg3hEy8mRvIGjjo0R2E8qTkcMn5Bz5mjFJeXI
--> ssh-ed25519 YFSOsg nvVCR2LV8DHU+hIQa19uX9pEhA+NQxMkmBUMDktKOGU
-Q9qhrcOeEA3myMqZbptbsWCS9hbm67pF5qO3jARN/bs
--> ssh-ed25519 iHV63A +Pca506lCnqn/+2e3lKVzlLcsa63EgngYry54yiAxA0
-hyZZUoRuYjJvhznZBAkRRjq2x6jZvJX0sfj+jigX39c
--> ssh-ed25519 BVsyTA hza+5wLH7L3VyXIwBK/sq5UNR6SC3EnKxQ3ucrVPwXc
-BAXKAf2gdMT29ZXEAeq0B54ojrGa9LwfhBK91v68yis
--> !By"-grease
-7r6wODXXipdv7nXJ+K653PLYdKOLF1pEvCWeKk8/q49s5ScMqZpGVA
---- zNjNg84OVHL/CbJyutcBz6eWD+71peLb7weZ/EjQaic
-r!�?RU��o�E��~W�>_��t��=�*7��t�=QԹ�[`@�B۝�jedܰ��q��o^���P���N���{H�^���j���B�h�:PP��&♗mܯt
\ No newline at end of file
diff --git a/secrets/mediawiki-admin-password.age b/secrets/mediawiki-admin-password.age
index 5efb88c4..30159f6d 100644
Binary files a/secrets/mediawiki-admin-password.age and b/secrets/mediawiki-admin-password.age differ
diff --git a/secrets/mediawiki-database-password.age b/secrets/mediawiki-database-password.age
index cb436a70..cfdce7ba 100644
--- a/secrets/mediawiki-database-password.age
+++ b/secrets/mediawiki-database-password.age
@@ -1,28 +1,43 @@
 age-encryption.org/v1
--> ssh-ed25519 iDKjwg z0obMnCseK5QoAge88uhbvcI5fk07UOBZk/rEXQCagU
-RtYb7D5diitYmAh+K0TbPlF2ps2LaBeVeQ8iabUA/3U
--> ssh-ed25519 uYcDNw xy8dFpnQszNlQernP7dkw/VIF1++KiTsIGDJsDHusSQ
-l82JxR2oJ71rRSZYPeXvNZyuEa2o2/uxDCJawOj9m4k
+-> ssh-ed25519 iDKjwg 5z9N7aq1bFqJOGru8Ue5X2UMQo07dci6TPv7oXC/Izk
+C3muvlb9BlU2JtDemLwHjfe4iwiFFiwzP55V8Kr6PCk
+-> ssh-ed25519 uYcDNw pXhHZWPIZo2clMc2USKcNPpw2T7azMy/SpC0OAOPqDc
+/CIOMLd/4H0TqjliHC5jQqL+Gl9YO3L2rUizNl5aXtk
+-> ssh-rsa f5THog
+vSVYgXdGIRK5rEpJheecRFALYmM00jvDEgM7lKzgVb1Vbs7Y342VEJiHdZPJYTdn
+v9AZ4d2AHporb3FOLLizprpzO6DV2q6bbDm97U2uNgAep9HmfHXQ7pxwvL5I2jdc
+HDQzWnqVz19JyObE1awPI2F+LVevN5Ha5OiU4r6n0qbs3+NesesMeSR3rZizJ3cn
+zyO5LvM5SJxMy+gJO/uYKCCuAi9/MbH/TeztfHpClp8xb8EXPnIDT2aujhDsv0B9
+xVP++OkjTbEhbbmRxV2o77q7q+H8WxeVUfACCHlegp9mm1SJ/o2ZyzLRu1qEM2dL
+sKO97uyLQxSRk4jN2T0gJRnZzia/yZ3eFJwKGZOSog0/kzYMvw8cNa2FgHfk/IDB
+b+jY6Qquc5uqA1B2DogHkYCVPShuHqDoKKvNsIopCZhUlOkEX4dAu+KvWG6yxQ+t
+NLoSP3hVmVn5aeASZXJysv5w9BVHTnf+mvJ9ZUTSEBbHmh+43u385WXNVlGC9+oq
+kS1bcKXfWx8rqgwWtYh5Lj0YoQ0SvuDuxiEPG8BUUvldL10T1J4SAihvXn4nqIZz
+I1gnhjT74uR1UhELL/BRvS2Y/6ZoveE8DC8NtvFdKNtmRVyTdj5UGd6r113jntiC
+PhxWTOs8hMeCjPKoknDfLviJCihnvW3Ac1EnHIc5s9A
 -> ssh-rsa kFDS0A
-NKl5eefpdKltFPeg5bO8vw4xa6qVo5nRMF4xTO7t6wcRagADcDWYp0ZfYoHABOFH
-yBL1YQ2VXAMmbchJKrIy4N9oy26cGifxzFBgkPlnKOxUUXuaXgv2vMTTOUUB5mlp
-gax7uq+J1qLtkc/yfvt/OOWv9qRf9vHhIWuG6/vbv+8ATWbMANLZB6GPBlW5dWJG
-A4ZV88Zd/zenB3d+bo5Gh9/RxazGfb98GwMFoHv67WUn/W542IDZyywTz/8cQB7I
-8POfee3cuiQ1K19vn4rbHldVxYCmbESS3KR6gzPk0HAi6KFxW29NqHsX//ObPkL3
-wYsKyYtsJLOy1gAKIcHG/6kysh3MstFq3Q977kuskk79JXIjiiPNFfQOh/WZKXvl
-EwuaTTvyzzXuPBRSaTMYUv3NwlT7IBeZ1D/hOmmmN4GmbE0qIp9hDQbwSrf4+3Z3
-irVMOee5SmLYwsj5cZPU7AdNs3Q1o0C2ooTA/WYFMdUKeI1ZhtNAekbuXseH2zr4
-N/j+XMSx7KAIB0Pb5yqkI/DliZpacG5DT6f+qgDYyEh0XEf7Eazn02EnquayB1Sr
-sgdZ7SO+ntPzc2l/JbhFN5SpH6iQJVohwkjBXQUQyJuLZBYdh4M0x4KF0P6xVO+P
-iBGM3/9jm86AOa6yhlfh8Z6h9ckKk5DNkMTJn+2fQc4
--> ssh-ed25519 YFSOsg ZpPUH11hi+hg1Euil1aJNXqrOKjQrucI8Mi9KVrMnwE
-xPoiMVzjfWUpUUC3EZUiogLJZfKWs2/jwGZfsx27CKQ
--> ssh-ed25519 iHV63A t4j7mr+hoW5fR9+ry3/tqKvQERZs/h7Qn9LEeeSWFhc
-XZjUNUWkWnJG7l8vahfppxZ/kjH1VRf8YNpt8x2H67M
--> ssh-ed25519 BVsyTA SztbpuYbTH+FkumMGCAQ4fQ/rRRZgGg2yCPHjS8qtTI
-F98vVoeITz/WJnJamw1I4zLHBcF46FYxKibwmbInFoA
--> %R9cvM-grease 8#EQ8Q l:Yu\
-VBsYA1Kyd/sz6RVeZNHBMvKlYmwKcuvWKyGOLzzcaz6C6kzHNgtWXcLRC0A9wMDt
-xQkX8fYdijHTcclcGerWUa8iqnpd7rAgo8RjG5e5JzhW
---- k9Ai5b4pxmq4DnN/3a6UyllvEzFaEFv0ePExwfUpplA
-��5�<��lE�N
��WՀϢ%b�<�����"a�)����8��*�Ŕc��C�0|V�qvS�
\ No newline at end of file
+bjqZTVtnEmQe2/K4njziDWUd3oNMz3xhlqDJRepgnvfLcdIgtMz6lpT7h9VMLHAT
+5Br7nmsgOiVHkndu8C71gt/OyuD3O1QjY8u7bquqZ2fI+a7aG3tVun71P8CoYLfX
+bCqzpYSa+uc3Jqkie2lL1Wbs8kOaceQTmrLLqnYLP++hpzkK/BmDUoKqOcVbwUV8
+cuoJeVsCPXn/dIVIPg8Zgp6K7Rv6i10wBxKRLHtv++hWmpdXQ4oao34qt/nxwco4
+uwB8qmJ4Va60uUuwb0AlBeiauFAnl1aoGn01bYOHCKIRIBd5GyE52ZsHxDEZg/3Y
+vGa3a5gQQa7VT9dGF9GRjKusZdFCtiewbptZXdi0HFSDDbHkphJfoYUsYXsPloWs
+gWNSXqFngklxYGjJMMfAuomtYxdD50ramMY85C+/mLGuZSKQ9u/8DOcm0CLhRskc
+Xj/VhGGRIuQrLvb1QJGpV5DPgT0+vkrqvnNKMgQ24l2ziogsCBHkSIl6If2HQkGe
+QLyIl+CDLgIshQ6Qrg9c9dRzH3np2Fg3XT8ypbmfON0EERd4u3sZ+uZzYtkza8/X
+o/xVkIVUCJh2GwyxqAD22kJCro0qPn4F1HAFWy/rBMRbapXiYlUFnLVgEu3Gs6Lx
+PGMuqnT/3/uzko8lQR49zohmHGziYDPzmZEjRNrJu6w
+-> piv-p256 vRzPNw A2Deyx1/qvv9ylHmyTO149TvT6Pkh35iH+FggOqUPKYz
+PGBMYjusfUINKi7ayGJxzBuP6f9GrLH2qFtaSH7ZH9w
+-> piv-p256 zqq/iw AuosErZS/Pu9DeljWCfX/KqoRn21B1L9hwYeSnjHi0CJ
+wVQo1+s1l5ZHCGVYyIE2JgJi7DAe/Ms+/aNvF+9YtTk
+-> ssh-ed25519 YFSOsg jtYU04ZXp2zKnStgexrsiacwsAbJIV/ZBLa4YN5RPnE
+tiZn82jmUpJmcVhRzrCJbvfGgdDTm/SDJQuZ4depLzs
+-> ssh-ed25519 iHV63A wSTdp2qyNeNLnYaKyM6nmYmScLVirO0rtnDx9lKTX00
+mhRzqgPZHkrT6lHe6mdb9WYzV4UJ1o/GIqz0i17WZH8
+-> ssh-ed25519 BVsyTA cWa5esVjShFSk+NwZ/5/JRD13qtGXc/OU4o8sxSgD2k
+rL3tman5xeS0J+KxIs42m3uglv8G3516Zi9yyRsD7B0
+-> ssh-ed25519 +3V2lQ yfTuw0c9pIGYaIbUM0MYqCOiNH56iTMuA/DmPHqdlyc
+gkqHI4vx480aC3Qvytj5IuiKODMH454BMxRkOHHD7g4
+--- cxCIUqVXbLdIb14TLxFvRO065Ran0D9ZlEs17nlBggw
+�����w�a�*��D���%���ͅ�-���k;����-���pߥ�����k��PQ�b�
\ No newline at end of file
diff --git a/secrets/mediawiki-oidc-client-secret.age b/secrets/mediawiki-oidc-client-secret.age
index 104b3c71..b9ecbf8a 100644
--- a/secrets/mediawiki-oidc-client-secret.age
+++ b/secrets/mediawiki-oidc-client-secret.age
@@ -1,27 +1,44 @@
 age-encryption.org/v1
--> ssh-ed25519 iDKjwg wNZLc0SqLieSDPQzQEcJML08uiCKPLJoI95maDa4a3E
-KXWlP0ZPWl3WiSX04UKtwHdhezMdLT3nskLl7E7OSHs
--> ssh-ed25519 uYcDNw yA4rP44m2CJgvuSG4NrRFY1BWAXbdzov5AK/eYDu42Q
-vfZ6m1Vw0WNsnCmXe4jOtSvHMHXVxRBvP2Fkqki/xK8
+-> ssh-ed25519 iDKjwg B4Q4n3OQcImK3kQGY+lnpoV9X8Cg7dVEudqnwYXD8nE
+ezhdtoWHukS641yB2bGsz7OqekTC6wuVhJltH34KCEM
+-> ssh-ed25519 uYcDNw BqZs3Yy2bEJK/cAj0QXFi1JfEo+pVnYGwrKxreUobUI
+qRWxFsM4Ic+x1uaoKMcFldZ/D5UZ4dbcqoVGMJbMlCQ
+-> ssh-rsa f5THog
+sNxBqEa+zGdScrGxMoCNIw4UXRhpIq6TVkAp/a/tAy46ko2aUp089mjLXYokLCEI
+ybEL/8ud8eYg3Ktj7crbcPhLcCtN8GR4M7AUXO2XssKK4kqrayOoXXJNT9UTIDuD
+zeyRE4WwVT/ggLBb2Fs84inH+Cab+r24MNlHc6wKHkiLGx2KB6IPv7iemH10Fews
+XGJaLp4W16tAnxRMuzHRHjhAtzx9j8tQTiEF1hOqIbxFcLP3ggZtpdTS6xX1KG/u
+nJZtFQaWG3uDmTVf7JRAowSEG+UBYEzHIxN1FRE9DVL9i1A/lmgAYhP7By8e/j2I
+eOfLa9eRHGAKoZ4B+RoNjb/NWuaVzoLQ/IzrvKq64zq+b5v1BSSGG9OtLk5E3dU7
+qoIl1aDObZ1hrGisJ2AxAOnC373vykxOhnHceeth8UqftNqARZLaAo3/LQJpq85a
+6a/ybNlrxD7DXCzM1CqdyHhHeOh4v/1fnB2wi94NX+Ke7RJ+PPHJoDhnMf7gIaVI
+IevVlzAt0tQ0QSwO9QYVNaP8O9KmmN1B2nf8qn+vscysvPUl2hzItcb0O2MYBfJJ
+SOwoTaHhwW63OK8FlfbOOgzMvxWMm4LSvA+n7UacKWJPDcR3PQzuK+k35sl+ScKB
+OfdblBDcqaUZ214AHzv1zq8k5356yUK+xYGWuFasxMY
 -> ssh-rsa kFDS0A
-Milr41weYJCyX92mWcSBSJEeUetq76tzjwsCjJtfpvG5ASsiu/Wj7jtngOO9wER2
-8kgh3DVQVlZV9kwHoC8zM3C+qYU4HQf74Sr9TXXcZko9HBZA17O3I5IBnp5cmVsq
-ZBE1gpuT+J/xSA14w4Kf7LbobNpYuMrEGoquWAH9ESjPt7HY067rGe8nBy2RoAM5
-FyXQ8uoPw6wDB5Ak6HGT3pdzazjtDugJdaO/9CT07lI+XvSAD5CBvtfjoWAdTphC
-+6S1t9gcNZrd+oQ3LZ1mSnvjVc+O4YHjzy56zo3Zh1KJLxMbdkO1st72fsNTNXjI
-gj3ZYmodz/lfTxQABreQdo9AUCBBQkoyGv2uilYbJPTTeUxCXUnGGkDqW4e0p/8z
-ukHiqeeMw4XqPXAduVlNIpsvW1s0sDB3Kx8t+KJirr4PHfIIulHbnjPxKQyXaj86
-nzSYSuzftOquAz8CIokgRyFhgJtRD2lzNhXbt6GvU4VLagtmbFQmhyqVJzzvmnE3
-7cu6Fcc07IiA7CuhweAmWA8/vjBtbyQMqVAHVn+ijT4WKb7gDfcL/w/MZaq5XOa0
-9zyoTa7y7ttC3AqzDWlfOEK9TC+ysKB6LgTwktNS3u0Msh2DYNqLsyN+ktDyb27F
-YzT4Wu5ZoYcCkgNwvAyU2hPfYzv66mQo1I0BXKYaiQg
--> ssh-ed25519 YFSOsg BJMjSn6gwtaOheT9Fnes45QZ5BSBGnhhGTPFO5DJIU0
-cyhAM4/waWjH/N6WWy/8w4M4PQt+QzpgMy+7M5DBTj0
--> ssh-ed25519 iHV63A JTvN/gJpphteU1WpESnZ9iTeePj986kuYxI2poVYdxc
-kJCBRrqzEW7c/Y6HiiJLmBzlsBtvZsK++NsEVoZHScs
--> ssh-ed25519 BVsyTA 9cJBL0f0XAQWat68M3mMVSAKpnKNNzAqAmcuQ8fJiic
-TSA6SRwonr8e1kMrGyf89F/TPmU2S1SmOlH2KbJmFTc
--> *OkMh]47-grease ,|3o ^Ai N WuMh
-YpKgkp1VxwVinaiFO0pFDw
---- 4278uiwRYOTQM1T7Cs/1Hzn3AiRkyvXuqtE+9wyfD+A
-�<C4l�U�tOX�L�i�ִ��8x�֘
�|PY�w��nt-��n�Ůu��z�g��uHpq�j�
\ No newline at end of file
+IhS+V1Iv0rg2ZA/F9WOQGl7vjSGEsV8OXm7q77Uf9zHw3yxXrWkAS9MawdyT6shJ
+1SS51c8nFdx1135i4CqYwqQ94aCvZYMSMbub7bMQsHyEon1KPeLSJ01OP7Fzo8xP
+Ffv2BigbrCShKJfStO6ughS3lBhqLl0/bUINkjtTzzIpbVyW49AfCxhlt2xdkgls
+5HrRihfUInm0euaf3uDF+I5/sf1Z4s+1Ytce550etZMYuzb3uL/uLji4SlleTPzF
+MjEm3j3J9hNEbImXrE0URRMtvsn9vIsmEHcPiodutDJNtolEPLJCgi2xxbV0sFPd
+vDOSLHpC0+bkqGVpfCAoXZ3iipYhSJiff1x1vp06tsKRYFAPZ6Xf22G0F2qOH5ci
+ELIhxcC4uggN3zU6Kn6mu+cLquln5+F8mj3oUJvUgHbWxxsXbtwHONSoBu/zH4vX
+HsAbIvGi+MOoAxhRfWJZEAlpXuQWmdhVv93tV1ovNh3RPRjhZjHgKAOh6T4YNXVL
++w9QaOKjS5GVvRm4pzOr2FDr0S6XCmRPT5af3iaTx5mXCbOvKvcU4DHVoBf+z6AM
+EOeX6Nbg5Y53xw+XnoHOtJEZ3jlMOoHopYxoPkCZzebc24U0lRvoa/Sznp/NLCYe
+TZUsxYE0PKmS3y7Mbzsh9ndpSfdGyEO4g25293mVdn8
+-> piv-p256 vRzPNw A/G5cbWw8Qk/3coF3miTW4Ly6lEq14cqvZw+V3nRH3F7
+hIlZRI47gbHxFtVDMTzFWGK4opwASBs2+2UayfpNnu8
+-> piv-p256 zqq/iw Ah1dVGfIxLG1boPe9uzLQlodIZKIhssbbUTh0iHDWHjN
+JM5wYMuymrAj5C7eRUTv7jODft3qwr5julB9sGClGCs
+-> ssh-ed25519 YFSOsg SdjyfEQ8he0o9YJa/xOS4LRMAO6PhZVTMWFIAEs+FQg
+4GlYuqhtXtlrNAWKnz7NvcMxDqB0ippsfxQW0w0WaRs
+-> ssh-ed25519 iHV63A v0u3Hw6eO7bLfGZvn9ZlI3efgBDVITpj2R9+tS6vQC0
+SB+5Mu2UJbZHTK87NCnstwtwxUy7Nqax8LLJHPcgEmE
+-> ssh-ed25519 BVsyTA PJ6f0X5TjtbkOQAxAQlajnGz8VgWBLYCZvCB7tlzxi4
+w9UAYVwdhOFT8+9/zkprPXO16n7aMRDG2EwEfsXJ/vw
+-> ssh-ed25519 +3V2lQ imQ3snuaaxF8Y0NopC5u3qZi74HDEjhFc/cSRX5VRQU
+zEe8cxACsxrPFSDno96nyhga35ZJXB9rVKYzJY+eHPg
+--- +tHk8JDyqT3idP1MrsunTGcEO0DFuUec/fshqmsPp2g
+�o�/�2���s{[`�����?o�ȶ9�ҵH5���ģ�����z
+0�E��@�w�捑�gҟ�
\ No newline at end of file
diff --git a/secrets/mediawiki-secret-key.age b/secrets/mediawiki-secret-key.age
index c1a26711..3ef2b8e7 100644
--- a/secrets/mediawiki-secret-key.age
+++ b/secrets/mediawiki-secret-key.age
@@ -1,28 +1,43 @@
 age-encryption.org/v1
--> ssh-ed25519 iDKjwg MGfeCP81T9itCIgFoOcDoJfLtvfOb1dEtx4SjRfQMDU
-QJcTZDMx6qZfTtQxRpDAb5oA7PWqAgVDiZ5m9PeD3OU
--> ssh-ed25519 uYcDNw 3uX4IxJVdepJ/258XhKUEOeX00nbKQ3+8WskCE/Oex0
-WaTAvd0zrcyFFwz7QWwaEsBrtp08g3wbANJvoL+hkfc
+-> ssh-ed25519 iDKjwg 2oxyNUkFiy7ibFwoekB0Z2jmSBEf8XyP1+42jNG7phM
+UlczSRNUs3KdeLvp8HUAk8wUfuuKEaN/s+C9wEBVtrY
+-> ssh-ed25519 uYcDNw mP2CBhTvN8h2UFp0Pm1zve6rIl5qF2qrMqBLcLFWuxE
+QUfrFUIeauO6zNbhyPuc0JCZ5Vb5mO/QfPkx4VyCUN4
+-> ssh-rsa f5THog
+AputF66htTIxUES7oCZL44NG5jYpM/F9qmGoN8+fm6k0f0oURozSYZSR2MW7iOcL
+Y4yeeCmHZ1u7MkL0zN2fBealNpKUR3AyfyUz0Bv/C2+7yiDUehkOq9ktsYjH/Bn4
+9EkdxwDDpC7485ZmDSQKuVw0p8XRvk0cC8lsZM/c8PjrJsF5d6AoVR9XzfFZqQXJ
+fn5Sk6OMZhneHB0snnCEiqCKKah1nbIgaJzUs69MaYM7rFYHqd+V9jcCOr73lIoA
+Zp1RTLybaWUOEtNUiLqy9j1CChdjCauSbGMCQrL+ZF8OZ2+v6CsrjG6LVV3JA3vY
+hLN0whrhbSbAj5JrLwx9f6oDwn+bNG6RXqFIpxpIbt1aN5xAX1mLuOl3XG0pzjhc
+t3k+XvaSUoNanrP3GdevYwLeVFejp+Ddf8uYQcVRf8PBEA9+WpI/4R+gP8tDBokp
+8t7GFqnfL2DPuEZWmo/46DtqRmMdqlVdt9WRccKYDDdcOpQFG9kxOhmopRUWnqZi
+/qbp0REISFD6/Kyfu1Htqf/3Hw4qHsViRKwLK/Bd59viP1Oa/No0T5RdXGoe7U9P
+3xmCAZpjPApTYenSpTusAVy0dFDsEk4Fpo+NZlr859PZ+3mxkJmvRpOy/NTPl4mL
+4JKDmyLe/QrQyUrYFfqdU+VsoORFN/lAKerADkOcFh8
 -> ssh-rsa kFDS0A
-kgdsJuX6ZiMPJx5OjJuu0pjLqIr7vmw6SSRAWVR2RgxUbZ2L0khOUCOSbeHExpju
-RtadRLVKgxGkGAYqaivcUj0fu71RbxAfsCkY6hwrXGAwWLLcviTeZpRJUcVWWdkW
-DkZKVukqq2XeB33CqVcTanEVgTmwfuASVb5WL/FBrDpITV0oTcyJB5k57Qor7utC
-9PBYJmkq8ZDbpcZQM210XYCJdOhK4J4j0Rbq3Er6a9mlxVWuGUiBUUXluwDBN7iG
-sEha1Y6GvWfaqy3Y0Y+XxkNx3KsRnRvT3h9lmCM/RVaIGIeOTgF/ZRSKoUuMZ9nY
-+XCXTGOhUZZBb/d0Edh+0EF7JCNOHA0Uygu+8RjxxNTMxLDV2eR5N+yYH4tbPuQj
-QI3Wo8H5iDwwCnyDwmXwkRWd9aEhfG16S3NqbyCfEA/xIUgQnIEx7DEjLJwDrb4v
-IVL6cxqSU/GCV2x7HyHf4syZBSQ6oC2Cy5sEJ5WV1m7+S35Vh5UQcxh+oNk1Gxji
-Y6yhem70RFLauzxldNcpI/xKTsj+mfrI21+fb6InVSHzlME0ggcMdz5mp799TEeg
-GYO+lIlfKIPWcQYI6Ci+Qbs1bGZ8kJy82C6arW6rooPQTdqnOgJE++1lj9dZO6bx
-W9oEdGnkIN/QH8RWVLi9bgznVmlzLLpYqM/d+bpEA+k
--> ssh-ed25519 YFSOsg ccuBr0eGaJ/t2lWMhKNP/c2TtpmGYaenxQSQI9DJv3c
-uLGi3j4gt5xRj3MOsLUjkkA9dCS12feyLQf1YZtDvgg
--> ssh-ed25519 iHV63A GHevWTk7/M0TtlIo/uZnCn84jq9I2jP9ehkt6PxRgEc
-nF5O/yCV/3zduBtGw6VbwPS2jFHJlUgHiSytDOPSzaU
--> ssh-ed25519 BVsyTA Tw/06YNSoYYlrtfocjh0pitrWJc8zNAr8RLc42mMjWI
-RaA9t5VwYWYHFquZuXmNrGVkdDOJDh3dgVG+31UxhM8
--> %zh9-grease 6 rETV7H
-1TID2TYG2RCwwRws8vOvdfDM0zQcqRTDqfJbZsbOAiZQnOU3Lt8g+rwcSgOB7kX4
-lx5lPRHxCa+86NljA+tW5l5u1JZurA
---- wBDm8U0KDrRkdoeUfQq0Zk81611Im9hlSo96NE4FB9w
-ȕ��7��]�DB��ўܳ�D[DC�����J�JrE+ݿ�p���3x�t�J�LӲ��1
\ No newline at end of file
+Xlg1Paj4+EwLyqpvns4Tr0p6HldEAlGoXpWjhHDqyoTyu+afNVUlEZSdKZIZkuBA
+KknOhHd0F0WhEGA9ieA4zzRXQtT2IV1gZex+sS1IQyHskBzUIQ6wSGa7KGMwzkOB
+abDFCqybdbcgEtSt2kunAmDf62poBMiI2RAL9qQbA9qom53ekoUk5Ge+5EUW92B5
+HLnUwhj0j/D4sRL3gnNuZnXnxQAaPHr0Ojcjcx61XoFy1wUrZltVRW6X92/1diXn
+rulEuxVssOqWEpHi3dYaWpg0sJgrPP2K8FZ76Vz/j5QKvARXW/UeSwUeEr1H7cSi
+eA3IUB9SHIlRwVQOlrNa2WHj5v236+VQqOBQewwLb/ev5lE4TkA/HtHbtwnjyWWm
+P/pXXNDcFm7gA9FnzbUe+u7rbSdyZDGYff1Jp2xn5+aGsUUPmCIAJBlzOe/+RqCY
+03WUstGZ5SBuB3bC95IMSa8pwtNKDs62ZXqbe91GaqzzzYbsUeQSJkfKJkqRmRlT
+wdXJHxV1Ot7ulStbArVULrc20j5UESqmiJuQnqfd9dro4pMppcB+lkibFJS0Wm9A
+PGuHF1SHZoWCJA1tOccli3SwWcfXNQyoJ6Y1OGcHnt0lX82LwjOv/Fwy7QB/N5x3
+xD2b4BekULFjLPnrO3n5xhLxZWT20VWuVjVhzPKoqxg
+-> piv-p256 vRzPNw A8RM25Qglq8NFI5leRtDZZID8uLH9EMc6AayAqxxqWOp
+X7WQdS7eAZZGZPQtJpdaYonqgsz/fFRMNeL9VF/IU9c
+-> piv-p256 zqq/iw A9laFsikY0G40GXHdLPbpwMCJWz2vC9wojcY2rLmCO8R
+EjSFWrhl2n4hHO4o04NWok5C7slm7Bj2YZwKrtjiEdQ
+-> ssh-ed25519 YFSOsg 70Hc2RsbEeS38yVGFFwpSPsvaG2soKD0c7VkrqukPg0
+o7/Ok5BWjV/9rTKGOzJTHLx6IXBpq1i1ZlU+NvSw2Fg
+-> ssh-ed25519 iHV63A 2g1462VDxZN2eNS9hCSatW0BrX0FytjUCF505fCsHEs
+T2sh+D1xjtfJ5s9G0VChOsYRzcXpzKX9/j/HsB5c+Fg
+-> ssh-ed25519 BVsyTA WogYDmweYRM2ylkgvjtKx7etjFLjI5IRKFgA49/1xgQ
+o2HLBLoAuplW48b64xv4I6vD89SQbwT+uzIrtWo9+kM
+-> ssh-ed25519 +3V2lQ 2oTDm1sK6VVD1dxcjg8H+zYGPIyVcKklOiX6GFUsG3A
+ZDbhkYBEj1mx25GeeP5yCZt8S7iNbOcUbFEU+cY3+xA
+--- ugYfMD7r7efVTdPdzkplZSWjq/fC3luecBPwwd1AYbM
+T-@gQMG�� ϊ>�������Y��D��f�!�ǻ4�G^a��	ja�<w�vQk������Wk�
\ No newline at end of file
diff --git a/secrets/metronom-root-ssh-key.age b/secrets/metronom-root-ssh-key.age
new file mode 100644
index 00000000..0a850769
Binary files /dev/null and b/secrets/metronom-root-ssh-key.age differ
diff --git a/secrets/metronom-wg-private-key.age b/secrets/metronom-wg-private-key.age
new file mode 100644
index 00000000..d813e2a1
Binary files /dev/null and b/secrets/metronom-wg-private-key.age differ
diff --git a/secrets/nachtigall-metrics-nginx-basic-auth.age b/secrets/nachtigall-metrics-nginx-basic-auth.age
deleted file mode 100644
index b84edc01..00000000
--- a/secrets/nachtigall-metrics-nginx-basic-auth.age
+++ /dev/null
@@ -1,31 +0,0 @@
-age-encryption.org/v1
--> ssh-ed25519 Y0ZZaw FWuk2kYGB+GfoY3rWfeCosoBOLvUHrH7SR8Fv18o+XI
-YyOTULtyOJ3vfAOnYSMzeCCyipJ4Fqrr3PJgRtbElJg
--> ssh-ed25519 iDKjwg Bq6lNuS5MOhsU/7ypHw/E70BktIA+SmN6e3pvrIqRBQ
-Xo0OOUXfOkPQfArhqSJyiAkH5lxcJIAO7M5krkCZNfc
--> ssh-ed25519 uYcDNw EfB1B4CSNk8Oe5B7T+KSl9O5OsCrulaLOjR3PBtxpSk
-xJxkmBSENc5JosdRiEAC3a41WI6TmTlTxm+lclup+g4
--> ssh-rsa kFDS0A
-dYH3A43wClFnDQp8m3ZnhTK5d8LeG6ZkqDQ5dS1yB//4G5TaUnMqOp5Q2G1gbgXY
-Zu9qYOHdUydn5HIRSwBXj/KbBm5xJ1zFImOszn7S5mk4iReHFyTnSzAi4utatQcY
-DEjGnvKKRoc7ih08+F44kq6DYnhUBFqF8eigQZIsyeWpiW6C1FzasL0KnXoedPG2
-AYJForNB8zKp7a2Evxi0MY7a+ldHAekktz1Fta2u9MvrWUtqP/yLqJhCwCNvos7J
-kG+XO4j0kiOQCIO9TOeLAu59+VCVM64mY+dp+xc8tX0fWuu7ItSAh6jRHzfgSKjC
-qDJc/1YpUG1EnYSH39mfVox3ndeMuVrG6Q1h509jZuxsw/zoDsbY3bbhTaUQ3X8Y
-5ShCponnEGBLqeSm1gALCAnlgu8IS4gL6ePKuAhN0qMYj6iiXP/Ugp3lTcv1TvFD
-KINnV/tas1CO3PApQm6JgijHEPT9zyUbqR/xN06+OCWbg4hHuEix+0OhM1T5w2xC
-KvKF30iUK0tU2hZvKdku2MpbP4N0cQLqBEWiyrUKHRMCdXi3kyO5D84UdWXvETAt
-BfEvZ8ZG5fiSXzbPLxVqObXFZUirLuWomWtstqkDuadL9xJkTcsbr8ZCCNpPhxdL
-oOfao+tox3RBilAS3AfQVhrPvD2rVUptm+0nPtnO3rY
--> ssh-ed25519 YFSOsg T2OdtA0kY4DqDIxE1QxMV5aCygvKlI5LgXQ+QYYuOko
-l0Kzo02jGISCT1zrGf5soXYj7FMVrN/9REF3Zscbmik
--> ssh-ed25519 iHV63A 75daRGD2TQ/mXRsckaH9sGGkHMkLxgHFhn0eDdkDsU8
-TXeoLqfU0ywQucPayYoG43Gr56uZoYIWaK9F2YJJ0FM
--> ssh-ed25519 BVsyTA J/xNtG1CAzfoiKPsnWwDp4pId7d3MywXpfhKAmpze3I
-8uMO07Se/6krP79flt+XZfjIsw12kWsoD6LqZyLG70M
--> B-grease y3$t@ ; Bs *w
-dUrvWB09znCDyvO7RnduMguc9pWTn19q1fc0MHFUXk7WQWns+4kpJIX1qljB5hz/
-NPAbNzwMDQKj6awHAth1iFLaEw
---- rI4jrrXCiUpV/EzGsla+lxONmL5/Eel/LODoIM80jcM
-�_�0��7J�q�[���'/����i�܍�l�m�
-��!JP��>��wk�����+ �)��PhU����O=>k=?�T�
\ No newline at end of file
diff --git a/secrets/nachtigall-metrics-prometheus-basic-auth-password.age b/secrets/nachtigall-metrics-prometheus-basic-auth-password.age
deleted file mode 100644
index 4ce287cf..00000000
--- a/secrets/nachtigall-metrics-prometheus-basic-auth-password.age
+++ /dev/null
@@ -1,30 +0,0 @@
-age-encryption.org/v1
--> ssh-ed25519 Y0ZZaw CxhF1nK1+6OmJb/68UQ4mBIqxGgr8ngkNsL9dfaPN2s
-jZ/JBaTCjFcL0SAGVx5ECDanVn4TGt0g2yn2OQOP9iY
--> ssh-ed25519 iDKjwg D/xqqA53Lw2UQJesg27wmK/UNCV+s914mvMlbKN1rhg
-AOg0SkPvSotuSHk33zVfRxB0wn67a29YWc/itDUZ/LQ
--> ssh-ed25519 uYcDNw /QdfQUJmBMQZ+KRCst1gA0LqFGvM1K91ZL/RIRP+qBc
-Ttksa44OdwLuRmgYPC2rIn+wy/SooRPUq8gQTR+pF0k
--> ssh-rsa kFDS0A
-L9MGJFRceqbge3EF/rqXdT13jt9faxP1NmfRB3i2mrTasvCaovc/62bA0UmlsB/9
-Y3hIzo28d6pZRcMm91l6PhWV0M33YNwPQf87vd7klv++1aMIdZ6/jHsQiohIBkRd
-4pBe6rrx/lUqEqfQVYUFPfRE50ufkw+hRw/NJCvcBgHgNhhDoeb8keWRPZhhuv0Z
-f0eP9ORKjeKxjv3tsIPjiE7aqxE1zTdrnSr7FuqklJhMYRdwVv+2ofNEh05hU6pR
-VL4AS7d6Di/0dWTWc/Je2ytsrdio2v0rPAUXN1fyTh4AtrAmGQzUXNWnr4sB5xH9
-QlL0Ea3IwndJSDNkqc4qI3JL0vx6QMUbsuNcMmVWSMkODP+gNQYXQNbnwNfeMAnE
-V++WBfyrA8+V+ES+usqeWoOXjApzShn+gnrV0DHHXDAzNR+M647rQcsLePSyNjf/
-NKd7Z8VfEq7m65AxmSHPezSGdICMf63WLG/Bffj9rWiQxaoiayGF8jbALpXlu93X
-txOw8pK7zA8xFEBujmkrDPH3sJFPLOgOMYa0uuCMbrCGxeJ34nuQMhSUTamESSXb
-AD3AgUrRvte1iXwy2PoZGolRLZfdq9zcAfFyq9KvIhvz/8b2F+KbqHQlAiKVPw8p
-XQo4sXcDAmF251WSCJGN1C6Doxj/6XLuWILbkobQqoI
--> ssh-ed25519 YFSOsg FtIvWeEXI9blJIFAWMacXgPym5ePGXsuiOR+Gh3b3R8
-0rp/NIu4kCCt05Is2+eRdUmgNX8QPMsDPhZWIejnBDA
--> ssh-ed25519 iHV63A 85G1w54UHS/gFcLvsXyYLPXvLHkJl3YQCi8ehb+ZrU8
-lXDaMXlPw5ohaaYpiEkCNAmE2tJ2824ydmp9EakPtD8
--> ssh-ed25519 BVsyTA XimcaonVCGGyyCfn3BSX/a7zjJkWeaVY/xAcdNDrl1U
-RaqpXzUd54qrkYYRbRTUclTpZdZx2us42lkP6wBxjBM
--> CWM8^B-grease
-HvBgzYx54YVP0M6pk1bp9qegLscQ4tHIV9DZhr7jnrW41adgY0D39wnE2IgIRc6g
-keRHAr7QVqdPy/kr+u0GwQ1MGFKI8Jss8vRxKwv/UgQfmg
---- dJWXhQRYjxWchTW1u3TrF7KvQIOdrOvkEC7oUtFcGeE
-l>qT�Fޮ/��@t�\�&Z�	��:��@���K�x��r��HK�ĦE�b0�֗5�m�/
\ No newline at end of file
diff --git a/secrets/nachtigall-root-ssh-key.age b/secrets/nachtigall-root-ssh-key.age
index d1514e6f..97f97489 100644
Binary files a/secrets/nachtigall-root-ssh-key.age and b/secrets/nachtigall-root-ssh-key.age differ
diff --git a/secrets/nachtigall-wg-private-key.age b/secrets/nachtigall-wg-private-key.age
index 325b1315..89148702 100644
Binary files a/secrets/nachtigall-wg-private-key.age and b/secrets/nachtigall-wg-private-key.age differ
diff --git a/secrets/nextcloud-admin-pass.age b/secrets/nextcloud-admin-pass.age
index 66deda80..48989235 100644
--- a/secrets/nextcloud-admin-pass.age
+++ b/secrets/nextcloud-admin-pass.age
@@ -1,27 +1,43 @@
 age-encryption.org/v1
--> ssh-ed25519 iDKjwg bydjKoMlcmku7EeLcXflr3Jtjttr3DHhxGz3EwFS810
-RULNHIfG1ueMpePeFe88QKElCRI4Co0ZuoqvViFxecs
--> ssh-ed25519 uYcDNw vOSLnWbhNa9jo/95PrtI+XrS0Pj7CdhIZ3TWJSbQEGk
-AmIGuPhrQVDJcAx9T6mg/RwRu/DIeeGjmzlnnXAa1mk
+-> ssh-ed25519 iDKjwg fP/QvhTudXqItdTj4mdIkL5EVmRmPznW3DqWYIDjki4
+1uQ3MrqMUCL+L2vd3FK8d3ah/SDpTQTcRUviEFtDE2w
+-> ssh-ed25519 uYcDNw mOBbRpGjkczSIJ9FZYrLmKTFJ24I/urhdCc0pMnTblw
+MsTWuQlBbtTWcQ0GJVKnyvMao8kAtb1WmREvrzkaeeA
+-> ssh-rsa f5THog
+PzUPFnuQwW2aYRRrB3QglmEZkO7k1Q9lUy2STG6P2IGMZTuD4KKvBUrVGFFGoY4R
+lQpT3Qe+RK4FTFckFEQM0GfZ5/6eiRF6RTMY7SQQ8eIT8TNXo2aNFSl8uXdUb+lb
+1DtyloVIc6+tozI9hqmoCudJSO4iy4Rrcy7XW4wLcPoh/Ef5NPdCFB+s0TS59led
+wX1RNEmYqCS1oi9z5+aQBRDl5QtJyesfPhoPCe/bEnAkf2+vMx6EDMPYkeCDcdtD
+zTpyACEh8SLZ3eNjNGT4JeXFTFgTVbajXnel/t+eUpcP2k15YVfZ8Xe+RqlqFv2x
+hKgiQT9rUX0jTxdadqXWb0iD2z6W1x0zzAi49rvzQ3x4r5tpcIj3Cf8hbqIkgW9h
+Alhs8wDFBtYu1NZPw/N5timH1B1QgZM0RxBMMzqGN7QvMz+yUsVhofhFsW37JKsJ
+O08+LxthLxtxXW5H+jVhn70d2At4hzCWD7CmgqPeURzmHeKf/d3vJKBpfA+lwCPd
+3AE8NRLTNLPTBT6s9bXSuAR2hikT8NTGw2641S0kTkl/dm1dgDpLNlJp+z5jt7Vi
+Z247IKY7dGLGJ7fiSDBjkRyls8XZME9irXlflFZwz2CWGiav7WW4ZCH+ln62xZai
+80Qn7XxNOI5QjX7XvU2aicK9ADW18TPT0gDu5l/gby8
 -> ssh-rsa kFDS0A
-fDuHqn9LdtgpO3AYo07P2i9rewpURoco22wY1SnDhEHls7MkFBqPUTO2EAXMc+OY
-tZSSs1rREZyECH9DG8ngZ3E06t/Z0Uk9azr4RDaFmhzh9rb1KFCJkpLscuDDO7kJ
-OiHT7MwNuRPWZxwT1srxX2T3jc8jKFlNUXsOpQrtzRqKWmeKbOJzpNHjmUlrvw3V
-fBnVN0ai7vlvo1L9mbTgQpu+3/08CKvE7N7rFteNe+jYQRLC13iI3j3rHeOj+UVE
-09rTqwijRtJbkTBxt9hrFDUSA592akYHuKAt+bklbQQlFHZ9bZScE+P+mAC1+ySB
-Q/XQhTr2FOO3G+2ieEOb0RGekozOGwJB3XK0sm+rVMsfMhtU/+nfbQGydFIkTgbq
-BKnAk+l94h6F3W3WmpOQTBbYVlfou3hmv2aodOYfFYpUHi8kQR0y6dFkARU//zz/
-cS8gs7w23JwGinBVSfsISkCMaM1/lnR5ZRnYtHIaU8aG5RAZhx39+vjBYHsJPKDp
-DoaATj1bskIcSTzqPIu7s4B8gI9MuEid8eUAjgBeuxAJCa59k5OxbtVAVx17DGn2
-QkLd/kn0xrJOPyY81fjqS7fapq9+gvxLqdyyznPQA6WKkUJ4DumAxL5lLq70a9I/
-dzk/AC5Jtf6SxqRzX1eUJR5SGI5aSJxo3Hih3m6nuLs
--> ssh-ed25519 YFSOsg +N6SyzhtCailgt6y4C4/0mlGjuxWS0bWHakRX/Bbliw
-bkQi60J0nfB/ujoYu8SiIxXp0Ff48MuNzoW0/CDd7AM
--> ssh-ed25519 iHV63A nrHBLzAxmvsxKvEKH6oqS0XIQ1K2kFmPZdOVmzKT00A
-R8t/WCmvSO9SBR4gDxfNArdo55NuolHCKYRNtF5oPTs
--> ssh-ed25519 BVsyTA H0lSXGJX+7TplHCmePj3AKeHLf+6GnE4pPKc81fANG8
-ESTz1sB2HWity5dnao69KuFBa5JGeTEgkqYg8lFQICE
--> ^D4?-grease R ,*WNbA@u l$*s}U|
-9LAkmaox13NiExiel18LqRT8hUryLKA
---- VuPVAYEmjv4FCkPmiFUCqdtznMOSAGslqarqFZnibuM
-�N>�_m؝(��$���j6PDBN�a�i�Յr�aф�$����|t�;��CLx��
\ No newline at end of file
+kH7ZVFtU7xEakvDPzYo13XOZSpfoz+lJ1ynVU1cKFKdf+1UUGSZPHdWEzOwpwJtf
+ngBfKyd0WKqn52A0CGkb2KueFGaPjdzKmTW3dtKaJunWM3Cl8lo0n8s1wIy0T0nU
+OoMOotsQjIHdJ2tcIJEGZ88wqPyrB93tHJRqplI+Exkz9Rp6frXKiwQtjpYTalyl
+wp8/AVRnKUVfgdnc0gWEEPHxo1vUGaZndbetopJW10iETHPDxLe47CyCgy9QolQY
+NNb4BsteyGarejGccEUGl6sS61hHoesxkRsQxi1bSAfEc6mVkZlniyyx/Dav2pdT
+76DsiROAmlzPOC2In2Isw4VzVOP6TZfUmS/fmsmFqvWw6VX7KDBzAqL+2d5F5d0B
+DlNtO0CGCglx1OZCyvBogNDbJMDKazRdHdjs9BrQR7DNfU6GDRvQLaAb2mTxjIvg
+FBJle2hB6/HXn6pkUhzbG3L1RpxflCxEU4MMxhoIz+kdur5D8Com1AucLScRQxn5
+5W7eYE7GQPCr0+X61IVW874Xg30AEVI9+IO6GKwPLt+NhrAoTOwbOFP1qtshe7J0
+lAfjrWdhVA5xb8T9C1o/kn8JRn5QBHsd74FFJgp9GioR4UjZRuW2A95Khjt533zf
+jQy5tVv2M/4Lst2Vei7wNyfLYPOjHP1b7GJno1MCeno
+-> piv-p256 vRzPNw A2LUP00+OanZ0DsuNDJIWJLye7Rj6D4O5l2c/DxXJvIS
+qiGIvKZBQRNfkTxBs4PXUK1ubPqvZnIVsApLVWV6zTA
+-> piv-p256 zqq/iw A1LbBDoHW+3Of5u91fVcsvfGfJoEuZpcFE5iRSdvRUlT
+QOU8dXskXIuChFQG2kk7YRvMIWSpU2wMFJQW3NwXmVk
+-> ssh-ed25519 YFSOsg K303rWahxhhuzyHC4SDDodElpVc0gP5+S/qjmNUhVz8
+LB+gLm2t5voR7d0qBJhREUMan7qn69Fov9B9hbXGKLU
+-> ssh-ed25519 iHV63A H/1/oiZb5C+6mijnevPhubEZfDpoBVaauvyL8dmJ910
+BoXHVRpA5ZlK1aEkO9ZzIDR+l1/RJs3ImpMO/+sJNZg
+-> ssh-ed25519 BVsyTA pjUGS/DEcAqV17vhkjUhewhDQhLV9yZH2rqq2SQSHy0
+Oxkjnv+OZCrGCOVfDeNej6qUT4jZxyjceFP6tlijV7c
+-> ssh-ed25519 +3V2lQ UqX3d+JlYS0xJ7gFJ/t2QNQ9ucZXjzI3K0vY4fZ+RyE
+o56qzcOMLlze2DXb6ACPBCkstsvgSlGGaled0XDJ56c
+--- EjD+6iWa92FuISe4UOv56bBS8YGVeHuq0nJ0VFc91Qs
+V?��[5����6�[e�a�Tt�5�OB�f�঴=���!/�8��ë8�{0�wb0�>�8rϥl�!
\ No newline at end of file
diff --git a/secrets/nextcloud-secrets.age b/secrets/nextcloud-secrets.age
index 6f3d10c0..365173b8 100644
--- a/secrets/nextcloud-secrets.age
+++ b/secrets/nextcloud-secrets.age
@@ -1,28 +1,46 @@
 age-encryption.org/v1
--> ssh-ed25519 iDKjwg Qpq2SP58ytg9NXD8eYvlgvVhaJMOQVnTxhDrydMNHjA
-V6ES5O5wFL52G4Oc4dGFWkqdFMkb3DniEex3a/fljj8
--> ssh-ed25519 uYcDNw Ll11H3DdUax5iCn6QNz4zZO7+R6ied79GEu4HEfXujs
-G4TE/qDl1deBy4g50lNcKKVNvFxxj+9HpgYKVHt2km4
+-> ssh-ed25519 iDKjwg EXCgUdm27axa8TZDO+ZiySsVc7aNCDqQ+TickiWNC2c
+d6WJGnev9aYPyZ0dmk8ZFpvv7y2rka5Q0LJ5lb/eIn0
+-> ssh-ed25519 uYcDNw jnHHU4AtaOQarze50D5mG/uyLxBwC1V7ywBHKJje0Ao
+43P37TLihVw6c52ptgZCnULIu/YdTIvUZ/wuAEl000E
+-> ssh-rsa f5THog
+OyyUBphnjdosEfSzeKYpa7R24g5nyZJRWr+ead5RUgNx0G/+EuwLGyRJwC0OYrg/
+39/GmhZrSlX9b1YjtXSsKPASbehEptOd+wtDXVuYECsKxRrryzqWOPckY7IkOz6Y
+ovNeMxJnQ7X7nS5u4kt5U1PDsCeIFH0X91SATqGsQukYB94w9te3LfF0YhQ92dRl
+r26Id/mwLm35HUHwOPqFLdx8b/eIrSnEYiSNWuA2PCQzxnq5o5xo/71U+CsQdFN6
+1otdnhICjezn0wLwGHyVI1Q0Ptz9YooKcCTcwIB1pt9oZhpCeRDfvodGbNdqEn78
+onMme/+bRb0riRttNaKktEt/fTQSAFQX8s5ZT+LFzRsOESGXwxmpBa/yQcX8ZleW
+UL7JYzgqjTXBd0ly7cTu9wtuRr+DXTdeB/B2LGYiT3ewSYMFViQh9fTY4b8ZqUfB
+H9pt0hicpv7PK20joqhPO3CNFhH/54SrVeFZOElGvdIjuM6+BGLRScIeEWi4Wu2+
+YS33eB+K0Tqs/Rxz1vorPOIij6FFuny8W07AUFk3khpzgUtjvYP8ObKdqFdzMbA0
+NP6H7+8FYzwbbnpMguaTvWL0n74ilC30nhbAKin+HcCxjl0SPfA3Q9xiC00nm4D8
+fdcGwxxWVC3eIjd9ng8xEZDnlG/SENDOkfnB6U/rmOo
 -> ssh-rsa kFDS0A
-gtXlJkXWTs2pvW6sm+FzDo+WaEh2S2ttIflw7x4Jswqaa7b/2VbnHn89NyYNG7J8
-+n/Un8IbG4wh7hVsbhKEOZA8S1BC0c8gXwLoexgF21GYmbWGUR5xdbhVIPnJmJpY
-IPgp7Ai72BEv782CjAVlAORVNzr0umtfq3PUlq6NXiYiyb7MT5g6SNd5Avy5r73s
-bUZWCUW6m63kDRoVNgfGhrSLHFi1AgLroIqhuuOiRWj16lTUVxh2VkLwRPERy6V8
-jUpb9nb1uAYzMMeMSAvRM5actTJxQA+5chSXUMhp6MR8XiB+EFFRpIDkcfs8O2Hi
-0QytXBo3W/NBNLG2RUgLMfq2mnI3bXXvxJZXKfmNxE6e6RVR6tSg23LlzkFtmE3c
-DGuYYBz3h4yxjkkjvKJ0VJ1IhQ5wvghdKs7kM+n1wHNOPBSKom/84uyHDvPrTr/0
-7S4Wx12l7DKZtTzv3UItPmBVRSEjbBOMZpQo/13rLQ1bx9WBeVVNSqjpy68W0Dlz
-tI3oWX9WIPDUB7xyCXHebkxGJ0lBrza85jnFt5zASbHXeq3pbo7rjPWt6c5oWuiJ
-X/OtIXKp0sxeXEgiOoAnNn+yVPBm/9b3ote+T0MwsVVLXQ3HCsYA5mXZCfRK5OA7
-w3nqorCBnBCyE//MCo7j+A1W9HKtDKAJltwfhemhtiQ
--> ssh-ed25519 YFSOsg kTmy8aPCd4THlnO6SWyW+Ifc21Ggau4fxdiQkjyvNwA
-Ck6dc8IpHhnuD6FeHJ09vsdcgaoDfYGfqI5bvYV6CKA
--> ssh-ed25519 iHV63A lHVBVGdvw1yp3huhqfGstff4UKRHp4wmbGpZPJxHjwo
-eWqfE+s06UgBSK0m9/GWWvhFf6ZcsN7vsygnxeXBF7k
--> ssh-ed25519 BVsyTA vUCYL+NZu8VT8G+bkd/LknxH/7cB3HwOalTZ4Escghw
-p+RZhqg6voORDwSwWZ962NOpIn6kX3cryuhbqVD7rzc
--> LzOpAF&-grease mZ4f4.74 8%Wkxw
-i6KRW+yK4flm+3fDrVbHAIMNzcbqErlGKHoAZJOwYrhl0tAaZBLk7IIPQ9bas3WQ
-ZbJ6fgj/YYbgRhX0jUcmNwv/5tI
---- 3bobJwE4FKDA2SnlzdzzTfMO8NU5+PvG+5of6jN0eCQ
-tF]+>�`]H�����}�T7VԾ���`������!��&]��Z�^�#����ى҉�]�i`Tk�|�b���Rx�&�^�n]��.�|Ѧ$ږ�h4��KL�0�x�^q_P�^��`Z!pc�B1}М���x��bYv�����"�QA��N`���4UX����YlЍW��X�e.��d�r��[S����폶Ħ,��Q~C��W���b�3f����)$��_MkP����(PdxU�o9�9h
���Ka�7��
;�������M�
\ No newline at end of file
+nLXxu2ApeHNMWCCQrTBJMoct2WpxKVvq0E01hgpczztKAS/hLrkXyRJOcKr5sPYr
+zOLTrq32ke0pW05UmIe49ZyeqwWX9qt+Zt/Ys7IzKTxpY+PeFV9aSRFqqMMyGAne
+Dc17haB5zI2Rsu6fkh4KsEt2RBFEHSH/Hvo4MbTxLRxCWMUY/8SanIYzpS7GbYQT
+goxjZ9sR5ddz5m4dba80d/PfunZHSRWpMcgIbGV81kuLmF1F3hcV/W66ur8lxnZL
+mlKNKyuIkhLYMWrrhBuLrrgmaxzum564HploEpAyqtUk04gqL4dLmHdNerImoncE
+GJsdMGSZmiY1lE57jXlnd5MCJebB7lJEKVn4/EqJxfWvwi8Qv+OV5Tj/S2azkcx7
+V1J9rjxO32LvESRn107cg9rZCcC+viXvgaPH+xPebQX1d1DzEjU4Q5YwFhtKriH2
+3BhuAG9qWN52NTjAR8U5pB60Z9wmtQ/oV2yS65g4U1O/URuKGOu/X/RJiHeWaQ6b
+ZSFiQmNOktfjkfSWvhT+pIwnMlz/mh+fkv1bc1IkLE4QNWh8AKfrkYGJKTryW3g5
+SCdVsw+htaP3NyrUZs5xK76O/8/yoDBtCzIYsO2wUXPGtSMu6z+8z40aI2RrVMl6
+hscfOjYZrY6HAxsEX8A6kN5BjSrgvSGHxg67ysRZvVQ
+-> piv-p256 vRzPNw Azrkr39IW+mJaJkMtCKcwXtQzE+ikzkM2+6mcv6L10rp
+zDd2I5sG+ntBmcG99zp0rXt/Hea/cdsllPt2oDwPIpc
+-> piv-p256 zqq/iw AnbpectilqGTEHiiPW9fjN3MD1+qfLKPC6tZSvuE15HD
+fWaDqLGIaHuv5Oe3EuvJ8g3wIkODUr2txmNYqEYE+M0
+-> ssh-ed25519 YFSOsg bCaQZ88DIrfYeaH+ZjY7Mnng6yJ8p0YkfN84U7v/Zx8
+Lq2OLI6GXz2oCuTxOYr2s5pmOVsrngHsNBlbN3aIDyk
+-> ssh-ed25519 iHV63A uyxi7qLjlA3M/QTIGjsu47xz2EsHDwLw6Als/IYlHyM
+rYg+sziqw/p4hCF5d/D7HGvVSabu21gFUz27FFJfs3w
+-> ssh-ed25519 BVsyTA DDibYPj2vuAqG7MvAVlBE6dmL5cWzhwEgVG87GSfA0I
+n3xFZJI3HHOffST83NvdG7jY9Xebs0EasC3D1QXjSns
+-> ssh-ed25519 +3V2lQ AVE09IqLBLLO/5zLrHAwDl9e/w5JYfnW2WNWQzYW3RI
+z/+4Jpqyl9sMJgFJ8ST0UsF7rqBaRhXHwPnqKMVWbxc
+--- x2z2IHrcFUKwlsjZWw/hqp69zqS8Nt6X3A/cSw0khFc
+�	����s��9�!.n�5��ٶ�ĕ}�dwGF:/Ԩ^���A�`��0L�E-��MY=J�(r�2�Rc���w��%���֗�$��D��4G|���	:Fq*�Nk#of�J�	7�?So�c�QS���/q��x�V
+?t�nR�@�Wc��F2��$���2�4=çx@��8!��b5o�{��j?,%-𲙠�+��a�H
ǰ����8���O��s=S�?gCz�QsZ�M�$U��ٚ�h$Q��y|̋�g�V;��?-[=!+
Ct� �\5���Rm
+��
+�)���
\ No newline at end of file
diff --git a/secrets/nextcloud-serverinfo-token.age b/secrets/nextcloud-serverinfo-token.age
new file mode 100644
index 00000000..2d12f48b
Binary files /dev/null and b/secrets/nextcloud-serverinfo-token.age differ
diff --git a/secrets/obs-portal-database-env.age b/secrets/obs-portal-database-env.age
index 0286690a..abae89c3 100644
Binary files a/secrets/obs-portal-database-env.age and b/secrets/obs-portal-database-env.age differ
diff --git a/secrets/obs-portal-env.age b/secrets/obs-portal-env.age
index c23caae3..63e1bd0d 100644
Binary files a/secrets/obs-portal-env.age and b/secrets/obs-portal-env.age differ
diff --git a/secrets/restic-password-droppie.age b/secrets/restic-password-droppie.age
deleted file mode 100644
index 3fdc90be..00000000
--- a/secrets/restic-password-droppie.age
+++ /dev/null
@@ -1,29 +0,0 @@
-age-encryption.org/v1
--> ssh-ed25519 iDKjwg tSrbeVPpTxjeuCg6JiOdeIcaGWq/PUOyXrt+ZNIWmzI
-fz4B2nMu36G1DYPyNiu30Txx4cOLGyUreuBLqktORhY
--> ssh-ed25519 uYcDNw zySKp8qUnCKOCbIP17bWYvJ/TsKxLl/v/AEsfVQpHTc
-SYqaUEXJ7mSA2wY6I3i/hirEiqvXVnWH1NYtXbaMzbw
--> ssh-rsa kFDS0A
-MiyJjq7nn9B+PF9Lf6vD496FZUnUy5zI9H2kunJLhmYnr+7ZJaPGI+MW0cuPjsmM
-1XhmUC72zA9WTiuReGijl9GhIyU0D6vPx+ezQrx18dUGRJEqnvk5C75SCUuPGtUi
-DamPxJc781mnDSyW91MgRrqlBVwhfJ9Zmws3+/j8LODWb0T9Jvy0ywmFX4ilapr9
-6dqbNmwBZkfh2CKB9LtMG/DuSNicgHscpt4Mt7EogJRdgBrGIcA1u8BXUOwf+R8G
-Ya8VzoQV0iVhGtbff3g/6/0+UX9KEZBQc/aiT2ItrgUmgMyjAZo13Dj3pD2wPdfa
-t346symp7bcYxRea/U0hfmPdnixIKgBLTUZkzrMFza26QOvnSwiMxWY+//Vmbp3z
-0YCsyOQTQJVB+Q0pYE0+9EVI9bInP0LxHhM7mIdJroscRtY1YphjZUlFmcUXk0iC
-5g3/wdLr8KdT4aZ93m4WVgkBUzg8chhfMHb9uFvpHT9xeZHrV3u30TuJpmmuqMXK
-JD3+9xRzNVHwvfZuhD8B3vkK2tYO7pTxJytkJtdolx/uSju8SCm9F4lwt5y8rQd4
-7676QS0IWS1WItcpLrsgk9nWZUNzy78gBc39jtJUOsFDqJSdAWACq/jgYpnx6Bja
-5aZonRAp3fyCEavUpS4AQUJZGVx9EFp9LqXeUiIkCJU
--> ssh-ed25519 YFSOsg vJ7xw4zDSKBFuv8FT6ZnB83uGwHDnDsEwsvQ6urZkEk
-gOkuwjOX8U/qmPuGrPPb+FYy6PuJjrgCNFYrukkaIPA
--> ssh-ed25519 iHV63A FzZRHQB39iDTLm4y1QLWtfDi3jZn6i59nuSlf0d5mww
-5kiyKN7KFTv8pJgRAZTUMgR2+TInByFotDhAw307P6g
--> ssh-ed25519 BVsyTA rTjBaEI6AwwmpK9Q8elVJaSN60deXOMEmZPrsH9O1nY
-HikNbHzx3BEJ3hn4YPFr2p/cnSu3qr9cvgdKCxN6xY8
--> h|2u%UF\-grease Gcp2NG
-y6OjgzrOYEVgrY2+fv8a1xrVuoHQIPncGuGeLI0zHh4xf1qbzD2vKYp+W1fRBE8d
-/yPEGUe/T/ZjO+F4oF266HUR23wancFeFoGpfJgWQVS2oc0Z4aMuNebf/+Kw087W
-
---- GJBLNxBoH7vI1mkcCmfbm9UiG4xuwIOWS7IaJKuO6cc
-C�3=�,�{-T�����	�-�]�̷��q=���
���=~}�1���l߄�f��_[�U_�A�G.�d���r�a`��Uy�Pt+̽����!<
\ No newline at end of file
diff --git a/secrets/restic-repo-droppie.age b/secrets/restic-repo-droppie.age
index 11cdb63a..ff6ca9c5 100644
Binary files a/secrets/restic-repo-droppie.age and b/secrets/restic-repo-droppie.age differ
diff --git a/secrets/restic-repo-garage-metronom-env.age b/secrets/restic-repo-garage-metronom-env.age
new file mode 100644
index 00000000..6a93395f
Binary files /dev/null and b/secrets/restic-repo-garage-metronom-env.age differ
diff --git a/secrets/restic-repo-garage-metronom.age b/secrets/restic-repo-garage-metronom.age
new file mode 100644
index 00000000..5012d17d
--- /dev/null
+++ b/secrets/restic-repo-garage-metronom.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 UE5Ceg HPvb1/RbiQHkS4ZtKlVf9NHAtMqjvvPokEagN2WzOzY
+VCG4q0DryDmSShE0f+6bc9cQTT9+GzTQiEI7pZMDO+M
+-> ssh-ed25519 uYcDNw rbqTP0+fDf4MdaBQ+pdZBTM36tyYU09vVbSJRDO5IU4
+adhbFdWIkTOXVXYNwaLU5XBfAAGjwty6k6XV6wE+tbw
+-> ssh-rsa f5THog
+fFJ5sambnBJgHwnihRtdwBUPZ8omT+V/usViUVXcDO7neeQExvD4hszto4uwBjZP
+ovPb8BRAVCHvb7eKcMxP5nnjs2BJLuNFIsnCn5Iqsn1dS8bJ+Z5tQ1Ez9ZP5j6P8
+Rdq+SInJRQ7PzXkDXzQ/7m/6Wm/m66ljlTHaOE2wKEpOLTWFVHcC0PRqdSTaLTvS
+lStsl48d0ixb2GCSZ5Q9xgBjmtnOZypOGYzq0DrYesbvEl0JaAtlFv1e6Gi6WxGd
+ZRxDVZ//1iUgPotFRCys2BiXGlp2RehgspNVgbAHaEkS2amg2Yt0/dQdpAg4ICWn
+u2m0D2BBV+i4qQ6j5mXo0o8+mfNHbIk2qnmSVuAXIehH8zV5Bc1FtKtJuPXdi9LU
+Vn9YIdPS3SK+kObiPb1FNJgCqSGeKrzayuJBHoe0V3w6m75wIgPwBlakBJLcnvnw
+anXVAaF8tLI2LD8fW81aYFEIUObW2U+RsYKpt+KCkQaQvC2BDXV8c9AXPokv/phT
+bpO8aU9JMCeY6Igoe/46a5UYIz0S0ZTkPrRNDy7GWWpBXfIYfnHaVAV5MDOKlSP3
+rpYzVpEUHtfKsu3iMKXGFzjYjjycP3pxHUqbucFeXTCEXvHOL6mQLb4uzUpzPpvK
+C5iDfJhY5CI18NexAcl78O2EmM9vejM9gc/u0+gDyNw
+-> ssh-rsa kFDS0A
+GNkJvuu+kyoieibdYtBRG8zvtiNE6HBJPhXMTThDd4p5YBSrbcOt3rd1aO+del8s
+CrvcXDGap78t9Sc1vb5xGgJkhY04M15lCvxFg7j9oIICEWknXfJRnCtytu2Vgm+f
+L1xDWKsXI1rLptx06VTvMa6mQWOhyMqPG2/6rpzaaizuUz55LXfe82CIH0fWY3uH
+2FVfZxamo987kPxw0XwdJYASQRaov4mVQ41fjzFPO4Hqor8Amx6xANNw30zSzvkQ
+3VTuNbGmHfBak3bJ9J4xP6cBOivc1sXEhE1p1DT773V4SAInIDakUgbjMvRqO+9t
+CdiTrELp0OH+l6ZkNIKdyulFAPgcq3mpBCaOo2MehEX2y/TChZ3UTXVQXdQOjDxE
+VoOS2DdKQb6aHI36uqKbwRlOaB8qdcPnwhTuJlEd/gf3TQMmeAVUhPed8ZLa47kb
+PYCqPLHe9ZoeWiwrDNNR9g9PBTiLzbTFTuMryjg2m4NJsyglpOav7xwLre6c2oM5
+6SyPvQPGNA2lX1+GvrRawWTuR3MbYGf9s4I9uk/NTNNlR4rRx95iE37smRfIsEPo
+3Zq5/4xzQXuM8rgunzvcuSfU6loYlB2SbtxgdYWMZ6ATezHSywNsgmMua73ynwMW
+FIkRLTlsdQTRoGdHJEUI+rp491IcdvjG7q+rTh2+Ckc
+-> piv-p256 vRzPNw ArUSnJawAUiaVuNX80Sg7UxYW+Rxz6xmdybPS5kkN571
+wm1TN++FnAaGNsC1FPkyNPTtgV5SGl6px6rRbOcHs24
+-> piv-p256 zqq/iw A7zNP7C1vFl1adP6CRw8jUwc+iGrqsoGZa6HdempM2ha
+10Gpc2tAGRpW8xyNw6US99ms9EOWnDeIK8rv/bcPYbU
+-> ssh-ed25519 YFSOsg hXUujF/sHbJDYNoPs8CzCM4ZtCH1kdleV62KkNqpxi4
+Aa/AmyUB1VyfRfKMtRM2YecKCobuogCgvhkSWeXYgEg
+-> ssh-ed25519 iHV63A 9UtfIAJhkB0oYwSQ/b6rj4ktmrsFMznlwJJlbq2e51g
+tVEZjTPLrQXCzVoBSk9QwiqbHG7ffp03wZO1Mlo8YrA
+-> ssh-ed25519 BVsyTA MNopfnObD1RtdFtoOslDiXFjIAnjyFet6S4CIbspPhI
+bxGqkemq/7vEJu0PrKBFeY66KRfBglSq9iDa9G25IcA
+-> ssh-ed25519 +3V2lQ m844JmuSTvYjQgSF6h6eOxIXTG/RJ7yYNCpEtgFbNVc
+YrdAfeYqxAZTpHtTnJ4yACD46yCrkIPCrsJhi3jCsio
+--- AFT4sH9mNNQVSULxK2N62VnO+JOt64Ii7x7ryZXpuXw
+�%����Z;K���TPzĥ�M�f��u]����>YoNJB�rc����'=����X���Z��Ap
\ No newline at end of file
diff --git a/secrets/restic-repo-garage-nachtigall-env.age b/secrets/restic-repo-garage-nachtigall-env.age
new file mode 100644
index 00000000..b788cd46
--- /dev/null
+++ b/secrets/restic-repo-garage-nachtigall-env.age
@@ -0,0 +1,44 @@
+age-encryption.org/v1
+-> ssh-ed25519 iDKjwg X7KNpuJwRDzWH2j8Es2AcG1CRyyhEqZu4anWH+Rg8jY
+k4y4ChY9F+0+Bu//yJBq/pqN5CiCoGe11Xbn6zuX0p8
+-> ssh-ed25519 uYcDNw tjiqSxDFnroN8m6rr9EAWCWHuYPRbVQAPVxDRR965Hg
+G2jG+Y+7ad4tIynX/hRpz8nd7rK5kFwAhHwQPu1fLRQ
+-> ssh-rsa f5THog
+mnXc9rwucSGfghckMYyfi/MbsX7n6pl9OHSMLeLtDrY7hPu3Es+R66HiEFTOvD7F
+nJty2ZAcX5OGln9sY23wSqmBnygvAf7MMCGHyc4I/tFjVDRedSd3YGWm3KHy5mbD
+KjIhCcMRY4wM7mjTOsJ6I9Br+Zv9LH/KXg/TKvWgJKA9xGAtNcM1sX2bVTfBdWrS
+J7BXoe+NYsGgEaiEiq9ZRAPRSLEh0WzEOlSUJqkbtHmvM1qCXxVlhVQf1KqkFV3p
+njeZwQKT9OlvqUezmuK1AmNdtQ9SPJAZsff/hMslSqaKb7HshB2O61eyt6rxUxZD
+WPhLYtMwpFJq9UkVU7aDKeWDUh78j9/u92dMGg9puLonzEKDZKEU71KrfbM5/7gY
+28n3O+4E8GcoKKeQhEqLOj1YEs0o/XVVjNtrpK1h7UxVYOPrjydrH959QPCSnLGD
+8Ub4d0ErE0vPqzF6gIKz79RYRnJnFECV2Z9hvxfgy0cEgjjoV8EIBpaRL8Ao5EZX
+XJr6dsMPV4tHidX7NmYc2Z4YXj63sdl0tJ/dcudsh+kfvvPrNNAezfQEavPu0jAS
+XbJbGJpklkkIILCjj/wY36sV8EglTGsUrVscwS1qSdnG7xx2dv5w8XlaE1cvNJH6
+3ojglwuIxnzgy1H5i/PmHD4utFLwzrGSnTeGtkqWj1c
+-> ssh-rsa kFDS0A
+A31FPONQhhYXQkkqlJKyYS75v1YZNM17+k9eTHewsu9lru0fqYuPUPG4eKnGuKNB
+hc9PgyCZyCsfnAT1CeWsIJEr9YB4AGDt573j2Zktclfd82g4A9822jgJRPc8J3S0
+c+6Hd8Q+eEeVVxHr9l3eaZoHaKSkRENcWfgDehnGOY7NhxWqwQMWttWy63YOPOh4
+7bPiljYs8CLjQm341K0HA+eGAFYKlImKw5QBgPugt1y/mdwwSunabaSO6exUzjiL
+4D7NdG53dNzNqgUI4HUlqgiLqnbmmAuNEZsPdLDHoxNWaHWL/XsC5Av2yplnuyzY
+2vCdUSNwrBudKVIQ7fbG7N+t7Vlbf0A82BxD6bne6FycHiHifRXwm7I1eYwspkDJ
+Lp/BjTMCckk8QIAGpsU54DOFn85j4cFG/1u/AXWLUPELBWQVWgcCsnvtWMi7/FtR
+1dKNSDXnlv+xFHlscrXxxMYpniZhUxWN7hTMgZA/jdcAwvaOCjVLK8b/5mdPt5+Q
+BFWLcqEvAqPpiDPXMz1AC7xlIShafVuXpC+pI2J6TP0ulBrvRR6Wz0DzS/hLQHeZ
+mvRVYC6vjLP8nx8Hd6xSatvMura6qzh3JgapSJYcnoWZ/x/eNRqU2+HDZ7cMSP8W
+n9kyYIV+WcfJPJu1ciYJsdlhIqIMYocqhd86M91GjPg
+-> piv-p256 vRzPNw AiASEnsywlQEIi+XXPQHKpGrZ7p3oP3scMqCKtI1NJsm
+yfxUMtiIlPuUHM0p1I8IxW76KDMOnXXCYrZiWlnCcxo
+-> piv-p256 zqq/iw A3W62WldmELQy5eYULBNcaXYfM1D9ifVepIEUJG2VAkI
+R5YX8RZ+Xg91nz++0z4lxLKFTzHQ9tIm38cGkLwt1MY
+-> ssh-ed25519 YFSOsg KJlyJClGTVcTR2QbId+Ctnd73aIxAhzJw/aLU4Vr2mU
+/yMP6uy48qB2yR/7I2lWbbrL0wvLu805Xis1BauVkfE
+-> ssh-ed25519 iHV63A Ks5N6wavZ1XaUXqnWWlpK5t2paAvw/DlSq7ErOT4XQc
+B98G8I0HdOa8eJLAq6toaCAnr0AIvRZc7L3pzBV0O+o
+-> ssh-ed25519 BVsyTA t6Abo+q1NAdk2KTRfTT0ZnEMEzzHs2nYv+5Ojun/gCE
+YmJLvo8rMZLv++swTKtkpKXUD732xzVrddTK/4YxtWI
+-> ssh-ed25519 +3V2lQ Ddq/IT60+xMQ5cfnc4ItYpOLxOhQ8P2MvODzLIKNX38
+tm/bS2ZztT5gtGkAWyeO0kxLuZgvArZj39lhaGqsBmM
+--- AS3H7o9XjhLLKr6GLWIc69C/2kMih1eCFQCaY9iM1pg
+��3���k[D	�4�W�k��r"R��QV`����\8\�5�����Pͧ���H������!n��mH���k�ϓ�)�>g��Ҹg�S<j�饓���^�4����Ԇ��
+�b��.�ٴ����g�i��ú'iҟ��F�p�!<�}�޻F����o���_̠�B� ]�:GX��}�vAh7���kt�(v0�#1��}��P��o�|ྦ/��e�
\ No newline at end of file
diff --git a/secrets/restic-repo-garage-nachtigall.age b/secrets/restic-repo-garage-nachtigall.age
new file mode 100644
index 00000000..a6028073
--- /dev/null
+++ b/secrets/restic-repo-garage-nachtigall.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 iDKjwg 97itC+uP5aHeRBbnFzSpfbSFN4uf82mCUi6ZP3DXUzY
+06Yy/Mhn7KXjZiNlPIKAxiHs5iMQCNOXkV4J3cctVkc
+-> ssh-ed25519 uYcDNw D+ud99Cg7LjLozJT6tXRPqgORiqHk6vN0uCo8jczp0E
+iv5E1/YVolBTMsjno83kFupZABcDUDyfWtdZDVjgknw
+-> ssh-rsa f5THog
+BTlqI3+dMFUJmfsjt8Flb6ac3ORBlF/ZMyQpg4RBscG72BQFE0pZRFYuyaP1TmIg
+1n1C448qSshq/RqCBJ+CLOWRFPF/mNa/uOv35Iw2sfnppeh4TzhqHHgtKMW5LqXX
+UA0elPqrRK1rM65XG45qNmDBBilQUUfsEh3+fP1JHWkbzAVMPzvsocC1V/zzmaqV
+xy14qAY/nh+CBz0shQ8VBgRG/Xuf1zvOu1cNzRoE1o66M1fLC5MJBBKfDPeqHvWs
+DOcyuYQXQLS13XO0/55wGhI4zwYSbD8k3tNinV6q2c+mJebmFYeiYsUQ0h366zh1
+U4oO8D5fVThge74/GVlN4ffdwopKfGnV/Y1164WktIN0NDfjnSxnDSmLajp+/Tm4
+QlsQ657LQjBvGdBtqv1NO/1ZljOkkipXFOuc8yU1Vo7H28cqAaon3ffXRC7tnPV1
+0a/b4VunrB207iIAz9PzdlH9VwG1pIoooFlB3LqcoD7GLHIw9CnT4Wv7iisv8tIY
+3exy6wt15EzR3sQq9Nv338hJdwqShrvWaDR1mql9/j0jsSdEwLjdikVVUCkktzqX
+MJN7VZRZVqTloIVtqdp2LK+vtTxZVuWoMX5PoQUSlevn7FIOo3XqkWj++1R0bXsY
+vnQsCivhZqHDZQX8IhsAcH9mkZbDCQAjOC/x1f7bUng
+-> ssh-rsa kFDS0A
+djYy1ARi2kfZ5WDbCaJtpHPaX1XhnYdWoFQVMCwOLOiIT3+/4q7ZQRBmzLMV2PFw
+wzwT6VUk/hbZ4jqey3mLq8w8VM3RC9aX2X91xxsJ4JrXXoF+Pxq4Jw/Y+INccgNM
++3shr+MOGyzQAQg6rYA2KcoQqZIoog0tdgTfjPCxP0yppqXaXz1cNM+PIH/7DUAw
+Ee3JdTOy21fnSRSvH9NiKsjfVqKkxS13wVxx/Sah1U1M6EcYXje4MnidasTWJ8FL
+uJvQyYMS5fZNRtYNi8/vlg+9lkeu35xNGWAQoEpSCnq6INXamFiZ7nXxKakG48Lk
+1MQFcbOOueuJ7XeHisaz9W5wMoiOKn8WUEvf0BQ2kwFezDl3tXv+6KZ2edcJh/xr
+LWHKZodjYK2GlDJKiqzRtACCTXuE5+KZNNHUQGSyPnP1/NszUdmzdVV8FwBI7kMf
+KKB1Ogr9QL/Z7ao/bGSa/qiEmqNi9OINXfqQc8CxgIeutOpZNyy/FS3+aqJ1J3Nq
+oKdXehz9Njl6RZxAWKRJsHejoiqRwuK+qqY2jn+q2ytCNqRgjEWxaAY2WTjNBfIA
+O+foUc0Jw3qfXpbmqtCA8iLuM1vl1J2hn7tK3RjVr0WodLfopanrLC97FjJb+pGc
+PP5rIwmaTubX9TSeRW99XaZVAFC9NwWJkfEyFBUZuQ8
+-> piv-p256 vRzPNw A+zNLcg+BQVr7Ee8N6HAge1pbOKM5pA+i2avNh13mf0w
+5TdgQQLsC8lMDTpJDLoGrbPpjv6UhCVChWq+WGDi8EI
+-> piv-p256 zqq/iw AwsA120HfuMR0G05b0dwvLHvO9nXEPeD5LmBsywY8/lJ
+x6+JhTjz/t6ukhDOgI4xPJ39W9D7PAAIiKt7JhwcGh0
+-> ssh-ed25519 YFSOsg ePGPHl8H+uWPgdhXs22vriMkDoqSZAeD4ud9rloXi2Y
+rdj/SfqX1BvX/ds8RpckMB3x4fT6KFyOdBizcfXs/pE
+-> ssh-ed25519 iHV63A KgbyMxoS+yDmnxtsYRUN2DTJKnhdSYnKF9/bpr0KBx8
+y14szB2siYO8KUv2JspJ4eYoi+loaMGD9NJ5fCxxC2M
+-> ssh-ed25519 BVsyTA GP1WI2f+SCXmyTwVfb5trshzISviH2aijSlXMmNFNl8
+6LT6Y0Tv1+GiIdXa9mzBrReLQhPn+j/M+1x4m8QVg3g
+-> ssh-ed25519 +3V2lQ Wt9U+lp1YkOUwDJ4Vq6Jy4/7P6OwREcOe08MxsbOq3Y
+47NRTAxj2+MOH5IlAAjwtG1mY7tWR26SHgmhtNW1IVM
+--- V8awWGoI/NAkAoowtvZZU56AA2vCUbEfk9B/EhV+2cA
+�21��U�K�ڡ-S���?��I��%҄7N������1�rt�hfvv�sW[K ��PQ$3W
\ No newline at end of file
diff --git a/secrets/restic-repo-storagebox-metronom.age b/secrets/restic-repo-storagebox-metronom.age
new file mode 100644
index 00000000..603f4282
--- /dev/null
+++ b/secrets/restic-repo-storagebox-metronom.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 UE5Ceg WD0wj4LXTAv2Be2GKOAB9aWoFUiRbfaaLMcznhmhqV4
+syAPY9lpX57RZLMAL0dEsVF7KCzSUgg1qcAqgrFf02Y
+-> ssh-ed25519 uYcDNw GyA4OLGHPEI/RNaIZyOfwsYmBNR/Mn52d08xfT/GGxc
+Fscd+7W9jCnMOBUMaQnzn4PigT7WprFM5/rPEPn/qic
+-> ssh-rsa f5THog
+LP/D3IT8EzizbHmknVuquhrBFlhLuYUdzpo9TZDh//Cm1Pg182F9HTgDF+RL0DhD
+yh7lUBYQSACbdLPMnNE13nWKjj13l9Qh3uooKXEj7wK/xLzF3FzCmIJXaeIxLUww
+iBrnIN+LV5SSNLrhT2IR1jYrss5FP3RLb78Rn4QnHSRJH2sfAh+ocP9DuYFVj2VA
+xRbzdpkHRkG6Q+AK2CKzCkfEUYsEJmmBIR/COL9WMHhmXxsVZqpN04J3SQZhoQGt
+8qJvl2M8UglrHGBCt/0of2Kh7pkSfqdo/wzVLLqRFL2wcbNG/QXEiOoFE/JsTs59
+zhJRly0ifh0LotYOQkOIgOuxEulBb9FUWRZo9LFHGAVT0IExsoAObH9hyjgT2Hbi
+QzHJbc16tDYPrJmcCVIR8BCHwOchLVJeDj1Yx91mTSHrae1sE8+42dFvaHGpcqTC
+AkgtRKjWpk86Ai8LebffsLhcR3GFkahjX5bJAWxFlbW6G2jHqdK7anzPXEb3qyNV
+kJk5Vf0VM6EPaeuiNecLwIVqJqi7+EanYfJQcUPED9PNMVjgINQBE44iRqSJxg1C
+G2Y18y9Of7WY4yGdDT/a0q0E+WXQCg8iwd3RiQ+Z5KoENMBRtNY41VFDd9yW3jo6
+JdyRiTfmADYrT69XptwHPAZ4/HFEWi/O+VGWwwa9srI
+-> ssh-rsa kFDS0A
+pBTceA8fgUdgWkdlw1whGDw67zpEoIDgZkY8R3ZLRD9ARWxEz1CiBggK0Qpve8kz
+nT8xFfsYH9Bq7jL/0oRnrHUZdVol/VX1uCjly3kWhjYimCU6SUj8PmRCCEWvb7D5
+6EdnZiMr5WvftrS+y1sHUYOIWgip1+FIU7evE7/44vIODZWBd4W6XOOc/N5zX3De
+KagjeVd+bUdf+OJuOeNIusLMSJYSEe+AutiTbIBWS08MC3oSFeqRUc5XEeYWMUxv
+FkgM3Pic7DnhSOOEy9WU4N09V5A8GXKLoufEDW3CGW7xwBOPSW38UmMc6hmY5lHF
+JL0GoHTeVEC5PSU5ndpqIaR5TuGypVfq30twVMm7uvZCFiIYK0kztVyzW3fULMAK
+ggrqbGRIAyCW8R+Fgcuhhj6gkQjUIeAHTzxA4XyUrWV3051WFVZrm/duJSvbHvEE
+J0DoeXNgx0t8eLayHLWQFTBn+OcVbni+w8hXHAspq8nPeolZouKEUywCX+rt6qFi
+ZsfR9eJLxJUz1LdYQ13PxtIg0yGfAhDWeELbFy5QETT73F+ILJwFcC/YUYmyZRbq
++F7JjHd6Dj444sV5QIi1DMsNzX3S68qW+hBqPvMlYj2sd6u4IfC4r0+Vzy2H2ipS
+zr9lRLtC7ZtntOFXzFnzpok2kuhv7jnbZer3DC2pI98
+-> piv-p256 vRzPNw AojojTwgknxzzo8ShplFBbXsLvgR+roiJvRhOmny045D
+ymW+fp8WZGp0bW+2eESc0AvIWoZIbQ7iGOxiPov8PbE
+-> piv-p256 zqq/iw ApjnL8J3CDsmCSOs2r2TA2uuUioqX8mA44RgnxQvMSYE
+LP/ZT5PN3oU4lO5pd3pXaSD5LIffBXsRL2dElpGDlBA
+-> ssh-ed25519 YFSOsg tpkrkH5vZupecWj2X/0IkeVW21SvH5HkzvJupNHKuWM
+llpPpMiPVR4xW/Iar0xfMMPNBMR2MYslXygTSPPaEug
+-> ssh-ed25519 iHV63A Leu0ATjr6DhUG9SbtEJoeYtrmwX+0kgkeCH0554D1Sw
+FWjdSl8G7g1MY9Vyn0J10kSu4L4kEMplJpMgSt0WvyA
+-> ssh-ed25519 BVsyTA aysi3vWr+xWzKbwc9ogd8cp/J/5MSNAX9BAO9eeIHTg
+hUlQ0EHwt1qy034Er/mL8cZIGVh6MAWr5aPkkS1gYzY
+-> ssh-ed25519 +3V2lQ IoJWcd8q8dk3gv43GwlpxTq720vs5vVJTm/Q8s66UUA
+lYm1WUibkXk96I8Ou91yR0eui0yPfj+j5drYiTLLqKM
+--- joud1M8D9XMgO7C4hWnES6PZWkBxcL6El+Q59YutFrw
+틠��B�ql�F�<����~�P�.��p&$֟;W����F�R���M�JU�n��� ܼ�(�u��Y�A�v����
\ No newline at end of file
diff --git a/secrets/restic-repo-storagebox-nachtigall.age b/secrets/restic-repo-storagebox-nachtigall.age
new file mode 100644
index 00000000..70e79c44
--- /dev/null
+++ b/secrets/restic-repo-storagebox-nachtigall.age
@@ -0,0 +1,44 @@
+age-encryption.org/v1
+-> ssh-ed25519 iDKjwg HpjoF0TwSaNUwwkLFHLyQX3yFZgEJq2qDtElK5rJE1k
+F/7ralF3HJJIGq17gy1EDLOfXwXCMxuYmPVDN8xJThw
+-> ssh-ed25519 uYcDNw iUAqWKrnnZZn6EUNx8cGkQxma4KcKIk+5VlN8mblnX8
+IY4aYA1AF5cVmQXgMTeNoKoTZ5QwK9yiMb6Ml1GQjSI
+-> ssh-rsa f5THog
+Rryh3EfwMtuCEqV5RWDJflClTBqFzz7ybPreSPtvke2tnGZwf6fVpg8SXyHyhqqP
+1RuBTVQmSfPcgZQXZD9hIUoSQ6ANPmzrJp2EWDo20SfTR1F8Nx5geuzI92EK5r3P
+XccOoFYk3tJzWhhFuGC2yONTtR8zBcW7hnoPUYSkUVpqBbulnep67geRburnf2hG
+N6GhCpf6CMeqBN//VB4ArR/1TL/fggZfT3LAnq/xifrlULPdDFljNF1PdvS8oCBT
+ap5Fx1ETWHU9BYQJ9ZpXlLCx614y3+G2EFgRd71rAbKgTCoOAqdGEzBpJ2Fqv0e+
+aVpx9vNRjdNrJ1CN4+6WPUTxdEOr0LxbHD9umKHe5lB0ufWGDA6akrOPPHS0KqE9
+p+3jaZ69SMdhH1KFgk4KABw9bjABXvVcnL8xmIxwal3ijaBluZUJ1c97nTsoIzTX
+xd7eCNedGwJTbsVXDVTLlhTcGlOhJjt51GqK5wpui9Y+690j6ooP+oQvJmsThG+i
+ZTfOhZIcOkSQfDxNJwcYf+NWKrjc8w7jNZ2l1dRst0GDJZ2AQgpiRi4pPh8aas7B
+gnq7E1TeIbBdeVJ3Xq4HKAWrHbbBisgnEdAe6msGHxRzgy7ope436HQa9kBWaezT
+YOE1HPLeBXsZNcChMdx332RrOT9puLFnGyxZi3OX8+o
+-> ssh-rsa kFDS0A
+N+2w8GhuhF2eNj3buaOO+DpSn6WF6nvc8Uxznj+BvXkXmUlTIMx5AlPQ1kqMIm7Z
+Eb/L9O236VZ8h/HYvLOAnPyAD4JrbWoF/QWohJdEKsIRhQzTJmixQ2hsz1ucsRjm
+TpUJXi7HDjvgkV1RuA1EE2ZEtzK3R6muSCtKiU1G8kCF1uzXIDHEWCsGWNnXPkvg
+O217phHhPbdBwL5Ss7CLQ3rxaP9dhQDdpDP4I7ksmEFVMs196naBZzm8AmSUwIXW
+HOOMHxAJ9gpzUiUUFXv2mZIf+hh9g63lEyHIVC6Nyl4tWlxQpL9pid4iFIqotgLY
+BkwxqIM9j2BPlVDsjHZ5JOO+fquDhY4FlDGfH+KWKyhOfDHUIYusNmT8V7dfTQnD
+mo/vyhFKIiliT9bqX4Bgd7A8ilvoCDEfe2U512X2fARTXyJkUldhbdrnkmLa0Dkj
+yvxqmy5zt4Lu+J5XYY9RH1xPfSRb4hTdjRd6ngeHdZ/Ubqs+9nKMy3XPgHIoRRX+
+CrQZLtxJZQ1ZnjKp8I/XmSBQqhe2NM3X5J+1yASMOC3c4SiOTuMKxFePf8PldakX
+YzYwzl+L/9TH+lhzXF3AZVJQqemvpyyb67tRXe1Eq5i++QCNp8m1O6Im4668brtc
+hflTiKulxpgzefu00iSJeyv6bYD1FVeLDZ4K2P0yibU
+-> piv-p256 vRzPNw AzvntNXWox7dJt2XezyAFQuNnmuat/rbJ/3io2cot6yG
+n8dDfQkeBhI4HMv7l3pNxnZLXrhiwEaTgbQb7Qk+HSk
+-> piv-p256 zqq/iw ArGxIkliG0hVyJha0m+mHUHRLXb4GILEx5iNUtpnJaYC
+jJJunr93I0O9OTUfaX9wC+nIYgWta5rQWfDKBWVFjgA
+-> ssh-ed25519 YFSOsg 5JEpbCAj1bDoN6GBlmVbbqCZSf50BMvZamKmQsWkths
+ky/lEFjeiHzQ79mWu+xXw+UXGV1rcQRgfyPlhFv1VFQ
+-> ssh-ed25519 iHV63A FqLFegAcl3hbwRkhgK/WUOM5bp26xnxYeGGC0YDGhlI
+JhgGX8m9BDBDICye4QQdaQ+sD5pLLE+wpULRnzf/uUs
+-> ssh-ed25519 BVsyTA 9Z99xZ91IlPbLGg4ZxWelslSamRoukT/XyU2etPX7wg
+uA75ZpB0nxA+6iGQrez1udWgU/FrzEddVTullIhmEL8
+-> ssh-ed25519 +3V2lQ YCpUxJEPp0SEzckc5r+02ORuFkLjlViVzmoOFvEZbX8
+nn7HStubmvyGNMJGOD/sCWVLL2eqGQhOKQUDlWnBDaU
+--- Wu8o56D7U0wpizWM567g6rnk6yVgR9SlrB0Pp+1wf7Y
+���s���K�*�y}��7=K�="��� :�C�ۈ駧G��UP���+���U,q��Ԟ8�
+D��Q���K`�ܹE����i������]��
\ No newline at end of file
diff --git a/secrets/restic-repo-storagebox.age b/secrets/restic-repo-storagebox.age
deleted file mode 100644
index 9118a5dd..00000000
--- a/secrets/restic-repo-storagebox.age
+++ /dev/null
@@ -1,27 +0,0 @@
-age-encryption.org/v1
--> ssh-ed25519 iDKjwg G30n55ZAQdPKSHqDyAv42h2RyX67tW/Giq47A189CnY
-XgXVZolY+DjIpfQYpkWcpbmo9ikbAexAV6amuwcK4f4
--> ssh-ed25519 uYcDNw y+amMdymUI72L6mfmruyiOfYS0p+mmTxxfGB7DKMdGs
-oO3/sPGgppRWnVGsL9/3NpPJEQqr8p1h3hyJ9+7gLXM
--> ssh-rsa kFDS0A
-B2kcpfc+92kPSds7zaFW+KrwU+oEUn8kdLCy/swjaNlV2NETzXJNAx/xSDlylRTm
-5TZcLCs106B1JxVr9Ir61WTyTb1PppLJVh0BRrDDfE+m5678M+KW2RrXrPm1IrHt
-0al0gSt0qG07RvETzjKwWOm3NdzKNvVbeiLrBxXIPow3zBzE/pCgK/RARVmsLflb
-MBU88tYAoHw8N5Ba+5Lnh/V80K+DEtPGFTROyKDgaXZtVfLNU331m3dbEG1FRi/n
-JQBBY80m2yylP24YFxJwCVkresIutjJ3OOk8nth5lgbgqHRW/Z+n6FZIs7L6SV8f
-D6qNDB1qcqLk7qMZNDEhjntwcxhHQ80bXnOMdU+p+7/fc2VGw+VgkKpjj3u+xkh4
-x0rJAS3edE6ysaIwRAZgGhobHxXBjnWHJp0dRz2+eeVfeomrT4BwT4zPDqkM2EvM
-x4wsUh1qBhiJn3lkuyTKD7fXAk91tS+8iFF5Bp/cue8QIIJoXD6hs6AXRcR9OdZQ
-vQuGqB9AxRYAUFqxhXGFUEvpvOh6/Mt4daO1fqGkkSeQK88TdKgVgvemf0cAX4sQ
-OWgFaK8bLqls7MX7rp57vlhEqhBY29bdMKRUG4hGxnUxH/JmVI3oJ3PoYz93ayb8
-P0w8L/wlGRfJdSSqSFuZrAFhQ41xjbq2z09kQQr6FVw
--> ssh-ed25519 YFSOsg NjG+pG/FEkrqIx4YhPlS3gGE7LgKBJTUOOE+kW0OBCo
-J0h7GHWTC/S23F/QGBj54fr2YUMCOnolRKWSS9zrjzk
--> ssh-ed25519 iHV63A LOzrqEfJ5jFMLtV8QAbVbj9ikDE/lhBzqwjXWqJcb3w
-bgk0mxpif2wtDaS94OJ/uPVZBJZoIh2Eq5M8xRW/a/s
--> ssh-ed25519 BVsyTA JGE9eWZ1la2zSayjcGGRcPYXBTxsfvOxphDLndhYMHo
-Xor0OLMsXTU4MmkyvoYoU2tHGwDla/GbbW6AI+Fptuc
--> 6>G-grease ^'eq
-vOuziQ8uC81Tflh6vzXJJIqrCgh3UEZhs2tBkB9QwPww+Q
---- BpmRwNLuZ7Za7VA6xb4UWzjaSha6vpZcki868ZBpORo
-w�Q��r�lo\n���O����6��l˅,l����>��ܚ��,�/��ؐ���73|Rw@V�`ߥ�
0o����L���q�Ί)E���c7��G[�G�
\ No newline at end of file
diff --git a/secrets/searx-environment.age b/secrets/searx-environment.age
index ff9993a9..bd396fee 100644
Binary files a/secrets/searx-environment.age and b/secrets/searx-environment.age differ
diff --git a/secrets/secrets.nix b/secrets/secrets.nix
index 32090c20..7ecb9927 100644
--- a/secrets/secrets.nix
+++ b/secrets/secrets.nix
@@ -1,27 +1,55 @@
 let
-<<<<<<< HEAD
   admins = import ../logins/admins.nix;
 
   nachtigall-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP7G0ufi+MNvaAZLDgpieHrABPGN7e/kD5kMFwSk4ABj root@nachtigall";
-  flora-6-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGP1InpTBN4AlF/4V8HHumAMLJzeO8DpzjUv9Co/+J09 root@flora-6";
+  metronom-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICLX6UvvrKALKL0xsNnytLPHryzZF5evUnxAgGokf14i root@metronom";
+  tankstelle-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJdF6cJKPDiloWiDja1ZtqkXDdXOCHPs10HD+JMzgeU4 root@tankstelle";
+  trinkgenossin-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDZXRDpom/LtyoCxvRuoONARKxIT6wNUwEyUjzHRE7DG root@trinkgenossin";
+  delite-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAKo7zlfQhcJ5/okFTOoOstZtmEL1iNlHxQ4q2baEcWT root@delite";
+  blue-shell-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP9g9X0a/MaVtbh44IeLxcq+McuYec0GYAdLsseBpk5f root@blue-shell";
+  underground-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGF3PtA89yhVkmN7aJI6gqXK8DW9L7kI71IgiK4TAEwI root@underground";
 
-  adminKeys = builtins.foldl' (keys: login: keys ++ (builtins.attrValues login.secretEncryptionKeys)) [] (builtins.attrValues admins);
+  adminKeys = builtins.foldl' (
+    keys: login: keys ++ (builtins.attrValues login.secretEncryptionKeys)
+  ) [ ] (builtins.attrValues admins);
 
-  nachtigallKeys = [
-    nachtigall-host
-  ];
+  nachtigallKeys = [ nachtigall-host ];
 
-  flora6Keys = [
-    flora-6-host
+  tankstelleKeys = [ tankstelle-host ];
+
+  metronomKeys = [ metronom-host ];
+
+  trinkgenossinKeys = [ trinkgenossin-host ];
+
+  deliteKeys = [ delite-host ];
+
+  blueshellKeys = [ blue-shell-host ];
+
+  undergroundKeys = [ underground-host ];
+
+  garageKeys = [
+    trinkgenossin-host
+    delite-host
+    blue-shell-host
   ];
 in
 {
   # ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBB5XaH02a6+TchnyQED2VwaltPgeFCbildbE2h6nF5e root@nachtigall
   "nachtigall-root-ssh-key.age".publicKeys = nachtigallKeys ++ adminKeys;
+  # ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPDeKXqbhNzbXk15h2k8wGBByxMDCC6HE1/fwa4j6ECu root@metronom
+  "metronom-root-ssh-key.age".publicKeys = metronomKeys ++ adminKeys;
 
   "nachtigall-wg-private-key.age".publicKeys = nachtigallKeys ++ adminKeys;
-  "flora6-wg-private-key.age".publicKeys = flora6Keys ++ adminKeys;
+  "tankstelle-wg-private-key.age".publicKeys = tankstelleKeys ++ adminKeys;
+  "metronom-wg-private-key.age".publicKeys = metronomKeys ++ adminKeys;
+  "trinkgenossin-wg-private-key.age".publicKeys = trinkgenossinKeys ++ adminKeys;
+  "delite-wg-private-key.age".publicKeys = deliteKeys ++ adminKeys;
+  "blue-shell-wg-private-key.age".publicKeys = blueshellKeys ++ adminKeys;
 
+  "mastodon-active-record-encryption-deterministic-key.age".publicKeys = nachtigallKeys ++ adminKeys;
+  "mastodon-active-record-encryption-key-derivation-salt.age".publicKeys =
+    nachtigallKeys ++ adminKeys;
+  "mastodon-active-record-encryption-primary-key.age".publicKeys = nachtigallKeys ++ adminKeys;
   "mastodon-secret-key-base.age".publicKeys = nachtigallKeys ++ adminKeys;
   "mastodon-otp-secret.age".publicKeys = nachtigallKeys ++ adminKeys;
   "mastodon-vapid-private-key.age".publicKeys = nachtigallKeys ++ adminKeys;
@@ -31,7 +59,10 @@ in
 
   "keycloak-database-password.age".publicKeys = nachtigallKeys ++ adminKeys;
 
-  "forgejo-actions-runner-token.age".publicKeys = flora6Keys ++ adminKeys;
+  "tankstelle-forgejo-actions-runner-token.age".publicKeys = tankstelleKeys ++ adminKeys;
+  "trinkgenossin-forgejo-actions-runner-token.age".publicKeys = trinkgenossinKeys ++ adminKeys;
+  "trinkgenossin-forgejo-actions-runner-token-miom.age".publicKeys = trinkgenossinKeys ++ adminKeys;
+  "trinkgenossin-forgejo-actions-runner-token-momo.age".publicKeys = trinkgenossinKeys ++ adminKeys;
   "forgejo-database-password.age".publicKeys = nachtigallKeys ++ adminKeys;
   "forgejo-mailer-password.age".publicKeys = nachtigallKeys ++ adminKeys;
   "forgejo-ssh-private-key.age".publicKeys = nachtigallKeys ++ adminKeys;
@@ -39,18 +70,28 @@ in
   "matrix-mautrix-telegram-env-file.age".publicKeys = nachtigallKeys ++ adminKeys;
   "matrix-synapse-signing-key.age".publicKeys = nachtigallKeys ++ adminKeys;
   "matrix-synapse-secret-config.yaml.age".publicKeys = nachtigallKeys ++ adminKeys;
-  "matrix-synapse-sliding-sync-secret.age".publicKeys = nachtigallKeys ++ adminKeys;
+  "matrix-authentication-service-secret-config.yml.age".publicKeys = nachtigallKeys ++ adminKeys;
+  "matrix-appservice-irc-mediaproxy-signing-key.jwk.age".publicKeys = nachtigallKeys ++ adminKeys;
+
+  "staging-matrix-synapse-secret-config.yaml.age".publicKeys = undergroundKeys ++ adminKeys;
+  "staging-matrix-authentication-service-secret-config.yml.age".publicKeys =
+    undergroundKeys ++ adminKeys;
+  "staging-matrix-appservice-irc-mediaproxy-signing-key.jwk.age".publicKeys =
+    undergroundKeys ++ adminKeys;
 
   "nextcloud-secrets.age".publicKeys = nachtigallKeys ++ adminKeys;
   "nextcloud-admin-pass.age".publicKeys = nachtigallKeys ++ adminKeys;
+  "nextcloud-serverinfo-token.age".publicKeys = nachtigallKeys ++ adminKeys;
 
   "searx-environment.age".publicKeys = nachtigallKeys ++ adminKeys;
 
+  "restic-repo-garage-metronom.age".publicKeys = metronomKeys ++ adminKeys;
+  "restic-repo-garage-metronom-env.age".publicKeys = metronomKeys ++ adminKeys;
   "restic-repo-droppie.age".publicKeys = nachtigallKeys ++ adminKeys;
-  "restic-repo-storagebox.age".publicKeys = nachtigallKeys ++ adminKeys;
-
-  "drone-db-secrets.age".publicKeys = flora6Keys ++ adminKeys;
-  "drone-secrets.age".publicKeys = flora6Keys ++ adminKeys;
+  "restic-repo-storagebox-nachtigall.age".publicKeys = nachtigallKeys ++ adminKeys;
+  "restic-repo-storagebox-metronom.age".publicKeys = metronomKeys ++ adminKeys;
+  "restic-repo-garage-nachtigall.age".publicKeys = nachtigallKeys ++ adminKeys;
+  "restic-repo-garage-nachtigall-env.age".publicKeys = nachtigallKeys ++ adminKeys;
 
   "mediawiki-database-password.age".publicKeys = nachtigallKeys ++ adminKeys;
   "mediawiki-admin-password.age".publicKeys = nachtigallKeys ++ adminKeys;
@@ -59,13 +100,32 @@ in
 
   "coturn-static-auth-secret.age".publicKeys = nachtigallKeys ++ adminKeys;
 
-  "grafana-admin-password.age".publicKeys = flora6Keys ++ adminKeys;
-  "grafana-keycloak-client-secret.age".publicKeys = flora6Keys ++ adminKeys;
-  "grafana-smtp-password.age".publicKeys = flora6Keys ++ adminKeys;
+  "grafana-admin-password.age".publicKeys = trinkgenossinKeys ++ adminKeys;
+  "grafana-keycloak-client-secret.age".publicKeys = trinkgenossinKeys ++ adminKeys;
+  "grafana-smtp-password.age".publicKeys = trinkgenossinKeys ++ adminKeys;
 
-  "nachtigall-metrics-nginx-basic-auth.age".publicKeys = nachtigallKeys ++ adminKeys;
-  "nachtigall-metrics-prometheus-basic-auth-password.age".publicKeys = flora6Keys ++ nachtigallKeys ++ adminKeys;
+  "alertmanager-envfile.age".publicKeys = trinkgenossinKeys ++ adminKeys;
 
   "obs-portal-env.age".publicKeys = nachtigallKeys ++ adminKeys;
   "obs-portal-database-env.age".publicKeys = nachtigallKeys ++ adminKeys;
+
+  "tt-rss-feed-crypt-key.age".publicKeys = nachtigallKeys ++ adminKeys;
+  "tt-rss-keycloak-client-secret.age".publicKeys = nachtigallKeys ++ adminKeys;
+  "tt-rss-smtp-password.age".publicKeys = nachtigallKeys ++ adminKeys;
+  "tt-rss-database-password.age".publicKeys = nachtigallKeys ++ adminKeys;
+
+  # mail
+  "mail/hensoko.age".publicKeys = metronomKeys ++ adminKeys;
+  "mail/teutat3s.age".publicKeys = metronomKeys ++ adminKeys;
+  "mail/admins.age".publicKeys = metronomKeys ++ adminKeys;
+  "mail/bot.age".publicKeys = metronomKeys ++ adminKeys;
+  "mail/crew.age".publicKeys = metronomKeys ++ adminKeys;
+  "mail/erpnext.age".publicKeys = metronomKeys ++ adminKeys;
+  "mail/hakkonaut.age".publicKeys = metronomKeys ++ adminKeys;
+
+  # garage
+  "garage-rpc-secret.age".publicKeys = garageKeys ++ adminKeys;
+  "garage-admin-token.age".publicKeys = garageKeys ++ adminKeys;
+
+  "acme-namecheap-env.age".publicKeys = garageKeys ++ adminKeys;
 }
diff --git a/secrets/staging-matrix-appservice-irc-mediaproxy-signing-key.jwk.age b/secrets/staging-matrix-appservice-irc-mediaproxy-signing-key.jwk.age
new file mode 100644
index 00000000..8b4a65e0
Binary files /dev/null and b/secrets/staging-matrix-appservice-irc-mediaproxy-signing-key.jwk.age differ
diff --git a/secrets/staging-matrix-authentication-service-secret-config.yml.age b/secrets/staging-matrix-authentication-service-secret-config.yml.age
new file mode 100644
index 00000000..eaab469c
Binary files /dev/null and b/secrets/staging-matrix-authentication-service-secret-config.yml.age differ
diff --git a/secrets/staging-matrix-synapse-secret-config.yaml.age b/secrets/staging-matrix-synapse-secret-config.yaml.age
new file mode 100644
index 00000000..a8571618
Binary files /dev/null and b/secrets/staging-matrix-synapse-secret-config.yaml.age differ
diff --git a/secrets/tankstelle-forgejo-actions-runner-token.age b/secrets/tankstelle-forgejo-actions-runner-token.age
new file mode 100644
index 00000000..98b21b74
--- /dev/null
+++ b/secrets/tankstelle-forgejo-actions-runner-token.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 1X0eLA u7lsLMIoEG14ywwXTvVBIgEXj9HTU4T/9jZWURDboy8
+MLk3yg2a6mJzhZJ85UbV49BNR/LtFiAP9eC77qnn0U0
+-> ssh-ed25519 uYcDNw Rpfhe2cv+3ZUQNfIy3xwhnwf9JnakYWvIcRv/hbJAxc
++dKxrgjKmu9WpnOgMBe76ntdKNDUbL1mLZAmAF3FLgA
+-> ssh-rsa f5THog
+QX/43QwVTPVQUlEVVaQp8ANVp+YiVHswSzjxn6CfqZcbwxaZCraDbA99Ix1bNWkW
+Ojn9kxgzIWxMQnxXJnLAbpMNbAswSQBLvQBhSUVf+Bs/xmV3rLD58PzCJ9yMZPsT
+RInwk/w5UQ4Hpf9Lbm0GwGruru8c7nJtV/cwZX9IJlYscnUwTYRLKNxZQ1cFOA3a
+Wr54j1OXKML4djFbUdHHiGkFPiBHPNAlk+EIKttjwxYzBDSlsdzFnJhY1QSXkrm7
+ag0GEEtJC07MtsBxv8VoO6l9BH1Y3j5hWB0Gih/8rR1ro8Yp/sQXBBXgldeIi9cR
+pT4MMD8QpK8oFCXdCnZcU8mcRQABvkP5SlTRIGtCv7nreCSPUk+G5cUpDd1Pw6JF
+rnzj3Gonz73Ubad8npoOtHU6RSKgsSiJI+4sbDI9leuumbs1Mz7ihoA3HdS/lBmw
+OhOLIwyl1egj7OUJodTM/kcsCH92rfENt1SbYjJ3Jbgx1gq1N1+xbRbinKRxBGsS
+QgF2pj/ufJBjyuV5La1PCh9/j5UEZOzM23bSu2tCe5HGksPDM7IN/YDP81fFd/eD
+AUfPZ1yUOL9Of081M6km+SCF3XyRs/2yRkZuqkFG4BVnuzi7qi0JMn1MF/2ldGIN
+IDHeIDIJrmMuiZVrz+ms7VdloYq6F3/OJ4Ytyr/kI8o
+-> ssh-rsa kFDS0A
+hOPK8WZmH/o0TtpjvlKXC7fXRtzPThyqIoHBy2AmEURPO2jQOIdfvI9LEaPsEMQF
+RTER2+rh9LvSQY0nCjd1HtOFpdZgU+ZP3iJTwVCjlx5nYSwX+XxkuxWTjaxUvuuK
+we8KLxOWqv3cSSaO3IAEJzQ1DuxrrXrLPfW5mcVmymNfqQ9d2Q6Mq2guyJ5Uy0Pu
+1LrhDHX/X21U0/pRbpg/fGpmR7vD5NwQtqB3LJKxCKs0MYtvO6fyZB/W0+PGw42X
+MOSwx9cs+KogwDMRNDB6dzqp6HjHTs2L5cmjW6yvlf1L1KBAfnPIAoYtfCmnySzL
+AHwivD8aw1qZmR1oai9jYRdoM4kH3k5kfmZUE8FXI1vtCGr68pnAfgkTBUE8XYGb
+dc0+vKxIij/B+GFm2Zb6Xeb+faQnSHORJ1qqTHnRkWFl1RtP+tndG57dyeeqSMJD
+uIP0S2iXWSe38HZLsuRgRlJkZ5aNTN5ADk8KVMM0swSk71ZiLhM4Y0EKVGFKhujx
+gqu52zxCdADYXqMQLx5/44JQ7SHkzZVg+JxpRyB3utQ9iIi/UH+sddiY1jhszZcu
+Mnb5nwgR9jnNIz8AC1KD+dwUGZohEd2m/xSYj6nD1MkH89BioDH0jPaA+LcrdI7D
+CS2qXFFYsG3mAAQVyXrjUeeYiFmTKJclnij/4qGtpww
+-> piv-p256 vRzPNw AlV7Oyz/gsyYPGP4+mkMBV11j0rau/wvS93FXzQ8L827
+cKiIR7/yLJKok7ez9MSs9ffW/qVxkEIJ5IWrKqbwfq8
+-> piv-p256 zqq/iw Au17akNKMkGePMk10H5cf5qokB061e2UFP/O94AbhvLA
+vC5M59NTX+RQw5+0/h31Of9DPXjYv/J4cyIxnTDQog8
+-> ssh-ed25519 YFSOsg Sn+FlTN1zqm5mY0WA2/ZoEb1Z8jcrRSNyUZpX2BhP0Y
+OhDKPrfAP5Z4JPo+8WXzCmEDvL9QBctol9EfnqoHozg
+-> ssh-ed25519 iHV63A g+gtt0ilCDo++EJvfpu+Xhrx2gu2wcECRqJSrQhaADs
+WAOqjDHceQqNaItsXgNFpKwKrFZSgiQug1Frp6LpFiQ
+-> ssh-ed25519 BVsyTA +y06rF6diU3RuJkRvTfyrbbvx1n6bhZhpCmXeJxk0Qg
+2OBEX4AKHGsGZ22vvi7Eo7sEmzxqkVR87II+gxnDiSk
+-> ssh-ed25519 +3V2lQ Z93E8cR2SdSrg4INsPqZ1atPzo/C68B8ZmpVvga2RlY
+0uy1GQv8nzJXV983ztqezDOsO0Qii2oFcVqXYsN3z4M
+--- jO8j4dQtv8bzUgiFOnhJBe/U+sJIb5tecSDL3eSdOn8
+��	p�w6���};p�F�B^O�և����m�2���g�=afPM�Kk��ކ+ݷG���>��J�[m�S`�	`Gі
\ No newline at end of file
diff --git a/secrets/tankstelle-wg-private-key.age b/secrets/tankstelle-wg-private-key.age
new file mode 100644
index 00000000..488f07ed
--- /dev/null
+++ b/secrets/tankstelle-wg-private-key.age
@@ -0,0 +1,44 @@
+age-encryption.org/v1
+-> ssh-ed25519 1X0eLA eLFHek688PRXrCPdtx6Kr8MFlmif6OlP7V5J+aAEsxs
+8sCph1/Xyiq39pGqMI+YrgAxrmFKHC1TVSveaII79Bs
+-> ssh-ed25519 uYcDNw jRyxPhEJeKoi3wpKpsLww1CXc6DGrTt+cDCNG0qiZ1U
+xohRFJJajs5xxAUT5jVrov6cNxGqmbyNVbLcehfBXuw
+-> ssh-rsa f5THog
+dQkO5kA6SUQJTn3pJH9xqOhjw6roVpLeaYzJ+cFcgjyxPH0IdZBs+PAc1CAkvdSF
+lye2eNzwmej32oZQJJR2xWkTbev78QAXyjjwXu6Bnarvn0FhvDzbHvsxuU/OV+L5
+klANn5eTPh1h68YcI+DV2VrTEJP1jlPnfRH+olERWNT+cSyFaRbHF9+eepStLX5U
++0yUmO2Eb8P+fHhzmGUgDadX6j7MB1QA8PYKiYflxWT8/Tm4esCWhT7lbQpykt5y
+ni+OOX4z+noE+CmpvPsYfLu1qNtNzn4RLk+VDNuxOrU11UiQ++hwIPwwWDW4HufI
+q0Tr7DVNhT1MDRKRuxniAeTDGfJ/AV5TdHqbDzvUt4t1HneM1qaRpWFhuxrsKR3a
+2LhWiGfAXxSOuqKY5HRBqI2t0TdysybA61iCI3Np+ZySVGNDiZXCSpociCjMRhQN
+BdIbaj6cQFIDt8QN5GQXo9YXgDOg2KAomP9LjSI98UcAF+YpwQmd5tbdS+L4l6JO
+/VtWyv3kNWzx7P1U3+XgFRmVYzYYcLZuUgKX/v64AmLt7S7HmXrb3JliLwllJhN8
+LH+UTvZgiL01SH5Clkj7/lOGVbNc+7beaGCHiLl/3CrrfAe39VfxSBvCvOOxKMlI
+wuNJrdvhpNyjGJHXKTVyzrJVH/Z1NtlvNMIE/nv9gLc
+-> ssh-rsa kFDS0A
+dRCuP4LfpT3TJ9VC/QOxyOVMWSVQmsUInM1IzwFKfVJkPsn4KTSM9y7R4fT+lWWz
+hpz0AS+mIRSNEWxttwrQWiy+2+/sdJGSxUIEdc//DagkI18TPvAm05J8dv9Yr2fT
+i55Z1OfX/YxobGE64UxDdm2GPM62YGp/Bw6AxInCRc8sFY1Aib+tjH/Hsh9Q6Q7W
+wB+oER7Ve/qHZFQoI/ANkIOcdhY1OGT/fP3Wn9UvfU1NBsa36c4WrTE4Lw/bM2PS
+JUF30R7Zk/KIfKb+nG6bqYU6aEW+ux4P8jyCMc8uqwHS1QZTpcc82SRzp22BA2IK
+nNB2/aMjIYUuLhSvn7jnEtZBhjCTCDfgMSvyItwuArZQwljQAGuBsiM3LSkUaZ7f
+Z4WG7U1KkDWzIz4WKgFLyfl+Nj2yrMJdXGURVucfjlUd2h+6p67S9KX0fJgvxJR0
+yk1pZ3ACgEX2gK6pSIK+ihnqfdbq/d/xfzDbDCe/VitJbCd3p7soZ1t3UYN6rDrN
+I0oym7WfQcLt1hWIvx55+l1jMci7/KymRWw5gG9f8aaoUYOzYKp2BVJ8OJ7YLKcR
+NdoT6gtmQW2uk3NeNLhvZnZJI6auJTmt7xsHEDhboEimj+yGXv7efnZXuroda2pd
+gt/j5pUkyQZKknmHSANGppGp/CVj+ICAhCzMGv1icec
+-> piv-p256 vRzPNw A/SHGUJUCugkzFFhKCanwsvxRnLXkbcIYSXO7E3fyNjU
+Wn3uO/+zegfjueDk/S7Uaan0ICCWlEbE/ElO9HRv28U
+-> piv-p256 zqq/iw A3VZYnmi5RXHoYwpHvd+EvWxt/XqWZ3bm6/UhI0TtKDr
+fRGTUCQAPU1h95chz6ZmYVRtNax55C+9LqakXVDEj3A
+-> ssh-ed25519 YFSOsg PS/SetaQ11NQywWP3s55lRyB9FER3NsJQXeU7aFa00Q
+2o3AJqeMnphZ8MhMRIZxsE8aV521Nc3npK0WC37BYVw
+-> ssh-ed25519 iHV63A gCVUgaCet2MPyC6t2v2bWt7soUEfjvViMvgkcoMGqTs
+gNZTOD7U9NSckqrUje1ZMaVESxYplcTpKlrG1DvUTS4
+-> ssh-ed25519 BVsyTA ++3gIxa9SLXmGH9Lwp3cf2UWX1VjEvq9BqHvM/97z1U
+x1VU2tIIDI0PNwf/Diu9A42mCHbueUH3Sr0yoRMG6Hw
+-> ssh-ed25519 +3V2lQ mc88yZDfTsanqgjnpOlT28kvc7hjhO3fAN6ZUiDlIFI
+InHXQotpYtG7i7wST/A9mPLgErwOyKgtlmNSviiCaBg
+--- jynDcc+2BT1fdS2w7/sRWW3iA7nKnON+Hm76qgmadZw
+���x���5P�e0��O<`hv�|�����鱯L�	6
+������(AY�6�F?|��߁y��#���‡8N_y
\ No newline at end of file
diff --git a/secrets/trinkgenossin-forgejo-actions-runner-token-miom.age b/secrets/trinkgenossin-forgejo-actions-runner-token-miom.age
new file mode 100644
index 00000000..fea967c4
Binary files /dev/null and b/secrets/trinkgenossin-forgejo-actions-runner-token-miom.age differ
diff --git a/secrets/trinkgenossin-forgejo-actions-runner-token-momo.age b/secrets/trinkgenossin-forgejo-actions-runner-token-momo.age
new file mode 100644
index 00000000..9c642106
--- /dev/null
+++ b/secrets/trinkgenossin-forgejo-actions-runner-token-momo.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 NID4eA 9Km4/2/pkgAFfyScmcdQIsA64B+cc7JeEXdNw/gLgVE
+Gp760BQdreQfYj+9OZpKGLzzboLUmnQDJPYMm4Ln7XA
+-> ssh-ed25519 uYcDNw pY5x4MMZ8mVxQPlhczfEWXrRRMZsC6O1X/6BkIl00Bo
+Mjy65DKNsEYlhBzZZSiF+QTfrrUN3goNOKQ+TQxhzPY
+-> ssh-rsa f5THog
+d4GgujPw3coMH65lyb3dyqI8vD7U5oyK2FGeGVXa2z+MElFQQ30FbCDFJIgUpn3h
+XrXz/52Vs7LxPhMfvqO0y1YnT06oRBsnS3f9X1QhL6R70pju5b1jR4K/gWFyBw+7
+w0D9/rsXh9e922rp5t194srGiaIXojtxreOh97UEV7GL5lR0+Y5RHXl+oQJvUhAT
+qPxoblYm1qUkkd4ywZc6/GIzG7DYyW66qDeCx6wH7Ib35a4CNV0KgFmyeOpeX3d/
+HhGuSEatVembdE7TDYrvjBjxGiW3Ix9kwgzoBS8md7GfbD36gT78wciyHakkaE2m
+K95TZ9K6hZamOR/kHybrktkdlds0fqFJ2lr3vgBfrVr6qBlk7PnooVgewV2C+7lH
+afBIRT+vHHBs1/oYRFxOPHj3q2xpWsVXdtLIFfd5ked0ekSdgdrUoUOhf6mGzl5a
+CNNhn4aG7Oryk12m2CcpkYnJJ2ssw6lDvf/WB88sW5ExME/n0mjYEQIBLbmvD1h7
+bQrYBr8UqOHvhA0b5G9G8TrdGyEyd7aD8u7iZZECGP1uL5YlQCFGr0v1bb5n7GuB
+rzV/SyU6RKWijf3IhAi0Xaet/wYApK501ag+v156npNRzupvZUsHjcn1qpvogg2K
+V3niDVDZvd9sXp1xdbfSPmpvJeCfs+5HMpnt5RXLgyE
+-> ssh-rsa kFDS0A
+ocjzfUNIWCl8J30E8ThCbBlDMM24bHLCVJphoTAiK97eVkvjer4qYwIqgx/83zwZ
+1ieGBOIWkmnl6SMzMEjI8SPwJKOcvmNYJQE4Pi3H/qRh7jw9BG7DwiR80r4o9lOy
+qlIKhiFgDbsssotnzIu9qQeWjkk+dc/5y0UGxn//OVy7O6q/XmLRIw5zXQeJkuHf
+0wqpUaWSLcrnTN6X2oOFnSMWJ/DL2ULtec3oT15VDsplXYOxUkzN4Xt0iCssJHbU
+k+0auD6Fma6qkoV4STkOyHnO+Jp4m4TyXruU8ndeySrZpDyTTKI9Eg9wMJY6PzVy
+s1wu0/NOiPCKJPV9fn9dfWtxyTi8bM82U/38nVMDqYQ6d2Qc0QjFsAdoO3W89uoF
+eLnTCZySchGQMCnc/RbEKC1uh9dxjm8pGk3juOYuNSzAuBS1i1nd763FyTom/rHh
+ww1jYY5f3j8nxGd6VDLrTmwuNvrP13NrkiF66arRY17b1NjPoKZ3JCegCuJYC75D
+j8pZMYs99AJMhhJw8lyUfPD5RfoK4OgoGyQ3PjznrQHMekqqQcP04nbKdZaKA/QI
+5KOF/qt7lv0yiOASO8+0C+Qqk5gEJm9KcX7BOaxhW0YE2pYWEwjrT+NoeBxQFu5o
+D/wJM9fLvmwfHV3QdPxzzeNm42vSbdnyl30ykkRUrao
+-> piv-p256 vRzPNw Aollcw4IUKHV94+7yhHn4Qv1Lvv7Gg5TXcSZziEbfK4m
+xx/i7v31NfXFQZpdopheuXCxVgfeDe0XNrK2rqX3d4k
+-> piv-p256 zqq/iw AoV2FnCZqVv0UkXmOCxGd6LF+DiY/BxY1ZW2IgrHp3HQ
+JgSr05Jw0txRERkftpYuonu7iObN8keFk5F51NQZMig
+-> ssh-ed25519 YFSOsg 3+jORCqVTkqid/Bq7bHVlpnyhx4jof9V7OeaUu9eTjU
+QbxGTYIUF9vSwuXIZalYloomT5u0NKXbIbCro2b+qxE
+-> ssh-ed25519 iHV63A J9x31ghWAdtAicod9FbMO4dYdUpE1D3mPXTUQe6dzxI
+Oi4RP6LPd8EVIKN9StVR+OWumKMj68ZjVYJP4xNSLl8
+-> ssh-ed25519 BVsyTA WT9DsFF+RfmjJf9wCWN3cia5sQgZHWPG3MHOF0wQvUY
+o+tvv7WarmpuNBFS8Uj6x3I4v0qnKregnpQyaq17LJw
+-> ssh-ed25519 +3V2lQ uJg8rMjDoZkmM54h+4mzkZaMJTnrEQFH+iRCVxVb/gI
+osZOy+spo4mCI76E/qgeNMJbDO3uwughKHHmCRk+jC4
+--- YyHRgpPXzBC0r959KlfyFaA1ilDzzb8YS/yeDWNTs60
+A�<�Ĭw������z���&� �L��<����
��j�)*8Д���j=��3"�ÿM�Q������i�V�f���o
\ No newline at end of file
diff --git a/secrets/trinkgenossin-forgejo-actions-runner-token.age b/secrets/trinkgenossin-forgejo-actions-runner-token.age
new file mode 100644
index 00000000..4402ece4
--- /dev/null
+++ b/secrets/trinkgenossin-forgejo-actions-runner-token.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 NID4eA +iD73cCN5j4zSi+6Pv8KblglzrIleayuzc+zXV1Dfn0
+Jf7IwEqt/Zs7Vcnmr51Zpn0YKuPAASJ8iGSKV+Y5mnQ
+-> ssh-ed25519 uYcDNw vVNfTtCO3LQJ4xCxsYFEAfM3eP3bqfawxm4JkW5xjU0
+BGrReIXoR0R0Xs5weOvz4Kuf5OxoSjCJSlg5xDhqS54
+-> ssh-rsa f5THog
+UyeGX4ZC4T1j6a+cNUFN5Ly4LsDEybd4KAd+eZs/s4fQiFH3b1xZ1uAVwxUtCMem
+ugpie2W1f/VrsviCSgdY+WZAEP6zmErak3NQ85VYQauKt4HibboTADGo0PBZxtmn
+Nctq++tdJrg0LUf9SIGkwmOKJ3iRw77tlE2l+pLq6IVsGGuMVDZBXl+jLrelOEQP
+1kXFI1VMJ44M8hQuKvplcDEy8clcHedWiK2eD9MWw1aAat7ZJtTXgb0do0u67IAa
+h8EWsaoOQbraJa7IhcKQTiLYLAT0FDkDfxZu6dSHWsBwOrh0FajFNGa/0xChkw2Q
+FuAlSQmE8qg9XuSDayMXeZOUMsNIzD5LXk4UL+RMjVRxtMDDY7vBUCjsx1VceWS0
+blWC5MNihJySE7Uj/h6Dnpc8HDBd4/wnxoooSR5pAl6AE6Ifs0CbVo9bEp2WTMy3
+OtUX8nYbrfjep1VQ0XudpEa+NL8mT772dJmwdAX+XtJc4eSVUPbDfg2hZkqCe3Xq
+E9JUVg4CPEVqS56J4j1uKhcGEK80SCNe/w0W/B0ORfLmSA/dOZRF0h+yFQWGlRzA
+PqG2YhpctdkBNA+6vGK5n7aGPJfJrTMAAjA37us+lWDA1boF5/JZmrcv1z3+dyGS
+Bi4i3rJlWoqS/XX59w2cVllIjIyeV0odbymfQhyAz8c
+-> ssh-rsa kFDS0A
+ZLz/VMJ17fDwULcEy1eSEz79Qu/lhJjahEsn3HYJWiWjO74/SdY+ha/rqSQnjcSG
+reuD0eNYifqyXRnDpiSTgOSFEESL7wL727U3MqLbPIwxJ2ugmQfiKcDUjp/cwHIO
+NJmn5hb5upDGHYpTf1i85W0AalZBO3yiq9mdGDkDyPmSGazDGo6zy2eL378iFsK5
+Xs/k9T+T2xzUNdLRpEfJq2gtYVxA67ovbaUjtkj5JtTUJB/hmVqSzFsJyvGRqdS/
+W6ZhPPMfPBCPb9RdiyHtDWY/39Ls8EneR6ZzP2tUx5hzObV9Lrf4gd6zpFIHtEtt
+8/u2Ns0wrQ9r//3TG0sAR/4l9O8V2y8rjDOpZL8csWWcpQVmdJI6e7/chiqTUI/6
+Tf1iSaUG55uBFn/YPQpGHXDTkntNTSQN5Ms5qnNdbcmjBGwnqH3B1o2peNx+Yxyi
+xcmsD4cStDx/Ej1yY+egyToT/ZvrH2RR56Rc+HltRYfBK8wUtmY6/g7NcoWFF61M
+dCa351LY+AZBQvfsg8PmypLnQwHg1AG4ogwLNUI0ygeVFSl1wAuDKCtpy6zfs035
+agU8J4A9MQPmaX99UFV6FWMv3+H3QDjTWqFW/37bXmFl03l5h1n5xZ0Kc786KDv0
+8tvy0csqW1MIvnzoyujghienP4OTfWwMPnCIqeAG0UA
+-> piv-p256 vRzPNw A3wssMH6Nlh9cBTsipou44CwzCE++4TarqGjObd2/8Xd
++WsJqumP6xpJfjg7yEc6NRRz+D2ksTJpgVZXqXalM18
+-> piv-p256 zqq/iw A3JV+cHOFLTBsfBDHM5K7k/lsUZsIvpkvx1rpUAjWPuU
+CowRYCoRJ9x1PswAw7aLUbQpvDiggBJT84/likBAHPc
+-> ssh-ed25519 YFSOsg +CaWUAu6+hp1xpVwKZZO9328d9E+bVIejGL5w8MuLF4
+YvwVnv/8exOf6IpjUlQAVHUBgLET8uEYEO/nH9+P6Qc
+-> ssh-ed25519 iHV63A didGnygsV/Dh+Ni6u+bCv83dTJakWe4lzZERHcpQ7Rg
+Y07PZjU9i7VKrzW3+K0zJif6YBsp3T+JMDbeXxGWq40
+-> ssh-ed25519 BVsyTA KENv1RVR11qe+MnytyJQHIcsUVBsXRwFDw344vGD53Q
+mRqWR5QzBhgbzoofIygPhKkbSjzpKwbc4IFJhCjurrE
+-> ssh-ed25519 +3V2lQ cocFFuJ/bErUGrE6jBvwzjCi7hyrUaZd6SMA0zuuqWU
+068MLruYKztolTd4F7nmsUj+BDGGclxEe3xsgrt/964
+--- IOwBL6PiBIiyFKMnwBrTBNqYPJONjpSHpuZX/QUjz1M
+�P)��i*�? Z�4o��Z�w�*��S�[g�O:"E�ٖ�)#�Uj�٠��y�
-B:2��u`�'7-l<y6p�i���1
\ No newline at end of file
diff --git a/secrets/trinkgenossin-wg-private-key.age b/secrets/trinkgenossin-wg-private-key.age
new file mode 100644
index 00000000..7164dd4a
--- /dev/null
+++ b/secrets/trinkgenossin-wg-private-key.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 NID4eA 1is1r32P3zZOSHUn+Whq3qz+IQ2D9tLhcJrfnjxMgnw
+iiiYo5Y7lRlRB/Ajw14h2+6fzKmppFwbdVLy3PrcUM0
+-> ssh-ed25519 uYcDNw 1vrxsNaJAanyB5Z0GRLy7xwlIsKa0xlim0j8BdNNdmc
+HtgE5xGQDIzsGbPQjzRlK9BF6bs0ILFyVylxf8dZFMs
+-> ssh-rsa f5THog
+G/kUjc/bzN4UZQWBL8iI3E8Xn6IA66M948ylC4hTMQDXM/Dmx2XO7sdxtbe+hxna
+x5xGEhrq3sNiEn9hiYMo3566oj/CgbevE2qx2RTG2moKzt5/GrIC7B4hUhf6/G47
+TcljL/T8hQ7FyvxiHFy5ga5zRxmt2f9WMfdMwcJXeuTNPWVvppaBRrCZdJCDf1wt
+ziPzOioc5Pa3/nnakBxB2g0R3c5j5/Q8JGF9PAi86t3Kkd935cv8Sfaby2CG5xx2
+DyFg6Q2Xu/h9XktudrEcWJYAOojaEKVrJzOG9iEGtxYqAU02uQHpJ87hmFS5O/8l
+nf94JKXihgU41Xm9BqtJa/rJBpcvgGCJxIKzzja95IgobkvDcudCzNpHbGQyAVJI
+dEfY0xAuXuxqH1b27qM0E46pU3mfoJjXNjDJJrFZbCgiUEAd8ZdupEV84HTen4Ok
+lZz2LC62S4M8l7YR84SGhJ+61J/dSkSMSmCBTL7PNRuPEDrITP9zsYcJITxV7baE
+3sEThce8OTWip5HQTEUjM690YG6sngRXyNLxYQS+1j1aJtpxIaucSjAer+R06pQl
+rgTyw8lr9V5u9oNYs+UkgWVul5/c1DYHmiSV22LvFIFZstot348iHThFtDYDaPdZ
+PkZ1sYvCx1a/NE/GVYzk2i8wgkCPzm62hUyYdVP5xBI
+-> ssh-rsa kFDS0A
+FpQtkQBp7Tqlw/KV4sFzQjnAG5Mn6TI3d5bc+2nz5F9xP5AWbEzstPHj/DguOpBm
+9Z/PERJWAwo1jMEq8Kc/1t9uIJ8qYC62nhTSvTrcblrFH3dtjKW/Dznk1OQuC9+R
+GhxIx91L95foQ09u0KWCkV/NH3R+txTpVOuYjBs8d48uGH6IUslMk5lf+WaY3ttP
+7aSn94jGqHDjVdo/ZTZ4fucOHAsAlptxqxAKE0mwZx0/vcGG1AdXdVSdwc4vGPhL
+zYXHWrfB7AGTbyzA8VpOs/SJpyVM9EQ6LKbnxRNUle9gKkVMKFSNYGBp6AImhwFV
+2UySRTHktLEInBTfjoLsR8Qp7UQSAeWbKlOdwvymj3Jp0hIbi3mL0Vo8VtduOfMG
+EFzhS3ZAC1ns0+CFKDa1HDwSis6dVBtvS4CV0V/TTpsBl31FjhqFgDPYhuESdwrl
+PBZ9GAWLXHD2Llh40WCvce6c+PAzVaa1FK4fQZIIBhBiHmno7i/ZF6hc9pZ5aNbs
++F3wrRxLstCSgharb/2ssAku2E1G5rwi4FDc5NFMo7vL0X27N7LS9b4GcL4IO8JX
+nvv5TaYPxLovy5hKO7Z0fOUoNzQYOpwT6ThG/G8C4JeznM9xzLo11dkPXy1FdTJo
+DXjmQAf9mL+duonU1tTv3hGAF1lFzfL1y+xTfJ5QlIs
+-> piv-p256 vRzPNw A2huTkzO8upwwylGpIRm0COiqYmuVXvQwedmUFlLURkn
+Y6KqsAhrml22Xrb9yYB5+7aC1qKg+UeO3mJxXJy/6zA
+-> piv-p256 zqq/iw A/+cX+vykBF+79ID0X52UHghRXEguX1lp34/bJ4GMK0C
+KsVxsu1etpbdxFIFpDYsSnUQQA+szR0iGi+Eu6X6t5k
+-> ssh-ed25519 YFSOsg wkemzA9T/gNLSf4Kngw72OSjMydYRVTbuQ5IncBpGyE
+tBZ/m65T5+8E0o3ukC0MAYcXv6iPOyX3/16b4PM5S0g
+-> ssh-ed25519 iHV63A M5/buY1jQzvGhSSUwKlx2MDlWcFK+Az8FlFLLcLAeF0
+zQeG81Xz52LkrBZcEU3E12qV+b0fc4Y6R/FxAyEHNvA
+-> ssh-ed25519 BVsyTA QJa3CqRMH8gv8w0N2sSo0t2NM+ZIKyeu2UVbqBFfsTI
+QLirOOVDg8HPmdxjzbp1gEVV7Kf3YjG2PWxpbjR234s
+-> ssh-ed25519 +3V2lQ Gw6BmENvFBUZZ3CnXyRFLn69a9l6WUQPUR3ErzC4zE4
+10AQp6t9tr0lyn55aJvT4bkYXzDMy2aRoqFUXR6rmOs
+--- 1NVDNHA07Rf1nptW8Me81WU4bb6zaag82ttOL/rqkbo
+ @JBi�c��i��N�Z�����|�]���dU}g�aG|d*������]��=>�]tfrM���gԵ���hvX�ۋ���
\ No newline at end of file
diff --git a/secrets/tt-rss-database-password.age b/secrets/tt-rss-database-password.age
new file mode 100644
index 00000000..8a5c64d5
--- /dev/null
+++ b/secrets/tt-rss-database-password.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 iDKjwg hN8V8IpFMqDsN2JDqcbzpOdO06OqZFCev+GRozWU5Rc
+SQszi7zkFTZM3KQ9DhmkXdEWK3e5omlJQtXngA/6LYE
+-> ssh-ed25519 uYcDNw JwFr2NXmB/rsWK7bJbpddlwxlQPrRjLyKtbMSKLvyQ8
+Bi5+ApK942D4m94IePeqC+Ba9oVCwQ1SvxdWUc9Lx6k
+-> ssh-rsa f5THog
+x+ZLzm9DxyGEqU0q2yETII9+RtBW1smQW0ilj6N/Rz89e79FugNzOwMbNOub5neR
+bF69YoKK5nDYwKZqiuDKCvcTbIEBzTSjhhXgncDqEx3/mvUZJ54g6vx3xoVKI7hZ
+fPkDiAdODMmXsKjjTtzXvEGz75+vhvj8+qKD+f5G2z6vgJOUItlXqDqEYA+gb70/
+32bJe8dZ2z5rQIjmkBqgIFm+RPai7RDwItIAJNE8ghEaCwwYncopUgmI10djRKaA
+WxIeZhiimfQd3ZrlyYdY012K/Wq0WhYtpfl7qjWcpspYZq22ay+PVMM9WEM6hKEq
+NM6af6WgZQzOWgYv+0QQt6T+WVVFj9WlrCETrB8hBTeUb9c9mfKszLlG6DI8MgYo
+syTqppSL1y5D+vC52M6Bj2Dk3AfftCGXWfH18mVTWgKY/Wgpg2WNkJp+iVagoY2f
+oy9lyMDJ12zNROzbukV5MM7ZoQciuk1QQtCmEo5xTcZZpTsyVnN6jkclT8LYrF/5
+BQ3chKnRacxdzuFHZ2V3tN1WMQnc4RuHYUNEtYjEqobUp5lxx3RLz6Rj8UIZv+0D
+cszZyQlgXyVByzKWreR4jN/wF03XpeiIR13TKzwdxfISurkql7jzFC/OxyQURqCu
+1YWTpqTVTFUIXDpcmVdPMLjelYl3MKSAQVhQ2/VRv/4
+-> ssh-rsa kFDS0A
+dd4nmQif4Tyhd6RHARZXMyblq+o5+KUu3gXqVkRYeQ4Ju2WTPeghCBJ8eB/uCLK8
+jTuo7igrJrhCREEnMnyLhnMVW3RA3BPRYEsVTRDztLS9TYYm95jtvrA6FQHbEJnw
+V8uQ7AUxOl3odX7Kwzk49Ou8egjwR28GD5POmNd3QzYDXv0H/WaGR+6hEwJm3Cbo
+2NrSMPIhZjUiv6bYX3WNUqLF4ZhLvNSdpSczuf0Ppd3x6mcuK6YsAyab9dBv2Mbr
+Ho7CsissZQFpx31salwIpzE+aaVZXwuY7n4IOFygHUg7zmpA+1FYl92WjKc5m25u
+/IJy+KOYA5JYkEdhASm3fd0dtq6mxjMR7vFUk23Fb3RUmUVwjIXrncCV0ixYlcPa
+lGp5rqDuW5BKNnSFRMb/yZ8mrrDsOIN2+OiKCcYbxmY2nn8F5Zg7LHnoS8UcV263
+Upqv9u6idCbKPeZRtV8BM5PG1C0HYW8LWFNfUCF+MKg5X/5Y4ON5F61ZGOMjufGE
+/Ki1b30vV48ESSqrG+F0Ck5AJ0cWFDhQgirH1kmvYnc1NuH6CHAZ02HbU27CGJBK
+FB2Oc7FR3fRghKPnEyxYYinc+2kJLwuz1S3LvI4BGa3ZJufsln1Jf9M/mypftX/i
+6FAIt55wnm0KjphFoADxfm8l2NqEd7dQaswRccFaLxA
+-> piv-p256 vRzPNw A1uUvbbM+wXpnADilNWAsIlq8Hw91fcPAIH+ToZqzxEB
+OVF9Wd2UINvL4f3tMbvghrxfcYOWPTqSbcwOvDwXwe0
+-> piv-p256 zqq/iw A1F8cm4YZdR2XOEfluMc0adxCziGZicuNq6JxBJrDoA3
+/r0bA7gdhivKbYJqMsgtXHVwljFUVTv7C7u2f/AI8Yc
+-> ssh-ed25519 YFSOsg FPuiOurOP8hYlMBi7GQTDOninLePF0jZ/AEkDbv35Hg
+moIdWebdzkpDksv3t4U0a3DbVaYwrLlG9J28leIbiHA
+-> ssh-ed25519 iHV63A hLw9QpDIPt4r5m9oogbGMKZ3VMIbPlThGRsOHZHb6io
+UQLIBoVS3hVRBj3gCf3AFQO4UmkI/LEFeo3CEuRf0ko
+-> ssh-ed25519 BVsyTA 6AxHFuXJObyjSp9HOZ+n9dE+oQu1qhDD4mW6cSHargU
+u82QHBX7Cro85ZD1vZa5vrl6RoYkBPUFqK2rH7szwhY
+-> ssh-ed25519 +3V2lQ j5yXugaCsEPU8ryp2w5+9FF9BAWI+5CSR4RsP5K+Kzk
+9RLONjDCS5TylGjoh6NlNdwMSCeZAIWWkN1yKn97GQI
+--- jVMtBDjAcHOdQYChnPzPhSpirEjgtWq98BbLggqAhmQ
+�f�ʢ����cө7��2���6/���t,P��e_0,f��GU�گb^����N�B�T�?��J`�
���ع_;�}�
\ No newline at end of file
diff --git a/secrets/tt-rss-feed-crypt-key.age b/secrets/tt-rss-feed-crypt-key.age
new file mode 100644
index 00000000..904e614e
--- /dev/null
+++ b/secrets/tt-rss-feed-crypt-key.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 iDKjwg dU5fIXm6oulBzoP1O0fW7kfm3+AnpFlc1vyAvEAOyRg
+t1At/esPyH4Z1Aa8Oox8uJN54E1IAieA91boK/6e1xs
+-> ssh-ed25519 uYcDNw IpelhE6Y2oqofsx3Mpm8WMy1c4Kj7n9AKDd6MmfkAyQ
+mpy2p5+wD250d4st2yPDxwEO6V5316mX0R+3er45RqI
+-> ssh-rsa f5THog
+eJi3xg3zkoGpevd3DT5wRwKOHHGpdypTKLnkyucMaqX5+uFa1aFzO1/kWj+sa1EF
+fvyi+yjregOInQG3Jf//nty6KdYUXmbOM5wqw+V82qkYpTLvAyAwT+2R2hHyBFzD
+QO4v0Ikf1jOOPmxa6ebA6KhQxRHvJcRmclwLUVz7pna6yOg8AeCIzP33ENrgSDBB
+RRIUKon2rrJXPN7q/ZFnw9STqZZPPyuIpmkNbJuoyCr5vhb1egtBj++Sw1R1FW0L
+m9aUR/Ta1OhJ7ccXLLSgRc2AtpdBdPhUCBDRJrX8Pj+dfbW9WwWUtyW2j/UXWJAj
+SM54P9gOTOZ37ZgwqwOpiueOVGxLDd5ddsUHc4TaqgfpDkyMZazkdA5gv4BFDMGr
+J1m2FhzHQVwXp9yE28TZoKS5M6YKQrWYWRGqQ6uenilLJTGWL1uwIPAGUl8mgzBs
+ZL8GfMN7AfQ6Qrbv4d8rtrJJ7Aj1foD007wzZd8MjLCkT/ib4z6kjtIk06ROJ5uH
+WoXQOcvted7D/BpncK7zi+pK8mH0uZVYgndYLnavWk9OXKmZ7ikJASsAAchVPs+s
+9zp7MKWu+hkO0Sd5zEMB/pWPmRL/dGLaIz4lvPoNEInPl+OSG5W0SSs2nmERPTn3
+EaLisQ5vkgK37/R/L3cWWgxrBWbntuosB/uw0tvMegE
+-> ssh-rsa kFDS0A
+lSyD7GI9cLFi/il/v1vZPogyhjQ7Eo+K7peqcQN7iKYH4RSGA5I57vZyFUVKT+FV
+0ECoXyyKH+wliN10K/obNU6eaqSEYOdsaIaW8e+P5J4sBQVdFWmX5P5VWYQ4A4L/
+2nR0Z8r4H+1CMzPc0Rq3Gc5NdJhd5+G03RPYcCim/WL78QGhGZsBkmZUXUVka5hA
+ipU1YM18EudrWukdtfrYL2vocTMf0NtilVfYF63IYA7FE6+oeBohAxYt5EpqkO7t
+G0d5DZ+Dasgl9QlEflMobuH1W1/f6+O+7RXbfBYgQXhRQvp1f1zDdz8sWJrAiW6D
+jctSzD2o1LQ27nmSXX3PN+DLxKu29bU+zd88k4NPhB+Wa3Xv8ZDFp9mC+9/+R8Mo
+0mfYbjOBTh6HJ0GAB43kSDDOvbynLsPtyoXqrALcVWMu8bQyn0NH0aesUvHy9V1r
+wDco6g9QN4ufZeWvMYAcoIzo9VPSaGv2X/mjKOb+BSESO2yYdekQenkuHRvQxNUL
+y3/PQHdpOA/dfdmDy8M6L6TSzs+Vxe7rG18Xhz52SMmTzHridxtsno9gT4B9w6i7
+/YYbHlUDxKY5b2jrduGdiPhRNSMvW6UHB9Q/nqUl80apT7BGxkpZ+nkLeBWd2Hma
+vmqPqZ2hl993p1AqpwkRcoPe4+Okil7cAJyfjHZNsS0
+-> piv-p256 vRzPNw AgwgbpEx45g9gQ9NdOJ9TRZvCWaLjbUhbprNKZJtahz4
+rcBJ0e1xVHL7vNtoXwOIs8pX5E7kRKSm/dr0ceAjMN8
+-> piv-p256 zqq/iw AsKNyiIKxdUhpUVeoLI8BrpFNZ61L+MjIrJrRKeHafv7
+AOXAZZilihL95W8TE4hRcE+LTEoOT0ZNAXOMroChHi0
+-> ssh-ed25519 YFSOsg +EPPAG4BQMJj8J1hez3aNJ0VgHCJf03bSRldknmnhDg
+ssrBYfAOMq/J4wLx4JfBMpqc/wedLX6D8lJB8/VQCFU
+-> ssh-ed25519 iHV63A D2T1A7mmN+5JxcoHjqj28UzdQRUvdFEI1uPdqjva1VM
+K6RDPNB8C+kf1VAFp/PL/YGWbMDGyctObvSxpy+3S64
+-> ssh-ed25519 BVsyTA FQTa9YZHuHyvbc2aGMii1oV8+YZknYiMlvAZFXaW/V4
+NEc7E/WSTtiZBgcIGVzhZNDb6n8uX6SPjRX2oQRB9RI
+-> ssh-ed25519 +3V2lQ A8VMdZjmx/vGz9dnPbJqTvH4oeg8ONfW5MCw7p/WmlQ
+vd8OxuP332eFAoSbQeCwncNtIUboObsNaMgYZhnnipU
+--- 8B7Jzu/OQYVIQxJWC+b4WcjEUtYApfeAy3fkeZuzw+A
+�(��_�G�(+|+J*��E샠m��d���ӵ:�,�.0�f����"YC��F394
\ No newline at end of file
diff --git a/secrets/tt-rss-keycloak-client-secret.age b/secrets/tt-rss-keycloak-client-secret.age
new file mode 100644
index 00000000..46e6bb67
--- /dev/null
+++ b/secrets/tt-rss-keycloak-client-secret.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 iDKjwg mMzhH6MqV4ix0VYpjka5/4E0DiKt0o/hmFGle8ZXBzo
+mKrIjVEAIpip6Pd5FBVRaKRVHVdjG2EZoZKtTAoXzaI
+-> ssh-ed25519 uYcDNw Mu8yjooNdK/RkwGti2RlDUNWbBDkZoC1ytkGeowX9Uw
+IlzuSRgVHEf1bnKRrVmBs7yUZbvEkiV3okobTk0EulE
+-> ssh-rsa f5THog
+QbBUjPa8wl1hb+ySlHBEVlAqfwRdhiy70Gn8L1r5QvKE8jig5Dz+J/w4N0/9sJz8
+5X4beaIKL6nSWqoslX6hAfcmYinMvGVJzfBWUfn0fwYeAgXf6EWPH3kcn3D9AYs/
+d4FSriGIPZL3xY57stn+WNqnd3W/h6E6amCbJIu4eq8oTut41qbLgBNrsBk5TnB0
+et5jye3BxBCQgh95p7vh30af05DxKPa7VTwIR91Y0ZhP7uefj1EObiCVpg85FZ3L
+9zT05QtUWilhVJpFD70LWwiHQuByPus1IzPytCxK+VubfwB4t4QA8iMLHQu4nYVw
+zrvc7zKtxtDJCTHXqA7jL5U0a3mHfYK8S1gTM2hgTDhnm/0lrFmKt9gBHwdrJC8P
+mDRAb5g4FH1dKqrKYW+XDX08Eh9HmaTwhoQhx2aPg8fR2SIhaArKgfrSgs4EdGVw
+5DtfSc0V7ct03VIGc1Yj6tl4vUnIvvbwAudfwhjTrPVpczeiCC5KjanCEq5uw5ck
+FZCkYNGfeSpvlyisuk5qldRQSovkkhKiuTSU3Zg7aXX0q8vhcTZfaa9eU5TFDEhA
++8e5Pnbxl2IPB85tMSMPpbcMzmI+GJnwynrD1bwc5j0hE9KAqH8jqPZDvODITXJ9
+JWhaEavVLfB6phTELbYy6FQmQ5nng8X0P1x1v0lj60Q
+-> ssh-rsa kFDS0A
+fYDoHvd7w1CqMtIK2N5bMkXmOVHsM43DoxSBYZdw0w+pGA1UiwIOQLOyVXlboePk
+xAVi/5fzR7UJioTFmNbAdjoGUxyO0dGrnguj6F2ZH+uhf+Gfu0YQ9mI6cfV3PJZW
+VVD0B7aMiOlRJ504Kk2dh02BM0/EMI4mvQ8hJ372xSkjKo24DXPY5KHm5EQh2VjI
+e8Up55TQF/qnHFidDBpXharETPJ0Ue1qSDTvylfRrma0kVjbDcMkHX/s2dz09U+h
+Eka0Zx0zLNeqeDDFUDWGl3106RquuFYcH0SvdVZMclYcrWGdg0jb1T2IZaNy3dTQ
+mUZe3wtJS8N72XrNdfIrTy3C3bkoEqZsVS8LRoSvMpnCxJoclj56wkcPEMk5Vuga
+CZl1J78+XBfuWqjvzlVMMjminJQYktH5NryKF1ApvdkeCQ3mnvClfBxO8xED/KwK
++s8Xng7w45eEjjaqVrxBjEEL9l89fm7HSqsVggl81H/Kr+EGLZypBTUZhq9oTvzQ
+ssYWFVnKJb5gX5cWv9MMwQPEFSPtblTw12d+7pYCkzCYJy9EYvBnrgLmR7XLUm3H
+YBcFVb7HHCgdSV39NQW2us73VV1/BUBoH6PyKRXpUXPrXTGSgxHy9vFMSrz61YRB
+vQAv5YyxHORqXHWuUvk6+pCrgULa/BF7Z5CgCoB1tPs
+-> piv-p256 vRzPNw ApDrlrsd78YhnqJyEOat3UWUyB7t5qHaI0hZXibitDbt
+im4viuyFZyFz40qoGnUpTx6q34uT6FH6rL/3hio7+Hw
+-> piv-p256 zqq/iw Ao8fRIIAfiKrLDSUXjlMEJtNM3OiC5dlGY1gjU8AOu7X
+xvFCYJXD7SQyDdRcd4l9CLngxUXfEsvQ6SJS5Gqy2a8
+-> ssh-ed25519 YFSOsg zTkJFwxhNAuk3+2SSYO55w75vc/aF3ITNBSfJ1scjxo
+6lTOURiikuEt5AMs758bngbA2PoFDG0XKYuoEXiva0k
+-> ssh-ed25519 iHV63A hAHqF1KtFDYS6VD9cD7dZIZ4dRFs0U+P+hFcEg6maX0
+wqz1SXml5r6rjrouMWHwl434SvsYnEnXiAmSD6joVBQ
+-> ssh-ed25519 BVsyTA cMFW6z/n78WfLsxgdxwTeRsd7yOIi3EhzGSBTy5UGh8
+sph1RQxczvV518OlOchORVTRIDUCzugfo2WBF0Rqvs4
+-> ssh-ed25519 +3V2lQ jxR0jUkW9tYINIuXuU//9zcAJ4xevGRmcf0SOsjdkn8
+d2KmbYwUNjNjWQem7xG5SpDHYTDc/FFwR3aaa58WRxU
+--- REXqCcIZT/mWBfx56TVIxC2ye0nyh+CNfj7aYfL1+1A
+2��ΝNH[���z�(e堇 ��[k�h��������b�����N��9"��w�
���<?aα�
\ No newline at end of file
diff --git a/secrets/tt-rss-smtp-password.age b/secrets/tt-rss-smtp-password.age
new file mode 100644
index 00000000..4855d3b0
--- /dev/null
+++ b/secrets/tt-rss-smtp-password.age
@@ -0,0 +1,43 @@
+age-encryption.org/v1
+-> ssh-ed25519 iDKjwg Zn/Fz/Al2fyQLTiMGIlu2p3sDHMeUktUpo7ZxmsS63A
+k93K1/dELZzuwVxfYgI+y3kz/kI7xs/qopi601SFycg
+-> ssh-ed25519 uYcDNw k4Px1Oxt27bjO9EBIOE0bvVOpJdAVyyYsPI91Ryu/iM
+SDAj5LeplQ5tnDZvfrW2KUD0nIH2GZ9MBiT5hFaCHZ0
+-> ssh-rsa f5THog
+yC9ONviP5h5mg24p2Fn9J8tlBnZVRecCJVuOjVPspWIM4qHhTS2PWm6JzfxuZ5zb
+VO5A0I5p1wNkmVRGR3aUIVgSRWUI3wf4J74xlRuHdeOZWpb/GXQX+AFY2o4vPsB2
+8h53v2/yBwCtFdqVopghTi99yJV56X1cAlkqvywXkShY71Gchu2cNak2lNaPPOcs
+TlJ2lJbiH2khYcAXwuz2jJI1jWvJNw+/scBGEegoFp836OJJjxOFj9yuPsdhB7VN
+ceDSCZNke3nZCwOKl5Qf7niT8W43Hj0quYCLX0g4QcBTSX+VHY3af/VtWqggsOwU
+Eh/0DAg90skuLZag+nRHJLrBxq1HwotvG+DdEJ3yAO8EtpVp3hHps8sNsZZ11kNe
+NWodOdUFffb1EpIgaib7uybL7QROnK6S69LAXQMd/9zGmy158o/hejeHGs7jpux6
+phoxU8z3VpRmTnzTuNW9AmSzZ0jMWb/3LKNMrVj/eoncTDnPEtox/0U6YBDa0ybz
++eo8vvyXVkG67/II4UdN5UvQj21zGr85I7dsQ+NvvuwlHS/GK7PFUyxHkPJcqMg/
+GTN7xuWS/MTnylmhqAmKvsGCb29Cipz646x+t0/0qBVyF3H2PGQRNaQwMfzOuplr
+/wcY/t3BZdAHsNWmqxOqVbeKDsx9entVhG1pGKgVtq8
+-> ssh-rsa kFDS0A
+ZhNJJ/MP/AauTmW+GMWzNh7bHdKgvn2KM9UcTLlkklqO6Yx0mg+kzhzHiwndHPX+
+mrBohHI67avzR52OUgDpbVLd1CQPZcLz2GD7n8/ozn7EjzC1eHrGKeKw/hf8C/2N
+qvFNPQ3MtEA4BQ2dwSMbWV/gjphXf+Rm/+qPtyeBqU6yNepAxqgZ3PCfr0QByqeE
+SY8hThxHXL49BCpDHhxJvAqZtxVMbtpHO0AIXSVQ0BdD9hylPpkhbcx6PhRbAd8X
+UxUu4XO6GJSKYqVcwwGeqoR7C1wvOgcGvMo/tLTx3ovzvpcnyQ9KCemENYy9dE4Q
+Nn40qRrOR3NzzUW/ONs93+hVswtpKTivP1LMegZxAE9EXTILflzFjmMsDLmEWY3M
+i8GPr33JOmHxTkwY21SD6enYsQtbsVdreQd0FJZesXBaLReAHwXDpMlA/Py/iqTY
+RYXuxw3RgXxvHTV9QdsArq7Tz0euVUoEXC6CiYlH/1TPJByj9PibJoT/OoQxrRyj
+7wemAPvN+sLv6Rs5ZeTrJBKIinvuS7k5OiwKxkJGLNPgYmRviyJEQlqVMTHNRN21
+RKkLzJrIDjJ6l+tW3wwDARDL9u2lxFoVF98GdOGVa/yZvKbJGECJKLGQ6bEqVomQ
+sN6k7/ydbOfuPwtq6/Ax8RVKHkdfR5HORFiRrEC5jc0
+-> piv-p256 vRzPNw AlL/+S0yI6mpICDYlVboboFBrLTGjP+xPoWJkGVqVide
+zaI3+1ZmGzE1E+FKtvLuabepXuM0YYwMPQQUQhssUm8
+-> piv-p256 zqq/iw A5ef4pOc6NCKaCOev0HRg0yvECGRXQkkW6qcOBwOTNne
+hfBE7el+0M3+dDWOepMyiB7/hhMjZ6AsobfxGFqMSkc
+-> ssh-ed25519 YFSOsg GHsjugc0+RzkSCU1VFs1BKLB8MGvkWef+axklDUS4Qo
+zqEJPv9QwBZwb4s79w5CP3T64vlXVCbsWiDP1sgjgUc
+-> ssh-ed25519 iHV63A NJZEaUKZ03Y0cmkZS+m5ckmMYsOoAb9J22isDTtLeEw
+kbqt8Xce6gSjHg76Z5HXHDoXLCfCcjkC0O76/0fJxwo
+-> ssh-ed25519 BVsyTA arqPduVIieRmtyFaoeovsOle9nNhc18IBFmJJPTaoWc
+QfrfpdGYiK5Y4w0YFA56u60T6CV5qwdfQZKAr7UQqYg
+-> ssh-ed25519 +3V2lQ 6oZIAyrrn4GezQ5K0YxwVL3ceKpwgtZoZ00M+aREEi4
+kBLTRckPYLtKug0G0vN5ix1Oa08iP5hZA2XwGSuY8ug
+--- JTzuhPCSkc4zBpp6drMB7/4WKke+q52srW4hiRM5RFo
+�`l��g��z=u��Ŋ�fvwo���^������F���~��&P���]���ͻ'�$�
\ No newline at end of file
diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl
index e007f5b1..23a248b2 100644
--- a/terraform/.terraform.lock.hcl
+++ b/terraform/.terraform.lock.hcl
@@ -1,23 +1,24 @@
-# This file is maintained automatically by "terraform init".
+# This file is maintained automatically by "tofu init".
 # Manual edits may be lost in future updates.
 
-provider "registry.terraform.io/namecheap/namecheap" {
-  version     = "2.1.0"
-  constraints = "2.1.0"
+provider "registry.opentofu.org/namecheap/namecheap" {
+  version     = "2.1.2"
+  constraints = "2.1.2"
   hashes = [
-    "h1:p8LqzJtI4Mkxhcam2s73eFJzctlAZXZJ0Wwgd51Kyto=",
-    "zh:3731f5f14a0958cd27a589ef7daa9be786b6490f2309c429eb2e9862aa4ac5f7",
-    "zh:3cbceb12ec3521d9dfbd890eee731a40f4e1f42de30d28fc1d1e524091148caa",
-    "zh:44095af1b1d1ee6d4b930e21e3c5bf0f81d9df65fe04f6f1e55d46713c240b21",
-    "zh:693e169228fe0c5fb1989425b1ad42c1206f8187c9932b4daee5a5c5e851a28e",
-    "zh:6b04c3c2666db3050f49bc85151496fe33cf852db9ad8fc6f455d1daf0a2bba6",
-    "zh:85fd126a573cc468f8d5d1b90f4a94f5977ea40623b1c5cd7c799bb95ef233bd",
-    "zh:99014437ef4e96161b0029efa12f05fa1ab63ff9bc0a255b0a249e17b4f8587a",
-    "zh:a4d8288ef01d4002a5aa07d1e64e4504757f07d6ada24fbf7d3670ceb24d2871",
-    "zh:d27f7798cbe1957294bb08459b1fbabe68721cc9cc50afee80bda87ce674dab8",
-    "zh:d85483f90380829d05b8a2725ce50bf2ee766d6c1cbef223b388d19c5a92dce2",
-    "zh:ddfecfbefd32e40386b482a2610e4173a52591afea3861f041041439d51d34da",
-    "zh:f9a10edfe11dbc4947cbb2f0db8935050693d5fff3b6559096288c689c2dd847",
-    "zh:fae14a74781a94bcaac07b6d533dd9eb1e40c1d152eb6ee49b2a44cdf5740cfe",
+    "h1:CxrZrPIQwzPgWoU/YkCrU03GsB6EVgjPPRuUUnu7zs0=",
+    "zh:0aed3d71075afa43797e72fdeddd444b6e61c4b891efb06b3d1e32ae50f8c443",
+    "zh:11d6119e3b9e0c92342ed5b3d230f0a9461242f07fa6c6e03f09619a4b82bb9c",
+    "zh:12ce14c749e1e6089ac779fd9dd11d35a5934490e480acaf325ab24a869821b3",
+    "zh:331fe9b343870f75bc046e9e94cb4ecf13b0197ffc1ac1350e14ced371295360",
+    "zh:38d8f7ee36f1b3ca6bb2c4a4acadcefc39f556b0d45212fd593ca78d7600a90e",
+    "zh:3f5decea8777964b4ff40a42fc9154d4d7d8c43985c544f865aa627ade85f78f",
+    "zh:78bfc4a448c868b07c66e7aee4190ddc9c62c677408e3e075a665ee59d0745fa",
+    "zh:80c8be9b56825d61393f1b2366b6a5c1072b39fac4f0a62c4b7e28e5dab932c1",
+    "zh:87c8070cf579a850a8099e5652c930bd9d0923e4d3af8509e3123defc4d2d4c7",
+    "zh:8cb6954feb50fc39bbb0a08e030e731f54357261741c7620e05a7bc24070f37e",
+    "zh:993a3e876209b1de0bb8266b451b75783ac65613302d18002f09e13ec5b64f42",
+    "zh:a501d7681e9fd3842d3516e8b168a08a7ab8ee1722f43425b09c3bd950dbdad5",
+    "zh:bf59b03f9bbf455bc63e1dfb19cc67247252680681a31f4283f0802bba11d7e8",
+    "zh:e97bd12923b0148e3e7ea769443f7f71beaeb7e78ad9ced0ebe21d3ad6c47b64",
   ]
 }
diff --git a/terraform/dns.tf b/terraform/dns.tf
index 60226c09..cb3b81ce 100644
--- a/terraform/dns.tf
+++ b/terraform/dns.tf
@@ -1,181 +1,381 @@
 # https://registry.terraform.io/providers/namecheap/namecheap/latest/docs
 resource "namecheap_domain_records" "pub-solar" {
-  domain = "pub.solar"
-  mode = "OVERWRITE"
+  domain     = "pub.solar"
+  mode       = "OVERWRITE"
   email_type = "MX"
 
   record {
-    hostname = "flora-6"
-    type = "A"
-    address = "80.71.153.210"
+    hostname = "nachtigall.wg"
+    type     = "A"
+    address  = "10.7.6.1"
+  }
+  record {
+    hostname = "metronom.wg"
+    type     = "A"
+    address  = "10.7.6.3"
+  }
+  record {
+    hostname = "tankstelle.wg"
+    type     = "A"
+    address  = "10.7.6.4"
+  }
+  record {
+    hostname = "trinkgenossin.wg"
+    type     = "A"
+    address  = "10.7.6.5"
+  }
+  record {
+    hostname = "delite.wg"
+    type     = "A"
+    address  = "10.7.6.6"
+  }
+  record {
+    hostname = "blue-shell.wg"
+    type     = "A"
+    address  = "10.7.6.7"
+  }
+  record {
+    hostname = "nachtigall.wg"
+    type     = "AAAA"
+    address  = "fd00:fae:fae:fae:fae:1::"
+  }
+  record {
+    hostname = "metronom.wg"
+    type     = "AAAA"
+    address  = "fd00:fae:fae:fae:fae:3::"
+  }
+  record {
+    hostname = "tankstelle.wg"
+    type     = "AAAA"
+    address  = "fd00:fae:fae:fae:fae:4::"
+  }
+  record {
+    hostname = "trinkgenossin.wg"
+    type     = "AAAA"
+    address  = "fd00:fae:fae:fae:fae:5::"
+  }
+  record {
+    hostname = "delite.wg"
+    type     = "AAAA"
+    address  = "fd00:fae:fae:fae:fae:6::"
+  }
+  record {
+    hostname = "blue-shell.wg"
+    type     = "AAAA"
+    address  = "fd00:fae:fae:fae:fae:7::"
+  }
+  record {
+    hostname = "metronom"
+    type     = "A"
+    address  = "49.13.236.167"
+  }
+  record {
+    hostname = "mail"
+    type     = "A"
+    address  = "49.13.236.167"
+  }
+  record {
+    hostname = "trinkgenossin"
+    type     = "A"
+    address  = "85.215.152.22"
+  }
+  record {
+    hostname = "trinkgenossin"
+    type     = "AAAA"
+    address  = "2a01:239:35d:f500::1"
+  }
+  record {
+    hostname = "delite"
+    type     = "A"
+    address  = "5.255.119.132"
+  }
+  record {
+    hostname = "delite"
+    type     = "AAAA"
+    address  = "2a04:52c0:124:9d8c::2"
+  }
+  record {
+    hostname = "blue-shell"
+    type     = "A"
+    address  = "194.13.83.205"
+  }
+  record {
+    hostname = "blue-shell"
+    type     = "AAAA"
+    address  = "2a03:4000:43:24e::1"
   }
   record {
     hostname = "auth"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
+  }
+  record {
+    hostname = "mas"
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "ci"
-    type = "A"
-    address = "80.71.153.210"
+    type     = "A"
+    address  = "80.71.153.210"
+  }
+  record {
+    hostname = "buckets"
+    type     = "A"
+    address  = "85.215.152.22"
+  }
+  record {
+    hostname = "buckets"
+    type     = "A"
+    address  = "5.255.119.132"
+  }
+  record {
+    hostname = "buckets"
+    type     = "A"
+    address  = "194.13.83.205"
+  }
+  record {
+    hostname = "buckets"
+    type     = "AAAA"
+    address  = "2a01:239:35d:f500::1"
+  }
+  record {
+    hostname = "buckets"
+    type     = "AAAA"
+    address  = "2a04:52c0:124:9d8c::2"
+  }
+  record {
+    hostname = "buckets"
+    type     = "AAAA"
+    address  = "2a03:4000:43:24e::1"
+  }
+  record {
+    hostname = "*.buckets"
+    type     = "CNAME"
+    address  = "buckets.pub.solar."
+  }
+  record {
+    hostname = "web"
+    type     = "CNAME"
+    address  = "buckets.pub.solar."
+  }
+  record {
+    hostname = "*.web"
+    type     = "CNAME"
+    address  = "buckets.pub.solar."
+  }
+  record {
+    hostname = "tankstelle"
+    type     = "A"
+    address  = "80.244.242.5"
+  }
+  record {
+    hostname = "alerts"
+    type     = "CNAME"
+    address  = "trinkgenossin.wg.pub.solar"
   }
   record {
     hostname = "git"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
+  }
+  record {
+    hostname = "rss"
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "stream"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
-  }
-  record {
-    hostname = "list"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "obs-portal"
-    type = "A"
-    address = "80.71.153.210"
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "vpn"
-    type = "A"
-    address = "80.71.153.210"
+    type     = "A"
+    address  = "80.71.153.210"
   }
   record {
     hostname = "cache"
-    type = "A"
-    address = "95.217.225.160"
+    type     = "A"
+    address  = "95.217.225.160"
   }
   record {
     hostname = "factorio"
-    type = "A"
-    address = "80.244.242.2"
+    type     = "A"
+    address  = "80.244.242.2"
   }
   record {
     hostname = "collabora"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "@"
-    type = "ALIAS"
-    address = "nachtigall.pub.solar."
-    ttl = 300
+    type     = "ALIAS"
+    address  = "nachtigall.pub.solar."
+    ttl      = 300
   }
   record {
     hostname = "chat"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "cloud"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "turn"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "grafana"
-    type = "A"
-    address = "80.71.153.210"
+    type     = "CNAME"
+    address  = "trinkgenossin.pub.solar"
   }
   record {
     hostname = "hpb"
-    type = "A"
-    address = "80.71.153.239"
+    type     = "A"
+    address  = "80.71.153.239"
   }
   record {
     hostname = "files"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "search"
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
+  }
+  record {
+    hostname = "stickers.chat"
     type = "CNAME"
     address = "nachtigall.pub.solar."
   }
   record {
     hostname = "wiki"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "mastodon"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "matrix"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "tmate"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "www"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "nachtigall.pub.solar."
   }
   record {
     hostname = "@"
-    type = "TXT"
-    address = "v=spf1 include:spf.greenbaum.zone a:list.pub.solar ~all"
+    type     = "TXT"
+    address  = "v=spf1 a:mail.pub.solar a:list.pub.solar ~all"
   }
   record {
     hostname = "list"
-    type = "TXT"
-    address = "v=spf1 a:list.pub.solar ?all"
+    type     = "TXT"
+    address  = "v=spf1 a:list.pub.solar ?all"
   }
   record {
     hostname = "_dmarc"
-    type = "TXT"
-    address = "v=DMARC1; p=reject;"
+    type     = "TXT"
+    address  = "v=DMARC1; p=reject;"
   }
   record {
     hostname = "_dmarc.list"
-    type = "TXT"
-    address = "v=DMARC1; p=reject;"
+    type     = "TXT"
+    address  = "v=DMARC1; p=reject;"
   }
   record {
-    hostname = "modoboa._domainkey"
-    type = "TXT"
-    address = "v=DKIM1;k=rsa;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx/EqLMpk0MyL1aQ0JVG44ypTRbZBVA13MFjEntxAvowaWtq1smRbnEwTTKgqUOrUyaM4dVmli1dedne4mk/ncqRAm02KuhtTY+5wXfhTKK53EhqehbKwH+Qvzb12983Qwdau/QTHiFHwXHufMaSsCvd9CRWCp9q68Q7noQqndJeLHT6L0eECd2Zk3ZxJuh+Fxdb7+Kw68Tf6z13Rs+MU01qLM7x0jmSQHa4cv2pk+7NTGMBRp6fVskfbqev5nFkZWJ7rhXEbP9Eukd/L3ro/ubs1quWJotG02gPRKE8fgkm1Ytlws1/pnqpuvKXQS1HzBEP1X2ExezJMzQ1SnZCigQIDAQAB"
+    hostname = "mail._domainkey"
+    type     = "TXT"
+    address  = "v=DKIM1;k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI333HhjmVmDYc5hYTtmB6o9KYb782xw+ewH1eQlpFcCMyJ1giYFeGKviNki9uSm52tk34zUIthsqJMRlz2WsKGgk4oq3MRtgPtogxbh1ipJlynXejPU5WVetjjMnwr6AtV1DP1Sv4n5Vz0EV8cTi3tRZdgYpG6hlriiHXbrvlIwIDAQAB"
   }
   record {
     hostname = "@"
-    type = "MX"
-    address = "mail.greenbaum.zone."
-    mx_pref = "0"
+    type     = "MX"
+    address  = "mail.pub.solar."
+    mx_pref  = "0"
   }
   record {
     hostname = "list"
-    type = "MX"
-    address = "list.pub.solar."
-    mx_pref = "0"
+    type     = "MX"
+    address  = "list.pub.solar."
+    mx_pref  = "0"
+  }
+  record {
+    hostname = "list"
+    type     = "A"
+    address  = "138.201.80.102"
+  }
+  record {
+    hostname = "list"
+    type     = "AAAA"
+    address  = "2a01:4f8:172:1c25::1"
   }
   record {
     hostname = "nachtigall"
-    type = "A"
-    address = "138.201.80.102"
+    type     = "A"
+    address  = "138.201.80.102"
   }
   record {
     hostname = "nachtigall"
-    type = "AAAA"
-    address = "2a01:4f8:172:1c25::1"
+    type     = "AAAA"
+    address  = "2a01:4f8:172:1c25::1"
+  }
+  record {
+    hostname = "underground"
+    type     = "A"
+    address  = "80.244.242.3"
+  }
+  record {
+    hostname = "test"
+    type     = "CNAME"
+    address  = "underground.pub.solar."
+  }
+  record {
+    hostname = "mas.test"
+    type     = "CNAME"
+    address  = "underground.pub.solar."
   }
   record {
     hostname = "matrix.test"
-    type = "CNAME"
-    address = "nachtigall.pub.solar."
+    type     = "CNAME"
+    address  = "underground.pub.solar."
+  }
+  record {
+    hostname = "chat.test"
+    type     = "CNAME"
+    address  = "underground.pub.solar."
+  }
+  record {
+    hostname = "stickers.chat.test"
+    type     = "CNAME"
+    address  = "underground.pub.solar."
+  }
+  record {
+    hostname = "auth.test"
+    type     = "CNAME"
+    address  = "underground.pub.solar."
   }
   # SRV records can only be changed via NameCheap Web UI
   # add comment
diff --git a/terraform/providers.tf b/terraform/providers.tf
index 0301fd5c..92debc2c 100644
--- a/terraform/providers.tf
+++ b/terraform/providers.tf
@@ -1,9 +1,9 @@
 terraform {
-  required_version = "~> 1.2.3"
+  required_version = "~> 1.8.0"
   required_providers {
     namecheap = {
       source = "namecheap/namecheap"
-      version = "2.1.0"
+      version = "2.1.2"
     }
   }
 }
diff --git a/terraform/remote-backend.tf b/terraform/remote-backend.tf
deleted file mode 100644
index e18597e2..00000000
--- a/terraform/remote-backend.tf
+++ /dev/null
@@ -1,9 +0,0 @@
-# https://www.terraform.io/language/v1.2.x/settings/backends/manta
-terraform {
-  backend "manta" {
-    path        = "pub-solar/nachtigall"
-    object_name = "terraform.tfstate"
-    account     = "pub_solar"
-    url         = "https://eu-central.manta.greenbaum.zone"
-  }
-}
diff --git a/terraform/state-encryption.tf b/terraform/state-encryption.tf
new file mode 100644
index 00000000..4c267b33
--- /dev/null
+++ b/terraform/state-encryption.tf
@@ -0,0 +1,30 @@
+# https://opentofu.org/docs/language/state/encryption/#new-project
+# Set env var TF_VAR_state_passphrase
+variable "state_passphrase" {
+  type = string
+}
+
+terraform {
+  encryption {
+    ## Step 1: Add the desired key provider:
+    key_provider "pbkdf2" "pub_solar_key" {
+      passphrase = var.state_passphrase
+    }
+    ## Step 2: Set up your encryption method:
+    method "aes_gcm" "pub_solar_method" {
+      keys = key_provider.pbkdf2.pub_solar_key
+    }
+
+    state {
+      ## Step 3: Link the desired encryption method:
+      method = method.aes_gcm.pub_solar_method
+
+      ## Step 4: Run "tofu apply".
+
+      ## Step 5: Consider adding the "enforced" option:
+      # enforced = true
+    }
+
+    ## Step 6: Repeat steps 3-5 for plan{} if needed.
+  }
+}
diff --git a/terraform/terraform-backend-git.hcl b/terraform/terraform-backend-git.hcl
new file mode 100644
index 00000000..117d185b
--- /dev/null
+++ b/terraform/terraform-backend-git.hcl
@@ -0,0 +1,3 @@
+git.repository = "gitea@git.pub.solar:pub-solar/terraform-state.git"
+git.ref = "main"
+git.state = "dns-pub.solar.json"
diff --git a/tests/keycloak.nix b/tests/keycloak.nix
new file mode 100644
index 00000000..2ab4ecee
--- /dev/null
+++ b/tests/keycloak.nix
@@ -0,0 +1,102 @@
+{
+  self,
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+let
+in
+{
+  name = "keycloak";
+
+  hostPkgs = pkgs;
+
+  node.pkgs = pkgs;
+  node.specialArgs = self.outputs.nixosConfigurations.nachtigall._module.specialArgs;
+
+  nodes = {
+    acme-server = {
+      imports = [
+        self.nixosModules.home-manager
+        self.nixosModules.core
+        ./support/ca.nix
+      ];
+    };
+
+    client = {
+      imports = [
+        self.nixosModules.home-manager
+        self.nixosModules.core
+        ./support/client.nix
+      ];
+    };
+
+    nachtigall = {
+      imports = [
+        self.inputs.agenix.nixosModules.default
+        self.nixosModules.home-manager
+        self.nixosModules.core
+        self.nixosModules.backups
+        self.nixosModules.nginx
+        self.nixosModules.keycloak
+        self.nixosModules.postgresql
+        ./support/global.nix
+      ];
+
+      systemd.tmpfiles.rules = [ "f /tmp/dbf 1777 root root 10d password" ];
+
+      virtualisation.cores = 1;
+      virtualisation.memorySize = 4096;
+
+      pub-solar-os.auth = {
+        enable = true;
+        database-password-file = "/tmp/dbf";
+      };
+      services.keycloak.database.createLocally = true;
+
+      networking.interfaces.eth0.ipv4.addresses = [
+        {
+          address = "192.168.1.3";
+          prefixLength = 32;
+        }
+      ];
+    };
+  };
+
+  testScript =
+    { nodes, ... }:
+    let
+      user = nodes.client.users.users.b12f;
+      #uid = toString user.uid;
+      bus = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u ${user.name})/bus";
+      gdbus = "${bus} gdbus";
+      su = command: "su - ${user.name} -c '${command}'";
+      gseval = "call --session -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval";
+      wmClass = su "${gdbus} ${gseval} global.display.focus_window.wm_class";
+    in
+    ''
+      acme_server.start()
+
+      acme_server.wait_for_unit("default.target")
+      acme_server.wait_for_unit("step-ca.service")
+      acme_server.succeed("ping ca.test.pub.solar -c 2")
+      acme_server.wait_for_open_port(443)
+      acme_server.wait_until_succeeds("curl 127.0.0.1:443")
+
+      nachtigall.start()
+      nachtigall.wait_for_unit("default.target")
+      nachtigall.succeed("ping 127.0.0.1 -c 2")
+      nachtigall.wait_for_unit("nginx.service")
+      nachtigall.wait_for_unit("keycloak.service")
+      nachtigall.wait_for_open_port(8080)
+      nachtigall.wait_for_open_port(443)
+      nachtigall.wait_until_succeeds("curl http://127.0.0.1:8080/")
+      nachtigall.wait_until_succeeds("curl https://auth.test.pub.solar/")
+
+      client.start()
+      client.wait_for_unit("default.target")
+      # client.wait_until_succeeds("${wmClass} | grep -q 'firefox'")
+      client.screenshot("screen")
+    '';
+}
diff --git a/tests/support/ca.nix b/tests/support/ca.nix
new file mode 100644
index 00000000..632c610c
--- /dev/null
+++ b/tests/support/ca.nix
@@ -0,0 +1,47 @@
+{
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+{
+  imports = [ ./global.nix ];
+
+  systemd.tmpfiles.rules = [ "f /tmp/step-ca-intermediate-pw 1777 root root 10d password" ];
+
+  networking.interfaces.eth0.ipv4.addresses = [
+    {
+      address = "192.168.1.1";
+      prefixLength = 32;
+    }
+  ];
+
+  services.step-ca =
+    let
+      certificates = pkgs.stdenv.mkDerivation {
+        name = "certificates";
+        src = ./step;
+        installPhase = ''
+          mkdir -p $out;
+          cp -r certs $out/
+          cp -r secrets $out/
+        '';
+      };
+    in
+    {
+      enable = true;
+      openFirewall = true;
+      intermediatePasswordFile = "/tmp/step-ca-intermediate-pw";
+      port = 443;
+      address = "0.0.0.0";
+      settings = (builtins.fromJSON (builtins.readFile ./step/config/ca.json)) // {
+        root = "${certificates}/certs/root_ca.crt";
+        crt = "${certificates}/certs/intermediate_ca.crt";
+        key = "${certificates}/secrets/intermediate_ca_key";
+        db = {
+          type = "badgerv2";
+          dataSource = "/var/lib/step-ca/db";
+        };
+      };
+    };
+}
diff --git a/tests/support/client.nix b/tests/support/client.nix
new file mode 100644
index 00000000..c34c847c
--- /dev/null
+++ b/tests/support/client.nix
@@ -0,0 +1,35 @@
+{
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+{
+  imports = [ ./global.nix ];
+
+  services.xserver.enable = true;
+  services.xserver.displayManager.gdm.enable = true;
+  services.xserver.desktopManager.gnome.enable = true;
+  services.xserver.displayManager.autoLogin.enable = true;
+  services.xserver.displayManager.autoLogin.user = "b12f";
+
+  systemd.user.services = {
+    "org.gnome.Shell@wayland" = {
+      serviceConfig = {
+        ExecStart = [
+          # Clear the list before overriding it.
+          ""
+          # Eval API is now internal so Shell needs to run in unsafe mode.
+          "${pkgs.gnome.gnome-shell}/bin/gnome-shell --unsafe-mode"
+        ];
+      };
+    };
+  };
+
+  networking.interfaces.eth0.ipv4.addresses = [
+    {
+      address = "192.168.1.2";
+      prefixLength = 32;
+    }
+  ];
+}
diff --git a/tests/support/global.nix b/tests/support/global.nix
new file mode 100644
index 00000000..f5e68c91
--- /dev/null
+++ b/tests/support/global.nix
@@ -0,0 +1,50 @@
+{
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+{
+  pub-solar-os.networking.domain = "test.pub.solar";
+
+  security.acme.defaults.server = "https://ca.${config.pub-solar-os.networking.domain}/acme/acme/directory";
+
+  security.pki.certificates = [ (builtins.readFile ./step/certs/root_ca.crt) ];
+
+  services.openssh = {
+    enable = true;
+    openFirewall = true;
+    settings = {
+      PermitRootLogin = lib.mkForce "yes";
+      PermitEmptyPasswords = lib.mkForce "yes";
+      PasswordAuthentication = lib.mkForce true;
+    };
+  };
+
+  security.pam.services.sshd.allowNullPassword = true;
+
+  virtualisation.forwardPorts =
+    let
+      address = (builtins.elemAt config.networking.interfaces.eth0.ipv4.addresses 0).address;
+      lastAddressPart = builtins.elemAt (lib.strings.splitString "." address) 3;
+    in
+    [
+      {
+        from = "host";
+        host.port = 2000 + (lib.strings.toInt lastAddressPart);
+        guest.port = 22;
+      }
+    ];
+
+  networking.interfaces.eth0.useDHCP = false;
+
+  networking.hosts = {
+    "192.168.1.1" = [ "ca.${config.pub-solar-os.networking.domain}" ];
+    "192.168.1.2" = [ "client.${config.pub-solar-os.networking.domain}" ];
+    "192.168.1.3" = [
+      "${config.pub-solar-os.networking.domain}"
+      "www.${config.pub-solar-os.networking.domain}"
+      "auth.${config.pub-solar-os.networking.domain}"
+    ];
+  };
+}
diff --git a/tests/support/step/certs/intermediate_ca.crt b/tests/support/step/certs/intermediate_ca.crt
new file mode 100644
index 00000000..32208384
--- /dev/null
+++ b/tests/support/step/certs/intermediate_ca.crt
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB4DCCAYagAwIBAgIQVR/3c0swvc/ifeYqLQn3HTAKBggqhkjOPQQDAjA6MRcw
+FQYDVQQKEw5wdWIuc29sYXItdGVzdDEfMB0GA1UEAxMWcHViLnNvbGFyLXRlc3Qg
+Um9vdCBDQTAeFw0yNDA4MjQwMTI3MTBaFw0zNDA4MjIwMTI3MTBaMEIxFzAVBgNV
+BAoTDnB1Yi5zb2xhci10ZXN0MScwJQYDVQQDEx5wdWIuc29sYXItdGVzdCBJbnRl
+cm1lZGlhdGUgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATpCjy3PAiawAeb
+47ZZ9kPXuuV0EavOfFlgnlZBkOc2AXY0R6P1jK06US0SiPo17rqyNgUWH0oV4v8i
+/HbZYNXYo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAd
+BgNVHQ4EFgQU1hueYsLAH6+wxjArqCM3IHFqnIEwHwYDVR0jBBgwFoAUxg/BmKK7
+9Zs+b1bvlpYwggy5lnswCgYIKoZIzj0EAwIDSAAwRQIgfxkjyC4HHADRmNDLqZ5L
+0po+JD5/9b1L//JoXG+vgXECIQDgkRe8r8/0Ep/NWgBtbkA3oTYq8vCwo1FewBZZ
+43fo5w==
+-----END CERTIFICATE-----
diff --git a/tests/support/step/certs/root_ca.crt b/tests/support/step/certs/root_ca.crt
new file mode 100644
index 00000000..71f5cea0
--- /dev/null
+++ b/tests/support/step/certs/root_ca.crt
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIBuDCCAV2gAwIBAgIQMXg7xoEIrVjgvKcrRaxo0DAKBggqhkjOPQQDAjA6MRcw
+FQYDVQQKEw5wdWIuc29sYXItdGVzdDEfMB0GA1UEAxMWcHViLnNvbGFyLXRlc3Qg
+Um9vdCBDQTAeFw0yNDA4MjQwMTI3MDlaFw0zNDA4MjIwMTI3MDlaMDoxFzAVBgNV
+BAoTDnB1Yi5zb2xhci10ZXN0MR8wHQYDVQQDExZwdWIuc29sYXItdGVzdCBSb290
+IENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYNxMcHclQP/zv2y6LJIGx9pg
+Q2337Zb8TuPY+DnL1MjuCMoeTaMwngzjU/DSbKL0Vx/y+I+PBjhHmPrYcGDcSKNF
+MEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE
+FMYPwZiiu/WbPm9W75aWMIIMuZZ7MAoGCCqGSM49BAMCA0kAMEYCIQDcgr9WyR1C
+806aEQ38alYgGg3PhQdT14q47tWIUOnpygIhAM0x/QK/mm7VvQxBLAA4DT6X730m
+k/tBvh9SHNbwPxCt
+-----END CERTIFICATE-----
diff --git a/tests/support/step/config/ca.json b/tests/support/step/config/ca.json
new file mode 100644
index 00000000..6735a002
--- /dev/null
+++ b/tests/support/step/config/ca.json
@@ -0,0 +1,44 @@
+{
+  "federatedRoots": null,
+  "address": ":443",
+  "insecureAddress": "",
+  "dnsNames": ["ca.test.pub.solar"],
+  "logger": {
+    "format": "text"
+  },
+  "db": {
+    "type": "badgerv2",
+    "badgerFileLoadingMode": ""
+  },
+  "authority": {
+    "provisioners": [
+      {
+        "name": "acme",
+        "type": "ACME"
+      },
+      {
+        "type": "JWK",
+        "name": "test.pub.solar",
+        "key": {
+          "use": "sig",
+          "kty": "EC",
+          "kid": "lM-BJXRwwQcdgxLqAS4Za23A2YatZpwXx-PP5NIt8JM",
+          "crv": "P-256",
+          "alg": "ES256",
+          "x": "ouB2mP04Kt8rDa10C8ZzYyzA36rrz-k0c4_ud1hVjyg",
+          "y": "RbXKcudQRPEFqjG_5AxuqCQXn7pyRToQCwC4MrwLVUQ"
+        },
+        "encryptedKey": "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjYwMDAwMCwicDJzIjoiNWR5T2puR2Y5aFFNRlc1U25fRWhzUSJ9.a3xtSBuMmzZCMsdfHAXMgFpe9bq8A6bGGOoW9F2Gw7AhxL4bG-AlgA.IA68rSJSGTAKnaVS.XDQc4da-8D9Ykfw-8S4uphsauq5gsEm4qp7zKQUIvcjUlnPAtiHP3xiiBie29ncdg8rKmyzprEEOpTNvXtQl7LsPsHXyKV3SqsTnJecvim9YXGDneAHyWe-XF6hyCZAfSoFbFMgLDKR6d44hMht3ueazL_TPlkFUBLrJbsW782MfdfF3nzcaDf_JDuhKsKHDmKqZyNXDzwf6rINe8adrf5gqaLM2_sGhk7i3XyXygn8HHVw1Dj_w2gPOVm4MS7CO_NgikPqAtGuXDhpWZfXte-FlnMO6d9xQF67b0cwB8kmColPSp1zRiCKPAk9vof8Nn-gGE_aw8zxPi0CJkoY.xbuqSSspgLc_Uw17uiRF7Q"
+      }
+    ]
+  },
+  "tls": {
+    "cipherSuites": [
+      "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+      "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
+    ],
+    "minVersion": 1.2,
+    "maxVersion": 1.3,
+    "renegotiation": false
+  }
+}
diff --git a/tests/support/step/config/defaults.json b/tests/support/step/config/defaults.json
new file mode 100644
index 00000000..40f76069
--- /dev/null
+++ b/tests/support/step/config/defaults.json
@@ -0,0 +1,6 @@
+{
+  "ca-url": "https://ca.test.pub.solar",
+  "ca-config": "/home/b12f/.step/config/ca.json",
+  "fingerprint": "4d6a1a918355380acbd0256a2203d0a0da8436bb788e8f19326589045c3cd842",
+  "root": "/home/b12f/.step/certs/root_ca.crt"
+}
diff --git a/tests/support/step/secrets/intermediate_ca_key b/tests/support/step/secrets/intermediate_ca_key
new file mode 100644
index 00000000..a8eb8b27
--- /dev/null
+++ b/tests/support/step/secrets/intermediate_ca_key
@@ -0,0 +1,8 @@
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,0b34c00cb76ffc16441f5fe762d8d915
+
+xJQ5r5kGiaG6rCsmVnONxm99sqceb62dO8/YvgdZ/ouHAxz1OlXYpTJNd2GvezAc
+XA6Zx6eGzNCOyhgMNJTXEn8QmcJcMd6OjVLxQ9Tr2Mi3LShcBzMPs30/X2XYsM22
+5G4fRhQD0L4nQ08B3GG6FjPe/HYmkRNZmAeDc2wE5Fg=
+-----END EC PRIVATE KEY-----
diff --git a/tests/support/step/secrets/root_ca_key b/tests/support/step/secrets/root_ca_key
new file mode 100644
index 00000000..19605f93
--- /dev/null
+++ b/tests/support/step/secrets/root_ca_key
@@ -0,0 +1,8 @@
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,48f59a57e5a2b81359e0a3668161b61e
+
+jMZbpiHSFa74ns30QrAnIlcguqWp+FE20cXbiIVPpLAJpzGskc3k5vRFTpPM8geg
+sZ6bVvq3APbKmkopxZHWpd4ly6uHkolbtR1NFxTNKymaJZuSuKspUmDohkIyZN6c
+KG0upERMZIOg6Ky1JiM5pLJMHBTsCmzJBmdFCW7GSww=
+-----END EC PRIVATE KEY-----
diff --git a/tests/website.nix b/tests/website.nix
new file mode 100644
index 00000000..e2010d8c
--- /dev/null
+++ b/tests/website.nix
@@ -0,0 +1,63 @@
+{
+  self,
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+{
+  name = "website";
+
+  hostPkgs = pkgs;
+
+  node.pkgs = pkgs;
+  node.specialArgs = self.outputs.nixosConfigurations.nachtigall._module.specialArgs;
+
+  nodes = {
+    acme-server = {
+      imports = [
+        self.nixosModules.home-manager
+        self.nixosModules.core
+        ./support/ca.nix
+      ];
+    };
+
+    nachtigall = {
+      imports = [
+        self.nixosModules.home-manager
+        self.nixosModules.core
+        self.nixosModules.nginx
+        self.nixosModules.nginx-website
+        ./support/global.nix
+      ];
+
+      virtualisation.cores = 1;
+      virtualisation.memorySize = 4096;
+
+      networking.interfaces.eth0.ipv4.addresses = [
+        {
+          address = "192.168.1.3";
+          prefixLength = 32;
+        }
+      ];
+    };
+  };
+
+  testScript = ''
+    acme_server.start()
+
+    acme_server.wait_for_unit("default.target")
+    acme_server.wait_for_unit("step-ca.service")
+    acme_server.succeed("ping ca.test.pub.solar -c 2")
+    acme_server.wait_for_open_port(443)
+    acme_server.wait_until_succeeds("curl 127.0.0.1:443")
+
+    nachtigall.start()
+    nachtigall.wait_for_unit("default.target")
+    nachtigall.succeed("ping test.pub.solar -c 2")
+    nachtigall.succeed("ping ca.test.pub.solar -c 2")
+    nachtigall.wait_for_unit("nginx.service")
+    nachtigall.wait_for_open_port(443, "test.pub.solar")
+    nachtigall.wait_until_succeeds("curl https://test.pub.solar/")
+  '';
+}
diff --git a/treefmt.toml b/treefmt.toml
new file mode 100644
index 00000000..241a3be6
--- /dev/null
+++ b/treefmt.toml
@@ -0,0 +1,27 @@
+[formatter.nix]
+command = "nix"
+options = ["fmt"]
+includes = ["*.nix"]
+excludes = []
+
+[formatter.prettier]
+command = "prettier"
+options = ["--write"]
+includes = [
+  "*.json",
+  "*.yaml",
+  "*.md",
+]
+excludes = [
+  "modules/grafana/grafana-dashboards/*"
+]
+
+[formatter.shell]
+command = "shfmt"
+options = [
+  "-s",
+  "-w",
+  "-i",
+  "2",
+]
+includes = ["*.sh"]