{"id":11,"date":"2007-04-17T07:46:28","date_gmt":"2007-04-17T13:46:28","guid":{"rendered":"http:\/\/blogs.cae.tntech.edu\/mwr\/2007\/04\/17\/unattended-debian-installations-or-how-i-learned-to-stop-worrying-and-love-the-preseedcfg\/"},"modified":"2024-10-27T14:26:20","modified_gmt":"2024-10-27T14:26:20","slug":"unattended-debian-installations-or-how-i-learned-to-stop-worrying-and-love-the-preseedcfg","status":"publish","type":"post","link":"https:\/\/sites.tntech.edu\/renfro\/2007\/04\/17\/unattended-debian-installations-or-how-i-learned-to-stop-worrying-and-love-the-preseedcfg\/","title":{"rendered":"Unattended Debian Installations (or How I Learned to Stop Worrying and Love the preseed.cfg)"},"content":{"rendered":"<p>A CMR project recently bought 12 new Dell PowerEdge SC1435 servers to replace some of our aging compute cluster systems. In previous server rollouts, I&#8217;d generally get one system installed and configured, image it with SystemImager, and then PXE-boot the rest of the systems to pull that image. However, it&#8217;s tough to audit exactly what got installed, and how. It&#8217;s also arguably a waste of space to keep images of all the types of cluster systems we have (PowerEdge 2650, PowerEdge 1850, PowerEdge 1855, Dimension 9200, etc.). So enter <a href=\"http:\/\/d-i.alioth.debian.org\/manual\/en.i386\/apb.html\">Debian Preseeding<\/a>. With preseeding, I can make a text file that describes what packages I want installed, debconf configurations that vary from the default, how I want the partitioning done, copy configuration files from web or ftp servers to the target drive, etc. It took a few days to get going, but the long-term payoff should be enormous.<\/p>\n<p>The resulting installation timeline for a PowerEdge SC1435 (relative to power-on in HH:MM:SS):<\/p>\n<ul>\n<li>00:00:25 &#8211; Power-on self tests have completed enough to allow me to hit F12 for PXE boot.<\/li>\n<li>00:01:20 &#8211; Rest of power-on self tests have completed, PXE boot process starts. All installation parameters are passed in from the pxelinux.cfg file on the DHCP server or the preseed.cfg file on a nearby ftp server.<\/li>\n<li>00:04:50 &#8211; Base and standard task packages installed. openssh-server and puppet packages are installed. puppet defaults file is downloaded. System starts formatting a 500GB SATA drive for \/tmp space.<\/li>\n<li>00:08:20 &#8211; System finishes formatting \/tmp, and reboots since that was the last step of the unattended install.<\/li>\n<li>00:09:30 &#8211; System is at login prompt. Root password works. puppet will take over installing miscellaneous packages and other post-installation configuration tasks. Once puppet has finished copying over root@adminserver&#8217;s public key, I can log in from adminserver without being prompted for a password.<\/li>\n<\/ul>\n<p>Total number of keypresses from power-up to login: 1. Annotated preseed and pxelinux files after the jump.<\/p>\n<p><!--more--><br \/>\nPXELinux config file (amd64 version, i386 would be nearly identical &#8212; the contents of the &#8220;append&#8221; line should be all on one line. It&#8217;s broken here for readability.)<\/p>\n<pre>default preseed\nlabel preseed\nkernel debian-installer\/amd64\/linux\nappend initrd=debian-installer\/amd64\/initrd.gz ramdisk_size=10800 root=\/dev\/rd\/0 rw auto\n  url=http:\/\/REDACTED\/.\/preseed.cfg console-keymaps-at\/keymap=us locale=en_US interface=eth0\n  hostname=x domain=x netcfg\/dhcp_timeout=60 --\nprompt 1\ntimeout 1<\/pre>\n<p>Changes versus <a href=\"http:\/\/ftp.debian.org\/debian\/dists\/etch\/main\/installer-amd64\/current\/images\/netboot\/pxelinux.cfg\/default\">the default configuration<\/a>:<\/p>\n<ol>\n<li>Removed display command for splash screen. At one point, I was running out of parameter space on the append line, and removing &#8216;vga=normal&#8217; was one space saver. I didn&#8217;t expect the splash screen to work once that was removed, so I dumped it as well.<\/li>\n<li>Removed F1, F2, &#8230; , F9, F0 commands for online help. Optional.<\/li>\n<li>Changed &#8216;default install&#8217; to &#8216;default preseed&#8217;.<\/li>\n<li>Added preseed stanza, with default kernel, but much different append options.<\/li>\n<li>At the time I started this, the default pxelinux config file had entries for the ramdisk size and root device; these do not appear in the current Debian config file, and I&#8217;ll remove mine once I verify that they&#8217;re unneeded.<\/li>\n<li>Added append option &#8216;auto url=http:\/\/REDACTED\/.\/preseed.cfg&#8217; to define location of preseed configuration file.<\/li>\n<li>Added append options &#8216;console-keymaps-at\/keymap=us&#8217; and &#8216;locale=en_US&#8217; to define basic localization for the installation.<\/li>\n<li>Addd append options &#8216;interface=eth0&#8217;, &#8216;hostname=x&#8217;, &#8216;domain=x&#8217;, and &#8216;netcfg\/dhcp_timeout=60&#8217; to get the networking configured. The &#8216;hostname=x&#8217; and &#8216;domain=x&#8217; parameters were one of the last tricky bits. I had wrongly assumed that specifying that I&#8217;d be using DHCP to get my address would make it pass over asking for a hostname and domain. Preseeding dummy values for each gets past the questions, and DHCP overrides the dummy values as soon as the DHCP negotiation is done.<\/li>\n<li>Changed &#8216;timeout 0&#8217; to &#8216;timeout 1&#8217; to allow the installer to proceed without me manually selecting any configurations. Obviously, you may want to increase the timeout to some larger value if you need more time to hit a key to override something for testing.<\/li>\n<\/ol>\n<p>preseed.cfg (the contents of the &#8220;d-i preseed\/late_command&#8221; line should be all on one line. It&#8217;s broken here for readability.):<\/p>\n<pre>### References:\n###  http:\/\/d-i.alioth.debian.org\/manual\/en.amd64\/install.en.pdf\n###  http:\/\/d-i.alioth.debian.org\/manual\/example-preseed.txt\n###  http:\/\/www.hands.com\/d-i\/etch\/classes\/\n\n### This file needs to be at\n### http:\/\/REDACTED\/preseed.cfg and\n### referenced via boot arguments as\n### http:\/\/REDACTED\/.\/preseed.cfg\n\n### Generic settings applicable to all CAE Debian systems\n\nd-i debian-installer\/locale string en_US\nd-i console-tools\/archs select at\nd-i console-keymaps-at\/keymap select American English\nd-i debian-installer\/keymap string us\nd-i netcfg\/choose_interface select eth0\nd-i netcfg\/dhcp_timeout string 60\nd-i netcfg\/get_hostname string unassigned-hostname\nd-i netcfg\/get_hostname seen true\nd-i netcfg\/get_domain string unassigned-domain\nd-i netcfg\/get_domain seen true\nd-i netcfg\/dhcp_options select Retry network autoconfiguration\nd-i mirror\/codename string etch\nd-i mirror\/country string enter information manually\nd-i mirror\/http\/countries select enter information manually\nd-i mirror\/http\/directory string \/debian\/\nd-i mirror\/http\/hostname string ftp.cae.tntech.edu\nd-i mirror\/http\/proxy string\nd-i clock-setup\/utc boolean false\nd-i time\/zone string US\/Central\nd-i apt-setup\/security_host string\nd-i apt-setup\/local0\/repository string http:\/\/ftp.cae.tntech.edu\/debian-security etch\/updates main\n\n# XXX -- TEMPORARY HACK UNTIL WE GET A SIGNED LOCAL REPOSITORY\nd-i debian-installer\/allow_unauthenticated string true\n\nd-i passwd\/make-user boolean false\nd-i passwd\/root-password-crypted password $1$REDACTED\nd-i grub-installer\/only_debian boolean true\nd-i grub-installer\/with_other_os boolean true\ntasksel tasksel\/first multiselect standard\nd-i pkgsel\/include string puppet lsb-release openssh-server\nd-i finish-install\/reboot_in_progress note\n\npopularity-contest popularity-contest\/participate boolean false\n\n### Less generic settings\n\n# Partitioning:\n# sda1: 40-100MB for \/boot\n# sda2: majority of remaining space for \/\n# sda3: 64MB-(2*RAM) for swap\nd-i partman-auto\/disk string \/dev\/sda\nd-i partman-auto\/method string regular\nd-i partman-auto\/expert_recipe string \n  boot-root :: \n    40 50 100 ext3 \n      $primary{ } $bootable{ } \n      method{ format } format{ } \n      use_filesystem{ } filesystem{ ext3 } \n      mountpoint{ \/boot } \n    . \n    500 10000 1000000000 ext3 \n      method{ format } format{ } \n      use_filesystem{ } filesystem{ ext3 } \n      mountpoint{ \/ } \n    . \n    64 512 200% linux-swap \n      method{ swap } format{ } \n    .\nd-i partman\/confirm_write_new_label boolean true\nd-i partman\/choose_partition select Finish partitioning and write changes to disk\nd-i partman\/confirm boolean true\n\n# Some systems may vary on \/tmp -- many have separate disks for it\n# (\/dev\/sdb1), some may have a separate partition on the sda\n# drive. This needs to be split out into a system-specific file and\n# chained in via class tmp_on_sdb1\n# Only applicable for hosts with separate \/tmp disk on \/dev\/sdb1 --\n# PE1855 blades (ch226-11...-19), SC1435 servers (ch226-21...-32), old\n# ch208a\nd-i preseed\/late_command string wget -O \/target\/etc\/default\/puppet http:\/\/REDACTED\/puppet ; \n  wget -O \/target\/root\/caeftp_key.asc http:\/\/REDACTED\/caeftp_key.asc ;\n  in-target apt-key add \/root\/caeftp_key.asc ; echo ';' | sfdisk \/dev\/sdb ; mke2fs -j -q \/dev\/sdb1 ;\n  echo '\/dev\/sdb1 \/tmp ext3 defaults 0 2' &gt;&gt; \/target\/etc\/fstab; cp \/var\/log\/syslog \/target\/root<\/pre>\n<p>I&#8217;m not going to run through every change made in the preseed.cfg file, since the options are well-documented and what&#8217;s useful in one environment won&#8217;t necessarily translate to another. But I am mildly proud of the late_command at the end: this does two things that were minor pains on a normal preseed installation:<\/p>\n<ol>\n<li>Bootstraps a basic puppet defaults file over to the target drive. Grabbing \/etc\/default\/puppet from a remote site before rebooting makes sure that when puppetd starts up, that it can contact the central server for key signing, and work normally afterwards.<\/li>\n<li>Partitions and formats \/dev\/sdb to be my \/tmp directory. Debian-installer&#8217;s partman can&#8217;t partition more than one disk automatically, but each of these new systems had a second drive I had planned on using for \/tmp. <a href=\"http:\/\/www.linuxcommand.org\/man_pages\/sfdisk8.html\">Sfdisk<\/a> comes to the rescue. The input format description in the sfdisk man page indicates that if you give it a line with no values specified, it will make a partition from the first nonassigned sector to the maximum size, and set the ID to 83 for a Linux partition. So the first time I run this, I go from a drive with an empty partition table to one with a giant partition 1, exactly what I wanted. Subsequent times I run this, it should leave the partition table unmodified, which is also fine. I can&#8217;t find the original hint I found for this use of sfdisk.<\/li>\n<\/ol>\n<p>My \/etc\/default\/puppet is:<\/p>\n<pre>\n# Puppet doesn't like starting before it can contact the puppetmaster.\n# Wait up to 30 seconds before continuing.\n\nfor n in `seq 1 30`; do\n  ping -c 1 REDACTED &gt;&amp; \/dev\/null &amp;&amp; break\n  echo -n \" $n\"\n  sleep 1\ndone\nDAEMON_OPTS=\"--server REDACTED --factsync\"\n<\/pre>\n<p>You may be able to avoid putting in the 30-second sleep, but at one point, with some puppet version, it was helpful on DHCP-managed systems. The critical thing to override on Debian, though, is the <code>-w 0<\/code> flag in the default DAEMON_OPTS in \/etc\/init.d\/puppetd. Removing it ensures that puppetd will start up, contact the gold server for key signing, and wait for the signing to happen, rather than immediately exit.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A CMR project recently bought 12 new Dell PowerEdge SC1435 servers to replace some of our aging compute cluster systems. In previous server rollouts, I&#8217;d generally get one system installed and configured, image it with SystemImager, and then PXE-boot the rest of the systems to pull that image. However, it&#8217;s tough to audit exactly what &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/sites.tntech.edu\/renfro\/2007\/04\/17\/unattended-debian-installations-or-how-i-learned-to-stop-worrying-and-love-the-preseedcfg\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Unattended Debian Installations (or How I Learned to Stop Worrying and Love the preseed.cfg)&#8221;<\/span><\/a><\/p>\n","protected":false},"author":87,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,7,10],"tags":[],"class_list":["post-11","post","type-post","status-publish","format-standard","hentry","category-debian","category-infrastructures","category-linuxunix","entry"],"_links":{"self":[{"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/posts\/11","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/users\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/comments?post=11"}],"version-history":[{"count":1,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/posts\/11\/revisions"}],"predecessor-version":[{"id":509,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/posts\/11\/revisions\/509"}],"wp:attachment":[{"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/media?parent=11"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/categories?post=11"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/tags?post=11"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}