This commit is contained in:
parent
68fc02e2aa
commit
b685bff186
1 changed files with 316 additions and 0 deletions
316
content/blog/2024-06-11-deploying-cuirass-on-guixsd.md
Normal file
316
content/blog/2024-06-11-deploying-cuirass-on-guixsd.md
Normal file
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
<a id="orge201d70"></a>
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
<a id="org0f19dc3"></a>
|
||||||
|
|
||||||
|
# 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\`.
|
||||||
|
|
||||||
|
|
||||||
|
<a id="org5f8483e"></a>
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
<a id="org8d12621"></a>
|
||||||
|
|
||||||
|
# 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/Snamellit<sub>CA.pem</sub>\` 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.
|
||||||
|
|
||||||
|
|
||||||
|
<a id="orged5a51b"></a>
|
||||||
|
|
||||||
|
# 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:
|
||||||
|
<C-C>
|
||||||
|
$
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
<a id="org2ef3b08"></a>
|
||||||
|
|
||||||
|
## TODO Figure out a more elegant way to submit jobs
|
||||||
|
|
||||||
|
There has to be a more elegant way
|
||||||
|
|
Loading…
Reference in a new issue