This feature is EXPERIMENTAL and is NOT SECURE. It will allow access to arbitrary files on your server.
This document describes one way to setup a Bazaar HTTP smart server, using Apache 2.0 and FastCGI or mod_python.
You have a webserver already publishing /srv/example.com/www/code as http://example.com/code/... with plain HTTP. It contains bzr branches and directories like /srv/example.com/www/code/branch-one and /srv/example.com/www/code/my-repo/branch-two. You want to provide read-only smart server access to these directories in addition to the existing HTTP access.
First, configure mod_fastcgi, e.g. by adding lines like these to your httpd.conf:
LoadModule fastcgi_module /usr/lib/apache2/modules/mod_fastcgi.so FastCgiIpcDir /var/lib/apache2/fastcgi
In our example, we're already serving /srv/example.com/www/code at http://example.com/code, so our existing Apache configuration would look like:
Alias /code /srv/example.com/www/code <Directory /srv/example.com/www/code> Options Indexes # ... </Directory>
We need to change it to handle all requests for URLs ending in .bzr/smart. It will look like:
Alias /code /srv/example.com/www/code <Directory /srv/example.com/www/code> Options Indexes, FollowSymLinks RewriteEngine On RewriteBase /code RewriteRule ^(.*/|)\.bzr/smart$ /srv/example.com/scripts/bzr-smart.fcgi </Directory> # bzr-smart.fcgi isn't under the DocumentRoot, so Alias it into the URL # namespace so it can be executed. Alias /srv/example.com/scripts/bzr-smart.fcgi /srv/example.com/scripts/bzr-smart.fcgi <Directory /srv/example.com/scripts> Options ExecCGI <Files bzr-smart.fcgi> SetHandler fastcgi-script </Files> </Directory>
This instructs Apache to hand requests for any URL ending with /.bzr/smart inside /code to a Bazaar smart server via FastCGI.
First, configure mod_python, e.g. by adding lines like these to your httpd.conf:
LoadModule python_module /usr/lib/apache2/modules/mod_python.so
Define the rewrite rules with mod_rewrite the same way as for FastCGI, except change:
RewriteRule ^(.*/|)\.bzr/smart$ /srv/example.com/scripts/bzr-smart.fcgi
RewriteRule ^(.*/|)\.bzr/smart$ /srv/example.com/scripts/bzr-smart.py
Like with mod_fastcgi, we also define how our script is to be handled:
Alias /srv/example.com/scripts/bzr-smart.py /srv/example.com/scripts/bzr-smart.py <Directory /srv/example.com/scripts> <Files bzr-smart.py> PythonPath "sys.path+['/srv/example.com/scripts']" AddHandler python-program .py PythonHandler bzr-smart::handler </Files> </Directory>
This instructs Apache to hand requests for any URL ending with /.bzr/smart inside /code to a Bazaar smart server via mod_python.
Refer to the mod_python documentation for further information.
We've configured Apache to run the smart server at /srv/example.com/scripts/bzr-smart.fcgi. This is just a simple script we need to write to configure a smart server, and glue it to the FastCGI gateway. Here's what it looks like:
import fcgi from bzrlib.transport.http import wsgi smart_server_app = wsgi.make_app( root='/srv/example.com/code', prefix='/code/', path_var='REQUEST_URI', readonly=True) fcgi.WSGIServer(smart_server_app).run()
We've configured Apache to run the smart server at /srv/example.com/scripts/bzr-smart.py. This is just a simple script we need to write to configure a smart server, and glue it to the mod_python gateway. Here's what it looks like:
import modpywsgi from bzrlib.transport.http import wsgi smart_server_app = wsgi.make_app( root='/srv/example.com/code', prefix='/code/', path_var='REQUEST_URI', readonly=True) def handler(request): """Handle a single request.""" wsgi_server = modpywsgi.WSGIServer(smart_server_app) return wsgi_server.run(request)
Now you can use bzr+http:// URLs, e.g.:
bzr log bzr+http://example.com/code/my-branch
Plain HTTP access should continue to work:
bzr log http://example.com/code/my-branch
Because the Bazaar HTTP smart server is a WSGI application, it can be used with any 3rd-party WSGI middleware or server that conforms the WSGI standard. The only requirements are:
- to construct a SmartWSGIApp, you need to specify a root transport that it will serve.
- each request's environ dict must have a 'bzrlib.relpath' variable set.
The make_app helper used in the example constructs a SmartWSGIApp with a transport based on the root path given to it, and calculates the 'bzrlib.relpath` for each request based on the prefix and path_var arguments. In the example above, it will take the 'REQUEST_URI' (which is set by Apache), strip the '/code/' prefix and the '/.bzr/smart' suffix, and set that as the 'bzrlib.relpath', so that a request for '/code/foo/bar/.bzr/smart' will result in a 'bzrlib.relpath' of 'foo/bzr'.
It's possible to configure a smart server for a non-local transport, or that does arbitrary path translations, etc, by constructing a SmartWSGIApp directly. Refer to the docstrings of bzrlib.transport.http.wsgi and the WSGI standard for further information.
It is possible to allow pushing data over the http smart server. The easiest way to do this, is to just supply readonly=False to the wsgi.make_app() call. But be careful, because the smart protocol does not contain any Authentication. So if you enable write support, you will want to restrict access to .bzr/smart URLs to restrict who can actually write data on your system. At this time, it is not possible to allow some people to have read-only access and others to have read-write access to the same urls. Because at the HTTP layer (which is doing the Authenticating), everything is just a POST request. However, it would certainly be possible to have HTTPS require authentication and use a writable server, and plain HTTP allow read-only access.