This was one of my project proposals for the Interactivos'13 open-source projects workshop in Madrid. It didn't get selected in the end, but if you feel inspired by this or want to implement this … feel free to do so. This is open content licenced under CC BY 3.0 or at your option, any later version.

Project Summary

For many professions, there's a home for collaboration on the Net: programmers have SourceForge and Github (and many more). Electronics engineers have Open Design Engine ( and Upverter ( Writers have tools like EtherPad Lite and Google Docs. But artists and designers? Not one I'm aware of. 

Sure, there's and Huge platforms, but not collaborative at all: the only thing to do there is present your work and comment on others. "Fork Me on Art Hub" project wants to fill exactly that gap. It wants to place artists and designers into an open content "rhizome of graphical knowledge", where it feels like everybody collaborating with everybody else, and doing so without needing any special invitation.

Here's how: A web-based platform for social collaboration in artwork and design, grown around version management for artwork files with git, the promotion of open content licenses (like CC-BY-SA), and "uninvited contributions" by fellow designers and those previously known as "art consumers". This kind of "uninvited contributions" is well-known in the software world, for example called "forking" and "pull requests" on Github.

(Note: For the version management part, this project is complemented by the "Git for GIMP" project proposal. That project makes the workflow much more likable for designers, but initially the platform can also work without this and collaborate with SparkleShare for example.)

Project Description

The portal's functionality is best explained by assuming a "social network" type portal, plus the following features (listed by importance, and explained in detail in the "Project Description"):

  1. Free git project hosting. Artists and designers can register for free and host art project for free as long as they assign an open content license to it. All art projects are automatically versioned with git, and the different versions are also accessible via a web interface (gitorious is a nice base software for that). And not just the artwork will be in the git repo, also utility files and everything else needed to collaborate on an artwork, like scripts for generative art.

  2. "Fork Me" function to create derivatives. Like on Github, there will be a prominent "Fork" feature. Once you click this, it allows to initialize a new own git repo with the artwork in question, and to add own versions by building on original ones. Once you have something you want to contribute back to the original author, you can create a "pull request" for that version.

  3. One-click accepting of contributions. Ideally, it will be possible to include others' updates back into your own work by just clicking "accept" for an appropriate pull-request notification that pops up on the website. It would be possible to get pre-views of the changes before accepting a change, of course.

  4. Embeddable widget with "Fork Me" function. This is one of the most innovative aspects here. For embedding an artwork into a website, whether the artists own one or any other, the Art Hub platform provides auto-generated "embed code". That HTML snippet not only shows the artwork, but also a "Fork Me" button that takes the reader to the Art Hub platform and shows some easy steps to create a derivative artwork. And then, all derivatives are shown in a slideshow that is also accessible from within the embedded HTML. Which means that creating derivative works results in immediate publicity in all publications showcasing the original work – and the "consumer" is no longer consumer at all, but co-producer. Esp. for art-related publications it will be a lot of fun for the artistists and art-enthusiast readers to see the derivative works produced by their fellow readers.

  5. Social commit messages. To make the Art Hub system more enjoyable in spute of quite technical version management, the git commit messages for each new version should be split into a technical and social part. Giving thanks, making a funny comment etc. goes into the social part, and update notifications and pull requests on the web platform would should show these social parts of the commit message as well, alongside with the picture of the author, similar to the update notification feed found in social networks like Facebook.

  6. Derivative graph. With artwork, it's not like with software: given a set of derivatives, people will hardly ever agree on a best version, while in software all improvements are regularly merged into the main version. So with artwork, there will be many forks that do not get merged back into the original, and these should be shown as a tree-like graph of derivative works (incl. preview images) on a project's page.
    This would even be the main feature of this invention: allowing not just one version of a graphic to exist, but a lot of interdependent versions. (They can be all incorporated within one git repo, as branches that branch into even more branches.) Those who search for a work to incorporate can then look through all the variants. And it would be the work of the main graphic project's authors to provide a systematic collection of the derivatives that are the most relevant, in her view.

  7. "Getting derivatives" as reputation. Collaboration is also about culture: on Github, you can estimate the popularity of a project by looking at the number of followers and forks. And similarly, people creating derivative works should be considered a good thing on the Art Hub platform and their number would be shown prominently, to encourage the culture of sharing.

  8. Embedding option with automatic attribution. When generating the HTML snippet with the embed code, the platform also automatically includes proper attribution for all base works, in accordance with the artworks' licenses. This automatic attribution removes a major practical hazzle when dealing with open content photography and images: keeping track of sources and attributing correctly.

  9. art hub integration into FLOSS graphics apps. There would be plugins for major FLOSS apps (GIMP, Inkscape, MyPaint) to open and fork Art Hub art repositories directly from the Internet. (Note that these app plugins would manage a local git repo invisibly, no need to care about that.) When saving back to the repo (or a new forked repo) with the graphics application, a "new fork / derivative / pull request" notice will appear on the Art Hub platform. Tihs feature is for workflow improvement only, and not needed for a first working verison.

  10. Federation. Some artists may want to fork the platform itself and create their own self-hosted artist community. As the platform software will be free and open source, this is clearly possible. However there should be an actively promoted "federation" feature that allows a global search on all platforms that have it enabled, plus cross-platform forking of artwork projects.

  11. CC licence registry. The platform can also take over the role of a "copyright licence registry", here for open content licenses, as another way to promote collaboration among the arts. It's a platform to record the fact of people licencing their work, to avoid potential later legal hazzle.

  12. Automatic pingbacks for derivatives. Of course the platform informs the authors about derivatives created on the platform, but additionally it can search the web (with image similarity search etc.) for other derivatives and likewise create notifications for these.

  13. New collaboration option for large graphics. This software would allow new types of collaboration on large infographics etc., by creating placeholders at first, putting them together into the master graphic, then letting everybody work on fleshing out one placeholder each and feeding the changes automatically into the master graphic.
    Similarly, this kind of distributed, versioned graphics creation system should also work for multi-page DTP documents with lots of illustrations, like by integrating it with Scribus. So a lot of authors (including the general public) can work on creating a complex document, both the text and graphics.

This was one of my project proposals for the Interactivos'13 open-source projects workshop in Madrid. It didn't get selected in the end, but if you feel inspired by this or want to implement this … feel free to do so. This piece is open content licenced under CC BY 3.0 or at your option, any later version.

Project Summary

Version control software like git makes collaboration between programmers quite seamless: it can merge together their changes and lets them revert unwanted changes. Not so for artists and designers, where collaboration still can mean mailing files around with timestamps in filenames. That's slow and error prone, not the fun of simultaneous collaboration.

Projects like SparkleShare improve on that, bringing git to designers (and designers love it). But git was originally made for source code and not images, so it's always a manual editing effort to merge changes from two designers who did parallel changes to the same version of an artwork. Resolving all these conflicts manually is also no fun, and effectively blocks designers from experiencing git's true power: branching, for example. You could do some experimental changes to some artwork, exploring your own path or paths, while your collaborators proceed on the main version, fixing little flaws for example. Once you agree what experimental changes to include in the main version, git should do so for you. For source code, git can do so automatically. For GIMP images (or maybe MyPaint, Inkscape or Scribus files instead), this project will extend git with that ability.

An additional aspect of this project is that it complements the "Fork Me on Art Hub" project proposal, which is a git based art sharing platform with novel features that encourage collaboration between artists and those still considered "consumers of art". However, this project can also function without that special platform, as it can work with every git repository (like from GitHub, Gitorious, Bitbucket, or self-hosted).

Finally, here's the main technical innovation of this "Git for GIMP" project: "change instructions" for raster images. For now, when SparkleShare stores a new image version into a git repository, it does so as a binary file. Git can compare it to the earlier version and store only the binary diff to save space (see "git gc"), but it does not understand about its inner structure, so it does not know how to merge parallel changes. After this project, git will instead store an image version as aggregated "change instructions" for a base image. Informal examples of change instructions would be:

  • move layer "person 1" by 14 px to right and by 30 px to top
  • change transparency of layer "flare" to 30%
  • change image data of layer "shadow" by combining it with the attached overlay layer (which has RGBA enabled)

The last type allows git even to merge changes to the actual image data of the same layer. Namely, if they don't conflict (don't affect the same pixels). Note that working with image files is no different with this extended git: when checking out a specific version, git will apply the relevant change instructions to the base version and provide the requested version in your file system.

Project Description

The "Project Summary" contains all the major points about this project already, so here are just some more details about the idea and possible implementation, in a quite random order, one detail per paragraph:

The current situation of images in git / svn. There are several options to add handling of binary data to git [examples]. It seems that changes only create small increments in repo size (at least when using "git gc" garbage collection). This would be the same as in SVN then, as discussed with a Pixelnovel Timeline developer. However in all these cases, git and svn do not yet understand about the inner structure of the image files, so they cannot automatically merge non-conflicting changes.

The user's experience. From a user's perspective, the software should act mostly like SparkleShare (and will probably indeed be based on it!). So, a designer's work is synced to a central git repository and from there to teammates automatically whenever a change is saved. However, to enable advanced versioning like git branching, there will be a little git plugin for the chosen graphics application, probably GIMP, to enter the git commit message, choose or create a branch, revert to a prior version (ideally with thumbnail preview) and so on.

GIMP or Inkscape? The proposal is here so far to build a tool for putting OpenRaster images (from GIMP or MyPaint) into git repositories. This requires a completely new tool to extract the "change instructions" mentioned above, and to build new OpenRaster images by applying them. If that's too complex for a two-week workshop, a similar approach can be done for Inkscape's SVG files. With the advantage that they are XML text already, so it will require little effort to teach git how to merge parallel changes. The main effort would then be to develop a user-friendly git plugin for Inkscape that designers will love to use. (It should show incoming "pull requests" notifications when others have done changes to an open file, and the designer would accept them with a single click.)

OpenRaster, not XCF. In case that a pixel based graphics application is chosen for this project (like GIMP, which is the current proposal), it is advisable to use the OpenRaster format for storing the images. So, not GIMP's native XCF format, which is not recommeded as a data interchange format and mostly represents GIMP's internal data structures [source]. OpenRaster is included in GIMP since version 2.7.1 or 2.8 [source]. The additional advantage of OpenRaster is that it benefits multiple applications (like MyPaint) and allows collaboration between them. A disadvantage is that it is still quite a new, not much adopted file format – but nonetheless the proposed open standard format for raster images. Apart from OpenRaster and XCF, TIFF would be the only other format that could be used. However the modes of saving layer metadata etc. are normally proprietary, as TIFF is basically just a container format.

Deriving instructions from GIMP history? In GIMP's case, these "change instructions" might be derived from the GIMP's history feature. But maybe a better alternative is to derive them by comparing two versions of a saved file directly – as done in the world of source code by "diff".

Inspirations from Pixelnovel Timeline and ComparePSD. The closest existing product for version control in images is Pixelnovel Timeline, and it offers a lot if insights for a great workflow and user interface when developing version control software for designers – see . It is based on the SVN version control system, however it can only do linear versioning and rollback and needs manual merging for changes derived in parallel from the same version. Also interesting for UI design in this project is the Pixelnovel ComparePSD tool for comparing PSD files layer by layer.

Inspirations from Kaleidoscope App. There is an app for visually comparing differeing versions of an image, to spot differences optically: Kaleidoscope.

This applies to Debian 6 "Squeeze", using PHP 5.4.11 from Dotdeb, and Froxlor 0.9.27 from the Debian archives.

Setup instructions

  1. We assume that your Apache2 server is installed and working, and so is your PHP 5.4.x installation.
  2. Install PHP-FPM:
    apt-get install libapache2-mod-fastcgi php5-fpm
  3. Enable to use PHP-FPM in Froxlor. (After saving, you will get an additional "configuration" link in the line for PHP-FPM.)
  4. In the PHP-FPM configuration in Froxlor, change "Path to php-fpm configurations" to "/etc/php5/fpm/pool.d/", because that's the path where the Debian package expects these .conf files by default. (Alternatively, you could adapt that behavior by editing the include directive in /etc/php5/fpm/php-fpm.conf, at the very bottom).
  5. In the PHP-FPM configuration in Froxlor, change "Command to restart php-fpm" to "/etc/init.d/php5-fpm restart".
  6. Let Froxlor create the new configs:
    php /var/www/froxlor/scripts/froxlor_master_cronjob.php --force
  7. Exchange the php5 handler with the fastcgi one (and other stuff needed by PHP-FPM):
    a2enmod fastcgi actions alias
    a2dismod php5
  8. Fix that Apache complains about a config line "Invalid command 'SuexecUserGroup'" in the Apache vhost configs generated by Froxlor [source]:
    1. apt-get install apache2-suexec
    2. a2enmod suexec
  9. Fix that php-fpm cannot start because Froxlor missed creating system users and groups for the customers it refers to by name in the php-fpm config files.
    1. cd /var/customers/webs/
    2. For every customer in there, execute an equivalent with the proper ID values and customer names for:
      addgroup --gid 10006 customername
      adduser --uid 10006 --gid 10006 customername
  10. Restart PHP-FPM:
    service php5-fpm restart
  11. Restart Apache2:
    service apache2 restart

Should work now. Verify by testing as shown below.

How to test your setup

  1. When testing your setup, test with a domain or subdomain site, not with the "IP and port" site. Because for the latter one, Froxlor misses to create a proper pool configuration file in /etc/php-fpm.d/ (while generating the VirtualHost config file properly), so it will always fail with error messages like this in /var/log/apache2/error.log, using your FQDN server name:

    [Wed Feb 20 19:57:13 2013] [error] [client] (2)No such file or directory: FastCGI: failed to connect to server "/var/www/": connect() failed
    [Wed Feb 20 19:57:13 2013] [error] [client] FastCGI: incomplete headers (0 bytes) received from server "/var/www/"

    Note that the file /var/www/ is indeed missing, but that is not the problem: the equivalent file is missing for working websites as well (the docs say "The filename does not have to exist in the local filesystem.").

  2. The first, simplest test is to choose a website and place a little script (called userinfo.php or something) in it with just this content: <?php system('id'); ?>. When calling it in your webbrowser, it should generate output that points to the user and group used in the SuexecUserGroup directive in that site's VirtualHost config. So note that php-fpm, as configured by Froxlor, does not use the script's owner as the user to execute it as, unlike mod_suphp.

  3. Then proceed to test a full website (keeping all other sites temporarily disabled by moving the configs out of /etc/apache2/sites-enabled/). Do not choose a phpMyAdmin or WordPress site for your first testing site however, as there can be special problems to be dealt with.

Fixing other issues

  • "There is no fastcgi wrapper set." When restarting Apache2, you might see messages like "[warn] FastCGI: there is no fastcgi wrapper set, user/group options are ignored". These can be ignored because Froxlor uses suexec to adapt the user and group of the server process, not the php-fpm internal mechanisms. See the system('id'); test above which proves this.
  • Adding directories to open_basedir. When using Froxlor with Apache and mod_php5, you could add site-specific values to open_basedir. When using PHP-FPM, this is no longer possible because site-specific values are now stored in /etc/php5/fpm/pool.d/*.conf files, which will be overwritten when Froxlor regenerates its config files. And there's seemingly no option to add to them from within Froxlor. One might edit the affected .conf files and set them to non-writable for the Froxlor user, but  that will create hard-to-track future problems. It's cleaner to add all directories required for one site to all of them, globally, via "Server -> Settings -> Web Server Settings -> Configuration", where you'll find an option to append paths to the open_basedir setting of all your virtual hosts.
  • Installing Roundcube from the Debian package. You will have to add some paths to the open_basedir default setting as described just above. This includes /etc/roundcube. However, it seems that Froxlor 0.9.27 silently discards any directory in /etc/ that you try to add to open_basedir via "Server -> Settings -> Web Server Settings -> Configuration". Seems to be an undocumented "security feature" 😀 To fix that bug, you could normally overwrite open_basedir per vhost, but PHP-FPM does not interpret that, which is why we have to modify the global open_basedir setting. The best solution I found was to do this (if we're lucky, Debian package management will not complain because we only exchange what is the symlink and what is the real thing):
    rm /var/lib/roundcube/config/*
    mv /etc/roundcube/* /var/lib/roundcube/config/

    ln -s /var/lib/roundcube/config/ roundcube
  • Restarting PHP-FPM. This can be required after doing manual changes to its config files in /etc/php-fpm.d/. The simplest way is: service php5-fpm restart.
  • Enabling the IP-and-port site. By default, Froxlor will not generate a /etc/php5/fpm/pool.d/*.conf file for the "IP and port" website, so it will not be served by php-fpm, resulting in "Server Error 500". This behavior is controlled by the option in Froxlor to use PHP-FPM "for Froxlor itself" (wuite a misnomer, but true: in the "IP and port" site configuration there is the same assumption that Froxlor is normlly provided via that site, where it says "User defined docroot (empty = point to froxlor)"). So the solution goes like this:
    1. Enable that option to use PHP-FPM for Froxlor itself.
    2. Note that the additional options on the same page, to change the user and group names to be used for the Froxlor chost with PHP-NPM, have no effect on the generated VirtualHost config (which seems to be a Froxlor bug). So better leave them as they are at "froxlorlocal".
    3. Let Froxlor recreate the config files:
      php /var/www/froxlor/scripts/froxlor_master_cronjob.php --force
    4. Ensure that there is now a config file in /etc/php5/fpm/pool.d/ named by the FQDN of your host.
    5. Restart Apache2: service apache2 restart
    6. Restart PHP-FPM: service php5-fpm restart
    7. Call up your IP address in your browser and see if it works.
  • Fixing WordPress sites that use URL rewriting. When re-enabling these sites, they will probably fail with this error message in the log: "Request exceeded the limit of 10 internal redirects due to probable configuration error.". The solution is to adapt the .htaccess file of WordPress with the rewrite rules to look like this [source]:
    # BEGIN WordPress
    <IfModule mod_rewrite.c>
    RewriteEngine On
      RewriteBase /
      RewriteCond %{REQUEST_URI} !^/fastcgiphp/*
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule . index.php [L]
    # END WordPress
  • Fixing Indefero sites that use URL rewriting. Indefero is a simple, Google Code like, open source code and project hosting software that utilizes git. When trying to serve it via PHP-FPM, it will say "Server Error 500", and in the log "Request exceeded the limit of 10 internal redirects due to probable configuration error.". In analogy to the solution for WordPress above, simply add a RewriteCond %{REQUEST_URI} !^/fastcgiphp/* to its .htaccess file to prevent the circular redirection. The .htaccess will then be:
    Options +FollowSymLinks
    <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteBase /
      RewriteCond %{REQUEST_URI} !^/fastcgiphp/*
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule ^(.*) /index.php/$1

Problem. When installing a PHP 5.4 package and a MySQL 5.5 package, both from Dotdeb for Debian 6.0 "Squeeze", this results in PHP interfacing with MySQL via a SQL client library version 5.1.66 (or another one from the MySQL 5.1 series). That in turn causes phpMyAdmin to complain about it after logging in there: "Your PHP MySQL library version 5.1.66 differs from your MySQL server version 5.5.29. This may cause unpredictable behavior." Is this a problem, and how to fix it?

Analysis and solutions. This is not a real problem, just a cosmetic one. The client library version is lower and will be compatible for calling a higher server version. Only the other way round it would break things. At least this is the idea why the author has packaged it with this dependency [source].

Specifically, package php5-mysql depends on libmysqlclient16 (>= 5.1.21-1), which depdens on mysql-common (>= 5.1.66-0+squeeze1). Which in total means that the library for PHP5, provided by Dotdeb, claims to be ok working with a MySQL 5.5 server.

This has been found out from the output of: dpkg -s php5-mysql, dpkg -s libmysqlclient16. For an overview of all your installed MySQL-related packages and their versions, use dpkg -l "*mysql*". Finally, to find out the MySQL client library version from within PHP, see here.

So it is only PHP software (phpMyAdmin) which complains about this. The only clean way to remove this warning would be to install the MySQL 5.1 server instead. But as every downgrade, it's not too easy (you have to backup your databases and may need to re-import them from SQL files [source]). And as said, it's seemingly just a cosmetic problem, all software so far runs fine.

The other option to fix this would be to use php5-mysqlnd instead of php5-mysql. However, that's seemingly not possible when using phpMyAdmin from Debian Squeeze packages (like we do), which depends on php5-mysql only and seemingly forgot to include an alternative dependency to php5-mysqlnd [source].

Not an easy question, also there's a lot of discussion about this on the web. I will just summarize what I found on the web, give my personal evaluation of it, and name some sources.

The selection criteria here are esp. security and ease of use, within boundaries of performance and memory usage (here, of a medium-sized VPS host for shared webhosting).

The different alternatives

php-fpm sounds like the best overall solution both for speed and memory usage (except on systems with very limited RAM). It is a FastCGI implementation with improvements over the older mod_fastcgi and mod_fcgi ones that lets it better adapt to servers with limited RAM (by using its "dynamic mode", for example). See the php-fpm website. For installation, there are installation instructions for Apache (more of these) on Debian, also explaining how the Froxlor server admin panel accesses php-fpm (as it generates the VirtualHost configs just like that). But there are also slightly more advanced installation instructions for Apache and lighthttpd.

php-fpm will not allow php_admin_value open_basedir directives in the per-site VirtualHost configs (Froxlor will not generate these directives in VirtualHost sections when having PHP-FPM enabled, and when using them manually there Apache will not start.). However, it allows open_basedir directives in its own per-site configuration files, with globally valid user additions. The instructions for using this feature are in teh article about PHP-FPM with Froxlor.

mod_suphp seems to be the best alternative for a shared webhost with very limited RAM (1 GiB) and many but rather low-traffic sites. Its disadvantage is having the slow speed of CGIs (because a separate process has to be started and for every PHP request), but that only becomes a problem when CPU resources for the overhead of process starting are no longer sufficient. On the plus side, it is memory efficient. See the installation instructionsIf it does not work out well (too slow / too high CPU load), you can try php-fpm or mod_fcgi instead, with memory limiting tweaks by reducing idle process runtime. 

However, the problem with mod_suphp is that it does not allow php_admin_value directives per VirtualHost section. This can be worked around by using per-host php.ini files instead [source], except when using a server admin panel that does not support them. Like Froxlor, independent of the webserver you use with it (this feature is only provided by a bleeding edge patch for Froxlor 0.9.28-svn5, which even generates these per-site php.ini files and the proper open_basedir settings [source]. Which is not a good idea to use, as the future development of Froxlor is unsure at best as of 2013-02, meaning one might get permanently stuck in using an untested development version of ones server panel (!)).

So the only option is to configure open_basedir globally in the corresponding php.ini config file. But then, all website paths (or their common root path) would be listed there, which nearly completely anihilates the benefit of open_basedir for shared hosting, namely, the protection against cross-infection with worms, between sites of different customers. Which means that currently, Froxlor prohibits a meaningful use of php-fpmmod_suphp and mod_fcgi, except you want to put in own development efforts of course. Because: using one of these handlers alone, without open_basedir, provides no proper protection as users will use mode 0666 for their files by mistake or lack of experience [source]. Then, open_basedir alone is an even better protection alone than one of the uid-changing handlers alone. Which means currently, with Froxlor 0.9.27, security wise we're prohibited from using mod_suphp. Use php-fpm instead, or switch to mod_ruid2 or mpm-itk after hardening the kernel with grsec.

An added problem specific to mod_suphp and Froxlor is that, as Froxlor does not support mod_suphp natively, it will still assume that mod_php5 is in use and allow users to enable their open_basedir sections (unlike when enabling php-fpm in Froxlor for example). Which will then cause Apache to fail on the next restart because of the generated php_admin_value directives out of proper ifmod sections … quite a nightmare scenario.

mod_fcgi and mod_fastcgi (implementing FastCGI) on the other hand also has the "execute with user ID of script owner" mechanism but needs a lot of RAM when having more than a few websites (50 MiB permanently for a single process, which can handle only one request in parallel for one website).

mod_php with mod_ruid2 is nice (security of mod_suphp plus speed of mod_php) but, in case that somebody finds certain apache2 vulnerabilities, is a security problem itself as it would allow people to suid to root with apache2 and scripts running inside of it (like with mod_php5). So it is only recommended when having a hardened kernel with grsecurity or similar [source, even recommended in the official project documentation], so nothing for simple and quick setups.

mpm-itk. This provides the same "execute as the file's user" security as the above alternatives (except mod_php alone of course). But it's not a module, instead part of the Apache binary. It also does not use the CGI model like mod_suphp, making it much faster than that. And also faster than FastCGI [benchmarks]. Indeed, it should be nearly as fast as mod_php alone. Also, it's very simple to configure with just three directives, and in contrast to mod_suphp it allows the php_admin_value directives. See some installation instructions. However, the big caveat is the same as with mod_ruid2: Apache2 runs as root until after header processing, when it can switch user IDs, so a potential exploit happening before might give root access to the system immediately [source, at "Quirks and Warnings"]. For that reason, only use it with a hardened kernel, just as with mod_ruid2 (see there).

mod_php alone (resp. mod_php5 now) provides insufficient isolation of customer sites against each other, as all files are readable (and upload directories even writable) by the webserver user, which means world-readable and world-writable because of the way Froxlor does its user account management.

More alternatives. There is a nice Apache wiki article on Privilege Separation with some nice ideas and background infos. However, it provided no additional practical solution in this context.

Results (esp. together with Froxlor)

For a secure but also simple to do and simple to maintain setup on a shared webhost with not too many medium traffic sites, I would use php-fpm. The same if there's just one or a few high-traffic sites. If there are instead a really lot of low traffic sites, I would use mod_suphp instead.

If the solution has to be deployed together with the server management panel Froxlor (version 0.9.27 currently), php-fpm is also a good solution (instructions). mod_suphp however is not (see the discussion about open_basedir problems in the mod_suphp section above).


In addition to the individual sources already linked to, the following documents (mostly forum discussions) were consulted when writing this article:


This description applies to Froxlor 0.9.27. The issue was reported by me as Froxlor issue #1159 ("Absolute document root path interpreted as relative to customer folder"), but since their issue reporting system is down as of 2013-02-18 I publish it here with teh workaround, as good as I can remember.

How to reproduce this problem:

  1. Create domain with absolute docroot. As Froxlor admin, create a new domain entry in Froxlor as a "main domain". Adjust the document root setting of that new domain by using an absolute path rather than one relative to the customer directory. For example, I had to use /usr/share/phpmyadmin/ for an installation of phpMyAdmin.
  2. Re-create configs. For that, do one of these:
    1. Execute this via SSH on the server:
      php /var/www/froxlor/scripts/froxlor_master_cronjob.php --force
    2. Wait until the next Froxlor cron job runs, which will also rewrite all vhost configs that need changes. (Clicking "Server -> Re-create configs" in Froxlor won't speed that up, it just queues additional config files for re-creation.)
  3. Restart Apache. Because the config changes will not be picked up in all cases automatically. So:
    service restart apache2
  4. Test. The domain should have been created correctly, using your provided document root directory. Froxlor should not have created directories below the customer's directory.
  5. Edit as customer. Edit the settings of the domain as a the customer who owns this domain. (To switch to the customer's account as Froxlor admin, go to "Ressources -> Domains" and click on the appropriate link in the "Customer" column. A new window with a concurrent login opens. Here, navigate to "Domains -> Settings" and click the "Edit" icon for your domain.) Just change something unimportant and save the settings. Do not change the document root path!
  6. Re-create configs, restart Apache. See steps 2 and 3.

As a result of this process, the domain you edited will no longer work, just showing the standard Froxlor "under construction" page. Froxlor has interpreted the absolute document root directory as relative to the customer's directory, and has created a corresponding directory hierarchy there incl. the "under construction" page. This happens only when editing a domain condiguration as customer, not when doing so as root. It has only a negative effect for domains that require an absolute document root path, as the relative interpretation works just fine for the standard directory names generated by Froxlor.


Edit your domain settings as Froxlor admin and remove the customer directory path from the front of your document root path. Then re-create the configs and restart Apache as shown above. Finally remove the nonsense directories created by Froxlor because of this bug.

This fix only works for Froxlor main domains, as subdomains cannot be edited by Froxlor admins.

Workaround for prevention

Simply do not edit domains that require absolute document root paths with a Froxlor customer account. Use a Froxlor admin account. Of course this implies that with the current Froxlor 0.9.27 you cannot let your customers have domaisn with absolute document root paths, instead only with paths inside the customer directories.

For so-called "Froxlor main domains" (which can also be subdomains!), editing as admin is possible without restrictions. (The only setting not visible when editing them as admin is "Redirect code", and that one makes no sense together with an absolute document root path as it requires the document root field to contain a URL.)

For Froxlor subdomains however, editing as admin is not possible at all. They do not appear in "Ressources -> Domains" when logged in as Froxlor admin. Which means, subdoamains that require absolute document root paths must be created as Froxlor main domains to edit them as admin. If not, you're forced to change the Apache config files manually, and your changes will be lost whenever Froxlor re-generates these config files.

In this post, I want to show a solution that can help to quickly install your set of desired open source Android apps from FDroid, by installing them with adb. It also works with Google Play, but you have to download them as .apk files first. This is not possible on Google Play directly, but for example with third-party services like Be aware of potential security implications though.

So it would be possible to have a single script running on your computer and bulk-installing all your Android apps on your phone. However, once you installed your desired apps once in any way, it is faster and more comfortable to use App2zip, App2zip Pro or ZIPme to create a .zip file with your apps that you can then install in recovery mode on any phone you want them on.

The process for unattended install of Android apps via adb works as follows:

  1. Enable USB debugging on the Android phone. This is needed for adb to work. [instructions]
  2. Install Google Play. We install a minimized version of Google Apps here that contains just Google Play and required libraries. You can install everything else from Google Apps via the Google Play Store later. [TODO: Minimize this further by installing just the three essential apps, saving 70 more MiB].
    1. Download the minimized Google Apps package from  "[APP][MINIMALISM] Google Play 3.10.10 | Market ONLY Gapps for GB/ICS/JB4.1/JB4.2".
    2. Push it to the phone's SD card:
      adb push /sdcard/
    3. Reboot into your favorite recovery:
      adb reboot recovery
    4. Install the ZIP file from the SD card with your recovery software.
  3. Install APKs. For every APK, simply call [see adb command line arguments]:
    adb install filename.apk
    Due to permissions issues, on some Ubuntu host systems you will have to do:
    sudo adb install filename.apk