Permission denied error when binding a port
Platform notice: Server and Data Center only. This article only applies to Atlassian products on the Server and Data Center platforms.
Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
Problem
You're trying to bind a port in a Linux environment and are receiving a "Permission denied" error. Typically this is either port 80 or 443.
The following appears in the catalina.out
Jun 7, 2012 4:58:57 PM org.apache.coyote.http11.Http11Protocol init
SEVERE: Error initializing endpoint
java.net.BindException: Permission denied <null>:80
at org.apache.tomcat.util.net.JIoEndpoint.init(JIoEndpoint.java:549)
at org.apache.coyote.http11.Http11Protocol.init(Http11Protocol.java:176)
at org.apache.catalina.connector.Connector.initialize(Connector.java:1022)
at org.apache.catalina.core.StandardService.initialize(StandardService.java:703)
at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:838)
at org.apache.catalina.startup.Catalina.load(Catalina.java:538)
at org.apache.catalina.startup.Catalina.load(Catalina.java:562)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:261)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: java.net.BindException: Permission denied
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:383)
at java.net.ServerSocket.bind(ServerSocket.java:328)
at java.net.ServerSocket.<init>(ServerSocket.java:194)
at java.net.ServerSocket.<init>(ServerSocket.java:150)
at org.apache.tomcat.util.net.DefaultServerSocketFactory.createSocket(DefaultServerSocketFactory.java:50)
at org.apache.tomcat.util.net.JIoEndpoint.init(JIoEndpoint.java:538)
... 12 more
Jun 7, 2012 4:58:57 PM org.apache.catalina.core.StandardService initialize
SEVERE: Failed to initialize connector [Connector[HTTP/1.1-80]]
LifecycleException: Protocol handler initialization failed: java.net.BindException: Permission denied <null>:80
at org.apache.catalina.connector.Connector.initialize(Connector.java:1024)
at org.apache.catalina.core.StandardService.initialize(StandardService.java:703)
at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:838)
at org.apache.catalina.startup.Catalina.load(Catalina.java:538)
at org.apache.catalina.startup.Catalina.load(Catalina.java:562)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:261)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Cause
Ports below 1024 are called Privileged Ports and in Linux (and most UNIX flavors and UNIX-like systems), they are not allowed to be opened by any non-root user. This is a security feature originally implemented as a way to prevent a malicious user from setting up a malicious service on a well-known service port.
Resolution
There are a few different solutions to work around this:
- Install and configure Apache or nginx as a reverse proxy server, which can be started as root to open the port, and then downgrade its privileges back to a normal user.
- Set up a firewall on the server using
iptables
or an alternative, so that the lower port number is forwarded internally to a higher port number listened by Confluence. - Use jsvc, which is able to open ports as root, and then downgrade privileges.
- Use authbind to grant privileges for a non-root user to open a privileged port.
If using Linux 2.6.24 or later, you can set up a file capability on the java executable, to give elevated privileges to allow opening privileged ports only, and no other superuser privileges:
# setcap cap_net_bind_service+ep /path/to/bin/java
After setting this you may notice errors when starting Java like this, for example:
$ java -version /path/to/bin/java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
This means that the library is being imported from a dynamic path, and not in the trusted ld.so path. See http://bugs.sun.com/view_bug.do?bug_id=7157699 for details. To fix this, you need to locate the library, and add its path to the ld.so configuration. Note that the below is an example, and this may differ depending on Linux distribution. Replace JAVA_HOME with the correct location:
$ find JAVA_HOME -name 'libjli.so' JAVA_HOME/lib/amd64/jli/libjli.so # echo "JAVA_HOME/lib/amd64/jli" > /etc/ld.so.conf.d/java-libjli.conf # ldconfig -v
After setting this all up, you need to make sure that Confluence only starts java with the direct binary path, and not via a symbolic link, otherwise the capability will not be picked up.
Setting this up means that any user can open privileged ports using Java, which may or may not be acceptable for you
Whilst it may get things working, it is not recommended to run Confluence as root. If there is ever any security vulnerability where an attacker may execute arbitrary code as the running user, then they will gain root access.