User:Jlo/Replacing Debian Jessie with Alpine remotely

From Alpine Linux
Jump to: navigation, search

I want to "upgrade" 200 remote Debian Jessie embedded boxes to AlpineLinux in run-from-ram mode. I have already successfully and happily validated the second stage as this is a minor variation around the "setup-ownbox" script I have added to a standard PXE apkovl. Those box are remotely sshable via openVPN. We need to keep network settings as is because some boxes have ad-hoc network config is restricted zones.

Stage 0

we need to prepare or a cache with reduced set of package or maybe some local repo with all needed packages needed for first stage and use that repo with no-cache option...

How_to_make_a_custom_ISO_image_with_mkimage

sh mkimage.sh --tag 3.6.2 --outdir ~/iso --arch x86_64 --repository http://my.own.repo/alpine/v3.6/main --profile jessie
profile_jessie() {
	profile_standard
	title="AL debian"
	desc="Packages included.
		Suitable for Local install script."
	apks="$apks openvpn wpa_supplicant wireless-tools"
	#apks="$apks linux-firmware"
}

==> alpine-jessie-3.6.2-x86_64.iso

Stage 1

prepare-jessie-for-alpine

#!/bin/sh
# this must be fully automatic
export DEBIAN_FRONTEND=noninteractive
apt-get -y install rsync extlinux
# /boot is a separate partition
rm -fr /boot/boot
ln -sf . /boot/boot
# let's get system file from our install server
cd /tmp
wget http://my.server.home/alpine/alpine-jessie-3.6.2-x86_64.iso
wget http://my.server.home/alpine/debian.apkovl.tar.gz
mount -o loop /tmp/alpine-jessie-3.6.2-x86_64.iso /mnt
rsync -a /mnt/ /boot/
sync 
umount /mnt
# prepare the config overlay
rm -fr /tmp/apkovl
mkdir /tmp/apkovl
tar xzf /tmp/debian.apkovl.tar.gz -C /tmp/apkovl
# keep current active network connection(s) and identity
cp /etc/hostname /tmp/apkovl/etc/
cp /etc/network/interfaces  /tmp/apkovl/etc/network/
cp -r /etc/openvpn /tmp/apkovl/etc/
cp -r /etc/ssh /tmp/apkovl/etc/
cd /tmp/apkovl
# be sure active VPN connections are preserved
mkdir -p /tmp/apkovl/etc/init.d
for v in /tmp/apkovl/etc/openvpn/*.conf ; do
  vn=$(basename $v|cut -d. -f1)
  ln -fs openvpn /tmp/apkovl/etc/init.d/openvpn.$vn
  ln -fs /etc/init.d/openvpn.$vn /tmp/apkovl/etc/runlevels/default/openvpn.$vn
done
# config done ; commit
tar czf /boot/$(hostname).apkovl.tar.gz .
# now the booltoader ; this will kill the active grub...
cat > /boot/extlinux.conf << EOF
timeout 20
prompt 1
default hardened
label hardened
    kernel /boot/vmlinuz-hardened
    initrd /boot/initramfs-hardened
    append alpine_dev=sda1:ext2 modloop=modloop-hardened modules=loop,cramfs,sd-mod,usb-storage,ext2 quiet
EOF
dd if=/usr/lib/syslinux/mbr/mbr.bin of=/dev/sda
extlinux -i /boot
# done
sync
reboot

usage:

~:# prepare-jessie-for-alpine

Stage 2

not tested yet in this procedure but used successfully (a small variant) to prepare new AL boxes.

setup-albox-from-debian

#!/bin/sh
BEGIN=$(date +%s)
name=$1
D=sda
echo "Manufacturing box named *${name}*..." 
rc-service modloop stop
umount /media/${D}* || (echo "Unable to unmount ${D}. Aborting..." ; exit 1)
### Partition the SSD $D
# f2fs want partition of type ext2 in parted
parted -a cylinder -s /dev/${D} -- \
 mklabel msdos                \
 mkpart primary fat32 0%  1%  \
 mkpart primary ext2  1%  2%  \
 mkpart primary ext2  2%  7%  \
 mkpart extended      7% 100% \
 mkpart logical ext2  7%  9%  \
 mkpart logical ext2  9% 15%  \
 mkpart logical ext2 15% 20%  \
 mkpart logical ext2 21% 22%  \
 mkpart logical ext2 22% 23%  \
 mkpart logical ext2 23% 24%  \
 mkpart logical ext2 24% 25%  \
 mkpart logical ext2 25% 26%  \
 mkpart logical ext2 26% 27%  \
 mkpart logical ext2 27% 28%  \
 mkpart logical ext2 28% 29%  \
 mkpart logical ext2 29% 30%  \
 set 1 boot on                \
 || exit 1
### prepare boot partition
mkfs.vfat /dev/${D}1 || exit 1
mkdir -p /media/${D}1
setup-bootable /media/${B} /dev/${D}1 || exit 1
mount -t vfat /dev/${D}1 /media/${D}1 || exit 1
### format partition to hold apkovl and apk/cache; it must be of ext? type
mkfs.ext4 -F -q /dev/${D}2 || exit 1
mkdir -p /media/${D}2
mount -t ext4 /dev/${D}2 /media/${D}2 || exit 1
### format remaining partitions with f2fs
for i in $(seq 3 16);do
  [ $i -eq 4 ] && continue
  mkfs.f2fs -q /dev/${D}$i || exit 1
  mkdir -p /media/${D}$i
  mount -t f2fs /dev/${D}$i /media/${D}$i || exit 1
done
### copy apkovl and apk/cache and stuff
rsync -azur --numeric-ids root@my.server.home:sda* /media/ || exit 1
### prepare new apkovl
rm -fr /tmp/template
mkdir -p /tmp/template
tar xzf /media/${S}2/$(hostname).apkovl.tar.gz -C /tmp/template || exit 1
rm /media/${D}2/$(hostname).apkovl.tar.gz
cd /tmp/template
rm -f etc/ssh/ssh_host_*
for f in $(grep -r $(hostname) etc 2> /dev/null | cut -d: -f1|sort -u);do sed -i -e s/$(hostname)/${name}/g $f;done
for f in $(grep -r ${S} etc 2> /dev/null | cut -d: -f1|sort -u);do sed -i -e s/${S}/${D}/g $f;done
echo "/dev/sdb2 /media/sdb2 ext4 ro,relatime,errors=continue,user_xattr,acl 0 2" > etc/fstab
# remaining partitions are for own stuff
# partition 4 is the extended one 
# (we maybe could just skip 3 and directly jump to extended for own stuff to simplify install script)
echo "/dev/sda3 /media/sda3 f2fs defaults,ro 0 2" >> etc/fstab
for i in $(seq 5 16);do echo "/dev/sda$i /media/sda$i f2fs defaults 0 2" >> etc/fstab;done
# partition 2 will hold apkovl and apk/cache
rm etc/apk/cache
ln -s /media/${D}2/cache etc/apk/cache
ln -s /etc/init.d/local etc/runlevels/default/local
tar czf /media/${D}2/${name}.apkovl.tar.gz . || exit 1
### done
sync
umount /media/${D}*
END=$(date +%s)
DURATION=$(($END-$BEGIN))
echo "Manufacture process took $DURATION seconds to complete." 
logger "Manufacture process took $DURATION seconds to complete." 
reboot

Usage:

~:# setup-albox-from-debian mynewbox