How to Run Tomcat on Port 80 as Non-Root User in AWS Ubuntu Instance


2 views

When attempting to bind Tomcat to port 80 on Ubuntu, you'll encounter the classic error:

java.net.BindException: Permission denied <null>:80

This occurs because ports below 1024 are privileged ports in Linux, requiring root access. Your security-conscious instinct is correct - running Tomcat as root is dangerous.

1. Authbind Method (Recommended)

Authbind allows specific users to bind to privileged ports:

sudo apt-get install authbind
sudo touch /etc/authbind/byport/80
sudo chmod 500 /etc/authbind/byport/80
sudo chown tomcat7 /etc/authbind/byport/80

Then modify your Tomcat startup script (usually in /etc/default/tomcat7):

AUTHBIND=yes

2. IPTables Port Forwarding

Redirect traffic from port 80 to your Tomcat port (8080):

sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables-save > /etc/iptables.rules

Make it persistent across reboots by adding to /etc/network/interfaces:

pre-up iptables-restore < /etc/iptables.rules

3. Systemd Socket Activation

For Ubuntu 16.04+ with systemd:

# Create /etc/systemd/system/tomcat.socket
[Unit]
Description=Tomcat Socket
[Socket]
ListenStream=80
[Install]
WantedBy=sockets.target

Then create /etc/systemd/system/tomcat.service:

[Unit]
Requires=tomcat.socket
After=network.target

[Service]
User=tomcat
Group=tomcat
WorkingDirectory=/usr/share/tomcat
Environment=CATALINA_PID=/var/run/tomcat.pid
ExecStart=/usr/share/tomcat/bin/catalina.sh run

Remember to:

  1. Configure your Security Group to allow inbound traffic on port 80
  2. Verify no NACL is blocking the traffic
  3. Check that your instance has a public IP or Elastic IP

If it still doesn't work:

# Check listening ports
sudo netstat -tulpn | grep :80

# Verify AWS Security Groups
aws ec2 describe-security-groups --group-ids sg-xxxxxxxx

# Test connectivity
telnet your-ip 80

The authbind method is generally the cleanest solution that maintains security while solving the port binding issue.


The key error in your Catalina.out reveals everything:

java.net.BindException: Permission denied <null>:80
at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:391)

This occurs because ports below 1024 are privileged ports in Linux, requiring root access. Your Tomcat instance (running as non-root user) cannot bind to port 80 directly.

Authbind allows specific users/programs to bind to low-numbered ports:

# Install authbind
sudo apt-get install authbind

# Configure for port 80
sudo touch /etc/authbind/byport/80
sudo chmod 500 /etc/authbind/byport/80
sudo chown tomcat7 /etc/authbind/byport/80  # Replace with your Tomcat user

# Modify Tomcat startup script
sudo nano /etc/default/tomcat7

Add this line at the end:

AUTHBIND=yes

Redirect traffic from port 80 to 8080:

sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables-save | sudo tee /etc/iptables.rules

Make it persistent after reboot by adding to /etc/rc.local:

iptables-restore < /etc/iptables.rules

Create a new systemd socket file:

sudo nano /etc/systemd/system/tomcat80.socket

With this content:

[Unit]
Description=Tomcat Socket for Port 80

[Socket]
ListenStream=80
BindIPv6Only=both
Accept=yes

[Install]
WantedBy=sockets.target

Then create a service file:

sudo nano /etc/systemd/system/tomcat80@.service

With this content:

[Unit]
Description=Tomcat on Port 80

[Service]
Type=simple
ExecStart=/usr/share/tomcat8/bin/catalina.sh run
User=tomcat8
Group=tomcat8

After implementing any solution, verify with:

sudo netstat -tulnp | grep 80
curl -I http://localhost

Never run Tomcat as root. Instead:

  • Use authbind for temporary solutions
  • Implement proper firewall rules
  • Consider using a reverse proxy (Nginx/Apache)

For production environments, I recommend combining authbind with proper SELinux/AppArmor configurations.