Adding a Developer to the EC2 Devbox¶
Module: environments/aws/edge/ap-south-1/dev/00-Infrastructure/02-ec2-devbox
1. Add the user to keypairs.tf¶
Add an entry to the users map:
locals {
users = {
# ...existing users...
new_user = {
username = "new_user"
email = "new.user@ai71.ai"
}
}
}
Use keypair_only = true instead if you only want credentials generated without a login account (e.g. for someone who isn't ready to be provisioned yet).
2. Generate their credentials¶
Review the plan. A new user always adds 4 resources:
tls_private_key.users["new_user"]aws_key_pair.users["new_user"]aws_secretsmanager_secret.user_private_keys["new_user"]aws_secretsmanager_secret_version.user_private_keys["new_user"]
It will also show aws_instance.devbox as needing replacement, because the new user's key is baked into user_data, and user_data_replace_on_change = true. Replacing the instance means:
- A brand-new instance boots from the pinned AMI.
- The old root volume is not deleted (
delete_on_termination = false), but it becomes orphaned — the new instance does not carry over existing developers' home directories automatically. - The public IP (
3.111.79.98) stays the same, since the Elastic IP itself isn't destroyed, only re-associated.
Choose one of the two paths below depending on whether a replacement is acceptable right now.
Path A — Full apply (accepts instance replacement)¶
Use this when it's safe to cycle the box (e.g. scheduled maintenance window, or no one has uncommitted work on it).
This creates the credentials and replaces the instance, so the new user's Linux account, authorized key, and passwordless sudo are created automatically via user_data — no manual steps needed.
Path B — No-downtime (generate credentials only, provision manually)¶
Use this when other developers have active work/data on the running instance and it can't be replaced right now. This is what was done to onboard mukammed_alimbet.
Step 1 — Apply only the credential resources, skipping the instance:
terraform apply \
-target='tls_private_key.users["new_user"]' \
-target='aws_key_pair.users["new_user"]' \
-target='aws_secretsmanager_secret.user_private_keys["new_user"]' \
-target='aws_secretsmanager_secret_version.user_private_keys["new_user"]'
-targetproduces a warning that the plan may be incomplete — that's expected here, since we're intentionally deferring the instance change.
Step 2 — Retrieve the new user's public key (derived from the private key just generated):
aws secretsmanager get-secret-value \
--secret-id ai71-aps1-dev-edge-devbox/keypairs/new_user \
--region ap-south-1 \
--query SecretString \
--output text > new_user.pem
chmod 600 new_user.pem
ssh-keygen -y -f new_user.pem > new_user.pub
Step 3 — Get your own key (you need existing sudo access to the box, e.g. tarun_mittal):
aws secretsmanager get-secret-value \
--secret-id ai71-aps1-dev-edge-devbox/keypairs/tarun_mittal \
--region ap-south-1 \
--query SecretString \
--output text > tarun_mittal.pem
chmod 600 tarun_mittal.pem
Step 4 — SSH in and manually run the same provisioning steps user_data would have run (see templates/user_data.sh.tftpl for the source of truth):
PUBKEY=$(cat new_user.pub)
ssh -i tarun_mittal.pem tarun_mittal@3.111.79.98 "sudo bash -c \"
set -euo pipefail
useradd -m -s /bin/bash 'new_user'
mkdir -p /home/new_user/.ssh
chmod 700 /home/new_user/.ssh
echo '\$PUBKEY' > /home/new_user/.ssh/authorized_keys
chmod 600 /home/new_user/.ssh/authorized_keys
chown -R new_user:new_user /home/new_user/.ssh
echo 'new_user ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/new_user
chmod 440 /etc/sudoers.d/new_user
chmod 755 /home/new_user
id new_user
\""
Step 5 — Verify login:
Step 6 — Clean up local key files once the key has been securely handed off:
Note on drift after Path B¶
The account now exists on the running instance but Terraform still shows aws_instance.devbox as pending replacement (because user_data differs from what's actually running). This is expected and harmless — it's not a conflict:
- If/when the instance is next replaced for any other reason,
user_datawill recreate this same account automatically, since the user is already inkeypairs.tf. - Run
terraform planany time to confirm no other drift has crept in.
3. Hand off the private key¶
Retrieve and securely share the .pem file with the new developer, then delete any local copies:
aws secretsmanager get-secret-value \
--secret-id ai71-aps1-dev-edge-devbox/keypairs/new_user \
--region ap-south-1 \
--query SecretString \
--output text > new_user.pem
Give them the connect command:
4. Update the module README¶
Add a row for the new user to the table in 02-ec2-devbox/README.md so the docs there stay in sync.
Removing a user¶
Remove their entry from the users map in keypairs.tf and run terraform apply (this also replaces the instance, so plan accordingly using the same considerations as above). If they were provisioned manually via Path B, also remove them directly on the box: