···11+let
22+ domain = "quiz.lassul.us";
33+ port = 8773;
44+in
55+{ self, ... }:
66+{
77+ # nixcon-quiz: live multiplayer quiz for NixCon. Everyone answers the same
88+ # question against the same server clock; /spectate is the 16:9 screen for
99+ # the livestream with a QR code to join.
1010+ #
1111+ # The questions are not part of any repository (whoever reads them knows
1212+ # every answer) and stay out of the world-readable store. Copy them over
1313+ # after deploying; until then the service is skipped:
1414+ # rsync -r --delete ~/src/nixcon-quiz/questions/ root@neoprism.r:/var/lib/nixcon-quiz/questions/
1515+ # ssh root@neoprism.r systemctl restart nixcon-quiz
1616+ imports = [ self.inputs.nixcon-quiz.nixosModules.default ];
1717+1818+ services.nixcon-quiz = {
1919+ enable = true;
2020+ host = "127.0.0.1";
2121+ inherit port domain;
2222+ };
2323+2424+ # One address may hold a few tabs (players and a spectator screen) and
2525+ # reload at a human pace; each tab keeps one event stream open.
2626+ services.nginx.appendHttpConfig = ''
2727+ limit_conn_zone $binary_remote_addr zone=nixcon_quiz_conns:10m;
2828+ limit_req_zone $binary_remote_addr zone=nixcon_quiz_joins:10m rate=5r/s;
2929+ '';
3030+3131+ services.nginx.virtualHosts.${domain}.locations."/api/events".extraConfig = ''
3232+ limit_conn nixcon_quiz_conns 16;
3333+ limit_req zone=nixcon_quiz_joins burst=30 nodelay;
3434+ limit_conn_status 429;
3535+ limit_req_status 429;
3636+ '';
3737+}
···122122 # browser maze game with spectator camera (maze.lassul.us)
123123 ../../2configs/mazegame.nix
124124125125+ # live NixCon quiz with a livestream screen (quiz.lassul.us)
126126+ ../../2configs/nixcon-quiz.nix
127127+125128 # radicle public seed (radicle.lassul.us)
126129 ../../2configs/radicle.lassul.us.nix
127130 # radicle identity + node for this machine (/var/lib/rad)