We hope you find this tutorial helpful. In addition to guides like this one, we provide simple cloud infrastructure for developers. Learn more →

How To Install a Custom Composer Repository on Ubuntu

Posted Apr 21, 2014 21.6k views Ubuntu

In this tutorial, we will install a custom Composer repository. This means you can host your own private packages and use them in your composer.json file.

Composer is a PHP dependency management tool which lets you specify which libraries your project needs and it will install them automatically for you. For more information about Composer and general usage, please see this article.

There are two types of custom repositories: Satis and Packagist. Satis is a static one, which means it generates the JSON and HTML files and it's a static web page. Packagist is the code of packagist.org and is therefore a very advanced tool that also includes statistics and searching. In this tutorial, you will be showed you how to install both.

Here we assume you know what Composer is and how to use it. Either Satis or Packagist should be installed (not both).



As was already said, Satis is a static repository. The README of the GitHub repository states the following:

It uses any composer.json file as input and dumps all the required (according to their version constraints) packages to a Composer Repository file.

The installation of Satis is very easy:

cd /var/www/
curl -sS https://getcomposer.org/installer | php
php composer.phar create-project composer/satis --stability=dev --keep-vcs

Now all that needs to be done is adding repositories and generating the static web page. To do this, create a file satis.json in /var/www with the following contents (use nano /var/www/satis.json to edit the file):

    "name": "My Repository",
    "homepage": "http://YOUR_IP",
    "repositories": [
        { "type": "vcs", "url": "https://github.com/symfony/yaml" },
        { "type": "vcs", "url": "https://github.com/symfony/HttpFoundation"
    "require-all": true

In this file, we set a name for the repository, set the homepage (which must be set to the web root from where Satis is hosted), and some repositories are specified. For this example, I have used 2 Symfony2 components. Now we can generate the static web pages:

php satis/bin/satis build satis.json .

Using these examples, it will take quite a while because these repositories have many versions. You may need to authenticate against GitHub, as Composer uses the GitHub API which has limits on its usage by default. This case is also described in the Troubleshooting section on the Composer website:

Because of GitHub's rate limits on their API it can happen that Composer prompts for authentication asking your username and password so it can go ahead with its work.

If you would prefer not to provide your GitHub credentials to Composer you can manually create a token using the following procedure:

  1. Create an OAuth token on GitHub. Read more on this.
  2. Add it to the configuration running composer config -g github-oauth.github.com <oauthtoken> Now Composer should install/update without asking for authentication.

When Composer has finished, you can visit http://YOUR_IP. This will show all packages and versions that have been added.

Whenever one of the repositories is updated, the command we use to generate web pages should be run. You can also use a cron job for this, but that is already covered in this tutorial.


Now, we will start the installation of Packagist. Packagist is a Symfony2 application which means it has quite a few dependencies. This article assumes you are using a fresh install, so Satis should NOT be installed. As stated before, only one of the two should be installed.

First, all of the requirements should be installed.

One of the requirements is Redis, a database storage server. Execute the following commands to install Redis:

sudo apt-get update
sudo apt-get -y install build-essential tcl8.5
cd /opt
wget http://download.redis.io/releases/redis-2.8.7.tar.gz
tar xzf redis-2.8.7.tar.gz
mv redis-2.8.7 redis
cd redis

This downloaded Redis. We should now compile and install it:

sudo make install
cd utils

The following command sets up the server:

sudo ./install_server.sh

You can press enter for every question you get, which means the default will be used, which is fine for this installation. Last, make it start up automatically:

sudo update-rc.d redis_6379 defaults

Test if it works by executing:

redis-cli ping

If it responds by PONG, your installation works fine.

Another requirement is Solr: a search engine. To install this software, first install Java:

sudo apt-get -y install openjdk-7-jdk
mkdir /usr/java

If you are on a 64-bit Droplet (most people will be), you should execute the following command:

ln -s /usr/lib/jvm/java-7-openjdk-amd64 /usr/java/default

If you are on a 32-bit system, you should execute the following command:

ln -s /usr/lib/jvm/java-7-openjdk-i386 /usr/java/default

Then, download Solr:

cd /opt
wget http://archive.apache.org/dist/lucene/solr/3.6.2/apache-solr-3.6.2.tgz
tar -xvf apache-solr-3.6.2.tgz
cp -R apache-solr-3.6.2/example /opt/solr
cd /opt/solr
sudo wget -O /etc/default/jetty
sudo wget -O /opt/solr/etc/jetty-logging.xml

Next, we can setup the Solr user and automatic starting:

sudo useradd -d /opt/solr -s /sbin/false solr
sudo chown solr:solr -R /opt/solr
sudo wget -O /etc/init.d/jetty http://svn.codehaus.org/jetty/jetty/branches/jetty-6.1/bin/jetty.sh
sudo chmod a+x /etc/init.d/jetty
sudo update-rc.d jetty defaults

The last step is to restart Solr:

sudo /etc/init.d/jetty restart

To test if Solr works, visit http://YOUR_IP:8983/solr in your browser. If this gives an administration interface, your installation has succeeded.

We should also configure Apache and PHP correctly:

sudo a2enmod rewrite
sudo apt-get -y install php5-intl php5-curl acl git

You can now start the real installation of Packagist. To start, execute the following commands:

cd /var/www/
rm index.html info.php
git clone https://github.com/composer/packagist .
curl -sS https://getcomposer.org/installer | php

First, create a database by opening up the mysql command line:


You may be prompted to authenticate if you have set a password for the root user, which is recommended. Create a user called packagist and assign a password (change the password your_password to something more secure):

CREATE USER 'packagist'@'localhost' IDENTIFIED BY 'your_password';
GRANT USAGE ON * . * TO  'packagist'@'localhost' IDENTIFIED BY
GRANT ALL PRIVILEGES ON  `packagist` . * TO  'packagist'@'localhost';

This will also create a database called packagist.

Now copy the file parameters.yml.dist to parameters.yml:

cp app/config/parameters.yml.dist app/config/parameters.yml

We should now edit the file to suit our needs:

nano app/config/parameters.yml

The file should be changed to suit the server's needs.

The first options are the database* parameters. They are self-describing; they can be filled in easily. If you followed the above steps for creating a database, you can leave `databasedrivertopdomysql, just likedatabasehostwhich can be left at the defaultlocalhost. Thedatabasenameanddatabaseusershould be set topackagistand thedatabase_password` should be set to the password you set before.

The next section is about mailing. You probably want to use SMTP or sendmail as mailer_transport, but that depends on your mailing server. When you use SMTP, all other details about SMTP should be filled in as well.

The packagist_host parameter is required, so either set it to the domain name connected with your Droplet or use your Droplet's IP. After packagist_host has been filled in, uncomment the following two parameters. If you are not using HTTPS, router.request_context.scheme should be set to http.

If the above steps were followed correctly, the redis_dsn parameter shouldn't need to be changed. The locale can also be left to default and the ga_key is not required. The github.client_id and github.client_secret are, however, recommended to fill in. For this, first register a new application on GitHub. The callback URL can be left empty. After the application has been registered, copy the Client ID to github.client_id. The same should be done for the Client Secret.

The next thing that needs to be filled in is the secret and remember_me.secret. Those can be filled in randomly or it can be a random string generated at thebitmill.com. Punctuation should be unchecked in the generator as it can cause issues with YAML.

The rest of the parameters can be left at their default value. Now execute the following commands:

php composer.phar install
app/console doctrine:schema:create
app/console cache:clear --env=prod
app/console assets:install web
mkdir home
sudo chown www-data:www-data -R /var/www/home
APACHEUSER=`ps aux | grep -E '[a]pache|[h]ttpd' | grep -v root | head -1 |
cut -d\  -f1`
sudo setfacl -R -m u:$APACHEUSER:rwX -m u:`whoami`:rwX app/cache app/logs
sudo setfacl -dR -m u:$APACHEUSER:rwX -m u:`whoami`:rwX app/cache app/logs

The only thing left is setting up a correct VirtualHost. Edit /etc/apache2/sites-available/default:

nano /etc/apache2/sites-available/default

Change DocumentRoot /var/www to DocumentRoot /var/www/web. Add a line under DocumentRoot with the contents SetEnv HOME /var/www/home. Then change <Directory /var/www> to <Directory /var/www/web>. Next, place a minus sign before Indexes so that the line becomes like this:

Options -Indexes FollowSymLinks MultiViews

Then change the line after that from AllowOverride None to AllowOverride All. Finally, restart Apache:

sudo service apache2 restart

Now, we need to setup Solr correctly. Edit /opt/solr/solr/solr.xml:

nano /opt/solr/solr/solr.xml

In this file, find collection1 and replace it by packagist, so that the file looks like this:

<?xml version="1.0" encoding="UTF-8" ?>

 All (relative) paths are relative to the installation path

  persistent: Save changes made via the API to this file
  sharedLib: path to a lib directory that will be shared across all cores
<solr persistent="false">

  adminPath: RequestHandler path to manage cores.
    If 'null' (or absent), cores will not be manageable via request handler
  <cores adminPath="/admin/cores" defaultCoreName="packagist">
    <core name="packagist" instanceDir="." />

Now, Packagist's schema.xml should be used in Solr. Execute the following commands:

rm /opt/solr/solr/conf/schema.xml
cp /var/www/doc/schema.xml /opt/solr/solr/conf/schema.xml
sudo /etc/init.d/jetty restart

Your installation can now be accessed at http://YOUR_IP/. It should work just like Packagist does. When your installation needs to support more version control systems (VCS), also install those:

sudo apt-get -y install subversion
sudo apt-get -y install mercurial

Also set up a cron job for the following commands (recommended interval is 1 minute, see this tutorial for setting up cron jobs):

/var/www/app/console packagist:update --no-debug --env=prod
/var/www/app/console packagist:dump --no-debug --env=prod
/var/www/app/console packagist:index --no-debug --env=prod

Whenever a new package is added, it won't be automatically indexed by Solr; for that the above commands should really be set up as a cron job or be executed manually every time something changes. The first option is probably the easiest.

Some things don't work immediately like the statistics page. Packagist should be up for approximately 2 days before so it doesn't give a 500 Error anymore.

Using your repository

Your own Composer can now be used. To do this, add the following repositories section to composer.json:

    "repositories": [
     "type": "composer",
     "url": "http://YOUR_IP/"
    // these are just examples of requirements, you don't actually need
them (delete this comment as comments are officially not supported in JSON)
    "require": {
        "symfony/yaml": "dev-master",
        "symfony/http-foundation": "dev-master"
Submitted by: Koen Vlaswinkel


Creative Commons License