Skip to content

Commit a95a530

Browse files
committed
nixos/gitlab: add activeRecord key files
GitLab 17.11 started using rails activeRecord encryption for some values. Introduce new key files. This is breaking for unstable/25.05. Also add a test to prevent this from happening unnoticed in the future. For the future there should also be an option to set multiple activeRecord keys for rotation.
1 parent 2e2cab7 commit a95a530

File tree

3 files changed

+76
-2
lines changed

3 files changed

+76
-2
lines changed

nixos/doc/manual/release-notes/rl-2505.section.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,8 @@
333333

334334
- The behavior of the `networking.nat.externalIP` and `networking.nat.externalIPv6` options has been changed. `networking.nat.forwardPorts` now only forwards packets destined for the specified IP addresses.
335335

336+
- `services.gitlab` now requires the setting of `activeRecordPrimaryKeyFile`, `activeRecordDeterministicKeyFile`, `activeRecordSaltFile` as GitLab introduced Rails ActiveRecord encryption.
337+
336338
- `python3Packages.bpycv` has been removed due to being incompatible with Blender 4 and unmaintained.
337339

338340
- `python3Packages.jaeger-client` was removed because it was deprecated upstream. [OpenTelemetry](https://opentelemetry.io) is the recommended replacement.

nixos/modules/services/misc/gitlab.nix

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,50 @@ in
907907
'';
908908
};
909909

910+
secrets.activeRecordPrimaryKeyFile = mkOption {
911+
type = with types; nullOr path;
912+
default = null;
913+
description = ''
914+
A file containing the secret used to encrypt some rails data
915+
in the DB. This should not be the same as `services.gitlab.secrets.activeRecordDeterministicKeyFile`!
916+
917+
Make sure the secret is at ideally 32 characters and all random,
918+
no regular words or you'll be exposed to dictionary attacks.
919+
920+
This should be a string, not a nix path, since nix paths are
921+
copied into the world-readable nix store.
922+
'';
923+
};
924+
925+
secrets.activeRecordDeterministicKeyFile = mkOption {
926+
type = with types; nullOr path;
927+
default = null;
928+
description = ''
929+
A file containing the secret used to encrypt some rails data in a deterministic way
930+
in the DB. This should not be the same as `services.gitlab.secrets.activeRecordPrimaryKeyFile`!
931+
932+
Make sure the secret is at ideally 32 characters and all random,
933+
no regular words or you'll be exposed to dictionary attacks.
934+
935+
This should be a string, not a nix path, since nix paths are
936+
copied into the world-readable nix store.
937+
'';
938+
};
939+
940+
secrets.activeRecordSaltFile = mkOption {
941+
type = with types; nullOr path;
942+
default = null;
943+
description = ''
944+
A file containing the salt for active record encryption in the DB.
945+
946+
Make sure the secret is at ideally 32 characters and all random,
947+
no regular words or you'll be exposed to dictionary attacks.
948+
949+
This should be a string, not a nix path, since nix paths are
950+
copied into the world-readable nix store.
951+
'';
952+
};
953+
910954
extraShellConfig = mkOption {
911955
type = types.attrs;
912956
default = { };
@@ -1180,6 +1224,18 @@ in
11801224
assertion = cfg.secrets.jwsFile != null;
11811225
message = "services.gitlab.secrets.jwsFile must be set!";
11821226
}
1227+
{
1228+
assertion = cfg.secrets.activeRecordPrimaryKeyFile != null;
1229+
message = "services.gitlab.secrets.activeRecordPrimaryKeyFile must be set!";
1230+
}
1231+
{
1232+
assertion = cfg.secrets.activeRecordDeterministicKeyFile != null;
1233+
message = "services.gitlab.secrets.activeRecordDeterministicKeyFile must be set!";
1234+
}
1235+
{
1236+
assertion = cfg.secrets.activeRecordSaltFile != null;
1237+
message = "services.gitlab.secrets.activeRecordSaltFile must be set!";
1238+
}
11831239
{
11841240
assertion = versionAtLeast postgresqlPackage.version "14.9";
11851241
message = "PostgreSQL >= 14.9 is required to run GitLab 17. Follow the instructions in the manual section for upgrading PostgreSQL here: https://nixos.org/manual/nixos/stable/index.html#module-services-postgres-upgrading";
@@ -1480,11 +1536,17 @@ in
14801536
db="$(<'${cfg.secrets.dbFile}')"
14811537
otp="$(<'${cfg.secrets.otpFile}')"
14821538
jws="$(<'${cfg.secrets.jwsFile}')"
1483-
export secret db otp jws
1539+
arprimary="$(<'${cfg.secrets.activeRecordPrimaryKeyFile}')"
1540+
ardeterministic="$(<'${cfg.secrets.activeRecordDeterministicKeyFile}')"
1541+
arsalt="$(<'${cfg.secrets.activeRecordSaltFile}')"
1542+
export secret db otp jws arprimary ardeterministic arsalt
14841543
jq -n '{production: {secret_key_base: $ENV.secret,
14851544
otp_key_base: $ENV.otp,
14861545
db_key_base: $ENV.db,
1487-
openid_connect_signing_key: $ENV.jws}}' \
1546+
openid_connect_signing_key: $ENV.jws,
1547+
active_record_encryption_primary_key: $ENV.arprimary,
1548+
active_record_encryption_deterministic_key: $ENV.ardeterministic,
1549+
active_record_encryption_key_derivation_salt: $ENV.arsalt}}' \
14881550
> '${cfg.statePath}/config/secrets.yml'
14891551
)
14901552

nixos/tests/gitlab.nix

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ in
106106
otpFile = pkgs.writeText "otpsecret" "Riew9mue";
107107
dbFile = pkgs.writeText "dbsecret" "we2quaeZ";
108108
jwsFile = pkgs.runCommand "oidcKeyBase" { } "${pkgs.openssl}/bin/openssl genrsa 2048 > $out";
109+
activeRecordPrimaryKeyFile = pkgs.writeText "arprimary" "vsaYPZjTRxcbG7W6gNr95AwBmzFUd4Eu";
110+
activeRecordDeterministicKeyFile = pkgs.writeText "ardeterministic" "kQarv9wb2JVP7XzLTh5f6DFcMHms4nEC";
111+
activeRecordSaltFile = pkgs.writeText "arsalt" "QkgR9CfFU3MXEWGqa7LbP24AntK5ZeYw";
109112
};
110113

111114
registry = {
@@ -477,6 +480,9 @@ in
477480
gitlab.start()
478481
''
479482
+ waitForServices
483+
+ ''
484+
gitlab.succeed("cp /var/gitlab/state/config/secrets.yml /root/gitlab-secrets.yml")
485+
''
480486
+ test true
481487
+ ''
482488
gitlab.systemctl("start gitlab-backup.service")
@@ -496,5 +502,9 @@ in
496502
gitlab.systemctl("start gitlab.target")
497503
''
498504
+ waitForServices
505+
+ ''
506+
with subtest("Check that no secrets were auto-generated as these would be non-persistent"):
507+
gitlab.succeed("diff -u /root/gitlab-secrets.yml /var/gitlab/state/config/secrets.yml")
508+
''
499509
+ test false;
500510
}

0 commit comments

Comments
 (0)