diff --git a/files/after_install b/files/after_install new file mode 100644 index 00000000..f14f21a2 --- /dev/null +++ b/files/after_install @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# rvm after_install hook to provide selinux support +# This script will make sure the correct selinux contexts are set on ruby +# files after each ruby version install. + +# WARNING - As of 2012-02-08, there is a bug in current versions +# of rvm (now 1.10.2) such that it cannot find this after_install hook +# See rvm issues #744 and #745 on github for more information + +if [ $EUID -ne 0 ]; then + # Don't try to mess with selinux if we are not root + exit +fi + +if [ ! \( -x /usr/sbin/semanage -a -x /sbin/restorecon \) ]; then + echo "SELinux executables missing, rvm after_install hook failed" + exit 1 +fi + +# Set up rvm file context patterns if they are not already present +# This will handle installs in either /usr/local/rvm or /usr/lib/rvm +semanage fcontext -l | /bin/grep -q rvm || { + semanage fcontext -a -t bin_t '/usr/(local|lib)/rvm/wrappers(/.*)?' + semanage fcontext -a -t bin_t '/usr/(local|lib)/rvm/rubies/ruby-.*/bin(/.*)?' + semanage fcontext -a -t lib_t '/usr/(local|lib)/rvm/rubies/ruby-.*/lib(/.*)?' + semanage fcontext -a -t lib_t '/usr/(local|lib)/rvm/gems(/.*)?' + semanage fcontext -a -t passenger_exec_t '/usr/(local|lib)/rvm/gems/ruby-.*/gems/passenger-.*/agents/(apache2/)?Passenger.*' +} + +# Run restorecon on the rvm hierarchy to fix the contexts +restorecon -R $rvm_path diff --git a/lib/facter/rvm_installed.rb b/lib/facter/rvm_installed.rb index 411afd5e..d13c5508 100644 --- a/lib/facter/rvm_installed.rb +++ b/lib/facter/rvm_installed.rb @@ -1,7 +1,23 @@ -Facter.add("rvm_installed") do - rvm_binary = "/usr/local/rvm/bin/rvm" +Facter.add(:rvm_installed) do + setcode do + result = 'false' + if File.exist?('/usr/local/rvm/bin/rvm') or File.exist?('/usr/bin/rvm') + result = 'true' + end + result + end +end +Facter.add(:rvm_binary) do + confine :rvm_installed => :true setcode do - File.exists? rvm_binary + result = '' + [ '/usr/local/rvm/bin/rvm', '/usr/bin/rvm' ].each do |binfile| + if File.exist?(binfile) + result = binfile + break + end + end + result end end diff --git a/lib/puppet/provider/rvm_gem/gem.rb b/lib/puppet/provider/rvm_gem/gem.rb index b8841388..4de712a3 100644 --- a/lib/puppet/provider/rvm_gem/gem.rb +++ b/lib/puppet/provider/rvm_gem/gem.rb @@ -5,7 +5,7 @@ Puppet::Type.type(:rvm_gem).provide(:gem) do desc "Ruby Gem support using RVM." - commands :rvmcmd => "/usr/local/rvm/bin/rvm" + commands :rvmcmd => Facter.value(:rvm_binary) def ruby_version diff --git a/lib/puppet/provider/rvm_gemset/gemset.rb b/lib/puppet/provider/rvm_gemset/gemset.rb index 63725e8c..f50000d6 100644 --- a/lib/puppet/provider/rvm_gemset/gemset.rb +++ b/lib/puppet/provider/rvm_gemset/gemset.rb @@ -2,7 +2,7 @@ Puppet::Type.type(:rvm_gemset).provide(:gemset) do desc "RVM gemset support." - commands :rvmcmd => "/usr/local/rvm/bin/rvm" + commands :rvmcmd => Facter.value(:rvm_binary) def ruby_version resource[:ruby_version] diff --git a/lib/puppet/provider/rvm_system_ruby/rvm_system_ruby.rb b/lib/puppet/provider/rvm_system_ruby/rvm_system_ruby.rb index 9f5b433f..bfc2284d 100644 --- a/lib/puppet/provider/rvm_system_ruby/rvm_system_ruby.rb +++ b/lib/puppet/provider/rvm_system_ruby/rvm_system_ruby.rb @@ -1,7 +1,7 @@ Puppet::Type.type(:rvm_system_ruby).provide(:rvm) do desc "Ruby RVM support." - commands :rvmcmd => "/usr/local/rvm/bin/rvm" + commands :rvmcmd => Facter.value(:rvm_binary) def create rvmcmd "install", resource[:name] diff --git a/manifests/dependencies.pp b/manifests/dependencies.pp index b85e88c2..f17424ca 100644 --- a/manifests/dependencies.pp +++ b/manifests/dependencies.pp @@ -1,4 +1,13 @@ class rvm::dependencies { + # Precreate the rvm group, otherwise the git installer fails to create it + # as a system group + if ! defined(Group['rvm']) { + group { 'rvm': + ensure => present, + system => true, + } + } + case $operatingsystem { Ubuntu,Debian: { require rvm::dependencies::ubuntu } CentOS,RedHat: { require rvm::dependencies::centos } diff --git a/manifests/dependencies/centos.pp b/manifests/dependencies/centos.pp index 73688b0c..de478634 100644 --- a/manifests/dependencies/centos.pp +++ b/manifests/dependencies/centos.pp @@ -6,7 +6,7 @@ if ! defined(Package['make']) { package { 'make': ensure => installed } } if ! defined(Package['gettext-devel']) { package { 'gettext-devel': ensure => installed } } if ! defined(Package['expat-devel']) { package { 'expat-devel': ensure => installed } } - if ! defined(Package['curl-devel']) { package { 'curl-devel': ensure => installed } } + if ! defined(Package['libcurl-devel']) { package { 'libcurl-devel': ensure => installed } } if ! defined(Package['zlib-devel']) { package { 'zlib-devel': ensure => installed } } if ! defined(Package['openssl-devel']) { package { 'openssl-devel': ensure => installed } } if ! defined(Package['perl']) { package { 'perl': ensure => installed } } @@ -15,7 +15,6 @@ if ! defined(Package['gettext-devel']) { package { 'gettext-devel': ensure => installed } } if ! defined(Package['wget']) { package { 'wget': ensure => installed } } if ! defined(Package['bzip2']) { package { 'bzip2': ensure => installed } } - if ! defined(Package['sendmail']) { package { 'sendmail': ensure => installed } } if ! defined(Package['mailx']) { package { 'mailx': ensure => installed } } if ! defined(Package['libxml2']) { package { 'libxml2': ensure => installed } } if ! defined(Package['libxml2-devel']) { package { 'libxml2-devel': ensure => installed } } @@ -24,4 +23,12 @@ if ! defined(Package['readline-devel']) { package { 'readline-devel': ensure => installed } } if ! defined(Package['patch']) { package { 'patch': ensure => installed } } if ! defined(Package['git']) { package { 'git': ensure => installed } } + if ! defined(Package['libyaml-devel']) { package { 'libyaml-devel': ensure => installed } } + + if $selinux == 'true' { + # Make sure we have semanage and restorecon commands + if ! defined(Package['policycoreutils-python']) { + package { 'policycoreutils-python': ensure => present } + } + } } diff --git a/manifests/init.pp b/manifests/init.pp index 64848e08..4103476e 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,10 +1,18 @@ -class rvm($version='latest', $install_rvm=true) { +class rvm( + $version = 'latest', + $install_rvm = true, + $use_pkg = false, + $rstage = 'rvm-install' +) { stage { 'rvm-install': before => Stage['main'] } if $install_rvm { class { - 'rvm::dependencies': stage => 'rvm-install'; - 'rvm::system': stage => 'rvm-install', version => $version; + 'rvm::dependencies': stage => $rstage; + 'rvm::system': + stage => $rstage, + version => $version, + use_pkg => $use_pkg; } } } diff --git a/manifests/passenger/apache.pp b/manifests/passenger/apache.pp index 9e4a084f..2e1eb93e 100644 --- a/manifests/passenger/apache.pp +++ b/manifests/passenger/apache.pp @@ -1,7 +1,6 @@ class rvm::passenger::apache( $ruby_version, $version, - $rvm_prefix = '/usr/local/', $mininstances = '1', $maxpoolsize = '6', $poolidletime = '300', @@ -23,36 +22,31 @@ # TODO: How can we get the gempath automatically using the ruby version # Can we read the output of a command into a variable? # e.g. $gempath = `usr/local/rvm/bin/rvm ${ruby_version} exec rvm gemdir` - $gempath = "${rvm_prefix}rvm/gems/${ruby_version}/gems" - $binpath = "${rvm_prefix}rvm/bin/" + $gempath = "${rvm::system::rvmpath}/gems/${ruby_version}/gems" case $operatingsystem { Ubuntu: { class { 'rvm::passenger::apache::ubuntu::post': ruby_version => $ruby_version, version => $version, - rvm_prefix => $rvm_prefix, mininstances => $mininstances, maxpoolsize => $maxpoolsize, poolidletime => $poolidletime, maxinstancesperapp => $maxinstancesperapp, spawnmethod => $spawnmethod, gempath => $gempath, - binpath => $binpath; } } CentOS,RedHat: { class { 'rvm::passenger::apache::centos::post': ruby_version => $ruby_version, version => $version, - rvm_prefix => $rvm_prefix, mininstances => $mininstances, maxpoolsize => $maxpoolsize, poolidletime => $poolidletime, maxinstancesperapp => $maxinstancesperapp, spawnmethod => $spawnmethod, gempath => $gempath, - binpath => $binpath; } } } diff --git a/manifests/passenger/apache/centos/post.pp b/manifests/passenger/apache/centos/post.pp index 40d93f0a..995a80ce 100644 --- a/manifests/passenger/apache/centos/post.pp +++ b/manifests/passenger/apache/centos/post.pp @@ -1,27 +1,37 @@ class rvm::passenger::apache::centos::post( $ruby_version, $version, - $rvm_prefix = '/usr/local/', $mininstances = '1', $maxpoolsize = '6', $poolidletime = '300', $maxinstancesperapp = '0', $spawnmethod = 'smart-lv2', - $gempath, - $binpath + $rvmpath = $rvm::system::rvmpath, + $gempath ) { - exec { - 'passenger-install-apache2-module': - command => "${rvm::passenger::apache::binpath}rvm ${rvm::passenger::apache::ruby_version} exec passenger-install-apache2-module -a", - creates => "${rvm::passenger::apache::gempath}/passenger-${rvm::passenger::apache::version}/ext/apache2/mod_passenger.so", - logoutput => 'on_failure', - require => [Rvm_gem['passenger'], Package['httpd','httpd-devel','mod_ssl']]; + + exec { 'passenger-install-apache2-module': + command => "$rvm_binary $ruby_version exec passenger-install-apache2-module -a", + creates => "${gempath}/passenger-${version}/ext/apache2/mod_passenger.so", + logoutput => 'on_failure', + require => [Rvm_gem['passenger'], Package['httpd','httpd-devel','mod_ssl']]; + } + + if $selinux == 'true' { + exec { 'passenger-contexts': + command => "/sbin/restorecon -R $rvmpath", + refreshonly => true, + subscribe => Exec['passenger-install-apache2-module'], + before => File['/etc/httpd/conf.d/passenger.conf'], + } + } + + file { '/etc/httpd/conf.d/passenger.conf': + content => template('rvm/passenger-apache-centos.conf.erb'), + require => Exec['passenger-install-apache2-module']; } - file { - '/etc/httpd/conf.d/passenger.conf': - ensure => file, - content => template('rvm/passenger-apache-centos.conf.erb'), - require => Exec['passenger-install-apache2-module']; + if defined(Service['httpd']) { + File['/etc/httpd/conf.d/passenger.conf'] ~> Service['httpd'] } } diff --git a/manifests/passenger/apache/centos/pre.pp b/manifests/passenger/apache/centos/pre.pp index c26a9fca..c517ce80 100644 --- a/manifests/passenger/apache/centos/pre.pp +++ b/manifests/passenger/apache/centos/pre.pp @@ -3,4 +3,12 @@ if ! defined(Package['httpd']) { package { 'httpd': ensure => installed } } if ! defined(Package['httpd-devel']) { package { 'httpd-devel': ensure => installed } } if ! defined(Package['mod_ssl']) { package { 'mod_ssl': ensure => installed } } + + # Using this temp directory makes passenger work better with selinux + file { '/var/run/passenger': + ensure => directory, + owner => root, + group => 0, + mode => 0755, + } } diff --git a/manifests/passenger/apache/ubuntu/post.pp b/manifests/passenger/apache/ubuntu/post.pp index 87fc72ad..5cc08e9b 100644 --- a/manifests/passenger/apache/ubuntu/post.pp +++ b/manifests/passenger/apache/ubuntu/post.pp @@ -1,19 +1,18 @@ class rvm::passenger::apache::ubuntu::post( $ruby_version, $version, - $rvm_prefix = '/usr/local/', $mininstances = '1', $maxpoolsize = '6', $poolidletime = '300', $maxinstancesperapp = '0', $spawnmethod = 'smart-lv2', - $gempath, - $binpath + $rvmpath = $rvm::system::rvmpath, + $gempath ) { exec { 'passenger-install-apache2-module': - command => "${binpath}rvm ${ruby_version} exec passenger-install-apache2-module -a", + command => "$rvm_binary ${ruby_version} exec passenger-install-apache2-module -a", creates => "${gempath}/passenger-${version}/ext/apache2/mod_passenger.so", logoutput => 'on_failure', require => [Rvm_gem['passenger'], Package['apache2', 'build-essential', 'apache2-prefork-dev', diff --git a/manifests/passenger/gem.pp b/manifests/passenger/gem.pp index f57f6651..b39b4080 100644 --- a/manifests/passenger/gem.pp +++ b/manifests/passenger/gem.pp @@ -1,7 +1,8 @@ class rvm::passenger::gem($ruby_version, $version) { rvm_gem { "passenger": - ensure => $version, + ensure => $version, ruby_version => $ruby_version, + require => Rvm_system_ruby["${ruby_version}"], } } diff --git a/manifests/system.pp b/manifests/system.pp index 207076ad..1d73ff0b 100644 --- a/manifests/system.pp +++ b/manifests/system.pp @@ -1,13 +1,38 @@ -class rvm::system($version='latest') { - exec { 'system-rvm': - path => '/usr/bin:/usr/sbin:/bin', - command => "bash -c '/usr/bin/curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer -o /tmp/rvm-installer ; - chmod +x /tmp/rvm-installer ; - rvm_bin_path=/usr/local/rvm/bin rvm_man_path=/usr/local/rvm/man /tmp/rvm-installer --version ${version} ; - rm /tmp/rvm-installer'", - creates => '/usr/local/rvm/bin/rvm', - require => [ - Class['rvm::dependencies'], - ], +class rvm::system($version = 'latest', $use_pkg = false) { + # If you set $use_pkg to true, then this module expects that you have made + # an rvm-ruby package available in some repository + # One source for this package is https://github.com/mdkent/rvm-rpm + if ($use_pkg) { + $rvmpath = '/usr/lib/rvm' + package { 'rvm-ruby': + ensure => $version, + require => Class['rvm::dependencies'], + } + } + else { + $rvmpath = '/usr/local/rvm' + exec { 'system-rvm': + path => '/usr/bin:/usr/sbin:/bin', + command => "bash -c '/usr/bin/curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer -o /tmp/rvm-installer ; + chmod +x /tmp/rvm-installer ; + rvm_path=${rvmpath} /tmp/rvm-installer --version ${version} ; + rm /tmp/rvm-installer'", + creates => "${rvmpath}/bin/rvm", + require => Class['rvm::dependencies'], + } + } + + # Install the rvm hook to set selinux file contexts if needed + if $selinux == 'true' { + file { "$rvmpath/hooks/after_install": + source => 'puppet:///modules/rvm/after_install', + owner => root, + group => 'rvm', + mode => 0755, + require => $use_pkg ? { + true => Package['rvm-ruby'], + false => Exec['system-rvm'], + }, + } } } diff --git a/manifests/system_user.pp b/manifests/system_user.pp index 08a0ffb0..1534ecd2 100644 --- a/manifests/system_user.pp +++ b/manifests/system_user.pp @@ -7,18 +7,12 @@ if ! defined(User[$username]) { user { $username: - ensure => present; - } - } - - if ! defined(Group[$group]) { - group { $group: - ensure => present; + ensure => present, } } exec { "/usr/sbin/usermod -a -G $group $username": unless => "/bin/cat /etc/group | grep $group | grep $username", - require => [User[$username], Group[$group]]; + require => [User[$username], Group[$group]], } } diff --git a/templates/passenger-apache-centos.conf.erb b/templates/passenger-apache-centos.conf.erb index 219f124f..b5d1c1e2 100644 --- a/templates/passenger-apache-centos.conf.erb +++ b/templates/passenger-apache-centos.conf.erb @@ -2,10 +2,11 @@ LoadModule passenger_module <%= gempath %>/passenger-<%= version %>/ext/apache2/ PassengerRoot <%= gempath %>/passenger-<%= version %> - PassengerRuby <%= rvm_prefix %>rvm/wrappers/<%= ruby_version %>/ruby + PassengerRuby <%= rvmpath %>/wrappers/<%= ruby_version %>/ruby PassengerMaxPoolSize <%= maxpoolsize %> PassengerPoolIdleTime <%= poolidletime %> PassengerMinInstances <%= mininstances %> PassengerMaxInstancesPerApp <%= maxinstancesperapp %> PassengerSpawnMethod <%= spawnmethod %> + PassengerTempDir /var/run/passenger diff --git a/templates/passenger-apache.conf.erb b/templates/passenger-apache.conf.erb index fc5ec7ba..eb41a8ad 100644 --- a/templates/passenger-apache.conf.erb +++ b/templates/passenger-apache.conf.erb @@ -1,6 +1,6 @@ PassengerRoot <%= gempath %>/passenger-<%= version %> - PassengerRuby <%= rvm_prefix %>rvm/wrappers/<%= ruby_version %>/ruby + PassengerRuby <%= rvmpath %>/wrappers/<%= ruby_version %>/ruby PassengerMaxPoolSize <%= maxpoolsize %> PassengerPoolIdleTime <%= poolidletime %> PassengerMinInstances <%= mininstances %>