When setting up production servers, it's crucial to follow security best practices by creating dedicated users for each service. This isolation prevents privilege escalation attacks where a compromised service could access other system components.
For Debian-based systems (including Squeeze), the standard method involves:
sudo adduser --system --group --no-create-home --shell /usr/sbin/nologin tomcat
sudo adduser --system --group --no-create-home --shell /usr/sbin/nologin nginx
sudo adduser --system --group --no-create-home --shell /usr/sbin/nologin postgres
Beyond basic user creation, implement these restrictions:
# Set immutable home directory (even if not used)
sudo chattr +i /nonexistent
# Restrict service capabilities
sudo setcap -r /usr/lib/postgresql/11/bin/* 2>/dev/null
# Create individual apparmor profiles for each service
sudo aa-genprof /usr/sbin/tomcat
For maximum security, consider these directory structures:
# Nginx example
sudo mkdir -p /srv/nginx/{logs,temp,conf}
sudo chown -R nginx:nginx /srv/nginx
sudo chmod 750 /srv/nginx
Check your setup with these commands:
# Verify shell restriction
getent passwd tomcat | cut -d: -f7
# Check process ownership
ps aux | grep -E 'tomcat|nginx|postgres'
If services fail to start:
# Check for permission errors
sudo -u tomcat /path/to/tomcat/bin/startup.sh
# Verify directory ownership
namei -l /var/lib/tomcat/webapps
For modern Debian systems using systemd:
[Service]
User=tomcat
Group=tomcat
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
When deploying critical services like Tomcat, Nginx, and PostgreSQL on Debian, creating dedicated system users is a fundamental security practice. These accounts should have:
- No interactive shell access
- Minimal filesystem permissions
- Ownership of only necessary resources
The most secure approach combines useradd
with proper shell restrictions:
# First, ensure nologin is a valid shell
if ! grep -q "/usr/sbin/nologin" /etc/shells; then
echo "/usr/sbin/nologin" >> /etc/shells
fi
# Create user with locked down permissions
sudo useradd -r -s /usr/sbin/nologin -d /nonexistent -M tomcat
sudo useradd -r -s /usr/sbin/nologin -d /nonexistent -M nginx
sudo useradd -r -s /usr/sbin/nologin -d /nonexistent -M postgres
Key parameters explained:
-r
: Creates a system account-s /usr/sbin/nologin
: Prevents shell access-d /nonexistent
: No home directory-M
: Don't create home directory
For additional security, implement filesystem restrictions:
# Create secure directories with proper ownership
sudo mkdir -p /var/lib/tomcat
sudo chown tomcat:tomcat /var/lib/tomcat
sudo chmod 750 /var/lib/tomcat
# Set up apparmor profiles for service isolation
sudo apt-get install apparmor apparmor-utils
sudo aa-genprof tomcat
For Nginx:
sudo useradd -r -s /usr/sbin/nologin -d /var/lib/nginx -M nginx
sudo mkdir -p /var/lib/nginx/tmp
sudo chown -R nginx:nginx /var/lib/nginx
sudo chmod -R 750 /var/lib/nginx
For PostgreSQL:
sudo useradd -r -s /bin/bash -d /var/lib/postgresql -M postgres
sudo mkdir -p /var/lib/postgresql/data
sudo chown -R postgres:postgres /var/lib/postgresql
sudo chmod -R 700 /var/lib/postgresql
Check your configuration with:
# Verify shell access is blocked
sudo -u tomcat /usr/sbin/nologin
# Check account details
grep 'tomcat\|nginx\|postgres' /etc/passwd
# Verify directory permissions
ls -ld /var/lib/tomcat
ls -la /var/lib/tomcat
For reproducible deployments, use Ansible:
- name: Create secure service accounts
user:
name: "{{ item }}"
shell: /usr/sbin/nologin
home: /nonexistent
create_home: no
system: yes
loop:
- tomcat
- nginx
- supervisor
If services fail to start:
- Check
/var/log/syslog
for permission errors - Verify proper SELinux/AppArmor contexts
- Ensure required directories exist with correct ownership