Bare gitops for atlante.unipv.it
  • Python 72.2%
  • Shell 18.9%
  • Dockerfile 8.9%
Find a file
2026-06-29 10:34:17 +02:00
docs/superpowers Add PAM host-auth implementation plan 2026-06-25 15:39:03 +02:00
hub Add libnss-extrausers + minimal PAM service to hub image 2026-06-25 15:47:51 +02:00
hub-pam Harden PAM sync script; fix compose admin default; document mount-order 2026-06-25 16:05:13 +02:00
systemd Add systemd path-unit to auto-sync the hub PAM database 2026-06-25 15:45:09 +02:00
traefik Initial import: atlante ops (Traefik + static book + JupyterHub) 2026-06-17 00:41:58 +02:00
.env.example Mount curated PAM DB into hub; default admin to zanussi 2026-06-25 15:51:08 +02:00
.gitignore Gitignore SDD scratch dir 2026-06-25 16:07:16 +02:00
book.nginx.conf Initial import: atlante ops (Traefik + static book + JupyterHub) 2026-06-17 00:41:58 +02:00
compose.yml Make book bind-mount path relative 2026-06-25 16:57:09 +02:00
jupyterhub_config.py Dynamic image seleciton in hub 2026-06-29 10:34:17 +02:00
README.md Document SELinux bin_t relabel for the PAM sync unit 2026-06-25 17:25:13 +02:00

atlasworks

Ops for atlante.unipv.it — a rootless-podman stack behind Traefik with:

  • a static Jupyter Book at /
  • JupyterHub at /hub (one container per user, who picks a simulator image).

Checked out on the server at ~/atlasworks.

Run the setup on the server

0. One-time host (sudo)

echo 'net.ipv4.ip_unprivileged_port_start=80' | sudo tee /etc/sysctl.d/99-rootless-lowports.conf
sudo sysctl --system
sudo loginctl enable-linger zanussi      # keep the rootless stack up across logout/reboot

0b. One-time host — PAM auth (sudo)

Hub login authenticates against local host accounts in the jupyterhub group. The hub runs rootless and cannot read /etc/shadow, so a root systemd path-unit exports only that group's members into hub-pam/{passwd,shadow,group} (owned by zanussi, gitignored), which the hub reads via libnss-extrausers.

sudo groupadd -f jupyterhub
sudo usermod -aG jupyterhub zanussi      # repeat per allowed user
sudo install -m 0644 ~/atlasworks/systemd/jupyterhub-pam-sync.service /etc/systemd/system/
sudo install -m 0644 ~/atlasworks/systemd/jupyterhub-pam-sync.path    /etc/systemd/system/
# SELinux (Enforcing): systemd (init_t) may only exec bin_t files
sudo semanage fcontext -a -t bin_t '/home/zanussi/atlasworks/hub-pam/sync-pam\.sh'
sudo restorecon -v /home/zanussi/atlasworks/hub-pam/sync-pam.sh
sudo systemctl daemon-reload
sudo systemctl enable --now jupyterhub-pam-sync.path
sudo systemctl start jupyterhub-pam-sync.service   # initial populate

Run 0b before bringing the stack up (step 4): compose.yml bind-mounts hub-pam/{passwd,shadow,group} as files, so they must already exist (created by the initial sync-pam.sh run above). If the stack starts first, podman auto-creates them as empty directories and every login fails.

Password changes (passwd) and group changes (usermod -aG) resync automatically; no hub restart needed. Only local (files//etc/shadow) accounts work — SSSD/LDAP users are not supported by this path.

1. Configcp .env.example .env, then set in .env: HUB_HOST=atlante.unipv.it, CONTAINER_SOCK=/run/user/$(id -u)/podman/podman.sock, ACME_EMAIL, HUB_ADMIN. (ACME_EMAIL must ALSO be set literally in traefik/traefik.prod.yml — Traefik doesn't expand ${VAR}.)

2. Host roots

  • ~/datasets/ — raw inputs, mounted ro at /data.
  • ~/workspace/<sim>/{config,workloads,results} — per-sim config, .wl workloads, outputs; mounted rw at /workspace. Container writes work via keep-id (the spawner maps the container user to you) — no chown needed.

3. Build the simulator runtime image — built from the sim repo itself:

cd ~/research/autoscaling && ./docker/build.sh   # -> peg-runtime-autoscaling:<date> + :latest

Builds (context = repo root): CloudSim jar + the pinned peg-autoscaling Python 3.13 kernel + R/IRkernel + jupyterlab-git. Tags the build with the date plus a floating :latest — the tag the hub spawns.

4. Bring up the stack

export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock
podman compose --profile prod up -d

5. Log in — at https://atlante.unipv.it/hub/, log in with your host username + password (you must be in the jupyterhub group; see step 0b). HUB_ADMIN (zanussi) is the hub admin. Then pick "Autoscaling simulator (latest)".

Updating

  • Bind-mounted config (jupyterhub_config.py, compose.yml, traefik/*, .env): podman compose --profile prod up -d --force-recreate <service>.
  • Simulator image: rerun ~/research/autoscaling/docker/build.sh — it retags :latest, so no config edit is needed; then --force-recreate jupyterhub. Running user servers survive; new spawns get the rebuilt :latest. (Roll back by retagging a dated image to :latest.)
  • Book content: deployed separately by the journal repo's deploy.py into ~/atlasworks/book/ (live, no restart).