% Created 2025-08-23 Sat 05:35
% Intended LaTeX compiler: pdflatex
\documentclass[presentation]{beamer}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\usepackage{longtable}
\usepackage{wrapfig}
\usepackage{rotating}
\usepackage[normalem]{ulem}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{capt-of}
\usepackage{hyperref}
\usetheme{default}
\author{Bryan Moffit <moffit@jlab.org>}
\date{\today}
\title{Installation and Configuration of CentOS7 Diskless OS for x86\_64 and armv7}
\hypersetup{
 pdfauthor={Bryan Moffit <moffit@jlab.org>},
 pdftitle={Installation and Configuration of CentOS7 Diskless OS for x86\_64 and armv7},
 pdfkeywords={},
 pdfsubject={},
 pdfcreator={Emacs 29.4 (Org mode 9.7.21)}, 
 pdflang={English}}
\begin{document}

\maketitle
\begin{frame}{Outline}
\tableofcontents
\end{frame}

\begin{frame}[label={sec:org8d169fe},fragile]{Installation and Configuration Intro}
 The following guide describes the installation and configuration of CentOS7 for use with diskless clients running \texttt{x86\_64} (e.g. VME Controllers), \texttt{armv7} (VTPs), or \texttt{aarch64} (MOLLERADC).
It's my hope that this will be useful to anyone left to do this on their own.

This guide assumes that you have a DHCP that can be configured with these parameters
\begin{verbatim}
filename "pxelinux.0";
next-server 129.57.xxx.xxx;
\end{verbatim}
Where \texttt{next-server} should reflect the IPv4 address of your (tftp) host machine.

It also assumes that your host machine and VME/VTP have DNS entries.

\alert{dnsmasq} is a program that can be used to handle TFTP, DHCP, and DNS.
Here's a good write-up I found describing it's use with pxelinux:
\href{https://www.theurbanpenguin.com/pxelinux-using-proxy-dhcp/}{PXELinux using Proxy DHCP}
\begin{block}{The Boot Process}
\begin{block}{VME}
BIOS configured for PXE (check your settings from these \href{https://coda.jlab.org/drupal/content/controller-configuration}{pages})
\begin{block}{DHCP provides info to connect to bootloader}
\begin{itemize}
\item ip address
\item tftp server address (your machine's hostname)
\item tftp filename to load (\texttt{pxelinux.0})
\end{itemize}
\end{block}
\begin{block}{\href{https://en.wikipedia.org/wiki/SYSLINUX}{pxelinux}}
\begin{itemize}
\item boot environment configured \texttt{pxelinux.cfg/<address files>}
\item tftp to get kernel and initial ramdisk
\end{itemize}
\end{block}
\begin{block}{kernel}
\begin{itemize}
\item loads up operating system filesystem using NFS
\end{itemize}
\end{block}
\end{block}
\begin{block}{VTP}
uboot loaded on power up
\begin{block}{\href{https://en.wikipedia.org/wiki/Das\_U-Boot}{uboot}}
\begin{itemize}
\item environment loaded from \texttt{env.txt} on microSD
\item tftp to get kernel and initial ramdisk
\end{itemize}
\end{block}
\begin{block}{kernel}
\begin{itemize}
\item loads up operating system filesystem using NFS
\end{itemize}
\end{block}
\end{block}
\end{block}
\end{frame}
\begin{frame}[label={sec:orga256ce8},fragile]{Host packages to install}
 \begin{verbatim}
nfs-utils, tftp-server, syslinux-tftpboot, syslinux
\end{verbatim}

\begin{itemize}
\item I installed these on my host system using yum
\end{itemize}
\begin{verbatim}
yum install nfs-utils tftp-server syslinux-tftpboot syslinux
\end{verbatim}
\end{frame}
\begin{frame}[label={sec:orge475c99},fragile]{Download}
 \begin{block}{centos7\_dist}
\begin{itemize}
\item Clone the \texttt{centos7\_dist} repo from github
\end{itemize}
\begin{verbatim}
git clone --depth 1 git@github.com:JeffersonLab/centos7_dist.git
\end{verbatim}
or on site
\begin{verbatim}
git clone --depth 1 /site/coda/contrib/devel/centos7_dist
\end{verbatim}
\end{block}
\begin{block}{tgz’s}
Download and install the root and tftp pair for your module(s).
\begin{itemize}
\item VTP (\alert{armv7)}:
\begin{itemize}
\item \href{https://coda.jlab.org/drupal/system/files/coda/iso/root\_armv7-rc6.tgz}{root-rc6} (filesize = 1G)  \href{https://coda.jlab.org/drupal/system/files/coda/iso/tftp\_armv7-rc2.tgz}{tftp-rc2} (filesize = 26M)
\end{itemize}

\item VME (\alert{x86\_64)}:

\begin{itemize}
\item \href{https://coda.jlab.org/drupal/system/files/coda/iso/root\_x86\_64-rc5.tgz}{root-rc5} (filesize = 1.5G) \href{https://coda.jlab.org/drupal/system/files/coda/iso/tftp\_x86\_64-rc2.tgz}{tftp-rc2} (filesize = 7.2M)
\end{itemize}

\item I downloaded these and moved them into the \texttt{tgz} directory
\begin{verbatim}
centos7_dist/tgz/root_x86_64-rc5.tgz
centos7_dist/tgz/tftp_x86_64-rc2.tgz
\end{verbatim}
\end{itemize}
\end{block}
\end{frame}
\begin{frame}[label={sec:org0108a2d},fragile]{Configure the distribution}
 \begin{block}{VME OS}
I put together the following configuration for my system:
\begin{verbatim}
# The local paths for NFS exports to diskless paths: /, /home, and snapshot files
#   using base path
#       /usr/local/diskless
#
# Uncomment and set, if running the diskless_* scripts on a machine
#  that's not the indented NFS server.  Otherwise the default is NFS_SERVER_HOSTNAME=$(hostname -s)
#NFS_SERVER_HOSTNAME="daqfs.jlab.org"

NFS_PATH=/usr/local/diskless/CentOS7/x86_64

NFS_ROOT_PATH=${NFS_PATH}/root
NFS_SNAPSHOT_PATH=${NFS_PATH}/snapshot
NFS_HOME_PATH=${NFS_PATH}/home

NFS_EXPORTS=centos7-x86_64.exports

#
# The hostname of our vme controller
#
CLIENT_HOSTNAME[0]="davme6"

#
# root filesystem and kernel boot files
#
TGZ_ROOT=tgz/root_x86_64-rc5.tgz
TGZ_TFTP=tgz/tftp_x86_64-rc2.tgz

#
# kernel boot files specific to TGZ_TFTP version
#
VMLINUZ=vmlinuz-3.10.0-1062.9.1.el7.x86_64
INITRD=initramfs-3.10.0-1062.9.1.el7.x86_64.img

#
# tftp files
#
TFTP_PATH=/var/lib/tftpboot
TFTP_PXELINUX_CFG_PATH=${TFTP_PATH}/pxelinux.cfg
TFTP_PXELINUX_CFG_DEFAULT=centos7-x86_64.default
TFTP_KERNEL_PATH=${TFTP_PATH}/CentOS7-x86_64-Diskless

#
# Template files
#
TEMPLATE_PATH=templates
YP_CONF_TEMPLATE=${TEMPLATE_PATH}/yp.conf
READONLY_ROOT_TEMPLATE=${TEMPLATE_PATH}/readonly-root
PXECONFIG_ADDR_TEMPLATE=${TEMPLATE_PATH}/pxelinux.cfg_ADDR
AUTOFS_HOME_TEMPLATE=${TEMPLATE_PATH}/auto.home
UBOOT_ENV_TEMPLATE=${TEMPLATE_PATH}/env.txt
\end{verbatim}

\begin{itemize}
\item \texttt{NFS\_PATH}

This is where the centos7 x86\_64 filesystem will be unpacked.

\begin{itemize}
\item I updated this path to this location on my host system
\end{itemize}

\begin{verbatim}
NFS_PATH=/usr/local/diskless/CentOS7/x86_64
\end{verbatim}

\item \texttt{CLIENT\_HOSTNAME[n]}

\begin{itemize}
\item I only have one VME controller at the moment, it's hostname will be \texttt{davme6.jlab.org}.  But's short hostname is what is needed here:
\end{itemize}
\begin{verbatim}
CLIENT_HOSTNAME[0]=davme6
\end{verbatim}

\item \texttt{TGZ\_ROOT, TGZ\_TFTP, VMLINUZ, INITRD}

\begin{itemize}
\item These ought to be defined in an sample configuration file provided with the tgz's.  They contain the root filesystem, and boot files needed for the diskless client.
\end{itemize}

\item \texttt{TFTP\_PATH}

Sometimes this path will be different for different types of tftp
servers.

\begin{itemize}
\item I'm using \alert{tftp-server} on RHEL 7.  So this path is the
default:
\end{itemize}

\begin{verbatim}
TFTP_PATH=/var/lib/tftpboot
\end{verbatim}
\end{itemize}



The scripts will generate the necessary configuration files and commands to install them (as root or with sudo)
\begin{block}{diskless\_ROOTOS.sh}
\begin{itemize}
\item I ran this command using my config file as the only argument
\begin{verbatim}
./diskless_ROOTOS.sh walkthrough_example.cfg
\end{verbatim}
\begin{verbatim}
# 
# Generating yp.conf
# 
# ... Generated: output/yp.conf
# 
# Generating home.autofs
# 
# ... Generated: output/auto.home
# 
# Generating readonly-root
# 
# ... Generated: output/readonly-root
# 
# #   Extract TGZ_ROOT=tgz/root_x86_64-rc5.tgz to 
# #   NFS_ROOT_PATH=/usr/local/diskless/CentOS7/x86_64/root
install -b -p -m 755 -d /usr/local/diskless/CentOS7/x86_64/root
tar xzf tgz/root_x86_64-rc5.tgz -C /usr/local/diskless/CentOS7/x86_64/root
# 
# #  Make the snapshot and home directories
install -b -p -m 755 -d /usr/local/diskless/CentOS7/x86_64/snapshot
install -b -p -m 755 -d /usr/local/diskless/CentOS7/x86_64/home
# 
# #   To install yp.conf
install -b -p -m 644 output/yp.conf /usr/local/diskless/CentOS7/x86_64/root/etc/yp.conf
# 
# #   To Install auto.home
install -b -p -m 644 templates/home.autofs /usr/local/diskless/CentOS7/x86_64/root/etc/auto.master.d/home.autofs
install -b -p -m 644 output/auto.home /usr/local/diskless/CentOS7/x86_64/root/etc/auto.master.d/auto.home
# 
# #   To Install readonly-root
# 
install -b -p -m 644 output/readonly-root /usr/local/diskless/CentOS7/x86_64/root/etc/sysconfig/readonly-root
\end{verbatim}

\item This one generates a number of config files for the client OS and provides the installation commands to be run in sequence using sudo or as the root user.
\end{itemize}
\end{block}
\begin{block}{diskless\_NFSexports.sh}
\begin{itemize}
\item This script generates the exports files needed for NFS
\begin{verbatim}
./diskless_NFSexports.sh walkthrough_example.cfg
\end{verbatim}
\begin{verbatim}
# 
# Generating NFS exports...
#   ... Generated: output/centos7-x86_64.exports
# 
# To install NFS exports:
install -b -p -m 644 output/centos7-x86_64.exports /etc/exports.d/centos7-x86_64.exports
\end{verbatim}
\end{itemize}
\end{block}
\begin{block}{diskless\_PXE-TFTP.sh}
\begin{itemize}
\item This script generates the configuration and installation commands for PXE and TFTP.

\begin{verbatim}
./diskless_PXE-TFTP.sh walkthrough_example.cfg
\end{verbatim}
\begin{verbatim}
# 
# Generating pxelinux config files
#   ... Linked: output/81391D92 to centos7-x86_64.default
# 
# To Install pxelinux config files
install -b -p -m 755 -d /var/lib/tftpboot/pxelinux.cfg/
install -b -p -m 644 output/centos7-x86_64.default /var/lib/tftpboot/pxelinux.cfg/
# 
# Link: /var/lib/tftpboot/pxelinux.cfg/81391D92 to centos7-x86_64.default
ln -sf centos7-x86_64.default /var/lib/tftpboot/pxelinux.cfg/81391D92
# 
# Extract TGZ_TFTP=tgz/tftp_x86_64-rc2.tgz to 
# TFTP_KERNEL_PATH=/var/lib/tftpboot/CentOS7-x86_64-Diskless
install -b -p -m 755 -d /var/lib/tftpboot/CentOS7-x86_64-Diskless/
tar xzvf tgz/tftp_x86_64-rc2.tgz -C /var/lib/tftpboot/CentOS7-x86_64-Diskless
\end{verbatim}
\end{itemize}
\end{block}
\end{block}
\begin{block}{VTP OS}
If you've got a VTP, the configuration will be very similar, mostly swapping x86\_64 with armv7.

\begin{itemize}
\item CLIENT\_HOSTNAME[n]

I only have one VTP, it's hostname will be \texttt{davtp1.jlab.org}.  It's short hostname is all that's needed here:
\begin{verbatim}
CLIENT_HOSTNAME[0]="davtp1"
\end{verbatim}

\item VTP\_MAC\_ADDR

This parameter is used in the generation of the VTPs environment file.  The MAC address is unique for each VTP, and can be obtained from Ben Raydo.
\begin{verbatim}
VTP_MAC_ADDR="ce:ba:f0:03:cc:ff" 
\end{verbatim}
\end{itemize}

Execute the scripts that were called for the VME OS using the armv7 config file.
\begin{block}{diskless\_UBOOT.sh}
This script generates the uboot \texttt{env.bin} that needs to be loaded onto the microSD used by the VTP
\begin{verbatim}
./diskless_UBOOT.sh walkthrough_vtp_example.cfg
\end{verbatim}
\begin{verbatim}
# 
# Generating U-Boot Environment
#  output/env.bin now ready for VTP microSD
\end{verbatim}
\begin{itemize}
\item Copy the resulting file \texttt{output/env.bin} to the VTPs microSD FAT partition.
\end{itemize}
\end{block}
\end{block}
\end{frame}
\begin{frame}[label={sec:org3f4396c},fragile]{Enable and start the NFS-server service}
 \begin{itemize}
\item As \alert{root}, execute
\begin{verbatim}
systemctl enable nfs-server.service 
systemctl start nfs-server.service 
\end{verbatim}
\end{itemize}
\end{frame}
\begin{frame}[label={sec:org8e24ea6},fragile]{Enable and start the TFTP server}
 \begin{itemize}
\item As \alert{root}, execute
\begin{verbatim}
systemctl enable tftp
systemctl start tftp
\end{verbatim}
\end{itemize}
\end{frame}
\begin{frame}[label={sec:org5fae6c3},fragile]{First Login}
 \begin{block}{Setup daq account}
\begin{itemize}
\item I logged in as root and set up the home directory for the daq account and set its password
\end{itemize}

\begin{verbatim}
ssh root@davme6
/usr/sbin/mkhomedir_helper daq
passwd daq
\end{verbatim}
\begin{itemize}
\item Change the root password while you're at it.
\end{itemize}

\begin{itemize}
\item Now you can log in as the daq user
\end{itemize}
\begin{verbatim}
ssh daq@davme6
\end{verbatim}
\end{block}
\end{frame}
\begin{frame}[label={sec:org482cf4b},fragile]{Fixes}
 \begin{block}{VTP Booting sometimes halts (fixed in rc6)}
\begin{itemize}
\item in serial debug connection, booting stops/halts at
\begin{verbatim}
[  OK  ] Reached target Local File Systems (Pre).
         Starting udev Kernel Device Manager...
[  OK  ] Started udev Kernel Device Manager.
[  OK  ] Started Dispatch Password Requests to Console Directory Watch.
[  OK  ] Reached target Paths.
[  OK  ] Found device /dev/ttyPS0.
\end{verbatim}
\end{itemize}
\begin{block}{Update \texttt{rhel-readonly.service}}
\begin{itemize}
\item Change the \texttt{/etc/systemd/system/rhel-readonly.service [Unit]} section to read:
\end{itemize}
\begin{verbatim}
[Unit]
Description=Configure read-only root support
DefaultDependencies=no
Conflicts=shutdown.target systemd-tmpfiles-setup.service
Before=shutdown.target emergency.service emergency.target local-fs.target systemd-random-seed.service
After=systemd-remount-fs.service
\end{verbatim}
\end{block}
\end{block}
\end{frame}
\end{document}
