Tag: svn

Our goal in this three part tutorial is to provide multiple users access to a SVN server running a recent version of Ubuntu Linux through the SSH protocol. In SVN language, this combination of protocols is called svn+ssh. The straight forward way would be to create a unix user account for every SVN user and let them tunnel to the SVN server. However, giving all these users shell access to the server is a potential security issue and goes far beyond the initial purpose of just giving access to the SVN server. As a solution, we will create a single unix user account, that is not allowed to have any shell access, and let the SVN users connect through this user account to the SVN server.

Client-side configuration on Windows systems

As stated in the server-side configuration, the private key file id_rsa needs to be distributed to the user on the client side. He or she will use the private key to connect to the SVN server. As the private key is enough to establish the connection, it needs to be stored in a safe place on the computer (and may be additionally secured by a password, see ssh-keygen above).

On Windows, we will use PuTTY to establish the SSH connection and TortoiseSVN for the SVN connection on top of the SSH connection:

As a first step, we are required to convert the private key from OpenSSH format to a format, that PuTTY can read. For this, start PuTTYgen (that came with the PuTTY installer) and select from the menu

Conversions -> Import Key

Load the private key file id_rsa and then click the “Save private key” button in PuTTYgen’s main window. Choose a meaningful filename, for example id_rsa.ppk.

Now as we have the private key file in a format compatible with PuTTY, we configure a so called PuTTY session that connects to the SSH/SVN server with the private key. This session will then be used by TortoiseSVN to automatically set up the SSH connection. Start PuTTY, enter the host name of the SSH/SVN server, in

Connection -> Data

enter the username sshsvn and in

Connection -> SSH -> Auth

provide the path to the private key file id_rsa.ppk. After you have done all configuration, change back to the first tab and store the configuration as a new session that we will call here svn_over_ssh.

After storing the session, double-click it from the list. A terminal window will open and stop after displaying some messages. As expected, the connection is established with the provided private key, but is not granted a shell (pty). Remember, that we disabled shell access for user sshsvn. The last line is output from the SVN server.

After closing the terminal window (and quitting PuTTY at the same time), start TortoiseSVN by right-clicking the Desktop and selecting

TortoiseSVN -> Repo-Browser

from the context menu. The syntax of the URL for the repository is

svn+ssh://PuTTY_SESSION_NAME/repo-path

so in our case reads

svn+ssh://svn_over_ssh/

Please note that in difference to the Linux client, there is no need for a trailing @ char to browse the root directory. Clicking the OK button will connect to the SVN server and we are ready to use TortoiseSVN to connect to the SVN server.

Summary

We have seen how to connect from a Windows system to a SSH/SVN server with a private key for the SSH connection. The server will decide upon the matching public key which SVN user account is used for the SVN connection.

Our goal in this three part tutorial is to provide multiple users access to a SVN server running a recent version of Ubuntu Linux through the SSH protocol. In SVN language, this combination of protocols is called svn+ssh. The straight forward way would be to create a unix user account for every SVN user and let them tunnel to the SVN server. However, giving all these users shell access to the server is a potential security issue and goes far beyond the initial purpose of just giving access to the SVN server. As a solution, we will create a single unix user account, that is not allowed to have any shell access, and let the SVN users connect through this user account to the SVN server.

Client-side configuration on Unix / Linux systems

As stated in the server-side configuration, the private key file id_rsa needs to be distributed to the user on the client side. He or she will use the private key to connect to the SVN server. As the private key is enough to establish the connection, it needs to be stored in a safe place on the computer (and may be additionally secured by a password, see ssh-keygen above).

In general, the server’s URL in the svn command configures the protocol to be used. So

svn list svn+ssh://sshsvn@SERVER_ADDRESS/@

will establish a connection to the SVN server at SERVER_ADDRESS via the combination of SSH and SVN protocols for SSH user sshsvn (remember that we connect to the server as user sshsvn and distinguish different SVN users by the used private key). Please note the trailing @ that is necessary to access the SVN server’s root level. If you get

svn: Syntax error parsing revision 'SERVER_ADDRESS'

errors, you forget the trailing @.

But how to tell the svn command to use the provided private key? There are two solutions for this. First, we may add the private key to the SSH authentication agent,

ssh-add /path/to/id_rsa

Please note that this adds the private key only temporarily. For permanant solutions, see here for example.

The second and preferred way for me is to set the SSH command to be used by SVN with the SVN_SSH environment variable,

Summary

We have seen how to connect from a Unix / Linux system to a SSH/SVN server with a private key for the SSH connection. The server will decide upon the matching public key which SVN user account is used for the SVN connection.

Further Reading

Apart from the man pages of the referenced commands, the main sources for this tutorial have been

Our goal in this three part tutorial is to provide multiple users access to a SVN server running a recent version of Ubuntu Linux through the SSH protocol. In SVN language, this combination of protocols is called svn+ssh. The straight forward way would be to create a unix user account for every SVN user and let them tunnel to the SVN server. However, giving all these users shell access to the server is a potential security issue and goes far beyond the initial purpose of just giving access to the SVN server. As a solution, we will create a single unix user account, that is not allowed to have any shell access, and let the SVN users connect through this user account to the SVN server.

Server-side configuration

Let us start by creating the single unix account, which we call sshsvn. This account will be allowed to establish SSH connections to the server by means of public key authentication but not by password login, e.g. we will lock the unix account. If you want to prevent password logins for all user accounts, consider setting the PasswordAuthentication option to no in your sshd config file (typically in /etc/ssh/sshd_config).

sudo adduser sshsvn

Creating the user with adduser will ask for a password, which we must provide at this point but which will never be used (as we will lock the account in the next step).

sudo usermod --lock sshsvn

For the new user account, we create a key pair for public key authentication.

ssh-keygen -t rsa

When asked for the basic filename of the keys, enter ./id_rsa. Hit enter twice when asked for a passphrase. The passphrase could be used to protect the private key, an option that we will not use for the sake of brevity here but would give additional security!

The ssh-keygen command created two files. The file id_rsa is the private key which will be distributed to a SVN user who will be allowed to connect to the server. id_rsa.pub is the public key, that validates authentication requests initiated with the private key. The following step will store the public key as valid key for SSH authentication for user sshsvn on the server.

Having a quick look at /home/sshsvn/.ssh/authorized_keys we see that it holds a single line with three fields separated by spaces. The three fields are

TYPE: type of key (RSA in our case)

KEY: the public key itself

COMMENT: and a comment (that we ignore)

If we would not have locked the user sshsvn, the current setup would suffice to get password-less but public key authentication for shell access via ssh. However, our goal is to restrict the sshsvn user to svn use only. This can be done by prepending a command field to /home/sshsvn/.ssh/authorized_keys.

The specified command does tunnel the SSH connection to the local SVN server instead of starting a shell. The whole bunch of no-* options further restricts the possibilities of the sshsvn user (see the man page of ssh-keygen for details).

Providing the –tunnel-user argument to svnserve in the command string allows us to define an alternate user for a given public key.

So finally, this gives us the possibility to use a single, locked unix user account to serve multiple svn users. For each svn user, we create a public/private key pair. Each public key is added to /home/sshsvn/.ssh/authorized_keys and the SVN user for each public key is configured with the –tunnel-user argument. This is an abstract example of an /home/sshsvn/.ssh/authorized_keys for four users.

For adiminstration of the SVN server it is important to note, that tunneled users are handled as if successful authentication would have happened. So no SVN password entry is necessary.

Summary

We have seen how to configure a SSH/SVN server to provide a single unix user account that serves SVN over SSH for multiple SVN users. Having this unix user locked prevents even shell access to the SVN server and focusses on the primary goal of just giving safe SVN access to the users.

Further Reading

Apart from the man pages of the referenced commands, the main sources for this tutorial have been

Version control systems such as subversion (short SVN) are great backup tools. But what if the SVN respository itself gets corrupted and no backup of the backup is available? This post demonstrates
how to recover from certain SVN repository corruptions.

For me, problems started when a svn commit aborted with the error message

PATH_TO_REPO/svn/db/current: End of file found

Examination of the file PATH_TO_REPO/svn/db/current revealed, that it was of zero size, vulgo empty. Looking out for solutions, I came across this post on the subversion user mailing list that describes how to restore this file.

First, navigate to the sub-directories of PATH_TO_REPO/svn/db/revs to learn about the youngest revision number of your subversion repository, e.g. the number of the latest revision. Each revision has a file entry in this path, named with the revision number. So the highest filename yields the youngest revision number.

Next, edit the file PATH_TO_REPO/svn/db/current by adding a single line

<youngest revision> zzzzz zzzzz

So for example if your youngest revision number was 5432, then the file should read

5432 zzzzz zzzzz

afterwards (the second and third colum are dummy entries).

Providing a transitional PATH_TO_REPO/svn/db/current enables us now to dump the entire SVN repository including all the information about revisions etc. into a backup file

svnadmin dump PATH_TO_REPO > svn.dump

If repository corruption affected only PATH_TO_REPO/svn/db/current, this step will succeed. However, if you are unlucky, you will encounter

* Dumped revision 5431.
svnadmin: Malformed file

or similar error messages. There might be plenty of reasons for this. This post here has some work-around, which ran me straight into another error

svnadmin: Can't set position pointer in file 'PATH_TO_REPO/svn/db/revs/0/5431': Invalid argument

It is important to recognize that the line just before svnadmin: Malformed file gives you the last revision that was dumped successfully. In my case, this meant that only the last revision was corrupted and I simply skipped that revision. Similarly, you might also skip corrupted revisions, see the -r argument of the svnadmin dump command,

svnadmin dump -r 0:5431 PATH_TO_REPO > svn_repo.dump

After having created a backup of the SVN repository successfully, move the old repository into some safe part,

mv PATH_TO_REPO /backup

and then create a new SVN repository at the original location

svnadmin create PATH_TO_REPO

Finally, load the backup into the repository (given that the repository was empty, as in our case, it will even have the same UUID afterwards).

svnadmin load PATH_TO_REPO < svn_repo.dump

Having arrived here, you will be able to use your SVN repository just as before.