Savannah Internals

This page describes inner workings of the GNU Savannah platform (web frontend + backend processes).

Some terminology

  • 'GNU Savannah' (or just 'Savannah') is the name of the entire platform, encompassing the various hosts (see SavannahArchitecture), services (see SavannahServices), people (see SavannahTeam) and other odds and ends.

  • 'Savane' (French for 'savannah') is the code name for the source code which runs many parts of the savannah platform (most notably: the web frontend at

While usually these are distinguished, they are sometimes used interchangeably, and should be appropriately understood by the context.

  • 'groups' - in the savane code, projects are referred to as "groups" (and in a few cases, these are conceptually groups rather than programming projects, e.g., the Free Software Free Society Portuguese and the GNU Spanish Translation Team). The database table is named groups, and several php files are named groupXXX.php while referring to projects. group_id=N in urls refer to the project internal ID.

  • Savannah Administrators are volunteers with special access permissions on the savannah frontend website (see 'becoming super-user' below), and administrator ssh access to the savannah hosts. See SavannahTeam and List of current administrators.

  • Project Administrators (in the context of this document) are savannah users who have administrative access to their own project. As an example, these people are project administrators for GNU AWK:

Savannah source code

The source code for the php frontend and most of the perl/shell backend scripts is available at: N.B. That's the administration project/group, and the git repository named savane within it.

To experiment with running a local copy of Savane see RunningSavaneLocally and SavaneInABox.

Warning about repositories: There are several other repositories/clones/forks which look like the savane repositories (e.g., savane-cleanup, another savane.git ). The repository listed above is the only official one. All code running on the savannah hosts comes from the administration project, using several version control systems there: git, cvs, subversion; each of which holds different stuff.

Savannah hosts

Please see SavannahArchitecture and SavannahServices rather than repeating information here.

workflow - overview



  1. Users submit a new project. Savannah administrators approve the project (see ApprovingSubmission).
  2. Project administrators of existing project can change project settings (e.g., add a mailing list, switch from cvs to git, etc.).
  3. The PHP code on frontend updates the MySQL database, and optionally runs one-time project creation scripts.
  4. On vcs and download, cron jobs regularly query the database for updates, and make the necessary changes (e.g., create a new git repository for a new project).
  5. The cvsweb repositories hold the html files which are the source for a project's web pages. When these are updated, a special hook calls a cgi script on to request a website update.
  6. A cron job on regularly checks for update requests, and cvs updates the requested repositories.
  7. A cron job on internal regularly query the database for mailing list updates. It then creates the mailing lists on This is done because is managed by the FSF, not Savannah.
  8. Publishing a new tarball release for GNU packages is performed by an automated process, explained in the GNU Maintainer's guide. It is not managed by Savannah administrators, and only mentioned here for completeness.
  9. GNU Bug Tracker ( is based on Debian's Bug Tracking System. It is not managed by Savannah administrators. Packages hosted on Savannah, either gnu or nongnu, can request to use the bug tracker. More information:
  10. For nongnu projects, project members with write access can upload new files to be available for download as 'releases' (e.g., While GNU projects can also store files this way, it is very strongly recommended that official GNU packages use via the automated ftp uploads (see item 8, above). For details, see download section in SavannahServices. See also UserAuthentication.
  11. Project members with write access can push code to the repositories on vcs using ssh. See 'vcs' section in SavannahServices for configuration details. See CvsGettingStarted, Svn, UsingHg, UsingBzr, UsingGit for usage information, and UserAuthentication for ssh authentication details.

User registration (frontend)

Anyone with a valid email account can register on GNU Savannah.

Warning: the email that Savannah sends will often be considered spam by big email providers, or outright rejected.

Project submission (frontend)

Any savannah user can submit a submit a new project request. This procedure is for nongnu projects only (for gnu projects see here:

  • Public URL:
  • Source code: /frontend/php/register/index.php (and see all files in /frontend/php/register/ ).
  • After form submission, The php confirmation.php file in register/:
    • updates the database record in the groups table, with STATUS='P'.
    • sends a notification email to
    • Creates a new task in the task tracker (FIXME: how?)
    • FIXME: the source code mentions something about cookbook and recipes database tables?
  • The project is in pending state until approved by Savannah administrators.

Project approval, creation (frontend)

Savannah admins approve and create projects after careful and manual review. Project creation is the same for GNU projects (the manual review for GNU projects is done by the GNU evaluation volunteers, not savannah admins).

  • Public URL: (only available to savannah admins in superuser mode).
  • The URL is display as 'group administration' link when viewing a pending project ticket.
  • Source code: /frontend/php/siteadmin/groupedit.php.
  • In this page the following changes can be made:

    • system name (i.e. 'short name') - the name will be used in URLs, as a unix group name for access control, and as directory names in various locations. Must be unique.
    • status: pending,active,deleted,maintenance,incomplete.
    • license
    • visibility (public/private)

    These changes are written to the groups table.

  • Two special commands are available in this page as well:
    • The green "V" icon: calls groupedit.php again with cgi parameters updatefast=1 and status=A, thus marking the project as active in the groups table, and in savannah.
    • The configure (screwdriver and wrench) icon: calls /frontend/php/siteadmin/triggercreation.php, which calls the necessary one-time project creation scripts.
  • The triggercreation.php script does the following:
    • Sets project defaults (e.g., having a homepage, having 'downloads', using cvs repository, using task,support,bugs trackers, using news, etc.). This are fields such as use_homepage=1 in the groups table.
      The items set by default are hard-coded in triggercreation.php. (this is one reason that by default, all new projects on savannah start with a cvs repository). This settings can later be changed by the project administrators.
    • Sends an email to the project administrator (based on the savannah user who submitted/registered the project).
  • FIXME: triggercreation.php mentions "site-specific triggers executed"
    • which ones are these and where are they executed?

Project administration - general information (frontend)

Project admins can modify various items for their projects using the savannah web interface.

Project administration - feature selection (frontend)

Project admins can enable/disable features for their projects, using the savannah web interface.

  • features in this context are the facilities used by the project, such as git, cvs, homepage, downloads, news, bugs/support/patches/tasks trackers, mailing lists, etc.
    Each feature has a corresponding field in the groups table (e.g., use_git, use_homepage, use_downloads) which is set to 1 or 0.

  • Some features are associated with a url. The urls for these features are initialized to the savannah defaults at project creation, but can be later changed by the project administrators. Examples:

    1. If use_homepage=1, the url_homepage field defaults to (for gnu projects) or (for nongnu projects). Project administrators can change this, although GNU packages should not do so.
    2. If use_git=1, the url_git field defaults to git/?group=PROJECT (which resolves to, a page containing instructions about accessing git on savannah for this project). Project administrators can change this to any other URL, although they should not do so, especially not GNU packages. (The purpose of Savannah is to host source code.)
  • Public URL: (only available to project admins).

  • Source code: /frontend/php/project/admin/editgroupfeatures.php.

  • When updating features (selecting or deselecting features), the changes are saved to the database, in the groups table. No other changes are performed.

  • These database changes will be picked up by the cron jobs running on other VMs (see below). This is the reasons some features take time to propagate (e.g., when a project administrator turns on git, the git repository is not created immediately). It would be better to do things synchronously, or at least very quickly.

Project administration - mailing lists (frontend)

Project admins can add/configure/delete mailing lists for their projects using the savannah web interface.

  • Mailing lists require special handling: the mailing list server (, using GNU Mailman) is administered by the FSF, not Savannah.
  • Special configuration on allows remote execution of shell scripts from frontend to automate list creation/deletion. More info: ListServer.
  • Public URL: (only available to project admins).
  • Source code: /frontend/php/mail/admin/index.php.
  • The php code updates the mail_group_list table (no other direct changes are done by the script). New mailing lists are added as new records in the tables. Change requests to mailing lists are done by changing the status field (see source code for possible values).
  • A cron job on internal reads the changes in the mail_group_list and executes the necessary changes on See "cron jobs on internal" section below.

MySQL Database

See SavannahDatabaseSchema and SavannahDatabaseExamples.

Cron job on vcs

Stored in vcs:/etc/cron.d/sv:

# remake user list for outgoing mail.
*/10 * * * *    root    nice -n 11 sv_aliases --cron && sed -e '/# Savannah include start/,/# Savannah include end/s/\([^:]\+\): .*/\1:' /etc/email-addresses -e 's,This is /etc/email-addresses,DO NOT EDIT - GENERATED FROM email-addresses.,' > /etc/email-addresses_SENDER

# remake list of git repositories in each project.
*/15 * * * *    root    nice -n 11 /usr/src/infra/git/ && /usr/src/infra/git/

# remake CVSROOT/{commit,log}/info (for cvs commit email?).
31 * * * *  root    nice -n 11 /usr/src/infra/cvs/

# remake list of groups for the vcs.
35,05 * * * *   root    nice -n 11 sv_groups --cron --only-cvs --only-homepage --only-svn --only-git --only-hg --only-bzr
  • /backend/mail/ (installed in vcs:/usr/local/bin/sv_aliases) - This script prepares an alias-type file for for exim4 mail server, used when sending commit updates to mailing lists.

    • The script queries the MySQL database, extracting user names and emails for all savannah users. Additionally, emails for 'squads' (per-project mailing groups) are queried. The results are saved in vcs:/etc/email-addresses.
    • vcs:/etc/email-addresses is symlinked to the standard vcs:/etc/exim4/email-addresses file. Example:

    • The sed command in the cronjob file replaces each user's email with, and saves the results in vcs:/etc/email-addresses_SENDER. Example:

    • FIXME: where is /etc/email-addresses_SENDER mentioned/used? in an exim4 config file?

  • - this script updates the vcs:/srv/git/project-list file which is used by gitweb CGI application.

    • FIXME: file is vcs:/usr/src/infra/git/, and is not in the savane repository. Add it?
    • gitweb configuration file is vcs:/etc/gitweb.conf.
    • Implemetation detail: the script does not re-generate the project-list from scratch. Instead, it scans /srv/git for new git repositories, and only adds them to the file if they aren't already listed. This allows manually adding information to the project-list file, ensuring it will not be overwritten. The manually added information is the owner name/email for some repositories. Example:

      $ cat /srv/git/project-list
      administration.git Savannah+Hackers
      autostrap.git Sylvain+Beucler
      coreutils.git Jim+Meyering

      These names (e.g. Jim Meyering) will appear in the owner field when viewing the gitweb page of the project (example:

  • - this script updates the vcs:/srv/git/cgitrepos file which is used by the cgit CGI application.

    • FIXME: file is vcs:/usr/src/infra/git/ and is not in the savane repository. Add it?
    • cgit configuration file is vcs:/etc/cgitrc.
    • Implementation detail: the script reads the /srv/git/project-list file (generated by, above), and for each mentioned project, writes an entry in cgitrepos. Example:

      $ cat /srv/git/cgitrepos
      ... Core Utilities
      repo.desc=GNU coreutils
      repo.owner=Jim Meyering
  • - This script updates the CVS hooks in savannah repositories.

    • FIXME: file is vcs:/usr/src/infra/cvs/ and is not in the savane repository. Add it?
    • The script queries the database (groups table) for project using cvs repositories, and projects using homepages (which use the cvsweb repositories).
    • For each cvs repository, it creates/updates the <project>/CVSROOT/{loginfo,commitinfo} files.
    • Example of commitinfo for source-code (not web) CVS repository:

      $ cat /sources/pspp/CVSROOT/commitinfo
      DEFAULT /usr/local/bin/ -T pspp_70 %p
      ALL $CVSROOT/CVSROOT/no-commits %{s}
    • Example of loginfo for source-code (not web) CVS repository:

      $ cat /sources/pspp/CVSROOT/loginfo
      DEFAULT /usr/local/bin/ --mail-to --send-diff --file-prefix pspp_70 --config /etc/log_accum-sources.config %p %{sVv}
    • Example of loginfo for web CVS repository:

      $ cat /srv/cvs/web/datamash/CVSROOT/loginfo
      ALL echo 'Triggering webpages update...'; cat > /dev/null; curl -s -F type=gnu -F project=`basename %r`
  • sv_groups - This script creates new repositories for projects in the savannah database

    • reminder: when a new project is approved/created on savannah, or when a project administrator selects a new repository feature the frontend php code only updates the database. this script picks up the changes and executes them.
    • file is /backend/accounts/
    • The script queries the groups table, and creates the needed repositories.
      Example: For project XXX, if groups.use_git=1, it look for vcs:/srv/git/XXX.git. If it doesn't exist, create it with git init and additional savannah-specific configurations (e.g. permissions, hooks, xattrs).
    • Repository initialization and configuration is delegated to the relevant perl module. See,,,,,
    • Two types of CVS repositories can be created: cvs (Using CvsMakeArea in - source code repository; webcvs (Using WebCvMakeAreaSavannahGNU in - webcvs repository (content will be available on
    • The script also contains legacy code to create unix groups on the local machine (using /usr/sbin/groupadd). This part is not used any more, since groups and users are delegated to nsswitch/libnss-mysql (see UserAuthentication).
    • FIXME: What as "Area Attic" (mentioned in the code)?
    • The script takes parameteres determining which items to create (e.g. --only-git).
    • On vcs host, the git/hg/bzr/cvs/cvsweb repositories are created.
    • On download host, the download (and legacy 'arch') are created.

Cron jobs on download

stored in download:/etc/cron.d/sv:

*/30 * * * *    root    sv_groups --cron --only-download --only-arch
  • sv_groups - This script creates new repositories for projects in the savannah database. See description for sv_groups in the above section.

Cron jobs on frontend

  • frontend:/etc/cron.d/sv_export [non-functional] - contains the following commands:

    # XML data export
    02 * * * *      root    sv_export --xml-path /var/cache/savane
    # Remove old data export
    30 1 * * *      root    sv_export_cleaner --xml-path /var/cache/savane
    # Get list of Git repositories
    3,33 * * * *    root    scp /etc/savane

    sv_export is an old feature which exports project data into XML.
    FIXME: remove this?

  • frontend:/etc/cron.daily/sv_list_groups [unfinished] - an attempt to publish an authoritative list of active projects hosted on GNU Savannah. The script contains the following code:

    mysql savane -B -e 'SELECT group_type.type_id,,
                               unix_group_name, group_name
                        FROM groups, group_type
                        WHERE groups.type = group_type.type_id
                              AND groups.status="A"
                        ORDER BY type;' \
                        > /var/www/overlay/cooperation/groups.tsv

    FIXME: complete this nice feature, and expose it with apache configuration. Also possibly with JSON data, and more fields.

Cron jobs on internal

stored in internal:/etc/cron.d/sv:

# Assign uidNumber and gidNumber inthe database (and rebuild cache for
# libnss-mysql-bg). 7211 was the latest group created by the old
# sv_groups cron - maybe one day we'll move everything to the 70000
# range. Then create homedirs and authorized_keys files.
*/5 * * * *   root   sv_assign_uid_gid --min-gidNumber=77212

# New list creation
*/5 * * * *     root    sv_mailman --cron

# Database cleaning
*/25 * * * *    root    sv_cleaner --cron
48 12 2 * *     root    sv_cleaner --cron --big-cleanup

# Reminder
4 4 * * *       root    sv_reminder --cron
25 18 * * *     root    sv_reminder --cron
  • sv_assign_uid_gid - creates unique user ids and group ids for users/projects in the savannah system.

    • reminder: across all savannah hosts, unix user/group ids are managed with nsswitch/libnss-mysql (see UserAuthentication for details).
    • Source code: /backend/accounts/
    • When a new user (or project) is created on savannah, the php code on frontend does not assign uid/gid.
    • This script picks up new users (SQL: user.uidNumber is NULL) and new projects (SQL: groups.gidNumber is NULL) and assigns them ids.
  • sv_mailman - queries the mail_group_list table, and creates/updates the mailing lists on

    • Source code: /backend/mail/
    • This script is tightly-coupled with the php code in /frontend/php/mail/admin/index.php.
    • The index.php code sets the mail_group_list.status field to the requested new status, and the sv_mailman script executes the changes and updates the database.
    • sv_mailman calls internal:/usr/sbin/newlist. The newlist script is a stub which delegates the call to using SSH. See MailSystem for more details.
      The gist of internal:/usr/sbin/newlist is:

      cat <<EOF | ssh -T -i ~/.ssh/
  • sv_cleaner - cleans up left-overs from interrupted php code?

  • sv_reminder - sends email reminders to users.

    • source code: /backend/misc/
    • The help message says:

      This script will send reminder to users in some specific cases. 
      Case 1: an item is about to start or finish, all people from the item 
      notification list should be warned. 
      Case 2: an user decided to receive a batch of open item assigned to
      him each x days, minimum priority being > 5
      Case 3: a project admin decided that members assigned to some item of 
      should receive a batch each x days, minimum priority > 5
      (Case 4: a project admin decided that members assigned to some item
      whose statut/resolution havent changed for some period should receive
      a batch each x days)
    • FIXME: investigate this script. update mechanism

Mailing list configuration

Additional functionality

super-user and impersonate on frontend

frontend configuration files

(files which are not in the administration (or any version control) repositories)

git hooks on vcs

cvsweb hooks on vcs