30 May 2026

Why do control panels set Linux file permissions incorrectly?

When hosting panel compatibility trumps the principle of least privilege, even Linux permissions become a questionable compromise.

In the world of web hosting there is one of those “truths” repeated so many times that it has almost become dogma: directories must have permissions 755 and files must have permissions 644Guides, tutorials, control panels, general-purpose providers, support documentation, forums, and even some automatic permission restoration tools say so. The problem is that this rule, while convenient and often effective, isn't necessarily the right one from a security perspective.

The point isn't to argue that a site with 755 directories and 644 files is automatically compromised or absolutely insecure. That would be a trivial simplification, and in a certain sense, even false. The point is different: 755 and 644 are permissions designed to ensure universal compatibility, not to truly respect the principle of least privilege.And this is where the misunderstanding arises, or rather, the original sin of much of the commercial hosting based on control panels like cPanel, Plesk, and the like.

In a multi-user Linux system, the third permissions digit, the one referring to "others," meaning all other system users, should not be used as a shortcut to operate the web server. If the web server needs to read a website's files, then it should be able to do so because it belongs to the correct group, because the PHP process is running under the correct user, or because the service architecture has been thoughtfully designed. Not because we've decided to make the website readable by any local user on the system.

The real meaning of 755 and 644

Let's start from the basics. A permit 755 on a directory means:

rwxr-xr-x

The owner can read, write, and enter the directory. The group can read and enter. Everyone else can read and enter. On a directory, the execute bit doesn't mean "run a program," but traverse the directory, that is, being able to enter it, reach files and subdirectories and resolve the path.

linux-read-write-execute-permissions

A permit 644 on a file means:

rw-r--r--

The owner can read and write. The group can read. Everyone else can read. So, if a PHP file, configuration file, or text file has permissions of 644, any local user who isn't the owner and isn't a member of the group can still read it, as long as they have access to the parent path.

Here, many fall into the misconception that "you can't read the PHP source file via the web." True, if the web server is configured correctly. But Linux permissions govern more than just HTTP access. They also govern local access from shells, system processes, compromised scripts, poorly restricted users, cron jobs, backup tools, FTP or SFTP accounts, other sites hosted on the same machine, and any process that manages to run under a different local user.

Saying that 755 and 644 are “fine” often ignores the multi-user context in which those permissions are applied.

Why do panels still use 755 and 644?

The answer is uncomfortable but simple: because they almost always workControl panels are general-purpose products. They must support both old and new stacks, well-configured and poorly configured servers, Apache with mod_php, Apache with PHP-FPM, Nginx as a reverse proxy, LiteSpeed, LSAPI, suPHP, suexec, FastCGI, FTP users, web file managers, backups, restores, migrations, WordPress plugins, automated installers, old content management systems, poorly written scripts, and clients that upload files with dubious permissions.

cpanel permissions

In this scenario, 755 for directories and 644 for files is the easiest way to avoid support tickets. If the web process does not belong to the correct group, if Apache runs as nobody, if Nginx runs as nginx, if the PHP-FPM pool is not perfectly aligned with the site user, if the File Manager still needs to display and manipulate files, those permissions guarantee one thing: the site will probably remain responsive.

But that doesn't make them the best permits. It makes permissions more convenient for the panel vendor and the provider who wants to reduce compatibility issues. It's a huge difference.

When a panel automatically sets directories to 755 and files to 644, it's implicitly saying, "I'm not sure which user or group should read these files, so I'll allow others to read them too." It's a pragmatic choice. But from a systems perspective, it's a shortcut.

The principle of least privilege

The principle of least privilege dictates that each user, process, or service should have only the permissions strictly necessary to perform its function. Applied to website files, this means:

  • the user who owns the site must be able to read and write the files;
  • the PHP process must be able to read PHP files and possibly write only to the designated directories;
  • the web server must be able to read the static assets it needs to serve directly;
  • other users of the system should not be able to read anything;
  • Sensitive files should not be readable by unnecessary processes.

If we take this principle seriously, the 755/644 pair immediately appears too large. The most coherent configuration instead becomes:

Directory: 750
File:      640

Or, in some even more restrictive cases:

Directory: 750 o 700
File:      640 o 600

For particularly sensitive files such as wp-config.php, .env, configuration.php of Joomla or app/etc/env.php For Magento, it may make sense to go further, depending on how PHP accesses the file.

WordPress, PHP-FPM, and Nginx: Why the Model Is Changing

A significant part of the confusion arises from the fact that many historical recommendations derive from traditional Apache environments, often with mod_php or configurations where the web server needed to read much of the content directly. But In the modern world, especially in professional environments, a WordPress or PHP site is often run under a different model:

  • Nginx handles the HTTP connection and serves static assets;
  • PHP-FPM runs PHP code;
  • each PHP-FPM pool can run as a site-specific user;
  • the PHP code is not “read by Nginx” to be interpreted, but passed to PHP-FPM via FastCGI;
  • PHP process can be isolated per user, domain or subscription.

In this scenario, continuing to think as if everything had to be readable by “others” is technically backward. If PHP-FPM is running as the site user, PHP files can be read by the owner user. If Nginx needs to serve static files, it can access those files via the group. There's no logical need to grant read permission to the rest of the local world.

The correct model is to design ownership and groups consistently. For example:

owner: utente_sito
group: web-utente_sito

directory: 750
file:      640

In this scheme, the site user maintains control of the files, while the group grants access to authorized processes, such as Nginx or a specific service. Everyone else has no access.

The problem of nginx being used globally

A seemingly simple solution might be: "put Nginx in the user's group" or "assign the files to the nginx group." This reasoning is correct in its direction, but it must be applied carefully.

A crude example might be:

chown -R nomesito:nginx /home/nomesito/public_html
find /home/nomesito/public_html -type d -exec chmod 750 {} ;
find /home/nomesito/public_html -type f -exec chmod 640 {} ;

This works: Nginx, being in the group, can traverse directories and read files. "others" users can't do anything. However, if all sites on the server use the global group, nginx, then any process running as Nginx can potentially read files from all those sites. In a single-site server, this may be acceptable; in a multi-user environment, it's not the best isolation.

The most elegant solution is to use dedicated groups per site or per application context:

groupadd web-nomesito
usermod -aG web-nomesito nginx
usermod -aG web-nomesito nomesito

chown -R nomesito:web-nomesito /home/nomesito/public_html
find /home/nomesito/public_html -type d -exec chmod 750 {} ;
find /home/nomesito/public_html -type f -exec chmod 640 {} ;

To keep the group consistent on new files created inside directories, you can also use the bit setgid on directories:

find /home/nomesito/public_html -type d -exec chmod g+s {} ;

This way, new files created within those directories inherit the parent directory's group. It's not a magic wand, because you still have to manage umasks, deployments, SFTP, PHP processes, and update tools, but it's a much more sensible model than opening everything up to "others."

Why 750/640 is more correct

With directories at 750 and files at 640 you get a much cleaner separation:

rwxr-x---  directory
rw-r-----  file

The owner has full control. The group can read and pass through. Others can't do anything. This means that another local user cannot snoop around in the site's files just because the control panel has decided to use permissive permissions to avoid problems.

In WordPress, the difference isn't trivial. Within a WordPress installation, we can find configuration files, database credentials, authentication keys, custom plugins, forgotten backups, exports, logs, SQL dumps, temporary files, caches, external service configurations, API tokens, SMTP credentials, and much more. Of course, many of these files shouldn't be in the document root. But we know how the real world works: sites accumulate material, plugins, temporary folders, and migration leftovers.

If everything is readable by others, any weakness in local isolation can translate into a loss of confidentiality. A spectacular remote vulnerability isn't necessarily necessary. Sometimes a compromised account on the same server, a poorly isolated script, a cron job running with inadequate privileges, or a superficial multiuser setup are all it takes.

A more correct configuration for WordPress

On a modern stack with Nginx and PHP-FPM per user, a more sensible setup might be this:

SITE_USER="nomesito"
SITE_GROUP="web-nomesito"
SITE_PATH="/home/nomesito/public_html"

groupadd -f "$SITE_GROUP"
usermod -aG "$SITE_GROUP" nginx
usermod -aG "$SITE_GROUP" "$SITE_USER"

chown -R "$SITE_USER:$SITE_GROUP" "$SITE_PATH"

find "$SITE_PATH" -type d -exec chmod 750 {} ;
find "$SITE_PATH" -type f -exec chmod 640 {} ;
find "$SITE_PATH" -type d -exec chmod g+s {} ;

chmod 600 "$SITE_PATH/wp-config.php"

Of course, this is a conceptual example, not a recipe to blindly launch on any server. First, you need to check how PHP-FPM runs, what user it's running under, what primary group it uses, how files are created by WordPress updates, how the deployment system works, and whether ACLs, SELinux, AppArmor, CageFS, a control panel, or other isolation mechanisms are in place.

In some cases, 750/640 may be more suitable. In others, 750/650 may be more suitable if you want to maintain the execution bit on specific files or if there are particular operational needs. In still others, 700/600 may be more suitable for sections not served directly from the web. The point is not to idolize a number, but to stop considering 755/644 as a universal law.

The responsibility of control panels

Plesk and cPanel aren't "wrong" because they don't understand Linux permissions. They're mature, complex products used in vastly different contexts. Their problem is another: they need to choose defaults that work in as many scenarios as possible. And when software has to choose between rigorous security and reducing support issues, it often chooses the latter.

The result is that a setting designed for compatibility becomes, in the common perception, a security recommendation. And that's dangerous. Because the inexperienced system administrator reads "755 directories, 644 files" and thinks, "That's the correct configuration." What he should actually read is, "This is the configuration that will probably avoid 403 errors in most general-purpose environments."

The difference is substantial. A default value isn't automatically a best practice. A value that avoids tickets isn't automatically the safest value. A configuration tolerated by a control panel isn't necessarily the ideal configuration for a modern, expertly designed, managed environment.

The case of writable files

Another often confusing topic is writeability. WordPress, plugins, caching, uploads, and updates all need to write to certain directories. But this doesn't mean the entire site needs to be writable or readable by everyone.

More rigorous management should distinguish between:

  • application code, which should be modifiable only by the owner or the deployment system;
  • upload directories, which must be writable by the PHP process;
  • cache directories, which must be writable by the application process;
  • configuration files, which should be as restrictive as possible;
  • static assets, which Nginx should be able to read but not modify.

A mature policy doesn't say "all 755s and 644s." It says: "Who should read? Who should write? Who should pass through? Who should have no access?" Only then do you choose chmod, chown, groups, ACLs, and umasks.

Conclusion: the problem is not Linux, it's the laziness of the default

Linux already offers all the tools to do things well: users, groups, permissions, ACLs, umask, setgid, process isolation, PHP-FPM separate pools, chroot, containers, namespaces, MAC systems like SELinux and AppArmor. The problem isn't the Unix model. The problem is the habit of using loose configurations because "that's how it works."

Control panels have historically promoted or standardized permissions like 755 and 644 because they're simple, compatible, and reduce the risk of breaking poorly configured sites. But in a professional environment, especially for WordPress and more generally for PHP sites served by Nginx with a PHP-FPM backend, there are more correct, more consistent, and more respectful configurations that respect the principle of least privilege.

750 directories and 640 files, with properly designed ownership and groups, represent a healthier model. It's not always straightforward to implement, it's not always compatible with any panel without modifications, but it's conceptually superior. The web server shouldn't read because "everyone can read." It should read because it's authorized to do so. PHP shouldn't write everywhere. It should write only where needed. Other system users shouldn't be able to snoop around the code and configurations of a site that doesn't belong to them.

True system security isn't about copying commands from a generic guide, but understanding the execution model of your stack. If the server is well designed, 755 and 644 aren't a necessity: they're just a compromise inherited from the past. And like many historical compromises in shared hosting, they persist not because they're right, but because they're convenient.

Do you have doubts? Don't know where to start? Contact us!

We have all the answers to your questions to help you make the right choice.

Chat with us

Chat directly with our presales support.

0256569681

Contact us by phone during office hours 9:30 - 19:30

Contact us online

Open a request directly in the contact area.

DISCLAIMER, Legal Notes and Copyright. RedHat, Inc. holds the rights to Red Hat®, RHEL®, RedHat Linux®, and CentOS®; AlmaLinux™ is a trademark of the AlmaLinux OS Foundation; Rocky Linux® is a registered trademark of the Rocky Linux Foundation; SUSE® is a registered trademark of SUSE LLC; Canonical Ltd. holds the rights to Ubuntu®; Software in the Public Interest, Inc. holds the rights to Debian®; Linus Torvalds holds the rights to Linux®; FreeBSD® is a registered trademark of The FreeBSD Foundation; NetBSD® is a registered trademark of The NetBSD Foundation; OpenBSD® is a registered trademark of Theo de Raadt; Oracle Corporation holds the rights to Oracle®, MySQL®, MyRocks®, VirtualBox®, and ZFS®; Percona® is a registered trademark of Percona LLC; MariaDB® is a registered trademark of MariaDB Corporation Ab; PostgreSQL® is a registered trademark of PostgreSQL Global Development Group; SQLite® is a registered trademark of Hipp, Wyrick & Company, Inc.; KeyDB® is a registered trademark of EQ Alpha Technology Ltd.; Typesense® is a registered trademark of Typesense Inc.; REDIS® is a registered trademark of Redis Labs Ltd; F5 Networks, Inc. owns the rights to NGINX® and NGINX Plus®; Varnish® is a registered trademark of Varnish Software AB; HAProxy® is a registered trademark of HAProxy Technologies LLC; Traefik® is a registered trademark of Traefik Labs; Envoy® is a registered trademark of CNCF; Adobe Inc. owns the rights to Magento®; PrestaShop® is a registered trademark of PrestaShop SA; OpenCart® is a registered trademark of OpenCart Limited; Automattic Inc. holds the rights to WordPress®, WooCommerce®, and JetPack®; Open Source Matters, Inc. owns the rights to Joomla®; Dries Buytaert owns the rights to Drupal®; Shopify® is a registered trademark of Shopify Inc.; BigCommerce® is a registered trademark of BigCommerce Pty. Ltd.; TYPO3® is a registered trademark of the TYPO3 Association; Ghost® is a registered trademark of the Ghost Foundation; Amazon Web Services, Inc. owns the rights to AWS® and Amazon SES®; Google LLC owns the rights to Google Cloud™, Chrome™, and Google Kubernetes Engine™; Alibaba Cloud® is a registered trademark of Alibaba Group Holding Limited; DigitalOcean® is a registered trademark of DigitalOcean, LLC; Linode® is a registered trademark of Linode, LLC; Vultr® is a registered trademark of The Constant Company, LLC; Akamai® is a registered trademark of Akamai Technologies, Inc.; Fastly® is a registered trademark of Fastly, Inc.; Let's Encrypt® is a registered trademark of the Internet Security Research Group; Microsoft Corporation owns the rights to Microsoft®, Azure®, Windows®, Office®, and Internet Explorer®; Mozilla Foundation owns the rights to Firefox®; Apache® is a registered trademark of The Apache Software Foundation; Apache Tomcat® is a registered trademark of The Apache Software Foundation; PHP® is a registered trademark of the PHP Group; Docker® is a registered trademark of Docker, Inc.; Kubernetes® is a registered trademark of The Linux Foundation; OpenShift® is a registered trademark of Red Hat, Inc.; Podman® is a registered trademark of Red Hat, Inc.; Proxmox® is a registered trademark of Proxmox Server Solutions GmbH; VMware® is a registered trademark of Broadcom Inc.; CloudFlare® is a registered trademark of Cloudflare, Inc.; NETSCOUT® is a registered trademark of NETSCOUT Systems Inc.; ElasticSearch®, LogStash®, and Kibana® are registered trademarks of Elastic NV; Grafana® is a registered trademark of Grafana Labs; Prometheus® is a registered trademark of The Linux Foundation; Zabbix® is a registered trademark of Zabbix LLC; Datadog® is a registered trademark of Datadog, Inc.; Ceph® is a registered trademark of Red Hat, Inc.; MinIO® is a registered trademark of MinIO, Inc.; Mailgun® is a registered trademark of Mailgun Technologies, Inc.; SendGrid® is a registered trademark of Twilio Inc.; Postmark® is a registered trademark of ActiveCampaign, LLC; cPanel®, LLC owns the rights to cPanel®; Plesk® is a registered trademark of Plesk International GmbH; Hetzner® is a registered trademark of Hetzner Online GmbH; OVHcloud® is a registered trademark of OVH Groupe SAS; Terraform® is a registered trademark of HashiCorp, Inc.; Ansible® is a registered trademark of Red Hat, Inc.; cURL® is a registered trademark of Daniel Stenberg; Facebook®, Inc. owns the rights to Facebook®, Messenger® and Instagram®. This site is not affiliated with, sponsored by, or otherwise associated with any of the above-mentioned entities and does not represent any of these entities in any way. All rights to the brands and product names mentioned are the property of their respective copyright holders. All other trademarks mentioned are the property of their respective registrants. MANAGED SERVER® is a European registered trademark of MANAGED SERVER SRL, with registered office in Via Flavio Gioia, 6, 62012 Civitanova Marche (MC), Italy and operational headquarters in Via Enzo Ferrari, 9, 62012 Civitanova Marche (MC), Italy.

JUST A MOMENT !

Have you ever wondered if your hosting sucks?

Find out now if your hosting provider is hurting you with a slow website worthy of 1990! Instant results.

Close the CTA
Back to top