How to Execute Commands as a nologin User in Linux (suPHP/Rails Deployment Guide)


38 views

When hardening server security by assigning /usr/sbin/nologin shells to service accounts (like www-data for suPHP or Rails deployments), we encounter a common operational hurdle: how to execute commands as these users when interactive login is disabled. This is particularly crucial for deployment tasks like running Rails migrations or managing background workers.

Linux provides multiple robust solutions for this scenario:

# Basic syntax for running single commands
sudo -u www-data COMMAND

# For complex operations requiring shell features
sudo -u www-data /bin/sh -c 'command1 && command2'

For a Ruby on Rails application running under www-data, here's how to execute common tasks:

# Run database migrations
sudo -u www-data bundle exec rake db:migrate RAILS_ENV=production

# Execute Rails console
sudo -u www-data bundle exec rails console production

# Restart Passenger instances
sudo -u www-data touch tmp/restart.txt

When dealing with file permissions in multi-user environments:

# Set proper ownership for Rails apps
sudo chown -R www-data:www-data /var/www/myapp

# Verify permission inheritance
sudo -u www-data ls -la /var/www/myapp/tmp

To schedule tasks for restricted accounts:

# In root's crontab
0 3 * * * sudo -u www-data /bin/sh -c 'cd /var/www/myapp && bundle exec rake maintenance:daily'

When encountering environment or permission errors:

# Debug environment variables
sudo -u www-data printenv

# Test PATH resolution
sudo -u www-data which ruby
sudo -u www-data ruby -v

When you configure system users like www-data with /sbin/nologin as their shell (a common security practice for web server accounts), you encounter a new problem: how to execute commands as these users when maintenance tasks are required.

# Typical nologin setting in /etc/passwd
www-data:x:33:33:www-data:/var/www:/sbin/nologin

1. Using sudo with command specification

The most straightforward method is configuring sudo to allow specific commands:

# In /etc/sudoers or a new file in /etc/sudoers.d/
www-user ALL=(www-data) NOPASSWD: /usr/bin/rake

Then execute as:

sudo -u www-data rake assets:precompile

2. Direct command execution without shell

For one-off tasks, use this syntax that bypasses shell requirements:

su -s /bin/bash -c "rake db:migrate" www-data

3. SSH forced command (for remote execution)

When needing remote execution:

# In ~www-data/.ssh/authorized_keys
command="rake db:migrate" ssh-rsa AAAAB3NzaC1y...

For a complete Rails deployment scenario:

# Bundle install as www-data
sudo -u www-data -H bundle install --deployment --without development test

# Run migrations
sudo -u www-data -H bundle exec rake db:migrate RAILS_ENV=production

# Precompile assets
sudo -u www-data -H bundle exec rake assets:precompile RAILS_ENV=production
  • Always prefer sudo over su for better auditing
  • Limit sudo permissions to specific commands only
  • Consider creating wrapper scripts for complex operations
  • Use -H flag with sudo to set proper HOME environment

If you encounter environment issues:

# Debug environment variables
sudo -u www-data -H env

# Alternative with full login simulation
sudo -iu www-data env