The default way teams share a server is that everyone logs in as ubuntu or root. It works right up until two people run an agent in the same directory, or somebody's shell history contains a token, or you need to know who deleted something.

The fix is unglamorous and about thirty years old.

One Linux user per person

sudo adduser --disabled-password --gecos "" alice
sudo chmod 750 /home/alice

750 is the important part. The default on many distros is 755, which means every other user on the box can read Alice's home directory โ€” including her shell history, her agent's config, and any credentials it cached.

Each user also gets their own session server, keyed by uid. Bob cannot attach to Alice's session even if he knows its name. That falls out of the design rather than needing configuration.

A shared directory that actually works

Collaboration needs somewhere shared. The naive approach โ€” chmod 777 โ€” is how you end up with files nobody can overwrite.

sudo groupadd devteam
sudo usermod -aG devteam alice
sudo usermod -aG devteam bob
sudo install -d -m 2770 -g devteam /srv/shared

Two details in 2770 carry all the weight:

  • The leading 2 is setgid. Files created inside inherit the devteam group automatically, so a file Alice creates is writable by Bob without anyone remembering to chgrp.
  • The trailing 0 denies everyone else. This is the one people get wrong.

The mistake worth highlighting

Most guides suggest 2775. We used 2775 too, then tested it properly: we created a user deliberately excluded from the shared group and checked what they could reach.

They could read every file in the shared directory. The trailing 5 grants read and execute to "other", and "other" means every account on the machine. If your product promises that some things are private, 2775 quietly breaks that promise.

2770 fixes it. The lesson is less about the octal than about the method: assert the negative. Do not check that the people who should have access do โ€” check that someone who should not, cannot.

Give everyone their own git identity

A shared deploy key means every commit is from "the server". Generate a key per user:

sudo -u alice ssh-keygen -t ed25519 -N "" -C "alice@box" \
  -f /home/alice/.ssh/id_ed25519

Each person adds their own public key to their own GitHub account. Now git push is attributable, and revoking one person's access does not mean rotating a key everyone depends on.

Verify it, do not assume it

Four commands tell you whether the setup is real:

sudo -u bob ls /home/alice          # must fail
sudo -u bob touch /srv/shared/x     # must succeed if bob is in the group
sudo -u carol cat /srv/shared/x     # must fail if carol is not
sudo -u bob ls /run/user/$(id -u bob)   # must not reach alice's sessions

If any of those does the opposite of what you expect, you have found the bug now rather than during an incident.