Apache Subversion 配置参数详解
逐项详解 Apache Subversion 1.14 服务端与客户端配置参数,覆盖 svnserve.conf 五个通用参数、passwd 与 authz 授权文件、svnserve 启动参数、Apache dav_svn 指令、客户端 config/servers 默认值与凭据缓存,并给出生产模板与生效验证回显,全部实测。
Apache Subversion 配置参数详解
目标:逐项讲清 Apache Subversion 1.14 的配置体系——svnserve 模式的 svnserve.conf/passwd/authz 与服务启动参数、Apache WebDAV 模式的 dav_svn 指令、客户端 ~/.subversion 的 config/servers 默认值——每项参数给出默认值、修改方式与实测生效验证。以下内容均在 Ubuntu 22.04.5 + Subversion 1.14.1 环境实测。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- Apache Subversion:1.14.1-3ubuntu0.22.04.1(apt)
- Apache HTTP Server:2.4.52-1ubuntu4.24(WebDAV 模式)
- 版本库:/srv/svn/repo1(FSFS 格式)
- 服务形态:svnserve(systemd 单元 svnserve.service,监听 3690)+ Apache mod_dav_svn(监听 80)
- 演示账号:admin / root,密码 q1w2e3r4
二、前置条件
- 已按《Apache Subversion 安装指南》完成 subversion、subversion-tools 安装,且至少启用 svnserve 或 Apache dav_svn 之一。
- 已存在一个版本库(本文以 /srv/svn/repo1 为例)。
- root 权限;修改服务端配置后需要重启对应服务(见第三节)。
三、参数查看与修改方式
3.1 配置参数分布
| 层级 | 文件/位置 | 生效范围 |
|---|---|---|
| 版本库服务参数 | <版本库>/conf/svnserve.conf | 仅该版本库的 svnserve 访问行为 |
| 用户口令 | <版本库>/conf/passwd(或 password-db 指向的文件) | svnserve 认证 |
| 路径授权 | <版本库>/conf/authz(或 authz-db 指向的文件;WebDAV 模式为 AuthzSVNAccessFile) | svn:// 与 http:// 共用格式 |
| svnserve 进程 | systemd 单元 ExecStart(或命令行) | 监听地址/端口/根目录等 |
| Apache 指令 | /etc/apache2/mods-enabled/dav_svn.conf | 全部 WebDAV 访问 |
| 客户端全局 | /etc/subversion/config、/etc/subversion/servers | 本机所有用户的 svn 客户端 |
| 客户端个人 | 当前用户 svn 客户端 | |
| 凭据缓存 | ~/.subversion/auth/(目录树) | 已保存的用户名口令 |
查看各文件默认内容的方法(默认文件几乎全为注释,注释里就是参数说明):
grep -vE "^#|^$" /srv/svn/repo1/conf/svnserve.conf # 查看生效行
grep -E "^# ?(store-passwords|store-auth-creds)" /etc/subversion/config
3.2 修改与生效方式
- svnserve 模式:改 conf 文件后执行
systemctl restart svnserve(svnserve 无 reload 机制,进程读取的是启动时与每次连接时的库内配置,改进程参数必须重启)。 - Apache WebDAV 模式:改 dav_svn.conf 后先
apachectl configtest校验,再systemctl restart apache2。 - 客户端参数:直接编辑 config/servers,下一条 svn 命令即生效,无需重启任何进程。
- 授权正确性可离线校验:
svnauthz accessof --username admin --path / /etc/svn/authz,实测回显rw。
四、参数总览
| 参数 | 所在位置 | 默认值 | 作用 |
|---|---|---|---|
| anon-access | svnserve.conf [general] | read | 匿名用户访问级别 |
| auth-access | svnserve.conf [general] | write | 认证用户访问级别 |
| password-db | svnserve.conf [general] | passwd | 用户口令文件 |
| authz-db | svnserve.conf [general] | 未启用 | 路径授权文件 |
| realm | svnserve.conf [general] | 未启用 | 认证域名称(凭据缓存关联键) |
| -r/--root | svnserve 启动参数 | 未限制 | 服务根目录,URL 里相对此路径 |
| --listen-port | svnserve 启动参数 | 3690 | 监听端口 |
| --listen-host | svnserve 启动参数 | 所有地址 | 监听地址 |
| -c/--compression | svnserve 启动参数 | 5 | 网络传输压缩级别 0-9 |
| -M/--memory-cache-size | svnserve 启动参数 | 16(MB) | FSFS 内存缓存大小 |
| DAV svn | dav_svn.conf | 必写 | 声明该 Location 为 SVN 服务 |
| SVNPath / SVNParentPath | dav_svn.conf | 二选一 | 单库路径 / 多库父目录 |
| AuthUserFile | dav_svn.conf | 无 | htpasswd 口令文件 |
| AuthzSVNAccessFile | dav_svn.conf | 无 | 路径级授权文件 |
| Require valid-user | dav_svn.conf | 无 | 强制认证 |
| store-passwords | config | no | 是否明文缓存口令 |
| store-auth-creds | config | no | 是否缓存认证凭据 |
| http-timeout | servers | 60(秒) | HTTP 请求超时 |
| http-compression | servers | auto | HTTP 传输压缩 |
五、核心参数分类详解
5.1 svnserve.conf 通用段([general])
本机实测生效配置(anon-access 关闭匿名、启用口令文件与授权文件):
[general]
anon-access = none
auth-access = write
password-db = passwd
authz-db = authz
realm = repo1
逐项说明:
| 参数 | 取值 | 默认 | 实测行为 |
|---|---|---|---|
| anon-access | none / read / write | read | 设为 none 后,不带凭据的检出立刻被拒:svn: E170001: Can't get username or password(实测回显) |
| auth-access | none / read / write | write | 认证后的最大权限;生产建议 write 并配合 authz-db 收敛 |
| password-db | 文件名 | passwd | 相对路径相对本文件所在 conf 目录;也可写绝对路径让多库共用一份 |
| authz-db | 文件名 | 未启用 | 启用后进入路径级授权(见 5.2);未启用时只按 auth-access 控制整体读写 |
| realm | 字符串 | 未启用 | 客户端凭据缓存按 realm 归档;svn auth 实测显示 Authentication realm: <svn://127.0.0.1:3690> repo1 |
💡 多库共用账号的惯用做法:password-db、authz-db 写绝对路径指向同一份文件(如 /srv/svn/passwd、/srv/svn/authz),realm 保持每库唯一。
5.2 passwd 与 authz 文件
passwd 文件([users] 段一行一个 用户 = 口令,实测内容):
[users]
admin = q1w2e3r4
authz 文件(分组 + 路径段,实测内容):
[groups]
dev = admin
[/]
@dev = rw
* =
语法要点:
[/]是相对 svnserve-r根目录(或 SVNParentPath)的路径;单库(SVNPath / realm 内)也支持[repo1:/]形式以库名开头,实测两种写法并存有效。@dev引用 [groups] 里定义的组;admin直接引用用户;*匹配所有用户(含匿名)。- 权限只有
r、rw、空(无权限)三档;空值可显式写* =。 - 校验命令与实测回显:
# svnauthz accessof --username admin --path / /srv/svn/authz
rw
⚠️ authz 按"最长匹配路径优先"取规则;
[/]的规则不会向下累加合并,务必在每一段里写全所需权限。
5.3 svnserve 服务启动参数
本机 systemd 单元实测内容:
[Unit]
Description=Subversion protocol daemon (svnserve)
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/svnserve --daemon --foreground --root /srv/svn
Restart=on-failure
User=svn
Group=svn
[Install]
WantedBy=multi-user.target
常用参数(取自 svnserve --help 实测输出,默认值均来自其标注):
| 参数 | 默认值 | 说明 |
|---|---|---|
| -d [--daemon] | - | 守护进程模式 |
| --foreground | - | 前台运行,配合 systemd Type=simple 必用(与 -d 同用时前台生效) |
| -r [--root] ARG | 未限制 | 对外暴露的根目录;设 /srv/svn 后 URL 为 svn://host/repo1,未设则需带全路径 |
| --listen-port ARG | 3690 | 监听端口 |
| --listen-host ARG | 所有地址 | 监听指定 IP 或主机名 |
| -R [--read-only] | 关闭 | 强制整体只读,覆盖库内配置 |
| --config-file ARG | - | 集中指定 svnserve.conf(可指向库外公共文件) |
| -c [--compression] ARG | 5 | 传输压缩级别 0-9 |
| -M [--memory-cache-size] ARG | 16(MB) | FSFS/FSX 内存缓存,0 为动态大小 |
生效验证(systemctl status 与端口):
# systemctl status svnserve --no-pager -l
● svnserve.service - Subversion protocol daemon (svnserve)
Loaded: loaded (/etc/systemd/system/svnserve.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2026-10-12 00:47:42 UTC; 1s ago
Main PID: 4026 (svnserve)
Tasks: 1 (limit: 5753)
Memory: 1.0M
CPU: 6ms
CGroup: /system.slice/svnserve.service
└─4026 /usr/bin/svnserve --daemon --foreground --root /srv/svn
# netstat -tlnp | grep 3690
tcp 0 0 0.0.0.0:3690 0.0.0.0:* LISTEN 4026/svnserve
5.4 Apache dav_svn 指令
本机 /etc/apache2/mods-enabled/dav_svn.conf 实测生效内容:
<Location /svn>
DAV svn
SVNParentPath /srv/svn
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/svn/svn.htpasswd
AuthzSVNAccessFile /etc/svn/authz
Require valid-user
</Location>
逐项说明:
| 指令 | 说明 | 实测行为 |
|---|---|---|
| DAV svn | 声明 Location 由 mod_dav_svn 处理 | 缺失时 /svn 被当作普通路径 404 |
| SVNParentPath /srv/svn | 多库父目录,URL 为 http://host/svn/<库名> | curl 认证后返回库列表 HTML 索引;与 SVNPath 二选一 |
| SVNPath /srv/svn/repo1 | 单库模式,URL 直接映射该库 | 单库部署时用,URL 不再含库名 |
| AuthType Basic + AuthName | Basic 认证与提示域 | 401 响应实测携带 WWW-Authenticate: Basic realm="Subversion Repository" |
| AuthUserFile /etc/svn/svn.htpasswd | htpasswd 生成的口令文件 | 生成命令 htpasswd -cb /etc/svn/svn.htpasswd admin q1w2e3r4 |
| AuthzSVNAccessFile /etc/svn/authz | 启用 mod_authz_svn 路径级授权 | 文件格式与 5.2 相同,可跨库写 [repo1:/] 段 |
| Require valid-user | 所有请求强制认证 | 匿名请求实测 401 |
需要 Apache 以写权限访问版本库:Apache 运行用户为 www-data,将其加入版本库属主组并开组写权限(本机实测命令):
usermod -aG svn www-data
chown -R svn:svn /srv/svn/repo1
chmod -R g+rwX /srv/svn/repo1
配置修改后先校验再重启:
# apachectl configtest
Syntax OK
# systemctl restart apache2
💡 configtest 出现
AH00558: Could not reliably determine the server's fully qualified domain name时不影响功能,属全局 ServerName 未设置;写入 conf-available/servername.conf 并 a2enconf 后消除。
5.5 客户端参数(~/.subversion 与 /etc/subversion)
首次执行 svn 命令后,客户端会在用户家目录生成 ~/.subversion/(实测含 README.txt、auth、config、servers 四项)。系统级默认文件在 /etc/subversion/(config、servers),全部参数以注释形式提供默认值,实测默认值:
# grep -E "^# ?(password-stores|store-passwords|store-auth-creds)" /etc/subversion/config
# password-stores = gpg-agent,gnome-keyring,kwallet
# store-passwords = no
# store-auth-creds = no
# grep -E "^# ?(http-timeout|http-compression)" /etc/subversion/servers
# http-timeout = 60
# http-compression = auto
常用客户端参数:
| 参数 | 文件 | 默认值 | 说明 |
|---|---|---|---|
| store-auth-creds | config | no | 是否把用户名/口令缓存到 ~/.subversion/auth |
| store-passwords | config | no | 配合 store-auth-creds 控制口令是否明文落盘 |
| password-stores | config | gpg-agent,gnome-keyring,kwallet | 凭据存储后端列表 |
| http-timeout | servers | 60(秒) | HTTP 类访问超时 |
| http-compression | servers | auto | 是否压缩 HTTP 传输 |
查看与清理已缓存凭据的实测回显:
# svn auth --username admin --password q1w2e3r4 --non-interactive
------------------------------------------------------------------------
Credential kind: svn.simple
Authentication realm: <http://127.0.0.1:80> Subversion Repository
Username: admin
------------------------------------------------------------------------
Credential kind: svn.simple
Authentication realm: <svn://127.0.0.1:3690> repo1
Username: admin
💡 realm 与 URL 共同决定缓存条目归属:svnserve 模式 realm 改名后旧缓存即失配,客户端会重新索要账号,这也是排障时"强制重新认证"的常用手段。
六、生产配置模板
6.1 svnserve 模式模板(适用:4 核 8GB 内存、千兆内网、10-50 人团队、库总量 100GB 以内)
# /srv/svn/repo1/conf/svnserve.conf
[general]
anon-access = none
auth-access = write
password-db = /srv/svn/passwd
authz-db = /srv/svn/authz
realm = repo1
# /srv/svn/passwd(多库共用)
[users]
admin = q1w2e3r4
# /srv/svn/authz(多库共用)
[groups]
dev = admin
[/]
@dev = rw
* =
[repo1:/trunk]
@dev = rw
# /etc/systemd/system/svnserve.service 的 [Service] 关键行
ExecStart=/usr/bin/svnserve --daemon --foreground --root /srv/svn --listen-host 0.0.0.0 --listen-port 3690 -M 64
Restart=on-failure
User=svn
Group=svn
模板说明:账号文件集中到 /srv/svn 便于多库共用;-M 64 把 FSFS 缓存从默认 16MB 提到 64MB,适配 8GB 内存下多库并发;生产务必保留 anon-access = none。
6.2 Apache WebDAV 模板(适用:需要浏览器浏览、HTTPS 与 LDAP/统一账号体系接入的场景)
<Location /svn>
DAV svn
SVNParentPath /srv/svn
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/svn/svn.htpasswd
AuthzSVNAccessFile /etc/svn/authz
Require valid-user
</Location>
配套:htpasswd -cb /etc/svn/svn.htpasswd admin q1w2e3r4;authz 同 6.1;上线前 apachectl configtest 必须 Syntax OK,再 systemctl restart apache2。
七、常见问题(FAQ)
Q1:改了 svnserve.conf / passwd / authz 不生效?
svnserve 模式下口令与授权按连接读取,改动即对"新连接"生效,已建立的连接不受影响;而改了进程参数(--listen-port 等)必须 systemctl restart svnserve。验证办法:重新 checkout 一条新连接看是否要求认证。WebDAV 模式改 dav_svn.conf 后必须 restart apache2。
Q2:svn: E170001: Can't get username or password 与 E170001: Authentication error from server: Password incorrect 分别是什么问题?
前者是匿名访问被拒(anon-access = none 且未带凭据),后者是账号存在但口令错误(实测回显见安装指南第七章)。解决:前者补 --username admin --password q1w2e3r4,后者核对 passwd 文件或重置口令。
Q3:authz 配置后仍能访问不该访问的路径?
按最长匹配路径取规则,且 * 会覆盖匿名语义:[/] 段写了 @dev = rw 但没写 * = 时,其他用户继承的是 svnserve.conf 的 anon-access 默认 read,等于全库可读。解决:每段显式写 * =(无权限)或 * = r,并用 svnauthz accessof --username 某用户 --path /目标路径 /srv/svn/authz 逐条核验(实测该命令输出 rw 或空)。
Q4:WebDAV 模式 401 后输入正确账号仍反复要求认证?
常见原因:AuthUserFile 路径写错或 htpasswd 文件对 Apache 不可读;realm 值改动后客户端缓存的凭据失配。解决:ls -l 核对文件与属主,必要时删除客户端 ~/.subversion/auth 下对应条目(或用 svn auth 列出后清理)重试。
Q5:svnserve 监听正常但远程连不上?
排查顺序:netstat 确认 0.0.0.0:3690 监听(实测回显见 5.3)→ 服务器防火墙放行 3690/tcp → --listen-host 是否误绑了内网地址 → authz 是否把来源用户写成了无权限(表现为连接成功但访问被拒,用 5.2 的 svnauthz accessof 核验)。
八、参考链接
- Apache Subversion 官方站点:http://subversion.apache.org/
- 官方文档(Version Control with Subversion,服务器配置章节):http://svnbook.red-bean.com/
- svnserve 与 mod_dav_svn 部署对比:http://svnbook.red-bean.com/nightly/en/svn.serverconfig.html
- Ubuntu 软件包信息:https://packages.ubuntu.com/jammy/subversion