Technology

Designing Linux Users, Groups and sudo on a VPS for Multiple Projects and Teams

When you put several projects and multiple teams on a single Linux VPS, the technical challenge is rarely CPU or RAM – it is access management. Who can log in where? Who can deploy? Who can touch production databases? If you do not design a clear user, group and sudo structure from day one, the server slowly turns into a black box of shared passwords, random symlinks and mysterious file owners. At dchost.com, we regularly onboard teams that arrive with exactly this situation and want to clean it up without breaking their live sites.

In this article we will walk through a practical way to design Linux users, groups and sudo rules on a VPS so that multiple projects and teams can work safely side‑by‑side. We will focus on simple building blocks that scale: per‑person accounts, project groups, role‑based sudo and predictable directory ownership. You can apply the same ideas whether you run a single VPS at dchost.com or a fleet of servers behind a load balancer. The goal is straightforward: a layout that is easy to explain on a whiteboard, easy to automate and easy to audit after six months.

Why User, Group and sudo Design Matters on a Multi‑Project VPS

On a single‑tenant server, it is tempting to create one user such as ubuntu or root, share its SSH key in the team and move on. On a multi‑project VPS used by several developers, agencies or clients, that approach quickly becomes a liability.

  • No accountability: With shared accounts, you cannot answer simple questions like “Who edited config.php yesterday?” or “Who ran that dangerous command?”
  • Hard permission boundaries: When all code runs under one user, it is hard to keep Project A from reading or overwriting Project B’s files.
  • Risky operations: If everyone has full sudo, a typo in production can drop a database or bring the web stack down.
  • Painful off‑boarding: When someone leaves, you need to rotate keys and passwords everywhere because nothing is truly individual.

A clear architecture for Linux users, groups and sudo fixes these problems. You get:

  • Per‑person access: One Unix account per human, their own SSH key, easy off‑boarding.
  • Per‑project isolation: Project directories owned by dedicated groups instead of a single catch‑all user.
  • Role‑based sudo: Developers can restart PHP‑FPM or Nginx without being able to reconfigure the firewall or mount disks.
  • Cleaner deployments: CI pipelines and automation tools use well‑defined service users with minimal permissions.

If you are setting up a brand‑new VPS at dchost.com, this should sit right next to your first‑day tasks like updates and firewall rules. Our guide on the first 24 hours on a new VPS (updates, firewall and users) pairs nicely with the concepts we will cover here.

Core Building Blocks: Users, Groups, Permissions and sudo

Before designing the architecture, it is worth revisiting the basic Linux concepts we are going to combine.

Users: Human vs service accounts

A user in Linux is an identity: it owns files and can run processes. On a multi‑project VPS you usually have two types:

  • Human users: One account per person, like alice, bob. They log in over SSH, use shells and sudo.
  • Service users: Accounts such as nginx or deploy used by daemons and CI/CD tools. Often they do not have a real shell or password.

Groups: Shared permissions

A group is a way to give several users the same access to some resources. On a multi‑project VPS, groups are your main tool for representing:

  • Projects: proj_blog, proj_api
  • Teams: team_frontend, team_ops
  • Roles: sudo_web for web stack operations, sudo_db for DB operations

Permissions are then applied to these groups at the directory and sudo level.

Permissions and umask

Linux file permissions define what the owner, group and others can do: read (r), write (w), execute (x). For example, 750 means:

  • Owner: rwx (7)
  • Group: r-x (5)
  • Others: --- (0)

We will rely on group permissions heavily, so it is worth revisiting our article explaining Linux file permissions (644, 755, 777) for shared hosting and VPS if you need a refresher.

The umask controls default permissions of new files. For collaborative project directories, we usually want new files to be writable by the group, not just the owner.

sudo: Controlled privilege escalation

sudo lets a user run commands as another user (often root) while tracking who did what. The configuration lives in /etc/sudoers and /etc/sudoers.d/. With sudo you can say things like:

  • Members of sudo_web may restart Nginx and PHP‑FPM.
  • Members of sudo_db may run pg_dump and mysql on production databases.
  • Everyone else has no sudo at all.

Done right, sudo is one of your strongest protection layers on a multi‑project VPS.

Designing an Architecture for Multiple Projects and Teams

Let us design a model that works for 2–10 projects and a handful of developers or agencies on the same VPS. We will keep it simple enough to implement manually, but structured enough to automate later.

Step 1: Map your reality

In a quick planning session, list the things you need to represent on the server:

  • Projects: For example corporate‑site, api‑backend, shop‑frontend.
  • Environments: Production, staging, sometimes development.
  • Teams and roles: Who deploys? Who only reads logs? Who manages databases?
  • External parties: Any agencies or freelancers that should only touch one project?

Write this on a whiteboard. The Linux layout will be a direct translation of this picture.

Step 2: Define user types

We recommend three main types of accounts on the VPS:

  1. Personal users (one per person)
    Examples: alice, bob, carol. These accounts own SSH keys and are members of various groups but typically do not own project directories themselves.
  2. Project deploy users
    Examples: deploy_corp, deploy_api. These are used by CI/CD (GitHub Actions, GitLab, etc.) and sometimes for manual deploys. They own the deployed code, not the personal users.
  3. System/service users
    Examples: nginx, mysql, redis. These are created by your packages and system; we will not modify them except for permission needs.

Why separate personal and deploy users? Because code history, release ownership and rollbacks become much simpler. If a developer leaves, you do not have to chown half the filesystem.

Step 3: Define group types

Next, define groups that mirror your projects and roles:

  • Project groups: One per project per environment, e.g. g_corp_prod, g_corp_stage, g_api_prod.
  • Role groups for sudo: sudo_web (web stack operations), sudo_db (DB ops), sudo_ops (full operations).
  • Optional team groups: If you have large teams, you can add team_front, team_back etc. and then map team groups into project groups, but for most small VPS setups project groups alone are enough.

In practice, a developer’s Unix account will end up looking like:

  • Primary group: alice (created with the user).
  • Supplementary groups: g_corp_prod, g_corp_stage, sudo_web.

Step 4: Plan directory layout

A predictable directory structure makes permissions much easier to reason about. A common and clean pattern is:

/srv/
  corp-site/
    prod/
      app/      # code
      shared/   # uploads, cache, logs
    stage/
      app/
      shared/
  api-backend/
    prod/
      app/
      shared/

Each prod and stage directory can then be owned by its project+environment group, such as g_corp_prod. Web server config under /etc/nginx/sites-available follows the same naming.

Step 5: Decide your sudo policy

Finally, write down who should be able to do what with elevated privileges. A minimal but practical set:

  • Developers: Can restart services related to their projects (Nginx, PHP‑FPM, queue workers), but cannot manage firewall or users.
  • Ops / lead developer: Can manage web stack and database tools, but still not system‑wide configuration like disk partitioning.
  • Root (or a small ops group): Full access for rare operations, possibly only via sudo -i, never via direct SSH.

We will implement this with role‑based sudo groups in a moment.

Concrete Example: One VPS, Three Projects, Two Teams

Let us build a concrete example to make this more tangible. Imagine a VPS at dchost.com hosting three applications for a small company:

  • Corporate website: WordPress at corp.example.com
  • API backend: Laravel at api.example.com
  • Shop frontend: Next.js at shop.example.com

Two teams work on it: Web (WordPress + frontend) and Backend (API + some WordPress integration).

Users

  • Personal users: alice (backend), bob (web), carol (ops lead).
  • Deploy users: deploy_corp, deploy_api, deploy_shop.

Groups

  • Project groups: g_corp_prod, g_corp_stage, g_api_prod, g_shop_prod.
  • Role groups: sudo_web (web service control), sudo_db (database tools), sudo_ops (full operations).

Directory ownership

We may decide:

  • /srv/corp-site/prod owned by deploy_corp:g_corp_prod, mode 2770 (setgid, group‑writable).
  • /srv/api-backend/prod owned by deploy_api:g_api_prod, mode 2770.
  • /srv/shop-frontend/prod owned by deploy_shop:g_shop_prod, mode 2770.

The setgid bit (2 in 2770) ensures newly created files inherit the directory’s group, keeping collaboration simple.

Group membership

We might assign group membership like this:

  • alice (backend): g_api_prod, g_corp_stage, sudo_web, sudo_db
  • bob (web): g_corp_prod, g_shop_prod, sudo_web
  • carol (ops): all project groups + sudo_web, sudo_db, sudo_ops

Deploy users become members of their respective project groups so that CI/CD can write into project directories.

sudo rules

We then declare in /etc/sudoers.d/ (details in the next section):

  • %sudo_web may run systemctl restart nginx, php-fpm, queue workers.
  • %sudo_db may run mysql, mysqldump, psql, pg_dump.
  • %sudo_ops has ALL=(ALL) ALL for rare operations.

This gives a clean story in security audits: web team changes web services; backend team changes API and DB via well‑defined tools; ops can do everything, but rarely does so.

Implementing the Design Step‑by‑Step on Linux

Now let us translate the architecture into real commands. The examples assume a Debian/Ubuntu‑like system, but the concepts apply to other Linux distributions as well.

1. Create groups

# Project groups
sudo groupadd g_corp_prod
sudo groupadd g_corp_stage
sudo groupadd g_api_prod
sudo groupadd g_shop_prod

# Role / sudo groups
sudo groupadd sudo_web
sudo groupadd sudo_db
sudo groupadd sudo_ops

2. Create personal users

Create users without sudo yet; we will handle privileges via group membership.

sudo adduser alice
sudo adduser bob
sudo adduser carol

Then attach them to the relevant project and sudo groups:

sudo usermod -aG g_api_prod,g_corp_stage,sudo_web,sudo_db alice
sudo usermod -aG g_corp_prod,g_shop_prod,sudo_web bob
sudo usermod -aG g_corp_prod,g_corp_stage,g_api_prod,g_shop_prod,sudo_web,sudo_db,sudo_ops carol

For SSH best practices (keys instead of passwords, no direct root login), pair this with the approach from our article on SSH key management and access sharing for small teams.

3. Create deploy users

Deploy users typically do not need interactive shells. We can give them /usr/sbin/nologin or /bin/false as their shell and restrict authentication to SSH keys used by CI.

sudo useradd -m -s /usr/sbin/nologin -G g_corp_prod deploy_corp
sudo useradd -m -s /usr/sbin/nologin -G g_api_prod deploy_api
sudo useradd -m -s /usr/sbin/nologin -G g_shop_prod deploy_shop

Place CI/CD public keys into /home/deploy_*/.ssh/authorized_keys and lock these accounts down to deployment commands if necessary using command="..." in the authorized key entry.

4. Create project directories and set permissions

We now prepare the directory structure under /srv:

sudo mkdir -p /srv/corp-site/{prod,stage}/{app,shared}
sudo mkdir -p /srv/api-backend/prod/{app,shared}
sudo mkdir -p /srv/shop-frontend/prod/{app,shared}

# Ownership: deploy user as owner, project group as group
sudo chown -R deploy_corp:g_corp_prod /srv/corp-site/prod
sudo chown -R deploy_corp:g_corp_stage /srv/corp-site/stage
sudo chown -R deploy_api:g_api_prod /srv/api-backend/prod
sudo chown -R deploy_shop:g_shop_prod /srv/shop-frontend/prod

# Permissions: setgid (2), group-writable, no access for others
sudo chmod -R 2770 /srv/corp-site
sudo chmod -R 2770 /srv/api-backend
sudo chmod -R 2770 /srv/shop-frontend

The combination of chown and chmod 2770 ensures:

  • Only users in the project group (plus the deploy user) can read and write.
  • New files inherit the group, so collaboration does not break.
  • Other users on the VPS cannot even list the directories.

5. Adjust umask for group collaboration

To ensure new files are group‑writable, you can adjust the umask for deploy users and interactive shells. For example, set umask 0002 in /etc/profile.d/umask.sh:

echo 'umask 0002' | sudo tee /etc/profile.d/umask.sh > /dev/null

Now, files created inside project directories will typically be rw-rw---- (660) instead of rw-r----- (640), which is what you want for shared workspaces.

6. Configure role‑based sudo

Instead of editing /etc/sudoers directly, we recommend using separate files under /etc/sudoers.d/. Always edit with visudo -f so syntax errors do not break sudo entirely.

Web operations sudo rules

sudo visudo -f /etc/sudoers.d/web-ops

Example content:

%sudo_web ALL=(root) NOPASSWD: 
  /bin/systemctl reload nginx, 
  /bin/systemctl restart nginx, 
  /bin/systemctl reload php*-fpm.service, 
  /bin/systemctl restart php*-fpm.service, 
  /bin/systemctl restart supervisor, 
  /usr/bin/journalctl -u nginx -u php*-fpm -u supervisor

This allows web team members to restart web services and inspect logs without giving them unrestricted root.

Database operations sudo rules

sudo visudo -f /etc/sudoers.d/db-ops

Example content:

%sudo_db ALL=(root) NOPASSWD: 
  /usr/bin/mysql, 
  /usr/bin/mysqldump, 
  /usr/bin/psql, 
  /usr/bin/pg_dump

You might choose to remove NOPASSWD here for an extra confirmation step before running DB tools.

Ops / full admin sudo rules

sudo visudo -f /etc/sudoers.d/ops

Example content:

%sudo_ops ALL=(ALL) ALL

Keep membership in sudo_ops very limited (for example only your main ops lead). Everyone else should work through the more limited sudo_web and sudo_db roles.

7. Tie it into your security hardening

User, group and sudo design does not live in a vacuum. It should be part of a broader server security baseline: SSH hardening, firewall rules, automatic updates and log monitoring. Our VPS security hardening checklist with sshd_config, Fail2ban and disabling root SSH goes through these steps in detail and complements the architecture we have just built.

Security Best Practices and Common Pitfalls

Even with a good design, a few habits can quietly weaken your model over time. Here are issues we see often when helping dchost.com customers clean up existing VPS setups.

Avoid shared accounts

It is tempting to let everyone use a single deploy or admin account for convenience. The cost comes later when you cannot trace who did what or when off‑boarding requires changing keys and passwords in many places. Keep personal accounts for humans; restrict shared accounts to CI/CD and automation, and protect them carefully.

Never “fix” permissions with 777

When a web app fails with a “permission denied” error, a common quick‑and‑dirty fix is to run:

chmod -R 777 /srv/corp-site/prod

This gives everyone full control, including any exploited web process or untrusted user on the server. Instead, use group‑based permissions (like 2770) and proper group membership. If you are unsure how far to go, revisit our guide on safe Linux file permissions on VPS.

Disable direct root SSH login

Root should exist but not be directly reachable via SSH. Use:

PermitRootLogin no

in /etc/ssh/sshd_config, then restart SSH. Admins log in as themselves and use sudo. That way, logs show which person did what, not just “root”.

Separate staging from production

On small VPS setups it is common to put staging and production on the same machine. If you do, at least give them different groups (g_corp_stage vs g_corp_prod) and watch who is in each. Do not automatically grant staging access to everyone who touches production, and vice‑versa. That way, a risky experiment in staging is less likely to leak into production directories.

Combine with a firewall and log monitoring

Even the best user architecture will not help if SSH is open to the world with password logins, no firewall and no log alerts. We recommend pairing your access structure with a firewall configuration (ufw, firewalld or nftables) and basic monitoring. Our article on firewall configuration on VPS servers shows how to lock down network access in a practical way.

Scaling the Model: From One VPS to Many

As your projects and teams grow, this architecture should scale horizontally without rethinking everything.

Standardise your pattern

Once you are happy with the layout on one VPS, document your conventions:

  • How project groups are named (g_project_env).
  • How deploy users are named (deploy_project).
  • Where code and shared data live (/srv/project/env/{app,shared}).
  • Which sudo roles exist and what they allow (sudo_web, sudo_db, sudo_ops).

Then reuse this pattern on every new VPS or dedicated server you provision at dchost.com. Consistency makes troubleshooting and onboarding much easier.

Automate with Ansible and Terraform

Manually running useradd, groupadd and chown is fine for the first server. When you have several, you will want automation. A common pattern:

  • Use Terraform (or similar) to provision new VPS instances.
  • Use Ansible to configure users, groups, sudoers, directories and permissions based on structured variables (projects, environments, teams).

We have a dedicated guide on automating VPS setup with Terraform and Ansible where the same concepts are turned into reusable playbooks. Your user/group architecture is a perfect fit for this style of infrastructure‑as‑code.

Consider central authentication for larger teams

If you reach the stage where you manage dozens of servers and tens of developers, consider central authentication (LDAP/FreeIPA, SSSD, or managed directory services). Your logical design stays the same – one user per person, project/role groups, sudo roles – but group membership is now managed centrally and pushed to all servers.

Wrapping Up: A Calm, Maintainable VPS Access Model

A Linux VPS does not have to be a mystery box that only one senior developer can touch. With a deliberate design for users, groups and sudo, you get a structure you can explain in a five‑minute whiteboard session: “These are our project groups, those are our deploy users, here is what sudo_web can do, here is where each app lives under /srv.” That clarity pays off whenever you onboard a new colleague, respond to a security review or need to hand over operations to another team.

At dchost.com we see the same pattern over and over: teams that invest a bit of time early in a clean access model spend far less energy later firefighting permission issues, mysterious ownership problems or risky blanket sudo rights. If you are about to launch new projects or migrate from shared hosting to one of our VPS or dedicated server plans, this is an ideal moment to put these ideas in place. Pair this architecture with our VPS hardening checklist and, if you automate, with Terraform and Ansible based VPS automation. The result is a server layout that feels calm, predictable and ready to grow with your projects and teams.

Frequently Asked Questions

A good rule of thumb is one personal Unix account per human plus one deploy user per project. Each person logs in as themselves and gains access via project groups, rather than sharing generic accounts like "admin". Deploy users such as "deploy_api" or "deploy_corp" own the deployed code and are used by CI/CD pipelines. Service users like nginx or mysql are created by the system and should generally not be reused for human logins. This pattern keeps off‑boarding simple, makes audit logs meaningful and avoids the confusion of shared passwords or SSH keys.

In most cases, no. Giving every developer unrestricted sudo on production defeats the purpose of Linux permissions and makes mistakes much more costly. Instead, create role‑based sudo groups like "sudo_web" for web stack operations and "sudo_db" for database tools. Grant developers the minimal set of commands they need, such as restarting Nginx or PHP‑FPM, viewing service logs, or running mysqldump/pg_dump. Reserve a more powerful "sudo_ops" group for a very small number of people who handle rare, high‑risk operations. This way you keep productivity high while limiting blast radius when something goes wrong.

The safest way is to use a dedicated project group and rely on group‑based permissions. Create a group like "g_api_prod", assign all relevant developers and the deploy user to it, then make the project directory owned by "deploy_api:g_api_prod" with permission mode 2770. The leading 2 sets the setgid bit, which makes new files inherit the group. Combine this with a umask of 0002 so new files are group‑writable. Avoid using chmod 777, which exposes your code and data to any user or exploited process on the server. This scheme keeps collaboration smooth while maintaining strict isolation between projects.

Yes, you can safely share a VPS between staging and production environments if you isolate them properly. Use separate project groups such as "g_corp_prod" and "g_corp_stage", distinct directory trees (for example /srv/corp-site/prod and /srv/corp-site/stage) and careful sudo rules so that staging operations never point at production databases or caches by mistake. Limit who belongs to the production groups and treat staging as a less privileged environment. For stronger guarantees, combine this logical separation with firewall rules, different database instances and disciplined deployment pipelines.

The model of one personal user per person, project groups and role‑based sudo is a perfect foundation for automation. With Terraform you can provision new VPS instances at dchost.com, and with Ansible you can declaratively create users, groups, sudoers files and project directories exactly as designed. Group names like g_project_env and sudo roles like sudo_web become variables in your playbooks. That means every new server starts with the same clean, audited access model, rather than ad‑hoc manual changes. Our article on automating VPS setup with Terraform and Ansible shows how to turn this design into reproducible infrastructure code.