Linux & OS Intermediate

Resolving ‘rsync error: some files could not be transferred (code 23) permissions denied’ on Alpine Linux

Fix rsync permission denied (code 23) errors on Alpine Linux. Troubleshoot ownership, permissions, and immutable bits for successful file transfers.

👨‍💻
Senior Systems Architect • Verified in Staging Labs

Fix rsync permission denied (code 23) errors on Alpine Linux. Troubleshoot ownership, permissions, and immutable bits for successful file transfers.

rsync is a powerful and versatile utility for synchronizing files and directories, widely used in web hosting and DevOps for backups, deployments, and migrations. However, permission issues are a common hurdle, especially when dealing with different user contexts or specific operating system nuances like those found in Alpine Linux. This guide will walk you through diagnosing and resolving the notorious "some files could not be transferred (code 23) permissions denied" error when working with rsync on Alpine.

Symptom & Error Signature

When attempting to transfer files using rsync, the process might complete partially or fail entirely, reporting that certain files could not be transferred due to permission issues. You will typically see output similar to this in your terminal:

rsync -avzP --exclude 'cache/*' /source/path/ user@remote-alpine-host:/destination/path/
sending incremental file list
rsync: [sender] chgrp "/destination/path/some_directory/another_file" failed: Operation not permitted (1)
rsync: [sender] chown "/destination/path/some_directory/another_file" failed: Operation not permitted (1)
rsync: [sender] recv_generator: failed to stat "/destination/path/file_that_needs_transfer" (in destination/path): Permission denied (13)
rsync error: some files could not be transferred (code 23) at main.c(1828) [sender=3.2.7]
rsync: [receiver] mkstemp "/destination/path/.file_to_create.tmp" failed: Permission denied (13)
rsync: [receiver] mkstemp "/destination/path/.another_file.tmp" failed: Permission denied (13)
rsync error: some files could not be transferred (code 23) at main.c(1828) [receiver=3.2.7]

The key indicators are "Permission denied (13)", "Operation not permitted (1)", and rsync error: some files could not be transferred (code 23). Code 23 specifically indicates a partial transfer due to an error, often permission-related.

Root Cause Analysis

The "permission denied" error with rsync on Alpine Linux typically stems from the following underlying issues:

  1. Incorrect User Permissions on Destination: The user running the rsync command on the remote (destination) Alpine host does not have the necessary write, read, or execute permissions for the target directory or files. This is the most common cause. rsync often attempts to preserve file ownership and group (-o, -g options), which can also fail if the destination user lacks privileges to change these attributes.
  2. Insufficient Group Permissions on Destination: Similar to user permissions, if the target directory or files are owned by a group different from the rsync user's primary or secondary groups, and group write permissions are missing, the transfer will fail.
  3. ACLs (Access Control Lists) on Destination: While less common on a default Alpine installation, if ACLs have been explicitly configured, they can override standard UNIX permissions, restricting access for the rsync user.
  4. Immutable Bit Set on Destination Files/Directories: Files or directories marked with the immutable bit (chattr +i) cannot be modified, deleted, or renamed even by the root user. This is a strong security measure but can block rsync operations.
  5. NFS/SMB Share Permissions: If the rsync destination is a Network File System (NFS) or Samba (SMB/CIFS) mount, the share-level permissions configured on the server exporting the share might be restricting access, overriding local filesystem permissions. For example, root_squash in NFS exports can cause root users on the client to be treated as nobody, leading to permission issues.
  6. Destination Filesystem Read-Only: The target filesystem might be mounted as read-only, preventing any write operations. This can happen due to filesystem errors, administrative actions, or specific system configurations.
  7. Alpine's sudo / doas Configuration: Alpine Linux often uses doas instead of sudo by default, or neither might be fully configured for the rsync user, preventing privilege escalation when needed to manage permissions or ownership.

Step-by-Step Resolution

Follow these steps to diagnose and resolve the rsync permission issues on your Alpine Linux destination.

1. Verify Source and Destination Paths

Ensure that both your source and destination paths are correct and accessible. A simple ls -ld /path/to/directory on both ends can confirm their existence.

2. Identify the rsync User and Destination Ownership

Determine which user rsync is operating as on the remote (destination) Alpine host, and compare it with the ownership and permissions of the destination directory.

  1. Identify the rsync user on the remote host: The rsync command, when run via SSH (user@host:/path), will execute on the remote host as user. You can confirm this by running whoami when SSHed into the remote server.

    ssh user@remote-alpine-host 'whoami'
    

    If you're using a systemd service, cron job, or another automated method to run rsync, ensure you know which user that process runs as.

  2. Check permissions and ownership of the destination path on Alpine: Use ls -la on the parent directory of your rsync target to see the owner, group, and permissions.

    ssh user@remote-alpine-host 'ls -la /parent/of/destination/'
    

    Example output:

    drwxr-xr-x    3 root     root          4096 Sep 14 10:00 destination
    

    In this example, /parent/of/destination/destination is owned by root:root with rwxr-xr-x permissions. If your rsync user is someuser, they would not have write access here.

3. Adjust Destination Directory/File Permissions & Ownership

Based on the previous step, you'll likely need to grant the rsync user appropriate permissions on the destination Alpine server.

  1. Change Ownership: The safest and most common approach is to change the ownership of the destination directory (and its contents, recursively) to the user that rsync is running as.

    # Connect to your Alpine host via SSH
    ssh root@remote-alpine-host # Or user with sudo/doas privileges
    
    # Change ownership of the destination directory recursively
    chown -R rsync_user:rsync_group /destination/path/
    

    Alpine Linux uses doas by default for privilege escalation, not sudo. If sudo is not installed or configured, you might need to use doas or perform these actions as root. To install sudo: apk add sudo && setup-sudo. For doas configuration, edit /etc/doas.conf. This guide will use sudo for broader compatibility, but substitute doas where appropriate for Alpine.

  2. Adjust Permissions: Once ownership is correct, ensure the permissions allow writing. For directories, both read and execute (to traverse) are needed, plus write. For files, read and write.

    # Set appropriate permissions for the destination directory
    # For directories: rwx (7) for owner, rx (5) for group, rx (5) for others
    # For files: rw (6) for owner, r (4) for group, r (4) for others
    find /destination/path/ -type d -exec chmod rwxr-xr-x {} +
    find /destination/path/ -type f -exec chmod rw-r--r-- {} +
    
    # Alternatively, if you want full control for the owner and group, and read for others:
    chmod -R ug+rwX,o+rX /destination/path/
    

    Be careful with chmod -R 777 (world-writable). While it fixes permission errors, it creates a significant security vulnerability. Only use precise permissions.

4. Address Immutable Files (if present)

If specific files or directories still fail to transfer after adjusting ownership and standard permissions, they might have the immutable bit set.

  1. Check for Immutable Bit: Use lsattr to inspect file attributes.

    ssh user@remote-alpine-host 'lsattr -R /destination/path/'
    

    Look for lines containing i (immutable), e.g.:

    ----i--------e-- /destination/path/important_config.conf
    
  2. Remove Immutable Bit: Use chattr -i to remove the immutable attribute. You must be root to do this.

    ssh root@remote-alpine-host 'chattr -i /destination/path/important_config.conf'
    

    Removing the immutable bit (+i) should be done with caution, as it weakens the security of protected files. Re-add it after rsync if the file requires immutability: chattr +i /path/to/file.

5. Check Network Share Permissions (NFS/SMB)

If /destination/path/ is a mounted NFS or SMB share, the permissions issues might originate from the server exporting the share.

  1. NFS Shares: On the NFS server, inspect /etc/exports. If root_squash is present, it will map root users from clients to nobody:nogroup, often causing permission denied errors. Consider no_root_squash if rsync needs to preserve root ownership, but be aware of the security implications.

    Example /etc/exports entry:

    /data/share *(rw,sync,no_root_squash,no_subtree_check)
    

    After modifying /etc/exports, run exportfs -ra on the NFS server.

  2. SMB/CIFS Shares: On the Samba server, check smb.conf for force user, force group, create mask, directory mask, or user mapping settings that might restrict access.

6. Run rsync with Debugging and Verbosity

To gain more insight into why rsync is failing, use verbose and dry-run options.

  1. Dry Run: Use --dry-run (-n) to simulate the transfer without making any actual changes. This is invaluable for testing permission adjustments.

    rsync -avzP --dry-run --exclude 'cache/*' /source/path/ user@remote-alpine-host:/destination/path/
    
  2. Verbose Output: Add multiple -v flags for more detailed output (-vv or -vvv). This can sometimes reveal the exact file or directory causing the permission issue.

    rsync -avvP --exclude 'cache/*' /source/path/ user@remote-alpine-host:/destination/path/
    
  3. Log File: Direct rsync output to a log file for easier review, especially for long transfers.

    rsync -avzP --log-file=/var/log/rsync_error.log --exclude 'cache/*' /source/path/ user@remote-alpine-host:/destination/path/
    

7. Check Destination Filesystem Status

Confirm the destination filesystem is not mounted as read-only.

ssh user@remote-alpine-host 'mount | grep /destination/path'

Look for (ro) in the mount options. If found, remount the filesystem as read-write (e.g., sudo mount -o remount,rw /destination/path). Investigate why it was mounted read-only initially, as this often indicates underlying filesystem problems.

By systematically working through these steps, you should be able to identify and resolve the rsync permission denied errors on your Alpine Linux system, ensuring successful and reliable file synchronization.

👨‍💻

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.