Windows 下部署使用 Rsync

🪟 Windows Rsync 部署方案

适用于 windows 部署 rsync ssh 模式 方案。


一、软件安装

✅ 注意:

  • 服务器需要安装 OpenSSH + cwRsync Client
  • 客户端只需要安装 cwRsync Client

1. 安装 OpenSSH(服务器)

前往 GitHub 下载 OpenSSH 安装程序:

🔗 https://github.com/PowerShell/Win32-OpenSSH/releases

安装后,在 PowerShell 中启动 SSH 服务:

1
Start-Service sshd

验证是否成功:

1
ssh

2. 安装 cwRsync Client(客户端 & 服务器)

下载地址:
🔗 cwRsync v6.4.2 x64 免费版

  • 解压后将 bin 目录添加到环境变量
  • 将其路径置于 Path 变量最前方,避免误调用其他 SSH 客户端

二、生成密钥对并配置免密登录

1. 在客户端生成密钥对

1
2
cd C:\Users\xxx\Downloads\cwrsync_6.4.2_x64_free\bin
ssh-keygen -t rsa -b 2048 -C "用户名@机器名"

按提示一路回车,默认路径为:

  • 私钥:C:\Users\xxx\.ssh\id_rsa
  • 公钥:C:\Users\xxx\.ssh\id_rsa.pub

2. 将公钥传到服务器

2.1 如果服务器不存在.ssh目录及authorized_keys,请先进行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 以管理员身份运行powershell,依次执行以下命令:

# 创建用户主目录下的 .ssh 目录:
mkdir C:\Users\用户名\.ssh

# 设置适当的权限(确保目录安全):
icacls C:\Users\用户名\.ssh /inheritance:r
icacls C:\Users\用户名\.ssh /grant:r "用户名:(OI)(CI)F"

# 创建授权密钥文件:
New-Item -Path C:\Users\用户名\.ssh\authorized_keys -ItemType File

# 设置授权密钥文件的权限:
icacls C:\Users\用户名\.ssh\authorized_keys /inheritance:r
icacls C:\Users\用户名\.ssh\authorized_keys /grant:r "用户名:F"

2.2 在服务器主机中操作:

  • 编辑文件:C:\Users\xxx\.ssh\authorized_keys
  • id_rsa.pub 的内容复制到此文件中
  • 设置权限:(如果已经是禁用继承状态,先执行启用,再执行以下禁用操作)
    1
    2
    3
    4
    5
    # GUI操作
    文件属性 → 安全 → 高级 → 禁用继承 → 转换为显式权限

    # powershell命令,禁用继承并转换为显式权限
    icacls C:\Users\用户名\.ssh\authorized_keys /inheritance:d

3. 配置 SSH 免密码登录

编辑服务器配置文件 C:\ProgramData\ssh\sshd_config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#  启用 SSH 的公钥认证
PubkeyAuthentication yes

# 指定服务器上存储用户授权公钥的文件路径
AuthorizedKeysFile .ssh/authorized_keys

# 禁用 SSH 的密码认证
PasswordAuthentication no

# 注释掉管理员匹配设置
#Match Group administrators
# AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

# 限定用户操作(可选)
Match User rsyncuser
# 限定用户活动目录
ChrootDirectory C:\RsyncData
# 禁用 TCP 转发
AllowTcpForwarding no
# 禁用 X11 转发
X11Forwarding no

4. 重启 SSH 服务

1
2
3
4
5
# GUI 操作
右键「此电脑」→ 管理 → 服务 → 找到 OpenSSH Server → 重启

# 或者 powershell 管理员操作
Restart-Service sshd

5. 测试连接

在客户端命令行中:

1
ssh 用户名@主机IP

若成功登录则表示免密 SSH 配置成功 ✅

三、测试使用

在客户端命令行中:

1
2
# 将客户机 D:\test 目录下文件,上传至服务器 C:\Users\xxx\test 目录
rsync -avz --partial --progress -e "ssh" /cygdrive/d/test xxx@IP:"/cygdrive/c/Users/xxx/test"

四、如何创建新用户

以下脚本需保存为后缀为ps1的脚本文件,编码格式为UTF-8-BOM

新版powershell脚本,版本大于PowerShell 5.1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

# ========================= 个性化设置项 ===================================
$username = "rsyncuser"
$password = "userpassword" # 你的明文密码
$sshpubkey = "您的公钥内容" # 公钥内容
$rsyncdatadir = "C:\RsyncData" # rsync上传目录

# ========================= 创建用户 ===================================
New-LocalUser -Name $username -Description "Restricted rsync user" -NoPassword
Set-LocalUser -Name $username -PasswordNeverExpires $true

# $Password = Read-Host -AsSecureString
# Set-LocalUser -Name "rsyncuser" -Password $Password
$SecurePassword = ConvertTo-SecureString $password -AsPlainText -Force
Set-LocalUser -Name $username -Password $SecurePassword

# 建完用户后,用触发一次登录,用于生成用户个人目录(Profile目录)
# 定义用户名和密码

# 转换为SecureString
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
# 创建Credential对象
$credential = New-Object System.Management.Automation.PSCredential ($username, $securePassword)
# 使用Start-Process以指定身份运行cmd.exe,静默生成
Start-Process "cmd.exe" -ArgumentList "/c exit" -Credential $credential -WindowStyle Hidden

# ========================= 创建ssh目录及公钥文件 ===================================
# 为rsyncuser创建.ssh目录
$sshDir = "C:\Users\$username\.ssh"
if (!(Test-Path $sshDir)) {
New-Item -Path $sshDir -ItemType Directory
}

# 创建authorized_keys文件(如果您已经有公钥内容,直接写入该文件)
$authorizedKeysFile = "$sshDir\authorized_keys"
Set-Content -Path $authorizedKeysFile -Value $sshpubkey

# 设置.ssh目录权限
$acl = Get-Acl $sshDir
$acl.SetAccessRuleProtection($true, $false) # 禁用继承
# 只添加必要的权限
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($username, "FullControl", "Allow")
$acl.SetAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators", "FullControl", "Allow")
$acl.AddAccessRule($rule)
Set-Acl $sshDir $acl

# 设置authorized_keys文件权限
$acl = Get-Acl $authorizedKeysFile
$acl.SetAccessRuleProtection($true, $false) # 禁用继承
# 只添加必要的权限
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($username, "Read", "Allow")
$acl.SetAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators", "FullControl", "Allow")
$acl.AddAccessRule($rule)
Set-Acl $authorizedKeysFile $acl

# ========================= 创建专用目录 ===================================
# 如果专用同步目录不存在,则创建
if (-not (Test-Path -Path $rsyncdatadir)) {
New-Item -Path $rsyncdatadir -ItemType Directory -Force
}
# New-Item -Path $rsyncdatadir -ItemType Directory

$Acl = Get-Acl -Path $rsyncdatadir
$Permission = $username,"Modify","Allow"
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $Permission
$Acl.SetAccessRule($AccessRule)
Set-Acl -Path $rsyncdatadir -AclObject $Acl


# ========================= (可选)禁止 C:\ 根目录 写入 ===================================
# 禁止写入(写数据、添加目录、删除子项)
icacls C:\ /deny "$($username):(WD,AD,DC)"

# 允许读取和遍历 C:\
icacls C:\ /grant:r "$($username):(RX)"

旧版powershell脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

# ========================= 个性化设置项 ===================================
$userName = "rsyncuser"
$passwordPlainText = "YourStrongPasswordHere" # 你的明文密码
$sshPubKey = "您的公钥内容" # 公钥内容
$rsyncDataDir = "C:\RsyncData" # rsync上传目录

Write-Host "===== 检查 rsyncuser 用户是否存在 ====="

# 1. 检查 rsyncuser 是否存在
# 转换明文密码为 SecureString
$securePassword = ConvertTo-SecureString $passwordPlainText -AsPlainText -Force
# 创建凭据对象
$credential = New-Object System.Management.Automation.PSCredential($userName, $securePassword)

$user = Get-WmiObject Win32_UserAccount -Filter "Name='$userName'"

if ($user -eq $null) {
Write-Host "用户不存在,正在创建用户:$userName"

# 创建用户
# net user $userName /add
net user "$userName" $passwordPlainText /add

# 设置密码
# $password = Read-Host "请输入 rsyncuser 的密码"
# $password = "YourStrongPasswordHere" # 在这里直接写入密码
# net user $userName $password

# 设置密码永不过期
wmic UserAccount where "Name='$userName'" set PasswordExpires=FALSE

Write-Host "用户创建成功:$userName"

# 静默登录一次以生成Profile目录
Write-Host "正在以 $userName 身份静默登录以生成用户目录..."
Start-Process -FilePath "cmd.exe" -ArgumentList "/c exit" -Credential $credential -WindowStyle Hidden -ErrorAction Stop
Write-Host "静默登录完成。"

} else {
Write-Host "用户已存在:$userName"
}

# 2. 创建 .ssh 目录
Write-Host "===== 创建 .ssh 目录和 authorized_keys 文件 ====="
$sshDir = "C:\Users\$userName\.ssh"
if (!(Test-Path -Path $sshDir)) {
Write-Host "创建目录:$sshDir"
New-Item -ItemType Directory -Path $sshDir -Force
} else {
Write-Host "目录已存在:$sshDir"
}

$authorizedKeysFile = Join-Path $sshDir "authorized_keys"
if (!(Test-Path -Path $authorizedKeysFile)) {
Write-Host "创建文件:$authorizedKeysFile"
New-Item -ItemType File -Path $authorizedKeysFile -Force
# 写入你的公钥内容
Set-Content -Path $authorizedKeysFile -Value $sshPubKey
} else {
Write-Host "文件已存在:$authorizedKeysFile"
}

# 3. 设置 .ssh 目录权限
Write-Host "===== 设置 .ssh 目录权限 ====="
$acl = Get-Acl -Path $sshDir
$acl.SetAccessRuleProtection($true, $false)
$acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) }

$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList @(
$userName,
"FullControl",
"ContainerInherit,ObjectInherit",
"None",
"Allow"
)
$acl.AddAccessRule($rule)

$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList @(
"SYSTEM",
"FullControl",
"ContainerInherit,ObjectInherit",
"None",
"Allow"
)
$acl.AddAccessRule($rule)

$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList @(
"Administrators",
"FullControl",
"ContainerInherit,ObjectInherit",
"None",
"Allow"
)
$acl.AddAccessRule($rule)

Set-Acl -Path $sshDir -AclObject $acl

# 4. 设置 authorized_keys 文件权限
Write-Host "===== 设置 authorized_keys 文件权限 ====="
$acl = Get-Acl -Path $authorizedKeysFile
$acl.SetAccessRuleProtection($true, $false)
$acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) }

$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList @(
$userName,
"Read",
"None",
"None",
"Allow"
)
$acl.AddAccessRule($rule)

$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList @(
"SYSTEM",
"FullControl",
"None",
"None",
"Allow"
)
$acl.AddAccessRule($rule)

$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList @(
"Administrators",
"FullControl",
"None",
"None",
"Allow"
)
$acl.AddAccessRule($rule)

Set-Acl -Path $authorizedKeysFile -AclObject $acl

# 5. 创建 C:\RsyncData 目录
Write-Host "===== 创建 RsyncData 目录并设置权限 ====="
# $rsyncDataDir = "C:\RsyncData"
if (!(Test-Path -Path $rsyncDataDir)) {
Write-Host "创建目录:$rsyncDataDir"
New-Item -Path $rsyncDataDir -ItemType Directory -Force
} else {
Write-Host "目录已存在:$rsyncDataDir"
}

# 设置 RsyncData 目录权限
$Acl = Get-Acl -Path $rsyncDataDir
$Acl.SetAccessRuleProtection($true, $false)
$Acl.Access | ForEach-Object { $Acl.RemoveAccessRule($_) }

$AccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList @(
$userName,
"Modify",
"ContainerInherit,ObjectInherit",
"None",
"Allow"
)
$Acl.AddAccessRule($AccessRule)

Set-Acl -Path $rsyncDataDir -AclObject $Acl

Write-Host "===== 全部配置完成 ====="

Windows 下部署使用 Rsync
http://eevann.cn/2025/04/22/win-rsync/
作者
月下独白
发布于
2025年4月23日
许可协议