|
| 1 | +# self-hosted runner setup |
| 2 | + |
| 3 | +## dockerhub |
| 4 | + |
| 5 | +our image is at |
| 6 | + |
| 7 | +`dockerhub.pl.sophia.inria.fr/python-nodejs:latest` |
| 8 | + |
| 9 | +### publish the image |
| 10 | + |
| 11 | +``` |
| 12 | +# as boxtops@root |
| 13 | +
|
| 14 | +cd |
| 15 | +# if needed |
| 16 | +git clone https://github.com/flotpython/jupyterlab-examples |
| 17 | +
|
| 18 | +cd ~/jupyterlab-examples/.github/docker |
| 19 | +
|
| 20 | +# will build & push the image to dockerhub.pl.sophia.inria.fr |
| 21 | +# the docker login as admin has been made once and for good as the root user there |
| 22 | +./rebuild.sh |
| 23 | +
|
| 24 | +# check available tags |
| 25 | +curl -u admin:$password https://dockerhub.pl.sophia.inria.fr/v2/_catalog |
| 26 | +curl -u admin:$password https://dockerhub.pl.sophia.inria.fr/v2/python-nodejs/tags/list |
| 27 | +``` |
| 28 | + |
| 29 | +## general comments |
| 30 | + |
| 31 | +### right in the host context |
| 32 | + |
| 33 | +- the self-hosted runner is required to run as a regular user (not root), this |
| 34 | + is enforced by the GH runner code |
| 35 | +- as this needs a minimal amount of isolation between runs, we've tried using |
| 36 | + `conda` or `pixi` to provide that isolation; however, the bottom line is |
| 37 | + **it's not a good idea** |
| 38 | +- running right inside the host context is **doable**, and in a first stage |
| 39 | + we've used that for the `frontend` course on `bigjack` |
| 40 | +- however this is both **fragile** (not sure how several concurrent runs would |
| 41 | + behave) and also - very - **slow** |
| 42 | + |
| 43 | +### in a container |
| 44 | + |
| 45 | +- for that reason we have explored containerization options |
| 46 | +- ***BUT*** using **podman** turns out to be **overcomplex**, due to the need to |
| 47 | + run the runner as a non-root user - don't do that ! |
| 48 | +- for that reason we have switched to using **regular docker** |
| 49 | +- btw: that is a bit unfortunate because we had `thermals` that could have done the |
| 50 | + job pretty well, but well, c'est la vie... |
| 51 | +- using `boxtops` then instead |
| 52 | +- also, it is important that the container itself must not run as root either, |
| 53 | + because `myst --execute` will then have its `jupyter-server` fail silently in |
| 54 | + that case (the logs would report that the `--allow-root` flag is missing) |
| 55 | + |
| 56 | +### need to use a publicly available image |
| 57 | + |
| 58 | +- the GH action that sets up the container insists on doing a `docker pull` |
| 59 | + first, there does not seem to be a way to skip that |
| 60 | +- hence the need to push the image to a publicly available docker registry |
| 61 | +- we have setup dockerhub on `dockerhub.pl.sophia.inria.fr` for that purpose |
| 62 | + it is requires login for publication but is configured to allow anonymous |
| 63 | + pulls |
| 64 | + |
| 65 | +### the image |
| 66 | + |
| 67 | +- this is expected to be run on boxtops |
| 68 | + does not really matter much, but it does require the `docker login` step |
| 69 | +- is published as `dockerhub.pl.sophia.inria.fr/python-nodejs:latest` |
| 70 | +- rebuild with |
| 71 | + ```bash |
| 72 | + cd ~/jupyterlab-examples/.github/docker |
| 73 | + git pull |
| 74 | + ./rebuild.sh |
| 75 | + ``` |
| 76 | +- this uses `Dockerfile.python-nodejs` |
| 77 | +- note that the user `github-actions` is created with uid/gid 1001 (see also |
| 78 | + below) |
| 79 | + |
| 80 | +## setup steps on the GH side |
| 81 | + |
| 82 | +### allow public repos to use self-hosted runners |
| 83 | + |
| 84 | +- ***IMPORTANT*** - do it once for each orga ! |
| 85 | + you also need to allow public repos to use self-hosted runners in the |
| 86 | + organization settings on GitHub |
| 87 | + |
| 88 | + `github.com/$ORGA` -> Settings -> Actions -> Runner groups -> Default Group -> Allow public repositories |
| 89 | + |
| 90 | +## setup on the runner host |
| 91 | + |
| 92 | +***IMPORTANT***: make sure you run genuine docker and not podman |
| 93 | + |
| 94 | +```bash |
| 95 | +dnf install -y docker-cli |
| 96 | +systemctl enable --now docker |
| 97 | +``` |
| 98 | + |
| 99 | +### runner cleanup steps |
| 100 | + |
| 101 | +if needed: on the GH site, go to `github.com/$ORGA` |
| 102 | +> -> Settings -> Actions -> Runners |
| 103 | +
|
| 104 | +and remove the runners you don't need anymore |
| 105 | + |
| 106 | +then on the host machine, as root: |
| 107 | + |
| 108 | +```bash |
| 109 | +# spot running services |
| 110 | +systemctl | grep github-actions-runner |
| 111 | + |
| 112 | +# stop them all - or be specific if only for one orga |
| 113 | +systemctl stop github-actions-runner@* |
| 114 | + |
| 115 | +# disable them all - same |
| 116 | +systemctl disable github-actions-runner@* |
| 117 | + |
| 118 | +# remove the service files - same |
| 119 | +rm /etc/systemd/system/github-actions-runner@*.service |
| 120 | + |
| 121 | +# reload systemd |
| 122 | +systemctl daemon-reload |
| 123 | + |
| 124 | +# remove the runner folders - if it's the last orga that had a runner on this box |
| 125 | +userdel -rf github-actions |
| 126 | +``` |
| 127 | + |
| 128 | +## runner setup steps |
| 129 | + |
| 130 | +### once at least as root |
| 131 | + |
| 132 | +it's important that `github-actions` user is created with **the same uid/gid** as the image ! |
| 133 | +otherwise there will be permission issues and the container won't even start properly ! |
| 134 | + |
| 135 | +```bash |
| 136 | + |
| 137 | +# create a user `github-actions` on the machine |
| 138 | +groupadd -g 1001 github-actions |
| 139 | +sudo useradd -u 1001 -g 1001 -d /containers/github-actions -s /bin/bash github-actions |
| 140 | + |
| 141 | +# add it to the `docker` group |
| 142 | +usermod -aG docker github-actions |
| 143 | +``` |
| 144 | + |
| 145 | +### as github-actions - for one orga |
| 146 | + |
| 147 | +```bash |
| 148 | +# login as `github-actions` |
| 149 | +su - github-actions |
| 150 | + |
| 151 | +# create a folder for the orga runner |
| 152 | +ORGA=ue22-p25 |
| 153 | +mkdir github-actions-runner-${ORGA} |
| 154 | +cd github-actions-runner-${ORGA} |
| 155 | +``` |
| 156 | + |
| 157 | +### create the runner |
| 158 | + |
| 159 | +- go to github orga page |
| 160 | + -> Settings -> Actions -> Runners -> New self-hosted runner |
| 161 | +- select Linux / x64 |
| 162 | +- Download: |
| 163 | + - copy-&-paste **but WITHOUT the creation of `actions-runner` folder** |
| 164 | + turns out in our setup this is replaced by `github-actions-runner-${ORGA}` |
| 165 | +- Configure: |
| 166 | + - you may add the 'docker' tag to the runner just in case |
| 167 | + |
| 168 | +### back as root |
| 169 | + |
| 170 | +- install the runner as a service |
| 171 | + |
| 172 | +```bash |
| 173 | +# if needed |
| 174 | +cp ~/jupyterlab-examples/.github/scripts/github-actions-runner@.service /etc/systemd/system/github-actions-runner@.service |
| 175 | +systemctl daemon-reload |
| 176 | + |
| 177 | +ORGA=ue22-p25 |
| 178 | +systemctl enable --now github-actions-runner@${ORGA} |
| 179 | +``` |
| 180 | + |
| 181 | +- double check the logs - esp. wrt to the extra folder level if you did create |
| 182 | + `actions-runner` folder |
| 183 | + in that case rename the folder as appropriate |
| 184 | + ```bash |
| 185 | + journalctl -u github-actions-runner@${ORGA} -f |
| 186 | + ``` |
| 187 | + |
| 188 | +### how to check for current runners |
| 189 | + |
| 190 | +one possible caveat is - done that already - is to attach the runner to a repo |
| 191 | +instead of the orga... |
| 192 | + |
| 193 | +to check the current runners for the orga (run on your laptop for authenticated |
| 194 | +access): |
| 195 | + |
| 196 | +``` |
| 197 | +ORGA=ue22-p25 |
| 198 | +gh api /orgs/$ORGA/actions/runners |
| 199 | +``` |
| 200 | + |
| 201 | +in case of a mistake (if you attached the runner to a repo instead of the orga): |
| 202 | + |
| 203 | +- you'll need to remove the token in the downloaded folder before you can re-run |
| 204 | + config.sh again; this requires to have the old token though |
| 205 | +- another approach probably, remove the runner from the GH website, remove the |
| 206 | + folder and start over again |
| 207 | + |
| 208 | +## historical notes |
| 209 | + |
| 210 | +### first successful build with frontend (but without containerization) |
| 211 | + |
| 212 | +- was done: |
| 213 | + - with orga=ue22-p25 |
| 214 | + - using host context (no container) |
| 215 | + - relies on conda for isolation |
| 216 | + - runner box is bigjack |
| 217 | + - takes in the 12 minutes |
| 218 | + - and would probably be fragile if several runs were to be launched concurrently |
| 219 | + |
| 220 | +### forget about pixi |
| 221 | + |
| 222 | +too many issues with this idea of using pixi for isolation... just don't do that ! |
| 223 | +the `pixi` branch in `flotpython/course` has some leftovers of that attempt |
| 224 | + |
| 225 | +### remember to not try and run myst as root |
| 226 | + |
| 227 | +one lesson though, it can't run as root (jupyter as spawned by myst would just fail) |
0 commit comments