Call us Toll-Free:
1-800-218-1525
Email us

How to serve Mercurial HG repository over NGinx

Adrian Singer, September 3    --    Filed under Programming
Mercurial server can be setup in two modes:

* hg serve - a built in lightweight web server that is provided as part of the Mercurial package. hg serve can be used to quickly serve a single repository, but it's not a good choice for production systems.

hg serve doesn't support user authentication, multiple repositories and is limited to handling a single connection at a time.

* hgweb.cgi - a Python script that is faster, supports user authentication, multiple repositories, styles and web console.

As part of this post I'll walk you through setting up hgweb.cgi on an NGinx web server.

Step 1 - Install Python

cd /usr/ports/lang/python25
make all install

Step 2 - Install hgweb.cgi

Save this file under your web server main direcory.

hgweb.cgi:
#!/usr/bin/env python

import cgitb
from mercurial.hgweb.hgwebdir_mod import hgwebdir
from mercurial.hgweb.request import wsgiapplication
from flup.server.fcgi import WSGIServer

cgitb.enable()

def make_web_app():
return hgwebdir("/home/admin/htdocs/hgweb.config")

WSGIServer(wsgiapplication(make_web_app)).run()

Replace /home/admin/htdocs/ with your web server folder

Step 3 - Configure hgweb

Save this config file under your web server main directory.

hgweb.config:
[ui]
username = root
editor = vim

[hooks]
changegroup = hg update >&2

[web]
baseurl =/.
style= gitweb
push_ssl = false
allow_push = *

[paths]
Clients = /home/
SPI = /home/admin/htdocs/

Replace mydomain with your web server url

Create this global settings file under /etc/mercurial/hgrc:

[web]
style= gitweb

Step 4 - Install Spawn-fcgi

Before we can tell NGinx to handle the hgweb.cgi Python script, we have to install spawn-fcgi

Follow these steps:
wget "http://www.lighttpd.net/download/spawn-fcgi-1.6.2.tar.gz"
tar -xvf spawn-fcgi-1.6.2.tar.gz
cd spawn-fcgi-1.6.2
./configure
make all
make install

Start spawn-fcgi:
/usr/local/bin/spawn-fcgi -f /home/code/hgweb.cgi -a 127.0.0.1 -p 8081

Try running hgweb.cgi by issuing: python hgweb.cgi
If you get a message about missing flup, you'll have to download flup and install it:

wget "http://www.saddi.com/software/flup/dist/flup-1.0.1.tar.gz"
tar -xvf flup-1.0.1.tar.gz
cd flup-1.0.1
python setup.py install

--

Now create a new file under /usr/local/etc/rc.d/start-spawnfcgi.sh to start spawn-fcgi automatically after a reboot.

Save the same line above under /usr/local/etc/rc.d/start-spawnfcgi.sh

Step 5 - Configure NGinx

Add this to your nginx.conf, replacing mydomain.com with your web server domain name and 1.2.3.4 with the dedicated ip address:

server {
listen 1.2.3.4:80;
server_name mydomain.com;

server_name_in_redirect off;

auth_basic "Restricted";
auth_basic_user_file /home/hg/.htpasswd;

gzip on;

location / {

root /home/hg/;
index index.php index.html index.htm;

fastcgi_pass 127.0.0.1:8081;
fastcgi_param SCRIPT_FILENAME /home/hg/$fastcgi_script_name;
include /etc/nginx/fastcgi_top.conf;
fastcgi_param DOCUMENT_ROOT /home/hg/;
include /etc/nginx/fastcgi_bottom.conf;

fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
}


}

Note that we are password protecting the repository by using an .htpasswd file. You can generate one using publicly available htpasswd generators like this one.

Tell NGinx to reload its configuration file:
kill -HUP `cat /usr/local/nginx/logs/nginx.pid`

If all goes well, you should be able to point your browser to mydomain.com and see a list of Mercurial repositories.

View 2 Comment(s)

Mercurial Version Control

Adrian Singer, September 2    --    Filed under Programming
Mercurial (also called HG) is a cross-platform, super-fast, distributed revision control system for software developers.

Unlike other version control tools such as CVS, SVN, Preforce etc., Mercurial is a distributed system, where every node can act as both a client and server.

We've tested a lot of competing revision control systems, before Mercurial won us over.

The advantages Mercurial brings to the table include:

* Allows users to work on a local copy of the files, even when not connected to a network

* Most operation are faster since no network is involved

* Allows private work, so you can use your revision control system even for early drafts you don't want to publish

* Avoids relying on a single physical machine. A server disk crash is a non-event with distributed revision control

* Allows participation in projects without requiring permissions from project authorities, instead of requiring "committer" status

Graphical User Interface

Mercurial comes with great desktop integration for Windows and Mac, using a tool called Tortoise. Once installed, it adds a right-click context-menu, allowing one-click commit, file diff, sync, directly from the file explorer.

Tortoise includes a green icon next to all files that are up-to-date and an orange icon next to files that have been updated and need to be uploaded.



How to install Mercurial

An all-in-one Mercurial+Tortoise installer is available here

Once installed, Mercurial will add a right-click context-menu, as shown in the image above.

Before you move forward, it is important that you setup a Username, so that all Commits you upload, include your name.

Right click and select 'Global Options' from HG menu. Then enter your full name under Username



Next - click on the 'Sync' tab and select Update as the 'after pull operation'



Connecting to a live repository

Create a new folder on your machine where you'd like to save all source files, right click and select 'Create Repository Here' from Mercurial's menu



This will create two files under the current directory:
.hg subfolder
.hgignore text file

To avoid any conflicts, go ahead and delete the .hgignore text file.

Now that the repository is created, we can download all files from the server. Right click again and select 'Synchronize' from the menu.

This popup window will open:



Enter the live repository url and click the 'Pull' button to download all source files from the live repository.

Note: You can repeat this process of synchronizing with the live server, whenever you'd like to download updates from the server.

The first time you synchornize, it's going to take a while. But subsequent pulls will be very quick.

Updating Files

Step 1: Open the local copy of the file in your favorite editor, make changes and hit Save.

Mercurial detects the change and automatically updates the file icon to orange.

Step 2: Once you're done making changes, right-click and select HG Commit.

Enter a comment describing the changes you've just implemented. For example:
"Project 384283 - Added opt-in form on instant pay increase"

Good comments are the basis of a solid version control system. Your comments help other developers understand the nature of your changes, as they download them to their local repositories.

Step 3: Unlike a centralized cvs, the 'Commit' operation is a local one. Once changes are committed to your local repository, Right click and select 'Synchronize'. Enter the live repository url and click the 'Push' button. This takes care of uploading your changes to the server.

Adding new files to the project

In order to add a new file, you have to take one additional step -

Highlight the new files, right click and select 'Add Files'



Then, follow the steps listed under "Updating Files", committing changes and synchronizing with the server.

View 2 Comment(s)

How to install vsftpd on FreeBSD

Michel Nadeau, August 28    --    Filed under Programming
vsftpd is a very light-weight, full-featured FTP server that can be installed and ready to use in only a couple of minutes. It's used by many huge FTP sites like RedHat, Debian, GNU, ISC and many more!

NOTE: you can use this tutorial to install vsftpd on almost any UNIX/Linux distribution, except for the step 4.

1. Installing vsftpd

Installing vsftpd is very simple. First, you need to download and extract it:

mkdir -p /usr/local/src
cd /usr/local/src
fetch ftp://vsftpd.beasts.org/users/cevans/vsftpd-2.2.0.tar.gz
tar xvfz vsftpd-2.2.0.tar.gz

Then, you're ready to compile it:

cd vsftpd-2.2.0
make

And then to install it:

make install

2. Configuration

vsftpd uses the /etc/vsftpd.conf configuration file. A good idea is to start with the default one:

cp vsftpd.conf /etc

Here's a complete reference guide to customize each options of vsftpd.conf:

http://vsftpd.beasts.org/vsftpd_conf.html

3. Start/stop vsftpd

To start vsftpd, simply run:

vsftpd

To stop it, you have to kill it:

killall vsftpd

4. Start vsftpd automatically on boot

To start vsftpd automatically on boot, simply create the /usr/local/etc/rc.d/vsftpd.sh file, change its mode to 755, and put this content in it:

#!/bin/sh

/usr/local/sbin/vsftpd &

Conclusion

vsftpd is faster than proftpd, easier to install and to configure. It's very secure, stable and flexible: try it and give me your opinion about it!

How to setup web server vhost + FTP account on NGinx and ProFTPD

Adrian Singer, August 26    --    Filed under Programming
As part of this post I will walk you through the process of setting up shared hosting, using an NGinx web server, ProFTPD ftp and Bind DNS.

Before you get started, you're going to need three things:

* Domain name to setup vhost under
* A dedicated ip address to use for the vhost
* Select username and password for ftp

Step 1 - Point to DNS servers

Login to your domain registrar (GoDaddy, eNom etc.), click on the designated domain and then update the DNS servers managed by this domain to DNS servers that you control.

Here at SPI, we use AlwaysUpDNS, so the two DNS servers to setup with the new domain, are going to be:

dns1.alwaysupdns.com
dns2.alwaysupdns.com

Once you update the DNS servers, it may take anywhere from 1 to 48 hours for the changes to propagate.

To check whether or not DNS propagated, you can run this command

dig mydomainname.com

Step 2 - Setup DNS hosting

Add new DNS hosting entry for the designated domain.

Here at SPI we use a custom version of Bind, so the way this is done is:

(a) Create a copy of a template 'blank' DNS hosting record

cp /etc/alwaysupdns/template.dns /etc/alwaysupdns/mydomainname.dns

Replace mydomainname with the domain name

The end file should look like this:

$TTL 60

@ IN SOA mydomain.com. mydomain.com. (
20090710 ; Serial number
60 ; Refresh
900 ; Retry
864000 ; Expire
60 ; Min TTL
)

; A record (web browsers go here)
@ IN A 1.2.3.4

; Email server
mydomain.com. MX 10 mx1.softwareprojects.com.

; DNS Servers
@ IN NS dns1.alwaysupdns.com.
@ IN NS dns2.alwaysupdns.com.

(b) Edit /etc/alwaysupdns/mydomainname.dns in your favorite editor and update the A record to point to the new dedicated ip address (replacing 1.2.3.4).

Also while you're at it, replace all occurrences of 'mydomain' with your domain name.

You can leave everything else as is.

(c) Edit /var/named/etc/namedb/named.conf and add this block to the end of the file

zone "mydomain.com"
{
type master;
file "/etc/alwaysupdns/mydomain.dns";

allow-transfer { 204.13.249.76; 208.78.69.76; 91.198.22.76; 203.62.195.76; };
};

Replace 'mydomain' everywhere with the domain name.

The zone-trafser details, make it possible to use DynDNS as a secondary level dns server.

(d) Restart Bind DNS by issuing:

killall named
named

(e) Test Bind is returning the correct response:

nslookup
server dns1.alwaysupdns.com
set q=a
mydomain.com

Step 3 - Add vhost record to Nginx

Open the NGinx config file (/usr/local/nginx/conf/nginx.conf) in your favorite editor and add this section to the bottom of the file, right before the closing }

# MyDomain
server {
listen 1.2.3.4:80;
server_name www.mydomain.com *.mydomain.com;
server_name_in_redirect off;

# set regular docroot
location /
{
root /home/mydomain.com/;
index index.php index.html index.htm;
}

location ~* \.(php)$
{
fastcgi_intercept_errors on;

fastcgi_pass backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/mydomain.com/$fastcgi_script_name;
include /etc/nginx/fastcgi_top.conf;
fastcgi_param DOCUMENT_ROOT /home/mydomain.com;
include /etc/nginx/fastcgi_bottom.conf;
}

}

Replace 1.2.3.4 with the new dedicated ip address

Replace mydomain with the new domain name and create a new folder under /home/mydomain.com to host the new site

Once done, tell NGinx to reload its config file, by issuing

kill -HUP `cat /usr/local/nginx/logs/nginx.pid`

Step 4 - Create FTP user

First we have to create a system user, by issuing an adduser and providing a username and password you've preselected for this website.

Be sure to specify the folder as /home/mydomain.com (replacing mydomain with the chosen domain) and enter ftponly as the new user shell.

For example:

adduser

Username: mydomain
Full name: My Domain
Uid (Leave empty for default):
Login group [mydomain]:
Login group is mydomain. Invite mydomain into other groups? []:
Login class [default]:
Shell (sh csh tcsh bash rbash ftponly nologin) [sh]: ftponly
Home directory [/home/mydomain]: /home/mydomain.com
Home directory permissions (Leave empty for default):
Use password-based authentication? [yes]:
Use an empty password? (yes/no) [no]:
Use a random password? (yes/no) [no]:
Enter password:
Enter password again:
Lock out the account after creation? [no]:
Username : mydomain
Password : *****
Full Name : My Domain
Uid : 1031
Class :
Groups : mydomain
Home : /home/mydomain.com
Home Mode :
Shell : /sbin/ftponly
Locked : no
OK? (yes/no): yes
adduser: INFO: Successfully added (mydomain) to the user database.

Step 5 - Jail FTP user

To prevent the FTP user from gaining access to any other folders on this server, we need to jail the user to the home directory for the new domain.

Open ProFTPd config file (/usr/local/etc/proftpd.conf) and locate the block that begins with DefaultRoot

Add this line below, replacing mydomain with the new domain name

DefaultRoot /home/mydomain.com mydomain

Restart ProFTPD by issuing

killall proftpd
/usr/local/etc/rc.d/proftpd.sh

Then connect to the new site via FTP and verify it is working properly, not letting you access any parent folders above the current directory.

Step 6 - Update permissions

The last step is to update the new folder permissions, so that our FTP user will be able to create / delete files.

chown -R mydomain:mydomain /home/mydomain.com/

Replace mydomain with the chosen domain name

How to fix: MySQL Duplicate entry for key PRIMARY on Auto_Increment

Adrian Singer, August 20    --    Filed under Programming
We encountered an interesting error on a client database this past few days, where MySQL was issuing random errors, complaining about:

Duplicate entry '1' for key 'PRIMARY'

These errors were coming up on various tables at different times in the day, but the crazy thing is - the duplicate key error is on an auto-increment field!

That's not normal.

When you have a table defined as

CREATE TABLE test (id int auto_increment, somevalue int, primary key (id));

There's no way you can generate a duplicate key error on the 'id' field, unless you manually pass the value of the auto_increment id field (which we were not)

Running a mysqlcheck reported all tables are OK. We proceeded to issue OPTIMIZE TABLE statements (this rebuilds indexes) as well as manually running REPAIR TABLE for each table, but nothing helped.

The table indexes were obviously corrupted in some way, although MySQL tools reported all is well...

How to fix this problem

The only way we could fix it, is by rebuilding the entire database from scratch.

Dropping all tables and reloading them from a backup.

Step 1

Create a backup of the database by issuing:


mysqldump
-uUSER -pPASSWORD DBNAME > /tmp/my_backup.sql

Replace USER with your MySQL username, PASSWORD with your MySQL password and DBNAME with the databasename you are looking to repair.

Step 2

Drop and recreate the database


drop database DBNAME
;
create database DBNAME;

Step 3

Reload the import


mysql
-uUSER -pPASSWORD DBNAME < /tmp/my_backup.sql


View 2 Comment(s)

How to avoid Rsync Endless Loop

Adrian Singer, July 27    --    Filed under Programming
Rsync is a great command-line sync tool, that allows fast replication from one web server to another.

If you are running more than one Rsync command in a cronjob, replicating several folders into a target machine, watch out for the Rsync endless loop bug.

There are two steps you can take to avoid this:

Step 1:

Consider this scenario:

Destination machine B has these two cronjobs, set to run every 5 minutes:

*/5 * * * * /usr/local/bin/rsync --progress --stats --archive -z --compress -t MachineA.com:/usr/home/ /usr/home/

*/5 * * * * /usr/local/bin/rsync --progress --stats --archive -z --compress -t MachineA.com:/usr/home/something/ /usr/home/something/

Since the folder /usr/home/something/ is also included by the first cronjob, this can easily cause the infamous Rsync endless loop bug.

The fix, add an --exclude to the first cronjob, like this:

*/5 * * * * /usr/local/bin/rsync --exclude /usr/home/something/ --progress --stats --archive -z --compress -t MachineA.com:/usr/home/ /usr/home/

*/5 * * * * /usr/local/bin/rsync --progress --stats --archive -z --compress -t MachineA.com:/usr/home/something/ /usr/home/something/

Step 2:

If it takes more than 5 minutes for Rsync to complete, before the next instance runs, you're in trouble.

To be safe, write a php script that will check if the Rsync daemon is running, prior to launching another one.
« Previous Posts » Next Posts



About Us  |  Contact us  |  Privacy Policy  |  Terms & Conditions