Contents
Intro
First of all, this howto wouldn´t have been possible without junovitch and his thread:
HOWTO: Puppet and Puppet Dashboard on top of Nginx/Passenger
so big kudos for that!
I´ve been wanting to test setting this up for a while to explore the integration of Foreman and oVirt; an open-source alternative to VMWare vSphere that we use in our organization for test and development systems, and wanted to know if Foreman could be a tool to save us some time.
Installing packages
So I don´t know how you want to do, compile from ports or install with pkg, but these are the packages that are needed:
We have our own Poudriere build server so I don´t really remember what options were used, but mostly just the defaults. Only 'gotcha' I can remember is to keep Apache at 2.4 and ruby at 2.2:
/etc/make.conf
Setting up database
Setting up Puppet and Foreman
This next part is by far the hardest; getting all gems in the bundle installed. Seems like a new issue for every version but something that has always been a problem is therubyracer and libv8. Basically just do
NOTE: Here you make sure to catch the 'admin' password that gets printed!!!
Setting up Apache
A little housekeeping is never a bad thing:
Setting up Foreman-proxy
Summary
When all is said and done you should have The Foreman web interface available at "https://foreman.foo.bar" where you log in with the 'admin' account and the password you previously saved. You then start by adding the smart proxy which is at "https://foreman.foo.bar:8443" and start pointing some clients towards it.
/Sebulon
- Intro
- Installing packages
- Setting up database
- Setting up Puppet and Foreman
- Setting up Apache
- Setting up Foreman-proxy
Intro
First of all, this howto wouldn´t have been possible without junovitch and his thread:
HOWTO: Puppet and Puppet Dashboard on top of Nginx/Passenger
so big kudos for that!
I´ve been wanting to test setting this up for a while to explore the integration of Foreman and oVirt; an open-source alternative to VMWare vSphere that we use in our organization for test and development systems, and wanted to know if Foreman could be a tool to save us some time.
Installing packages
So I don´t know how you want to do, compile from ports or install with pkg, but these are the packages that are needed:
# pkg install -y gcc puppet4 puppetserver rubygem-puppet-lint git ruby22-gems rubygem-rake rubygem-passenger rubygem-bundler mariadb101-server mariadb101-client libxslt node sqlite3 rubygem-foreman foreman-proxy rubygem-hammer_cli_foreman libvirt apache24 npm sudo rubygem-concurrent-ruby
We have our own Poudriere build server so I don´t really remember what options were used, but mostly just the defaults. Only 'gotcha' I can remember is to keep Apache at 2.4 and ruby at 2.2:
/etc/make.conf
Code:
WITH_PKGNG="YES"
DEFAULT_VERSIONS+= apache=2.4 ruby=2.2
Setting up database
Code:
# cp /usr/local/share/mysql/my-huge.cnf /var/db/mysql/my.cnf
# patch /var/db/mysql/my.cnf << EOF
32c32,33
< max_allowed_packet = 1M
---
> # Allow 32MB packet Size for ~17MB size rows Puppet dashboard sends
> max_allowed_packet = 32M
56a58
> expire_logs_days = 10
EOF
# echo 'mysql_enable="YES"' >> /etc/rc.conf
# service mysql-server start
# printf "\\nY\\n<mysql_root_password>\\n<mysql_root_password>\\nY\\nY\\nY\\nY\\n" | mysql_secure_installation
# mysql -uroot -p<mysql_root_password> -e "CREATE DATABASE foreman_production CHARACTER SET utf8;"
# mysql -uroot -p<mysql_root_password> -e "CREATE DATABASE foreman_development CHARACTER SET utf8;"
# mysql -uroot -p<mysql_root_password> -e "CREATE DATABASE foreman_test CHARACTER SET utf8;"
# mysql -uroot -p<mysql_root_password> -e "CREATE USER 'foreman'@'foreman.foo.bar' IDENTIFIED BY '<foreman_password>';"
# mysql -uroot -p<mysql_root_password> -e "GRANT ALL PRIVILEGES ON foreman_production.* TO 'foreman'@'foreman.foo.bar';"
# mysql -uroot -p<mysql_root_password> -e "GRANT ALL PRIVILEGES ON foreman_development.* TO 'foreman'@'foreman.foo.bar';"
# mysql -uroot -p<mysql_root_password> -e "GRANT ALL PRIVILEGES ON foreman_test.* TO 'foreman'@'foreman.foo.bar';"
# mysql -uroot -p<mysql_root_password> -e "flush privileges;"
Code:
# mkdir -p /usr/local/etc/puppet/environments/production/{manifests,modules}
# echo 'Exec { path => "/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin" }' >> /usr/local/etc/puppet/environments/production/manifests/site.pp
# touch /usr/local/etc/puppet/autosign.conf
# puppet master --genconfig --confdir=/usr/local/etc/puppet --rundir=/var/run/puppet --vardir=/var/puppet --logdir=/var/log/puppet --codedir=/usr/local/etc/puppet > /usr/local/etc/puppet/puppetmasterd.conf-dist
# cp /usr/local/etc/puppet/puppetmasterd.conf-dist /usr/local/etc/puppet/puppet.conf
# rm -rf /var/puppet/ssl/*
# service puppetmaster onestart
# echo 'puppetserver_enable="YES"' >> /etc/rc.conf
# patch /usr/local/etc/puppetserver/conf.d/auth.conf << EOF
58a59,89
> match-request: {
> path: "/puppet/v3/resource_type"
> type: path
> method: [get, post]
> }
> allow: "*"
> sort-order: 500
> name: "puppetlabs resource type"
> },
> {
> match-request: {
> path: "/puppet/v3/environment_classes"
> type: path
> method: get
> }
> allow: "*"
> sort-order: 500
> name: "puppetlabs environment classes"
> },
> {
> # Puppet 3 & 4 compatible auth.conf with Puppet Server 2.2+
> match-request: {
> path: "^/puppet/v3/catalog/([^/]+).uuid$"
> type: regex
> method: [get, post]
> }
> allow: "/^$1|.uuid.*/"
> sort-order: 200
> name: "my catalog"
> },
> {
EOF
# sed -i '' 's|#use-legacy-auth-conf: false|use-legacy-auth-conf: false|' /usr/local/etc/puppetserver/conf.d/puppetserver.conf
# cd /usr/local/share/
# git clone https://github.com/theforeman/foreman.git -b 1.14-stable
# pw groupadd -n foreman -g 800
# pw useradd -n foreman -c "The Foreman" -d /usr/local/share/foreman -u 800 -g foreman -s /usr/sbin/nologin
# cat > /usr/local/share/foreman/config/database.yml << EOF
production:
adapter: mysql2
database: foreman_production
username: foreman
password: <foreman_password>
host: foreman.foo.bar
encoding: utf8
socket: "/var/run/mysqld/mysqld.sock"
development:
adapter: mysql2
database: foreman_development
username: foreman
password: <foreman_password>
host: foreman.foo.bar
encoding: utf8
socket: "/var/run/mysqld/mysqld.sock"
test:
adapter: mysql2
database: foreman_test
username: foreman
password: <foreman_password>
host: foreman.foo.bar
encoding: utf8
socket: "/var/run/mysqld/mysqld.sock"
EOF
# chmod 660 /usr/local/share/foreman/config/database.yml
# cp /usr/local/share/foreman/config/settings.yaml.example /usr/local/share/foreman/config/settings.yaml
# sed -i '' -e 's/\/etc\/puppet/\/usr\/local\/etc\/puppet/' -e 's/\/var\/lib\/puppet/\/var\/puppet/' -e "s/'localdomain.net'/'foo.bar'/" -e "s/'localhost.localdomain.net'/'foreman.foo.bar'/" /usr/local/share/foreman/config/settings.yaml
# chmod 660 /usr/local/share/foreman/config/settings.yaml
# cat > /usr/local/share/foreman/config/email.yaml << EOF
# Outgoing email settings
production:
delivery_method: :smtp
smtp_settings:
address: smtp.gmail.com
port: 587
domain: foo.bar
authentication: :login
user_name: user.name@gmail.com
password: P4$$w0rd!
EOF
# fetch https://raw.githubusercontent.com/theforeman/puppet-foreman/master/files/external_node_v2.rb
# sed -i '' 's|/usr/bin/env ruby|/usr/local/bin/ruby|' external_node_v2.rb
# mv external_node_v2.rb /usr/local/etc/puppet/node.rb
# chown puppet:puppet /usr/local/etc/puppet/node.rb
# chmod +x /usr/local/etc/puppet/node.rb
# fetch https://raw.githubusercontent.com/theforeman/puppet-foreman/master/files/foreman-report_v2.rb
# mv foreman-report_v2.rb /usr/local/lib/ruby/site_ruby/2.2/puppet/reports/foreman.rb
# cat > /usr/local/etc/puppet/foreman.yaml << EOF
---
# Update for your Foreman and Puppet master hostname(s)
:url: "https://foreman.foo.bar"
:ssl_ca: "/var/puppet/ssl/certs/ca.pem"
:ssl_cert: "/var/puppet/ssl/certs/foreman.foo.bar.pem"
:ssl_key: "/var/puppet/ssl/private_keys/foreman.foo.bar.pem"
# Advanced settings
:puppetdir: "/var/puppet"
:puppetuser: "puppet"
:facts: true
:timeout: 10
:threads: null
EOF
# sed -i '' -e 's/node_terminus = plain/node_terminus = exec/' -e 's/# external_nodes = none/external_nodes = \/usr\/local\/etc\/puppet\/node.rb/' -e 's/# reports = store/reports=log, foreman/' -e 's#autosign = /usr/local/etc/puppet/autosign.conf#autosign = /usr/local/etc/puppet/autosign.conf {owner = service, group = service, mode = 664 }#' /usr/local/etc/puppet/puppet.conf
This next part is by far the hardest; getting all gems in the bundle installed. Seems like a new issue for every version but something that has always been a problem is therubyracer and libv8. Basically just do
gem install -v '3.16.14.7' libv8
. If that doesn´t work, go here to see what versions there are until you find one that installs and write that down in the below bundler file, along with the dependent version of therubyracer from here. The last version digit of libv8 you use should be an odd number. They are the binary versions. Here´s what worked for 1.14:
Code:
# cd /usr/local/share/foreman
# cat > bundler.d/therubyracer.rb << EOF
gem 'therubyracer', '0.12.2', :require => 'v8'
gem 'libv8', '3.16.14.7'
EOF
# mkdir .bundle
# echo 'BUNDLE_BUILD__RUBY-LIBVIRT: "-v 0.7.0 --with-libvirt-include=/usr/local/include --with-libvirt-lib=/usr/local/lib"' >> .bundle/config
# bundle install --without postgresql --path vendor/bundle
# npm install
# RAILS_ENV=production bundle exec rake db:migrate
# RAILS_ENV=production bundle exec rake db:seed assets:precompile locale:pack webpack:compile
NOTE: Here you make sure to catch the 'admin' password that gets printed!!!
Setting up Apache
Code:
# chown -R puppet:puppet /usr/local/etc/puppet
# service puppetmaster onestop
# service puppetserver onestart
# mkdir -p /etc/pki/foreman/
# openssl genrsa -out /etc/pki/foreman/foreman.foo.bar.key 1024
# openssl req -new -subj "/CN=foreman.foo.bar" -key /etc/pki/foreman/foreman.foo.bar.key -out /etc/pki/foreman/foreman.foo.bar.csr
# openssl x509 -sha256 -req -days 3650 -in /etc/pki/foreman/foreman.foo.bar.csr -CA /var/puppet/ssl/certs/ca.pem -CAkey /var/puppet/ssl/ca/ca_key.pem -CAcreateserial -out /etc/pki/foreman/foreman.foo.bar.cert
# sed -i '' -e 's|^#LoadModule ssl_module libexec/apache24/mod_ssl.so|LoadModule ssl_module libexec/apache24/mod_ssl.so|' -e 's|#LoadModule socache_shmcb_module libexec/apache24/mod_socache_shmcb.so|LoadModule socache_shmcb_module libexec/apache24/mod_socache_shmcb.so|' /usr/local/etc/apache24/httpd.conf
# cat > /usr/local/etc/apache24/Includes/foreman.conf << EOF
LoadModule passenger_module /usr/local/lib/ruby/gems/2.2/gems/passenger/buildout/apache2/mod_passenger.so
PassengerRoot /usr/local/lib/ruby/gems/2.2/gems/passenger
PassengerRuby /usr/local/bin/ruby
PassengerHighPerformance on
PassengerMaxPoolSize 12
PassengerPoolIdleTime 1500
PassengerStatThrottleRate 120
PassengerEnabled On
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder On
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
SSLCompression off
SSLUseStapling on
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
SSLSessionTickets Off
<VirtualHost *:80>
ServerName foreman.foo.bar
ServerAlias foreman
DocumentRoot /usr/local/share/foreman/public
PassengerAppRoot /usr/local/share/foreman
<Directory /usr/local/share/foreman/public>
Options FollowSymLinks
DirectoryIndex index.html
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
Listen 443
<VirtualHost *:443>
ServerName foreman.foo.bar
ServerAlias foreman
DocumentRoot /usr/local/share/foreman/public
PassengerAppRoot /usr/local/share/foreman
SSLEngine on
SSLCertificateFile /etc/pki/foreman/foreman.foo.bar.cert
SSLCertificateKeyFile /etc/pki/foreman/foreman.foo.bar.key
SSLCACertificateFile /var/puppet/ssl/ca/ca_crt.pem
SSLCARevocationFile /var/puppet/ssl/ca/ca_crl.pem
SSLVerifyClient optional
SSLVerifyDepth 1
SSLOptions +StdEnvVars
<Directory /usr/local/share/foreman/public>
Options FollowSymLinks
DirectoryIndex index.html
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
EOF
# chown -R foreman:foreman /usr/local/share/foreman
# pw groupmod puppet -M foreman,foreman_proxy
# cat >> /usr/local/etc/sudoers << EOF
foreman_proxy ALL = NOPASSWD: /usr/local/bin/puppet cert *
Defaults:foreman_proxy !requiretty
EOF
# echo 'apache24_enable="YES"' >> /etc/rc.conf
# service apache24 start
A little housekeeping is never a bad thing:
Code:
# cat > /usr/local/bin/foreman-rake << EOF
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
RAKE_COMMAND=\$@
ORIGINAL_DIRECTORY=\$(pwd)
cd /usr/local/share/foreman
su -m foreman -c "bundle exec rake RAILS_ENV=production \${RAKE_COMMAND} --trace"
EXIT=\$?
cd \${ORIGINAL_DIRECTORY}
exit \${EXIT}
EOF
# chmod +x /usr/local/bin/foreman-rake
# cat >> /etc/crontab << EOF
# Clean up the session entries in the database
15 23 * * * root /usr/local/bin/foreman-rake db:sessions:clear >>/var/log/foreman/cron.log 2>&1
# Send out recurring notifications
0 7 * * * root /usr/local/bin/foreman-rake reports:daily >>/var/log/foreman/cron.log 2>&1
0 5 * * 0 root /usr/local/bin/foreman-rake reports:weekly >>/var/log/foreman/cron.log 2>&1
0 3 1 * * root /usr/local/bin/foreman-rake reports:monthly >>/var/log/foreman/cron.log 2>&1
# Expire old reports
30 6 * * * root /usr/local/bin/foreman-rake reports:expire days=28 >>/var/log/foreman/cron.log 2>&1
30 7 * * * root /usr/local/bin/foreman-rake reports:expire days=1 status=0 >>/var/log/foreman/cron.log 2>&1
# Refreshes ldap usergroups. Can be disabled if you're not using LDAP authentication.
*/30 * * * * root /usr/local/bin/foreman-rake ldap:refresh_usergroups >>/var/log/foreman/cron.log 2>&1
EOF
# mkdir /var/log/foreman
# touch /var/log/foreman/cron.log
Setting up Foreman-proxy
Code:
# gem install rgen
# cd /usr/local/etc/foreman-proxy/settings.d
# ln -s ../settings.yml foreman_proxy.yml
# cd ..
# patch settings.yml << EOF
6,8c6,8
< #:ssl_certificate: ssl/certs/fqdn.pem
< #:ssl_ca_file: ssl/certs/ca.pem
< #:ssl_private_key: ssl/private_keys/fqdn.key
---
> :ssl_certificate: "/var/puppet/ssl/certs/foreman.foo.bar.pem"
> :ssl_ca_file: "/var/puppet/ssl/certs/ca.pem"
> :ssl_private_key: "/var/puppet/ssl/private_keys/foreman.foo.bar.pem"
18c18
< #:trusted_hosts: []
---
> :trusted_hosts: [ foreman.foo.bar ]
25c25
< #:foreman_url: http://127.0.0.1:3000
---
> :foreman_url: "https://foreman.foo.bar"
42c42
< #:bind_host: '*'
---
> :bind_host: '0.0.0.0'
EOF
# patch settings.d/puppet.yml << EOF
3c3
< :enabled: false
---
> :enabled: true
11c11
< #:use_provider: puppet_proxy_puppetrun
---
> :use_provider: puppet_proxy_ssh
14c14
< #:puppet_version: 4.1
---
> :puppet_version: 4.8
EOF
# patch settings.d/puppet_proxy_legacy.yml << EOF
8c8
< #:puppet_conf: /etc/puppet/puppet.conf
---
> :puppet_conf: /usr/local/etc/puppet/puppet.conf
16c16
< #:puppet_url: https://puppet.example.com:8140
---
> :puppet_url: https://foreman.foo.bar:8140
19,21c19,21
< #:puppet_ssl_ca: /var/lib/puppet/ssl/certs/ca.pem
< #:puppet_ssl_cert: /var/lib/puppet/ssl/certs/puppet.example.com.pem
< #:puppet_ssl_key: /var/lib/puppet/ssl/private_keys/puppet.example.com.pem
---
> :puppet_ssl_ca: /var/lib/puppet/ssl/certs/ca.pem
> :puppet_ssl_cert: /var/lib/puppet/ssl/certs/foreman.foo.bar.pem
> :puppet_ssl_key: /var/lib/puppet/ssl/private_keys/foreman.foo.bar.pem
EOF
# patch settings.d/puppet_proxy_puppet_api.yml << EOF
9c9
< #:puppet_url: https://puppet.example.com:8140
---
> :puppet_url: https://foreman.foo.bar:8140
12,14c12,14
< #:puppet_ssl_ca: /var/lib/puppet/ssl/certs/ca.pem
< #:puppet_ssl_cert: /var/lib/puppet/ssl/certs/puppet.example.com.pem
< #:puppet_ssl_key: /var/lib/puppet/ssl/private_keys/puppet.example.com.pem
---
> :puppet_ssl_ca: /var/lib/puppet/ssl/certs/ca.pem
> :puppet_ssl_cert: /var/lib/puppet/ssl/certs/foreman.foo.bar.pem
> :puppet_ssl_key: /var/lib/puppet/ssl/private_keys/foreman.foo.bar.pem
EOF
# patch settings.d/puppet_proxy_ssh.yml << EOF
3c3
< #:command: puppet agent --onetime --no-usecacheonfailure
---
> :command: service puppet restart
6c6
< #:use_sudo: false
---
> :use_sudo: false
11c11
< #:wait: false
---
> :wait: false
14,15c14,15
< #:user: root
< #:keyfile: /etc/foreman-proxy/id_rsa
---
> :user: root
> :keyfile: /usr/local/etc/foreman-proxy/id_rsa
EOF
# ssh-keygen
Type in "/usr/local/etc/foreman-proxy/id_rsa" as path and do not type in any password.
# patch settings.d/puppetca.yml << EOF
3c3
< :enabled: false
---
> :enabled: true
5,8c5,8
< #:ssldir: /var/puppet/ssl
< #:puppetdir: /usr/local/etc/puppet
< #:puppetca_use_sudo: true
< #:sudo_command: /usr/local/bin/sudo
---
> :ssldir: /var/puppet/ssl
> :puppetdir: /usr/local/etc/puppet
> :puppetca_use_sudo: true
> :sudo_command: /usr/local/bin/sudo
EOF
# cd /var/lib/
# ln -s ../puppet puppet
# echo 'foreman_proxy_enable="YES"' >> /etc/rc.conf
# service foreman-proxy start
Summary
When all is said and done you should have The Foreman web interface available at "https://foreman.foo.bar" where you log in with the 'admin' account and the password you previously saved. You then start by adding the smart proxy which is at "https://foreman.foo.bar:8443" and start pointing some clients towards it.
/Sebulon
Last edited: