One repo script that gives time‑boxed SSH access (and the week it failed)

A small repo-level script I built to grant time-limited SSH access to servers for contractors and juniors — how it works, the race condition that taught me to use locking, and when this is still the wrong choice.

Written by: Arjun Malhotra

Close-up of hands typing on a laptop keyboard with code on the screen
Photo by Annie Spratt on Unsplash

It was 11:20 pm on a Friday. A client demo the next morning needed a quick config tweak on a staging server. The junior on-call pinged me from a hotspot on her way home: “Can you add my SSH key? I need access for an hour.” I could give her a key, edit authorized_keys, and move on — but I’ve done that dance before: orphaned keys, no audit trail, and a PR full of questions during retros.

So I wrote a tiny script that lives in every repo: give-me-access.sh. It creates a time‑boxed SSH key pair, pushes the public key to the server with a clear expiry tag, and trusts the server to clean up expired entries. It’s been the single most practical access pattern for our small, distributed Indian startup. It’s far from perfect — and one outage taught me why.

Why not use a proper SSH CA or a managed bastion? I like SSH CAs. I’ve set them up for larger teams. But for a 12‑person startup with contractors across Mumbai and Bengaluru, the overhead wasn’t worth it: PKI setup, onboarding docs, and a dependency on a central CA host. We needed something that:

What the script does (concrete) Here’s the flow I use — nothing magical, just small, repeatable steps.

Why this is better in practice

An honest failure: the race that taught me locking I was smug for three months. Then two engineers requested access to the same server within seconds. The script appended both keys to authorized_keys at the same time, and the file got corrupted (two concurrent writes clobbered it). Suddenly, nobody could login. We were on a 2am emergency call, fast-forwarding tail -f authorized_keys, manually reconstructing it, and muttering about our “clever” script.

Fix: use flock. I added a repo-level lock and a server-side lock file that the cleanup job respects. The change cost ten lines but saved three all-nighters. Lesson: local tools are easy to write, hard to get right in concurrency.

Other tradeoffs and real limits

A few small bits that made it usable day-to-day

When this approach failed me Late last year a contractor used our give-me-access script to debug a live import. Their laptop froze mid-upload and their key remained in authorized_keys. The cleanup cron had been temporarily disabled during a maintenance window. That one sticky key gave me a new policy: mandatory post‑access confirmation. The script now requires the user to run repo/scripts/release-access.sh before it will accept another request for the same user; if the user doesn’t, ops gets a notification. It’s clumsy but beats surprise keys.

If you try it

Takeaway The single thing I walked away with is this: small infra hacks must be built with the expectation they’ll be used by people who don’t read docs. That means safe defaults (short duration), clear audit trails, and mechanical cleanup. For day-to-day tasks at small Indian product teams, a tiny, time‑boxed SSH script is way more practical than a formal PKI — until you outgrow it. Then you’ll know exactly which parts to replace.