Linux Users, Groups & Permissions
This lesson is one of the most important for running a real web-hosting server.
You now know:
Domain
↓
DNS
↓
IP
↓
Network
↓
Nginx
↓
PHP-FPM
↓
WordPress
↓
MySQL
↓
Storage
Now we ask:
Who is allowed to do what?
That is the job of:
Users
Groups
Permissions
Ownership
1. Linux Is a Multi-User System
Linux was designed so that multiple users and processes can safely share one system.
For example:
root
ubuntu
www-data
mysql
can all exist on the same server.
They do not automatically have the same permissions.
2. Why This Matters for Hosting
Your VPS may run:
Nginx
PHP-FPM
MySQL
SSH
WordPress
If every process had unrestricted access to everything:
security disaster
Instead:
Nginx
↓
limited permissions
PHP-FPM
↓
limited permissions
MySQL
↓
limited permissions
This is called:
Least Privilege
Give a process only the access it actually needs.
3. Root
The most powerful traditional Linux user is:
root
Root has very broad authority over the system.
You can verify your current user:
whoami
If the result is:
root
you are operating as root.
4. Why Root Is Dangerous
Suppose you run:
rm -rf /some-directory
as a normal user.
You may receive:
Permission denied
As root, the command may succeed.
Therefore:
Root removes many of the protection barriers that normally prevent accidental or unauthorized changes.
5. sudo
Instead of logging in as root, Ubuntu commonly uses:
sudo
Example:
sudo systemctl restart nginx
This means approximately:
Run this command with elevated privileges according to the user’s sudo permissions.
6. Normal User
You might log into your VPS as:
ubuntu
Then:
whoami
returns:
ubuntu
But:
sudo whoami
may return:
root
if the user is authorized for sudo.
7. Why This Is Better
Instead of doing everything as root:
login
↓
root
↓
everything
you can use:
ubuntu
↓
normal work
↓
sudo
↓
administrative command
This reduces accidental damage.
8. Linux User Identity
Every user has a:
UID
User ID.
Run:
id
Example:
uid=1000(ubuntu) gid=1000(ubuntu) groups=...
The numbers are what the kernel fundamentally uses to identify users.
9. Root UID
Traditionally:
root
UID = 0
UID 0 has special administrative privileges.
10. Groups
Linux also uses:
Groups
A group allows multiple users to share permissions.
For example:
webadmins
could contain:
ubuntu
developer1
developer2
Then a file could be accessible to the group.
11. GID
Every group has a:
GID
Group ID.
Run:
id
to see your user and group information.
12. Example
Suppose:
User:
ubuntu
UID:
1000
Primary group:
ubuntu
GID:
1000
The exact IDs depend on the system.
13. id
Use:
id username
Example:
id ubuntu
You can also inspect:
id www-data
14. www-data
On Ubuntu/Debian systems, web services commonly use:
www-data
as a service account.
You can check:
id www-data
You may see a UID/GID assigned to it.
15. Why Does www-data Exist?
Imagine PHP-FPM runs as:
www-data
If PHP is compromised, you don’t want the attacker to automatically have:
root
access.
Instead, the compromised process initially has the permissions of its service account.
This is a major security boundary.
16. MySQL User
MySQL commonly runs under a dedicated account such as:
mysql
Check:
id mysql
This separates MySQL from other services.
17. SSH
SSH service processes may begin with elevated privileges for specific system operations and then use lower-privileged contexts for sessions as appropriate.
The important concept is:
SSH service
≠
automatically root shell
Your login account determines the normal user context of your shell.
18. File Ownership
Every normal file has:
owner
group
permissions
Run:
ls -l
Example:
-rw-r--r-- 1 www-data www-data index.php
The important parts are:
owner = www-data
group = www-data
19. Three Permission Classes
Linux traditionally evaluates permissions for:
Owner
Group
Others
For example:
-rwxr-x---
means:
Owner → rwx
Group → r-x
Others → ---
20. Read
r
means:
read
For a file:
read contents
For a directory:
list entries
subject to the other permissions needed for directory access.
21. Write
w
For a file:
modify contents
For a directory:
create/delete/rename entries
subject to directory access and other controls.
22. Execute
x
For a file:
execute
For a directory:
traverse/search
This difference is extremely important.
23. Directory x
Suppose:
/storage/websites/site/public/
has:
x
permission.
It means a user/process can traverse that directory if the other required permissions are satisfied.
Without appropriate x permissions on parent directories, a file can remain inaccessible even if the file itself is readable.
24. Example
You have:
/storage/websites/site/public/index.php
Even if:
index.php
is:
644
the web server still needs appropriate access to the parent directories.
25. Numeric Permissions
Linux commonly represents permissions numerically.
Remember:
r = 4
w = 2
x = 1
Add them.
26. 7
4 + 2 + 1 = 7
Therefore:
7 = rwx
27. 6
4 + 2 = 6
Therefore:
6 = rw-
28. 5
4 + 1 = 5
Therefore:
5 = r-x
29. 4
4 = r--
30. 0
0 = ---
31. 755
Break it into:
7 5 5
Therefore:
Owner = rwx
Group = r-x
Others = r-x
32. 644
6 4 4
Therefore:
Owner = rw-
Group = r--
Others = r--
This is commonly used for regular web files.
33. Files vs Directories
A common pattern is:
Files
→ 644
and:
Directories
→ 755
But this is not a universal law.
The correct permissions depend on:
application
owner
group
web server
deployment model
security requirements
34. Never Automatically Use 777
You may see:
chmod -R 777 website/
recommended in random tutorials.
Avoid this.
It means:
Owner = rwx
Group = rwx
Others = rwx
Everyone gets broad read/write/execute access.
35. Why 777 Is Dangerous
Suppose a web-accessible directory has:
777
and an application vulnerability allows arbitrary file creation.
An attacker may potentially write malicious files there.
You have unnecessarily expanded the attack surface.
36. chmod
Change permissions with:
chmod
Example:
chmod 644 index.php
37. Directory Example
chmod 755 public
Now:
owner → rwx
group → r-x
others → r-x
38. Recursive chmod
You can use:
chmod -R
But be extremely careful.
For example:
chmod -R 755 website/
will also make regular files executable.
That is often undesirable.
39. Better Recursive Strategy
A common pattern is to set:
directories → 755
files → 644
using find.
For example:
find website/ -type d -exec chmod 755 {} \;
and:
find website/ -type f -exec chmod 644 {} \;
This is still only a baseline; ownership and application requirements matter.
40. Ownership
Use:
chown
Example:
sudo chown www-data:www-data index.php
This means:
owner = www-data
group = www-data
41. chown user:group
General syntax:
chown USER:GROUP FILE
Example:
sudo chown ubuntu:www-data index.php
Now:
owner = ubuntu
group = www-data
42. Why Separate Owner and Group?
This can create a useful hosting model.
For example:
Owner:
deployment user
Group:
www-data
Then:
developer
↓
owns files
www-data
↓
can access required files
This can be more flexible than making everything owned by www-data.
43. Your Hosting Platform
A clean architecture might eventually have:
site owner/deployment user
│
▼
website files
│
▼
www-data
│
▼
PHP-FPM/Nginx
The exact model depends on whether users have shell access, how deployments work, and whether sites are isolated.
44. Security Principle
Ask:
Does PHP really need write access to the entire WordPress installation?
Usually:
No.
The web application often needs write access to specific locations such as uploads/cache directories, while core files should ideally be more restricted.
45. Why This Matters
If PHP can modify:
wp-config.php
all plugin files
all theme files
all WordPress core files
then a compromised PHP application may be able to persist malicious code throughout the site.
Reducing unnecessary write permissions can improve security.
46. WordPress Upload Directory
WordPress commonly needs to write to:
wp-content/uploads/
Therefore this directory may need write access for the PHP process.
But that does not mean:
entire website
should be writable.
47. Example Security Model
Conceptually:
WordPress core
↓
readable
↓
not generally writable by PHP
while:
wp-content/uploads
↓
writable by PHP
This is a stronger security posture.
The exact implementation must account for updates, plugins, deployment tools, and operational requirements.
48. umask
Now a deeper concept:
umask
It controls which permission bits are removed from newly created files/directories.
Check:
umask
You might see:
0022
49. Why umask Matters
Suppose a program requests default permissions when creating a file.
The process’s umask can restrict those permissions.
Conceptually:
Requested permissions
↓
umask
↓
Actual permissions
50. Example
A common umask:
022
can result in typical defaults such as:
files → 644
directories → 755
depending on what permissions the application requests when creating them.
51. setgid on Directories
There is another useful permission feature:
setgid
When applied to a directory, newly created files/directories can inherit the directory’s group rather than simply using the creator’s primary group, subject to system behavior.
This can be useful for shared website administration.
52. Example
Suppose:
website/
belongs to:
webteam
Set the directory’s setgid bit:
chmod g+s website/
Then newly created entries can inherit:
webteam
as their group.
53. Why Hosting Systems May Use This
Suppose:
developer
and:
www-data
both need controlled access.
A shared group can simplify collaboration.
Example:
webteam
├── developer
└── www-data
Then:
website files
↓
group = webteam
54. Sticky Bit
Another special permission is:
sticky bit
It is commonly seen on:
/tmp
Check:
ls -ld /tmp
You may see something like:
drwxrwxrwt
The final:
t
represents the sticky bit.
55. Why /tmp Uses Sticky Bit
Many users/processes can write to /tmp.
The sticky bit helps prevent one user from arbitrarily deleting another user’s files there, subject to ownership and privileges.
56. Special Permissions Summary
You now have:
setuid
setgid
sticky bit
They are advanced permission mechanisms.
For now remember:
setgid directory
=
group inheritance
sticky directory
=
restrict deletion of others' entries
57. ACLs
Linux can also support:
Access Control Lists
ACLs provide more granular permissions than the traditional:
owner
group
others
model.
For example:
owner → rwx
group → r-x
developer2 → rwx
others → ---
58. getfacl
Check ACLs:
getfacl file.txt
If ACLs are being used, this can explain permissions that aren’t obvious from:
ls -l
59. setfacl
ACLs can be modified using:
setfacl
Don’t add ACLs casually; they increase configuration complexity.
But they are useful for advanced shared hosting and deployment scenarios.
60. Permission Troubleshooting
Suppose WordPress says:
Unable to create directory
Don’t immediately run:
chmod -R 777
Instead investigate.
61. Step 1 — Identify the Process User
Find PHP-FPM:
ps aux | grep php-fpm
Look at which user its worker processes run as.
Often:
www-data
but verify your actual configuration.
62. Step 2 — Inspect Directory
ls -ld wp-content/uploads
Example:
drwxr-xr-x www-data www-data uploads
63. Step 3 — Check Parent Directories
Inspect:
namei -l /storage/websites/site/public/wp-content/uploads
This is an excellent command for permission troubleshooting.
It shows permissions and ownership along the entire path.
64. Why namei Is Powerful
Instead of checking:
/storage
/storage/websites
/storage/websites/site
/storage/websites/site/public
...
one by one:
namei -l PATH
shows the path components together.
65. Step 4 — Test as the Service User
For a controlled diagnostic, you can test access as the relevant user.
For example:
sudo -u www-data ls -la /storage/websites/site/public
This asks:
Can
www-dataaccess this directory?
66. Test File Creation
In a safe temporary/test directory:
sudo -u www-data touch test-file
If it fails:
Permission denied
you have confirmed the service user lacks the required write access there.
Do not create test files in production directories without removing them afterward.
67. Ownership Isn’t Everything
Suppose:
owner = www-data
but:
permissions = 444
Then the owner cannot write.
Therefore:
ownership
+
permissions
must be considered together.
68. Group Isn’t Enough Either
Suppose:
group = www-data
but:
permissions = 640
The group gets:
r--
not write access.
Therefore:
group membership
and:
group permission bits
both matter.
69. Effective Access
When troubleshooting, think:
Who is the process?
↓
What UID/GID does it have?
↓
Who owns the file?
↓
What group owns it?
↓
What permission class applies?
↓
Can it traverse the path?
↓
Can it perform the required operation?
This is much better than randomly changing permissions.
70. WordPress Example
Suppose:
PHP-FPM
↓
www-data
and:
/storage/websites/site/public/wp-content/uploads
is:
drwxr-xr-x ubuntu ubuntu
Then www-data may not have write access.
WordPress could fail to upload media.
71. Possible Better Model
You might instead use:
owner = deployment/admin user
group = www-data
with carefully chosen permissions.
For example, depending on your architecture:
directories → 775
files → 664
can allow group write access.
But this should only be used when the group really needs write access and the security implications are understood.
72. Don’t Copy Permission Numbers Blindly
There is no universal:
"WordPress permissions = exactly X"
The correct configuration depends on:
PHP user
deployment user
hosting isolation
automatic updates
plugin behavior
shared hosting model
security requirements
73. Hosting Isolation
This becomes especially important when hosting multiple customers.
Suppose:
siteA
siteB
siteC
If all PHP processes run as:
www-data
then they may share the same Unix identity.
That makes isolation weaker.
74. Per-Site Users
A stronger hosting design can use:
siteA → user siteA
siteB → user siteB
siteC → user siteC
Then:
PHP-FPM siteA
↓
siteA user
PHP-FPM siteB
↓
siteB user
Now one site’s process does not automatically have the same filesystem privileges as another site’s process.
75. Why Shared www-data Can Be Risky
Suppose:
siteA
is compromised.
If:
siteA PHP
↓
www-data
and:
siteB files
↓
also writable by www-data
then the compromise could potentially spread into siteB.
Per-site Unix users can reduce this risk.
76. This Is How Hosting Becomes Professional
Basic hosting:
All sites
↓
www-data
↓
same permissions
More isolated hosting:
siteA
↓
userA
siteB
↓
userB
siteC
↓
userC
This is an important architectural improvement for a multi-tenant hosting platform.
77. PHP-FPM Pools
PHP-FPM supports separate pools.
Conceptually:
PHP-FPM
│
├── siteA pool → userA
├── siteB pool → userB
└── siteC pool → userC
This can provide better isolation and per-site resource configuration.
78. Per-Site Resource Limits
A PHP-FPM pool can have settings controlling:
worker count
process management
user/group
socket
This allows:
siteA
↓
5 workers
siteB
↓
10 workers
depending on workload.
79. Combining Lessons
Now connect:
Users
+
Processes
+
Memory
+
Storage
Example:
siteA PHP-FPM
│
▼
userA
│
▼
website files
│
▼
RAM
while:
siteB PHP-FPM
│
▼
userB
│
▼
siteB files
This is much safer than letting every website share the same identity.
80. Root vs www-data
Memorize this distinction:
root
=
system administrator authority
www-data
=
service account commonly used by web services
They should not be treated as interchangeable.
81. The Dangerous Command
Be very careful with:
rm -rf
especially:
sudo rm -rf
As root, an incorrect path can cause severe damage.
Always verify:
pwd
and:
ls
before destructive operations.
82. Another Dangerous Pattern
Avoid casually doing:
chown -R www-data:www-data /
or:
chmod -R 777 /
These can destroy the security and functionality of the entire server.
83. Hosting Security Model
A good mental model:
ROOT
│
┌─────────┴─────────┐
▼ ▼
system services administrators
│
▼
limited users
│
▼
websites
Each layer gets only what it needs.
84. Essential Commands
Current user
whoami
Identity
id
User information
id www-data
File permissions
ls -la
Path permissions
namei -l /path/to/file
Change ownership
chown
Change permissions
chmod
ACL inspection
getfacl
Groups
groups
Test as another user
sudo -u USER command
85. Your Hosting Directory
For:
/storage/websites/learn.cresignsys.com/public
you should be able to answer:
Who owns it?
↓
What group owns it?
↓
What permissions?
↓
Which user runs PHP-FPM?
↓
Can that user read it?
↓
Can that user write where required?
↓
Can Nginx traverse/read it?
If you can answer those questions, you understand the permission layer.
86. Complete Hosting Stack
You now have:
DOMAIN
│
▼
DNS
│
▼
IP
│
▼
NETWORK
│
▼
LINUX
│
┌──────────────┼──────────────┐
▼ ▼ ▼
CPU RAM STORAGE
│ │ │
└──────────────┼──────────────┘
▼
SYSTEMD
│
▼
NGINX
│
process/user
│
▼
PHP-FPM
│
process/user
│
▼
WORDPRESS
│
▼
MYSQL
│
▼
DATABASE
And surrounding all of it:
Users
Groups
Permissions
Ownership
87. Lesson 054 — Core Principle
The deepest lesson is:
A Linux server doesn’t simply ask “does this file exist?” It asks “who is requesting access, what identity do they have, what permissions apply, and can they traverse the path?”
For hosting:
Browser
↓
Nginx
↓
PHP-FPM
↓
Unix user
↓
Filesystem permissions
↓
WordPress
This is the foundation of secure multi-website hosting.
Next Lesson — 055
Linux Networking — From Ethernet/VNIC to Port 443
We will now go deeper into the networking layer:
Internet
↓
Public IP
↓
VNIC
↓
Subnet
↓
Route table
↓
Security rules
↓
Linux network interface
↓
IP address
↓
TCP
↓
Port
↓
Socket
↓
Nginx
Then we will connect it directly to your Oracle Cloud VPS, including why:
DNS correct
+
Nginx running
can still result in:
Connection refused
Connection timed out
and how to determine exactly which layer is blocking the connection.
Leave a Reply