How to Synchronize a Static Site from Windows to a Linux Server

A guide to using rsync for file sync and permission management when setting up a website

Imagine that you are running a static site. In most cases, you would build the site locally on Windows rather than setting up a full toolchain on the server. In this setup, synchronizing files between your local machine and the server becomes the main concern.

The first tool that comes to mind is usually scp, since it is available out of the box with ssh. It is easy to use and the command is simple. For example:

1
scp -r public/* user@yourdomain:/var/www/yoursite/

However, this approach has several drawbacks, so I do not recommend using it.

First, scp essentially perform a full copy every time, rather than true synchronization. It cannot remove obsolete files and is relatively inefficient.

In addition, permission control is quite limited. If you just simply run the command above, you may get this:

1
2
3
4
5
6
7
8
9
web@light-ecs:~/site$ ll
total 116
drwx---r-x 16 web web  4096 Mar 29 02:11 .
drwxrwxr-x  3 web web  4096 Mar 29 02:11 ..
-rw-rw-r--  1 web web 13550 Mar 29 02:11 404.html
drwx---rwx  2 web web  4096 Mar 29 02:11 archives
drwx---rwx  4 web web  4096 Mar 29 02:11 categories
drwx---rwx 10 web web  4096 Mar 29 02:11 en
...

Clearly, this is not the desired result. As far as I know, a better practice is to have a dedicated user (e.g. web here) manage the site with read and write permissions, while the web server user (e.g. www-data) has read-only access, and zero access from other users.

rsync is the solution. However, since rsync is a Linux tool, some additional setup is required to use it on Windows.

Remote Setup

Suppose that the users are web and www-data. First, add the user web to the www-data group to avoid permission issues related to group ownership.

1
sudo usermod -aG www-data web

Then set the owner and mode for the site directory:

1
2
3
4
web@light-ecs:/var/www$ sudo mkdir yoursite
web@light-ecs:/var/www$ sudo chown web:www-data yoursite
web@light-ecs:/var/www$ sudo chmod 750 yoursite
web@light-ecs:/var/www$ sudo chmod g+s yoursite

The g+s (setgid) bit ensures that new files and directories inherit the parent directory’s group instead of the creator’s default group. This step is optional but recommended.

Once the remote server setup is complete, you can choose one of the following methods to use rsync.

Choice 1: Install cwRsync

Download cwRsync on Github and unzip it somewhere. Then the sync script can be written as:

1
2
3
4
5
6
7
8
9
$RsyncPath = "path\to\cwrsync_6.4.7_x64_free\bin\rsync.exe"
$SSHPath = "path\to\cwrsync_6.4.7_x64_free\bin\ssh.exe"
$LocalDir = "//?/path/to/your/page/"

& $RsyncPath -avz `
-e "$SSHPath" --delete `
--chmod=D2750,F640 `
$LocalDir `
user@yourdomain:/var/www/yoursite/

For some reason, you must specify the ssh.exe it should use explicitly. Additionally, the LocalDir must be an absolute path with the Windows-specific //?/ path prefix otherwise it may be interpreted as a remote host.

Choice 2: Using WSL

Using WSL is simpler and more convenient, so I recommend this method.

Make sure WSL is installed on your system. Then the sync script can be written as:

1
2
3
4
5
wsl rsync -avz `
--delete `
--chmod=D2750,F640 `
./public/ `
user@yourdomain:/var/www/yoursite/

As a non-native English speaker, I used AI tools to help refine the language.

comments powered by Disqus