I'm running a small startup project on a single Oracle Cloud VM. The backend API and two PostgreSQL databases—development and production—run in Docker containers. At the moment, I connect to the databases from DBeaver through an SSH tunnel. I'm adding another developer and need to let them work with the development database without sharing my private SSH key or accidentally giving them unrestricted server access. Adding their public key to the main Ubuntu user's authorized_keys seems broader than necessary, especially if that account has sudo privileges. What's the usual approach for a small team? Should I create a dedicated, restricted SSH user that can only forward the database port, use a private VPN such as Tailscale, restrict access by firewall rules, use a bastion or access-management tool, or avoid a shared database by giving each developer a local or isolated environment? I'm looking for a sensible balance between security, maintainability, and something that can be deployed quickly on a limited budget.
3 Answers
Whatever option you choose, avoid setting it up manually in a way you’ll forget later. Document the account and database permissions, use individual identities, log access, and have a simple process for removing someone’s access. A restricted SSH tunnel or private VPN is perfectly reasonable at this size; tools such as Vault, Teleport, or cloud IAM can be introduced later when the number of users, environments, or compliance requirements justifies the extra complexity.
For a small setup, a good immediate solution is a separate account for each person, SSH key authentication, no direct root login, and no sudo unless it is genuinely needed. You can make the account unable to start an interactive shell and restrict its SSH configuration to forwarding only the development database port. PostgreSQL should also have a distinct role for that developer with only the permissions they need. Keep production on a separate account and database role, preferably read-only or inaccessible altogether. A VPN such as Tailscale can simplify network access as the team grows, but it should complement—not replace—proper Linux and database permissions.
Before granting access to a shared development database, consider whether everyone actually needs it. PostgreSQL is easy to run locally with Docker Compose or development containers, and migrations can create the schema consistently for each developer and for CI. A shared staging or integration environment is still useful for testing deployments, but isolated local databases prevent one person’s experiment or destructive query from disrupting everyone else. If the team does use a shared environment, protect it with backups and clearly separated roles.
That makes sense for most day-to-day work. I’d still want controlled access to the shared environment for deployment and integration testing, but local databases could cover regular development.

Adding someone’s public key does not automatically give them root access; the privileges come from the account it is installed under. The risky part is using a powerful shared Ubuntu account, so individual low-privilege accounts and separate audit trails are important.