Installation instructions for the LysCVS system.
by Erik Forsberg <email@example.com>
LysCVS is a system that provides access to CVS in a easily
administered way for both local and external users.
In this release, a local user is a user that's present in NIS. An
external user is all other users, they are present in a MySQL
The functionality is similar to the functionality of sourceforge's CVS
server, with some exceptions:
* Local users still use their passwords to access the system.
* Only local users can create projects.
Aside from that, LysCVS is hopefully a bit less complex to setup, for
a small environment.
2. Theory of operation
There are local users, present in the NIS database, and external
users, not present in the NIS database but kept in a MySQL database.
Local users can create external users and add them to their
projects. External users can administrate projects (add/remove users
of it), but not create them. This way, limits of what projects may be
created are imposed by local rules, that local users hopefully obey
External users account data is accessed through libpam-mysql (for
password information) and nss_mysql (for other user information).
Local users also have a dummy entry in the MySQL database because of
the way nss works.
Projects created by local users get their own cvsroot and can have as
many modules as the users with write access to the repository wants.
Anonymous read-only access is also possible, using pserver. The
pserver is a special patched version. See the part about cvs for
When anonymous read-only access is enabled, a special user called
anoncvs_<projectname> is created and used in the CVSROOT/passwd file.
A mod_python program makes administration of projects easy. It also
frees the system administrator from boring tasks such as
adding/deleting users/projects. The administration webpages are using
a template system (HTMLgen) which means altering the look and feel of
the system is easy (very little hardcoded HTML).
Optionally, using Postfix as Mail Transfer Agent, LysCVS gives each
user (local or external) an email address on the form
Also, LysCVS can create a mailing list for each project that each
project member can decide if he/she want to be a member of. Commit
logs are automatically sent to that mailing list.
The reason you have to use Postfix is that both the mail addresses of
users, and the lists, are created using MySQL alias/virtual tables. I
do not know about any other MTA that can use MySQL, but if there are
such MTAs, you can probably use them after some hacking. Please report
any success doing that.
Note: If you don't want commit logs to be sent to a mailinglist,
you'll have to comment out two lines in scripts/editloginfo.sh and
First, find LysCVS. You've probably succeeded doing that :-).
Unpack the sources. In my examples, they are unpacked to /opt/lyscvs
Create your MySQL database using the file
<installroot>/src/nss.sql. Setup access rights correctly for MySQL.
Install nss_mysql, it's available from
http://savannah.gnu.org/projects/nss-mysql if your
distributions doesn't support it.
Configure nss_mysql. I use the following configuration files:
# This is the user configuration part
users.host = localhost;
users.where_clause = user.status = 'A'; # fully qualifed where clause
users.database = nss;
users.db_user = nss;
users.db_password = <password>;
users.table = user;
users.user_column = user_name;
users.password_column = password; # not used if you have enabled the shadow support
users.userid_column = uid;
users.uid_column = uid;
users.gid_column = gid; # not used if you have run configure --with-default_gid=GID
users.realname_column = realname;
users.homedir_column = homedir; # not used if you have run configure --with-default_home=DIR
users.shell_column = shell;
users.default_gid = 30; # GID of users default group
users.default_home = /home; # used only if you have run configure --with-default_home=DIR
# This is the groups configuration part
# This is only used if you have enabled the group support
groups.host = localhost;
groups.where_clause = groups.status = 'A'; #fully qualified where clause
groups.database = nss;
groups.db_user = nss;
groups.db_password = <password>;
groups.group_info_table = groups;
groups.group_name_column = group_name;
groups.groupid_column = group_id;
groups.members_table = user_group;
groups.member_userid_column = user_id;
groups.member_groupid_column = group_id;
# At this time, we do not support a GID column. We use
# the following trick to choose a GID : gid = group_id + first_gid.
# You should not set first_gid to less than 1000
groups.first_gid = 1000;
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.
passwd: compat mysql
group: compat mysql
hosts: files dns
protocols: db files
services: db files
ethers: db files
rpc: db files
You also need libpam-mysql. I have a /etc/pam.d/sshd that looks like
auth required pam_nologin.so
auth required pam_env.so # 
auth sufficient pam_unix.so
auth required pam_mysql.so user=pam_auth passwd=<password> db=nss passwdcolumn=password usercolumn=user_name crypt=1
account sufficient pam_unix.so
account required pam_mysql.so user=pam_account passwd=<password> db=nss passwdcolumn=password usercolumn=user
session required pam_unix.so
session optional pam_lastlog.so # 
session optional pam_motd.so # 
session optional pam_mail.so standard # 
password required pam_unix.so
Compile cvs. Grab a recent stable version from http://www.cvshome.org
and apply the patch <installroot>/src/cvs-sf-patch. Compile it and
place the cvs binary where your ssh logins can find it.
(In my setup, LysCVS has it's own openSSHD daemon with a restrictive
configuration (no port forwards, no X11 etc..) - but you don't have to
Configure pserver, I use xinetd with the following configuration:
socket_type = stream
protocol = tcp
wait = no
user = root
server = /opt/lyscvs/bin/cvs
server_args = --allow-root=/cvsroot pserver
bind = 10.100.1.1
Make sure you fix that ip in the bind statement. It's not mandatory,
but it helps, since people won't access the wrong IP by mistake.
Install apache, with mod_python. The latter is available from
Modify the lib/constants.py file. Most things should be pretty
straightforward to understand. Make sure all directories exists.
Modify your apache configuration. Something like this must be added:
RedirectMatch 301 /cvsadm.*$ https://cvs.example.com/cvsadm/login
Alias /cvsadm/ /opt/lyscvs/web/pybin/
RedirectMatch 301 /cvsadm/$ https://cvs.example.com/cvsadm/login
RedirectMatch 301 /cvsadm$ https://cvs.example.com/cvsadm/login
(You probably want to enable SSL too..)
Now, start blaming me because the installation instructions are too
short, and try to (re)start apache, and access your newly created cvs server.
As noted earlier, LysCVS can optionally cooperate with the Postfix MTA
to create mail addresses and mailing lists. This section describes how
to do this.
First, get and install Postfix, available from
http://www.postfix.org. Make sure you compile it with MySQL support
(read the file MYSQL_README included in the source distribution).
Next, configure Postfix. One of the nice features of Postfix is that
for most installations, the default values of the configuration
parameters are correct. There are only a few values you need to
change. See src/postfix-example.com for an example of what you
probably need to add to your /etc/postfix/main.cf (or wherever you
chose to place your postfix configuration).
Use the *.mysql files that also resides in the src/ directory. Each of
them defines an alias table that's used to create different parts of
the mail system. Check out the files in question, they have some
comments that describe their function.
Also note that create_repository.sh inserts a line in each new
projects CVSROOT/loginfo that mails the project-specific list with
info about each commit.
Some people probably don't want commit messages when they do commit's
themselves. Unfortunately, they won't be satisifed by this system. On
the other hand, they can construct their own line in loginfo to send
mail only when they're not the person doing the commit. Such a line
could look like this:
ALL (if [ `/usr/bin/id -un` != "username" ]; then (/bin/cat | /usr/bin/mail -s %s firstname.lastname@example.org); fi)
(Thanks goes to Peter Åstrand <email@example.com> for the above
This section probably needs more work, but since I'm so familiar with
mail systems and Postfix, I probably can't see what's unclear. Please
give me feedback on this!