From b685bff18658d594ee8de6b5f651dfda440fb07c Mon Sep 17 00:00:00 2001 From: Peter Tillemans Date: Wed, 12 Jun 2024 15:48:12 +0200 Subject: [PATCH] add cuirass adventure --- .../2024-06-11-deploying-cuirass-on-guixsd.md | 316 ++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 content/blog/2024-06-11-deploying-cuirass-on-guixsd.md diff --git a/content/blog/2024-06-11-deploying-cuirass-on-guixsd.md b/content/blog/2024-06-11-deploying-cuirass-on-guixsd.md new file mode 100644 index 0000000..af79f5b --- /dev/null +++ b/content/blog/2024-06-11-deploying-cuirass-on-guixsd.md @@ -0,0 +1,316 @@ ++++ +title = Deploying Cuirass on GuixSD +date = <2024-06-11 Tue> +author = Peter Tillemans +email = pti@snamellit.com +[taxonomies] +tags = [programming] +categories = [guix, linux] ++++ + + +# Table of Contents + +1. [Install Cuirass in Guix](#orge201d70) +2. [Create a postgresql server](#org0f19dc3) +3. [Enable the cuirass service](#org5f8483e) +4. [Enabling the Web Frontend](#org8d12621) +5. [Submitting jobs](#orged5a51b) + 1. [Figure out a more elegant way to submit jobs](#org2ef3b08) + + + + +# Install Cuirass in Guix + +I had a hard time installing **cuirass** on my system. I tried to collect +some notes to move step by step to a working solution. + +GUIX is great that it is really easy to revert your step to get out or +a dead end and start over from a previous point. Something I made +liberally use off to get something working. However it also means my +deployment process was not really linear but much more error driven. + + + + +# Create a postgresql server + +Starting the cuirass service will pull in a postgres server, however +it will use by default a version 10. Let's update that to 15 for some +future proofing: + + (service postgresql-role-service-type + (postgresql-role-configuration + (roles + (list (postgresql-role + (name "cuirass") + (create-database? #t)) + (postgresql-role + (name "xyz") + (create-database? #t)))))) + +I also added a database user for me (**xyz** here stands for my user +account). + +This will also create a database with the same name to allow the +cuirass user (and me) to login to the postgres database and do +database things. + +Run a \`guix system reconfigure\` and check if the postgres is running +with \`sudo herd status postgres\`. + + + + +# Enable the cuirass service + +With the database in place there is a fighting chance to get the +service running : + + (service cuirass-service-type + (cuirass-configuration + (specifications #~(list)))) + +The example in the reference documentation offers something more +interesting than an empty list but whatever I tried ended up with +'invalid field specifier' errors. But I get that too for nginx +configuration parts so that is probably a skill issue on my part. + +With a bit of luck we'll see: + + xyz@foo ~/.config/dotfiles/guix [env]$ sudo herd status cuirass + Status of cuirass: + It is running since 05:19:42 PM (4 hours ago). + Running value is 6513. + It is enabled. + Provides (cuirass). + Requires (user-processes guix-daemon postgres postgres-roles networking). + Will be respawned. + xyz@foo ~/.config/dotfiles/guix [env]$ sudo herd status cuirass-web + Status of cuirass-web: + It is running since 05:22:41 PM (4 hours ago). + Running value is 6679. + It is enabled. + Provides (cuirass-web). + Requires (user-processes cuirass). + Will be respawned. + +If not there may be some info in \`/var/log/cuirass.log\` or \`/var/log/cuirass-web.log\` + +Alternatively for debugging we can run the application from the git +repository. + +First of all we have to give our user access to the database: + + xyz@foo ~/.config/dotfiles/guix [env]$ sudo -u cuirass psql + Password: + psql (15.4) + Type "help" for help. + + cuirass=> grant all on database cuirass to xyz; + GRANT + +if the cuirass service has initialised the database already you can +add: + + cuirass=> grant all on all tables in schema public to xyz; + GRANT + cuirass=> grant all on all sequences in schema public to xyz; + GRANT + +This allows access without jumping through the sudo hoop. + +The code in the **guix-cuirass** project folder will now just work. Except +the postgresql socket should be exposed too in the proposed command of +the reference manual: + + guix shell -CPNW --expose=/var/log/guix/drvs \ + --expose=/var/run/dbus --expose=/run/avahi-daemon \ + --expose=/etc/ssl/certs --expose=/var/run/postgresql + +Note that if the tables and sequences are created when running in your +account it is quite possible that the **cuirass** user will not be able to +access them and complain with access denied errors. In that case we +have to do the grants for the **cuirass** user: + + xyz@foo ~/.config/dotfiles/guix [env]$ psql cuirass + Password: + psql (15.4) + Type "help" for help. + + xyz=> grant all on all tables in schema public to cuirass; + GRANT + xyz=> grant all on all sequences in schema public to cuirass; + GRANT + +Then restarting the service with \`sudo herd restart cuirass\` should +make it start, or at least give a different error. + +Once **cuirass** service is running, it will be possible to run the +**cuirass-web** service. It relies on the existence of the +**/var/run/cuirass/bridge** file which is created by the cuirass service. + +Just to be sure that the web server is running : + + xyz@foo ~/src/guix-cuirass [env]$ wget http://localhost:8081 + --2024-06-11 21:59:09-- http://localhost:8081/ + Resolving localhost (localhost)... 127.0.0.1 + Connecting to localhost (localhost)|127.0.0.1|:8081... connected. + HTTP request sent, awaiting response... 200 OK + Length: 6142 (6.0K) [text/html] + Saving to: ‘index.html’ + + index.html 100%[================================================>] 6.00K --.-KB/s in 0s + + 2024-06-11 21:59:09 (378 MB/s) - ‘index.html’ saved [6142/6142] + +Cool, we have a 200 Ok status code and some index.html file so the web +UI is running. Now exposing it to the 'net. + + + + +# Enabling the Web Frontend + +In the reference manual there is a nice configuration to start from to +configure nginx as a frontend for **cuirass-web** + +However you cannot start nginx https without having the certificates +and you cannot get the certificates without the server running. (Well +you can but that is outside the scope of this post) + +So we have to cut back the configuration to only start the http nginx +server to do the first handschake with letsencrypt to get the initial +certificates + +Let's start with the **certbot-service** : + + (service certbot-service-type + (certbot-configuration + (email "xyz@bar.com") + (certificates + (list + (certificate-configuration + (domains '("foo.bar.com"))) + )))) + +Then add the minimal part for a nginx http server to do the +letsencrypt dance. + + (service nginx-service-type + (nginx-configuration + (server-blocks + (list + ;; TLS is required for authentication; serve the site via + ;; HTTPS only. + (nginx-server-configuration + (listen '("80")) + (raw-content + (list "return 308 https://$host$request_uri;"))) + + )))) + +Doing a \`guix system reconfigure\` now will start the nginx server and +download fresh certificates. + +We can now add the https server proxy-ing the **cuirass-web** server: + + (service nginx-service-type + (nginx-configuration + (server-blocks + (list + ;; TLS is required for authentication; serve the site via + ;; HTTPS only. + (nginx-server-configuration + (listen '("80")) + (raw-content + (list "return 308 https://$host$request_uri;"))) + + (nginx-server-configuration + (listen '("443 ssl")) + (server-name '("foo.bar.com")) + (ssl-certificate "/etc/letsencrypt/live/foo.bar.com/fullchain.pem") + (ssl-certificate-key "/etc/letsencrypt/live/foo.bar.com/privkey.pem") + (locations + (list + ;; Proxy the whole Cuirass web site... + (nginx-location-configuration + (uri "/") + (body (list "proxy_pass http://localhost:8081;"))) + ;; ... but require authentication for the admin pages. + (nginx-location-configuration + (uri "~ ^/admin") + (body + (list "if ($ssl_client_verify != SUCCESS) \ + { return 403; } proxy_pass http://localhost:8081;"))))) + ;; (raw-content + ;; ;; Register your self-generated certificate authority. + ;; (list "ssl_client_certificate /etc/ssl/certs/Snamellit_CA.pem;" + ;; "ssl_verify_client optional;")) + ) + )))) + +Creating and installing the root CA is a bit out of scope. For this +post we'll just wave our hands and assume the certificate magically +appeared in the \`/etc/ssl/certs/SnamellitCA.pem\` location. Creating a +client certificate for firefox and importing it allows to access the +admin section and retrigger jobs etc. + +Once that is setup the commented out section can be activated. + + + + +# Submitting jobs + +For some reason I do not understand yet, the specification file must +be in the loadpath of the cuirass program. + +For testing I add them to the **examples** folder in the **guix-cuirass** +folder in the home folder of the **cuirass** user + + $ sudo -u cuirass -- bash # start a shell in the cuirass user + $ cd guix-cuirass # enter the project folder + $ cp /foo/bar/snamguix.scm examples # put spec somewhere on loadpath + $ # start dev environment in container + $ guix shell -CPNW --expose=/var/log/guix/drvs \ + --expose=/var/run/dbus --expose=/run/avahi-daemon \ + --expose=/etc/ssl/certs --expose=/var/run/postgresql + guix shell: loading environment from '/home/pti/src/guix-cuirass/guix.scm'... + $ ~/src/guix-cuirass [env]$ # register new recipe + $ ~/src/guix-cuirass [env]$ ./pre-inst-env cuirass register -S examples/snamguix.scm + 2024-06-11T20:18:08 running Fibers on 8 kernel threads + 2024-06-11T20:18:08 marking stale builds as "scheduled"... + 2024-06-11T20:18:08 builds will be made via the local build daemon + 2024-06-11T20:18:08 will perform up to 8 evaluations concurrently + 2024-06-11T20:18:08 opening bridge socket at '/tmp/cuirass-tests/var/run/cuirass/bridge' + 2024-06-11T20:18:08 retrieving list of pending builds... + 2024-06-11T20:18:08 unused GC roots older than 2592000s will be deleted every 86400s + 2024-06-11T20:18:08 deleting old GC roots from '/var/guix/gcroots/profiles/per-user/pti/cuirass'... + 2024-06-11T20:18:08 selected 0 GC roots to remove + WARNING: (cuirass base): imported module (fibers) overrides core binding `sleep' + 2024-06-11T20:18:08 heap: 12.18 MiB; threads: 17; file descriptors: 76 + WARNING: (cuirass scripts register): imported module (fibers) overrides core binding `sleep' + 2024-06-11T20:18:08 canceling 0 stale builds + 2024-06-11T20:18:08 restarting 0 pending builds + 2024-06-11T20:18:08 building 0 derivations in batches of 200 + 2024-06-11T20:18:08 done with 0 derivations + 2024-06-11T20:18:08 outputs: + + $ + +This actually starts the scheduler and it just keeps running (unless +we also give the –one-shot flag) but the side effect is to add the +specification to the database. + +From now on the channel will be checked and build any updated +packages. + + + + +## TODO Figure out a more elegant way to submit jobs + +There has to be a more elegant way +