How to fix file permission errors on Linux when running a MU Online server
Diagnose and fix Linux file permission errors (EACCES, Permission denied, failed log writes, or socket errors) on MU Online servers running under Wine, Docker, or bare metal.
Every MU Online server administrator who migrates from Windows to Linux — whether to host on a cheaper VPS or to run the GameServer via Wine inside a Docker container — runs into a file permission error sooner or later. The message might be a plain Permission denied, an EACCES in the MySQL log, a si
Every MU Online server administrator who migrates from Windows to Linux — whether to host on a cheaper VPS or to run the GameServer via Wine inside a Docker container — runs into a file permission error sooner or later. The message might be a plain Permission denied, an EACCES in the MySQL log, a silent failure writing to Data/Log/, or the process simply not starting with no clear explanation. Unlike Windows, Linux enforces permissions with a much stricter owner/group/other model, and a misconfiguration here can block the entire server's boot or, worse, leave sensitive files too exposed. This tutorial covers step-by-step diagnosis, the most common causes in MU Online environments (Wine, Docker, systemd), and how to fix them without resorting to dangerous shortcuts like chmod 777.
How Linux decides who can access what
Every file and directory on Linux has three permission sets — owner, group, and others — and three access types — read (r), write (w), and execute (x). A typical MU Online server runs under a dedicated user (e.g., muserver), and all game files (Data/, Log/, Config/) need to belong to that user or a group it's part of. When the process tries to open, create, or write to a file outside that permission scope, the kernel returns EACCES (Permission denied) before the server binary even runs any logic — which is why the error usually shows up in the first seconds of boot or on the first attempt to write a log.
Common symptoms on MU Online servers
| Observed symptom | Where it appears | Typical cause |
|---|---|---|
| GameServer closes on startup with no clear message | Terminal / systemd journal | No write permission on Data/Log/ |
| MySQL doesn't connect to the local socket | DBAgent/JoinServer log | Permission on the /var/run/mysqld/mysqld.sock socket |
EACCES error saving a character | GameServer log | Save directory belongs to another user |
| Wine hangs opening the executable | Wine console | .wine prefix with wrong owner/group |
| Container restarts in a loop | docker logs | Volume mounted with a UID different from the process user |
Diagnosis: essential commands
Before any fix, gather information. The three commands below solve 90% of diagnostic cases:
# Who owns the file/directory and what are the current permissions
ls -la /home/muserver/MuServer/Data/Log/
# Which user/group is running the server process
ps -eo user,group,cmd | grep -i gameserver
# Which user systemd (if used) runs the service as
systemctl show muserver.service -p User -p Group
Compare the file owner (first column of ls -la) with the user returned by ps or systemctl show. If they differ, you've already found the root cause in most cases.
Fixing owner and group (chown)
Once you've identified the correct user, adjust ownership of the entire server tree:
sudo chown -R muserver:muserver /home/muserver/MuServer/
This makes sure the muserver user owns every file and directory recursively. If the server also needs another service (e.g., a web panel) to read the files, create a shared group instead of changing ownership to the secondary service:
sudo groupadd mu-shared
sudo usermod -aG mu-shared muserver
sudo usermod -aG mu-shared www-data
sudo chgrp -R mu-shared /home/muserver/MuServer/Data/
sudo chmod -R 2770 /home/muserver/MuServer/Data/
The 2770 sets the setgid bit on the directory (the leading 2), ensuring new files created inside it automatically inherit the mu-shared group.
Adjusting permissions (chmod) without overdoing it
Avoid 777. Use the table below as a reference for safe, working permissions for the most common MU Online server folders:
| Directory/file | Recommended permission | Reason |
|---|---|---|
Data/Log/ | 750 (rwxr-x---) | Only the owner writes; group reads for monitoring |
Data/Save/ (characters) | 700 | Sensitive data, only the server process accesses it |
Config/*.ini | 640 | Read access for the group (e.g., admin panel), no execution |
| Server executables | 750 | Execution restricted to owner and group |
Backup scripts (.sh) | 750 | Controlled execution, no access for others |
Apply with explicit chmod per file type, never uniformly recursive:
find /home/muserver/MuServer/Data -type d -exec chmod 750 {} \;
find /home/muserver/MuServer/Data -type f -exec chmod 640 {} \;
Permissions inside Wine
When the GameServer runs via Wine (common for Windows builds ported to Linux), the ~/.wine prefix needs to belong to the same user running Wine — never run wine as root in a prefix created by another user. Check with:
ls -ld ~/.wine
whoami
If the prefix was accidentally created with sudo wine ..., the safest path is to recreate it from scratch with the correct user, rather than trying to fix permissions inside an entire emulated Windows registry tree:
rm -rf ~/.wine
WINEARCH=win32 winecfg
Permissions in Docker containers
The most common Docker error is UID mapping: the volume on the host belongs to UID 1000, but the process inside the container runs as UID 1001 (or root, UID 0), and the two don't match even if the usernames look the same. Fix it in one of two ways:
- Pinning the container's UID to match the host, in the Dockerfile:
ARG UID=1000
RUN useradd -m -u ${UID} muserver
USER muserver
- Adjusting the volume's owner on the host before bringing the container up:
sudo chown -R 1000:1000 /srv/muserver/data
docker compose up -d
Prefer the first option in production — it's reproducible and doesn't rely on remembering to run chown every time the volume is recreated.
SELinux and AppArmor: when chmod isn't enough
On distributions like CentOS, RHEL, Rocky Linux, and Fedora, SELinux can block access even with correct Unix permissions. The classic symptom is ls -l showing everything fine while the process still gets Permission denied. Check the state and the log:
getenforce
sudo ausearch -m avc -ts recent
If there are denials related to your process, adjust the file's context instead of disabling SELinux globally (which reduces the security of the entire server):
sudo semanage fcontext -a -t bin_t "/home/muserver/MuServer/GameServer(/.*)?"
sudo restorecon -Rv /home/muserver/MuServer/GameServer
On Ubuntu/Debian, the equivalent is AppArmor; check active profiles with sudo aa-status and adjust the corresponding profile if needed.
Immutable attributes and read-only mounts
Two rare cases that still confuse administrators: the immutable attribute (chattr +i) and read-only mounts. Check both before spending more time repeatedly reviewing chmod/chown:
lsattr /home/muserver/MuServer/Data/Log/mu.log
mount | grep /home
If the i attribute shows up, remove it with sudo chattr -i file. If the mount is ro (read-only) in /etc/fstab or on a network mount point (NFS), the problem isn't Unix permissions — it's a mount option, and it needs to be remounted with rw.
Best practices to prevent recurrence
Once you've fixed the immediate problem, harden the environment against recurrence: centralize the entire server install under a single dedicated service user (never run the GameServer with your personal account), document expected permissions in a versioned setup script, and use systemd with explicit User= and Group= instead of relying on whoever ran the command manually from the terminal. A deploy script that applies chown/chmod as part of the pipeline prevents the next server update from breaking permissions again.
[Service]
User=muserver
Group=muserver
WorkingDirectory=/home/muserver/MuServer
ExecStart=/home/muserver/MuServer/GameServer
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
Permission denied writing to log | Directory doesn't belong to the process user | chown -R to the correct user |
| Container restarts in a loop from a write error | Host UID differs from container UID | Pin the UID in the Dockerfile or adjust volume owner |
ls -l looks correct but the process still fails | SELinux/AppArmor blocking | Adjust context/profile, don't disable globally |
| Wine hangs opening the server | .wine prefix created by another user | Recreate the prefix with the correct user |
| File can't be modified even with correct permissions | Immutable attribute (chattr +i) | Remove with chattr -i |
| Write fails even though everything looks right | read-only mount | Remount with rw in /etc/fstab |
Permission fix checklist
- I identified the actual user/group running the server process.
- I compared it against the current file owner via
ls -la. - I applied
chown -Rto the correct user/group. - I adjusted
chmodper file type, avoiding777. - I checked SELinux/AppArmor if running RHEL/CentOS/Ubuntu with an active module.
- I checked immutable attributes (
lsattr) and mounts (mount). - I configured
systemdwith explicitUser=/Group=to prevent recurrence. - I tested restarting the service from scratch to confirm the error doesn't come back.
With permissions fixed and the service stable, the natural next step is to review your entire Linux deploy structure so future updates don't reintroduce the same problem — check out the server setup tutorial to review the full configuration from scratch.
Frequently asked questions
Why does my GameServer run as root but I still get Permission denied?
Running as root avoids most filesystem permission errors, but it doesn't fix restrictive ACLs, immutable attributes (chattr +i), read-only mounts, or containers where the mapped user differs from the host. Check these before assuming root solves everything.
Do I need to run chmod 777 to fix it once and for all?
No. 777 is a dangerous shortcut that opens the entire directory to read, write, and execute for any user on the system, including compromised processes. Prefer 750 or 770 with the correct owner and group — it solves the same problem without exposing the server.
The error only happens inside Docker, but it works fine on the host. Why?
This is usually a UID/GID mapping mismatch between the host and the container. If the volume was created by user 1000 on the host but the process inside the container runs as UID 1001, the container won't have permission even if the host shows the file as accessible.
How do I know if the problem is Unix permissions or SELinux/AppArmor?
Run the test command (e.g., try opening the file with the same user the service runs as) and check the corresponding log. If ls -l and id show matching permissions but the process still fails, check getenforce, audit.log, or dmesg for SELinux/AppArmor denials before touching chmod again.
Does running MuServer via Wine change anything about permissions?
Yes. Wine creates its own prefix (~/.wine) and maps Windows paths to real Linux directories. If the prefix belongs to a different user or has wrong permissions, the server 'runs' but silently fails to write logs, the local DB, or temp files inside the prefix.