Question

I'm deploying a Rails app that uses PostgreSQL and HSTORE.

To deploy it, I'm ussing rubber.

Everything works, except for HSTORE not being properly enabled. When the migration that contains execute("CREATE EXTENSION hstore") runs, I get the following errors:

** [out :: production.---] 
** [out :: production.---] -- execute("CREATE EXTENSION hstore")
** [out :: production.---] 
** [out :: production.---] rake aborted!
** [out :: production.---] An error has occurred, this and all later migrations canceled:
** [out :: production.---] 
** [out :: production.---] PG::Error: ERROR:  permission denied to create extension "hstore"
** [out :: production.---] HINT:  Must be superuser to create this extension.

The script that creates the postgres instance has this code:

create_user_cmd = "CREATE USER #{env.db_user} WITH NOSUPERUSER CREATEDB NOCREATEROLE"

so I think the problem might be related to the NOSUPERUSER attribute being set here.

Is there any way to enable hstore using rubber while keeping most of the generated files unchanged?

Was it helpful?

Solution

The problem is that rubber creates the DB user as NOSUPERUSER. My workaround is to create tasks that run before and after capistrano's deploy:migrate that will change the user to SUPERUSER and back.

Here's the code:

namespace :rubber do

  namespace :project do

    before "deploy:migrate", "rubber:project:add_pg_superuser_and_enable_hstore"
    after "deploy:migrate", "rubber:project:remove_pg_superuser"

    task :add_pg_superuser_and_enable_hstore,
         :roles => [:postgresql_master, :postgresql_slave] do
      alter_user_cmd = "ALTER USER #{rubber_env.db_user} SUPERUSER"
      create_hstore_cmd = "CREATE EXTENSION IF NOT EXISTS hstore;"
      rubber.sudo_script "add_superuser_create_hstore", <<-ENDSCRIPT
        sudo -i -u postgres psql -c "#{alter_user_cmd}"
        sudo -i -u postgres psql -c "#{create_hstore_cmd}"
      ENDSCRIPT
    end

    task :remove_pg_superuser, :roles => [:postgresql_master,
                                          :postgresql_slave] do
      alter_user_cmd = "ALTER USER #{rubber_env.db_user} NOSUPERUSER"
      rubber.sudo_script "add_superuser_create_hstore", <<-ENDSCRIPT
        sudo -i -u postgres psql -c "#{alter_user_cmd}"
      ENDSCRIPT
    end

  end

end

OTHER TIPS

Another option is to not have a postgres superuser involved when deploying but create a template (or use the default one) and install the extension on the template. Then when you create a database it will have the extension installed.

Good answers here and here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top