Home : Linux resources : Subversion server
This recipe was used to set my server up initially on SuSE 9.0 (where the shipped RPM edition of Subversion is so old as to be completely useless, so I built Subversion 1.3.0 from the tarball), and again when I migrated it to new hardware running openSUSE 10.2 (which comes with Subversion 1.4.0).
[But according to the openSUSE project "Lifetime" page, openSUSE 10.2 has been obsolete for more than 12 years now. Some of this may still work, but I haven't had reason to test it myself for quite some time, so take it with a huge grain of salt. -- rgr, 29-Jan-21.]
openssl req -x509 -newkey rsa:1024 -sha1 -days 90 -keyout key.pem -out req.pem
Be sure to specify -sha1; if you don't, you will get
MD5. The -x509 is what makes openssl req
generate a self-signed certificate. Specifying -days 90
produces a cert valid for 90 days; the default is thirty (and
this is ignored if you generate a proper signing request instead
of a self-signature). This recipe is based on the "req(1)"
man page, which explains what all the options mean.
In all cases, it is probably desirable to replace the word "server" with something specific to the server in question -- just be sure you do the same for the SSL config file.
OS key.pem (private key) req.pem (certificate) OpenSUSE /etc/apache2/ssl.key/server.key /etc/apache2/ssl.crt/server.crt CentOS /etc/pki/tls/private/server.key /etc/pki/tls/certs/server.crt
Note that this recipe installs the Subversion binaries into the default /usr/local/bin/ location. In order to use the backup script described below, you may need to add /usr/local/bin/ to $PATH.
CFLAGS=`apxs2 -q CFLAGS` ./configure --enable-shared \
--with-ssl --with-apxs=`which apxs2` --disable-mod-activation
These options have the following effect:
# Subversion server setup. -- rgr, 20-Mar-06.
<Location /svn>
DAV svn
# any "/svn/foo" URL will map to a repository /shared/svn/foo
SVNParentPath /shared/svn
# how to authenticate.
AuthType Basic
AuthName "Subversion repository at rgrjr.dyndns.org"
AuthUserFile /etc/svn-auth-file
# require authentication for anything beyond read access.
<LimitExcept GET PROPFIND OPTIONS REPORT>
Require valid-user
</LimitExcept>
</Location>
# Subversion server setup. -- rgr, 13-Dec-07.
<Location /svn>
DAV svn
# any "/svn/foo" URL will map to a repository /shared/svn/foo
SVNParentPath /shared/svn
# access control policy file.
AuthzSVNAccessFile /etc/svn-access.conf
# try anonymous access first, resort to real
# authentication if necessary.
Satisfy Any
Require valid-user
# how to authenticate.
AuthType Basic
AuthName "Subversion repository at rgrjr.dyndns.org [new]"
AuthUserFile /etc/svn-auth-file
</Location>
The difference between this and the previous
<Location> recipe is that the
<LimitExcept> part is is replaced by top-level
"Require valid-user" and "Satisfy Any" options, and the
AuthzSVNAccessFile identifies an access file. Note that
user credentials are still defined with htpasswd2 in
/etc/svn-auth-file as before.
# Subversion authentication. See
# http://svnbook.red-bean.com/nightly/en/svn.serverconfig.pathbasedauthz.html
# for details.
[/]
# Allow everyone to read the entire repository, unless overridden.
* = r
# Give write permission to rogers and rgr.
rogers = rw
rgr = rw
[lap-config:/]
# This is private, so we need "* =" to revoke anonymous reads, and
# "rogers = rw" to reinstate write permission.
* =
rogers = rw
The "[/]" paragraph reinstates the anonymous
read/authenticated write policy of the previous section for all
directories of all repositories, and the final paragraph
restricts all access to the lap-config repository to
rogers.
rogers@rgr> svn ls https://rgrjr.dyndns.org/svn/rgr-hacks/
branches/
tags/
trunk/
rogers@rgr>
This is the expected output for a repository created by
cvs2svn; if you look in trunk/, you will see
the version-controlled files in the top-level directory.
svn co https://rgrjr.dyndns.org/svn/rgr-hacks/trunk rgr-hacks
and look at the new working copy in the rgr-hacks
subdirectory.
To find binary files in a CVS working copy:
rogers@rgr> cd ~/emacs/rgr-hacks
rogers@rgr> find . -type f -name Entries \
| xargs -e egrep -n -e '\.(png|jpg|gif)/' \
| fgrep -v /-kb/
To fix them:
rogers@rgr> cvs admin -kb *.jpg
rogers@rgr> cvs update
Note that cvs admin operates on the repository
immediately; the cvs update is only needed to update the
working copy, but that is useful for subsequent searches.
Somewhat more problematic are files that are supposed to have DOS-style "CRLF" line endings, regardless of which OS they are checked out on. Even if marked "-kb", cvs2svn still treats these as "text/plain" and initializes their svn:eol-style to "native".
To find CRLF files (approximately) in a CVS working copy:
rogers@rgr> find . -type f | fgrep -v /CVS/ | xargs fgrep -l '\r'
Since these often have "*.text" or other file extensions that are
also used for files that should have "native" EOL style, there is
no good way for cvs2svn to tell them apart, so I just
fix them after the conversion (see below).
See also "How do I fix up end-of-line translation problems?" in the cvs2svn FAQ.
# svnadmin create /shared/svn/rgr-hacks
# chown -R rogers /shared/svn/rgr-hacks
rogers@rgr> cvs2svn --existing-svnrepos -s /shared/svn/rgr-hacks/ /shared/cvsroot/rogers/emacs/rgr-hacks/
Note that by default, cvs2svn will stuff everything that
is not a branch into a trunk/ subdirectory.
# chown -R wwwrun /shared/svn/rgr-hacks
rogers@rgr> xargs svn propset svn:eol-style CRLF < dos-eol-files.text
rogers@rgr> xargs perl -pi.bk -e 's/$/\r/;' < dos-eol-files.text
After testing, do:
rogers@rgr> svn ci -m 'Fix svn:eol-style on DOS-like files.'
rogers@rgr> find . -name '*.bk' | xargs rm
to commit and clean up.
rogers@rgr> cd ..
rogers@rgr> mv rgr-hacks rgr-hacks.cvs
rogers@rgr> svn co https://rgrjr.dyndns.org/svn/rgr-hacks/trunk rgr-hacks
rogers@rgr> diff -ur rgr-hacks.cvs rgr-hacks
Note that diff will find many trivial differences in
$Id:$ tags. If image files are reported to be
different, then you probably need to go back to step 1.
rgrjr:~ # svnadmin create /shared/svn/lap-config
rgrjr:~ # chown -R wwwrun.www /shared/svn/lap-config
rgrjr:~ #
rogers@lap> mkdir -p tmp/trunk
rogers@lap> cd tmp/trunk
rogers@lap> tar xzf source-of-files.tgz
rogers@lap> cd ../..
rogers@lap> ls tmp/trunk/
fstab.mgi hosts.random README.text.~1~ routes.rgrjr
fstab.random ntp.conf.mgi resolv.conf.mgi site-setup
HOSTNAME.mgi ntp.conf.random resolv.conf.rgrjr ssh_config
hosts.mgi README.text routes.mgi sshd_config
rogers@lap>
Note that Subversion will not include README.text.~1~,
knowing that it is an old version of the README.text
file.
rogers@lap> svn import tmp https://rgrjr.dyndns.org/svn/lap-config -m "Initial import (SuSE 9.1)"
Adding tmp/trunk
Adding tmp/trunk/hosts.random
Adding tmp/trunk/README.text
Adding tmp/trunk/ssh_config
Adding tmp/trunk/resolv.conf.rgrjr
Adding tmp/trunk/sshd_config
. . .
Committed revision 1.
rogers@lap> svn list https://rgrjr.dyndns.org/svn/lap-config
trunk/
rogers@lap>
rogers@lap> rm -fr tmp
rogers@lap> svn co https://rgrjr.dyndns.org/svn/lap-config/trunk lap-config
A lap-config/hosts.random
A lap-config/README.text
A lap-config/ssh_config
A lap-config/resolv.conf.rgrjr
A lap-config/sshd_config
A lap-config/HOSTNAME.mgi
A lap-config/routes.mgi
A lap-config/ntp.conf.mgi
A lap-config/site-setup
A lap-config/ntp.conf.random
A lap-config/routes.rgrjr
A lap-config/resolv.conf.mgi
A lap-config/fstab.mgi
A lap-config/hosts.mgi
A lap-config/fstab.random
Checked out revision 1.
rogers@lap> cd lap-config/
rogers@lap> ls
fstab.mgi hosts.mgi ntp.conf.random resolv.conf.rgrjr site-setup
fstab.random hosts.random README.text routes.mgi ssh_config
HOSTNAME.mgi ntp.conf.mgi resolv.conf.mgi routes.rgrjr sshd_config
rogers@lap>
This creates a normal working copy.
# Back up Subversion repositories daily at 00:50. This is ten minutes before
# the normal /home partition backup time.
50 0 * * * cd /home/rogers/projects/svn-dump && svn-dump.pl /shared/svn/*
Since all mod_dav_svn repositories on my server are
subdirectories of /shared/svn/, this catches everything with a
single command. The files that are created look like this:
rogers@rgr> ls -lt /home/rogers/projects/svn-dump
total 5468
-rw-r--r-- 1 rogers users 79596 06-29 00:50 web-site-213-235.svndump
-rw-r--r-- 1 rogers users 19269 06-29 00:50 rgr-hacks-397-414.svndump
-rw-r--r-- 1 rogers users 24044 06-29 00:50 kea-cl-558-568.svndump
-rw-r--r-- 1 rogers users 172628 05-16 00:50 web-site-164-212.svndump
-rw-r--r-- 1 rogers users 3210 04-14 00:50 hacks-4-4.svndump
-rw-r--r-- 1 rogers users 56310 03-31 00:50 kea-cl-523-557.svndump
-rw-r--r-- 1 rogers users 2264449 03-16 00:50 web-site-0-163.svndump
-rw-r--r-- 1 rogers users 4476 03-03 00:50 rgr-hacks-392-396.svndump
-rw-r--r-- 1 rogers users 903 02-05 00:50 rgr-hacks-391-391.svndump
. . .
Most files with only a few revisions are quite small, since each file
records only the incremental changes since the last dump. The
web-site-0-163.svndump file is large since that is the first
dump since converting this repository from CVS.
Periodically, in order to reduce the clutter of small *.svndump files, I delete the most recent files, and the next time the svn-dump.pl cron job runs, these files are consolidated into a single new *.svndump file.
rogers@home> svnadmin dump /shared/svn/rgr-hacks/ > rgr-hacks.svndump
* Dumped revision 0.
. . .
* Dumped revision 469.
* Dumped revision 470.
* Dumped revision 471.
rogers@home>
In this case, an 8.6MB file was generated for a repository that
is only 5.7MB. If dumping creates a file that is unmanageably
large, you might want to use the --deltas option of
svnadmin dump. Note that svnadmin
dump requires a path to the repository, not a URL, so this
must be done on the original server. Note also that this
command only writes to standard output, hence the redirection.
rogers@home> scp rgr-hacks.svndump rgrjr.com:
rgr-hacks.svndump 100% 8652KB 540.7KB/s 00:16
rogers@home>
# svnadmin create /var/www/subversion/rgr-hacks
#
# svnadmin load /var/www/subversion/rgr-hacks < rgr-hacks.svndump
<<< Started new transaction, based on original revision 1
. . .
<<< Started new transaction, based on original revision 471
* editing path : trunk/rgr-perl-hacks.el ... done.
------- Committed revision 471 >>>
#
(svnadmin load is even more verbose than svnadmin
dump, so this transcript is even more severely truncated.)
# chown -R wwwrun.www /var/www/subversion/rgr-hacks
#
svn switch --relocate https://rgrjr.dyndns.org/svn/rgr-hacks/ https://www.rgrjr.com/svn/rgr-hacks/
The --relocate option means to move the working copy to
the same version of the same repository but in a different
location, so
svn switch only needs to rewrite the URLs. In
particular, this means the working copy doesn't need to be
up-to-date, nor do any modified files need to be committed. It's
also quite fast.