diff --git a/setup.py b/setup.py
index 19deaea4e05c54b4d2534277f4e8d37022c6861a..816e56ba3b7f59653be2afc386e1625fdddac653 100755
--- a/setup.py
+++ b/setup.py
@@ -110,6 +110,7 @@ setup(name=name,
           'novnc = slapos.recipe.novnc:Recipe',
           'onetimeupload = slapos.recipe.onetimeupload:Recipe',
           'pbs = slapos.recipe.pbs:Recipe',
+          'postgres = slapos.recipe.postgres:Recipe',
           'proactive = slapos.recipe.proactive:Recipe',
           'publish = slapos.recipe.publish:Recipe',
           'publishurl = slapos.recipe.publishurl:Recipe',
diff --git a/slapos/recipe/postgres/__init__.py b/slapos/recipe/postgres/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..004981600915e7763fcee4c6c9de7ede26f0a7a5
--- /dev/null
+++ b/slapos/recipe/postgres/__init__.py
@@ -0,0 +1,136 @@
+##############################################################################
+#
+# Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsibility of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# guarantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 3
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+import os
+import sys
+import subprocess
+import textwrap
+from zc.buildout import UserError
+
+from slapos.recipe.librecipe import GenericBaseRecipe
+from slapos.recipe.librecipe import filehash
+
+class Recipe(GenericBaseRecipe):
+
+    def _options(self, options):
+        options['password'] = self.generatePassword()
+        options['url'] = 'postgresql://%(user)s:%(password)s/%(host)s:%(port)s/%(dbname)s' % dict(options, host=options['ipv6_host'].pop())
+
+
+    def install(self):
+        self.createCluster()
+        self.createConfig()
+        self.createDatabase()
+        self.createRunScript()
+
+        pgdata = self.options['pgdata-directory']
+
+        return [
+                os.path.join(pgdata, 'postgresql.conf')
+                ]
+
+
+    def createCluster(self):
+        initdb_binary = os.path.join(self.options['bin'], 'initdb')
+
+
+        pgdata = self.options['pgdata-directory']
+
+        if not os.path.exists(pgdata):
+            try:
+                subprocess.check_call([initdb_binary,
+                                       '-D', pgdata,
+                                       '-A', 'ident',
+                                       '-E', 'UTF8',
+                                       ])
+            except subprocess.CalledProcessError:
+                raise UserError('Could not create cluster directory in %s' % pgdata)
+
+
+    def createConfig(self):
+        pgdata = self.options['pgdata-directory']
+
+        with open(os.path.join(pgdata, 'postgresql.conf'), 'wb') as cfg:
+            cfg.write(textwrap.dedent("""\
+                    logging_collector = on
+                    log_rotation_size = 50MB
+                    max_connections = 100
+                    datestyle = 'iso, mdy'
+
+                    lc_messages = 'en_US.UTF-8'
+                    lc_monetary = 'en_US.UTF-8'
+                    lc_numeric = 'en_US.UTF-8'
+                    lc_time = 'en_US.UTF-8'
+                    default_text_search_config = 'pg_catalog.english'
+                    """))
+
+
+        with open(os.path.join(pgdata, 'pg_hba.conf'), 'wb') as cfg:
+            # see http://www.postgresql.org/docs/9.1/static/auth-pg-hba-conf.html
+
+            cfg.write(textwrap.dedent("""\
+                    # TYPE  DATABASE        USER            ADDRESS                 METHOD
+
+                    # "local" is for Unix domain socket connections only
+                    local   all             all                                     ident
+                    # IPv4 local connections:
+                    host    all             all             127.0.0.1/32            md5
+                    # IPv6 local connections:
+                    host    all             all             ::1/128                 md5
+                    # Allow replication connections from localhost, by a user with the
+                    # replication privilege.
+                    #local   replication     slapuser4                                ident
+                    #host    replication     slapuser4        127.0.0.1/32            md5
+                    #host    replication     slapuser4        ::1/128                 md5
+                    """))
+
+
+    def createDatabase(self):
+        pgdata = self.options['pgdata-directory']
+        postgres_binary = os.path.join(self.options['bin'], 'postgres')
+
+        try:
+            p = subprocess.Popen([postgres_binary,
+                                  '--single',
+                                  '-D', pgdata,
+                                  'postgres',
+                                  ], stdin=subprocess.PIPE)
+            p.communicate('CREATE DATABASE %s\n' % self.options['dbname'])
+        except subprocess.CalledProcessError:
+            raise UserError('Could not create database %s' % pgdata)
+
+
+    def createRunScript(self):
+        content = textwrap.dedent("""\
+                #!/bin/sh
+                %(bin)s/postgres \\
+                    -D %(pgdata-directory)s
+                """ % self.options)
+        name = os.path.join(self.options['services'], 'postgres-start')
+        self.createExecutable(name, content=content)
+
+
diff --git a/software/postgres/instance.cfg.in b/software/postgres/instance.cfg.in
new file mode 100644
index 0000000000000000000000000000000000000000..d389f446c5f036bd161e40754608e1d8a283f0cd
--- /dev/null
+++ b/software/postgres/instance.cfg.in
@@ -0,0 +1,68 @@
+[buildout]
+parts =
+  symlinks
+  publish
+  postgres-instance
+
+
+# Define egg directories to be the one from Software Release
+# (/opt/slapgrid/...)
+eggs-directory = ${buildout:eggs-directory}
+develop-eggs-directory = ${buildout:develop-eggs-directory}
+offline = true
+
+
+[instance-parameters]
+# Fetches parameters defined in SlapOS Master for this instance
+recipe = slapos.cookbook:slapconfiguration
+computer = $${slap-connection:computer-id}
+partition = $${slap-connection:partition-id}
+url = $${slap-connection:server-url}
+key = $${slap-connection:key-file}
+cert = $${slap-connection:cert-file}
+
+
+[directories]
+recipe = slapos.cookbook:mkdirectory
+bin = $${buildout:directory}/bin
+etc = $${buildout:directory}/etc
+services = $${directories:etc}/run/
+promises = $${directories:etc}/promise/
+var = $${buildout:directory}/var
+
+
+[symlinks]
+recipe = cns.recipe.symlink
+symlink_target = $${directories:bin}
+symlink_base = ${postgresql:location}/bin
+
+
+[postgres-instance]
+# create cluster, configuration files and a database
+recipe = slapos.cookbook:postgres
+
+# Options
+ipv6_host = $${instance-parameters:ipv6}
+user = user
+port = 5432
+dbname = db
+# pgdata_directory is created by initdb, and should not exist beforehand.
+pgdata-directory = $${directories:var}/data
+services = $${directories:services}
+bin = $${directories:bin}
+
+
+[publish]
+recipe = slapos.cookbook:publishurl
+url = $${postgres-instance:url}
+
+
+[slap-connection]
+# part to migrate to new - separated words
+computer-id = $${slap_connection:computer_id}
+partition-id = $${slap_connection:partition_id}
+server-url = $${slap_connection:server_url}
+software-release-url = $${slap_connection:software_release_url}
+key-file = $${slap_connection:key_file}
+cert-file = $${slap_connection:cert_file}
+
diff --git a/software/postgres/software.cfg b/software/postgres/software.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..46d21841829f08b1472a6ca8dcd370f71a9ee02a
--- /dev/null
+++ b/software/postgres/software.cfg
@@ -0,0 +1,25 @@
+[buildout]
+
+extends = 
+  ../../stack/slapos.cfg
+  ../../component/postgresql/buildout.cfg
+
+parts =
+  eggs
+  slapos-cookbook
+  instance-template
+  postgresql
+
+[instance-template]
+recipe = slapos.recipe.template
+url = ${:_profile_base_location_}/instance.cfg.in
+output = ${buildout:directory}/template.cfg
+#md5sum = 
+mode = 0644
+
+
+[eggs]
+recipe = zc.recipe.egg
+eggs =
+    cns.recipe.symlink
+