> ## Documentation Index
> Fetch the complete documentation index at: https://docs.derekdinh.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Resolving File Permission Errors on Linux and macOS

> Understand and repair Linux and macOS file permission errors using chmod, chown, and sudo, covering web servers, SSH keys, and home directories.

Permission errors are among the most common issues on Unix-based systems, and they are almost always fixable once you understand how the permission model works. Whether you are seeing "Permission denied" when accessing a web directory, an SSH key that is "too open," or files in a home directory that suddenly became inaccessible, the solution follows directly from reading the permission bits and applying the correct `chmod` or `chown` command.

## Understanding Unix File Permissions

Every file and directory on a Linux or macOS system has three permission sets — **owner**, **group**, and **others** — each containing three bits: **read (r)**, **write (w)**, and **execute (x)**.

### Reading `ls -l` Output

```bash theme={null}
ls -l /var/www/html/index.html
# -rw-r--r-- 1 www-data www-data 1234 Jan 10 09:00 index.html
#  ^^^^^^^^^   ^^^^^^^^ ^^^^^^^^
#  |            owner    group
#  permission bits
```

<AccordionGroup>
  <Accordion title="Breaking down the permission string">
    The ten-character string `-rw-r--r--` is read left to right:

    | Position | Meaning                                                       |
    | -------- | ------------------------------------------------------------- |
    | 1        | File type: `-` = regular file, `d` = directory, `l` = symlink |
    | 2–4      | Owner permissions: `rw-` = read + write, no execute           |
    | 5–7      | Group permissions: `r--` = read only                          |
    | 8–10     | Others permissions: `r--` = read only                         |
  </Accordion>

  <Accordion title="Octal notation quick reference">
    Permissions are often expressed as a three-digit octal number:

    | Octal | Binary | Meaning                |
    | ----- | ------ | ---------------------- |
    | `7`   | `111`  | read + write + execute |
    | `6`   | `110`  | read + write           |
    | `5`   | `101`  | read + execute         |
    | `4`   | `100`  | read only              |
    | `0`   | `000`  | no permissions         |

    So `644` means owner=rw, group=r, others=r. And `755` means owner=rwx, group=rx, others=rx.
  </Accordion>

  <Accordion title="The execute bit on directories">
    For directories, the **execute bit means "traverse"** — without it, users cannot `cd` into the directory or access files within it, even if they have read permission on individual files inside. A directory set to `644` is almost always a mistake.
  </Accordion>
</AccordionGroup>

***

## Step-by-Step Permission Repair

<Steps>
  <Step title="Diagnose the Permission Problem">
    Start by reading the exact error message and inspecting the permissions on the affected file or directory.

    ```bash theme={null}
    # Read the full error — it tells you what operation failed and on which path:
    # "Permission denied" when opening a file → check read bit for your user
    # "Permission denied" when writing a file → check write bit
    # "Permission denied" entering a directory → check execute bit on the directory

    # Inspect permissions on a specific file:
    ls -l /path/to/file

    # Inspect permissions on a directory and its immediate contents:
    ls -la /path/to/directory/

    # Check which user you are running as:
    whoami
    id
    ```

    ```bash theme={null}
    # Check if the problem is with the directory hierarchy — every directory
    # in the path must be traversable by your user:
    namei -l /var/www/html/index.html
    # namei walks each component of the path and prints its permissions
    ```

    <Tip>
      `namei -l` is one of the most useful tools for diagnosing permission failures in nested paths. If any component in the path lacks execute permission for your user, access to the final file will be denied regardless of its own permissions.
    </Tip>
  </Step>

  <Step title="Fix File Ownership with chown">
    `chown` changes the owner and/or group of a file. Use it when a file is owned by the wrong user — a common occurrence after copying files between accounts or running a command as root.

    ```bash theme={null}
    # Change owner to 'alice':
    sudo chown alice /home/alice/report.txt

    # Change owner and group simultaneously:
    sudo chown alice:developers /home/alice/report.txt

    # Recursively change ownership of a directory and all its contents:
    sudo chown -R alice:alice /home/alice/

    # Change only the group (leave owner unchanged):
    sudo chown :www-data /var/www/html/uploads/
    ```

    <Warning>
      Be careful with recursive `chown` on system directories. Running `sudo chown -R alice /etc` would break system authentication. Always double-check the target path before using `-R`.
    </Warning>

    **Verify the result:**

    ```bash theme={null}
    ls -la /home/alice/report.txt
    # -rw-r--r-- 1 alice alice 4096 Jan 10 09:00 report.txt
    ```
  </Step>

  <Step title="Fix File Permissions with chmod">
    `chmod` modifies the read, write, and execute bits. Both symbolic and octal notation are accepted.

    <Tabs>
      <Tab title="Octal Notation">
        ```bash theme={null}
        # Set a file to rw-r--r-- (owner read/write, everyone else read-only):
        chmod 644 /var/www/html/index.html

        # Set a directory to rwxr-xr-x (standard web directory):
        chmod 755 /var/www/html/

        # Set a script to be executable by owner only:
        chmod 700 ~/scripts/deploy.sh

        # Recursively apply permissions to all files inside a directory:
        chmod -R 644 /var/www/html/
        ```
      </Tab>

      <Tab title="Symbolic Notation">
        ```bash theme={null}
        # Add execute permission for the owner only:
        chmod u+x deploy.sh

        # Remove write permission from group and others:
        chmod go-w sensitive.conf

        # Give the group the same permissions as the owner:
        chmod g=u myfile.txt

        # Add read permission for everyone:
        chmod a+r readme.txt
        ```
      </Tab>

      <Tab title="Directories vs Files (Recursive)">
        When recursively fixing a web directory, files and directories typically need different permissions. Use `find` to apply them separately:

        ```bash theme={null}
        # Set all directories to 755:
        find /var/www/html -type d -exec chmod 755 {} \;

        # Set all files to 644:
        find /var/www/html -type f -exec chmod 644 {} \;
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Fix Common Permission Scenarios">
    <Tabs>
      <Tab title="Web Server Files (Apache / Nginx)">
        Web server processes (typically running as `www-data` on Debian/Ubuntu or `nginx` on RHEL) must be able to read your web files — and write to upload directories.

        ```bash theme={null}
        # Set correct ownership for an Apache site:
        sudo chown -R www-data:www-data /var/www/html/

        # Standard permissions for a web root:
        find /var/www/html -type d -exec chmod 755 {} \;
        find /var/www/html -type f -exec chmod 644 {} \;

        # Upload directories need write access for the web server:
        sudo chmod 775 /var/www/html/uploads/
        sudo chown www-data:www-data /var/www/html/uploads/
        ```

        <Note>
          For WordPress and similar CMS installations, the web server user often needs write access to the entire document root during upgrades. After upgrading, tighten permissions back to `644`/`755` and change ownership back to your deploy user.
        </Note>
      </Tab>

      <Tab title="SSH Keys">
        OpenSSH enforces strict permission requirements on key files and will refuse to use a key if it is "too open." These errors typically appear as "Permissions 0644 for '\~/.ssh/id\_rsa' are too open."

        ```bash theme={null}
        # Fix the .ssh directory permissions:
        chmod 700 ~/.ssh

        # Fix private key permissions (must be readable only by owner):
        chmod 600 ~/.ssh/id_rsa
        chmod 600 ~/.ssh/id_ed25519

        # Public key file (shareable, so 644 is fine):
        chmod 644 ~/.ssh/id_rsa.pub

        # authorized_keys must not be world-writable; 600 is the secure default:
        chmod 600 ~/.ssh/authorized_keys

        # Fix ownership (must be owned by the user, not root):
        chown -R $(whoami):$(whoami) ~/.ssh/
        ```

        ```bash theme={null}
        # Confirm SSH no longer complains about key permissions:
        ssh -v user@host 2>&1 | grep -i "perm\|key\|ident"
        ```

        <Warning>
          If `~/.ssh/authorized_keys` has world-write permissions, SSH will silently ignore it and refuse public-key authentication. This is a frequent cause of "falling back to password authentication" messages.
        </Warning>
      </Tab>

      <Tab title="Home Directory">
        A corrupted or overly permissive home directory can break login, `sudo`, and many applications that store configuration in `~`.

        ```bash theme={null}
        # Fix ownership of an entire home directory:
        sudo chown -R alice:alice /home/alice/

        # The home directory itself should not be world-writable:
        chmod 750 /home/alice/    # private (recommended)
        # or
        chmod 755 /home/alice/    # readable by others (acceptable on shared systems)

        # On macOS, repair a home directory's ACLs and permissions:
        diskutil resetUserPermissions / $(id -u)
        ```

        <Note>
          On macOS, the `resetUserPermissions` command resets permissions on all files in your home folder back to their defaults. This is the preferred approach over manually running `chmod` on macOS, as macOS uses extended ACLs in addition to standard POSIX permissions.
        </Note>
      </Tab>
    </Tabs>
  </Step>

  <Step title="Use sudo Safely">
    `sudo` grants temporary root-level access. Misusing it is a frequent source of incorrect ownership and permissions — files created as root when they should be owned by a service account or regular user.

    ```bash theme={null}
    # Run a single command as root:
    sudo chmod 600 /etc/myapp/secret.conf

    # Edit a root-owned file safely (avoids creating root-owned tmp files):
    sudo nano /etc/hosts

    # Run a command as a different user (not root):
    sudo -u www-data touch /var/www/html/test.txt

    # Check what sudo permissions your account has:
    sudo -l
    ```

    <Warning>
      Avoid running commands like `sudo chmod -R 777 /` or `sudo chown -R root /home` — these are destructive and can make the system unbootable or completely open to exploitation. If you find advice online suggesting `chmod 777` as a fix, it is masking the real problem rather than solving it.
    </Warning>

    ```bash theme={null}
    # If you accidentally ran a recursive chown as root and need to find
    # files now owned by root in a user's home directory:
    find /home/alice -not -user alice -ls
    ```
  </Step>
</Steps>

***

## Quick Reference: Permission Cheat Sheet

| Use Case                  | Recommended Permission | Command                      |
| ------------------------- | ---------------------- | ---------------------------- |
| Regular file              | `644`                  | `chmod 644 file`             |
| Executable / script       | `755`                  | `chmod 755 script.sh`        |
| Private config file       | `600`                  | `chmod 600 secret.conf`      |
| Web root directory        | `755`                  | `chmod 755 /var/www/html/`   |
| SSH private key           | `600`                  | `chmod 600 ~/.ssh/id_rsa`    |
| SSH directory             | `700`                  | `chmod 700 ~/.ssh/`          |
| Shared writable directory | `775`                  | `chmod 775 /shared/uploads/` |

***

## Escalation

<AccordionGroup>
  <Accordion title="Permission denied even after chmod/chown">
    Check for SELinux or AppArmor policies that override standard POSIX permissions:

    ```bash theme={null}
    # Check SELinux status (RHEL/Fedora/CentOS):
    getenforce
    ls -Z /path/to/file     # view SELinux context
    restorecon -Rv /var/www/html/   # restore default SELinux context

    # Check AppArmor status (Ubuntu/Debian):
    sudo aa-status
    sudo journalctl | grep -i apparmor | tail -20
    ```
  </Accordion>

  <Accordion title="Files on a mounted network share (NFS/SMB)">
    Permissions on NFS mounts are governed by the UID/GID mapping between the client and server. If the file owner's UID on the server does not match a UID on the client, access will be denied regardless of chmod settings. Contact your storage or systems administrator to review the NFS export options or Samba share configuration.
  </Accordion>

  <Accordion title="Escalation path">
    1. Record the exact error message, the output of `ls -la` on the affected path, and the output of `id` for the affected user.
    2. Check `journalctl -xe` or `/var/log/syslog` for related audit or denial messages.
    3. Submit a ticket to your systems administrator with the above information. If SELinux or AppArmor is involved, label the ticket accordingly, as policy changes require elevated access.
  </Accordion>
</AccordionGroup>
