Server security guide · Romania

How do I manage users and sudo with least privilege?

One shared 'deploy' account, a password the whole team knows and unrestricted sudo is a very common setup on small servers. It works until someone leaves, a laptop is stolen, or you have to find out who ran a command.

Updated:

Short answer

  1. Give every person their own account with their own SSH key, and remove shared accounts that use a password.
  2. Grant administrative rights through precise rules in /etc/sudoers.d/, by command and by group, rather than NOPASSWD: ALL for everyone.
  3. Run applications under service accounts created with nologin, with no shell and no password, so nobody can open a session as them.
  4. When a colleague leaves, disable the account, delete their key and rotate the secrets they could see on the same day, and audit accounts regularly with getent and lastlog.
Basic rule
one account per person, zero shared accounts
Where sudo rules live
/etc/sudoers.d/<role>, edited with visudo -f
Service accounts
shell /usr/sbin/nologin, no password
Offboarding
usermod -L -e 1, delete the key, rotate secrets

Why one account per person and sudo by command

A shared account makes two things impossible: finding out who made a change, and withdrawing access from one person alone. With one account per person, the sudo log says who ran what, and a departure means disabling a single account. The default on many VPS images, a sudo group that can run anything without a password, turns any compromised SSH key into root. Define roles instead: whoever deploys can restart the service and read its logs, whoever administers the database runs its commands, and full root stays with two people.

Service accounts, offboarding and audit

The application, the web server and the database each run under their own system account with a nologin shell and no password: even if someone learns the database password, they cannot open a session as that account. Offboarding is a written procedure carried out on the day of departure: lock the account, set its expiry in the past, remove the key from authorized_keys on every server, remove the person from groups, and rotate the passwords and API keys they have seen. Audit monthly: accounts with a valid shell, the sudo group, last login. Disable any account unused for 90 days.

  • sudo rules use the full path of the command, with no wildcards that allow arbitrary arguments
  • Commands that open an editor or a shell are never granted through restricted sudo
  • Commands that open a pager (journalctl, systemctl status, man) are granted only with --no-pager
  • The list of accounts and keys lives in configuration management, not in someone's head

What Romanian law expects

GDPR Article 32 requires measures that ensure only authorised people can reach personal data, and after a breach ANSPDCP checks exactly this control: who had access, on what basis, and when it was withdrawn. A shared account cannot answer any of those questions. For entities under OUG 155/2024, the NIS2 transposition approved by Law 124/2025, access-control policies and human-resources security are explicit minimum measures (Article 13, point f). Withdrawing access on the day someone leaves also protects the company against a disgruntled former employee.

Account types on a production server and their rights
Account typeShellAuthenticationsudo
Administrator (two people)bashpersonal SSH key, over the VPNALL, with a password on every command
Deploy / developerbashpersonal SSH keyonly the deploy commands, in sudoers.d
Service account (app, www-data, postgres)/usr/sbin/nologinnonenone
CI / automationbash, or nologin with ForceCommanddedicated, restricted keya single deploy command
rootbashlocal or console onlyn/a

Commands and configuration

Personal account with a key, and a service account without a shell
sudo adduser --disabled-password --gecos "Ana Popescu" ana
sudo install -d -m 700 -o ana -g ana /home/ana/.ssh
echo "ssh-ed25519 AAAA...Ana's key... ana@laptop" | sudo tee /home/ana/.ssh/authorized_keys
sudo chmod 600 /home/ana/.ssh/authorized_keys && sudo chown ana:ana /home/ana/.ssh/authorized_keys

sudo useradd --system --shell /usr/sbin/nologin --home /var/lib/app --create-home app
/etc/sudoers.d/deploy, edited with: sudo visudo -f /etc/sudoers.d/deploy
# the deploy group can restart the application and read its logs, nothing else.
# WARNING: journalctl and systemctl status open a pager, and a pager run as root
# allows escaping to a shell with !sh. That is why we force --no-pager and forbid free arguments.
Cmnd_Alias APP_OPS = /usr/bin/systemctl --no-pager restart app.service, \
                     /usr/bin/systemctl --no-pager --full status app.service, \
                     /usr/bin/journalctl --no-pager -n 200 -u app.service
Defaults!APP_OPS env_reset, env_delete += "PAGER SYSTEMD_PAGER LESS LESSOPEN LESSSECURE"
%deploy ALL=(root) NOPASSWD: APP_OPS
Same-day offboarding and monthly audit
# offboarding
sudo usermod -L -e 1 ana
sudo gpasswd -d ana sudo; sudo gpasswd -d ana deploy
sudo rm -f /home/ana/.ssh/authorized_keys
# then rotate the passwords and API keys she has seen

# audit: accounts that still have a login shell
getent passwd | grep -vE ':(/usr/sbin/nologin|/sbin/nologin|/bin/false)$'
getent group sudo deploy
sudo lastlog -b 90 | grep -v "Never"

Practical examples

IT outsourcing company in Iasi sharing a 'deploy' account

Ten people, one account, one password from 2021 and NOPASSWD: ALL. When a former employee deleted a customer directory, nobody could say who it was. The company created personal accounts with keys, limited sudo to the deploy commands and wrote an offboarding procedure.

Fintech in Bucharest with a Java service running as root

The Java service ran as root 'because it needs port 443'. A deserialisation flaw gave the attacker root on the server. Now the service runs under a nologin account on a high port, with nginx in front on 443.

Common mistakes

  • Putting every team member in the sudo group with NOPASSWD: ALL, so one lost SSH key means root.
  • Using a shared human account with a password everyone knows, instead of named accounts plus a separate automation account for CI.
  • Granting through sudo a command that opens an editor or a shell and believing it is restricted.
  • A colleague left three months ago, and their key is still on five servers.

How 4hosting helps

  • Hardening & Compliance defines the roles, the sudo rules and the offboarding procedure. Your plan includes the hours: 1 h a month from cPanel Advanced up, 1–8 h on VPS, 5–10 h on dedicated servers (depending on plan), 10 h on GPU servers.
  • You request those hours from the DevOps Services section of the client panel; they are not carried over, and extra hours are accepted and billed separately.
  • SIEM & Incident Response centralises sudo and authentication logs and alerts on a new account or an unusual command run as root.
  • Infrastructure as Code & GitOps puts accounts, keys and sudo rules into code, so every new server starts with the same access list.

Related questions

  • Why is NOPASSWD: ALL a problem if we already use SSH keys?

    Because the SSH key is then the only thing between an attacker and root. A stolen laptop that is unlocked, an agent forwarded to a compromised server or a key copied from a backup all become root at once. A sudo password is a local second factor, and command-level rules limit the damage.

  • How do I let a developer deploy without giving them root?

    Through a deploy group with sudo rules for the exact commands they need: restarting the service, reading its logs and, if required, a deploy script with a fixed path and no free arguments. In CI, the same commands run under a dedicated account with its own key.

  • How often should I review accounts?

    Monthly on servers that hold personal data or carry NIS2 duties, quarterly on the rest, plus after every departure from the team. The review takes five minutes with the audit commands and catches forgotten accounts, extra keys and unjustified members of the sudo group.

Request a security review

A production server starts getting attacked within minutes of receiving a public IP address, however small the project is. This guide ranks the controls by impact, from SSH access to incident response, with the Romanian rules that apply along the way. Every topic has its own page with a short answer, examples and ready-to-use configuration.