Darcs server extends the Darcs revision control system to push and pull changes to and from remote repositories. The Darcs server has minimal dependencies on the host system and can work on any account that can run CGI scripts, or has SSH access. Furthermore, it can restrict the users that can push or pull from the repository, and even encrypt all communication with the server.
For example, if you have already have a public repository on the web, you can directly allow others to push changes to that repository using CGI or through your regular SSH account (without giving others full SSH access of course). Or, you can setup a hidden repository that uses cryptographic encryption and verification to only allow authorized users to use the repository; again, this can work either through CGI or SSH
Darcs client:
Darcs server:
To push remote changes, you need the darcs program and the darcs-client program.
Suppose that there is a public repository on the web. Darcs can already get such repository and pull changes from it.
> darcs get http://domain.com/repos/myrepo
The darcs-client program can push changes directly to a remote repository if a darcs server is running. When you set the DARCS_APPLY_HTTP environment variable, darcs will automatically invoke the darcs-client program to push changes remotely. For example:
> export DARCS_APPLY_HTTP="darcs-client apply"
You can use the normal darcs commands to push your changes:
> darcs push Pushing to "http://www.domain.com/repos/myrepo"... Mon Mar 6 20:28:55 Pacific Standard Time 2006 Daan Leijen * Update darcs client documentation Shall I push this patch? (1/1) [ynWvpxqadjk], or ? for help: y Sending patch to remote repository... Server log: Verifying request... ok. Applying patch... Finished applying...
And this is basically it! Of course, this is the common case: the darcs server supports many configurations options, like http and ssh protocols, signed patches, encryption, per-user restrictions etc, that sometimes require more configuration on your part. You can configure darcs client by editing its configuration files, either in your darcs home directory, $HOME/.darcs/server.config, or in your repository directory _darcs/prefs/server.config. For example, we can use verbose output by adding:
verbose = yes
More options are introduced when describing relevant features. A full list of configuration option can be found in the configuration section.
The darcs server might be set up to only accept writes over ssh (instead of http). In that case, you need to have ssh access to the server. Usually, you can get this by sending your ssh public key to the repository administrator and asking for write access.
Darcs contacts the server using your default ssh key. You can customize the key with the ssh configuration option. This can be useful for example if you want to use a special (passphrase-less) key for darcs.
For example:
ssh = ssh -i ~/.ssh/id_darcs # use my id_darcs identity
If the darcs server accepts a remote push over http, it is usually configured to verify patches before authorizing the push. This means that you need to install the gpg program to sign your patches with your personal signature. After installing this program you can generate your personal key:
> gpg --gen-key
You are prompted for your name, email, and other options. Of course, you can skip this step if you already have a gpg key that you wish to use. To get authorized for remote push, you should send your public key to the administrator of the repository. You can export your public key using:
> gpg --armor --export <my name> > my_public_key.asc
Once you have authorization, any remote push will automatically be signed by the darcs-client with your default key. You can actually customize the key with the gpg configuration option. This can be useful for example if you want to use a special (passphrase-less) key for darcs. For example:
gpg = gpg -u <my name>
See also the darcs notes on gpg for information about using a gpg-agent program for passphrase keys.
A darcs server can be configured to encrypt all its communication. Again, you need the gpg program to encrypt and decrypt patches. Furthermore, you need the public key of the server in order to encrypt information that you send to the server. If you have not imported the server key yet, the darcs-client automatically downloads the public key to make it easy to import the key in your public key ring.
> gpg --import _darcs/prefs/repokey.asc
After you have imported the key, you can view the fingerprint of the key:
> gpg --fingerprint =<server identity>
You should verify if the fingerprint matches the published fingerprint of the server. The fingerpring can be given to you by paper, or published on a public website for example. The verification step is necessary to prevent a malicious person to pretend to be the darcs server. Once you have verified the key and trust it, you can locally sign it to automatically secure all communication with this server:
> gpg --lsign-key =<server identity>
See also the gpg manual for more information about importing and signing keys.
Usually, the darcs client gets the server address remotely using http, but when the remote repository is not publicly visible you need to specify the server address explicitly. This happens frequently with a pure ssh based solution (but can also be done with a CGI server). For example, the following repository section configures a specific ssh based server for our repository:
# declare the repository identifier repo darcs://domain.com/repos/myrepo server = ssh://username@domain.com # indentation required!
Note that a repository identifier starts with the darcs: protocol, even when it is also accessed
using http:. In general, the darcs: protocol is used to explicitly address the darcs-server. You can set the following environment variables to invoke the darcs client whenever the darcs: protocol is specified.
> export DARCS_APPLY_DARCS="darcs-client apply" > export DARCS_GET_DARCS ="darcs-client get" > export DARCS_MGET_DARCS ="darcs-client mget"
When a repository is not publicly visible, the darcs server can instead serve pull and getrequests using the darcs: protocol:
> darcs pull darcs://domain.com/repos/myrepo
or
> darcs get darcs://domain.com/repos/myrepo
Note: when using pull and get using the darcs server, it is necessary on windows systems to set the environment variable DARCS_MGETMAX to at most 50 or otherwise the command line will overflow when darcs client is called by darcs.
The darcs-client program reads configuration options, in priority order, from:
_darcs/prefs/server.config.$HOME/.darcs/server.config.DARCS_GPG and DARCS_SSH._darcs/prefs/server.cache.The configuration files are regular text files that can contain specific configuration options. Note however that one rarely needs to set these as the darcs-client automatically queries the server to retrieve the correct settings to communicate with that server. The configuration options are:
ssh | = <command> | Specify the ssh command to use. |
gpg | = <command> | Specify the gpg command to use. |
verbose | = <yes|no> | Be verbose. |
verify | = <yes|no> | Verify the identity of the server. |
sign-read | = <yes|no> | Sign read requests (ie. get and pull). |
sign-write | = <yes|no> | Sign write requests (ie. push). |
encrypt | = <yes|no> | Encrypt communication with the server. |
dryrun | = <yes|no> | Do not carry out apply commands remotely. |
refresh | = <yes|no> | Refresh the cached server information |
server-id | = <identity> | Use this gpg server key when encrypting and verifying. |
server | = <url> | Use this specific server address. |
repo darcs://<repo url> | Start a repository section. | |
# <comment> | A comment | |
The repo options starts a repository section: all indented options following this declaration are specific to that repository. Note that it is not required to have a repository at the
specfied URL, it just uniquely identifies the repository to the server. Furthermore, the repository
identifiers should start with the darcs: protocol. The server and
server-id options are only allowed in a repository section. Here is a short example of
how your configuration file might look like:
verbose = yes # see what darcs-client is doing verify = yes # verify the server identity gpg = c:\prog\gnupg\gpg # gpg is not in my default path repo darcs://domain.com/repos/myrepo server = http://domain.com/cgi-bin/darcs-server.cgi sign-read = no # don't sign reads (pull and get) sign-write = yes # but do sign writes (push) verify = no # and don't verify this specific server
The server location is always a full URL to either a cgi script, or an ssh account that is set up to invoke the darcs server. For example:
server = http://domain.com/cgi-bin/darcs-server.cgior
server = ssh://username@domain.com
If the server is unknown, the darcs-client tries to retrieve the server location remotely. If the repository is darcs://domain.com/repos/myrepo, it tries to read the remote _darcs/prefs/darcs-server file to locate the server. If that fails it uses darcs://domain.com/cgi-bin/darcs-server.cgi as the default location.
After determining the server location, darcs client contacts the server with an info request to determine the standard options of the server, ie. whether to encrypt, if reads are verified, etc. These options are all taken into account together with the configuration files. Due to this mechanism one usually doesn't have to configure the darcs client at all. Note that this information is cached in the file _darcs/prefs/server.cache so subsequent connections do not need to get this information remotely.
I have tried to make the server requirements as minimal as possible but you need at least a darcs binary on your server and be able to run Perl scripts. Furthermore, you must either have an SSH enabled account, or be allowed to run CGI scripts. Actually most providers provide most of these and the hardest thing might be to get your hands on darcs binary that runs on your platform.
First of all, you should create a private darcs server directory on your account, for example $HOME/.darcs-server.
/home/user> mkdir .darcs-server /home/user> chmod 700 .darcs-server
If you run the darcs server over cgi, you might actually have to make the directory group-readable since the cgi script might run under the web server account.
Next, from the distribution server directory, you should copy the files config, darcs-server-lib.pl and darcs-server.pl to this directory.
Open the darcs-server.pl file and edit line 10 to point to your new darcs server directory:
my $darcs_server_home = "/home/user/.darcs-server";
It is important that this is a full and absolute path (do not use a ~ for example). The file config in your darcs server directory contains the configuration of the server. Open this file in an editor and add information about each repository. For example, your
config file can look like:
# a repository declaration, specific options follow on indented lines. repo darcs://domain.com/user/repos/myrepo local = /home/user/www/repos/myrepo # the local directory allow-read = yes # everyone can read allow-write = yes # everyone can write
Of course, you can have as many repositories as you want. If the repository doesn't exist yet, you should either copy a repository there or create the directory and do a darcs init.
If the repository is publicly available through the web, you can also add a file _darcs/prefs/darcs-server that contains a single line with the url of your darcs server cgi script or ssh connection. This allows clients to automatically connect to your server. In our example, we would put this file in /home/user/www/repos/myrepo with either the cgi script location:
http://domain.com/user/cgi-bin/darcs-server.cgi
or the ssh connection:
ssh://user@domain.com
The darcs server can serve requests using SSH or a CGI script. Even though the darcs server does not care which protocol is used, the configuration is usually quite different since SSH and CGI handle security in an entirely different manner. In particular, CGI uses the gpg program to secure the connection and authenticate users. Therefore, I'll discuss the SSH and CGI configurations separately.
Making the repositories available via CGI is as simple as copying the darcs-server.pl file to your cgi-bin directory and renaming the extension to .cgi. Note that if the repository is not publicly available, clients need to set the server script now explicitly in their global configuration file as described in the section "A non-public repository".
You can restrict write (push) rights to specific users. Clients can sign their requests using gpg which are verified by the server for authorization. In your darcs server config file, the verify-write option specifies a keyring that is used to verify write requests. For example:
repo darcs://domain.com/user/repos/myrepo local = /home/user/www/repos/myrepo allow-read = yes allow-write = yes verify-write = myrepo.keyring
By using a relative location, darcs server will look in the darcs server directory for the myrepo.keyring file. Users that want write access can send their public key to you, and you can authorize them by importing their key into this keyring:
/home/user/.darcs-server> gpg --homedir=. --no-default-keyring \
--keyring=myrepo.keyring --import userkey.asc
The --no-default-keyring option is necessary to prevent gpg from importing the key in your default keyring too. Furthermore, it is good practice to always use the --homedir option to
point to your darcs server home directory when managing keys for the darcs server. This prevents mixing your darcs server keys with your private keyring. When the server invokes gpg it always sets the gpg home directory to point to the darcs server home directory.
In the same way, we can also restrict access to readers (pull and get). Of course, this only makes sense when the repository is not also publicly available via the web. The same url can be used for the repository since this is just an identifier. However, we move the repository from the www directory to the home directory so that is no longer available on the web. (One could still leave the _darcs/prefs/darcs-server file there though for client convenience). Here is how our new config file looks like:
repo darcs://domain.com/user/repos/myrepo
local = /home/user/private/repos/myrepo # private now!
allow-read = yes
allow-write = yes
verify-read = myrepo-read.keyring
verify-write = myrepo.keyring
We used a separate keyring for read verification, but of course we could just as well share the myrepo.keyring keyring.
It is a good practice to sign all responses from the server with a server signature. This way, users can verify that they communicate with the server they expect. To make this work, you should generate a local server key in the darcs server directory.
/home/user/.darcs-server> gpg --homedir=. --gen-key
You will be prompted for the name, email, and other options. It is recommended to use the name darcs://domain.com as the server key with an empty email address. If you use another identity, you will need to specify this identity using the server-id configuration option. Again, the homedir option needs to point to the darcs server home directory. Since the darcs server signs automatically, you should probably use a passphrase-less key (or configure your system to work with gpg-agent).
Once you generated the key, you can turn signing on by setting the sign configuration option.
sign = yes
Like many other options, this can be set either globally, or per repository. Also, you should probably publish the fingerprint of your public key on the web, so that users can verify if their public key really comes from your server.
/home/user/.darcs-server> gpg --homedir=. --fingerprint darcs://domain.com
To guard your precious code against spies that sniff the network, you can encrypt all the darcs-server communication using gpg. This requires that you have set up a server key and that users also install the gpg program. Usually, you also use the verify-read, verify-write, and sign options in combination with encryption. Encryption requires that you have set up a server key.
The encrypt option enables encryption. For example, we can encrypt all communication for all repositories by setting it globally in the config file:
encrypt = yes
Using a secure shell (SSH) is ideal when you can not run CGI scripts, or if you only expose your repository to a few users. A great advantage of darcs server is that you do not need to set up different user accounts for your repository, but you can give users restricted access via SSH through your normal account. This is done via the command option in SSH that restricts SSH to users to only that particular command. In our case, we just allow them to run the darcs-server program. Note that this also extends to utilities like scp. Users restricted in this fashion can not do anything on your account except accessing the repositories via darcs-server.
To enable access through SSH we add the user key to the .ssh/authorized_keys file on the system. In front of the key, we add the command option that restrict the user to just running the darcs server script. Here is an example with an SSH1 RSA user key:
command="/home/user/.darcs-server/darcs-server.pl" ssh-rsa AB3NzaC1yc2EAAAABIwA AAIEAqwRPEALGQbrhQQST9Obkj2OJrUsaRi1SYtFm5/vYJ/BDfViek5wVC028Q1V1yWDHmJy9DzFXae Z8kE2JM1wsbAN4SC2vryk8pJ631jh5Oq+PY1e39vlaEIv5uA+ECriyQz+DjLhy/oDmpk5neGMSwxOuL eXDU+eSvtK7UPNiVbRFOkOeod6viMJhK4BpNbPrClrtD6EpyJ5DhXDR7Bes/Rw== user@machine
It would be even better restrict the account even further by adding more options:
environment="DARCS_LOGNAME=david",no-port-forwarding,no-X11-forwarding,no-agent -forwarding,no-pty,command="/home/user/.darcs-server/darcs-server.pl" 1024 35 1 1817553790683499614097477370143348554184947854197722520418362286832782798975041 6099265220678021589492998916740713078238841607878229644157746694554723410376922 6364379796527302475112019022875978629812291126063895867418421028449705770038994 665511517190400155609012033981180255475519919550519308405663149 david@darcs.net
This an example with a newer SSH2 DSA key. There are quite a lot of options but it can never hurt to be careful. Note that there are no spaces between the options. Here is a short article that explains what these options actually mean and why it is safer to use them. As we will see later, it is good
practice to give each user a DARCS_LOGNAME using the environment option. Actually, on my
system the environement doesn't seem to work so I use the env program:
command="env DARCS_LOGNAME=david /home/user/.darcs-server/darcs-server.pl"
Note that if the repository is not publicly available, clients need to set the server now explicitly in their global configuration file as described in the section "A non-public repository".
Through the SSH protocol you can already control who can access the server. However, you
might want to restrict write access to specific repositories. One way is using gpg to verify writes as described above for the CGI protocol. However, since SSH already authenticates users, we can also use SSH itself to restrict access. The verify-write-logname configuration option restricts the users that are allowed write access based on the DARCS_LOGNAME given in the SSH authorized_keys file. For example, we can give David write access as follows:
repo darcs://domain.com/user/repos/myrepo # the url is just an identifier
local = /home/user/repos/myrepo
allow-read = yes
allow-write = yes
verify-write-logname = david
The list of names is comma separated and names can not contain spaces. You can use += instead of = to append long lists of names.
In the same way we can also restrict read access (which is of course only sensible when the repository is not also publicly available over the web). Restricting read access can also be convenient if you manage multiple repositories through a single SSH account. For example:
repo darcs://domain.com/user/repos/myrepo # the url is just an identifier
local = /home/user/repos/myrepo
allow-read = yes
allow-write = yes
verify-read-logname = david,tommy,juliusz
verify-write-logname = david
Again, another possibility to restrict read access is by using the gpg program as described above for the CGI protocol using the verify-read option.
Since SSH already encrypts all communication and authenticates the server, it is not necessary to use explicit signatures and encryption as is shown above for the CGI protocol.
The darcs-server script reads configuration options from the config file in the directory specified by the $darcs_server_home variable on line 10. The configuration file is a regular text file. The configuration options that can be set are:
# <comment> | A comment | |
repo darcs://<repo url> | Start a repository section. | |
local | = <directory> | Set the local repository directory. |
allow-read | = <yes|no> | Allow read access. |
allow-write | = <yes|no> | Allow write access. |
verify-read | = <yes|no|<keyring>> | Verify reads using a specified keyring. |
verify-write | = <yes|no|<keyring>> | Verify writes using a specified keyring. |
verify-read-logname | = <no|<names>> | Verify SSH reads using DARCS_LOGNAME names. |
verify-write-logname | = <no|<names>> | Verify SSH writes using DARCS_LOGNAME names. |
sign | = <yes|no> | Sign responses using gpg. |
encrypt | = <yes|no> | Encrypt communication with the server. |
server-id | = <gpg identity> | The gpg server identity for signing and encryption. |
max-request-size | = <size in kb> | The maximal acknowledged request size (4mb). This is a global option! |
max-patch-size | = <size in kb> | The maximal size of a patch bundle to apply (4mb). |
max-file-size | = <size in kb> | The maximal file size that a get or pull will acknowledge (1mb). |
max-file-size | = <size in kb> | The maximal file size that a get or pull will acknowledge (1mb). |
max-files-size | = <size in kb> | The maximal total size that a get or pull will acknowledge (100mb). |
max-files | = <count> | The maximal number of files that a get or pull will acknowledge (200). |
darcs | = <command> | Specify the darcs program. |
apply-options | = <command> | Specify apply options to use. See the security notes! |
gpg | = <command> | Specify the gpg program. |
gpg-options | = <command> | Specify extra gpg options. |
dryrun | = <yes|no> | Do not carry out apply commands. |
Be especially careful with the apply-options option. By default it uses --no-test --no-posthook to prevent execution of test or posthook scripts: an authorized repository writer can in
principle install any tests and run them on the server if the --no-test option is not given!
Here is how your configuration file might look like:
darcs = /home/user/bin/darcs server-id = darcs://domain.com/~user repo http://www.domain.com/~user/repos/myrepo local = /home/user/www/repos/myrepo allow-read = yes allow-write = no sign = yes
When granting others the permissions to write to a remote repository, they can basically write to any file or directory in the repository, and, depending on bugs in other programs, potentially to other locations in your file system. However, I have tried hard to make the server secure:
--no-test and --no-posthook for apply.
The server can use cryptographic verification of user signatures.Potential security holes that you should be aware of are:
command option in the authorized keys, an SSH user can have full access to your account. (This is why I personally believe that a CGI based server is potentially more secure.)apply-options yourself you might enable users to execute arbitrary test scripts or post hooks.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7 Mar 2006