Hi everyone, I copied the Seafile-data folder to a Windows machine as a backup, without the tar.gz file. I admit it was my mistake. As a result, after moving it back, the permissions for avatars, wallpapers, logos, and everything running on www-data (Nginx) were broken. If I recursively grant permissions to /shared inside the container, everything works again, but only until the container is restarted, of course, because scripts requiring root can’t run on startup.
I found that Nginx has a /media location and contains simlynks - avatars and custom, and www-data is getting “Permission denied” for them. Could you explain how the media read permissions are implemented?
Based on your description, the issue is caused by the way Windows handles file metadata. When you copied the folders directly to a Windows machine without using an archive format (like .tar.gz), you lost two critical pieces of information: Linux Ownership/Permissions (UID/GID) and Symbolic Links.
When you moved the files back, they likely inherited the permissions of the user who performed the copy, causing Nginx (running as www-data) to lose access.
Here are the points you should check to fix this permanently:
1. Fix Broken Symbolic Links
The Permission denied errors in the media folder are often because the symlinks for avatars and custom were converted into regular folders or corrupted during the Windows transfer.
- Check the
/opt/seafile/seafile-server-latest/seahub/mediadirectory. - Verify if
avatarsandcustomare actual symlinks pointing to your/shared/seafile/seahub-data/directory. - If they are regular folders, delete them and recreate the symlinks manually using
ln -s.
2. Correct Ownership (chown vs chmod)
Recursive chmod allows access, but if the ownership is wrong, certain Seafile operations or startup scripts may still fail. You need to ensure the files are owned by the user running the service inside the container.
- Run a recursive ownership change:
chown -R www-data:www-data /shared(Note: If you are using theNON_ROOTsetup, the owner should be the user with UID 8000).
3. Directory Traversal Permissions
Nginx needs the execute (+x) permission on every parent directory in the path to access a file.
- Ensure that
/shared,/shared/seafile, and/shared/seafile/seahub-dataall have at leastdrwxr-xr-xpermissions. If any parent directory is missing thexbit for the “others” or “group” category, Nginx will return a 403 or 404.
4. Why it breaks on restart
The Seafile container startup scripts often check the environment and may attempt to fix permissions or initialize components. If the underlying symlink structure is broken, the initialization might fail or reset permissions to a state that doesn’t account for your manual changes.
Tip for the future: Always wrap the seafile-data or shared folder in a .tar or .zip file before moving it to a Windows environment to preserve the Linux filesystem attributes.
Yes, that’s what I did initially, granting www-data -R permissions to /shared, and as I described above, it worked. Initially, the container ran as admin:administrator (it’s a QNAP NAS), and the container starts as admin:administrator. After changing admin:administrator permissions to www-data, there are two problems:
- Any action within the UI to change the logo, wallpaper, avatar, etc. creates an object within avatar\custom as admin:administrator, which immediately breaks the permissions for www-data.
- If I chown -R admin:administrator /shared, after rebooting the container, it crashes and won’t start.
after container restart I get
[2026-04-13 07:42:30] Skip running setup-seafile-mysql.py because there is existing seafile-data folder.
Error: the user running the script (“root”) is not the owner of “/shared/seafile/seafile-data” folder, you should use the user “www-data” to run the script.
Traceback (most recent call last):
File “/scripts/start.py”, line 91, in
main()
File “/scripts/start.py”, line 76, in main
call('{} start'.format(get_script('seafile.sh')))
File “/scripts/utils.py”, line 71, in call
return subprocess.check_call(\*a, \*\*kw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/lib/python3.12/subprocess.py”, line 413, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command ‘/opt/seafile/seafile-server-13.0.20/seafile.sh start’ returned non-zero exit status 255.
###################################################################
since above we changed the owner to www-data
But when I return the owner to admin:administrator, which is equivalent to root:root inside the container, everything starts working. I need to somehow specifically grant rights for ngixn www-data, and not the entire -R /shared

