Skip to content

fix: apply the user-level settings for every human account, not just one - #65

Merged
catinspace-au merged 2 commits into
mainfrom
feat/multi-user-target
Aug 26, 2026
Merged

fix: apply the user-level settings for every human account, not just one#65
catinspace-au merged 2 commits into
mainfrom
feat/multi-user-target

Conversation

@catinspace-au

Copy link
Copy Markdown
Contributor

A box with more than one person on it only ever got the dotfiles for whoever was named. Everyone else got the system-wide half and nothing else -- no shell config, no ~/.cargo, no ~/.local/bin, no dconf, no container stacks -- and the run reported success either way. A desktop image with a provisioning account plus a real user is exactly that shape.

install.sh now discovers the accounts and runs one pass per user.

Who gets it

Skipped by default:

  • root
  • system accounts -- uid below 1000, the systemd range above 60000, shells of nologin/false/sync
  • the cloud image's own account, which exists to provision the machine rather than to work in

That last one is read from system_info.default_user.name in /etc/cloud/cloud.cfg rather than matched by name, because it is ubuntu on an Ubuntu image and cloud-user on a Red Hat one. --users a,b names any set instead, that account included.

Why the loop is outside the roles

There are roughly 350 user-scoped references across 49 files. A per-task loop, or a user-scope tag applied to each of them, would eventually miss one silently -- which is the failure mode this area already has a history of. Looping the invocation cannot miss a task by construction, and the system-wide tasks are idempotent, so later passes no-op on everything except that user's own files.

The playbook is unchanged and still takes one hyperi_target_user per run, so nothing about tag semantics moved. Anything driving ansible-playbook directly writes its own loop, which the docs now show.

Verified

On a real two-account host, with both accounts seeded to a 12h clock:

  • pass for hyperi -> hyperi moves to 24h
  • pass for ubuntu -> ubuntu moves to 24h, and hyperi is still 24h

so a later pass does not undo an earlier one. Discovery returns hyperi on one box and derek on the other, correctly excluding ubuntu in both cases. tools/ci/run-tests.sh green, shellcheck clean.

A box with more than one person on it only ever got the dotfiles for whoever
was named. Everyone else got the system-wide half and nothing else -- no shell
config, no ~/.cargo, no ~/.local/bin, no dconf, no container stacks -- and the
run reported success either way. A desktop image with both a provisioning
account and a real user is exactly that shape.

install.sh now discovers the accounts and runs one pass per user.

Discovery skips root, the system ranges (uid < 1000, the systemd range above
60000, shells of nologin/false/sync), and the cloud image's own account. That
last one is read from system_info.default_user.name in /etc/cloud/cloud.cfg
rather than matched by name, because it is `ubuntu` on an Ubuntu image and
`cloud-user` on a Red Hat one; it exists to provision the machine, not to work
in. `--users a,b` names any set instead, that account included.

One pass per user rather than a loop inside the roles. There are roughly 350
user-scoped references across 49 files, so a per-task loop or a `user-scope`
tag would eventually miss one silently -- which is the failure mode this area
already has a history of. Looping the invocation cannot miss a task by
construction, and the system-wide tasks are idempotent, so later passes no-op
on everything except that user's own files.

The playbook itself is unchanged: it still takes one hyperi_target_user per
run. Anything driving ansible-playbook directly writes its own loop, which the
docs now show.

Verified on a real two-account host. With both accounts seeded to a 12h clock,
a pass for each leaves both at 24h -- the second pass does not undo the first.
Discovery returns `hyperi` on one box and `derek` on the other, correctly
excluding `ubuntu` in both cases, and `tools/ci/run-tests.sh` is green.
…settings

Falling back to whoever invoked the install would write dotfiles into root or the image's own provisioning account on exactly the machines the criteria exist to protect. Name the account with --users instead.
@catinspace-au
catinspace-au merged commit 82a7295 into main Aug 26, 2026
16 checks passed
@catinspace-au
catinspace-au deleted the feat/multi-user-target branch August 26, 2026 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant