The characters \ / : ? * " < > |
as well as leading and trailing spaces in file and directory names are generally problematic and cannot be used at all on some systems, e.g. the question mark on Windows.
For example, if a file with ?
in its name is created under Linux or in the Nextcloud GUI (provided that the forbidden_chars, which are only valid for the Nextcloud Web GUI, are not configured), the Nextcloud client under Windows will refuse to synchronize with the message File names containing the character "?" are not supported on this file system.
The solution is actually quite simple: rename the file in the Nextcloud GUI and replace or remove the special characters. Recently, however, the web GUI has always displayed a File not found error message when this action is performed. That's strange.
Is this a bug in Nextcloud or is it due to the environment where the request is passed through a chain of firewalls, WAFs and reverse proxies to the Nextcloud application server?
To keep it simple, we simulated the scenario in a local Docker container. We were very surprised when the renaming worked there - but it also made it clear where we needed to look.
First, we examined the Apache web server log files on the reverse proxy and the backend server. When renaming the file textfile ?.md
to textfile ??.md
in the web GUI, the browser first sends the URI /remote.php/dav/files/admin/text%20file%20%3F.md
(note the URL encoding). This arrives exactly the same at the reverse proxy.
However, the request to the Nextcloud application server had the form /remote.php/dav/files/admin/Text%20file%20?.md
. The question mark was not encoded. Therefore, Nextcloud cannot find the file and cannot rename it, which explains the error message in the web GUI.
On the Apache reverse proxy, we used RewriteRule
instead of ProxyPass
directives in the configuration of the Nextcloud vHost for flexibility. The last rule in our extensive RewriteRule
list was RewriteRule ^/(.*) http://nc.example.com/$1 [proxy,last]
.
Unlike ProxyPass
, however, RewriteRule
decodes the pattern ^/(.*)
, which is also described in the documentation: In the VirtualHost context, the pattern [...] is the (%-decoded) URL path. Since we match the entire URI in the directive and reference it via $1
, the http://nc.example.com/$1
substitution at the end is also decoded. This explains why the question mark was passed to Nextcloud unencoded.
We tested the following variations of RewriteRule and ProxyPass:
Directive | URI on Nextcloud Server | Rename successful? |
---|---|---|
RewriteRule ^/(.*) http://nc.example.com/$1 [proxy,last] |
/remote.php/dav/files/admin/Text%20file%20?.md |
no |
RewriteRule "^/(.*)" "http://nc.example.com/$1" [proxy,last,B=?] |
/remote.php/dav/files/admin/Text%20file%20%253f%253f%253f.md |
no |
RewriteMap escape int:escape RewriteRule ^/(.*) http://nc.example.com/${escape:$1} [proxy,last] |
/remote.php/dav/files/admin/New%2520text%2520file%2520%253f.md |
no |
RewriteMap escape int:escape RewriteRule "^/(.*)" "http://nc.example.com/${escape:$1}" [proxy,last,noescape] |
/remote.php/dav/files/admin/Text%20file%20%3f.md |
yes |
ProxyPass / http://nc.example.com/ |
/remote.php/dav/files/admin/Text%20file%20%3F.md |
yes |
ProxyPass / http://nc.example.com/ nocanon |
/remote.php/dav/files/admin/Text%20file%20%3F.md |
yes |
Although RewriteRules are much more flexible, we ultimately decided to use the ProxyPass directive because it is much easier to read. Of course, we are also happy to accept the slight performance advantage.
How can the creation of files and directories with problematic characters be prevented? To forbid this in the Nextcloud Web GUI, a list of forbidden_chars can be defined. However, in the current Nextcloud version 28 (as of 2024-03) there is no way to prevent a client from synchronizing such files. Nextcloud is working on a solution to this problem, which is expected to be available in Nextcloud 29 (see Issue 31663 and Issue 38614).
Until then: Configure the reverse proxy correctly 😉 and then rename files with problematic characters in the web GUI.