I spent a few days setting up a multi-user multi-project git repo using turnkey trac. Finally I made it, it is up successfully and the following are the instructions for it. This applies to the following version spec:

System Information

Trac: 0.11.7
Python: 2.6.5 (r265:79063, Apr 16 2010, 13:28:26) [GCC 4.4.3]
setuptools: 0.6
SQLite: 3.6.22
pysqlite: 2.4.1
Genshi: 0.5.1
mod_wsgi: 2.8 (WSGIProcessGroup wsgitrac WSGIApplicationGroup|)
Pygments: 1.2.2


Adding a project

WARNING: Hosting of the other projects may be affected while performing the following steps. Hence, it is better to take a backup of the vm before performing the following steps.

WARNING: Make sure to perform all the following steps exactly in the mentioned order only.

1. Login as root in the vm containing trac. (Using a terminal from a remote machine instead of directly working on the vm window as it is faster and easier for copy pasting)
// eg: ssh root@<IP>

2. Create the project.

trac-initproject git <project name>

//setting up the web page. Do not use the web interface of the project now.


cd /var/local/lib/trac/git-<project name>/conf/

4. edit trac.ini of the project.

4.1 append the following lines under [components]

acct_mgr.admin.accountmanageradminpage = enabled
 acct_mgr.api.accountmanager = enabled
 acct_mgr.db.sessionstore = disabled
 acct_mgr.htfile.htpasswdstore = enabled
 acct_mgr.notification.accountchangelistener = enabled
 acct_mgr.notification.accountchangenotificationadminpanel = enabled
 acct_mgr.web_ui.accountmodule = enabled
 acct_mgr.web_ui.loginmodule = enabled
 httphostlink.* = enabled
 iniadmin.* = enabled
 noanonymous.filter.* = enabled
 trac.web.auth.loginmodule = disabled

4.2 remove the entries under [account-manager] and add the following lines

force_passwd_change = true
 password_file = /etc/trac/htpasswd
 password_store = HtPasswdStore

5. Remove default premissions.

trac-admin /var/local/lib/trac/git-<project>/  permission remove authenticated '*'
 trac-admin /var/local/lib/trac/git-<project>/  permission remove anonymous '*'


service apache2 restart

7. You can use the web interface of the project now.( available at https://<IP>   Note: HTTPS instead of HTTP )

7.1 After logging in as admin(username: admin, password: you should ask and get it 🙂 ), you can add new users if required by going to Admin -> Accounts -> Users. Existing user accounts can be viewed in the page. Note that the users created will be global to all the projects and the existing user accounts can be reused.

7.2 The permissions given to users are project specific. Add permissions to different users by going to Admin -> General -> Permissions. TRAC_ADMIN permission will make the user have full administrative access to the newly created project. Details of different permissions are available at http://trac.edgewall.org/wiki/TracPermissions .
The web interface is now fully configured.

8. Configuring the git repo.

8.1 Login as root in the vm.
Create new users or reuse the existing user accounts for the project( Existing users can be seen by issuing cat /etc/passwd ). New users can be created using “adduser”.

adduser <username>

8.2 Create a user group for the project.

groupadd <project-name>

8.3 add the required user(s) to the group.

usermod -a -G <group name> <user name>

8.4 Allow push to checked out branch

cd /srv/repos/git/<project name>/.git

Append the following to config file.

 denyCurrentBranch = false

8.5 Assign permissions of git repo to group

cd /srv/repos/git/<project name>
 chown -R www-data.<group name> .git               # eg: chown -R www-data.myproject .git
 chmod -R 771 .git

9. Git for the project is ready for use now.

IMPORTANT: Never edit the source code by logging into to the vm and then commiting there(Otherwise, it will lead to insconsistency in the git repo). Always use git push remotely to modify the repository.

The repository is avaiable for remote use at ssh://<user name>@<IP>/srv/repos/git/public/<project>.git

To submit the initial code from your git repo to master branch in server,

#(If you are starting fresh withoud an existing local repo, in the directory containing the source files to be shared, do the following steps to initialize the local repo
 # git init
 # git add .
 # git commit -am "initial commit"

git push ssh://<user name>@<IP>/srv/repos/git/public/<project>.git  master

Others can clone the repo, create new branches and start working on them and push to master branch. Some remote examples are shown below. But it is better to start using after having a basic idea of git. A git tutorial is available at http://www.vogella.de/articles/Git/article.html

example commands:

//cloning a repo
 git clone ssh://<user>@<IP>/srv/repos/git/public/<project>.git
 //fetching from master
 git fetch ssh://<user><IP>/srv/repos/git/public/<project>.git  master
 //pushing to remote branch
 git push ssh://<user>@<IP>/srv/repos/git/public/<project>.git  <branch name>

You can avoid the hassle of typing password each time by using ssh passwordless login(see http://linuxconfig.org/Passwordless_ssh ). You can avoid the lengthy remote url in the commands by using “git remote add” (explained in the git tutorial).

Removing a project

cd /var/local/lib/trac/
 rm -rf git-<project>
 cd /etc/trac/
 rm -rf git-<project>.ini
 cd /srv/repos/git
 rm -rf <project>


The purpose of this article is to consolidate my understanding of the details of the everyday network and its various terminologies used. If you find errors(there is a good chance) or have a difference of opinion, please mention it in the comments section. I’ll consider them and make appropriate revisions.

keywords: layer 2, layer 3, broadcast domain, collision domain, switch, hub, bridge, router, layer 3 switch, IP address, MAC address, network layer, data link layer, DHCP, Default gateway, subnet, subnet mask

The OSI network reference model abstracts the network into 7 logical layers for separation of concerns. Layer 2(second from the bottom) is the data link layer and layer 3(third from the bottom) is the network layer(Layer 1, the bottommost, is the physical layer). Network devices are addressed through MAC addresses in the data link layer and IP addresses in the network layer. A network segment consists of a group of devices which form a part of a network.

When the devices have to communicate to each other, they have to be able to address each other and the sent packets have to be routed in the network to eventually reach the destination. An important concept in this respect is collision domain. If a network device, on receiving a packet addressed to one of the different hosts or networks connected to it,  sends copies of the packet to all the ports(where the the hosts/networks are connected), except the source port of the message, then all these hosts and networks form a single collision domain for the network device. Thus, a network device with a single collision domain simply make copies of all messages it receives, and sends them to all the hosts/networks in the collision domain except the source as it is unable to identify the correct destination among the possibilities. Such devices can be considered to be working at the physical layer(similar to a repeater)). A hub is an example of a device with a single collision domain. A hub simply make copies of each packets it receives in a port and sends them to all the other ports. The drawback of the devices with a single collision domain is that the bandwidth utilization is low. For example, if host A is sending to host B through a hub at 10kbps, then the bandwidth available at hosts C and D connected in the same hub will be reduced by 10kbps. This issue becomes magnified as the number of hosts increase and when many hubs are interconnected together.

Layer 2 addressing can be used to limit the collision domain. In layer 2, each device will have a unique MAC address. A layer 2-capable network device will be able to identify the destination host of a received packet from the destination MAC address in the packet and forward it only to the  port where the destination host is connected. Thus, there are multiple collision domains in the device(more precisely, one collision domain per port). Switch(specifically, layer 2 switch) is an example of a network device having this capability. Bridge is another layer 2 device(switches have higher performance as different ports are connected through independent paths internally, while in bridges different ports share a common path for packet forwarding internally ). Switches and bridges learn about the MAC address of the hosts connected in various ports from incoming messages and store them in a table(MAC address to port mapping) within for forwarding purpose. Thus, if the destination host MAC address of a packet in not available in its table, the switch will still flood a packet to all the other ports. But, after getting a reply from one of the ports, it will store the MAC address to port mapping in its internal table. Layer 2 networks cannot scale beyond a certain number of hosts as each switch will eventually have to store the MAC address to port mapping of most of the hosts in its table to avoid frequent broadcasts.

The scaling issue in layer 2 is solved by layer 3 addressing and routing. As stated earlier, devices address each other in layer 3 through IP addresses. A layer 3 network device(e.g., router) does routing of packets according to forwarding rules based on IP address prefixes of the source and destination addresses in the packets. A typical forwarding rule in a router could be “if packets come from port 1 with source IP prefix 192.168 and destination IP prefix 192.169. then, send it to port 5”. Since, the IP prefixes are used for routing, entire tables containing IP addresses of each host in the network need not be stored in a router.

The applications can communicate with remote hosts using the IP addresses of the remote hosts(without supplying the MAC address of the remote host). Consider that our office network consists of only layer 2 switches connected to each other interconnecting the different hosts. Each host has a unique IP address assigned to it. Assume that host A wants to communicate with host B by using the IP address of host B. But, the switch to which A is connected to will accept only MAC addresses for forwarding. Because of this, each host maintains a maintains a table(called ARP cache) containing IP address to MAC address mappings. If host B’s entry is available in the ARP cache of host A, it will send the packet to the switch with the MAC address of B mentioned in the packet. But, if the entry for B is not available in ARP cache of A, it sends a broadcast message(ARP query) to the switch with a packet asking “Who is <IP address of B> ?”.  Switch will identify that the incoming packet is a broadcast packet and will forward it to all the other ports. Other switches will also do the same when they get this broadcast packet. Thus, the broadcast packet will be seen by all hosts, in the network. Host B, on seeing such a message replies(ARP reply) to host A stating its MAC address.On receiving the reply, host A will add the entry for B in its table and send further messages to B using B’s MAC address. A layer 2 network consisting of only layer 2 network devices will be able to send broadcast to all the hosts/devices in the network. Hence, they have a single broadcast domain.

The matter gets further complicated when our layer 2 only network wants to communicate to the outside world. For this, a router will be connected to the layer 2 network (more specifically, to one of the switches in the layer 2 network). Now, when host A needs to communicate to host C using C’s IP address, it is not clear whether host C is present inside the layer 2 network or outside it(accessible through the router). If host C is inside our layer 2 network, we need to broadcast the ARP packet or look in the ARP cache. Otherwise, we need to forward the request to the router(Router will have a MAC address and IP address which can be used to communicate to it). Subnetting helps in making this decision.  A subnet is a logical portion of a network. The nodes in a subnet can be identified by the range of IP addresses of the subnet. The range of a subnet is defined by basically fixing the prefix portion of host IP addresses and the rest of the portion variable(for e.g., hosts can have IP addresses 192.168.10.[2-254]). The range of Ip addresses of a subnet is specified by a subnet mask. Each host need to configure its network interface with its IP address as well as the subnet mask to specify its subnet. Nodes which form part of different subnets can communicate to each othetr only through a layer 3 device like a router. Thus, in the earlier example, we need to ensure that all hosts in our layer 2 network belong to the same subnet. Host B can check its subnet mask to determine whether host C is in our internal network. If host C is in our network, it can broadcast the ARP request to the layer 2 network. Otherwise, it needs to forward the packet to the router to send it to the external network. For this, host A needs to know the IP address of the router. Hence, the IP address of the router has to be specified in the default gateway field of each host in the layer 2 network. If a host finds that a destination IP address in a packet is not in its own subnet and if no other routing configuration is present, then the packet has to be forwarded to the default gateway. Thus, when host B is not present in the layer 2 network host A forwards it to the default gateway(router) which further forwards it to the external network.

As discussed earlier, the user of each host needs to configure its IP address, subnet mask and default gateway. Since, it is not very user-friendly, DHCP can be used. If the user configures a network interface in the host to use DHCP, he don’t need to give the above details. When the host starts, it broadcasts a DHCP request in the layer 2 network. A DHCP server will be present in the network which on receiving the DHCP request, assigns an IP to the host and sends its IP address, subnet mask and default gateway. On receiving the DHCP reply, the host configures its interface automatically based on the information. Note that for DHCP to work, the network administrator has to set up a DHCP server in the network.

Our layer 2 network will fill forward the broadcast packets to all the hosts in it. But, on receiving such a broadcast packet, the router simply drops it(unless specially configured). Thus, the broadcast packet never goes out of a layer 2 network. Thus, routers limits the extend of broadcast domains. In other words a router creates multiple broadcast domains when it connects different layer 2 networks.

A layer 3 switch is a network device which has layer 2 functionalities like a switch, but also have layer 3 routing support.

I was creating a wordpress website in my web server which allowed for the download of a software. But, we wanted the download to happen only after the user had filled his details in a form.

We searched for an appropriate plugin for this, but could find only ss downloads as the closest to what wanted. But, ss downloads allows the download after the user has submitter his email id. Since, we needed additional information to be given like name, address, acceptance of terms and conditions etc. we decided to customize the plugin for it. If you have the same requirements, follow the steps we took to perform the same.

IMPORTANT: make sure to backup your website before doing the following.

1. If you have already installed ss downloads, remove it completely by doing as follows.

Go to wp-contents/plugins directory and delete the directory ss downloads.

cd wp-content/plugins/
rm -rf ss-downloads

You need to delete the ss downloads tables from the database also.
Login to your mysql database

mysql -u <username> -p

2. Switch to your wordpress database and delete the tables. (Use “show tables” to display all the tables in the database). <prefix> refers to your worpress table prefix.

use <wordpressdatabase>;
drop table <prefix>ss_downloads;
drop table <prefix>justemails;

3. Unzip a fresh download of the plugin in different directory not in the wordpress directory(e.g. your home directory or /tmp).
Open the file ss-downloads.php, look for the statement,

$sql = "CREATE TABLE " . $wpdb->justemails . " (

The details entered by the user will be store in this table. Modify the create table statement to include your desired fields.
For example,

$sql = "CREATE TABLE " . $wpdb->justemails . " (
			id mediumint(9) NOT NULL AUTO_INCREMENT,
			email VARCHAR(128) NOT NULL,
			firstname varchar(40) NOT NULL,
                          lastname varchar(40) NOT NULL,
                          jobcode varchar(5) NOT NULL,
                          company varchar(100) NOT NULL,
                          primaryactivity varchar(100) NOT NULL,
                          address varchar(500) NOT NULL,
                          phone varchar(100) NOT NULL,
                          countrycode varchar(5) not null,
                          tellus varchar(2000) not null,
			timestamp TIMESTAMP NOT NULL,
			UNIQUE KEY id (id)

4. Now, copy the ss-downloads directory to the website under plugins/ . Now go to the admin dashboard and enable the plugin. Create a sample download in a page using the same syntax as ss downloads ([download …]).
Now, we’ll modify the plugin step by step to suit our requirement. At any point you can view the website to verify that the desired modification is made.

5. Now open templates/emailform.php  Look for tag containing

 action="<?=SSD_PLUGIN_URL?>/services/addemail.php" method="post"

This is the form which the user sees to enter details. Change it as you want. For example,

<form name = "form1" action="<?=SSD_PLUGIN_URL?>/services/addemail.php" method="post" onSubmit="return checkform()">
<label for="element_1"><h3>First Name </h3></label>
<input id="element_1" name="firstname" type="text" maxlength="255" value=""/>

<label for="element_4"><h3>Last Name</h3></label>
<input id="element_4" name="lastname" type="text" maxlength="255" value=""/>

<label for="element_3"><h3>Job</h3></label>

Make sure you give a unique name for each element(e.g. name=”lastname”). You can even add javascript to the file for form validation.

6. Open services/addemail.php. Here, you need to add the entered details to the database. Look for the statement

$email = $_REQUEST['email'];

Add your own field also just under it in the format $<name> = $REQUEST[‘<name>’]; where <name> is name you gave for the field in emailform.php. For example,

$firstname = $_REQUEST['firstname'];
$lastname = $_REQUEST['lastname'];
$jobcode = $_REQUEST['jobcode'];
$company = $_REQUEST['company'];
$primaryactivity = $_REQUEST['primaryactivity'];
$address = $_REQUEST['address'];
$phone = $_REQUEST['phone'];
$countrycode = $_REQUEST['countrycode'];
$tellus = $_REQUEST['tellus'];

Now change database insert instruction and change it as per your fields. The instructions starts with $wpdb->insert($wpdb->justemails,..). For example,

$wpdb->insert($wpdb->justemails, array('email' => $email, 'firstname' => $firstname, 'lastname' => $lastname, 'jobcode' => $jobcode, 'company' => $company, 'primaryactivity' => $primaryactivity, 'address' => $address, 'phone' => $phone, 'countrycode' => $countrycode, 'tellus' => $tellus), array('%s','%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'));

We are finished! You can go mysql to view the entered user details by giving

select * from <prefix>justemails;

Please leave your comments on the article including tips for improvement.