PwrSrg
06/04/2024, 4:06 PMInvalid file: Read-only file system
error. My initial reaction is it was an obvious permissions issue, and every thread I have found on the subject emphatically insist the same thing - "It is a permissions issue, NOT a Lucee issue". But after 3 days of exhaustive testing, including a full-day ChatGPT step-by-step elimination process, everything points to Lucee.
I first checked the web folder permissions: 0775 root:www-data
Then the www-data group members: www-data:x:33:tomcat,ftpuser,ubuntu,daemon
That all seemed correct to me, so I created the following TEST script to see if it could write to the Lucee TEMP directory or not:
<!--- Lucee TEMP directory - WORKS --->
<cffile action="write" file="#getTempDirectory()#write-test.txt" output="Testing">
<!--- Relative directory - ERROR --->
<cffile action="write" file="write-test.txt" output="Testing">
The test script was able to successfully write to the Lucy temp directory, but still failed writing to the script directory with the same error, which suggests a permissions issue as originally anticipated.
Here is the Lucee error output in the browser:
Lucee 6.0.1.83 Error (application)
Message Invalid file [/web/litgate.dev/wwwroot/writetest/write-test.txt]
Detail /web/litgate.dev/wwwroot/writetest/write-test.txt: Read-only file system
Stacktrace The Error Occurred in
/web/litgate.dev/wwwroot/writetest/index.cfm: line 6
4:
5: <!--- Relative directory - ERROR --->
6: <cffile action="write" file="write-test.txt" output="Testing">
7:
8:
Java Stacktrace lucee.runtime.exp.ApplicationException: Invalid file [/web/litgate.dev/wwwroot/writetest/write-test.txt]
at lucee.runtime.tag.FileTag.checkFile(FileTag.java:1230)
at lucee.runtime.tag.FileTag.actionWrite(FileTag.java:726)
at lucee.runtime.tag.FileTag.doEndTag(FileTag.java:480)
at writetest.index_cfm$cf.call(/writetest/index.cfm:6)
at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:1028)
at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:951)
at lucee.runtime.listener.ClassicAppListener._onRequest(ClassicAppListener.java:65)
at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:45)
at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2715)
at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2701)
at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2672)
at lucee.runtime.engine.Request.exe(Request.java:45)
at lucee.runtime.engine.CFMLEngineImpl._service(CFMLEngineImpl.java:1259)
at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:1205)
at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:97)
at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:769)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:359)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1735)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:829)
Timestamp 6/4/24 9:09:39 AM CDT
And this is what is logged to exception.log (/opt/lucee/config/server/lucee-server/context/logs):
"ERROR","http-nio-8080-exec-3","06/04/2024","14:09:39","","Invalid file [/web/litgate.dev/wwwroot/writetest/write-test.txt];Invalid file [/web/litgate.dev/wwwroot/writetest/write-test.txt]
/web/litgate.dev/wwwroot/writetest/write-test.txt: Read-only file system;lucee.runtime.exp.ApplicationException: Invalid file [/web/litgate.dev/wwwroot/writetest/write-test.txt]
at lucee.runtime.tag.FileTag.checkFile(FileTag.java:1230)
at lucee.runtime.tag.FileTag.actionWrite(FileTag.java:726)
at lucee.runtime.tag.FileTag.doEndTag(FileTag.java:480)
at writetest.index_cfm$cf.call(/writetest/index.cfm:6)
at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:1028)
at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:951)
at lucee.runtime.listener.ClassicAppListener._onRequest(ClassicAppListener.java:65)
at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:45)
at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2715)
at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2701)
at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2672)
at lucee.runtime.engine.Request.exe(Request.java:45)
at lucee.runtime.engine.CFMLEngineImpl._service(CFMLEngineImpl.java:1259)
at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:1205)
at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:97)
at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:51)
..."
I checked the Lucee temp folder permissions:
sudo ls -la /opt/lucee/config/server/lucee-server/context/temp
total 16
drwxr-x--- 3 tomcat tomcat 4096 Jun 4 14:08 .
drwxr-x--- 20 tomcat tomcat 4096 Jun 4 13:30 ..
drwxr-x--- 4 tomcat tomcat 4096 Jun 4 13:30 compress
-rw-r----- 1 tomcat tomcat 8 Jun 4 14:09 write-test.txt
Then updated the test script's Owner:Group to match (tomcat:tomcat) and enabled ALL permissions just in case:
sudo chown -R tomcat:tomcat /web/litgate.dev/wwwroot/writetest
sudo chmod -R 777 /web/litgate.dev/wwwroot/writetest
sudo service nginx restart
After restarting Lucee and hitting the test script, I STILL get the same error. I even rebooted the entire LightSail server but still no luck.
During my ChatGPT session, one of its tests was to "determine if it is a local user/permissions issue, or a Lucee issue" by switching to the tomcat user and attempting to write a file to the same folder via the terminal which WORKED:
sudo touch /web/litgate.dev/wwwroot/writetest/test_output.txt
This is what now leads me to believe that it may in fact be a Lucee issue, and not a permissions issue.
WHY can the tomcat user successfully write to the folder, but Lucee running as the tomcat user CAN'T? Is there some crazy setting hidden somewhere inside of Lucee that is restricting all write permissions to ONLY the TEMP folder? I am now on my 4th day with this, and have completely run out of ideas. I have set up numerous Lucee servers in the past, and have never run into this before, though this is my first attempt FROM SCRATCH on an FRESH Ubuntu/Nginx server.
ANY help would be greatly appreciated!
The TEST script is LIVE here - https://dev.litgate.com/writetest
THANKS!!Rodney
06/04/2024, 4:16 PMquetwo
06/04/2024, 7:15 PMPwrSrg
06/04/2024, 8:52 PMsudo sestatus
to see if SELinux was enabled, but got command not found
. So I listed all installed packages and SELinux was not among them, so I don't think that is the case.
@Rodney - I have a bad feeling this is the issue. Unfortunately that thread is way over my head, as they are mostly discussing Docker containers which as far as I know I am not using. I may end up having to completely redeploy a new server using Apache instead. 😓
I honestly can't believe how difficult it is getting a simple Lucee server running on Linux. I figured it would just like every other piece of Linux software - sudo apt install lucee
, but ended up spending over 2 days getting one up and running, and it can't even write to the disk.quetwo
06/04/2024, 8:56 PMaa-status
that should tell you if you are running itPwrSrg
06/04/2024, 8:57 PMapparmor module is loaded.
35 profiles are loaded.
33 profiles are in enforce mode.
/snap/snapd/21465/usr/lib/snapd/snap-confine
/snap/snapd/21465/usr/lib/snapd/snap-confine//mount-namespace-capture-helper
/snap/snapd/21759/usr/lib/snapd/snap-confine
/snap/snapd/21759/usr/lib/snapd/snap-confine//mount-namespace-capture-helper
/usr/bin/man
/usr/lib/NetworkManager/nm-dhcp-client.action
/usr/lib/NetworkManager/nm-dhcp-helper
/usr/lib/connman/scripts/dhclient-script
/usr/lib/snapd/snap-confine
/usr/lib/snapd/snap-confine//mount-namespace-capture-helper
/usr/sbin/chronyd
/{,usr/}sbin/dhclient
lsb_release
man_filter
man_groff
nvidia_modprobe
nvidia_modprobe//kmod
snap-update-ns.amazon-ssm-agent
snap-update-ns.lxd
snap.lxd.activate
snap.lxd.benchmark
snap.lxd.buginfo
snap.lxd.check-kernel
snap.lxd.daemon
snap.lxd.hook.configure
snap.lxd.hook.install
snap.lxd.hook.remove
snap.lxd.lxc
snap.lxd.lxc-to-lxd
snap.lxd.lxd
snap.lxd.migrate
snap.lxd.user-daemon
tcpdump
2 profiles are in complain mode.
snap.amazon-ssm-agent.amazon-ssm-agent
snap.amazon-ssm-agent.ssm-cli
0 profiles are in kill mode.
0 profiles are in unconfined mode.
3 processes have profiles defined.
2 processes are in enforce mode.
/usr/sbin/chronyd (472)
/usr/sbin/chronyd (484)
1 processes are in complain mode.
/snap/amazon-ssm-agent/7993/amazon-ssm-agent (402) snap.amazon-ssm-agent.amazon-ssm-agent
0 processes are unconfined but have a profile defined.
0 processes are in mixed mode.
0 processes are in kill mode.
quetwo
06/04/2024, 8:58 PMPwrSrg
06/04/2024, 8:59 PMquetwo
06/04/2024, 9:00 PMPwrSrg
06/04/2024, 9:00 PMquetwo
06/04/2024, 9:01 PMquetwo
06/04/2024, 9:02 PMPwrSrg
06/04/2024, 9:02 PMquetwo
06/04/2024, 9:02 PMPwrSrg
06/05/2024, 1:11 PMsudo systemctl disable apparmor.service
) and stopping it didn't work (sudo systemctl stop apparmor.service
). Then I found a command to completely remove all profiles (sudo aa-teardown
), and that didn't work. When I run sudo aa-status
now all it returns is apparmor module is loaded
, but I still get the same error. I had also restarted both Nginx (sudo service nginx restart
) and Lucee (sudo service tomcat9 restart
). When I reboot the server all AppArmor profiles are running again.Evil Ware
06/05/2024, 2:05 PMEvil Ware
06/05/2024, 2:15 PMPwrSrg
06/05/2024, 2:21 PMsudo systemctl disable apparmor
) didn't work, nor did completely tearing down all AppArmor profiles (sudo aa-teardown
). sudo setenforce 0
returns sudo: setenforce: command not found
. /etc/selinux/config
doesn't exist, but /etc/selinux/semanage.conf
does. Actually, semanage.conf
is the only file in the /etc/selinux
directory. Here is it's contents:
# Authors: Jason Tang <jtang@tresys.com>
#
# Copyright (C) 2004-2005 Tresys Technology, LLC
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# Specify how libsemanage will interact with a SELinux policy manager.
# The four options are:
#
# "source" - libsemanage manipulates a source SELinux policy
# "direct" - libsemanage will write directly to a module store.
# /foo/bar - Write by way of a policy management server, whose
# named socket is at /foo/bar. The path must begin
# with a '/'.
# <http://foo.com:4242|foo.com:4242> - Establish a TCP connection to a remote policy
# management server at <http://foo.com|foo.com>. If there is a colon
# then the remainder is interpreted as a port number;
# otherwise default to port 4242.
module-store = direct
# When generating the final linked and expanded policy, by default
# semanage will set the policy version to POLICYDB_VERSION_MAX, as
# given in <sepol/policydb.h>. Change this setting if a different
# version is necessary.
#policy-version = 19
# expand-check check neverallow rules when executing all semanage commands.
# Large penalty in time if you turn this on.
expand-check=0
# By default, semanage will generate policies for the SELinux target.
# To build policies for Xen, uncomment the following line.
#target-platform = xen
Evil Ware
06/05/2024, 2:28 PMEvil Ware
06/05/2024, 2:29 PMEvil Ware
06/05/2024, 2:31 PMPwrSrg
06/05/2024, 3:51 PMPwrSrg
06/05/2024, 5:22 PMReadWritePaths
to be defined. So I had to add ReadWritePaths=/web/
to /etc/systemd/system/tomcat9.service.d/lucee.conf
. Once I did that and rebooted the server, everything WORKS as expected. What a nightmare!Evil Ware
06/06/2024, 2:01 PM