
The web server process — Nginx, Apache (apache2-cs), or the PHP-FPM worker behind it — has to be able to read every file it serves, and it has to be able to write to specific directories on top of that. Neither of those things happens automatically just because a file exists on disk; the kernel checks the file's owner, its group, and the permission bits against whoever the running process actually is, and if none of those line up, the request fails no matter how correct the code itself is.
On a stock Ubuntu box running a standard Nginx-plus-PHP-FPM stack, that process commonly runs as a single shared account, www-data, and every site on the server shares it. CloudStick does this differently: each website gets its own isolated system user — something like cpuser482 — and that site's PHP-FPM pool runs as that exact user, not as a shared account. That means ownership on a CloudStick server needs to match the site's own user, not www-data, which is the single most common source of confusion when someone applies advice written for a generic Ubuntu server to a CloudStick-hosted site.
For a typical WordPress-style app, the baseline that works almost everywhere is directories at 755 (rwxr-xr-x) and files at 644 (rw-r--r--), all owned by the site's own user and group. That gives the owner full read and write, and gives everyone else — including the web server process, if it happens to run under a different but overlapping group — read access and, for directories, the ability to look inside without being able to rename or delete what's there.
This baseline is deliberately conservative: nobody outside the owner can write anything, so a compromised neighboring account or a misconfigured shared process can't modify the site's code even if it can read it. The trade-off is that this baseline alone breaks the moment the application itself needs to write something at runtime — which is exactly the case the next section covers.
Some directories are exceptions to the read-only baseline by design. wp-content/uploads, any cache directory, and any folder the application writes into while it's running need to be writable by the web server process itself — otherwise every media upload, every generated cache file, and every plugin that writes its own data to disk fails silently or throws a permissions error the user never sees the real cause of.
There are two correct ways to make that happen: own the directory directly as the site's user (the simplest option when PHP-FPM already runs as that user), or make it group-writable at 775 and add the web server's group to that directory's group ownership. Either approach keeps the write access scoped to exactly the folders that need it, instead of loosening permissions across the whole application just to fix one broken upload form.
wp-config.php, and any other file holding database credentials or secrets, should be tighter than the 644 baseline. Set it to 640 (rw-r-----) so the owning user can still read it — which is all the web server process needs to boot the application — while every other local account on the box, including other sites' users if they happen to share a group, is locked out entirely.
It's a small change with an outsized payoff: a database password sitting in a 644 file is readable by any account on a shared box, while the same file at 640 is invisible to everyone except the one user that actually needs it and root.
A common mess to inherit is a site tree where an SFTP client, a badly configured deploy script, or a manual unzip as the wrong user has left files owned by all sorts of different accounts. The fix is one combined command that resets ownership and then reapplies the standard baseline across every directory and file in the tree:
Never reach for chmod 777 to make an ownership problem go away — it isn't a fix, it's a security hole, because it hands write access to every account on the box, not just the one that needed it. When the real problem is "wrong user," fix the owner. Reserve permission-bit changes for cases where the owner is already correct and only the access level is wrong.
Git-deployed applications are a common ownership trap that has nothing to do with a mistake in the code. If a dedicated deploy account — often called git — runs git pull on the server, every new or changed file that pull creates is owned by that git account, not by the site's own web-server user. The application still runs, right up until the next request that needs to write a cache file or a session, at which point it fails with a silent 500 error that has nothing obviously to do with ownership in the logs. The standard fix is a post-deploy hook, or a scheduled step right after the pull, that hands ownership of the whole tree back to the site's user with the same chown -R pattern shown above.
CloudStick avoids most of this by construction. Because every website gets its own dedicated system user and that site's PHP-FPM pool always runs as that same user, files uploaded through the dashboard — via the File Manager, the WordPress installer, or the built-in Git Deployment tool — land already owned correctly, with no post-deploy step required. This entire class of bug mostly only shows up when files are pushed onto a CloudStick server through an external SFTP or FTP account that doesn't match the site's own user, which is the one path that bypasses the dashboard's automatic ownership handling.
As a practical next step: if a site is throwing unexplained 500 errors on uploads or writes right after a deploy or a manual file transfer, run ls -la on the affected directory before touching anything else. A mismatch between the file owner and the site's PHP-FPM user is the first thing to rule out, and the fixes above — the 755/644 baseline, a group-writable uploads folder, a 640 wp-config.php, and a full chown -R when things have drifted — cover nearly every ownership issue you'll run into on a Linux web server.

