nixos/tandoor-recipes: fix database leak when serving media

To avoid serving the (default) SQLite database, set MEDIA_ROOT to a sub
directory of the data path. See
https://github.com/NixOS/nixpkgs/issues/338339 for details

Co-authored-by: bas <bas@noemail.invalid>
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
This commit is contained in:
Sefa Eyeoglu
2025-12-27 18:35:45 +01:00
co-authored by bas
parent 5c6d740a7d
commit a77e2c1672
7 changed files with 143 additions and 6 deletions
+12
View File
@@ -62,6 +62,12 @@
"module-boot-plymouth-tpm2-totp-quick-start-enable": [
"index.html#module-boot-plymouth-tpm2-totp-quick-start-enable"
],
"module-services-tandoor-recipes-migrating-media-option-1": [
"index.html#module-services-tandoor-recipes-migrating-media-option-1"
],
"module-services-tandoor-recipes-migrating-media-option-2": [
"index.html#module-services-tandoor-recipes-migrating-media-option-2"
],
"sec-override-nixos-test": [
"index.html#sec-override-nixos-test"
],
@@ -1122,6 +1128,12 @@
"module-services-samba-configuring-file-share": [
"index.html#module-services-samba-configuring-file-share"
],
"module-services-tandoor-recipes": [
"index.html#module-services-tandoor-recipes"
],
"module-services-tandoor-recipes-migrating-media": [
"index.html#module-services-tandoor-recipes-migrating-media"
],
"module-services-litestream": [
"index.html#module-services-litestream"
],
@@ -40,6 +40,8 @@
- `services.crabfit` was removed because its upstream packages are unmaintained and insecure.
- `services.tandoor-recipes` now uses a sub-directory for media files by default starting with `26.05`. Existing setups should move media files out of the data directory and adjust `services.tandoor-recipes.extraConfig.MEDIA_ROOT` accordingly. See [Migrating media files for pre 26.05 installations](#module-services-tandoor-recipes-migrating-media).
- `services.kubernetes.addons.dns.coredns` has been renamed to `services.kubernetes.addons.dns.corednsImage` and now expects a
package instead of attrs. Now, by default, nixpkgs.coredns in conjunction with dockerTools.buildImage is used, instead
of pulling the upstream container image from Docker Hub. If you want the old behavior, you can set:
@@ -0,0 +1,19 @@
# Tandoor Recipes {#module-services-tandoor-recipes}
## Dealing with `MEDIA_ROOT` for installations prior 26.05 {#module-services-tandoor-recipes-migrating-media}
See https://github.com/NixOS/nixpkgs/issues/338339 for some background.
### Option 1: Migrate media to new `MEDIA_ROOT` {#module-services-tandoor-recipes-migrating-media-option-1}
1. Stop the currently running service: `systemctl stop tandoor-recipes.service`
2. Create a media folder. NixOS `26.05` creates the media path at `/var/lib/tandoor-recipes/media` by default, but you may choose any other path as well. `mkdir -p /var/lib/tandoor-recipes/media`
3. Move existing media to the new path: `mv /var/lib/tandoor-recipes/{files,recipes} /var/lib/tandoor-recipes/media`
4. Set `services.tandoor-recipes.extraConfig.MEDIA_ROOT = "/var/lib/tandoor-recipes/media";` in your NixOS configuration (not needed if `system.stateVersion >= 26.05`).
5. Rebuild and switch!
These changes can be reverted by moving the files back into the state directory.
### Option 2: Keep existing directory (may be insecure) {#module-services-tandoor-recipes-migrating-media-option-2}
To keep the existing directory, set `services.tandoor-recipes.extraConfig.MEDIA_ROOT = "/var/lib/tandoor-recipes";`.
@@ -7,13 +7,15 @@
let
cfg = config.services.tandoor-recipes;
pkg = cfg.package;
stateDir = "/var/lib/tandoor-recipes";
useNewMediaRoot = lib.versionAtLeast config.system.stateVersion "26.05";
# SECRET_KEY through an env file
env = {
GUNICORN_CMD_ARGS = "--bind=${cfg.address}:${toString cfg.port}";
DEBUG = "0";
DEBUG_TOOLBAR = "0";
MEDIA_ROOT = "/var/lib/tandoor-recipes";
MEDIA_ROOT = "${stateDir}${lib.optionalString useNewMediaRoot "/media"}";
}
// lib.optionalAttrs (config.time.timeZone != null) {
TZ = config.time.timeZone;
@@ -26,12 +28,15 @@ let
# UID is a read-only shell variable
eval "$(${config.systemd.package}/bin/systemctl show -pUID,GID,MainPID tandoor-recipes.service | tr '[:upper:]' '[:lower:]')"
exec ${pkgs.util-linux}/bin/nsenter \
-t $mainpid -m -S $uid -G $gid --wdns=${env.MEDIA_ROOT} \
-t $mainpid -m -S $uid -G $gid --wdns=${stateDir} \
${pkg}/bin/tandoor-recipes "$@"
'';
in
{
meta.maintainers = with lib.maintainers; [ jvanbruegge ];
meta = {
maintainers = with lib.maintainers; [ jvanbruegge ];
doc = ./tandoor-recipes.md;
};
options.services.tandoor-recipes = {
enable = lib.mkOption {
@@ -101,6 +106,10 @@ in
};
config = lib.mkIf cfg.enable {
warnings = lib.mkIf (!useNewMediaRoot && !(cfg.extraConfig ? MEDIA_ROOT)) [
"`services.tandoor-recipes.extraConfig.MEDIA_ROOT` is unset. This is considered insecure for `system.stateVersion` < 26.05. See https://nixos.org/manual/nixos/unstable/#module-services-tandoor-recipes-migrating-media for migration instructions."
];
users.users = lib.mkIf (cfg.user == "tandoor_recipes") {
tandoor_recipes = {
inherit (cfg) group;
@@ -126,8 +135,11 @@ in
User = cfg.user;
Group = cfg.group;
StateDirectory = "tandoor-recipes";
WorkingDirectory = env.MEDIA_ROOT;
StateDirectory = [
"tandoor-recipes"
]
++ lib.optional (env.MEDIA_ROOT == "/var/lib/tandoor-recipes/media") "tandoor-recipes/media";
WorkingDirectory = stateDir;
RuntimeDirectory = "tandoor-recipes";
BindReadOnlyPaths = [
+1
View File
@@ -1552,6 +1552,7 @@ in
szurubooru = handleTest ./szurubooru.nix { };
taler = handleTest ./taler { };
tandoor-recipes = runTest ./tandoor-recipes.nix;
tandoor-recipes-media = runTest ./tandoor-recipes-media.nix;
tandoor-recipes-script-name = runTest ./tandoor-recipes-script-name.nix;
tang = runTest ./tang.nix;
taskchampion-sync-server = runTest ./taskchampion-sync-server.nix;
+91
View File
@@ -0,0 +1,91 @@
{ ... }:
{
name = "tandoor-recipes-media";
nodes.machine = {
services.tandoor-recipes = {
enable = true;
# This setting is not recommended, but it's an easy way serve the media
# folder in this test.
extraConfig = {
GUNICORN_MEDIA = true;
};
};
specialisation.oldVersion.configuration = {
system.stateVersion = "25.11";
services.tandoor-recipes = {
enable = true;
extraConfig = {
GUNICORN_MEDIA = true;
# Explicitly set insecure value (skips warning)
MEDIA_ROOT = "/var/lib/tandoor-recipes";
};
};
};
specialisation.oldVersionOverrideMedia.configuration = {
system.stateVersion = "25.11";
services.tandoor-recipes = {
enable = true;
extraConfig = {
GUNICORN_MEDIA = true;
MEDIA_ROOT = "/var/lib/tandoor-recipes/media";
};
};
};
};
testScript =
{ nodes, ... }:
let
specBase = "${nodes.machine.system.build.toplevel}/specialisation";
oldVersion = "${specBase}/oldVersion";
oldVersionOverrideMedia = "${specBase}/oldVersionOverrideMedia";
in
# python
''
def wait_for_tandoor():
machine.wait_for_unit("tandoor-recipes.service")
machine.wait_for_open_port(8080)
def stop_and_rm():
machine.systemctl("stop tandoor-recipes")
machine.succeed("rm -r /var/lib/tandoor-recipes")
db_path = "http://localhost:8080/media/db.sqlite3"
# The media folder shouldn't contain the database. Subsequently it
# should **not** get served, resulting in a 404. Previously the
# database was located in the media folder. Therefore serving the media
# folder would expose the database. See #338339.
wait_for_tandoor()
machine.succeed(f"curl --head {db_path} | grep \"HTTP/1.1 404 Not Found\"")
# Switch to NixOS 24.11 to check if the setup still functions the same
# as before.
stop_and_rm()
machine.succeed("${oldVersion}/bin/switch-to-configuration test")
# With the old setup the media folder should contain the database.
# Subsequently it should get served, resulting in a 200.
wait_for_tandoor()
machine.succeed(f"curl --head {db_path} | grep \"HTTP/1.1 200 OK\"")
# Switch to NixOS 24.11 with the MEDIA_ROOT already set to
# /var/lib/tandoor-recipes/media.
stop_and_rm()
machine.succeed("${oldVersionOverrideMedia}/bin/switch-to-configuration test")
# With MEDIA_ROOT being set to /var/lib/tandoor-recipes/media the media
# folder shouldn't contain the database. Subsequently it should **not**
# get served, resulting in a 404.
wait_for_tandoor()
machine.succeed(f"curl --head {db_path} | grep \"HTTP/1.1 404 Not Found\"")
'';
}
+1 -1
View File
@@ -166,7 +166,7 @@ python.pkgs.buildPythonPackage {
updateScript = ./update.sh;
tests = {
inherit (nixosTests) tandoor-recipes tandoor-recipes-script-name;
inherit (nixosTests) tandoor-recipes tandoor-recipes-script-name tandoor-recipes-media;
};
};