The svnserve program is a lightweight      server, capable of speaking to clients over TCP/IP using a
      custom, stateful protocol.  Clients contact an
      svnserve server by using URLs that begin with
      the svn:// or svn+ssh://
      schema.  This section will explain the different ways of running
      svnserve, how clients authenticate themselves
      to the server, and how to configure appropriate access control
      to your repositories.
There are a few different ways to invoke the
        svnserve program.  If invoked with no
        options, you'll see nothing but a help message.  However, if
        you're planning to have inetd launch the
        process, then you can pass the -i
        (--inetd) option:
$ svnserve -i ( success ( 1 2 ( ANONYMOUS ) ( edit-pipeline ) ) )
When invoked with the --inetd option,
        svnserve attempts to speak with a
        Subversion client via stdin and
        stdout using a custom protocol.  This is
        the standard behavior for a program being run via
        inetd.  The IANA has reserved port 3690
        for the Subversion protocol, so on a Unix-like system you can
        add lines to /etc/services like these (if
        they don't already exist):
svn 3690/tcp # Subversion svn 3690/udp # Subversion
And if your system is using a classic Unix-like
        inetd daemon, you can add this line to
        /etc/inetd.conf:
svn stream tcp nowait svnowner /usr/bin/svnserve svnserve -i
Make sure “svnowner” is a user which has appropriate permissions to access your repositories. Now, when a client connection comes into your server on port 3690, inetd will spawn an svnserve process to service it.
On a Windows system, third-party tools exist to run svnserve as a service. Look on Subversion's website for a list of these tools.
A second option is to run svnserve as a
        standalone “daemon” process.  Use the
        -d option for this:
$ svnserve -d $ # svnserve is now running, listening on port 3690
When running svnserve in daemon mode,
        you can use the --listen-port= and
        --listen-host= options to customize the exact
        port and hostname to “bind” to.
There's still a third way to invoke
        svnserve, and that's in “tunnel
        mode”, with the -t option.  This mode
        assumes that a remote-service program such as
        RSH or SSH has
        successfully authenticated a user and is now invoking a
        private svnserve process as that
        user.  The svnserve program
        behaves normally (communicating via stdin
        and stdout), and assumes that the traffic
        is being automatically redirected over some sort of tunnel
        back to the client.  When svnserve is
        invoked by a tunnel agent like this, be sure that the
        authenticated user has full read and write access to the
        repository database files. (See Servers and Permissions:  A Word of Warning.)  It's essentially the same as
        a local user accessing the repository via
        file:/// URLs.
Once the svnserve program is running,
        it makes every repository on your system available to the
        network.  A client needs to specify an
        absolute path in the repository URL.  For
        example, if a repository is located at
        /usr/local/repositories/project1, then a
        client would reach it via svn://host.example.com/usr/local/repositories/project1
        .  To increase security, you can pass the
        -r option to svnserve,
        which restricts it to exporting only repositories below that
        path:
$ svnserve -d -r /usr/local/repositories …
Using the -r option effectively
        modifies the location that the program treats as the root of
        the remote filesystem space.  Clients then use URLs that
        have that path portion removed from them, leaving much
        shorter (and much less revealing) URLs:
$ svn checkout svn://host.example.com/project1 …
When a client connects to an svnserve process, the following things happen:
The client selects a specific repository.
The server processes the repository's
        conf/svnserve.conf file, and begins to
        enforce any authentication and authorization policies defined
        therein.
Depending on the situation and authorization policies,
the client may be allowed to make requests anonymously, without ever receiving an authentication challenge, OR
the client may be challenged for authentication at any time, OR
if operating in “tunnel mode”, the client will declare itself to be already externally authenticated.
At the time of writing, the server only knows how to send a CRAM-MD5 [24] authentication challenge. In essence, the server sends a bit of data to the client. The client uses the MD5 hash algorithm to create a fingerprint of the data and password combined, then sends the fingerprint as a response. The server performs the same computation with the stored password to verify that the result is identical. At no point does the actual password travel over the network.
It's also possible, of course, for the client to be externally authenticated via a tunnel agent, such as SSH. In that case, the server simply examines the user it's running as, and uses it as the authenticated username. For more on this, see the section called “SSH authentication and authorization”.
As you've already guessed, a repository's
        svnserve.conf file is the central
        mechanism for controlling authentication and authorization
        policies.  The file has the same format as other configuration
        files (see the section called “Runtime Configuration Area”): section names
        are marked by square brackets ([ and
        ]), comments begin with hashes
        (#), and each section contains
        specific variables that can be set (variable =
        value).  Let's walk through this file and learn how
        to use them.
For now, the [general] section of the
          svnserve.conf has all the variables you
          need.  Begin by defining a file which contains usernames and
          passwords, and an authentication realm:
[general] password-db = userfile realm = example realm
The realm is a name that you define.
          It tells clients which sort of “authentication
          namespace” they're connecting to; the Subversion
          client displays it in the authentication prompt, and uses it
          as a key (along with the server's hostname and port) for
          caching credentials on disk (see the section called “Client Credentials Caching”).  The
          password-db variable points to a separate
          file that contains a list of usernames and passwords, using
          the same familiar format.  For example:
[users] harry = foopassword sally = barpassword
The value of password-db can be an
          absolute or relative path to the users file.  For many
          admins, it's easy to keep the file right in the
          conf/ area of the repository, alongside
          svnserve.conf.  On the other hand, it's
          possible you may want to have two or more repositories share
          the same users file; in that case, the file should probably
          live in a more public place.  The repositories sharing the
          users file should also be configured to have the same realm,
          since the list of users essentially defines an
          authentication realm.  Wherever the file lives, be sure to
          set the file's read and write permissions appropriately.  If
          you know which user(s) svnserve will run
          as, restrict read access to the user file as necessary.
There are two more variables to set in the
          svnserve.conf file: they determine what
          unauthenticated (anonymous) and authenticated users are
          allowed to do.  The variables anon-access
          and auth-access can be set to the values
          none, read, or
          write.  Setting the value to
          none restricts all access of any kind;
          read allows read-only access to the
          repository, and write allows complete
          read/write access to the repository.  For example:
[general] password-db = userfile realm = example realm # anonymous users can only read the repository anon-access = read # authenticated users can both read and write auth-access = write
The example settings are, in fact, the default values of the variables, should you forget to define them. If you want to be even more conservative, you can block anonymous access completely:
[general] password-db = userfile realm = example realm # anonymous users aren't allowed anon-access = none # authenticated users can both read and write auth-access = write
Notice that svnserve only understands “blanket” access control. A user either has universal read/write access, universal read access, or no access. There is no detailed control over access to specific paths within the repository. For many projects and sites, this level of access control is more than adequate. However, if you need per-directory access control, you'll need to use either use Apache with mod_authz_svn (see the section called “Per-Directory Access Control”) or use a pre-commit hook script to control write access (see the section called “Hook Scripts”). The Subversion distribution comes with commit-access-control.pl and the more sophisticated svnperms.py scripts for use in pre-commit scripts.
svnserve's built-in authentication can be very handy, because it avoids the need to create real system accounts. On the other hand, some administrators already have well-established SSH authentication frameworks in place. In these situations, all of the project's users already have system accounts and the ability to “SSH into” the server machine.
It's easy to use SSH in conjunction with
        svnserve.  The client simply uses the
        svn+ssh:// URL schema to connect:
$ whoami harry $ svn list svn+ssh://host.example.com/repos/project harry@host.example.com's password: ***** foo bar baz …
In this example, the Subversion client is invoking a local
        ssh process, connecting to
        host.example.com, authenticating as the
        user harry, then spawning a private
        svnserve process on the remote machine
        running as the user harry.  The
        svnserve command is being invoked in tunnel
        mode (-t) and its network protocol is being
        “tunneled” over the encrypted connection by
        ssh, the tunnel-agent.
        svnserve is aware that it's running as the
        user harry, and if the client performs a
        commit, the authenticated username will be attributed as the
        author of the new revision.
The important thing to understand here is that the Subversion client is not connecting to a running svnserve daemon. This method of access doesn't require a daemon, nor does it notice one if present. It relies wholly on the ability of ssh to spawn a temporary svnserve process, which then terminates when the network connection is closed.
When using svn+ssh:// URLs to access a
        repository, remember that it's the ssh
        program prompting for authentication, and
        not the svn client
        program.  That means there's no automatic password caching
        going on (see the section called “Client Credentials Caching”).  The
        Subversion client often makes multiple connections to the
        repository, though users don't normally notice this due to the
        password caching feature.  When using
        svn+ssh:// URLs, however, users may be
        annoyed by ssh repeatedly asking for a
        password for every outbound connection.  The solution is to
        use a separate SSH password-caching tool like
        ssh-agent on a Unix-like system, or
        pageant on Windows.
When running over a tunnel, authorization is primarily
        controlled by operating system permissions to the repository's
        database files; it's very much the same as if Harry were
        accessing the repository directly via a
        file:/// URL.  If multiple system users are
        going to be accessing the repository directly, you may want to
        place them into a common group, and you'll need to be careful
        about umasks.  (Be sure to read the section called “Supporting Multiple Repository Access Methods”.)  But even in the case of
        tunneling, the svnserve.conf file can
        still be used to block access, by simply setting
        auth-access = read or auth-access
        = none.
You'd think that the story of SSH tunneling would end
        here, but it doesn't.  Subversion allows you to create custom
        tunnel behaviors in your run-time config
        file (see the section called “Runtime Configuration Area”).  For example,
        suppose you want to use RSH instead of SSH.  In the
        [tunnels] section of your
        config file, simply define it like
        this:
[tunnels] rsh = rsh
And now, you can use this new tunnel definition by using a
        URL schema that matches the name of your new variable:
        svn+rsh://host/path.  When using the new
        URL schema, the Subversion client will actually be running the
        command rsh host svnserve -t behind the
        scenes.  If you include a username in the URL (for example,
        svn+rsh://username@host/path) the client
        will also include that in its command (rsh
        username@host svnserve -t).  But you can define new
        tunneling schemes to be much more clever than that:
[tunnels] joessh = $JOESSH /opt/alternate/ssh -p 29934
This example demonstrates a couple of things.  First, it
        shows how to make the Subversion client launch a very specific
        tunneling binary (the one located at
        /opt/alternate/ssh) with specific
        options.  In this case, accessing a
        svn+joessh:// URL would invoke the
        particular SSH binary with -p 29934 as
        arguments—useful if you want the tunnel program to
        connect to a non-standard port.
Second, it shows how to define a custom environment
        variable that can override the name of the tunneling program.
        Setting the SVN_SSH environment variable is
        a convenient way to override the default SSH tunnel agent.
        But if you need to have several different overrides for
        different servers, each perhaps contacting a different port or
        passing a different set of options to SSH, you can use the
        mechanism demonstrated in this example.  Now if we were to set
        the JOESSH environment variable, its value
        would override the entire value of the tunnel
        variable—$JOESSH would be executed
        instead of /opt/alternate/ssh -p
        29934.
It's not only possible to control the way in which the client invokes ssh, but also to control the behavior of sshd on your server machine. In this section, we'll show how to control the exact svnserve command executed by sshd, as well as how to have multiple users share a single system account.
To begin, locate the home directory of the account
          you'll be using to launch svnserve.  Make
          sure the account has an SSH public/private keypair
          installed, and that the user can log in via public-key
          authentication.  Password authentication will not work,
          since all of the following SSH tricks revolve around using
          the SSH authorized_keys file.
If it doesn't already exist, create the
          authorized_keys file (on Unix,
          typically ~/.ssh/authorized_keys).
          Each line in this file describes a public key that is
          allowed to connect.  The lines are typically of the
          form:
ssh-dsa AAAABtce9euch.... user@example.com
The first field describes the type of key, the second
          field is the uuencoded key itself, and the third field is a
          comment.  However, it's a lesser known fact that the entire
          line can be preceded by a command
          field:
command="program" ssh-dsa AAAABtce9euch.... user@example.com
When the command field is set, the
          SSH daemon will run the named program instead of the
          typical svnserve -t invocation that the
          Subversion client asks for.  This opens the door to a number
          of server-side tricks.  In the following examples, we
          abbreviate the lines of the file as:
command="program" TYPE KEY COMMENT
Because we can specify the executed server-side command, it's easy to name a specific svnserve binary to run and to pass it extra arguments:
command="/path/to/svnserve -t -r /virtual/root" TYPE KEY COMMENT
In this example, /path/to/svnserve
          might be a custom wrapper script
          around svnserve which sets the umask (see
          the section called “Supporting Multiple Repository Access Methods”).  It also shows how to
          anchor svnserve in a virtual root
          directory, just as one often does when
          running svnserve as a daemon process.
          This might be done either to restrict access to parts of the
          system, or simply to relieve the user of having to type an
          absolute path in the svn+ssh://
          URL.
It's also possible to have multiple users share a single
          account.  Instead of creating a separate system account for
          each user, generate a public/private keypair for each
          person.  Then place each public key into
          the authorized_users file, one per
          line, and use the --tunnel-user
          option:
command="svnserve -t --tunnel-user=harry" TYPE1 KEY1 harry@example.com command="svnserve -t --tunnel-user=sally" TYPE2 KEY2 sally@example.com
This example allows both Harry and Sally to connect to
          the same account via public-key authentication.  Each of
          them has a custom command that will be executed;
          the --tunnel-user option 
          tells svnserve -t to assume that the named
          argument is the authenticated user.  Without
          --tunnel-user, it would appear as though
          all commits were coming from the one shared system
          account.
A final word of caution: giving a user access to the
          server via public-key in a shared account might still allow
          other forms of SSH access, even if you've set
          the command value
          in authorized_keys.  For example, the
          user may still get shell access through SSH, or be able to
          perform X11 or general port-forwarding through your server.
          To give the user as little permission as possible, you may
          want to specify a number of restrictive options immediately
          after the command:
  command="svnserve -t --tunnel-user=harry",no-port-forwarding,\
           no-agent-forwarding,no-X11-forwarding,no-pty \
           TYPE1 KEY1 harry@example.com