第 3 章 配置服务器

目录

3.1. 基于 Apache 的服务器
3.1.1. 简介
3.1.2. 安装 Apache
3.1.3. 安装 Subversion
3.1.4. 配置
3.1.5. 多版本库
3.1.6. 路径为基础的授权
3.1.7. 使用 Windows 域认证
3.1.8. 多重认证源
3.1.9. 用 SSL 使服务器更安全
3.2. 基于 svnserve 的服务器
3.2.1. 简介
3.2.2. 安装 svnserve
3.2.3. 运行 svnserve
3.2.3.1. 以服务形式运行 svnserve
3.2.4. svnserve 的认证
3.2.5. 使用 svn+ssh 认证
3.2.6. svnserve 以路径为基础的授权

为了使用TortoiseSVN(或任何其他Subversion客户端),你需要放置你的版本库,你可以将版本库存于本地并使用file://协议访问,也可以放置于服务器,使用http://svn://访问,这两种服务器协议也可以被加密,使用https://svn+ssh://。本章介绍了在Windows主机上设置一个服务器的步骤。

如果你没有一个服务器,或者你独自工作,本地版本库会是你的最佳选择,你可以跳过本章,直接到第 4 章 版本库

3.1. 基于 Apache 的服务器

3.1.1. 简介

所有可能的服务器当中,Apache为基础的服务器是最灵活的,尽管配置有一点复杂,但是提供了其他服务器没有的便利:

WebDAV

Apache为基础的Subversion服务器使用WebDAV协议,许多其他程序支持这个协议,你可以在Windows资源管理器中将这样的版本库装载为一个“网络文件夹”,就像访问文件系统的其他目录一样访问它。

浏览版本库

你可以将浏览器指向版本库的URL,无需安装Subversion客户端就可以浏览内容,这样可以扩大访问你数据的用户圈。

认证

你可以使用所有Apache支持的认证机制,包括SSPI和LDAP。

安全

因为Apache非常稳定和安全,你的版本库可以自动获得同样的安全性,包括SSL加密。

3.1.2. 安装 Apache

无论是Windows2000、WinXP+SP1还是Windows2003,在安装Apache之前需要做的第一件事。

[警告]警告

请注意,Windows XP如果没有安装SP1将会导致不正常的网络传输,从而搞坏你的版本库!

  1. 从Apache网站http://httpd.apache.org/download.cgi下载最新版本的Apache,请确定你下载的版本高于2.0.54-1.3.xx的版本不能工作!同样,低于2.0.54的版本不能与Subversion 1.2一起工作,因为Apache低于2.0.54的Windows版本的编译存在问题。

  2. 一旦你有了Apache2安装程序,你可以双击它,然后它会指导你的安装过程,请确认你输入的server的URL正确(如果你的服务器没有dns名称,请直接输入IP地址)。我建议安装Apache为所有用户,在80端口,作为一个服务。注意: 如果你已经有了IIS或其他监听80段口的程序,安装会失败,如果发生这种情况,直接到程序的安装目录\Apache Group\Apache2\conf,打开httpd.conf。编辑文件的Listen 80为其他可用的端口,例如Listen 81,然后重新启动-这样就不会那个问题了。

  3. 现在可以测试Apache服务器了,将浏览器指向http://localhost/-将会看到一个预先配置的网站。

[小心]小心

如果你决定将Apache安装为服务,缺省情况以本地系统帐户运行会发出警告,更安全的方法是为Apache创建一个单独的运行帐户。

请确认Apache运行的帐户是版本库目录的访问控制列表(右键目录|属性|安全)中一个明确的条目,对目录有完全的控制能力,否则,用户不能提交他们的修改。

即使Apache运行于本地系统,你仍然需要这个条目(这种情况下将是SYSTEM帐户)。

如果没有设置Apache的访问权限,你的用户会得到“拒绝访问(Access denied)”的错误信息,在Apache的错误日志中为错误500。

3.1.3. 安装 Subversion

  1. http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91下载最新版本的Subversion。

  2. 运行Subversion安装程序,并根据指导安装,如果Subversion认识到你安装了Apache,你就几乎完成了工作,如果它没有找到Apache服务器,你还有额外的步骤。

  3. 使用Windwos资源管理器,来到Subversion的安装目录(通常是c:\program files\Subversion),找到文件/httpd/mod_dav_svn.somod_authz_svn.so,复制这些文件到Apache的模块目录(通常是c:\program files\apache group\apache2\modules )。

  4. 从Subversion安装目录将/bin/libdb*.dll/bin/intl3_svn.dll复制到Apache的模块目录。

  5. 使用记事本之类的文本编辑器修改Apache的配置文件(通常是 C:\Program Files\Apache Group\Apache2\conf\httpd.conf),做出如下修改:

    去掉如下几行的注释(删除 '#'标记):

    #LoadModule dav_fs_module modules/mod_dav_fs.so
    #LoadModule dav_module modules/mod_dav.so

    将下面几行添加到LoadModule部分的最后。

    LoadModule dav_svn_module modules/mod_dav_svn.so
    LoadModule authz_svn_module modules/mod_authz_svn.so
    

3.1.4. 配置

现在你已经设置了Apache和Subversion,但是Apache不知道如何处理Subversion客户端,例如TortoiseSVN。为了让Apache知道哪个目录是用来作为Subversion版本库,你需要使用编辑器(例如记事本)编辑Apache的配置文件(通常是c:\program files\apache group\apache2\conf\httpd.conf):

  1. 在配置文件最后添加如下几行:

    <Location /svn>
    DAV svn
    SVNListParentPath on
    SVNParentPath D:\SVN
    #SVNIndexXSLT "/svnindex.xsl"
    AuthType Basic
    AuthName "Subversion repositories"
    AuthUserFile passwd
    #AuthzSVNAccessFile svnaccessfile
    Require valid-user
    </Location>
    

    这个配置告诉 Apache 你的所有 Subversion 版本库位于D:\SVN,版本库对外的URL是: http://MyServer/svn/ 。访问被文件passwd中的用户/密码限制。

  2. 为了创建passwd文件,再次打开命令行提示符(DOS),来到apache2目录(通常是c:\program files\apache group\apache2)通过输入下面的命令创建文件

    bin\htpasswd -c passwd <username>
    

    This will create a file with the name passwd which is used for authentication. Additional users can be added with

    bin\htpasswd passwd <username>
    
  3. 再次重启Apache服务。

  4. 将浏览器指向http://MyServer/svn/MyNewRepository(MyNewRepository是你此前创建的版本库名),如果一切正常,你会被提示输入用户名和密码,然后你会看到版本库的内容。

你刚才输入的解释是:

表 3.1. 设置 Apache 的 httpd.conf

设置解释
<Location /svn>意思是Subversion版本库的URL是http://MyServer/svn/
DAV svn告诉Apache是哪个模块响应那个URL的请求-此刻是Subversion模块。
SVNListParentPath on对于Subversion1.3或者更高版本,这个指示表示显示所有SVNParentPath下的版本库。
SVNParentPath D:\SVN告诉Subversion需要查看的版本库位于D:\SVN之下
SVNIndexXSLT "/svnindex.xsl"使用它可以在用浏览器浏览时更好看。
AuthType Basic激活基本认证,就是用户名/密码
AuthName "Subversion repositories"用来说明何时弹出要求用户输入认证信息的认证对话框
AuthUserFile passwd指定使用的认证密码文件
AuthzSVNAccessFile位置Subversion版本库的访问控制文件的路径
Require valid-user指定只有输入了正确的用户/密码的用户可以访问URL

但是那只是一个例子,对于Apache你有很多的选择。

  • 如果你希望所有人可以读你的版本库,但是只有特定用户可以写,你可以修改下面几行

    Require valid-user
    

    to

    <LimitExcept GET PROPFIND OPTIONS REPORT>
    Require valid-user
    </LimitExcept>
    
  • 使用passwd可以整体的控制对版本库的访问,但是如果你希望精确的控制版本库目录访问,你可以修改需要下面几行

    #AuthzSVNAccessFile svnaccessfile
    

    ,并且创建Subversion的访问控制文件。Apache将会确保只有有效的用户可以访问你的/svn目录,然后将用户名传递给Subversion的AuthzSVNAccessFile模块,这样就可以根据Subversion访问控制文件实现更细粒度的访问控制。请注意路径可以是repos:path或简单的path,如果你不指定特定的版本库,访问控制规则会应用到SVNParentPath下所有的版本库,使用的授权策略文件的格式将在第 3.1.6 节 “路径为基础的授权”描述。

  • 如果要使浏览器浏览仓库时更“漂亮”,请将下行去掉注释

    #SVNIndexXSLT "/svnindex.xsl"
    

    ,将文件 svnindex.xsl, svnindex.cssmenucheckout.ico 放到你的文档根目录中(通常是 C:/Program Files/Apache Group/Apache2/htdocs)。 这个目录在 Apache 配置文件中用 DocumentRoot 指示。

    你可以直接在我们的代码库http://tortoisesvn.tigris.org/svn/tortoisesvn/trunk/contrib/other/svnindex中拿到这三个文件。如果访问这个链接需要认证,输入用户名称 guest,无需密码。

    TortoiseSVN 版本库中的 xsl 文件有个特性:如果你用浏览器浏览版本库,那么每个版本库中的目录右边会有个图标。如果你点击此图标,那么 TortoiseSVN 会为此 URL 启动检出对话框。

3.1.5. 多版本库

如果你使用SVNParentPath指示,你就不必在每次添加新Subversion版本库时修改Apache的配置文件,只需要在第一个版本库所在的位置建立新的版本库就可以了。在我的公司,我可以使用SMB(普通的windows文件访问)直接访问服务器的文件夹,所以我直接在那里创建一个目录,运行TortoiseSVN命令TortoiseSVN在此创建版本库...,然后一个新的项目...

如果你使用Subversion 1.3或更高版本,可以使用SVNListParentPath on指示,这样当你使用浏览器访问父路径而不是具体某个版本库时就会显示所有版本库列表。

如果你的Subversion是早于1.3的版本,你会得到错误页,为了得到一个更好看的项目列表,你可以使用下面PHP脚本为你自动生成索引。(为了使用下面的PHP,你需要安装PHP)。

3.1.6. 路径为基础的授权

mod_authz_svn模块可以根据用户名和路径实现细粒度的权限控制,对所有的Apache服务器有效,在Subversion 1.3以上版本的svnserve上也实现了路径为基础的授权。

一个可能的例子:

[groups]
admin = john, kate
devteam1 = john, rachel, sally
devteam2 = kate, peter, mark
docs = bob, jane, mike
training = zak
# Default access rule for ALL repositories
# Everyone can read, admins can write, Dan German is excluded.
[/]
* = r
@admin = rw
dangerman =
# Allow developers complete access to their project repos
[proj1:/]
@devteam1 = rw
[proj2:/]
@devteam2 = rw
[bigproj:/]
@devteam1 = rw
@devteam2 = rw
trevor = rw
# Give the doc people write access to all the docs folders
[/trunk/doc]
@docs = rw
# Give trainees write access in the training repository only
[TrainingRepos:/]
@training = rw

请注意,检查每一条路径是一件消耗极大的操作,特别是修订版本日志,服务器会检查在每一个修订版本的每一条路径是否可读,对于影响很多文件的修订将会花费很多时间。

认证和授权是不同的过程,如果用户希望获得对版本库的访问,他需要同时实现这两个步骤,对于要访问文件的普通认证请求和授权请求。

3.1.7. 使用 Windows 域认证

你已经注意到了,你需要为每个用户在passwd文件中创建用户名/密码条目,如果(因为安全原因)他们希望周期性的修改他们的密码,你需要手动的做出修改。

但是对于此问题有另一个解决方案-至少是你在使用域控制器的LAN中访问版本库时: mod_auth_sspi!

最初的SSPI是由Syneapps提供的,包括源代码,但是此开发已经终止,不过不要失望,社区重新拾起代码并进行了改进,它现在的新主页在SourceForge

  • 下载这个模块,将文件mod_auth_sspi.so复制到Apache的modules目录。

  • 编辑Apache的配置文件: 增加行

    LoadModule sspi_auth_module modules/mod_auth_sspi.so
    

    to the LoadModule's section. Make sure you insert this line before the line

    LoadModule auth_module modules/mod_auth.so
    
  • 为了让 Subversion Location 使用此认证类型,你需要将这一行

    AuthType Basic
    

    修改为

    AuthType SSPI
    

    并且在 <Location /svn> 中增加

    SSPIAuth On
    SSPIAuthoritative On
    SSPIDomain <domaincontroller>
    SSPIOmitDomain on
    SSPIUsernameCase lower
    SSPIPerRequestAuth on
    SSPIOfferBasic On
    

    。 如果你没有域控制器,可以将域控制器的名称置为 <domaincontroller>。

请注意,当你使用SSPI认证时,没有必要使用AuthUserFile定义密码文件,Apache使用Windows域验证用户名和密码,你需要更新svnaccessfile中的用户列表来参考DOMAIN\username

[提示]提示

Subversion的AuthzSVNAccessFile文件对用户名大小写敏感(“JUser”与“juser”不同)。

在微软的世界,Windows域和用户名不是大小写敏感,即使如此,一些网络管理员还是喜欢创建首字母大写的用户帐号(例如“JUser”)。

使用SSPI的一个问题是用户名和密码是用户在提示输入时发送到Subversion的,而IE经常会不管你的帐户是如何建立的都会自动发送你的用户名。

结果就是你必须为每一个用户在AuthzSVNAccessFile创建至少两个条目--一个小写的条目和一个与IE传递给Apache一样的条目,你也需要训练你的用户在通过TortoiseSVN输入访问版本库的凭证时使用小写字母。

Apache的错误和访问日志是你最好解密朋友,例如帮助你检测传递给Subversion的AuthzSVNAccessFile模块的用户名,你或许需要试验svnaccessfile中用户串的精确格式(例如DOMAIN\user还是DOMAIN//user)来使一切工作正常。

[重要]SSL 和 IE

如果你使用SSL保护你的服务器,并使用windows域来进行认证,你会发现不能使用IE浏览版本库了,不需要担心-那只是因为IE没有经过认证,其他浏览器没有这个问题,TortoiseSVN和其他Subversion客户端仍然可以得到认证。

如果你一直希望使用IE浏览你的版本库,你可以选择:

  • 在Apache的配置文件定义一个单独的<Location /path>指示,添加SSPIBasicPreferred On,这将使IE重新能够认证,但是其他浏览器和Subversion不能对这个location经过认证。

  • 也提供未加密(没有SSL)认证的浏览,奇怪的IE在没有使用SSL的认证时没有任何问题。

  • 在SSL的“标准”设置,通常在apache的虚拟SSL主机有下面的内容:

    SetEnvIf User-Agent ".*MSIE.*" \
                 nokeepalive ssl-unclean-shutdown \
                 downgrade-1.0 force-response-1.0
    

    对这种设置有好的原因吗,见http://www.modssl.org/docs/2.8/ssl_faq.html#ToC49,但是如果你希望ntlm认证,你需要使用keepalive: http://www.microsoft.com/resources/documentation/WindowsServ/2003/standard/proddocs/en-us/qos_enablekeepalives.asp,如果你取消整个"SetEnvIf"的注释,你就可以使IE经过Win32上配置了mod_auth_sspi和SSL的认证。

3.1.8. 多重认证源

也可以为Subversion使用不止一个的认证源,为此,你需要将每一种认证设置为non-authoritative,这样Apache会在多个源检查用户名/密码。

一个常见的场景就是同时使用Windows域和passwd文件认证,这样你可以为没有Windows域帐户的用户提供访问SVN的权限。

  • 为了开启Windows域和密码文件认证,在Apache配置文件的<Location>中添加下面的条目:

    AuthAthoritative Off
    SSPIAuthoritative Off
    

下面是组合使用 Windows 域&passwd 文件认证的完整配置:

<Location /svn>
DAV svn
SVNListParentPath on
SVNParentPath D:\SVN

AuthName "Subversion repositories"
AuthzSVNAccessFile svnaccessfile.txt

# NT Domain Logins.
AuthType SSPI
SSPIAuth On
SSPIAuthoritative Off
SSPIDomain <domaincontroller>
SSPIOfferBasic On

# Htpasswd Logins.
AuthType Basic
AuthAuthoritative Off
AuthUserFile passwd

Require valid-user
</Location>

3.1.9. 用 SSL 使服务器更安全

Apache服务器缺省并不支持SSL,这是因为美国的出口限制,但是你可以从其他地方下载安装。

  1. 首先,你需要一些文件来开启SSL,你可以在http://hunter.campbus.com/找到这些包,只需要解压缩这些文件,然后将mod_ssl.so复制到Apache的modules目录,将文件openssl.exe复制到bin目录,将文件conf/ssl.conf复制到Apache的conf目录。

  2. 使用文本编辑器打开Apache的conf目录的ssl.conf

  3. 注释掉(使用#)下面几行:

    DocumentRoot "c:/apache/htdocs"
    ServerName www.example.com:443
    ServerAdmin [email protected]
    ErrorLog logs/error_log
    TransferLog logs/access_log
    
  4. 此行

    SSLCertificateFile conf/ssl.crt/server.crt
    

    改为

    SSLCertificateFile conf/ssl/my-server.cert
    

    此行

    SSLCertificateKeyFile conf/ssl.key/server.key
    

    改为

    SSLCertificateKeyFile conf/ssl/my-server.key
    

    此行

    SSLMutex  file:logs/ssl_mutex
    

    改为

    SSLMutex  default
    
  5. 删除此行

    <IfDefine SSL>
    

    and

    </IfDefine>
    
  6. 如果你想所有apache模块知道SSL能力,就将注册表键HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Apache2\ImagePath的值从"C:\Program Files\Apache Group\Apache2\bin\Apache.exe" -k runservice修改为 "C:\Program Files\Apache Group\Apache2\bin\Apache.exe" -D SSL -k runservice

    这会设置一个内部标记,当下次启动apache服务时,apache模块会读取它。

  7. 打开Apache配置文件(httpd.conf),并且去掉此行的注释

    #LoadModule ssl_module modules/mod_ssl.so
    
  8. Openssl需要一个配置文件,你可以从http://tud.at/programm/openssl.cnf下载一个正在使用的,请注意: *.cnf类型的文件尽管是普通的文本文件,Windows对这种文件会特别处理!

  9. 然后你需要创建一个SSL证书,为此打开一个命令行窗口,进入apache目录(例如C:\program files\apache group\apache2),然后输入下面的命令:

    bin\openssl req -config bin\openssl.cnf -new -out my-server.csr
    

    你会被讯问密语,请不要使用简单的单词,而是使用整段话,例如一段诗,越长越好。你也需要输入server的URL,其他所有问题都是可选的,但是我们建议你最好输入这些信息。

    通常会自动产生privkey.pem文件,但是如果没有,请输入下面的命令生成它:

    bin\openssl genrsa -out privkey.pem 2048
    

    然后输入这个命令

    bin\openssl rsa -in privkey.pem -out my-server.key
    

    并且输入(在同一行)

    bin\openssl x509 -in my-server.csr -out my-server.cert
                     -req -signkey my-server.key -days 4000
    

    这样会创建一个在4000天里过期的证书,最后输入:

    bin\openssl x509 -in my-server.cert -out my-server.der.crt -outform DER
    

    这些命令在Apache目录(my-server.der.crtmy-server.csrmy-server.key.rndprivkey.pemmy-server.cert)里创建了一些文件,复制这些文件到目录conf/ssl(例如C:\program files\apache group\apache2\conf\ssl)-如果这个目录不存在,你需要首先创建一个。

  10. 重启apache服务

  11. 将你的浏览器指向https://servername/svn/project ...

[重要]强制 SSL 访问

当你设置了SSL让你的版本库更安全,你一定希望关闭普通的非ssl访问,为此,你需要在Subversion的<Location> 增加指示: SSLRequireSSL

一个<Location>实例就像这个样子:

<Location /svn>
DAV svn
SVNParentPath D:\SVN
SSLRequireSSL
AuthType Basic
AuthName "Subversion repositories"
AuthUserFile passwd
#AuthzSVNAccessFile svnaccessfile
Require valid-user
</Location>