doc/manual.docbook
branchdebian
changeset 172 5dd3698fad54
parent 162 1c0bc7d33648
child 179 243dd21d0dbc
equal deleted inserted replaced
118:107906bfe2c6 172:5dd3698fad54
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <article xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en"
       
     3   xmlns:xlink="http://www.w3.org/1999/xlink">
       
     4 <info>
       
     5   <title>Sharing Mercurial repositories with mercurial-server</title>
       
     6   <author><firstname>Paul</firstname><surname>Crowley</surname></author>
       
     7   <copyright><year>2009</year><holder>Paul Crowley, LShift Ltd</holder></copyright>
       
     8 </info>
       
     9 <section>
       
    10 <title>About mercurial-server</title>
       
    11 <para>
       
    12 Home page: <link xlink:href="http://www.lshift.net/mercurial-server.html"/>
       
    13 </para>
       
    14 <para>
       
    15 mercurial-server gives your developers remote read/write access to
       
    16 centralized <link xlink:href="http://hg-scm.org/">Mercurial</link>
       
    17 repositories using SSH public key authentication; it provides convenient
       
    18 and fine-grained key management and access control.
       
    19 </para>
       
    20 <para>
       
    21 Though mercurial-server is currently targeted at Debian-based systems such
       
    22 as Ubuntu, other users have reported success getting it running on other
       
    23 Unix-based systems such as Red Hat. Running it on a non-Unix system such as
       
    24 Windows is not supported. You will need root privileges to install it.
       
    25 </para>
       
    26 </section>
       
    27 <section>
       
    28 <title>Step by step</title>
       
    29 <para>
       
    30 mercurial-server authenticates users not using passwords but using SSH
       
    31 public keys; everyone who wants access to a mercurial-server repository
       
    32 will need such a key. In combination with <command>ssh-agent</command> (or
       
    33 equivalents such as the Windows program <link
       
    34 xlink:href="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter9.html#pageant">Pageant</link>),
       
    35 this means that users will not need to type in a password to access the
       
    36 repository. If you're not familiar with SSH public keys, the <link
       
    37 xlink:href="http://sial.org/howto/openssh/publickey-auth/">OpenSSH Public
       
    38 Key Authentication tutorial</link> may be helpful.
       
    39 </para>
       
    40 <section>
       
    41 <title>Installing mercurial-server</title>
       
    42 <para>
       
    43 In what follows, we assume that your username is <systemitem
       
    44 class="username">jay</systemitem>, that you usually sit at a machine called
       
    45 <systemitem class="systemname">spoon</systemitem> and you wish to
       
    46 install mercurial-server on <systemitem
       
    47 class="systemname">jeeves</systemitem>. We assume that you have created your SSH public key, set up your SSH agent with this key, and that this key gives you access to <systemitem
       
    48 class="systemname">jeeves</systemitem>.  
       
    49 </para>
       
    50 <para>First install mercurial-server on <systemitem
       
    51 class="systemname">jeeves</systemitem>:</para>
       
    52 <screen><computeroutput>jay@spoon:~$ </computeroutput><userinput>scp mercurial-server_0.6.1_amd64.deb jeeves:</userinput>
       
    53 <computeroutput>mercurial-server_0.6.1_amd64.deb 100%
       
    54 jay@spoon:~$ </computeroutput><userinput>ssh -A jeeves</userinput>
       
    55 <computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo dpkg -i mercurial-server_0.6.1_amd64.deb</userinput>
       
    56 <computeroutput>[sudo] password for jay: 
       
    57 Selecting previously deselected package mercurial-server.
       
    58 (Reading database ... 144805 files and directories currently installed.)
       
    59 Unpacking mercurial-server (from .../mercurial-server_0.6.1_amd64.deb) ...
       
    60 Setting up mercurial-server (0.6.1) ...
       
    61 jay@jeeves:~$ </computeroutput></screen>
       
    62 <para>
       
    63 mercurial-server is now installed on the repository host.  Next, we need to give you permission to access its repositories.
       
    64 </para>
       
    65 <screen><computeroutput>jay@jeeves:~$ </computeroutput><userinput>ssh-add -L > my-key</userinput>
       
    66 <computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo mkdir -p /etc/mercurial-server/keys/root/jay</userinput>
       
    67 <computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo cp my-key /etc/mercurial-server/keys/root/jay/spoon</userinput>
       
    68 <computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo -u hg /usr/share/mercurial-server/refresh-auth</userinput>
       
    69 <computeroutput>jay@jeeves:~$ </computeroutput><userinput>exit</userinput>
       
    70 <computeroutput>Connection to jeeves closed.
       
    71 jay@spoon:~$ </computeroutput></screen>
       
    72 <para>
       
    73 You can now create repositories on the remote machine and have complete
       
    74 read-write access to all of them.
       
    75 </para>
       
    76 </section>
       
    77 <section>
       
    78 <title>Creating repositories</title>
       
    79 <para>
       
    80 To store a repository on the server, clone it over.
       
    81 </para>
       
    82 <screen><computeroutput>jay@spoon:~$ </computeroutput><userinput>cd myproj</userinput>
       
    83 <computeroutput>jay@spoon:~/myproj$ </computeroutput><userinput>hg clone . ssh://hg@jeeves/jays/project</userinput>
       
    84 <computeroutput>searching for changes
       
    85 remote: adding changesets
       
    86 remote: adding manifests
       
    87 remote: adding file changes
       
    88 remote: added 119 changesets with 284 changes to 61 files
       
    89 jay@spoon:~/myproj$ </computeroutput><userinput>hg pull ssh://hg@jeeves/jays/project</userinput>
       
    90 <computeroutput>pulling from ssh://hg@jeeves/jays/project
       
    91 searching for changes
       
    92 no changes found
       
    93 <computeroutput>jay@spoon:~/myproj$ </computeroutput><userinput>cd ..</userinput>
       
    94 jay@spoon:~$ </computeroutput></screen>
       
    95 </section>
       
    96 <section>
       
    97 <title>Adding other users</title>
       
    98 <para>
       
    99 At this stage, no-one but you has any access to any repositories you
       
   100 create on this system. In order to give anyone else access, you'll need a
       
   101 copy of their SSH public key; we'll assume you have that key in
       
   102 <filename>~/sam-saucer-key.pub</filename>.  To manage access, you make changes to the special <filename
       
   103 class='directory'>hgadmin</filename> repository.
       
   104 </para>
       
   105 <screen><computeroutput>jay@spoon:~$ </computeroutput><userinput>hg clone ssh://hg@jeeves/hgadmin</userinput>
       
   106 <computeroutput>destination directory: hgadmin
       
   107 no changes found
       
   108 updating working directory
       
   109 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
       
   110 jay@spoon:~$ </computeroutput><userinput>cd hgadmin</userinput>
       
   111 <computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>mkdir -p keys/users/sam</userinput>
       
   112 <computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>cp ~/sam-saucer-key.pub keys/users/sam/saucer</userinput>
       
   113 <computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>hg add</userinput>
       
   114 <computeroutput>adding keys/users/sam/saucer
       
   115 jay@spoon:~/hgadmin$ </computeroutput><userinput>hg commit -m "Add Sam's key"</userinput>
       
   116 <computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>hg push</userinput>
       
   117 <computeroutput>pushing to ssh://hg@jeeves/hgadmin
       
   118 searching for changes
       
   119 remote: adding changesets
       
   120 remote: adding manifests
       
   121 remote: adding file changes
       
   122 remote: added 1 changesets with 1 changes to 1 files
       
   123 jay@spoon:~/hgadmin$ </computeroutput></screen>
       
   124 <para>
       
   125 Sam can now read and write to your
       
   126 <uri>ssh://hg@jeeves/jays/project</uri> repository.
       
   127 Most other changes to access control can be made simply by making and
       
   128 pushing changes to <filename
       
   129 class='directory'>hgadmin</filename>, and you can use Mercurial to
       
   130 cooperate with other root users in the normal way.
       
   131 </para>
       
   132 <para>
       
   133 If you prefer, you could give them access by
       
   134 logging into <systemitem class="systemname">jeeves</systemitem>,
       
   135 putting the key in the right place under <filename
       
   136 class='directory'>/etc/mercurial-server/keys</filename>, and re-running
       
   137 <userinput>sudo -u hg /usr/share/mercurial-server/refresh-auth</userinput>.
       
   138 However, using <filename
       
   139 class='directory'>hgadmin</filename> is usually more convenient if you need to make more than a very few changes; it also makes it easier to share administration with others and provides a log of all changes.
       
   140 </para>
       
   141 </section>
       
   142 </section>
       
   143 <section>
       
   144 <title>Access control</title>
       
   145 <para>
       
   146 Out of the box, mercurial-server supports two kinds of users: "root" users and normal users.  If you followed the steps above, you are a "root" user because your key is under <filename class='directory'>keys/root</filename>, while the other user you gave access to is a normal user since their key is under <filename class='directory'>keys/users</filename>.  Keys that are not in either of these directories will by default have no access to anything.
       
   147 </para>
       
   148 <para>
       
   149 Root users can edit <filename
       
   150 class='directory'>hgadmin</filename>, create new repositories and read and write to existing ones.  Normal users cannot access <filename
       
   151 class='directory'>hgadmin</filename> or create new repositories, but they can read and write to any other repository.
       
   152 </para>
       
   153 <section>
       
   154 <title>Using access.conf</title>
       
   155 <para>
       
   156 mercurial-server offers much more fine-grained access control than this division into two classes of users.  Let's suppose you wish to give Pat access to the <filename
       
   157 class='directory'>widget</filename> repository, but no other.  We first copy Pat's SSH public key into the <filename
       
   158 class='directory'>keys/pat</filename> directory in <filename
       
   159 class='directory'>hgadmin</filename>.  This tells mercurial-server about Pat's key, but gives Pat no access to anything because the key is not under either <filename
       
   160 class='directory'>keys/root</filename> or <filename
       
   161 class='directory'>keys/users</filename>.  To grant this key access, we must give mercurial-server a new access rule, so we create a file in <filename
       
   162 class='directory'>hgadmin</filename> called <filename>access.conf</filename>, with the following contents:</para>
       
   163 <programlisting># Give Pat access to the "widget" repository
       
   164 write repo=widget user=pat
       
   165 </programlisting>
       
   166 <para>
       
   167 Pat will have read and write access to the <filename
       
   168 class='directory'>widget</filename> repository as soon as we add, commit, and push these files.
       
   169 </para>
       
   170 <para>
       
   171 Each line of <filename>access.conf</filename> has the following syntax:
       
   172 </para>
       
   173 <programlisting><replaceable>rule</replaceable> <replaceable>condition</replaceable> <replaceable>condition...</replaceable>
       
   174 </programlisting>
       
   175 <para>
       
   176 Blank lines and lines that start with <code>#</code> are ignored. Rule is
       
   177 one of
       
   178 </para>
       
   179 <itemizedlist>
       
   180 <listitem>
       
   181 <literal>init</literal>: allow reads, writes, and the creation of new repositories
       
   182 </listitem>
       
   183 <listitem>
       
   184 <literal>write</literal>: allow reads and writes
       
   185 </listitem>
       
   186 <listitem>
       
   187 <literal>read</literal>: allow only read operations
       
   188 </listitem>
       
   189 <listitem>
       
   190 <literal>deny</literal>: deny all requests
       
   191 </listitem>
       
   192 </itemizedlist>
       
   193 <para>
       
   194 A condition is a globpattern matched against a relative path. The two most
       
   195 important conditions are
       
   196 </para>
       
   197 <itemizedlist>
       
   198 <listitem>
       
   199 <code>user=<replaceable>globpattern</replaceable></code>: path to the user's key
       
   200 </listitem>
       
   201 <listitem>
       
   202 <code>repo=<replaceable>globpattern</replaceable></code>: path to the repository
       
   203 </listitem>
       
   204 </itemizedlist>
       
   205 <para>
       
   206 <code>*</code> only matches one directory level, where <code>**</code>
       
   207 matches as many as you want. More precisely, <code>*</code> matches zero or
       
   208 more characters not including <code>/</code> while <code>**</code> matches
       
   209 zero or more characters including <code>/</code>. So
       
   210 <code>projects/*</code> matches <filename
       
   211 class='directory'>projects/foo</filename> but not <filename
       
   212 class='directory'>projects/foo/bar</filename>, while
       
   213 <code>projects/**</code> matches both.
       
   214 </para>
       
   215 <para>
       
   216 When considering a request, mercurial-server steps through all the rules in
       
   217 <filename>/etc/mercurial-server/access.conf</filename> and then all the
       
   218 rules in <filename>access.conf</filename> in <filename
       
   219 class='directory'>hgadmin</filename>
       
   220 looking for a rule which matches on every condition. The first match
       
   221 determines whether the request will be allowed; if there is no match in
       
   222 either file, the request will be denied.
       
   223 </para>
       
   224 <para>
       
   225 By default, <filename>/etc/mercurial-server/access.conf</filename> has the
       
   226 following rules:
       
   227 </para>
       
   228 <programlisting>init user=root/**
       
   229 deny repo=hgadmin
       
   230 write user=users/**
       
   231 </programlisting>
       
   232 <para>
       
   233 These rules ensure that root users can do any operation on any repository,
       
   234 that no other users can access the <filename
       
   235 class='directory'>hgadmin</filename> repository,
       
   236 and that those with keys in <filename
       
   237 class='directory'>keys/users</filename> can read or write to any repository
       
   238 but not create repositories.  Some examples of how these rules work:
       
   239 </para>
       
   240 <itemizedlist>
       
   241 <listitem>
       
   242 User <filename class='directory'>root/jay</filename> creates a repository
       
   243 <filename class='directory'>foo/bar/baz</filename>. This matches the first
       
   244 rule and so will be allowed.
       
   245 </listitem>
       
   246 <listitem>
       
   247 User <filename class='directory'>root/jay</filename> changes repository
       
   248 <filename class='directory'>hgadmin</filename>. Again, this matches the
       
   249 first rule and so will be allowed; later rules have no effect.
       
   250 </listitem>
       
   251 <listitem>
       
   252 User <filename class='directory'>users/sam</filename> tries to read
       
   253 repository <filename class='directory'>hgadmin</filename>. This does not
       
   254 match the first rule, but matches the second, and so will be denied.
       
   255 </listitem>
       
   256 <listitem>
       
   257 User <filename class='directory'>users/sam</filename> tries to create
       
   258 repository <filename class='directory'>sams-project</filename>. This does
       
   259 not match the first two rules, but matches the third; this is a
       
   260 <literal>write</literal> rule, which doesn't grant the privilege to create
       
   261 repositories, so the request will be denied.
       
   262 </listitem>
       
   263 <listitem>
       
   264 User <filename class='directory'>users/sam</filename> writes to existing
       
   265 repository <filename class='directory'>projects/main</filename>. Again,
       
   266 this matches the third rule, which allows the request.
       
   267 </listitem>
       
   268 <listitem>
       
   269 User <filename class='directory'>pat</filename> tries to write to existing
       
   270 repository <filename class='directory'>widget</filename>. Until we change
       
   271 the <filename>access.conf</filename> file in <filename
       
   272 class='directory'>hgadmin</filename>, this will match no rule, and so will
       
   273 be denied.
       
   274 </listitem>
       
   275 <listitem>
       
   276 Any request from a user whose key not under the <filename
       
   277 class='directory'>keys</filename> directory at all will always be denied,
       
   278 no matter what rules are in effect; because of the way SSH authentication
       
   279 works, they will be prompted to enter a password, but no password will
       
   280 work. This can't be changed.
       
   281 </listitem>
       
   282 </itemizedlist>
       
   283 </section>
       
   284 <section>
       
   285 <title>/etc/mercurial-server and hgadmin</title>
       
   286 <para>
       
   287 mercurial-server consults two distinct locations to collect information about what to allow: <filename
       
   288 class='directory'>/etc/mercurial-server</filename> and its own <filename
       
   289 class='directory'>hgadmin</filename> repository.  This is useful for several reasons:
       
   290 </para>
       
   291 <itemizedlist>
       
   292 <listitem>
       
   293 Some users may not need the convenience of access control via mercurial; for these users updating <filename
       
   294 class='directory'>/etc/mercurial-server</filename> may offer a simpler route.
       
   295 </listitem>
       
   296 <listitem>
       
   297 <filename class='directory'>/etc/mercurial-server</filename> is suitable
       
   298 for management with tools such as <link
       
   299 xlink:href="http://reductivelabs.com/products/puppet">Puppet</link>
       
   300 </listitem>
       
   301 <listitem>
       
   302 If a change to <filename
       
   303 class='directory'>hgadmin</filename> leaves you "locked out", <filename
       
   304 class='directory'>/etc/mercurial-server</filename> allows you a way back in.
       
   305 </listitem>
       
   306 <listitem>
       
   307 At install time, all users are "locked out", and so some mechanism to allow some users in is needed.
       
   308 </listitem>
       
   309 </itemizedlist>
       
   310 <para>
       
   311 Rules in <filename>/etc/mercurial-server/access.conf</filename> are checked before those in <filename
       
   312 class='directory'>hgadmin</filename>, and keys in <filename class='directory'>/etc/mercurial-server/keys</filename> will be present no matter how <filename
       
   313 class='directory'>hgadmin</filename> changes.
       
   314 </para>
       
   315 <para>
       
   316 We anticipate that once mercurial-server is successfully installed and
       
   317 working you will usually want to use <filename
       
   318 class='directory'>hgadmin</filename> for most
       
   319 access control tasks. Once you have the right keys and
       
   320 <filename>access.conf</filename> set up in <filename
       
   321 class='directory'>hgadmin</filename>, you
       
   322 can delete <filename>/etc/mercurial-server/access.conf</filename> and all
       
   323 of <filename class='directory'>/etc/mercurial-server/keys</filename>,
       
   324 turning control entirely over to <filename
       
   325 class='directory'>hgadmin</filename>.
       
   326 </para>
       
   327 <para>
       
   328 <filename>/etc/mercurial-server/remote-hgrc</filename> is in the
       
   329 <systemitem>HGRCPATH</systemitem> for all remote access to mercurial-server
       
   330 repositories. This file contains the hooks that mercurial-server uses for
       
   331 access control and logging. You can add hooks to this file, but obviously
       
   332 breaking the existing hooks will disable the relevant functionality and
       
   333 isn't advisable.
       
   334 </para>
       
   335 </section>
       
   336 <section>
       
   337 <title>File and branch conditions</title>
       
   338 <para>
       
   339 mercurial-server supports file and branch conditions, which restrict an
       
   340 operation depending on what files it modifies and what branch the work is
       
   341 on. </para>
       
   342 <caution>
       
   343 The way these conditions work is subtle and can be counterintuitive. Unless
       
   344 you need what they provide, ignore this section, stick to user and repo
       
   345 conditions, and then things are likely to work the way you would expect. If
       
   346 you do need what they provide, read what follows very carefully.
       
   347 </caution>
       
   348 <para>
       
   349 File and branch conditions are added to the conditions against which a rule
       
   350 matches, just like user and repo conditions; they have this form:
       
   351 </para>
       
   352 <itemizedlist>
       
   353 <listitem>
       
   354 <code>file=<replaceable>globpattern</replaceable></code>: file within the repo
       
   355 </listitem>
       
   356 <listitem>
       
   357 <code>branch=<replaceable>globpattern</replaceable></code>: Mercurial branch name
       
   358 </listitem>
       
   359 </itemizedlist>
       
   360 <para>
       
   361 However, in order to understand what effect adding these conditions will
       
   362 have, it helps to understand how and when these rules are applied.
       
   363 </para>
       
   364 <para>
       
   365 The rules file is used to make three decisions:
       
   366 </para>
       
   367 <itemizedlist>
       
   368 <listitem>
       
   369 Whether to allow a repository to be created
       
   370 </listitem>
       
   371 <listitem>
       
   372 Whether to allow any access to a repository
       
   373 </listitem>
       
   374 <listitem>
       
   375 Whether to allow a changeset
       
   376 </listitem>
       
   377 </itemizedlist>
       
   378 <para>
       
   379 When the first two of these decisions are being made, nothing is known
       
   380 about any changsets that might be pushed, and so all file and branch
       
   381 conditions automatically succeed for the purpose of such decisions. For the
       
   382 third condition, every file changed in the changeset must be allowed by a
       
   383 <literal>write</literal> or <literal>init</literal> rule for the changeset
       
   384 to be allowed.
       
   385 </para>
       
   386 <para>
       
   387 This means that doing tricky things with file conditions can have
       
   388 counterintuitive consequences:
       
   389 </para>
       
   390 <itemizedlist>
       
   391 <listitem>
       
   392 <para>You cannot limit read access to a subset of a repository with a <literal>read</literal>
       
   393 rule and a file condition: any user who has access to a repository can read
       
   394 all of it and its full history. Such a rule can only have the effect of
       
   395 masking a later <literal>write</literal> rule, as in this example:</para>
       
   396 <programlisting>read repo=specialrepo file=dontwritethis
       
   397 write repo=specialrepo
       
   398 </programlisting>
       
   399 <para>
       
   400 allows all users to read <literal>specialrepo</literal>, and to write to all files
       
   401 <emphasis>except</emphasis> that any changeset which writes to
       
   402 <filename>dontwritethis</filename> will be rejected.
       
   403 </para>
       
   404 </listitem>
       
   405 <listitem>
       
   406 For similar reasons, don't give <literal>init</literal> rules file conditions.
       
   407 </listitem>
       
   408 <listitem>
       
   409 <para>Don't try to deny write access to a particular file on a particular
       
   410 branch&#x2014;a developer can write to the file on another branch and then merge
       
   411 it in. Either deny all writes to the branch from that user, or allow them
       
   412 to write to all the files they can write to on any branch.
       
   413 </para>
       
   414 <programlisting>write user=docs/* branch=docs file=docs/*
       
   415 </programlisting>
       
   416 <para>
       
   417 This rule grants users whose keys are in the <filename
       
   418 class='directory'>docs</filename> subdirectory the power to push changesets
       
   419 into any repository only if those changesets are on the
       
   420 <literal>docs</literal> branch and they affect only those files directly
       
   421 under the <filename class='directory'>docs</filename> directory. However,
       
   422 the rules below have more counterintuitive consequences.
       
   423 </para>
       
   424 <programlisting>write user=docs/* branch=docs
       
   425 write user=docs/* file=docs/*
       
   426 read user=docs/*
       
   427 </programlisting>
       
   428 <para>
       
   429 These rules grant users whose keys are in the <filename
       
   430 class='directory'>docs</filename> subdirectory the power to change any file directly under the <filename class='directory'>docs</filename> directory, or any file at all in the <literal>docs</literal> branch.  Indirectly, however, this adds up to the power to change any file on any branch, simply by making the change on the docs branch and then merging the change into another branch.
       
   431 </para>
       
   432 </listitem>
       
   433 </itemizedlist>
       
   434 </section>
       
   435 </section>
       
   436 <section>
       
   437 <title>How mercurial-server works</title>
       
   438 <para>
       
   439 All of the repositories controlled by mercurial-server are owned by a
       
   440 single user, the <systemitem
       
   441 class="username">hg</systemitem> user, which is why all URLs for
       
   442 mercurial-server repositories start with <uri>ssh://hg@...</uri>.
       
   443 Each SSH key that has access to the repository has an entry in
       
   444 <filename>~hg/.ssh/authorized_keys</filename>; this is how the SSH daemon
       
   445 knows to give that key access. When the user connects over SSH, their
       
   446 commands are run in a custom restricted shell; this shell knows which key
       
   447 was used to connect, determines what the user is trying to do, checks the
       
   448 access rules to decide whether to allow it, and if allowed invokes
       
   449 Mercurial internally, without forking.
       
   450 </para>
       
   451 <para>
       
   452 This restricted shell also ensures that certain Mercurial extensions are
       
   453 loaded when the user acts on a repository; these extensions check the
       
   454 access control rules for any changeset that the user tries to commit, and
       
   455 log all pushes and pulls into a per-repository access log.
       
   456 </para>
       
   457 <para>
       
   458 <command>refresh-auth</command> recurses through the <filename
       
   459 class='directory'>/etc/mercurial-server/keys</filename> and the <filename
       
   460 class='directory'>keys</filename> directory in the
       
   461 <filename
       
   462 class='directory'>hgadmin</filename> repository, creating an entry in
       
   463 <filename>~hg/.ssh/authorized_keys</filename> for each one. This is redone
       
   464 automatically whenever a change is pushed to <filename
       
   465 class='directory'>hgadmin</filename>.
       
   466 </para>
       
   467 </section>
       
   468 <section>
       
   469 <title>Security</title>
       
   470 <para>
       
   471 mercurial-server relies entirely on <command>sshd</command> to grant access to remote users.
       
   472 As a result, it runs no daemons, installs no setuid programs, and no part
       
   473 of it runs as <systemitem
       
   474 class="username">root</systemitem> except the install process: all programs run as the user
       
   475 <systemitem
       
   476 class="username">hg</systemitem>. Any attack on mercurial-server can only be started if the attacker
       
   477 already has a public key in <filename>~hg/.ssh/authorized_keys</filename>,
       
   478 otherwise <command>sshd</command> will bar the way.
       
   479 </para>
       
   480 <para>
       
   481 No matter what command the user tries to run on the remote system via SSH,
       
   482 mercurial-server is run. It parses the command line the user asked for, and
       
   483 interprets and runs the corresponding operation itself if access is
       
   484 allowed, so users can only read and add to history within repositories;
       
   485 they cannot run any other command. In addition, every push and pull is
       
   486 logged with a datestamp, changeset ID and the key that performed the
       
   487 operation.
       
   488 </para>
       
   489 <para>
       
   490 However, while the first paragraph holds no matter what bugs
       
   491 mercurial-server contains, the second depends on the relevant code being
       
   492 correct; though the entire codebase is short, mercurial-server is a fairly
       
   493 new program and may harbour bugs. Backups are essential!
       
   494 </para>
       
   495 </section>
       
   496 <section>
       
   497 <title>Legalese</title>
       
   498 <para>
       
   499 This program is free software; you can redistribute it and/or modify it
       
   500 under the terms of the GNU General Public License as published by the Free
       
   501 Software Foundation; either version 2 of the License, or (at your option)
       
   502 any later version.
       
   503 </para>
       
   504 <para>
       
   505 This program is distributed in the hope that it will be useful, but
       
   506 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
       
   507 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
       
   508 more details.
       
   509 </para>
       
   510 <para>
       
   511 You should have received a copy of the GNU General Public License along
       
   512 with this program; if not, write to the Free Software Foundation, Inc., 51
       
   513 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
       
   514 </para>
       
   515 </section>
       
   516 <section>
       
   517 <title>Thanks</title>
       
   518 <para>
       
   519 Thanks for reading this far. If you use mercurial-server, please tell me about
       
   520 it.
       
   521 </para>
       
   522 <para>
       
   523 Paul Crowley, <email>paul@lshift.net</email>, 2009
       
   524 </para>
       
   525 </section>
       
   526 </article>
       
   527