Node:Top, Next:, Previous:(dir), Up:(dir)

Savannah

This document is for Savannah administrators, not Savannah users. Savannah is a SourceForge clone based on the SourceForge-2.0 software. It is dedicated the GNU projects.

Because of the highly specific nature of the software, Savannah is a fork of the SourceForge-2.0 software. Attempting to make it modular and configurable is a waste of time. The whole Savannah software is available from CVS and is managed by the Savannah project. The ChangeLog explains the modifications made to the original code.


Node:Introduction, Next:, Previous:Top, Up:Top

Introduction

Savannah currently provides the CVS frontend. Check the Task List for details on planned developments.

Setting up Savannah is not an easy task because it has to integrate existing habits and projects without breaking anything. However, the SourceForge Installation Guide by Guillaume Morin helps a lot understanding the software.


Node:Installation, Next:, Previous:Introduction, Up:Top

Installation

Savannah is installed on the machine subversions.gnu.org. The root of the installation is in /subversions/sourceforge. All the software that is not system wide and is needed to run Savannah is installed in this directory. The structure of this directory is similar to FHS-2.1. In the following table the path names are relative to the installation root. All directories covered by the SourceForge Installation Guide are omitted.


tmp
Directory to run the backend scripts.
src/savannah
The SourceForge software and the Savannah web pages.
src/savannah/www
The document root of Savannah web pages.
src/savannah/gnuscripts
Savannah specific backend scripts.

The whole Savannah software is available from CVS and is managed by the Savannah project.

In order to install changes commmited in the savannah project CVS tree, proceed as follows:

login subversions
su -
export CVS_RSH=ssh
cd /subversions/sourceforge/src/savannah
cvs -q update


Node:CVS repositories, Next:, Previous:Installation, Up:Top

CVS repositories

For each project registered on Savannah there may be two CVS repositories. One to store the sources of the project and one to store the web of the project. The sources repository is in /subversions/cvs/software and the web repository is in /subversions/cvs/gnuweb. The /webcvs symbolic link points to /subversions/cvs/gnuweb and the /cvsroot symbolic link points to /subversions/cvs/software.


Node:Import repositories, Next:, Previous:CVS repositories, Up:CVS repositories

Import repositories

Existing projects that migrate to Savannah may want their CVS repository to be transfered to subversions. Time is essential for such an operation since the project contributors want to work on the new repository on subversions and stop using the old. When the author asks cvs-hackers@gnu.org, ask him to send the tarbal by mail or send a URL from which it can be downloaded. Make an appointement with him and guarantee that the repository will be untared on subversions with 24 hours maximum. The project contributor must first create a project on subversions. When you have the tarbal untar it at /cvsroot/project. Make sure it does not contain a CVSROOT that would override the existing CVSROOT. If it does manualy copy the history and val-tags files only. Make sure the imported repository is untared under /cvsroot/project/project and does not polute the root of the repository.


Node:Sources CVS repositories, Next:, Previous:Import repositories, Up:CVS repositories

Sources CVS repositories

When a project has a license that is not website a source repository is created under /subversions/cvs/software/project with a private CVSROOT that only contains anoncvs. The developers of the project have access to the CVSROOT directory.

The group project is created to grant write access to the repository to all the members of the project.

When a Savannah project is assigned the website license, it only has a portion of the webcvs repository and no source CVS repository.

If the html_cvs field for a given Savannah project is empty, it is not associated with a part of the webcvs repository.

It allows them to add commit notification by doing the following, replacing project with the name of their project:

cvs -d subversions.gnu.org:/cvsroot/project co CVSROOT

In CVSROOT/commitinfo

^project /usr/local/bin/commit_prep -T project -r

In CVSROOT/loginfo

^project /usr/local/bin/log_accum -T project -C -m project-commit@gnu.org -s %{sVv}

The email address must exist, it will not be automatically generated.

For compatibility with the cvs setup before Savannah was introduced, /subversions/cvs/common contains repositories that existed before Savannah. When a project is registered in Savannah, a symbolic link is created (/subversions/cvs/software/project/project) that points to the already existing /subversions/cvs/common/project directory.

The /cvs symbolic link points to /subversions/cvs/common so that people already using it to access their repositories can continue to do so. Before Savannah existed a pserver access was available and Savannah continues to maintain it for these projects, updating the CVSROOT/passwd files with user/password pairs that are in the Savannah database.


Node:Web CVS repositories, Next:, Previous:Sources CVS repositories, Up:CVS repositories

Web CVS repositories

When a project has an html_cvs field that is not empty in the group table, a web repository is created in /subversions/cvs/gnuweb/html_cvs. By default the html_cvs field has the value /software/project/ but it may be edited with the savannah.gnu.org/admin/. See the gnujobs, greve and bravegw projects for examples.

When a Savannah project is assigned the website license, it only has a portion of the webcvs repository and no source CVS repository.

If the html_cvs field for a given Savannah project is empty, it is not associated with a part of the webcvs repository.

The group webproject is created to grant write access to the repository to all the members of the project.

All the www.gnu.org web was imported in /subversions/cvs/gnuweb. When a project is registered on Savannah and there already exists a directory for it in the repository (either .../software/project or the value of the html_cvs field), a chgrp -R webproject is done on this repository to grant the members of the project a write access to this portion of the web repository and only this one.

The www project in Savannah is treated in a special way. All the members of the www project have access to the whole repository in /webcvs. It means that they are always included in every webproject created.


Node:Web CVS Symbolic links, Next:, Previous:Web CVS repositories, Up:CVS repositories

Web CVS Symbolic links

Since CVS is not able to handle symbolic links, a simple mechanism has been implemented on the machine hosting the www.gnu.org to allow webmasters to control the symbolic link from the CVS tree.

The special file .symlinks contains a list of file name pairs, one per line. For instance:

foo.html index.html
bar.html other.html

is a valid .symlinks file. Every night a script reads all the .symlinks files, prepend a ln -s in front of each line and execute them. Well, in reality it's not that simple but you get the idea. The .symlinks file can only be used to control the symbolic link in the directory where they are. File names with / will be ignored.


Node:Web CVS top level directories, Next:, Previous:Web CVS Symbolic links, Up:CVS repositories

Web CVS top level directories

The /subversions/cvs/gnuweb/CVSROOT/loginfo file contains triggers that update the gnudist.gnu.org:/home/www/html directory whenever a commit is done. There is a single CVSROOT for all the projects that have a web repository.

When a top level directory is added in the webcvs repository a line must be added in the loginfo file to run webcvs whenever something is changed in this directory. This must be done manualy. Hopefully adding new top level directories is not a frequent operation and adding this is not too much overhead for the Savannah maintainer.


Node:Web CVS and Projects, Previous:Web CVS top level directories, Up:CVS repositories

Web CVS and Projects

The special project www have write access to all the /webcvs repository. It is possible to create projects that will limit write access of the members of the project to a subdirectory of the /webcvs repository only. For instance the bravegw Savannah project only give write access to the /webcvs/brave-gnu-world part of the repository.

A project bound to a specific subdirectory will grante write access to all the tree under this subdirectory. There is no way, for instance, to grant write access to group B to /webcvs/thispart and write access to group A to /webcvs/thispart/subdir. If you do this group B win and will have write access to /webcvs/thispart recursively and group A will have access to nothing. If you see a way to overcome this limitation, let us know.

The sf_www script generates the map that is published at www.gnu.org to Savannah. It writes the file in /subversions/sourceforge/src/server/standards and commits it. The server/standards directory is a read-write checkout of the www.gnu.org web CVS. The sf_www script is run once a day by the crontab.

A more webmaster oriented documentation explains the organisation of the www.gnu.org CVS tree and the rationale of its usage.


Node:Database, Next:, Previous:CVS repositories, Up:Top

Database

Savannah uses MySQL and the sourceforge database. The root user has a ~/.my.cnf file that defines the user/passwd. It is not necessary to specify them on the command line.


Node:Skill List, Previous:Database, Up:Database

Skill List

The tables people_skill and people_skill_level are loaded from the skill database maintained by CJN (http://cjn.sourceforge.net/). The script /subversions/sourceforge/src/savannah/gnuscripts/sf_skill loads the XML skill files from CJN and replace the content of the tables in the sourceforge database.

If some proprietary software shows on the skill list, add it to the %ignore table in the sf_skill script and re-run it.

cd /subversions/sourceforge/src/savannah/gnuscripts
edit sf_skill
sf_skill
cvs commit -m 'Ignore proprietary software xxxx'


Node:Mails and aliases, Next:, Previous:Database, Up:Top

Mails and aliases

Savannah will try to send mail to users under various circumstances (bug reports notification, account creation etc.). In some cases it will use the real mail address of the user, in others it will use user@savannah.gnu.org. In order for the user@savannah.gnu.org address to work properly for outgoing mails, the /etc/aliases file is updated automatically every 5 minutes with the following command:

sf_aliases

The user@savannah.gnu.org can never be used to recieve mail for the good reason that savannah.gnu.org does not listen on the SMTP port.


Node:Unlock alias at gnu.org account, Next:, Previous:Mails and aliases, Up:Top

Unlock alias at gnu.org account

People who have a simple alias name@gnu.org but no account on Kerberos cannot create an account on Savannah. When they ask to unlock the account name on savannah-hackers@gnu.org, tell them to create an account using a fake username and to send this username to savannah-hackers@gnu.org. When receiving that user name substitute the fake login name by the desired one:

mysql -e "update user set user_name = 'desired' where user_name = 'fake'" sourceforge


Node:Migration, Next:, Previous:Unlock alias at gnu.org account, Up:Top

Migration

Must be root to run this script. You are advised to run it in /subversions/sourceforge/tmp, although it is not mandatory.

The sf_migrate script creates a Savannah project for an existing project in the /subversions/cvs/common directory. It is done in three steps:

--add
Will create the project in Savannah if it does not yet exists. It will also scan the /etc/passwd and /etc/group files and create users in Savannah.

When explaining the situation to a user added to Savannah in this way, one could say it like this. If you have a Kerberos account on gnu.org, use the same login and password on Savannah and change the password immediately afterwards: it will not change your Kerberos password, just the Savannah password. If you only have a pserver account, use the same login and password on Savannah. If you have both, use the Kerberos account login and password. If you have none and access CVS using SSH public keys, ask to cvs-hackers@gnu.org to give you a password. This last case requires human interaction to prevent someone from stealing your account name.

--bind
Will bind the users created to the project. This cannot be done in one step (-add -bind) because of unique identifiers allocations by the MySQL database.
--mail
Generate a Emacs-VM formated mail ready to send to all contributors of the project that explains what has been done.

When a user with SSH access thru public key was added by sf_migrate, she/he will be instructed to ask for a password to cvs-hackers@gnu.org. The sf_pass script can be used to set her/his password. A mail must be sent by the user requesting the password with the encrypted password. Instruct the user to generate the password using the following command:

perl -e 'print crypt("mypassword",
  join "", (".", "/", 0..9, "A".."Z", "a".."z")[rand 64, rand 64])'

When the user send the password crypted, set it using:

sf_pass --set thename cryptpass | mysql sourceforge

After 24 hours, check user logged in and lock the user if it is not the case. This is to prevent obvious holes.

sf_pass --unset thename | mysql sourceforge


Node:Users and CVS synchronization, Next:, Previous:Migration, Up:Top

Users and CVS synchronization

Must be root to run this script. Must export CVS_RSH=ssh. You are advised to run it in /subversions/sourceforge/tmp, although it is not mandatory.

The sf_cvs script generates a shell script that will synchronize the system files with the state of the Savannah database (sourceforge).

This script only generates lines if something needs to be done. When the resulting script is executed, another run must not display any action, unless the database was modified in the meantime.

It performs the following tasks, in this order.


Add new projects
/subversions/cvs/software/project and /subversions/cvs/gnuweb/software/project directories are created.
Update existing projects
Fixes projects that do not have a /subversions/cvs/gnuweb/software/project directory.
Add missing users
Create users that are bound to at least a project in Savannah.
Remove users
Remove users not bound to any project in Savannah If user belongs to groups not managed by Savannah, just redefine its group list.
Update existing users
Modify the system files if they are not in sync with the Savannah database.
Update the CVS password file
Update the /subversions/cvs/CVSROOT/passwd file to reflect the passwd and users bound to projects in Savannah.
Update xinetd.conf
Update the cvspserver/cvskserver with all possible pserver roots


Node:Publishing this document, Next:, Previous:Users and CVS synchronization, Up:Top

Publishing this document

The HTML version of this document is published in two places: Savannah Administration Guide and Savannah Administration Guide. The source is stored in the subversions.gnu.org:/cvs co gnudocs repository. To facilitate the publication process you can edit it in the subversions.gnu.org:/subversions/sourceforge/src/gnudocs directory and then issue a

make publish

The publish goal assumes that the Savannah document root is in ../savannah/www and a read-write checkout of the www.gnu.org/server/standards directory is in ../server/standards. It will format the document to HTML and commit the changes to the repository.


Node:System Administration, Next:, Previous:Publishing this document, Up:Top

System Administration


Node:SSL certificate, Next:, Previous:System Administration, Up:System Administration

SSL certificate

The SSL certificate for savannah.gnu.org was generated in /etc/apache-ssl/. Check the README file for a log of the command. There has been a lot of discussions regarding the root certificate for GNU, the use of a PKI. At some point the savannah certificate will be generated using a proper root certificate.


Node:Savannah crontab, Next:, Previous:SSL certificate, Up:System Administration

Savannah crontab

The Savannah crontab jobs are in /etc/cron.d/savannah. Every cron command output is sent to savannah-hackers@gnu.org.

*/5 * * * *	root	sf_aliases
10 4 * * *	root	sf_www
17 * * * *	root	cd /subversions/sourceforge/tmp ; sf_cvs | ( date ; sh -x ) >> /var/log/sf_cvs.log 2>&1


Node:Savannah software root, Next:, Previous:Savannah crontab, Up:System Administration

Savannah software root

All software that is not system wide but only used for the purpose of Savannah must be installed in the prefix /subversions/sourceforge.

The MySQL installation is an exception that must be fixed. It is installed with the /usr/local/mysql prefix. It was not installed from the debian package because I (loic@gnu.org) was not able to fix the MySQL-3.23 package to make it work on potato.


Node:NGROUPS_MAX, Previous:Savannah software root, Up:System Administration

NGROUPS_MAX

The large number of groups a user can have (>32) implies to modify some basic programs (namely useradd and usermod).

Gordon Matzigkeit <gord@fig.org> modified /usr/local/src/cvs-1.10.8/src/server.c to overcome the limit builtin glibc. He also installed the /boot/vmlinuz-2.2.12-256groups kernel that was compiled with NGROUPS_MAX set to 256. The system files have not been reinstalled to match this version.

Here is the patch applied to /usr/local/src/shadow-19990827. The modified usermod and useradd have been installed in /subversions/sourceforge/bin.

*** ./debian/rules.~1~	Fri Feb  9 02:05:06 2001
--- ./debian/rules	Fri Feb  9 02:05:41 2001
***************
*** 38,44 ****
  ifneq ($(DEB_HOST_GNU_SYSTEM),gnu)
    include debian/scripts/login.mk
    package-list += binary-login
!   config_options += --with-libpam
    control_defs += -DMODDEP="(>= 0.72-5)"
  endif

--- 38,44 ----
  ifneq ($(DEB_HOST_GNU_SYSTEM),gnu)
    include debian/scripts/login.mk
    package-list += binary-login
! #  config_options += --with-libpam
    control_defs += -DMODDEP="(>= 0.72-5)"
  endif

*** ./build-tree/shadow-19990827/libmisc/addgrps.c.~1~	Mon Dec 28 12:34:41 1998
--- ./build-tree/shadow-19990827/libmisc/addgrps.c	Fri Feb  9 03:04:47 2001
***************
*** 20,25 ****
--- 20,28 ----
   * already there.  Warning: uses strtok().
   */

+ #undef NGROUPS_MAX
+ #define NGROUPS_MAX 256
+
  int
  add_groups(const char *list)
  {
*** ./build-tree/shadow-19990827/src/usermod.c.~1~	Fri Jul  9 09:27:38 1999
--- ./build-tree/shadow-19990827/src/usermod.c	Fri Feb  9 03:05:52 2001
***************
*** 74,79 ****
--- 74,82 ----

  #define	VALID(s)	(strcspn (s, ":\n") == strlen (s))

+ #undef NGROUPS_MAX
+ #define NGROUPS_MAX 256
+
  static char *user_name;
  static char *user_newname;
  static char *user_pass;
*** ./build-tree/shadow-19990827/src/groups.c.~1~	Mon Jun  7 09:40:45 1999
--- ./build-tree/shadow-19990827/src/groups.c	Fri Feb  9 03:15:54 2001
***************
*** 42,47 ****
--- 42,50 ----
  static void print_groups P_((const char *));
  int main P_((int, char **));

+ #undef NGROUPS_MAX
+ #define NGROUPS_MAX 256
+
  /*
   * print_groups - print the groups which the named user is a member of
   *
*** ./build-tree/shadow-19990827/src/id.c.~1~	Mon Jun  7 09:40:45 1999
--- ./build-tree/shadow-19990827/src/id.c	Fri Feb  9 03:16:34 2001
***************
*** 50,55 ****
--- 50,58 ----
  static void usage P_((void));
  int main P_((int, char **));

+ #undef NGROUPS_MAX
+ #define NGROUPS_MAX 256
+
  static void
  usage(void)
  {
*** ./build-tree/shadow-19990827/src/useradd.c.~1~	Fri Feb  9 02:06:01 2001
--- ./build-tree/shadow-19990827/src/useradd.c	Fri Feb  9 03:28:52 2001
***************
*** 53,58 ****
--- 53,61 ----
  #endif
  #include "faillog.h"

+ #undef NGROUPS_MAX
+ #define NGROUPS_MAX 256
+
  #ifndef SKEL_DIR
  #define SKEL_DIR "/etc/skel"
  #endif
*** ./build-tree/shadow-19990827/src/newgrp.c.~1~	Fri Feb  9 02:06:00 2001
--- ./build-tree/shadow-19990827/src/newgrp.c	Fri Feb  9 03:29:10 2001
***************
*** 49,54 ****
--- 49,57 ----
  static GETGROUPS_T *grouplist;
  #endif

+ #undef NGROUPS_MAX
+ #define NGROUPS_MAX 256
+
  static char *Prog;
  static int is_newgrp;

The sshd daemon has been rebuilt with the following patch so that CVS ssh operations have the proper set of groups. The sources are in /usr/local/src/openssh-1.2.3/ and the corresponding debian package is at /usr/local/src/ssh_1.2.3-9.2loic_i386.deb. The package was tagged on hold using dselect to prevent accidental upgrade. Note that this patch may have hideous impact for users who have real account and use ssh since most of the commands that deal with groups have not been recompiled to handle more than the limit of 32 groups. For instance the id command will core dump. Here is the patch applied on the distribution:

*** sshd.c.~1~	Fri Mar 17 04:40:18 2000
--- sshd.c	Tue Feb 13 06:32:17 2001
***************
*** 147,152 ****
--- 151,240 ----
  	      const char *display, const char *auth_proto,
  	      const char *auth_data, const char *ttyname);

+ #ifdef AUTH_SERVER_SUPPORT
+ #ifdef HAVE_GETSPNAM
+ #include <shadow.h>
+ #endif
+ #endif /* AUTH_SERVER_SUPPORT */
+
+ /* The GNU C Library currently has a compile-time limit on the number of
+    groups a user may be a part of, even if the underlying kernel has been
+    fixed, and so we define our own initgroups. */
+ #include <grp.h>
+ static int
+ xinitgroups (char *user, gid_t gid)
+ {
+   struct group *grp;
+   gid_t *buf;
+   int buflen, ngroups;
+
+   /* Initialise the list with the specified GID. */
+   ngroups = 0;
+   buflen = 16;
+   buf = malloc (buflen * sizeof (*buf));
+   buf[ngroups ++] = gid;
+
+   setgrent ();
+   while ((grp = getgrent ()))
+     {
+       /* Scan the member list for our user. */
+       char **p = grp->gr_mem;
+       while (*p && strcmp (*p, user))
+ 	p ++;
+
+       if (*p)
+ 	{
+ 	  /* We found the user in this group. */
+ 	  if (ngroups == buflen)
+ 	    {
+ 	      /* Enlarge the group list. */
+ 	      buflen *= 2;
+ 	      buf = realloc (buf, buflen * sizeof (*buf));
+ 	    }
+
+ 	  /* Add the group id to our list. */
+ 	  buf[ngroups ++] = grp->gr_gid;
+ 	}
+     }
+   endgrent ();
+
+   /* Return whatever setgroups says. */
+   buflen = setgroups (ngroups, buf);
+   free (buf);
+   return buflen;
+ }
+ #define initgroups xinitgroups
+
+ /* This worked fine, and was adopted into glibc, until setgroups got a
+    similar limitation, so we override it as well. */
+ #include <linux/posix_types.h>
+ #include <sys/syscall.h>
+ #include <errno.h>
+
+ int
+ setgroups (size_t n, const gid_t *groups)
+ {
+   size_t i;
+   __kernel_gid_t kernel_groups[n];
+
+   for (i = 0; i < n; i ++)
+     kernel_groups[i] = groups[i];
+
+   {
+     long res;
+     __asm__ volatile ("int $0x80"
+ 		      : "=a" (res)
+ 		      : "0" (__NR_setgroups),"b" ((long)(n)),
+ 		      "c" ((long)(kernel_groups)));
+
+     if ((unsigned long)(res) >= (unsigned long)(-125)) {
+       errno = -res;
+       res = -1;
+     }
+     return (int) (res);
+   }
+ }
+
  /*
   * Remove local Xauthority file.
   */


Node:Concept Index, Previous:System Administration, Up:Top

Index of Concepts

Table of Contents