This is an old revision of the document!
OS Install: Post Install
General Information
After installing an OS via kickstart or a VM Template, there is typically additional standard configuration performed depending upon the environment.
This page demonstrates how to create VM templates and kickstarts that will auto-execute scripts one time for a system's first boot.
Checklist
- Distro(s): Enterprise Linux 6/7
- Other: NFS Server sharing a post install configuration script
Firstboot
- The firstboot script is executed once.
- It is baked into the system via a VM template or kickstart.
- It stays generic and calls other external scripts on remote admin systems to do the actual post install configuration.
- It also reboots the system and sends an email once it has completed
Firstboot: The script
This script is meant to run once and then disable itself. It calls other post install script(s) to do the actual work.
/root/scripts/firstboot.sh
#!/bin/bash # Name: firstboot.sh # Description: Auto runs a post install script 1 time #### Customize These Variables #### nfs_server="10.1.2.3" nfs_server_share="${nfs_server}:/scripts" nfs_client_mountpoint="/mnt" post_install_script="${nfs_client_mountpoint}/scripts/postinstall.sh" post_install_log="/root/postinstall.log" # Write a successful run file firstboot_ran_file="/root/.firstboot-ran" # System Admins Group Email system_admins_email='sysadmins@example.com' # Reboot delay in minutes reboot_delay="1" #### End of Customize Variables #### #============================== # Functions; Main Starts After #============================== function check_os_type { ## Gather Distro and Major Version if [ -f /etc/system-release-cpe ];then distro=$(awk -F: '{printf "%s", $3}' /etc/system-release-cpe) major_version=$(awk -F: '{printf "%d", $5}' /etc/system-release-cpe) elif [ -f /etc/redhat-release ];then distro=$(awk '{printf "%s", $1}' /etc/redhat-release) major_version=$(awk -F. '{print $1}' /etc/redhat-release | awk '{printf "%d", $3}') fi } #==================== # Main Program #==================== echo -e "================================================" echo -e "####========== Firstboot Script ============####" echo -e "================================================" # Check to see if script has been run before if [[ -f ${firstboot_ran_file} ]]; then echo -e "\nfirstboot>> Error; First boot ran file detected at: ${firstboot_ran_file}!" echo -e "firstboot>> Will NOT execute this script. If you really want to execute, remove that file." exit 1 fi # Discover OS Type check_os_type # Start rpcbind service if [[ ${major_version} == "7" ]]; then systemctl start rpcbind else service rpcbind start fi # Try to reach the NFS server 3 times for index in 1 2 3; do ping -c 1 ${nfs_server} &> /dev/null if [[ $? -eq 0 ]]; then # Successful ping, exit loop break else # Unsuccessful; wait 10 seconds and try again echo -e "firstboot>> Could not reach ${nfs_server}. Sleeping for 10 seconds and will try again." sleep 10 fi done # Mount script location echo -e "\nfirstboot>> Mounting script location..." mount -t nfs ${nfs_server_share} ${nfs_client_mountpoint} # Execute post install script echo -e "\nfirstboot>> Executing post install script..." ${post_install_script} if [[ $? -eq 0 ]]; then echo -e "\nfirstboot>> Post install script successful." else echo -e "\nfirstboot>> Error; Post install script exited with error(s)! Quiting..." exit 1 fi #============================================== # Call other post install scripts/actions here #============================================== # Unmount nfs share echo -e "\nfirstboot>> Unmounting nfs share.." umount ${nfs_client_mountpoint} #### Safeguards to prevent firstboot.sh from running more than once #### # Create firstboot-ran file echo -e "\nfirstboot>> Creating firstboot ran file..." echo -e "firstboot>> firstboot.sh was run on $(date)." > ${firstboot_ran_file} chown -v root:root ${firstboot_ran_file} chmod -v 400 ${firstboot_ran_file} # Make script not executable echo -e "\nfirstboot>> Removing execute permissions on this script..." chown -v root:root ${0} chmod -v 400 ${0} # Disable auto execution if [[ ${major_version} == "7" ]]; then systemctl disable firstboot.service else sed -i '/firstboot.sh/d' /etc/rc.d/rc.local fi #### End of Safeguards #### # Email notification of completion echo -e "\nfirstboot>> E-mailing notification that the script completed..." echo -e "The firstboot script process has completed for: '$(hostname)' on $(date).\n\nThe following actions have successfully run:\n1) Post install script (System updates, General system configuration)\n2) Other scripts\n\nThe system ($(hostname)) will reboot in ${reboot_delay} minute(s).\n\n--- Post Install Errors and Warnings ---\n$(grep ERROR ${post_install_log})\n$(grep WARNING ${post_install_log})" | /bin/mail -s "Firstboot Complete: $(hostname)" ${system_admins_email} # Allow some time for the email to be sent sleep 5 # Reboot system shutdown -r +${reboot_delay} "firstboot>> Post install script(s) complete. System will be rebooted."
Firstboot: CentOS 7 Service
Firstboot will get executed on CentOS 7 via a custom systemd service unit.
Create the following service unit file: /etc/systemd/system/firstboot.service
[Unit] Description=Auto-execute post install scripts After=network.target [Service] ExecStart=/root/scripts/firstboot.sh [Install] WantedBy=multi-user.target
Firstboot: CentOS 6 Service
CentOS 6 will make use of rc.local to execute the script.
Append to: /etc/rc.d/rc.local
/root/scripts/firstboot.sh
Auto Setup
Now that we have a firstboot script and method of executing on boot(CentOS 7 service or CentOS 6 rc.local), the combination of the two can be added to VM templates or kickstarts for unattended execution.
Auto Setup: VM Templates
The modifications for auto execution need to be done on a new template that is a modification of your base VM template.
Warning: Do not delete your base template after you have created an auto setup version! If you ever want to update your auto setup template, you will need to deploy from the base template, make changes, and create a new auto setup version.
- Deploy a new VM from your base template (Create a base template here)
- Make the following modifications to the new system.
- CentOS 6
## VM deployed from the base template ## ## Create a script directory for root mkdir /root/scripts ## Mount NFS Server and Copy firstboot.sh to the VM mount -t nfs <nfs-server>:/scripts /mnt cp -v /mnt/firstboot.sh /root/scripts/ chown -Rv root:root /root/scripts chmod -Rv 700 /root/scripts ## Create line in rc.local to auto execute firstboot script echo "/root/scripts/firstboot.sh" >> /etc/rc.d/rc.local ## Unmount NFS server umount /mnt
- Run CentOS 6 clean up commands identical to the base template and create a new template.
- CentOS 7
## VM deployed from the base template ## ## Create a script directory for root mkdir /root/scripts ## Mount NFS Server and Copy firstboot.sh to the VM mount -t nfs <nfs-server>:/scripts /mnt cp -v /mnt/firstboot.sh /root/scripts/ chown -Rv root:root /root/scripts chmod -Rv 700 /root/scripts ## Copy firstboot.service unit to the VM cp -v /mnt/firstboot.service /etc/systemd/system/ chown -v root:root /etc/systemd/system/firstboot.service chmod -v 644 /etc/systemd/system/firstboot.service systemctl enable firstboot.service ## Unmount NFS server umount /mnt
- Run CentOS 7 clean up commands identical to the base template and create a new template.
Auto Setup: Kickstarts
Kickstart files require a post install section to be edited in order for the firstboot script to be placed on a new system.
- Create a kickstart file as normal
- Modify the “%post” section at the bottom to include the following:
- CentOS 6
%post --interpreter /bin/sh --log=root/ks-post.log ( ## Start rpcbind for NFS service rpcbind start ## Mount NFS Server mount -vt nfs 10.1.2.3:/scripts /mnt ## Create root's scripts directory mkdir /root/scripts ## Copy the firstboot script to the new directory cp -v /mnt/firstboot.sh /root/scripts/ chown -Rv root:root /root/scripts chmod -Rv 700 /root/scripts ## Create rc.local entry for auto execution on boot echo "/root/scripts/firstboot.sh" >> /etc/rc.d/rc.local ## Unmount NFS Server umount -v /mnt ) %end
- CentOS 7
%post --interpreter /bin/sh --log=root/ks-post.log ( ## Start rpcbind for NFS systemctl start rpcbind ## Mount NFS Server mount -vt nfs 10.1.2.3:/scripts /mnt ## Create root's scripts directory mkdir /root/scripts ## Copy the firstboot script to the new directory cp -v /mnt/firstboot.sh /root/scripts/ chown -Rv root:root /root/scripts chmod -Rv 700 /root/scripts ## Copy the firstboot service for auto execution on boot cp -v /mnt/firstboot.service /etc/systemd/system/ chown -v root:root /etc/systemd/system/firstboot.service chmod -v 644 /etc/systemd/system/firstboot.service ## Enable firstboot service systemctl enable firstboot.service ## Unmount NFS Server umount -v /mnt ) %end
Post Install Script
- The post install script is what gets called via the firstboot script.
- This script does all the heavy lifting (system updates, configuration, etc).
Post install script: Provide logging and error checking
Post install worker: Perform the actual installations/config work