Rsync Code 12 errors on Ubuntu VPS via Windows Terminal typically stem from permission mismatches, missing destination directories, or SSH configuration conflicts rather than network failures. This specific exit code indicates that the remote shell exited with an error during the transfer process. By verifying user permissions, ensuring target paths exist, and adjusting SSH command-line flags, you can resolve the issue and restore reliable file synchronization between your local Windows environment and the remote server.
Understanding Rsync Exit Code 12
The exit status
12 in Rsync is distinct from network timeouts (Code 30+) or authentication failures (Code 14). It specifically means that the remote shell command failed to execute properly. When you run Rsync over SSH, it essentially executes a command like
rsync --server ... on the remote host. If the remote system cannot start this daemon, or if the user context lacks necessary privileges, the connection drops immediately with Code 12. Common triggers include incorrect path syntax, insufficient write permissions on the destination directory, or interference from SSH wrapper scripts.
Verifying Destination Permissions and Paths
The most frequent cause of Code 12 is attempting to write to a directory where the connecting user does not have write access. Before running the sync command, log into your Ubuntu VPS via SSH and check the ownership of the target folder. Use the
ls -ld /path/to/destination command to view the current permissions. If the output shows that the directory is owned by
root or another user, your non-root SSH session will fail silently during the Rsync handshake.
To fix this, you must either change the ownership using
sudo chown -R $USER:$USER /path/to/destination or adjust permissions with
chmod. Additionally, ensure that the destination path exists. Rsync does not create intermediate directories automatically unless explicitly told to do so. If you are syncing to
/var/www/html/new_folder and
new_folder does not exist, Rsync may fail depending on the version and flags used. Always verify the absolute path on the remote side matches exactly what you intend.
Setup SSH Connection with 3 Ubuntu Machines to Bypass a Firewall outlines foundational connectivity steps that ensure your SSH tunnel is stable before layering file transfer protocols on top. A stable SSH baseline reduces variables when diagnosing application-layer errors like Code 12.
Adjusting SSH Command-Line Flags
Windows Terminal often invokes SSH with different default behaviors than traditional PuTTY sessions, particularly regarding terminal allocation and escape characters. The presence of pseudo-terminal allocation can sometimes interfere with Rsync's ability to spawn its server process cleanly. You can mitigate this by adding the
-T flag to disable pseudo-terminal allocation in your SSH command. For example, use
ssh -T user@host as part of your Rsync call.
Another critical adjustment involves handling escape characters. If your SSH config includes options that alter how commands are parsed, Rsync might misinterpret its own arguments. Ensure that your
~/.ssh/config file on Windows does not contain aggressive compression or cipher settings that conflict with the Ubuntu server's expectations. Try stripping down your SSH invocation to bare essentials:
rsync -avz -e "ssh -T" source/ user@remote:/dest/. This isolates whether the issue is with Rsync itself or the underlying SSH transport layer.
Checking for Wrapper Scripts and Aliases
On many Linux distributions, including Ubuntu, administrators sometimes set up SSH wrapper scripts or aliases in
~/.bashrc or
/etc/profile to enforce security policies or logging. These scripts often check for interactive terminals and may exit prematurely if they detect a non-interactive session, which is exactly what Rsync uses. If you see unexpected behavior, check if any startup scripts print messages or require input.
You can test this by running a simple command via SSH:
ssh user@host echo "test". If this command hangs or produces unexpected output, a wrapper script is likely interfering. To bypass this, you can force Rsync to use a login shell explicitly by modifying the
-e option to
-e "ssh -t", though this re-enables the pseudo-terminal issue mentioned earlier. A more robust solution is to comment out non-essential lines in
.bashrc that are not guarded by
if [ -z "$PS1" ], ensuring they only run for interactive shells.
Can Ansible Reuse SSH Connection for Rsync? discusses advanced SSH multiplexing techniques that can improve performance, but also highlights how complex SSH configurations can introduce subtle failures. Reviewing these concepts helps in understanding how SSH handles multiple concurrent connections and session states.
Debugging with Verbose Output
When standard fixes fail, enable verbose debugging to pinpoint the exact moment of failure. Add the
-v flag multiple times to your Rsync command, such as
rsync -vvv. This increases the verbosity level, showing you the exact SSH command being executed and the response from the remote server. Look for lines indicating "sending incremental file list" followed immediately by an error. If the error occurs before any file listing appears, the issue is almost certainly related to authentication or remote shell execution.
You can also capture the SSH debug logs by adding
-vvv to the SSH command within the
-e option:
-e "ssh -vvv". This provides detailed information about key exchanges, channel openings, and any rejection reasons. Analyzing these logs often reveals missing public keys or rejected host keys that standard error messages hide.
Frequently Asked Questions
Why does Rsync work with SCP but fail with Rsync?
SCP operates as a single-file copy mechanism without spawning a persistent server daemon on the remote host. Rsync requires the remote system to execute an
rsync --server process, which demands specific permissions and shell availability. If your user account has limited shell access or restricted commands, SCP may succeed while Rsync fails with Code 12 due to the inability to launch the required daemon.
How do I fix permission denied errors in Rsync?
You must ensure the destination directory is writable by the user initiating the transfer. Use
sudo chown to change ownership to your SSH user or apply
chmod 755 to grant read and execute permissions, and
chmod 777 temporarily for testing write access. Avoid leaving directories world-writable in production environments; instead, use group permissions to manage access securely.
Does Windows Terminal handle SSH differently than PowerShell?
Windows Terminal acts as a container for various shells, including PowerShell and CMD. The difference lies in the underlying shell's environment variables and startup scripts. If you switch from PowerShell to CMD within Windows Terminal, the SSH command might behave differently due to varying PATH settings or alias definitions. Always test your Rsync command in the specific shell profile you intend to use for automation.
What causes Rsync to hang before displaying Code 12?
A hang usually indicates a network timeout or a firewall dropping packets after the initial handshake. Check if your VPS provider blocks high-port ranges used by Rsync's data transfer phase. Ensure that your SSH port (default 22) is open and that no intrusion detection systems are terminating long-running or repetitive connections. Verify connectivity using
ping and
telnet to rule out basic network issues.
Can I use Rsync over a non-standard SSH port?
Yes, you can specify a custom port using the
-e flag combined with SSH options. Use
-e "ssh -p 2222" to direct Rsync to connect through port 2222 instead of the default 22. Ensure that your Ubuntu VPS SSH daemon is configured to listen on that port in
/etc/ssh/sshd_config and that the service has been restarted to apply changes.