Skip to content

Linux Administration: Why You Should Avoid Root for Deployments and Use Deployer Instead

Why You Should Avoid Using Root for Deployments

In many server deployments, it’s tempting to SSH as root because you avoid permission issues. But directly using root poses serious security and operational risks:

  • Root has full power: If your SSH key or password leaks, an attacker can do anything.
  • No accountability: With multiple people or CI/CD systems using the same root account, it’s impossible to track actions.
  • Easy to break the system: Small mistakes (like a mistyped command) can break everything instantly.
  • Bypasses best practices: Security principles recommend the least privilege possible for each task.

Why Use a Dedicated Deployer User Instead?

Using a dedicated deployer user minimizes these risks:

Limited scope:
Deployer only has the minimal permissions needed for deployments. If compromised, it can’t destroy your entire system.

Use sudo for root-level actions:
deployer can still restart services or copy to protected directories using sudo, but only when needed.

Logs and auditing:
sudo logs every privileged command, so you know who did what.

Easier to revoke:
If someone leaves the team, you only remove their deployer access—not full root access.


🛠️ Setting Up a Deployer User with Root Privileges

Let’s assume you’re logged in as root:

Create the deployer user:

bash
adduser deployer

Add deployer to the sudo group:

bash
usermod -aG sudo deployer

Allow passwordless sudo for seamless deployments (edit with visudo):

bash
visudo

Add this line:

deployer ALL=(ALL) NOPASSWD:ALL

Now deployer can run any sudo command without a password.


🔐 Configure SSH Access

On your local machine, generate an SSH key if needed:

bash
ssh-keygen -t ed25519 -C "deployer key"

Copy your public key to the server:

bash
ssh-copy-id deployer@your.server.ip

or manually add it to:

bash
/home/deployer/.ssh/authorized_keys

Using deployer Like Root

Now, instead of SSHing as root:

bash
ssh root@server

You connect as deployer:

bash
ssh deployer@server

For privileged commands (like installing packages or restarting services):

bash
sudo apt update
sudo systemctl reload nginx

No password needed because of the NOPASSWD config.


Example: Transition from Root-based to Deployer-based Deployment

Here’s a sample CI/CD script for root:

bash
ssh root@server <<'EOF'
  cd /var/www/myapp
  git pull origin main
  npm ci
  npm run build
  systemctl reload nginx
EOF

Updated script for deployer:

bash
ssh deployer@server <<'EOF'
  cd ~/myapp
  git pull origin main
  npm ci
  npm run build
  sudo cp -r build/* /var/www/myapp/
  sudo systemctl reload nginx
EOF

Key Points in the Updated Flow:

SSH as deployer, not root.
Use sudo only for tasks that truly require it (like copying to /var/www or reloading nginx).
All logs show deployer as the actor, improving auditability.


Final Thoughts

Security: Using deployer limits potential damage if credentials leak.
Best practice: Principle of Least Privilege—use the smallest set of permissions needed.
Scalable: Works smoothly with CI/CD tools like GitHub Actions, Jenkins, or GitLab CI.


Sample SSH Deployment Flow in GitHub Actions

yaml
- name: Deploy to production
  uses: appleboy/ssh-action@v1.0.0
  with:
    host: ${{ secrets.VPS_IP }}
    username: deployer
    key: ${{ secrets.DEPLOYER_SSH_KEY }}
    script: |
      cd ~/myapp
      git pull origin main
      npm ci
      npm run build
      sudo cp -r build/* /var/www/myapp/
      sudo systemctl reload nginx

Summary of Commands to Transition from Root to Deployer:

Create deployer:

bash
adduser deployer
usermod -aG sudo deployer

Allow passwordless sudo (visudo):

deployer ALL=(ALL) NOPASSWD:ALL

Copy your SSH key to deployer.

SSH as deployer, use sudo for privileged tasks only.


Done! You’re now following best practices for secure deployments.