Linux & OS Intermediate

Troubleshooting Linux rsync ‘Operation Not Permitted’ & Code 23 Errors from macOS

Resolve common 'rsync: some files could not be transferred permissions' errors when syncing from macOS to Linux, often caused by destination server permission issues or incorrect rsync flags like -a.

👨‍💻
Senior Systems Architect • Verified in Staging Labs

Resolve common 'rsync: some files could not be transferred permissions' errors when syncing from macOS to Linux, often caused by destination server permission issues or incorrect rsync flags like -a.

When synchronizing files from your macOS development environment to a remote Linux server using rsync over SSH, encountering permission-related errors is a common hurdle for many system administrators and developers. These errors typically manifest as Operation not permitted messages followed by rsync error: some files/attrs could not be transferred (code 23). This guide provides a highly technical, accurate, and step-by-step approach to diagnose and resolve these persistent rsync permission issues.

Symptom & Error Signature

You are attempting to push files from your local macOS machine to a remote Linux server using rsync, often with the -a (archive) flag. The command might look something like this:

rsync -avz --exclude '.DS_Store' -e "ssh -p 22" /path/to/local/project/ [email protected]:/var/www/html/project/

During the transfer, rsync fails to set file attributes (permissions, ownership, group) on the remote server for some files or directories, displaying errors similar to these:

sending incremental file list
...
rsync: [sender] chgrp "file.txt" failed: Operation not permitted (1)
rsync: [sender] chmod "directory/subdirectory/" failed: Operation not permitted (1)
rsync: [sender] chown "another_file.php" failed: Operation not permitted (1)
rsync error: some files/attrs could not be transferred (code 23) at main.c(1820) [sender=3.2.7]

The specific code 23 indicates that "some files/attrs could not be transferred," often due to permission problems.

Root Cause Analysis

The rsync permission errors, specifically Operation not permitted (code 1) leading to code 23, almost universally point to a mismatch between the desired file attributes (permissions, ownership, group) you're trying to set from your macOS machine and what the SSH user on the remote Linux server is actually allowed to do.

The primary culprits are usually:

  1. Insufficient Permissions on Remote Target Directory: The SSH user (user in [email protected]) does not have write permissions to the destination directory (/var/www/html/project/) on the Linux server. This is the most basic and common issue.
  2. rsync -a (Archive Mode) Implications: The -a flag is a powerful shortcut for -rlptgoD (recursive, links, permissions, times, group, owner, devices/specials). When rsync attempts to preserve owner (-o) and group (-g) on the remote server, it will fail if the SSH user:
    • Is not root.
    • Does not own the target directory.
    • Is not a member of the target group.
    • Does not have the necessary CAP_CHOWN or CAP_SETGID capabilities. Normal users on Linux cannot arbitrarily chown files to other users or chgrp files to groups they are not part of.
  3. Inability to Preserve Permissions (-p): While less common to fail entirely, preserving explicit permission bits (chmod) can also be problematic if the user doesn't own the file or if the remote filesystem/directory has restrictive umask settings or Access Control Lists (ACLs) that prevent the user from setting specific permissions.
  4. SELinux/AppArmor Context Restrictions: On systems with mandatory access control frameworks like SELinux (Red Hat-based) or AppArmor (Debian/Ubuntu), even if file system permissions seem correct, the security context might prevent the rsync process (running as your SSH user) from writing to or modifying files in certain locations.
  5. Immutable Bits: Less frequently, chattr +i (immutable bit) could be set on files or directories on the remote, preventing any modification, even by root.

Step-by-Step Resolution

Follow these steps to systematically diagnose and resolve the rsync permission errors.

1. Verify and Correct Remote Destination Directory Permissions

This is the most critical first step. Ensure the SSH user has appropriate write permissions to the target directory and its contents on the Linux server.

  1. Connect to your Remote Server:

    ssh [email protected]
    
  2. Check Current Permissions and Ownership: Replace /var/www/html/project/ with your actual destination path.

    ls -ld /var/www/html/project/
    ls -la /var/www/html/project/ # To see contents and their ownership
    whoami # To confirm the user you are logged in as
    

    Pay close attention to the owner:group and the permission bits (e.g., drwxr-xr-x). The whoami output should match the owner of the directory, or at least the user should be in the group that has write permissions.

  3. Adjust Ownership and Permissions (if necessary): If the SSH user (user) does not own the directory or doesn't have write permissions, you'll need to correct it.

    Carefully choose the correct owner, group, and permissions. Misconfiguring these can lead to security vulnerabilities or make your web server unable to read/write files. For web content, www-data (Ubuntu/Debian) or nginx/apache (other distros) is a common web server user.

    To change ownership and group (e.g., to your SSH user and www-data group, which your user might be a part of):

    sudo chown -R user:www-data /var/www/html/project/
    

    To ensure the owner has full read/write/execute and the group has read/execute:

    sudo chmod -R u=rwX,g=rX /var/www/html/project/
    

    The X in chmod allows execute permission only if the file is a directory or already has execute permission for some user. This is generally good practice to avoid making all files executable. If you need group write access for collaborative development, you might use g=rwX.

    After changing permissions, you might want to add your user to the www-data group: sudo usermod -aG www-data user. You'll need to log out and back in for group changes to take effect.

2. Adjust rsync Flags for Permission Handling

If the remote permissions are set correctly, the issue is likely rsync trying to set ownership/group that your SSH user cannot.

  1. Exclude Ownership and Group Preservation: The most common fix is to tell rsync not to preserve owner (-o) and group (-g) when using archive mode (-a). This way, files will be created with the ownership and group of the SSH user on the remote server.

    rsync -avz --exclude '.DS_Store' --no-o --no-g -e "ssh -p 22" /path/to/local/project/ [email protected]:/var/www/html/project/
    

    This command will preserve permissions (-p) but create files owned by user:user (or user:primary_group_of_user) on the remote, which is typically what's desired if user has write access to the destination.

  2. Explicitly Set Remote Ownership/Group (Alternative): If you need files on the remote to have a specific owner and group, you can use the --chown flag. This requires the user on the remote to have the necessary permissions (e.g., sudo access, which we'll cover later, or for the target owner/group to already be the SSH user's).

    rsync -avz --exclude '.DS_Store' --chown=www-data:www-data -e "ssh -p 22" /path/to/local/project/ [email protected]:/var/www/html/project/
    

    The --chown flag typically requires root privileges on the destination for non-self-owned files. If your SSH user is not root, this will likely fail unless user is implicitly allowed to chown to www-data:www-data (which is highly unusual). In most scenarios, --no-o --no-g is safer and more effective.

3. Bypass Permissions with sudo on Remote (Advanced)

If you absolutely need rsync to preserve all attributes and your remote user has password-less sudo access (or you're willing to provide a password), you can instruct rsync to execute as root on the remote side.

Using sudo with rsync on the remote side is a powerful operation. Ensure you fully trust the source and destination paths. Granting a user password-less sudo for rsync is a significant security risk and should only be done if strictly necessary and understood.

  1. Configure sudo (if not already): On the remote server, edit your sudoers file (sudo visudo) to allow the user to run rsync without a password.

    user ALL=(ALL) NOPASSWD: /usr/bin/rsync
    

    Or, more restrictively:

    user ALL=(ALL) NOPASSWD: /usr/bin/rsync --server *
    

    The latter is more secure as it only allows the server-side component of rsync.

  2. Execute rsync with sudo: From your macOS machine:

    rsync -avz --exclude '.DS_Store' -e "ssh -p 22" --rsync-path="sudo rsync" /path/to/local/project/ [email protected]:/var/www/html/project/
    

    This tells rsync to prepend sudo to the rsync command executed on the remote, allowing it to perform privileged operations like changing ownership and group.

4. Check SELinux/AppArmor Status (Remote)

If you're still facing issues after addressing file permissions and rsync flags, particularly on CentOS/RHEL (SELinux) or Ubuntu/Debian (AppArmor), these security modules might be blocking operations.

  1. Check SELinux Status (on remote CentOS/RHEL):

    getenforce
    sestatus
    

    If getenforce returns Enforcing, SELinux is active. Look for denials in the audit log:

    sudo ausearch -c rsync --raw | audit2allow -M rsync_local
    sudo cat /var/log/audit/audit.log | grep rsync
    sudo journalctl -xe | grep "SELinux"
    

    Temporarily setting SELinux to Permissive can help diagnose: sudo setenforce 0. If rsync works, you'll need to create proper SELinux policies or label the directory correctly (chcon).

  2. Check AppArmor Status (on remote Ubuntu/Debian):

    sudo aa-status
    sudo dmesg | grep "apparmor"
    sudo journalctl -xe | grep "apparmor"
    

    If AppArmor is enforcing a profile that restricts rsync or the target directory, you might see denials in dmesg or journalctl. You could temporarily disable the profile for diagnostic purposes: sudo aa-disable /etc/apparmor.d/path.to.profile.

5. Verify Remote Disk Space

While not directly a permission error, a full disk can sometimes lead to write failures that manifest misleadingly.

  1. Check Disk Usage (on remote):
    df -h /var/www/html/project/
    
    Ensure there is sufficient free space on the partition where your destination directory resides. If the disk is full, you'll need to free up space or expand the filesystem.

By systematically applying these troubleshooting steps, you should be able to identify and resolve the rsync permission issues when transferring files from macOS to your Linux server, ensuring smooth and reliable deployments.

👨‍💻

Johnathon Wheeler

Senior Systems Architect & DevOps Engineer • Austin, TX

Connect on LinkedIn →

Johnathon has over 16 years of hands-on experience designing, debugging, and scaling Linux web hosting stacks, container clusters, and high-availability database architectures. Every guide on ButItWorkedLocal is independently tested against Debian 12, Ubuntu 24.04/22.04 LTS, Rocky Linux, and Docker environments to guarantee reproducibility in production.

🛡️

Our Production Verification Guarantee

Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.