Linux & OS Intermediate

Resolving ‘rsync error: some files could not be transferred (code 23) (permissions denied)’ on Ubuntu 20.04 LTS

Fix rsync 'Permission denied' (code 23) errors on Ubuntu 20.04 LTS. This guide details root causes and step-by-step resolutions for file transfer issues.

👨‍💻
Senior Systems Architect • Verified in Staging Labs

Fix rsync 'Permission denied' (code 23) errors on Ubuntu 20.04 LTS. This guide details root causes and step-by-step resolutions for file transfer issues.

When performing critical file synchronization or backups on Ubuntu 20.04 LTS using rsync, encountering "Permission denied" errors can halt operations and indicate underlying access control issues. This guide will walk you through diagnosing and resolving the common rsync error where "some files could not be transferred" due to insufficient permissions on the destination system. Understanding the interplay between users, groups, file permissions, and rsync options is key to a robust and reliable synchronization strategy.

Symptom & Error Signature

Users typically encounter this issue when running an rsync command, either locally or remotely (via SSH), and some files or directories fail to transfer completely, leading to an exit code of 23. The terminal output will show specific files or directories that rsync could not read from the source or, more commonly, could not write/modify on the destination.

Typical error messages include:

rsync: [generator] mkstemp "/path/to/destination/some_file.tmp" failed: Permission denied (13)
rsync: [sender] chown "/path/to/destination/some_directory" failed: Operation not permitted (1)
rsync: [sender] chgrp "/path/to/destination/some_file" failed: Operation not permitted (1)
rsync: [sender] rsync_xfer_file failed on "/path/to/source/another_file": Permission denied (13)
rsync error: some files could not be transferred (code 23) at main.c(1821) [generator]
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1870) [receiver]

The key indicators are "Permission denied (13)" for file operations (like mkstemp or rsync_xfer_file) and "Operation not permitted (1)" for attribute changes (like chown or chgrp).

Root Cause Analysis

The rsync "Permission denied" error (code 23) almost exclusively points to a mismatch between the permissions of the user executing the rsync command and the access rights on the target files or directories, especially on the destination side. The common underlying reasons include:

  1. Insufficient Write Permissions on Destination: The user account rsync is operating as (either local or remote via SSH) lacks the necessary write and/or execute permissions for the target directories on the destination system.
  2. Incorrect File/Directory Ownership on Destination: Files or directories on the destination are owned by a different user or group than the rsync user, preventing modification even if basic group or other permissions seem permissive.
  3. rsync Attribute Preservation Conflicts: When using options like --archive (-a), which implies --owner, --group, --perms, --times, --links, --devices, --specials, rsync attempts to preserve file attributes (owner, group, permissions) from the source to the destination. If the rsync user on the destination does not have the privileges to change ownership or set specific permissions (e.g., not root), these operations will fail.
  4. ACLs (Access Control Lists): POSIX ACLs can override standard Unix permissions, creating a more granular but potentially confusing permission structure. An ACL might be explicitly denying access even if standard chmod output appears to grant it.
  5. Filesystem Mount Options: The destination filesystem might be mounted with options that restrict write access or attribute modification (e.g., ro for read-only, noexec, nosuid, or specific uid/gid mappings for network filesystems like NFS/SMB).
  6. SELinux/AppArmor: While less common on a default Ubuntu setup specifically for rsync, security modules like AppArmor could be enforcing profiles that restrict rsync's ability to write to certain paths, though this would typically manifest with more specific AppArmor errors.

Step-by-Step Resolution

Follow these steps systematically to diagnose and resolve rsync permission issues.

1. Verify the rsync Command and User Context

First, ensure your rsync command syntax is correct and understand which user rsync is operating as on both the source and destination.

# Example remote rsync from local source to remote destination via SSH
rsync -avz --exclude='*.log' /var/www/mywebsite/ user@remote_host:/var/www/mywebsite/

# Example local rsync
rsync -avz /source/data/ /backup/data/
  • Remote rsync: The user@remote_host part specifies the user on the destination. rsync will connect via SSH as this user. All operations on the remote_host will be performed with this user's privileges.
  • Local rsync: The user running the rsync command on the terminal is the user rsync operates as.

Verify the exact paths. A common mistake is a trailing slash on the source. /source/dir/ copies the contents of dir. /source/dir copies dir itself into the destination.

2. Check Destination Directory Permissions and Ownership

This is the most frequent cause. Connect to the destination server (if remote) or check locally.

a. Identify the Target Path and User: Determine the exact path rsync is trying to write to (e.g., /var/www/mywebsite/ in the example) and the user it's running as (e.g., user).

b. Inspect Permissions and Ownership: Use ls -ld to check the permissions and ownership of the destination directory and its parent directories.

# On the destination host (or locally if local rsync)
ls -ld /var/www/mywebsite/
ls -ld /var/www/
ls -ld /var/

Look for output like: drwxr-xr-x 3 root www-data 4096 Sep 7 10:00 /var/www/mywebsite/

In this example, root owns the directory, and www-data is the group. A user like user would only have "other" permissions, which are r-x (read and execute, but not write).

c. Adjust Permissions and Ownership:

Be cautious when using chown -R and chmod -R on critical directories. Ensure you are targeting the correct path and applying appropriate permissions. Incorrect permissions can lead to security vulnerabilities or break applications.

  • Change Ownership: Grant the rsync user (e.g., user) ownership or add them to the group that owns the directory.

    # Option 1: Grant ownership to the rsync user
    sudo chown -R user:user /var/www/mywebsite/
    
    # Option 2: Add rsync user to the existing group (e.g., www-data) and ensure group has write access
    sudo usermod -aG www-data user
    # Then log out and back in for group changes to take effect, or run 'newgrp www-data'
    # And ensure the directory group has write permissions (see chmod below)
    
  • Change Permissions: Grant write access to the rsync user or group.

    # Option 1: Give owner (user) full read/write/execute, group read/execute, others read/execute
    sudo chmod -R u+rwX,go+rX /var/www/mywebsite/
    
    # Option 2: If the rsync user is part of the www-data group, give group write access
    sudo chmod -R u+rwX,g+rwX,o+rX /var/www/mywebsite/
    
    • The X in chmod automatically adds execute permission only if the item is a directory or already has execute permission for some user. This is generally safer than 777 or 775.

3. Adjust rsync Attribute Preservation Options

If you don't need to preserve ownership and group from the source, or if the rsync user doesn't have privileges to change them, tell rsync to skip those attribute transfers.

The -a (archive) option implies -rlptgoD (recursive, links, perms, times, group, owner, devices). If permission errors specifically mention chown or chgrp failures, you can override parts of -a.

# Exclude owner and group preservation
rsync -avz --no-owner --no-group /source/ user@remote:/destination/

# Exclude permissions preservation too (use with caution, destination will retain its default permissions)
rsync -avz --no-owner --no-group --no-perms /source/ user@remote:/destination/

While --no-owner, --no-group, and --no-perms can resolve errors, they mean the destination files might not have the same ownership or permissions as the source. This can be problematic for web server environments (e.g., Nginx serving files not owned by www-data).

4. Investigate Access Control Lists (ACLs)

ACLs provide a more flexible permission system than standard Unix permissions. They can sometimes block access even if ls -l suggests otherwise.

a. Check for ACLs: Use getfacl to see if ACLs are set on the destination directory:

getfacl /var/www/mywebsite/

If ACLs are present, you'll see lines starting with user:, group:, or mask:.

b. Modify or Remove ACLs: If an ACL is explicitly denying access, you can modify it. For example, to grant user full access:

sudo setfacl -m u:user:rwx /var/www/mywebsite/
# Or to recursively apply:
sudo setfacl -Rm u:user:rwx /var/www/mywebsite/

To remove all ACLs from a directory and its contents:

# Remove default and effective ACLs for a directory
sudo setfacl -b /var/www/mywebsite/
# Recursively remove ACLs from files and directories within
sudo setfacl -Rb /var/www/mywebsite/

Modifying ACLs requires understanding. Always back up your configuration or test changes in a non-production environment first.

5. Verify Filesystem Mount Options

Ensure the filesystem where rsync is writing supports file ownership and permissions, and is not mounted read-only.

df -hT /var/www/mywebsite/
cat /etc/fstab

Look for ro (read-only) mount options or issues with network filesystem (NFS/CIFS) mounts that don't correctly map user IDs. If ro is found in /etc/fstab or mount options, you might need to remount the filesystem as rw.

# Example to remount a partition
sudo mount -o remount,rw /dev/sda1 /var/www

6. Run rsync with Elevated Privileges (Last Resort, with Caution)

If all else fails and you have a strong understanding of the implications, running rsync with sudo can bypass most permission issues by executing as root.

# Local rsync as root
sudo rsync -avz /source/data/ /backup/data/

# Remote rsync as root (this will prompt for root's password on remote_host)
sudo rsync -avz /source/ user@remote_host:/destination/ # This will still connect as 'user' but 'sudo' applies locally on source
# To run as root on destination, you typically SSH as root directly or use 'sudo' within the remote command:
rsync -avz /source/ root@remote_host:/destination/
# Or use --rsync-path:
rsync -avz /source/ user@remote_host:/destination/ --rsync-path="sudo rsync"

Running rsync as root (either directly or via sudo) gives it full control over the system. Incorrect source/destination paths can lead to data loss or system instability. Use this only when absolutely necessary and verify your paths meticulously.

If you must run as root, consider using the --chown option to set the correct ownership on the destination files immediately after transfer:

# Transfer as root, but ensure files are owned by www-data on destination
sudo rsync -avz --chown=www-data:www-data /var/www/mywebsite/ root@remote_host:/var/www/mywebsite/

By methodically working through these steps, you should be able to identify and resolve the permission issues preventing your rsync transfers on Ubuntu 20.04 LTS. Always prioritize using the least privileged user necessary to accomplish the task for enhanced security.

👨‍💻

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.