Accessing a cvs repository
This article shows how to use a cvs repository to check out a local copy,
modify the contents, then check the working copy back into the main repository. It
also shows how to control the access to the main repository and how to use ssh
for the connection.
I will assume you have already read cvs –
create your own repository and know how to create a repository. In this article
I will use the term working to refer to a repository which exists on your local
computer. The main repository will exist somewhere else. The working copy is
s q what you check out, modify, then commit back to the main repository. This strategy
is common practice and is The Way To Go(tm).
When I started writing this article, I was trying to get access to a cvs repository
from another box. I promptly became very confused between cvs and cvsup.
cvs
is an Concurrent Versions System. Basically, it’s a repository. cvsup
is a network distribution package for CVS repositories. One is the actual
repository. The other deals with distributing that repository.
You use cvsup to update your ports or get your source code.
The main resource for this article is http://cvsbook.red-bean.com/cvsbook.html.
Setting up the cvs server
Most of this section was taken from The
Password-Authenticating Server and describes how to configure a cvs server. I
will assume the repository is at cvs.example.org. Here’s a command I
could use for the login to that server:
$ cvs -d :pserver:dan@cvs.example.org:/usr/local/cvs login
I’ll come back to the details of this command in a later section. For now, I will
deal with the cvs server setup. The reason for showing this command is that it is
directing cvs to use the pserver method for logging in. This is by
far the most common access method. I’ll now describe how to do enable pserver
on cvs.example.org. This is accomplished with the following steps:
- Ensure the service is in the service name database. This entry should already be
in /etc/services, but you should verify that it is:cvspserver 2401/tcp
- Enable the service via
inetd
by adding the following line (which will
already be present but will require modification) to/etc/inetd.conf
:cvspserver stream tcp nowait root /usr/bin/cvs cvs --allow-root=/usr/local/cvs
pserverNote that the example above differs from that found in the URL above because cvs
is located in a different location under FreeBSD. Use the above. Not that
found in the URL.In this example, the repository resides at
/usr/local/cvs
. - HUP inetd so that it takes notice of the above changes:
# killall -hup inetd
With the above changes, you should be able to connect to the cvs server. Provided
any firewall rules allow it. Here’s a simple test.
$ telnet cvsup.example.org 2401
Trying 203.79.82.27...
Connected to cvsup.example.org.
Escape character is '^]'.
If that’s what you see, then you’ve succeeded in setting up the cvs server.
Congratulations. Now let’s add a bit of security.
Adding passwords to the server
When adding passwords to the server, make sure you don’t use the same
passwords people use to login into the system. Keep them different. If the cvs
passwords are ever compromised, they can’t be used to get into the rest of the system.
I put my cvs repository files under the control of a dedicated user. I
created the user especially for this task. Just use adduser. Read The
Password-Authenticating Server for more detail here.
Here’s what I added to /usr/local/cvs/CVSROOT/passwd
:
dan:tGX1fS8sun6rY:pubcvs
Entries in this file are of the format:
<USERNAME>:<ENCRYPTED_PASSWORD>:<OPTIONAL_SYSTEM_USERNAME>
There’s a script at the above URL for generating such passwords. I suggest you
use it. Note that the output from the password script is time sensitive.
That’s OK. It’s supposed to be that way. It’s not a problem. It’s also
not a bug. That’s by design. And it does work.
Accessing the server using the password
Let’s go back to where I started. This was the command I used to
access the cvs server:
$ cvs -d :pserver:dan@cvs.example.org:/usr/local/cvs login
(Logging in to dan@cvs.example.org)
CVS password:
$
And that’s it. You’re logged into the cvs
server. You can
issue all the normal commands. Such as a checkout:
$ cvs co scripts
cvs server: Updating scripts
U scripts/.procmailrc
U scripts/archive-logs.sh
U scripts/crontab
U scripts/fp-updates.dtd
U scripts/load_xml_into_db.pl
U scripts/log-catcher.awk
U scripts/log-munger.awk
U scripts/openbsd-cvs-parse.pl
U scripts/process_cvs_mail.pl
On the cvs server, the repository resides at /usr/local/cvs
.
We are obtaining the contents of /usr/local/cvs/scripts
. The
above checkout obtains a working copy of that repository. You can treat those files
exactly as you would any other files. See cvs – create
your own repository for command examples.
And when you’re finished, don’t forget to log out.
$ cvs logout
(Logging out of dan@cvs.example.org)
using ssh for added secrecy
Since writing this article, I started using stunnel for my cvs connections.
So far I have been using the pserver method for connecting to the cvs
server. This method works fine and is acceptable over trusted networks (e.g. over
your own LAN). But if the Internet or other shared network lies between you and the cvs
server, you might want to consider using a more secure method. Luckily, cvs
is designed to use other external programs for client-server communication.
In this
example, I’m going to use ssh. In my previous examples, cvs has
been told that the repository exists on another box (e.g. pserver:dan@cvs.example.org).
That works well. But for this example, I’m going to make cvs think
the repository is local, but it will actually reside remotely. I will use an SSH
tunnel for this. This method requires that you have a shell account on the cvs
server and that you an access that account from your workstation. The main reason
I’m using a tunnel is because my cvs server sits behind my gateway and is NAT’d.
If your cvs server is not NAT’d you can use just plain straight ssh.
If you use this method, you’ll also need to use two terminal session on the
workstation. One will be used for your cvs operations. The second
will be used for an ssh tunnel.
My reference for this configuration is http://jakarta.apache.org/site/cvsonunix.html.
- Create the ssh tunnel to the cvs server:
ssh -L 2401:localhost:2401 cvsup.example.org
dan@cvsup.example.org's password:
Last login: Fri Feb 16 09:05:30 2001 from box.example
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD 4.2-STABLE (XEON) #0: Sun Feb 11 14:45:37 NZDT 2001Welcome to the dual XEON.
You will remember port 2401 from above. That’s the port on which cvs
connects to the cvs server. The above command redirects local port 2401 (-L
) to port 2401 on
2401cvsup.example.org
. - login into the cvs server using pserver:
$ cvs -d :pserver:dan@localhost:/usr/local/cvs login
(Logging in to dan@localhost)
CVS password:Note that I am using
localhost
here. Notcvsup.example.org
as I have in previous examples. I can uselocalhost
because of the ssh
tunnel set up in step 1. This tunnel redirects port 2401 on localhost (which the
login will use) to port 2401 on thecvs.example.org
. - use cvs as normal:
$ cvs checkout www
cvs server: Updating www
cvs server: Updating www/imagesThat’s it.
I use screen to keep that second connection in the
background. Note that this command connects to port 2022 because that port is
redirected to the cvs server which is behind a NAT’d gateway.
screen -S tunnel ssh -p 2022 -L 2401:localhost:2401 cvsup.example.org
Then I detach from the screen session, leaving the ssh tunnel in the
background.
Even better than screen, is this approach:
$ ssh -L 2401:localhost:2401 -N -f -g cvsup.example.org
The -N
means you are not supplying a command (e.g. ls
,
sleep
). The -f
makes it go into the background. And
-g
is to allow hosts other than localhost to connect (e.g. other hosts on your
network). Ensure only your network can connect. You don’t want others getting
in there….
plain old ssh
As mentioned before, I used the tunnel because of NAT. But you can
do this:
export CVS_RSH=ssh
export CVSROOT=:ext:dan@cvs.example.org:/usr/local/cvs
I have tried:
CVS_RSH="ssh -p 2022"
because of my NAT’d gateway, but I had no success:
$ cvs checkout www
cvs [checkout aborted]: cannot exec ssh -p 2022: No such file or directory
cvs [checkout aborted]: end of file from server (consult above messages if any)
That’s why I used the ssh tunnel instead.
But since I wrote the above, David MacKenzie wrote in with this solution:
Create a shell script, ssh2022 which contains this:
#!/bin/sh
exec ssh -p 2022 "$@"Then chmod that file:
chmod 755 ssh2022
Then your export statement is:
export CVS_RSH=/usr/local/bin/ssh2022
David says this technique also works with rdist6 -P and rsync -e.
Keep it short and sweet
You don’t have to specify the -d option with the cvs command. You
can set an environment variable:
export CVSROOT=:pserver:dan@cvs.example.org:
/usr/local/cvs
Then you can just issue this command:
$ cvs login
(Logging in to dan@cvs.example.org)
CVS password:
But if you are using an ssh tunnel, you should specify local host. If
you don’t, cvs will ignore the ssh tunnel and connect directly to the remote host
and transmissions will be in clear text.
export CVSROOT=:pserver:dan@localhost:
/usr/local/cvs
Errors I have known (added on 19 June 2002)
I encountered this error when setting up my FreshSource repository:
$ cvs co configuration
cvs checkout: authorization failed: server xeon rejected access to /usr/repo/freshsource for user mike
cvs checkout: used empty password; try "cvs login" with a real password
To fix this problem I had to do two things:
- Remember to add an entry to
/etc/inetd.conf
for the new repository
(/usr/repo/freshsource
). - Add an entry to
~/.cvspass
which related to/usr/repo/freshsource
.
I could have just done a cvs login
instead of step two above. But the problem
was I could not remember my cvs password… So I cheated. Read more about this in
The Red Bean Book section on login.
Well, I just noticed that I never mentioned ~/.cvspass
. I suggest reading
The Red Bean Book and look for Run Control Files.
Other errors I have known (added on 8 January 2003)
I was setting up a new repo today and I really messed something up. Here was the error I was getting on the server:
Jan 8 13:13:33 xeon cvs: login refused for /home/repo/mynewrepo
I was playing with ~/.cvspass
and /home/repo/mynewrepo
to
ensure the passwords were correct. Nothing worked. Finally, I went to /etc/inetd.conf
and found the problem. The line for cvspserver
contained this entry:
--allow-root=/home/repomynewrepo
I had missed a /. I fixed that. Then things worked.
Here is another situation I recently encountered:
$ cvs co www
cvs [checkout aborted]: unrecognized auth response from xeon: cvs [pserver aborted]: descramble: unknown scrambling method
This was a case of the password in ~/.cvspass
on the client not matching the password in
/home/repo/mynewrepo
on the server.
This and the other article on CVS tought me pretty much everything I needed to get going with CVS. The one thing that I did change was to use public keys for establishing the ssh session from my windows machines with a combination of putty, pagent and TurtleCVS.
Works very nicely!
[%sig%]