How to Use Puppet to Append Environment Variables to /etc/profile for Java/Tomcat Setup


3 views

When automating Java and Tomcat installations with Puppet, we often need to configure environment variables like JAVA_HOME in system-wide configuration files. The /etc/profile file is executed for login shells, making it an ideal place to set these variables.

The most elegant solution is to use the file_line resource from Puppet's stdlib module. First ensure you have the module installed:

puppet module install puppetlabs-stdlib

Here's a complete example that installs the packages and configures JAVA_HOME:

# Install required packages
package { [ 
  "openjdk-6-jdk", 
  "openjdk-6-doc", 
  "openjdk-6-jre",
  "tomcat6", 
  "tomcat6-admin", 
  "tomcat6-common", 
  "tomcat6-docs",
  "tomcat6-user"
]:
  ensure => present,
}

# Ensure JAVA_HOME is set in /etc/profile
file_line { 'set_java_home':
  path  => '/etc/profile',
  line  => 'JAVA_HOME="/usr/lib/java"\nexport JAVA_HOME',
  match => '^JAVA_HOME=',
}

If you prefer not to use stdlib, you can manage the entire file:

file { '/etc/profile':
  ensure  => file,
  content => "# Original /etc/profile content\nJAVA_HOME=\"/usr/lib/java\"\nexport JAVA_HOME",
  # Or use source => 'puppet:///modules/profile/profile_with_java'
}
  • Use file_line for minor modifications to avoid overwriting other configurations
  • Consider using /etc/environment for simpler variable declarations
  • For production, manage these variables in a dedicated profile.d script

After Puppet runs, verify with:

source /etc/profile
echo $JAVA_HOME

When managing Java and Tomcat installations with Puppet, setting environment variables like JAVA_HOME is a common requirement. The challenge lies in modifying system-wide configuration files like /etc/profile in an idempotent way - ensuring the changes persist without causing duplicate entries.

The most elegant solution is to use Puppet's file_line resource from the stdlib module. This allows you to append lines to files while checking for duplicates:

file_line { 'set_java_home':
  path  => '/etc/profile',
  line  => 'JAVA_HOME="/usr/lib/jvm/default-java"',
  match => '^JAVA_HOME=',
}

file_line { 'export_java_home':
  path  => '/etc/profile',
  line  => 'export JAVA_HOME',
  match => '^export JAVA_HOME',
  require => File_line['set_java_home'],
}

Here's how to combine this with your existing package installation:

package { [
  'openjdk-6-jdk',
  'openjdk-6-doc',
  'openjdk-6-jre',
  'tomcat6',
  'tomcat6-admin',
  'tomcat6-common',
  'tomcat6-docs',
  'tomcat6-user'
]:
  ensure => present,
}

file_line { 'set_java_home':
  ensure  => present,
  path    => '/etc/profile',
  line    => 'JAVA_HOME="/usr/lib/jvm/default-java"',
  match   => '^JAVA_HOME=',
  require => Package['openjdk-6-jdk'],
}

file_line { 'export_java_home':
  ensure  => present,
  path    => '/etc/profile',
  line    => 'export JAVA_HOME',
  match   => '^export JAVA_HOME',
  require => File_line['set_java_home'],
}

Using Augeas

For more complex modifications, Augeas provides a powerful alternative:

augeas { 'set_java_environment':
  context => '/files/etc/profile',
  changes => [
    'set JAVA_HOME "\"/usr/lib/jvm/default-java\""',
    'set export[. = "JAVA_HOME"] "JAVA_HOME"',
  ],
  onlyif  => 'match export[. = "JAVA_HOME"] size == 0',
}

Template Approach

For complete control, you can manage the entire file as a template:

file { '/etc/profile':
  ensure  => file,
  content => template('profile/profile.erb'),
  mode    => '0644',
}

This requires maintaining a complete template file, which might be overkill for simple additions.

After applying these changes, verify them with:

puppet agent --test
source /etc/profile
echo $JAVA_HOME