Skip to content
This repository was archived by the owner on Aug 18, 2026. It is now read-only.

mCaptcha: Make setup less prone to crashing on startup - #1464

Merged
OPNA2608 merged 3 commits into
ngi-nix:mainfrom
OPNA2608:fix-mcaptcha-flaky-tests
Jul 29, 2025
Merged

mCaptcha: Make setup less prone to crashing on startup#1464
OPNA2608 merged 3 commits into
ngi-nix:mainfrom
OPNA2608:fix-mcaptcha-flaky-tests

Conversation

@OPNA2608

Copy link
Copy Markdown
Contributor
  • Wait for network-online.target
    To avoid/reduce likeliness of error about network being down
  • Wait for postgresql target instead of service
    Service is when postgresql is started, target when initial setup scripts have actually completed
  • Wait for redis when creating it locally
    Happened to work out fine so far, but no reason not to make sure they're launched in the correct order
  • Fix postgresql authentication setting in bring-your-own-services test
    Was erroring about IPv6 host not being allowed. Just allow all hosts for this test.

I still have one flakiness issue with projects.mCaptcha.nixos.tests.create-locally on my machine, where mcaptcha thinks that redis is not launched with the mcaptcha module despite redis in the service log explicitly mentioning that it loaded it:

mcaptcha # [    8.016137] systemd[1]: Starting Redis Server - redis-mcaptcha...
[...]
mcaptcha # [    8.256870] redis-server[879]: Supervised by systemd. Please make sure you set appropriate values for TimeoutStartSec and TimeoutStopSec in your service unit.
mcaptcha # [    8.259288] redis-server[879]: oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
mcaptcha # [    8.261103] redis-server[879]: Redis version=8.0.3, bits=64, commit=00000000, modified=0, pid=879, just started
mcaptcha # [    8.263135] redis-server[879]: Configuration loaded
mcaptcha # [    8.264776] redis[879]: monotonic clock: POSIX clock_gettime
mcaptcha # [    8.269559] redis[879]: Running mode=standalone, port=6379.
mcaptcha # [    8.277889] redis[879]: <mcaptcha_cache> Created new data type 'mcaptbuck'
mcaptcha # [    8.279726] redis[879]: <mcaptcha_cache> Created new data type 'mcaptmcap'
mcaptcha # [    8.281202] redis[879]: <mcaptcha_cache> Created new data type 'mcaptsafe'
mcaptcha # [    8.283154] redis[879]: <mcaptcha_cache> Created new data type 'mcaptchal'
mcaptcha # [    8.284430] redis[879]: Module 'mcaptcha_cache' loaded from /nix/store/zx03cwkx3lgbiszrdp7b5i1r1r4g4wr1-cache-0.1.0/lib/libcache.so
mcaptcha # [    8.286909] redis[879]: Server initialized
mcaptcha # [    8.288317] redis[879]: Ready to accept connections tcp
mcaptcha # [    8.289348] redis[879]: Ready to accept connections unix
mcaptcha # [    8.292336] systemd[1]: Started Redis Server - redis-mcaptcha.
[...]
mcaptcha # [   16.288103] systemd[1]: Started mCaptcha: a CAPTCHA system that gives attackers a run for their money.
[...]
mcaptcha # [   16.376122] mcaptcha-start[1049]:  INFO  mcaptcha > mcaptcha: mCaptcha - a PoW-based CAPTCHA system.
mcaptcha # [   16.377609] mcaptcha-start[1049]: For more information, see: https://mcaptcha.org
mcaptcha # [   16.378834] mcaptcha-start[1049]: Build info:
mcaptcha # [   16.379589] mcaptcha-start[1049]: Version: 0.1.0 commit: v0.1.0
mcaptcha # [   16.381293] mcaptcha-start[1049]:  INFO  mcaptcha::settings > Loading config file from /nix/store/0slcmkrm67hb7bp1pvdg1rs27agpwjs5-mcaptcha.config.toml
mcaptcha # [   16.391412] mcaptcha-start[1049]:  INFO  mcaptcha::data     > Initializing credential manager
mcaptcha # [   16.510358] mcaptcha-start[1049]: thread 'main' panicked at src/data.rs:142:22:
mcaptcha # [   16.512244] mcaptcha-start[1049]: called `Result::unwrap()` on an `Err` value: MCaptchaRedisModuleIsNotLoaded
mcaptcha # [   16.514552] mcaptcha-start[1049]: note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
mcaptcha # [   16.523597] systemd[1]: mcaptcha.service: Main process exited, code=exited, status=101/n/a
mcaptcha # [   16.525169] systemd[1]: mcaptcha.service: Failed with result 'exit-code'.

And once it fails its initial setup at that point, things are in a broken state and it will seemingly not be able to recover from that:

mcaptcha # [   17.593138] systemd[1]: Started mCaptcha: a CAPTCHA system that gives attackers a run for their money.
mcaptcha # [   17.649232] mcaptcha-start[1057]:  INFO  mcaptcha > mcaptcha: mCaptcha - a PoW-based CAPTCHA system.
mcaptcha # [   17.651318] mcaptcha-start[1057]: For more information, see: https://mcaptcha.org
mcaptcha # [   17.652948] mcaptcha-start[1057]: Build info:
mcaptcha # [   17.653538] mcaptcha-start[1057]: Version: 0.1.0 commit: v0.1.0
mcaptcha # [   17.655155] mcaptcha-start[1057]:  INFO  mcaptcha::settings > Loading config file from /nix/store/0slcmkrm67hb7bp1pvdg1rs27agpwjs5-mcaptcha.config.toml
mcaptcha # [   17.657054] mcaptcha-start[1057]:  INFO  mcaptcha::data     > Initializing credential manager
mcaptcha # [   17.667827] mcaptcha-start[1057]:  INFO  sqlx::postgres::notice > relation "_sqlx_migrations" already exists, skipping
mcaptcha # [   17.672581] mcaptcha-start[1057]: thread 'main' panicked at src/data.rs:142:22:
mcaptcha # [   17.673492] mcaptcha-start[1057]: called `Result::unwrap()` on an `Err` value: MCaptchaRedisModuleIsNotLoaded
mcaptcha # [   17.675104] mcaptcha-start[1057]: note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
mcaptcha # [   17.681142] systemd[1]: mcaptcha.service: Main process exited, code=exited, status=101/n/a
mcaptcha # [   17.682616] systemd[1]: mcaptcha.service: Failed with result 'exit-code'.

I'm hoping that this flakiness is just limited to my machine and not CI, but it's not great either way…

@OPNA2608

Copy link
Copy Markdown
Contributor Author

CC @ethancedwards8, since you also looked into this for #1463.

@OPNA2608

Copy link
Copy Markdown
Contributor Author

Nope, CI also runs into this…

vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.800461] systemd[1]: Started mCaptcha: a CAPTCHA system that gives attackers a run for their money.
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.802353] systemd[1]: Reached target Multi-User System.
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.803666] systemd[1]: Startup finished in 2.746s (kernel) + 11.055s (userspace) = 13.801s.
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.857848] mcaptcha-start[1030]:  INFO  mcaptcha > mcaptcha: mCaptcha - a PoW-based CAPTCHA system.
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.859316] mcaptcha-start[1030]: For more information, see: https://mcaptcha.org
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.860651] mcaptcha-start[1030]: Build info:
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.861243] mcaptcha-start[1030]: Version: 0.1.0 commit: v0.1.0
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.862825] mcaptcha-start[1030]:  INFO  mcaptcha::settings > Loading config file from /nix/store/0slcmkrm67hb7bp1pvdg1rs27agpwjs5-mcaptcha.config.toml
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.872115] mcaptcha-start[1030]:  INFO  mcaptcha::data     > Initializing credential manager
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.992488] mcaptcha-start[1030]: thread 'main' panicked at src/data.rs:142:22:
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.993504] mcaptcha-start[1030]: called `Result::unwrap()` on an `Err` value: MCaptchaRedisModuleIsNotLoaded
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   13.994910] mcaptcha-start[1030]: note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   14.004531] systemd[1]: mcaptcha.service: Main process exited, code=exited, status=101/n/a
vm-test-run-test-of-mcaptcha-with-database-and-other-services-all-running-on-the-same-node> mcaptcha # [   14.006609] systemd[1]: mcaptcha.service: Failed with result 'exit-code'.

And it also runs into this issue on projects.mCaptcha.nixos.tests.bring-your-own-servicesGah.

@ethancedwards8

Copy link
Copy Markdown
Contributor

Yeah. It'll work on my machine but not in CI. Very frustrating

@OPNA2608

OPNA2608 commented Jul 28, 2025

Copy link
Copy Markdown
Contributor Author

Should we just disable these tests for now, and open an issue about re-enabling them in a less-flaky state later? We had to do that afew times for Heads in the past.

(For debugging this, I'd start to patch libmcaptcha to figure out why it runs into this error here and what makes it think that redis isn't configured properly, but I'm not sure how annoying it is to patch cargo dependencies with the way the Nix helpers are setting stuff up for the build :s)

@ethancedwards8

Copy link
Copy Markdown
Contributor

I have an example for the cargo dependency patching, one sec.

@ethancedwards8

Copy link
Copy Markdown
Contributor

@fricklerhandwerk

Copy link
Copy Markdown
Contributor

How about also waiting for port? It amounts to the same thing as we have roughly, but is more idiomatic.

@OPNA2608

OPNA2608 commented Jul 28, 2025

Copy link
Copy Markdown
Contributor Author

depsExtraArgs doesn't work here because this uses cargoLock instead of cargoHash: https://github.com/NixOS/nixpkgs/blob/4800b181ff3c17f73a50296b85053d37ef9c1711/pkgs/build-support/rust/build-rust-package/default.nix#L90-L110

Got somewhere by doing this though:

mcaptcha.overrideAttrs (oa: {
  cargoDeps = oa.cargoDeps.overrideAttrs (oa2: {
    buildCommand = oa2.buildCommand + ''
      realdir="$(realpath $out/libmcaptcha-0.2.4)"
      rm "$out/libmcaptcha-0.2.4"
      cp -r --no-preserve=mode "$realdir" "$out/libmcaptcha-0.2.4"

      pushd "$out/libmcaptcha-0.2.4"
      # apply patches here
      popd
    '';
  }); 
})

This code here takes the very first module listing that mcaptcha gets from its request to redis. This then gets checked later to make sure it's the mcaptcha_cache module.

But the order in which redis replies its loaded modules doesn't seem consistent. On some runs, it's:

mcaptcha # [   14.189538] mcaptcha-start[1031]:  ERROR libmcaptcha::redis::mcaptcha_redis > mCaptcha redis module list entry: bulk(string-data('"name"'), string-data('"mcaptcha_cache"'), string-data('"ver"'), int(0), string-data('"path"'), string-data('"/nix/store/zx03cwkx3lgbiszrdp7b5i1r1r4g4wr1-cache-0.1.0/lib/libcache.so"'), string-data('"args"'), bulk())
mcaptcha # [   14.193327] mcaptcha-start[1031]:  ERROR libmcaptcha::redis::mcaptcha_redis > mCaptcha redis module list entry: bulk(string-data('"name"'), string-data('"vectorset"'), string-data('"ver"'), int(1), string-data('"path"'), string-data('""'), string-data('"args"'), bulk())

Other times, it's:

mcaptcha # [   19.134242] mcaptcha-start[1069]:  ERROR libmcaptcha::redis::mcaptcha_redis > mCaptcha redis module list entry: bulk(string-data('"name"'), string-data('"vectorset"'), string-data('"ver"'), int(1), string-data('"path"'), string-data('""'), string-data('"args"'), bulk())
mcaptcha # [   19.137870] mcaptcha-start[1069]:  ERROR libmcaptcha::redis::mcaptcha_redis > mCaptcha redis module list entry: bulk(string-data('"name"'), string-data('"mcaptcha_cache"'), string-data('"ver"'), int(0), string-data('"path"'), string-data('"/nix/store/zx03cwkx3lgbiszrdp7b5i1r1r4g4wr1-cache-0.1.0/lib/libcache.so"'), string-data('"args"'), bulk())

In the case of the latter, libmcaptcha errors out because vectorset != mcaptcha_cache. So it seems like upstream's assumption about the module listing order doesn't seem correct, and it should instead just iterate over the entire list. I'll try my best to come up with a patch for this, though I would consider my Rust skills to be at the sub-beginner level 😅.

@OPNA2608

OPNA2608 commented Jul 28, 2025

Copy link
Copy Markdown
Contributor Author

I've added a commit that applies a patch to libmcaptcha. I re-ran the create-locally test in a loop for 20-ish minutes, and couldn't get another test failure with it. I'll submit that upstream and see what they think about it.

Edit: Submitted upstream as mCaptcha/libmcaptcha#15. I'm going to bed now.

@ethancedwards8

Copy link
Copy Markdown
Contributor

Fails again... different reason this time, though:

vm-test-run-test-of-mcaptcha-with-database-and-other-services-running-on-a-different-node> !!! Traceback (most recent call last):
vm-test-run-test-of-mcaptcha-with-database-and-other-services-running-on-a-different-node> !!!   File "<string>", line 5, in <module>
vm-test-run-test-of-mcaptcha-with-database-and-other-services-running-on-a-different-node> !!!     my_own_services.wait_for_unit("postgresql.target")
vm-test-run-test-of-mcaptcha-with-database-and-other-services-running-on-a-different-node> !!! 
vm-test-run-test-of-mcaptcha-with-database-and-other-services-running-on-a-different-node> !!! RequestedAssertionFailed: action timed out after 900 tries with one-second pause in-between

@eljamm

eljamm commented Jul 29, 2025

Copy link
Copy Markdown
Contributor

The actual error is likely because of:

> my_own_services # [   12.585359] systemd[1]: Starting Redis Server - redis-mcaptcha...[   12.711141] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
> my_own_services # 
> my_own_services # [   12.717063] cfg80211: failed to load regulatory.db

So we'll probably need to enable hardware.wirelessRegulatoryDatabase in the build machines.

Edit: Nevermind, reran the build and now it passes, but it's still odd that this happens ...

@OPNA2608

Copy link
Copy Markdown
Contributor Author

The actual error is likely because of:

> my_own_services # [   12.585359] systemd[1]: Starting Redis Server - redis-mcaptcha...[   12.711141] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
> my_own_services # 
> my_own_services # [   12.717063] cfg80211: failed to load regulatory.db

So we'll probably need to enable hardware.wirelessRegulatoryDatabase in the build machines.

Same message appears on successful runs, so that doesn't seem to be a real issue.

Fails again... different reason this time, though:

vm-test-run-test-of-mcaptcha-with-database-and-other-services-running-on-a-different-node> !!! Traceback (most recent call last):
vm-test-run-test-of-mcaptcha-with-database-and-other-services-running-on-a-different-node> !!!   File "<string>", line 5, in <module>
vm-test-run-test-of-mcaptcha-with-database-and-other-services-running-on-a-different-node> !!!     my_own_services.wait_for_unit("postgresql.target")
vm-test-run-test-of-mcaptcha-with-database-and-other-services-running-on-a-different-node> !!! 
vm-test-run-test-of-mcaptcha-with-database-and-other-services-running-on-a-different-node> !!! RequestedAssertionFailed: action timed out after 900 tries with one-second pause in-between

I don't see the log of that anymore on the PR, and digging through buildbot evals to find it is annoying for me to do rn, but I think it was just taking too long to finish the postgresql initial setup which caused this to get tripped? We could prolly give it abit more time by waiting for postgresql startup first, and then also waiting for postgresql init finish. Or increasing the timeout on that wait_for_unit from the default 900 to something higher...

OPNA2608 added 3 commits July 29, 2025 11:55
- Wait for network-online.target
  To avoid/reduce likeliness of error about network being down
- Wait for postgresql target instead of service
  Service is when postgresql is started, target when initial setup scripts have actually completed
- Wait for redis when creating it locally
  Happened to work out fine so far, but no reason not to make sure they're launched in the correct order
- Fix postgresql authentication setting in bring-your-own-services test
  Was erroring about IPv6 host not being allowed. Just allow all hosts for this test.
Sometimes, mcaptcha_cache is not the first entry in the module listing that libmcaptcha receives. In that case, it
determines that the module is not loaded, and mcaptcha crashes.

Check all returned modules, not just the first.
CI managed to time out while waiting for the target at least once. We can give it abit more
leeway by waiting for the service first, then the target.
@OPNA2608
OPNA2608 force-pushed the fix-mcaptcha-flaky-tests branch from bf0307a to 8c70641 Compare July 29, 2025 09:55

@fricklerhandwerk fricklerhandwerk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks @OPNA2608

@OPNA2608
OPNA2608 merged commit 206aefa into ngi-nix:main Jul 29, 2025
14 checks passed
@github-project-automation github-project-automation Bot moved this to Done in Nix@NGI Jul 29, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants