Quick Recipe – restoring a corrupted SVN master repo with the slave repo

Technical, Technology

With svnsync, you could set up a replica of your SVN repository.  Apart from load balancing, the slave repo is also a backup of your master repo.

When in times you’d like to recover the master (we call it the original master) from the slave, you could follow these steps:

  1. Ensure no one is committing to SVN.
  2. Trigger svnsync in all SVN slaves.
  3. Stop the master’s SVN service.
  4. Duplicate your slave repo.  We call the duplicate the new repo.
  5. Change the UUID of the new repo to that of the original master.
    svnlook uuid <path to master repo> # Gives the master's UUID
    svnadmin setuuid <path to new repo> <master's UUID>
    svnlook uuid <path to new repo> # Check if it is set correctly
  6. In physical file system, backup and move away the original master.  Move and rename the new repo to exactly that of the path of the original master.
  7. Remove the hook for the slave (in my case, the file <repo>/hooks/pre-revprop-change).
  8. Add back the hook for the master (in my case, the file <repo>/hooks/post-commit).
  9. Restart the SVN service.


  1. Section “svnsync Bookkeeping” of svnbook
  2. Managing Repository UUIDs

Locking vs Lockless Version Management Models


The problem to avoid: changes by users overwriting each other

The problem to avoid: changes from users overwriting each other

Lock-modify-unlock versioning model:

Lock-Modify-Unlock Versioning Model

Disadvantages of Lock-Modify-Unlock versioning model:

  • Locking may cause administrative problems. Sometimes Harry will lock a file and then forget about it. Meanwhile, because Sally is still waiting to edit the file, her hands are tied. And then Harry goes on vacation. Now Sally has to get an administrator to release Harry’s lock. The situation ends up causing a lot of unnecessary delay and wasted time.
  • Locking may cause unnecessary serialization. What if Harry is editing the beginning of a text file, and Sally simply wants to edit the end of the same file? These changes don’t overlap at all. They could easily edit the file simultaneously, and no great harm would come, assuming the changes were properly merged together. There’s no need for them to take turns in this situation.
  • Locking may create a false sense of security. Suppose Harry locks and edits file A, while Sally simultaneously locks and edits file B. But what if A and B depend on one another, and the changes made to each are semantically incompatible? Suddenly A and B don’t work together anymore. The locking system was powerless to prevent the problem—yet it somehow provided a false sense of security. It’s easy for Harry and Sally to imagine that by locking files, each is beginning a safe, insulated task, and thus not bother discussing their incompatible changes early on. Locking often becomes a substitute for real communication.

Copy-Modify-Merge Versioning Model:

Copy-Modify-Merge Versioning Model (1 of 2)

Copy-Modify-Merge Versioning Model (2 of 2)

Source: http://svnbook.red-bean.com/en/1.4/svn.basic.vsn-models.html

SELinux blocks svn via http in CentOS / Fedora Core


If this happens, you may see something like “Could not open the requested SVN filesystem” on the browser and “(20014)Internal error: Can’t open file ‘/repos/svn/repo16/format’: Permission denied” in apache error_log.

When you feel puzzled why with seemingly correct permission settings in place, but it still does not work, you could try this:

# getenforce <– this shows you the status of SELinux. If you see “Enforcing”, then SELinux is on.

# setenforce Permissive <– this changes it to Permissive, which is like turning SELinux off.

The try again to see if it works. If it becomes ok, then you have to change the SELinux policy.

If proved to be the restriction by SELinux, then you could do the following:

  1. chcon -Rv -t httpd_sys_content_t /repos/svn/repo16
  2. chcon -v t httpd_sys_content_t /repos
  3. chcon -v t httpd_sys_content_t /repos/svn
  4. semanage fcontext -a -t httpd_sys_content_t “/repos(.*)?”

Quick Recipe – setting up master-slave subversion servers with replication using svnsync and transparent proxy in Ubuntu


If you are having enough background, this article is a shortcut for you to set up a group of SVN servers with one master and one slave (you should be able to generalize it to multiple slaves with some minor touches). This group of SVN servers could be synchronized (or replicated) to allow multi-site deployment for network efficiency. However, you could always refer to this article for details on setting up svnsync and this article for setting up ssh login without password.

Assumed you are given:

  1. A master SVN server ([Master]) access via HTTP with a proper repository setup at /var/svn/repos. (You could refer to this article for setting up an SVN server.)
  2. A slave SVN server ([Slave]) accessed via HTTP (with an empty repository /var/svn/repos created as in this article).
  3. The credentials for accessing the master and slave SVN servers are identical.
  4. The master and slave SVN servers can access each other.

To set this up, follow the recipe:

  1. [Slave] cd /etc/apache2/mods-enabled; sudo ln -s ../mods-available/proxy.load; sudo ln -s ../mods-available/proxy_http.load
  2. [Slave] Add a SVNMasterURI directive under the <Location> directive in /etc/apache2/mods-available/dav_svn.conf (details)
  3. [Slave] sudo adduser svnsync
  4. [Slave] sudo adduser svnsync svn
  5. [Slave] sudo chown -R svnsync:svn /var/svn/repos
  6. [Slave] Create a script /var/svn/repos/hooks/pre-revprop-change (details)
  7. [Slave] sudo chmod +x /var/svn/repos/hooks/pre-revprop-change
  8. [Slave] sudo svnsync init –username svnsync file:///var/svn/repos http://<master hostname>/svn/repos
  9. [Slave] Download the script svn-sync-slave.sh and put under /var
  10. [Slave] Modify the first line of /var/svn-sync-slave.sh from #!/bin/sh to #!/bin/bash
  11. [Slave] sudo chown svnsync:svn /var/svn-sync-slave.sh; sudo chmod +x /var/svn-sync-slave.sh
  12. [Master] Create a script /var/svn/repos/hooks/post-commit (details)
  13. [Master] sudo chown www-data:svn /var/svn/repos/hooks/post-commit; sudo chmod g+rws /var/svn/repos/hooks/post-commit
  14. [Master] sudo -i
  15. [Master] su – www-data
  16. [Master] ssh-keygen -t rsa (give empty passphrase)
  17. [Master] ssh svnsync@<slave hostname> mkdir -p .ssh
  18. [Master] cat .ssh/id_rsa.pub | ssh svnsync@<slave hostname> ‘cat >> .ssh/authorized_keys’

To test this setup:

  1. Find another computer with svn client installed. ([Client])
  2. [Client] svn import –username <user> <path to local folder> http://<slave hostname>/svn/repos
  3. Check whether the imported folders and files are in both master and slave SVN servers’ repositories.
  4. [Client] Pick any one file imported.  Modify it and commit it to http://<slave hostname>/svn/repos.
  5. Check whether the modified file is in both master and slave SVN servers’ repositories.

Update on 2011-07-28:

There is something subtle that needs special consideration.

In fact, when I try to apply this procedures to an old and big svn repository, there is a problem.  I tried to start synchronizing with a new repository (you have to start from scratch anyway!) over the network.  I then tried to do a rough gauging and calculation exercise.  It needs to take 3 months to sync them all (yes, days and nights, continuously).

Luckily, we resolved it by using the file-based nature of svn.  We first make a sync in the same machine.  But note that you should use the target url as the master url, i.e. you should use IP / hostname to sync instead of localhost as svnsync remembers the url you used to init the sync process.

Then, after the sync process is done (which is much much much faster), zip the whole repository and upload to the target slave machine.  In the slave machine, you could expand and rename the repository as you like.  At this point, the svnsync becomes incremental.  So it would not take you much time to do a few revisions’ synchronization.

Details here:

[Slave] Add a SVNMasterURI directive under the <Location> directive in /etc/apache2/mods-available/dav_svn.conf

SVNMasterURI http://<master hostname>/svn/repos

[Slave] Create a script /var/svn/repos/hooks/pre-revprop-change


if [ "$USER" != "svnsync" ]; then
    echo >&2 "Only the svnsync user can change revprops"
    exit 1

exit 0

[Master] Create a script /var/svn/repos/hooks/post-commit


ssh -l svnsync <slave hostname> "/var/svn-sync-slave.sh -r /var/svn/repos"

Quick Recipe – Setting up a Subversion Server to be Accessed via HTTP in Ubuntu


If you are having enough background, this article is a shortcut for you to set up a subversion server.  You could always refer to this article for more details.

Assumed you are given:

  1. An installation of Ubuntu Linux with access to APT repositories via network.
  2. Installed Apache2 web server.

To install subversion, follow this recipe:

  1. sudo apt-get install subversion
  2. sudo adduser svn
  3. sudo adduser www-data svn
  4. sudo mkdir /var/svn
  5. sudo svnadmin create /var/svn/repos
  6. sudo chown -R www-data:svn /var/svn/repos
  7. sudo chmod g+rws /var/svn/repos
  8. sudo apt-get install libapache2-svn
  9. Add a <Location> to /etc/apache2/mods-available/dav_svn.conf (details)
  10. (Optional) cd /etc/apache2/mods-enabled; sudo ln -s ../mods-available/dav_svn.load; sudo ln -s ../mods-available/dav_svn.conf
  11. sudo /etc/init.d/apache2 restart
  12. sudo htpasswd -c /etc/htpasswd.svn <1st user>
  13. sudo htpasswd /etc/htpasswd.svn <2nd user>

To test the installation and setup:

  1. cat /etc/htpasswd.svn
  2. svn co http://<hostname>/svn/repos mycopy –username <user>

Details here:
Add a <Location> snippet to /etc/apache2/mods-available/dav_svn.conf

<Location /svn/repos>
     DAV svn
     SVNPath /var/svn/repos
     AuthType Basic
     AuthName "SVN repository"
     AuthUserFile /etc/htpasswd.svn
     AuthzSVNAccessFile /var/svn/repos/conf/authz
        Require valid-user