Part 6 of 6 Running one for other people
Adding the people
By the end of this chapter, Laurence and Keanu have accounts of their own on the team's instance, each with the way in they will actually use, and a screen in the office shows the board and can do nothing else.
The instance has been running since An account, an install and a first run with exactly one account on it, and that account is not a person. Putting that right is the first thing this chapter does, and it has to be done in a particular order.
The work so far
Laurence has the service account, the install and the instance of An account, an install and a first run, reached at the address TLS, a proxy and systemd gave it:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin subroutine
sudo python3 -m venv /opt/subroutine
sudo /opt/subroutine/bin/pip install "subroutine[postgres]"
sudo install -d -o subroutine -g subroutine -m 0755 /var/lib/subroutine
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine init --workspace metacortex --instance-name MetaCortex
sudo -u subroutine tee -a /var/lib/subroutine/config/subroutine/config.toml > /dev/null <<'SETTING'
public_url = "https://tasks.example.com"
SETTING
The account you already have is not a person
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine user list
One row. subroutine init makes the first account and names it after whoever ran it, and on a server that was the service account. It administers the instance, it owns metacortex, and nobody can be it: it has no login shell, and nothing has ever issued it a credential.
subroutine user list without a workspace is the instance's accounts and what each may do to the installation itself. With a workspace it is that workspace's members and their roles there, which is the list further down.
It cannot be retired first
The tidy-minded move is to take the robot account out of the team's workspace before anybody else is in it. It is refused:
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine user remove subroutine
The same rule refuses subroutine user role, for the same reason: demoting the last administrator and removing them leave the workspace in the same state. A workspace nobody can administer has thrown away the remedy for every later mistake, including that one, and it cannot be repaired from inside.
So the order is fixed. Somebody who can administer the workspace comes first, and everything else follows.
A person who can administer it
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine user create laurence --name "Laurence Fishburne" --role admin --browser
subroutine user create is one command doing three things: it makes the account, puts it in the workspace, and gives it a role there. --role is member unless you say otherwise, and --workspace can be left out while there is only one.
An account with no workspace can see nothing at all, which reads as a broken credential rather than a missing role. That is why the membership arrives with the account instead of waiting for a second command somebody has to remember.
--browser mints the sign-in link in the same breath, which is the other half of the work and the half that is easy to forget. There is no password, so an account nobody can get into is the ordinary result of stopping one command early.
That third line is about this server, not about Laurence. Adding a second account would otherwise leave the command line here unable to tell whose list to show, so it pins the one it had. It is printed once, on the first account added, and setting somebody up never takes something away from you.
Now leave the service account where it is. With Laurence able to administer the workspace, removing it would be allowed, and it would leave every command you run on this server belonging to no workspace and with nothing to write to. It costs one row in a list, and there is nothing else to be gained.
The rest of the team
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine user create keanu --name "Keanu Reeves" --browser --terminal
--browser and --terminal are not alternatives. The link opens a browser session and the token is what a terminal and an agent present, so somebody who uses both doors needs both, and somebody having their machine set up by a colleague needs the token whatever they use.
The last lines are the one command Keanu runs at his end, which Your terminal here, your work there is the reader's side of. The name in it is his to choose, because it becomes the first part of every address he writes.
Send all of it the way you would send anything private. The link signs in as him and the token acts as him, and neither can be shown again.
Who is in the workspace, and what a role is
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine user list --workspace metacortex
Roles belong to a workspace. member in one is not member in another: each workspace is seeded with its own, and this is the command that says who holds which. So an instance holding a second workspace is holding a second, separate answer to what somebody may do, and deciding that is its own permission rather than something an administrator has everywhere.
subroutine user add is how somebody who already has an account joins a second workspace. It takes --role rather than assuming one, because there is no reason a person's place in one workspace should decide their place in another.
Changing what somebody may do
Adding somebody and re-grading them are two decisions, so they are two commands:
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine user role keanu admin
It moves somebody who is already a member, and turns down somebody who is not, naming the command that would put them in:
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine user role carrieanne member
The pair each name the other, so whichever you reach for first tells you the one you wanted.
When somebody leaves
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine user remove keanu
subroutine user remove takes away the membership and not the account:
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine user list
He is still there, with nothing he may do. Everything he wrote stays, and stays attributed to him, which is the point: a backlog that forgets who decided what is worth less than one that remembers, and somebody leaving is not a reason to rewrite the record.
Coming back is user add, and the role is said again rather than remembered:
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine user add keanu --workspace metacortex --role member
He was an administrator when he left and he is a member now, because that is what was typed. A role is a decision about today rather than a property somebody keeps.
Handing a way in over afterwards
The two flags are a convenience, and the commands behind them stand on their own. This is what to run when somebody has lost a link, or is setting a second machine up:
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine login link --username keanu
subroutine login link is also your own way back in. If the browser is how you administer this instance and something has gone wrong with it, a link minted at the console is a door that does not depend on anything else working. A stale one costs nothing: mint another.
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine token create --username keanu --title "Keanu's desktop"
The title is what you will read in a list of credentials later, so name the machine rather than the person: one person with a desktop and a phone has two, and only the title tells them apart when one of them has to go.
That last line is advice for a credential you issued for yourself, and this one is for Keanu's machine rather than this one. The file it names is this server's.
--username and --service-account are separate flags because they are separate decisions. The first issues a credential for somebody who already has an account; the second is for a machine identity, and makes one if there is none. Naming a person under it is refused rather than quietly handing out their credential:
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine token create --service-account keanu
Where a link's address comes from
It is public_url, which TLS, a proxy and systemd set. Leave it unset and a link carries the address the instance is listening on, which on the arrangement this part builds is loopback: a working address on the server itself, and the wrong one to hand to anybody else.
An instance listening beyond this machine with nothing saying where it is reached has no address to put in a link at all, and says so rather than making one that cannot work:
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
SUBROUTINE_HOST=0.0.0.0 \
SUBROUTINE_PUBLIC_URL= \
/opt/subroutine/bin/subroutine login link --username keanu
The two settings on that command put the instance back into the state it would be in without the previous chapter, which is the state a link is most often minted in by mistake: the proxy is up, the address works in a browser, and nothing has told Subroutine what it is.
A screen that only reads
A wall display, a kiosk, a board in a corridor: that is an account with the viewer role, and it needs nothing built.
sudo -u subroutine env \
XDG_CONFIG_HOME=/var/lib/subroutine/config \
XDG_DATA_HOME=/var/lib/subroutine/data \
XDG_STATE_HOME=/var/lib/subroutine/state \
/opt/subroutine/bin/subroutine user create screen --name "Office screen" --role viewer --browser
The browser hides the controls rather than refusing them. What a reader may do is worked out per workspace, and the page is drawn from that answer, so the capture box, Complete, Edit, the status and assignee controls and the comment box are absent. A control that appears and then says no is worse than one that is not there, and the instance refuses the write underneath it either way, as Signed in, from a browser or a phone shows from the other end.
Read-only is not inert. Controls that change how the page is read stay, such as revealing the rest of a truncated list, because that is a fact about the reader rather than about the item.
A screen nobody touches stays signed in. A session measures neglect rather than age: every use puts it back, so a display polling all day never lapses, while the same device left in a drawer eventually stops working.
Two things are worth knowing before you put one up, because neither is obvious and both are the cost of doing it this way:
- Getting it signed in is a person's job, at the machine. A link works once and not for long, so the first sign-in, and any after a lapse, means somebody standing at the screen with a fresh one. There is no long-lived credential a browser can hold instead, and a token will not sign a browser in.
- It is an account, so it is a row in
user list. On an instance where the other rows are people that is a small lie, and the remedy is to name it as what it is:screen,foyer,standup. Nobody should have to wonder later who that was.
Give it an account of its own rather than sharing somebody's. It can be revoked on its own, it says who did what if the screen is ever used to write, and turning it off locks nobody out.
With that, the people are in, each with the door they will use, and the instance is somebody's to administer other than the account that installed it.