Debian 安装 Apache 与 Subversion

前言

通过 Apache、Subversion 搭建 SVN 服务器,实现使用 HTTP、SVN 协议访问 SVN 仓库,并进行细粒度的权限控制,本教程适用于 Debian/Ubuntu 系统。

系统环境

1
2
3
4
5
6
7
8
# uname -a
# Linux debian 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 GNU/Linux

# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
NAME="Debian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"

安装软件

1
2
3
4
5
6
7
8
9
10
11
# 更新软件索引
# apt-get update

# 安装apache
# apt-get install -y apache2 apache2-utils

# 安装subversion,适用于debian
# apt-get install -y subversion subversion-tools libapache2-mod-svn

# 安装subversion,适用于ubuntu
# apt-get install -y subversion subversion-tools libapache2-mod-svn libapache2-svn

验证 Apache 是否安装成功

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
# 启动apache服务
# service apache2 start

# 或者执行
# /etc/init.d/apache2 start

# 查看apache是否占用80端口
# netstat -anp|grep 80

# 查看防火墙状态
# ufw status

# 如果开启了防火墙,则开放80端口
# ufw allow 80/tcp

# 保存防火墙配置
# ufw reload

# 浏览器输入以下地址访问apache服务,如果访问正常则说明apache安装并启动成功
http://127.0.0.1

# 服务管理命令
# 关闭:service apache2 stop
# 启动:service apache2 start
# 重启:service apache2 restart
# 查看状态:service apache2 status
# 前台方式启动:apachectl -D FOREGROUND
# 取消自启动:update-rc.d apache2 remove
# 开机自启动:update-rc.d apache2 defaults

# 相关目录文件说明:
# 安装目录:/usr/lib/apache2
# 启动脚本路径:/etc/init.d/apache2
# 配置文件目录:/etc/apache2
# 主配置文件:/etc/apache2/apache2.conf
# 端口配置文件:/etc/apache2/ports.conf

创建 SVN 仓库,并配置 Apache 的访问权限

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
# 创建存放所有SVN仓库的目录
# mkdir /var/lib/svn

# 创建SVN仓库jenkins-repo
# svnadmin create /var/lib/svn/jenkins-repo

# 将SVN仓库的读写权限授给apache用户
# chown -R www-data:www-data /var/lib/svn/jenkins-repo

# 配置apache的svn模块,在对应配置文件的末尾追加以下内容
# 这里相当于配置与Apache登录相关的内容(例如登录密码验证),只有dav_svn.passwd指定的用户才有权限访问所有仓库,下面会详细介绍相关配置
# vim /etc/apache2/mods-enabled/dav_svn.conf
<Location /svn>
DAV svn
SVNParentPath /var/lib/svn
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/apache2/dav_svn.passwd
Require valid-user
</Location>

# 创建Apache用户的密码文件,将jenkins替换为你自己指定的用户名,回车执行之后输入密码即可
# 注意这里的用户密码和Subversion仓库本身的身份校验机制(authz)没有任何关系,只用于Apache登录校验
# htpasswd -cm /etc/apache2/dav_svn.passwd jenkins

# 修改用户密码文件的权限
# chgrp www-data /etc/apache2/dav_svn.passwd
# chmod 660 /etc/apache2/dav_svn.passwd

# 重启apache服务
# service apache2 restart

mod_dav_svn 模块的其他配置介绍(如果嫌麻烦可忽略)

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
# 配置文件路径:/etc/apache2/mods-enabled/dav_svn.conf

# 下面配置中的"SVNParentPath /var/lib/svn"表示/var/lib/svn目录下的每个子目录都是一个仓库(即所有仓库的根目录),同时表示<Location>标签内的任何权限配置都被所有仓库共用;<Location>标签内的/svn,指通过HTTP协议访问时的URL路由
<Location /svn>
DAV svn
SVNParentPath /var/lib/svn
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/apache2/dav_svn.passwd
Require valid-user
</Location>

# 如果想要指定多个仓库,让每个仓库都拥有不同的访问权限配置,那么可以使用多个Location标签,同时需要将标签内的“SVNParentPath”替换为“SVNPath”,并指向具体仓库的目录
<Location /svn/jenkins-repo>
DAV svn
SVNPath /var/lib/svn/jenkins-repo
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/apache2/jenkins_repo.passwd
Require valid-user
</Location>

<Location /svn/python-repo>
DAV svn
SVNPath /var/lib/svn/python-repo
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/apache2/python-repo.passwd
Require valid-user
</Location>

# 如果替换上述"Require valid-user"为"Require user tony robert",那么只有tony和robert用户可以访问所有仓库
<Location /svn>
DAV svn
SVNParentPath /var/lib/svn
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/apache2/dav_svn.passwd
Require user tony robert
</Location>

# 通过使用<LimitExcept>标签,允许匿名读取所有仓库,而只有认证用户才能对所有仓库进行写操作
<Location /svn>
DAV svn
SVNParentPath /var/lib/svn
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/apache2/dav_svn.passwd
<LimitExcept GET PROPFIND OPTIONS REPORT>
Require valid-user
</LimitExcept>
</Location>

验证 HTTP SVN 是否可用

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
# 浏览器输入以下地址来访问SVN仓库,其中/svn是<Location>标签内的值,而jenkins-repo是上面创建的SVN仓库,访问之后页面会提示你输入用户名和密码
http://127.0.0.1/svn/jenkins-repo/

# 配置SVN客户端允许以明文方式保存密码到本地磁盘,首次使用svn客户端的情况下可能不存在servers配置文件,此时可忽略配置
$ vim ~/.subversion/servers
[global]
store-plaintext-passwords = yes

# 检出SVN仓库jenkins-repo,指定使用jenkins用户进行登录,其中/svn是<Location>标签内的值,而jenkins-repo是上面创建的SVN仓库,回车之后会提示你输入密码
$ svn checkout --username jenkins http://127.0.0.1/svn/jenkins-repo/

# 进入刚检出的仓库目录
$ cd jenkins-repo

# 创建文件
$ touch api.version

# 将指定文件纳入SVN版本控制
$ svn add api.version

# 将指定文件提交到SVN仓库
$ svn commit -m "add file" api.version

# 显示工作区中目录与文件的状态,如果上述步骤都成功执行,执行该命令后则不会有任何日志信息输出
$ svn status

# 可以使用以下命令查询svn命令具体的使用方法
$ svn --help
$ svn commit --help

# 至此,通过Apache、Subversion搭建SVN服务器(HTTP)的步骤算是基本完成了,下面将介绍使用Apache的mod_authz_svn模块对仓库目录进行更细粒度的权限控制,如果不需要细粒度的权限控制,则不用继续往下阅读了。

通过 mod_authz_svn 模块对仓库目录的访问进行细粒度权限控制

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
# 进入对应SVN仓库的目录
# cd /var/lib/svn/jenkins-repo

# 每个SVN仓库目录下都有对应的身份校验文件(authz、passwd),由SVN自动创建
# tree conf
conf
|-- authz
|-- hooks-env.tmpl
|-- passwd
`-- svnserve.conf

# 添加SVN仓库的用户帐号,注意这里的用户名/密码,需要和访问Apache的用户名/密码一致
# 即用户名/密码需要和"AuthUserFile /etc/apache2/dav_svn.passwd"指定的帐号信息一致
# vim conf/passwd
[users]
jenkins = 123456

# 配置SVN仓库的用户组、读写权限
# vim conf/authz
[groups]
team = jenkins

[/]
@team = rw

# 编辑SVN仓库的配置文件,对应内容修改如下,其中“anon-access”项的值必须为none
# vim conf/svnserve.conf
[general]
anon-access = none
auth-access = write
password-db = passwd
authz-db = authz

# 配置authz功能,其中AuthzSVNAccessFile指向的是SVN仓库的authz策略文件,多个SVN仓库可以使用多个<Location>标签进行配置,注意这里使用的是“SVNPath”,而不是"SVNParentPath"
# vim /etc/apache2/mods-enabled/dav_svn.conf
<Location /svn/jenkins-repo>
DAV svn
SVNPath /var/lib/svn/jenkins-repo
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/apache2/jenkins_repo.passwd
AuthzSVNAccessFile /var/lib/svn/jenkins-repo/conf/authz
Require valid-user
</Location>

# 如果使用”SVNParentPath“代替”SVNPath“来指定多个仓库的父目录时,那么所有仓库都将按照指定的策略文件来管理读写权限;此时如果要对具体每个仓库分别配置不同读写权限,authz文件内需要使用如下的语法进行配置:
<Location /svn>
DAV svn
SVNParentPath /var/lib/svn
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/apache2/dav_svn.passwd
AuthzSVNAccessFile /etc/svn/svn_authz
Require valid-user
</Location>

# vim /etc/svn/svn_authz
[groups]
project1_committers = paulex richard
project2_committers = jimmy michel

[repos1:/]
@ project1_committer = rw

[repos2:/]
@ project2_committer = rw

# 重启apache服务
# service apache2 restart

启动 Subversion 服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 默认情况下,通过Apache、Subversion搭建SVN服务器,如果只需要通过HTTP协议访问SVN仓库,则无需启动Subversion服务,相反如果想通过SVN协议直接访问SVN仓库则需要启动
# 其中/var/lib/svn是所有SVN仓库的父目录,如果直接使用SVN协议,那么SVN仓库的用户登录与读写权限控制默认是通过每个仓库下的passwd、authz、svnserve.conf配置文件分别进行控制,此时与Apache没有任何关系
# 参数 -d 表示后台运行,否则默认前台运行
# svnserve -d -r /var/lib/svn

# 测试SVN客户端使用SVN协议检出仓库jenkins-repo,指定使用jenkins用户进行登录,其中3690是Subversion服务的默认端口
# svn checkout --username jenkins svn://127.0.0.1:3690/jenkins-repo

# 查看防火墙状态
# ufw status

# 如果开启了防火墙,则开放3690端口
# ufw allow 3690/tcp

# 保存防火墙配置
# ufw reload

# 关于Subversion服务开机自启动的两种方式:
# 方式一:使用第三方工具Supervistor实现Subversion开机自启动
# 方式二:将配置Subversion配置成系统服务,由systemctl管理开机自启动

Dockerfile 里配置容器启动时默认启动 Apache 与 Subversion

1
2
3
4
5
6
7
RUN echo "svnserve -d -r /var/lib/svn" > /usr/local/start-servers.sh
RUN echo "apachectl -D FOREGROUND" >> /usr/local/start-servers.sh
RUN chmod +x /usr/local/start-servers.sh
CMD /bin/bash /usr/local/start-servers.sh

# 以后创建并以后台方式启动容器时,Apache与Subversion服务会默认自启动
# docker run -d -p 9126:80 -p 4690:3690 ...

Centos7 安装 Apache&Subversion

本文引用