diff options
author | Peter Palfrader <peter@palfrader.org> | 2015-02-18 15:38:15 +0100 |
---|---|---|
committer | Peter Palfrader <peter@palfrader.org> | 2015-02-18 15:38:15 +0100 |
commit | 41599461aa00610e1842fc72d8ac99812ace2edf (patch) | |
tree | 9e467279755db36cc96b3b48dc8029e93ebbb2ff | |
parent | b43a17f87d62ab2b03661c048bbe297acc980e6a (diff) |
Add install-VM-grongo
-rwxr-xr-x | install-VM-grongo | 417 | ||||
-rwxr-xr-x | ssh-co-dotfiles | 2 |
2 files changed, 419 insertions, 0 deletions
diff --git a/install-VM-grongo b/install-VM-grongo new file mode 100755 index 0000000..f3599e0 --- /dev/null +++ b/install-VM-grongo @@ -0,0 +1,417 @@ +#!/bin/bash + +# create a VM image using debootstrap +# +# Copyright 2013, 2014, 2015 Peter Palfrader <peter@palfrader.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You probably already have access to a copy of the GNU General Public +# License or you can find one on the Internet; if not, write to the +# copyright holder or to the Free Software Foundation, Inc., 59 Temple +# Place, Suite 330, Boston, MA 02111-1307 USA. + +set -e +set -u + +SUITE=jessie +hostlistfile=/root/VMs/host-list + +MIRROR=http://ftp.at.debian.org/debian +prefixlen=26 +gateway=213.235.231.193 +ip6prefix=2001:858:10f:100:: +ip6gateway=fe80:: +basedir=/srv/vmstore + +check_installed() { + local p + for p in "$@"; do + if ! dpkg -l "$p" 2>/dev/null | grep -q '^ii'; then + echo >&2 "Error: package $p not installed:" + echo >&2 " apt-get install $*" + exit 1 + fi + done +} +get_sshkey_fprs() { + local f + for f in etc/ssh/ssh_host*_key.pub; do + echo -n " " + ssh-keygen -l -f "$f" + done +} + +do_cleanup() { + #echo "Proposed cleanup:" + local cnt + cnt=$((${#cleanup[*]}-1)) + #for i in $(seq ${cnt} -1 0); do + # echo " ${cleanup[$i]}" + #done + #echo "Press enter to commence cleanup." + #read + for i in $(seq ${cnt} -1 0); do + echo "* ${cleanup[$i]}" + eval "${cleanup[$i]}" || true + done + echo "done." +} + +check_installed debootstrap debian-archive-keyring kpartx + +declare -a cleanup +cleanup+=(":") +trap do_cleanup EXIT + +echo -n "New VM's FQDN: " +if [ -n "${1:-}" ]; then echo "$1"; fqdn="$1"; shift; else read fqdn; fi +echo +guest="${fqdn%%.*}" +domainname="${fqdn#*.}" + +echo -n "Disk size: [10g]" +if [ -n "${1:-}" ]; then echo "$1"; disksize="$1"; shift; else read disksize; fi +disksize=${disksize:-10g} + +echo -n "Swap size: [4g]" +if [ -n "${1:-}" ]; then echo "$1"; swapsize="$1"; shift; else read swapsize; fi +swapsize=${swapsize:-4g} + +echo -n "Lvm size: [20g]" +if [ -n "${1:-}" ]; then echo "$1"; lvmsize="$1"; shift; else read lvmsize; fi +lvmsize=${lvmsize:-20g} +if [ "$lvmsize" = "0" ]; then lvmsize=""; fi + +echo -n "ipaddr: "; +if [ -n "${1:-}" ]; then echo "$1"; ipaddr="$1"; shift; else read ipaddr; fi + +echo -n "unique hostno (2-254): "; +if [ -n "${1:-}" ]; then echo "$1"; hostno="$1"; shift; else read hostno; fi + +if awk -v v="$hostno" '$1 == v {print}' "$hostlistfile" | grep .; then + echo >&2 "Host number $hostno already used in $hostlistfile." + exit 1 +fi +if awk -v v="$ipaddr" '$2 == v {print}' "$hostlistfile" | grep .; then + echo >&2 "IP address $ipaddr already used in $hostlistfile." + exit 1 +fi +if awk -v v="$fqdn" '$3 == v {print}' "$hostlistfile" | grep .; then + echo >&2 "FQDN $fqdn already used in $hostlistfile." + exit 1 +fi + +diskfileprefix="$basedir/$fqdn/" +if [ -e "$diskfileprefix" ]; then + echo >&2 "Error: Disk directory $diskfileprefix already exists." + exit 1 +fi + +target="/mnt/target-$guest" +if [ -e "$target" ]; then + echo >&2 "Error: Directory $target already exists." + exit 1 +fi + + +diskfileroot="${diskfileprefix}$guest-root" +diskfileswap="${diskfileprefix}$guest-swap" +diskfilelvm="${diskfileprefix}$guest-lvm" + +mkdir "$diskfileprefix" +(umask 077 && qemu-img create -f qcow2 "$diskfileroot" "$disksize") +(umask 077 && qemu-img create -f raw "$diskfileswap" "$swapsize") +if [ "$lvmsize" != "" ] ; then + (umask 077 && qemu-img create -f qcow2 "$diskfilelvm" "$lvmsize") +fi + +modprobe nbd max_part=63 + +rootdev=/dev/nbd0 +lvmdev=/dev/nbd1 + +qemu-nbd -c "$rootdev" "$diskfileroot" +cleanup+=("qemu-nbd -d '$rootdev'") + +if [ "$lvmsize" != "" ] ; then + qemu-nbd -c "$lvmdev" "$diskfilelvm" + cleanup+=("qemu-nbd -d '$lvmdev'") +fi + +if [ "$(head -c 65536 "$rootdev" | sha1sum | awk '{print $1}')" != "1adc95bebe9eea8c112d40cd04ab7a8d75c4f961" ]; then + echo -n "Warning: Disk appears to be not be empty. Continue anyway? [y/N] " + read ans + [ "$ans" = "y" ] || exit 0 +fi + +ip6addr="$ip6prefix$hostno:1" + +echo '2048,,L,*' | sfdisk -u S --Linux "$rootdev" +kpartx -v -p "-p" -a "$rootdev" -s +cleanup+=("kpartx -d -p '-p' -v '$rootdev'") +part1="/dev/mapper/$(basename $rootdev)-p1" +mkfs.ext4 "$part1" + +if [ "$lvmsize" != "" ] ; then + pvcreate "$lvmdev" + vgcreate "vg_$guest" "$lvmdev" +fi + +mkdir "$target" +cleanup+=("rmdir '$target'") +mount "$part1" "$target" +cleanup+=("umount '$target'") +cd "$target" +cleanup+=("cd /") + +debootstrap --variant=minbase --keyring=/usr/share/keyrings/debian-archive-keyring.gpg "$SUITE" . "$MIRROR" + +### Set up swap and fstab +mkswap "$diskfileswap" + +uuidroot=$(blkid -s UUID -o value ${part1}) && +uuidswap=$(blkid -s UUID -o value $diskfileswap) && +cat > etc/fstab << EOF +UUID=$uuidroot / ext4 errors=remount-ro 0 1 +UUID=$uuidswap none swap sw 0 0 +tmpfs /tmp tmpfs defaults,size=512m 0 0 +EOF + +### Set up basic networking stuff +echo "$guest" > etc/hostname +cat > etc/hosts << EOF +127.0.0.1 localhost +$ipaddr $fqdn $guest + +# The following lines are desirable for IPv6 capable hosts +::1 localhost ip6-localhost ip6-loopback +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters +ff02::3 ip6-allhosts +EOF +rm -fv etc/udev/rules.d/70-persistent-* +mkdir -p etc/udev/rules.d/ +touch etc/udev/rules.d/75-persistent-net-generator.rules + +cat > etc/network/interfaces << EOF +auto lo +iface lo inet loopback + +allow-hotplug eth0 +iface eth0 inet static + pre-up echo 0 > /proc/sys/net/ipv6/conf/\$IFACE/accept_ra + address $ipaddr/$prefixlen + gateway $gateway + +allow-hotplug eth1 +iface eth1 inet static + address 172.22.130.$hostno/23 +iface eth1 inet6 static + address $ip6addr/64 + gateway $ip6gateway + accept_ra 0 +EOF + +cat > etc/resolv.conf << EOF +nameserver 172.22.130.1 +search $domainname +EOF + +### A couple packages +mv etc/apt/sources.list etc/apt/sources.list.d/debian.list +echo "deb http://security.debian.org/ jessie/updates main" > etc/apt/sources.list.d/security.list +echo "deb $MIRROR jessie-updates main" > etc/apt/sources.list.d/updates.list +chroot . apt-get update +echo "Apt::Install-Recommends 0;" > etc/apt/apt.conf.d/local-recommends +chroot . apt-get install -y locales-all net-tools iproute ifupdown dialog vim netbase udev psmisc usbutils pciutils +chroot . apt-get install -y iputils-ping telnet bind9-host lvm2 +sed -i -e 's/issue_discards = 0/issue_discards = 1/' etc/lvm/lvm.conf + +### Set up kernel and bootloader +chroot . apt-get install -y linux-image-amd64 +DEBIAN_FRONTEND=noninteractive chroot . apt-get install -y grub2 + +! [ -e dev/sda ] +! [ -e dev/sda1 ] +cp -av `readlink -f "$rootdev"` dev/new-root +cp -av `readlink -f "$part1"` dev/new-root1 +chroot . grub-install --modules=part_msdos /dev/new-root +rm -v dev/new-root* + +cp -av `readlink -f "$rootdev"` dev/sda +cp -av `readlink -f "$part1"` dev/sda1 +rm -f boot/grub/device.map +sed -i -e 's/^GRUB_CMDLINE_LINUX=""$/GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8"/' etc/default/grub +cat >> etc/default/grub <<EOF +GRUB_TERMINAL="serial console" +GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1" +EOF +chroot . update-grub +rm -v dev/sda* + +rootpw="$(head -c 12 /dev/urandom | base64)" +echo "root:$rootpw" | chroot . chpasswd + +### install ssh +chroot . apt-get install -y ssh +sed -i -e "s/`hostname`\$/$guest/" etc/ssh/ssh_host*_key.pub +sshkeys="$(get_sshkey_fprs)" +rsahostkey="$(cat etc/ssh/ssh_host_rsa_key.pub)" +[ -e etc/ssh/ssh_host_ed25519_key.pub ] && ed25519hostkey="$(cat etc/ssh/ssh_host_ed25519_key.pub)" +mkdir -p root/.ssh +cp /root/.ssh/authorized_keys root/.ssh + +### unattended upgrades +chroot . apt-get install -y unattended-upgrades +cat > etc/apt/apt.conf.d/20auto-upgrades << EOF +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Unattended-Upgrade "1"; +EOF + +## trim +mkdir -p etc/cron.daily +tee > etc/cron.daily/local-trim-ext4 << 'EOF' +#!/bin/sh + +# by weasel + +for fs in `awk '$9 == "ext4" && $4 == "/" {print $5}' /proc/self/mountinfo`; do + fstrim "$fs" +done +EOF +chmod +x etc/cron.daily/local-trim-ext4 + +### first boot +cat > first-boot.sh << EOF +#!/bin/bash +set -e +sleep 10 +apt-get install -y acpi-support-base lldpd +apt-get install -y libpam-systemd dbus +apt-get install -y cron +apt-get install -y rsyslog +sed -i -e '/first-boot.sh/d' etc/rc.local +/etc/cron.daily/local-trim-ext4 +rm /first-boot.sh +(sleep 10 ; /sbin/reboot) & +disown %1 +EOF +chmod +x first-boot.sh +sed -i -e '$ i [ -x /first-boot.sh ] && /first-boot.sh' etc/rc.local + + +### clean up +chroot . apt-get clean + +# prepare virsh file +( : #) +cat << EOF +<domain type='kvm'> + <name>$guest</name> + <uuid>$(uuidgen)</uuid> + <memory unit='MiB'>2048</memory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.1'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <cpu mode='custom' match='exact'> + <model fallback='allow'>SandyBridge</model> + </cpu> + <clock offset='utc'> + <timer name='rtc' tickpolicy='catchup'/> + <timer name='pit' tickpolicy='delay'/> + <timer name='hpet' present='no'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <pm> + <suspend-to-mem enabled='no'/> + <suspend-to-disk enabled='no'/> + </pm> + <devices> + <emulator>/usr/bin/kvm</emulator> + <controller type='scsi' index='0' model='virtio-scsi'/> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' discard='unmap'/> + <source file='$diskfileroot'/> + <target dev='sda' bus='scsi'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw' discard='unmap'/> + <source file='$diskfileswap'/> + <target dev='sdb' bus='scsi'/> + </disk> +EOF +[ "$lvmsize" = "" ] || cat << EOF + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' discard='unmap'/> + <source file='$diskfilelvm'/> + <target dev='sdc' bus='scsi'/> + </disk> +EOF +cat << EOF + <interface type='bridge'> + <mac address='CC:7F:AE:65:$(printf "%02x" $hostno):01'/> + <source bridge='br-inet'/> + <virtualport type='openvswitch'/> + <model type='virtio'/> + </interface> + <interface type='bridge'> + <mac address='CC:7F:AE:65:$(printf "%02x" $hostno):02'/> + <source bridge='br-vmint'/> + <virtualport type='openvswitch'/> + <model type='virtio'/> + </interface> + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes'/> + <memballoon model='virtio'/> + </devices> +</domain> +EOF +) > "$diskfileprefix/$guest.xml" + +# and done +trap - EXIT +do_cleanup + +echo "$guest's root password is $rootpw" +echo "SSH host key fingerprints are:" +echo "$sshkeys" +echo "IP addresses:" +echo " $ipaddr" +echo " $ip6addr" +echo +echo "Maybe run" +echo " echo '$hostno' '$ipaddr' '$fqdn' >> '$hostlistfile'" +echo " virsh define '$diskfileprefix/$guest.xml' && rm '$diskfileprefix/$guest.xml'" +echo " virsh autostart '$guest'" +echo " virsh start '$guest'" +echo " virsh console '$guest'" +echo +echo ' for i in `/usr/local/sbin/vm_du_ suggest`; do ln -vsf /usr/local/sbin/vm_du_ /etc/munin/plugins/vm_du_$i; done' +echo ' service munin-node restart; sleep 3; service munin-async restart' diff --git a/ssh-co-dotfiles b/ssh-co-dotfiles index c59c9bf..e55e817 100755 --- a/ssh-co-dotfiles +++ b/ssh-co-dotfiles @@ -87,12 +87,14 @@ sXmB2EZXwPrgijgIFWpRTarioptI9NxNF4RtpAjH1dI1VtP9kybvYKSP+z3cniFL 4Q== -----END CERTIFICATE----- EOF + rm -f .gitconfig && cd .dotfiles && git remote set-url origin https://git2.palfrader.org/git/conf/dotfiles.git && git -c http.sslCAinfo="$HOME"/.git2.palfrader.org.crt -c http.sslCAPath="$HOME"/.nonexistent pull && git config --local --add http.sslCAinfo "$HOME"/.dotfiles/.certs/git2.palfrader.org.crt && git config --local --add http.sslCAPath "$HOME"/.nonexistent && rm -f .git2.palfrader.org.crt && + ./Link-Them && echo "Pulled with current cert."; fi ' |