From: Ian Kelling Date: Wed, 18 Aug 2021 04:03:04 +0000 (-0400) Subject: Merge branch 'upstream' X-Git-Url: https://iankelling.org/git/?p=automated-distro-installer;a=commitdiff_plain;h=591c84435e22df12f2b5121c08578bff7c6bb047;hp=490334746631a6c956eee47947f3ab8f8a451666 Merge branch 'upstream' --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5e08dd9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/fai/config/class/51-multi-boot diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README b/README new file mode 100644 index 0000000..a1cb54d --- /dev/null +++ b/README @@ -0,0 +1,315 @@ +PXE install w multi-boot, btrfs & Libreboot support + +Some things are specific to my home network, and uses files with secrets +that are not in this repo. I use this for bare metal and vms, and two +scripts which can run post boot so I use them on vps distributed image +as well. + +Features people may find useful: installs encrypted trisquel, debian, +ubuntu, arch, and parabola (archlike install is likely broken, I've only +done pxe boots recently), in a multi-boot setup using multiple +subvolumes of a single btrfs filesystem. Utilizes multiple disks, with +scripts to automatically decrypt on intentional reboots, but not after +shutdown or power loss. + +Normal install mode for fai is using pxe, but on a libreboot system, +there is no pxe. The pxe in a normal computer is nonfree +firmware. Alternatives to normal pxe that I've tried: + +* libreboot + seabios + ipxe + +* Use a live cd to call pxe-kexec, this is described later in this file. + +* Use the fai autodiscover iso. This is more automated, so nicer. + +* Use an install method above to setup a gnu/linux disk partition that + coordinates with libreboot grub to acts like a pxe boot using + kexec. The boot process takes a bit longer than normal pxe. This is + the bootstrap partition in my scripts. + +Things I haven't tried: + +* The bios chip has enough room for an initrd. This could be setup to + work like the partition I use to kexec, but it would be faster, and + not require installing to disk. + +The partititioning and filesystem script is at +fai/config/hooks/partition.DEFAULT. Disks are grouped as ssd or hdd and +raided in raid 1 or raid 0 per configuration. The base partitions are +divided into boot, swap, and root, (only boot is unencrypted). There are +scripts to resize those partitions post-provision and while the system +is running. + +People who use fai may find these things as useful examples: it uses +dnsmasq (on a openwrt machine) for dhcp instead of the isc +dhcp. fai-wrapper is a small script to use basic fai classes outside of +fai. It does not use the fai partitioning tool, but the script is +inspired from it and works outside of fai. It supports running a fai +server on debian within android via Maru. + +It also automates configuration of an openwrt router after manual +initial installation. + +After provisionining is done, I sync files using btrfs, or unison for +vps, then automate further setup using a different set of scripts, +https://iankelling.org/git/?p=distro-setup;a=tree. + +My network is a wndr3700v2 router with openwrt on it and a few pcs/laptops. + +Since fai requires a debian server as the fai server, there are also +scripts to automate a debian install using pxe and preseeding, which can +be done from any distro. + +Some of the scripts have dependencies for some simple obvious utility +scripts from https://iankelling.org/git, and of course there are some +hostnames that are specific to my network. + + +# Per-host/install configuration + +Before doing a fai install, you will need to populate a class file. I +use one called 51-multi-boot, which you can see example of in +fai/config/class/50-host-classes. + + + +Before doing a fai install, you will need to populate /q/root/luks and +/q/root/shadow, see their references. You might also want to copy +existing /etc/ssh/*host* to +/p/c/machine_specific/HOST/filesystem/etc/ssh + +host-* luks keyfiles generated like: +head -c 2048 /dev/urandom | od | s dd of=/q/root/luks/host-demohost + +Configuration of which luks key to use is in +fai/config/hooks/partition.DEFAULT + +Configuration of which (if any) shadow file to use is in +fai/config/distro-install-common/end +and which shadow file / luks file(s) to copy into the new machine depends +on fai-redep arguments. + +# Scripts (meant to be used directly): + + +# Setup the environment for the install + +# create tiny autodiscover cd +# todo: with fai-revm at least, this complains about missing vmlinuz. need to fix this. +fai-redep && sudo fai-cd -g $PWD/grub.cfg.autodiscover -f -A $BASEFILE_DIR/autodiscover.iso +# create normal fai cd (replace TARGET_HOSTNAME) +fai-redep -t TARGET_HOSTNAME && sudo fai-cd -M -g $PWD/grub.cfg.netinst-noreboot -f $BASEFILE_DIR/netinst.iso +# note, may need to set hostname, depending on config, +# and some other things for environment not on your lan +# for example see fai/config/class/LINODE.var. See linode notes below. + +mymk-basefile # Create basefiles for various distros +archlike-pxe # Setup pxe boot server from an archlike base image +fai-redep # Deploy fai configuration to host "faiserver" +faiserver-uninstall # uninstall fai-server +faiserver-setup # install fai-server on the current machine +myfai-chboot # setup fai tftp and nfs. useful for doing pxe-kexec +pxe-server # disable/enable pxe dhcp, tfp, and nfs. calls myfai-chboot +wrt-setup # setup my router in general: dhcp, dns, etc. + + +# Script to do a distro install + +faiserver-revm # using pxe & preseed, create a vm which is a fai server +dsfull # install & post-install a new fai distro +arch-init-remote # install arch after it's been booted into it's setup env +live-kexec # Kexec this or a remote machine using host faiserver. also + useful to run as curl live-kexec|bash + + +# Test scripts + +arch-revm # test arch install on a fresh vm +fai-revm # test fai install on a fresh vm + + +# Scripts to call after a distro install for various reasons + +chboot # Set grub to boot into a different distro (installed earlier) +install-chboot # reinstall chboot to /boot subvols, for chboot updates. +eboot # reboot without automatic disk decryption +fai-wrapper # use fai classes outside of fai. sourced, not called. +faiserver-disable # Disable the fai nfs server exports +fresize # resize swap or boot partitions in a host + + +# Replacing a raid 10 disk + +# i expect better results with newer kernel and btrfs progs than the default stretch +fai-server buster + +pxe-server -S HOST fai + +# btrfs replace or delete. prefer replace. to setup partitions on replacement drive: +scp fai-wrapper HOST: +ssh root@HOST +. fai-wrapper +export SPECIAL_DISK=/dev/REPLACEMENT_DEV +/var/lib/fai/config/hooks/partition.DEFAULT + + +ssh root@HOST +for x in /target/* /target; do umount $x; done +cat >p +PASSWORD HERE(ctrl-d ctrl-d) +cd /dev/disk/by-id/ +for d in ata*part1; do cryptsetup luksOpen -d /root/p $d crypt_dev_$d; done +x=(/dev/mapper/*part1); mount -o subvol=root_trisquelflidas $x /mnt +# btrfs fi show /mnt +# btrfs replace start -f /dev/mapper/OLD_DEV /dev/mapper/NEW_DEV /mnt +# btrfs replace status /mnt +# nohup btrfs dev delete /dev/sde1 /mnt +mount -o subvol=boot_trisquelflidas /dev/sda3 /mnt/boot +# also replace or delete disk for boot +for x in dev proc sys; do mount -o bind /$x /mnt/$x; done +chroot /mnt /bin/bash +# replace disk in fstab +# replace disk in /etc/crypttab +update-grub +update-initramfs -u +mount /a +/a/exe/keyscript-on +exit +reboot + + +# Expected output in fai logs + +On focal, +fai.log:updatebase.UBUNTU FAILED with exit code 1. +the real error is dpkg-reconfigure locales, seems to be related +to a workaround for < 20.04, relevant comment: +# in case the locales are already included inside the base file (Ubuntu) +in config/hooks/instsoft.DEBIAN + + +For flidas, when installing systemd, this error happens, and it's +a superflous upstream bug based on reading the post install script: + +addgroup: The group `systemd-journal' already exists as a system group. Exiting. +Operation failed: No such file or directory + +On nabia/newer, python is removed, now its python3, +and its easier to just let the package get removed than +do host class package config. +fai.log:WARNING: These unknown packages are removed from the installation list: python python-minimal + +Similar to python, linux-image-amd64 is the debian package name +for the kernel, linux-image-generic is for ubuntu, but the +DEBIAN class is defined on ubuntu and its easier to just let +the package get removed with this warning: +fai.log:WARNING: These unknown packages are removed from the installation list: linux-image-amd64 +Also, cryptsetup-initramfs is new to buster/nabia, it gets removed +on earlier versions. + + +# linode notes + +* create 2 disks, installer (3000 mb, raw), boot (remaining, raw) +* create 2 profiles w direct boot, no helpers: + * installer (sda=boot, sdb=installer, boot dev=sdb) + * boot (sda=boot) +* Boot into rescue mode, ssh in with lish, + curl url_to_some_fai_cd_created_image | dd of=/dev/sda + poweroff +* boot into installer. +* Lish shows console, at the end of install, it gives prompt because + logs failed to save remotely, check the logs, then reboot into boot + profile if all is well. If that doesn't happen, turn off lassie in + settings. + + +# ubuntu notes + +For someone who really needed ubuntu on host tp, otherwise they would +end up on a non-gnu os, and I didn't want to figure out how to get all +the default software installed, I did the following: + +# On remote host: +# install etiona +cd /b/fai +# set 51-multi-boot to set classes outside of fai-wrapper conditional, including NOWIPE +. fai-wrapper +./fai/config/hooks/partition.DEFAULT + +# on remote host +# install ubuntu 20.04 using virt-install +sudo -i +virt-install --os-variant=ubuntu16.04 --cdrom ubuntu-20.04-desktop-amd64.iso --disk path=u2004.qcow2 -r 2048 --vcpus 1 -n u2004 +qemu-img create -o preallocation=metadata -f qcow2 u2004.qcow2 15G +# alternatively, also tried a physical install, because I know the virtual install ends up +# with some differen things, like some spice service. then pulled the data out with +rsync -ahSAX --numeric-ids --exclude=proc --exclude=sys --exclude=dev --exclude=tmp --exclude=run root@tp:/ .; mkdir proc sys dev tmp + +modprobe nbd +qemu-nbd --connect=/dev/nbd0 u1804.qcow2 -f qcow2 +qemu-nbd --connect=/dev/nbd0 u2004.qcow2 -f qcow2 +mount /dev/nbd0p1 /mnt/1 # bionic +mount /dev/nbd0p5 /mnt/1 # focal +mount -o bind /mnt/root/root_ubuntubionic /mnt/2 +mount -o bind /mnt/root/root_ubuntufocal /mnt/2 +mkdir -p /mnt/2/boot +mount -o bind /mnt/boot/boot_ubuntubionic /mnt/2/boot +mount -o bind /mnt/boot/boot_ubuntufocal /mnt/2/boot +# S = sparse, A = acls, X = xattrs +rsync -ahSAX --numeric-ids /mnt/1/ /mnt/2 + +cd /mnt/2 +cp /tmp/fai/crypttab etc +sed -i "s#/root/keyscript,#decrypt_keyctl,#" etc/crypttab +cp /tmp/fai/fstab etc +echo "tmpfs /tmp tmpfs nodev,nosuid,size=50%,mode=1777 0 0" >> etc/fstab +chrbind +chroot . +mv /etc/resolv.conf /etc/resolv.conf.old +echo nameserver 1.1.1.1 >/etc/resolv.conf +# install programs from /a/bin/fai/fai/config/package_config/STANDARD: +apt install -y openssh-client openssh-server cryptsetup keyutils btrfs-progs console-setup kbd pciutils usbutils unattended-upgrades initramfs-tools-core dropbear-initramfs +mv /etc/resolv.conf.old /etc/resolv.conf +exit +d=etc/initramfs-tools +mkdir -p $d/root/.ssh etc/dropbear-initramfs root/.ssh +chmod 700 $d/root $d/root/.ssh root/.ssh +cp -p /root/.ssh/authorized_keys $d/root/.ssh/authorized_keys +cp -p /root/.ssh/authorized_keys etc/dropbear-initramfs +cp -p /root/.ssh/authorized_keys root/.ssh/authorized_keys +chroot . +sed -ri 's/^ *GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="rd.luks.crypttab=no"/' /etc/default/grub +grub-install --no-floppy $(grub-probe -tdrive -d /dev/sda) +update-grub +grub-bios-setup -d /boot/grub/i386-pc -s /dev/sda +exit +umount proc +umount dev +umount sys +reboot + +# pine rock64 notes +# the only useful image is ubuntu 18.04 ayafun or something. +# using emmc usb: +s mount /dev/sdb7 /mnt/1 +s cp `which qemu-arm-static` /mnt/1/usr/bin +s chroot /mnt/1 qemu-arm-static /bin/bash +usermod --login iank --move-home --home /home/iank rock46 +groupmod --new-name iank rock64 +passwd iank +# boot it +s apt-get update +s apt dist-upgrade + + +# TODO +Change arch to archlike and to support arch and parabola + + +# License + +The license for the project is GPLv2 or later, mostly because fai is and +I periodically merge the upstream example config, which contains small +scripts. Also, there is a modified encrypt.upstream, which is from the +cryptsetup package in arch, which is under the same license. diff --git a/arch-init b/arch-init new file mode 100755 index 0000000..2f14ad6 --- /dev/null +++ b/arch-init @@ -0,0 +1,114 @@ +#!/bin/bash -x +# Copyright (C) 2016 Ian Kelling + +# 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 should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +x="$(readlink -f "$BASH_SOURCE")"; source "${x%/*}/bash-trace" +cd ${x%/*} + +export HOSTNAME="$1" +mirror=$2 + +(( $# >= 1 )) || { echo "$0: error: need 1 or 2 arguments"; exit 1; } + +rm -f /etc/pacman.d/mirrorlist +# https://wiki.archlinux.org/index.php/Mirrors#Sorting_mirrors + +if [[ $mirror ]]; then + echo "Server = $mirror" >> /etc/pacman.d/mirrorlist +fi +curl -s 'https://www.archlinux.org/mirrorlist/?country=US&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on' | + sed -r 's/^[ #]*(Server *=)/\1/' >> /etc/pacman.d/mirrorlist + +. /a/bin/fai/fai-wrapper +export LUKS_DIR=/root/luks +export DISTRO=arch +partition_script=/a/bin/fai/fai/config/hooks/partition.DEFAULT +chmod +x $partition_script + +export PARTITION_PROMPT=true + +# to be idempotent if we fail after partitioning +already_partitioned=true +mount_out=$(mount) +for dir in /mnt{,/home,/boot,/a}; do + regex=" on $dir " + if [[ ! $mount_out =~ $regex ]]; then + already_partitioned=false + break + fi +done + +if ! $already_partitioned; then + /a/bin/fai/fai/config/hooks/partition.DEFAULT +fi + +. /tmp/fai/disk_var.sh + + +# arch doesn't need crypttab entries for initramfs crypt partititions +export rootn=1 +export bootn=3 +export swapn=2 +export BOOT_DEVICE +export ROOT_PARTITIONS +sed -ri --follow-symlinks "/^crypt_dev_\S+$rootn /d" /tmp/fai/crypttab + +if ! $already_partitioned; then + mount -o subvol=root_$DISTRO $ROOT_PARTITION /mnt + mkdir -p /mnt/boot + mount -o subvol=boot_$DISTRO $BOOT_PARTITION /mnt/boot +fi + +# https://wiki.archlinux.org/index.php/Dm-crypt/Device_encryption#Keyfiles +cp /root/luks/host-$HOSTNAME /mnt/crypto_keyfile.bin +chmod 600 /mnt/crypto_keyfile.bin + + +if [[ $mirror ]]; then + echo "$0: 404 errors about core.db etc are normal, +they will succeed using the secodary mirror" +fi +pacstrap /mnt base +cp /tmp/fai/{fstab,crypttab} /mnt/etc +cp /a/bin/fai/encrypt /mnt/usr/lib/initcpio/hooks + +cp -r /root/.ssh /mnt/root + +bindmount() { + local mountpoint=$2 + local source=$1 + mkdir -p $mountpoint + mount -o bind $source $mountpoint +} +bindmount /root/shadow /mnt/q/root/shadow +bindmount /a /mnt/a + +mkdir -p /mnt/etc/ssh +cp /etc/ssh/ssh_host_* /mnt/etc/ssh + +cp /a/bin/fai/arch-init-chroot /mnt/root +# for manual commands, arch-chroot /mnt bash +arch-chroot /mnt /root/arch-init-chroot + +# this gets mounted in chroot so we have to do it outside +rm -f /mnt/etc/resolv.conf +ln -s /run/systemd/resolve/resolv.conf /mnt/etc/resolv.conf + +# not necsesary, but makes reboot go fast. +umount -R /mnt; sleep 1 + +# causes 255 exit code, so doing this from the caller script. +# reboot now diff --git a/arch-init-chroot b/arch-init-chroot new file mode 100755 index 0000000..e173863 --- /dev/null +++ b/arch-init-chroot @@ -0,0 +1,169 @@ +#!/bin/bash -x +# Copyright (C) 2016 Ian Kelling + +# 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 should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + +# note, when I did genfstab, i +# neeeded to to do for x in mv /etc/*.pacorig; do mv $x ${x%.pacorig}; done + +pacman -Syu + +[[ -L /etc/localtime ]] || ln -s /usr/share/zoneinfo/America/Los_Angeles /etc/localtime +l=en_US.UTF-8 +echo "$l UTF-8" > /etc/locale.gen +locale-gen +echo "LANG=$l" > /etc/locale.conf +# if coming from windows, and you had to set the time, do this +# hwclock --systohc --utc + +# A password is required to access the volume: +# Command requires device and ampped name as arguments + +# If we were using btrfs raid, we supposedly would need this. +# # add btrfs as module instead of hook due to +# # https://wiki.archlinux.org/index.php/Btrfs, +# # https://bugs.archlinux.org/task/42884 +# # disabled, as with just the module, startup spammed something about +# # command takes a device name and something else. +# sed -ri --follow-symlinks '/^ *MODULES *=.*btrfs/!s/^( *MODULES *=.*)"/\1 btrfs"/' /etc/mkinitcpio.conf +# # remove extra space +# sed -ri --follow-symlinks 's/^( *MODULES *=[^"]*)" */\1"/' /etc/mkinitcpio.conf + + + + +# for desktop without full fs encryption, use this: +#cat > /etc/crypttab <<'EOF' +#tmp /dev/lvm/tmp /dev/urandom tmp,cipher=aes-xts-plain64,size=256 + +# otgherwise ERROR: file not found: `fsck.btrfs' +pacman -S --noconfirm btrfs-progs + +pacman -S --noconfirm grub gptfdisk + + +shopt -s extglob +echo "$0: fstab:" +cat /etc/fstab +# https://wiki.archlinux.org/index.php/Dm-crypt/System_configuration#Boot_loader +# if cryptdevice was lvm, it woulde be in this format, +# where x2-vg is from lvdisplay, VG Name field. +# cryptdevice=/dev/disk/by-uuid/585dff23-136f-446f-815f-01053b70c957:x2-vg +# but, if you are using your own fstab, it seems you just give it a name, +# which will be the crypt device name under /dev/mapper/ +# https://wiki.archlinux.org/index.php/GRUB#Additional_arguments + + +root_devs=( ${ROOT_PARTITIONS} ) +first_root_dev=${root_devs[0]} + + +k_args=( + cryptdevices=${ROOT_PARTITIONS// /,} + root=/dev/mapper/crypt_dev_${first_root_dev##*/} + resume=${first_root_dev%[0-9]}$swapn +) + + +# If we have more than 1 to decrypt, arch wiki lead me onto +# a sort of hacky way run the encrypt hook multiple times. + +# https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system#Configuring_mkinitcpio_2 +# used to have lvm2 after encrypt for lvm, but not using lvm anymore +for x in encrypt btrfs; do + sed -ri --follow-symlinks -f - /etc/mkinitcpio.conf < /etc/systemd/network/wired.network < /etc/systemd/network/br0.network < /etc/systemd/network/br0.netdev <&2' ERR + +usage() { + cat < /tmp/myarchlikeinit.log +if ! ip a | grep '^ *inet ' | grep -vF 127.0.0.1; then + cat <<'eof' +We don't have an ipv4 address. Maybe arch doesn't do that for us, +or we are probably using an ethernet port +which is not the 1st one, so we haven't automatically done dhcpcd, +so let's do it on whatever interface has a carrier +eof + for f in /sys/class/net/*; do + if [[ `cat $f/carrier` == 1 ]]; then + echo $0: running: dhcpcd ${f##*/} + dhcpcd ${f##*/} + break + fi + done +fi +systemctl start sshd diff --git a/archlike-pxe b/archlike-pxe new file mode 100755 index 0000000..db05bf9 --- /dev/null +++ b/archlike-pxe @@ -0,0 +1,91 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +# 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 should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Setup arch pxe boot server from the base image. +# +if [[ -s ~/.bashrc ]];then . ~/.bashrc;fi + +usage() { + cat < airootfs.md5; popd + +# seems if you've done a pxe boot, mounted the nfs, +# then shutdown, it's still busy. +ssh cmc "/etc/init.d/nfsd stop; \ +umount /run/archiso/bootmnt; \ +umount /run/parabolaiso/bootmnt; \ +rm -rf /mnt/usb/$idir" + +scp -r $idir wrt:/mnt/usb +ssh wrt "cd /mnt/usb && rm -f tftpboot && ln -s $idir tftpboot" + +# The default settings in the installer expect to find the NFS at /run/archiso/bootmnt + +# background: great documentation at +# https://wiki.archlinux.org/index.php/PXE +# arch can do netboot like ubuntu etc, but the docs look a little +# complicated, so fuck it, we use nfs cuz it's easy + +rm -rf $idir +sudo rm -rf squashfs-root diff --git a/bash-trace b/bash-trace new file mode 120000 index 0000000..015ae24 --- /dev/null +++ b/bash-trace @@ -0,0 +1 @@ +fai/config/files/boot/bash-trace/DEFAULT \ No newline at end of file diff --git a/bind/db.0.2.10.in-addr.arpa b/bind/db.0.2.10.in-addr.arpa new file mode 100644 index 0000000..522be5a --- /dev/null +++ b/bind/db.0.2.10.in-addr.arpa @@ -0,0 +1,23 @@ +; -*- zone -*- +$TTL 30 +@ IN SOA cmc.b8.nz. postmaster.iankelling.org. ( + 2021030716 ; serial + 1d 1d 4w 1M ; refresh retry expire minimum + ) +@ NS cmc.b8.nz. +;; systemd overrides 1 with _gateway, when its the gateway. laaame. +1 PTR cmc.b8.nz. +2 PTR kd.b8.nz. +3 PTR sy.b8.nz. +4 PTR wrt2.b8.nz. +5 PTR x2.b8.nz. +6 PTR x2w.b8.nz. +7 PTR syw.b8.nz. +8 PTR amy.b8.nz. +9 PTR bb8.b8.nz. +12 PTR demohost.b8.nz. +14 PTR wrt3.b8.nz. +19 PTR brother.b8.nz. +23 PTR amyw.b8.nz. +25 PTR hp.b8.nz. +;; todo: add transmission diff --git a/bind/named.conf b/bind/named.conf new file mode 100644 index 0000000..91f58fd --- /dev/null +++ b/bind/named.conf @@ -0,0 +1,114 @@ +// This is the primary configuration file for the BIND DNS server named. + +// deploy with: +// named-checkconf named.conf && named-checkzone 0.2.10.in-addr db.0.2.10.in-addr.arpa && scp named.conf db.0.2.10.in-addr.arpa 10.2.0.1:/etc/bind; ssh 10.2.0.1 /etc/init.d/named restart + + +options { + + listen-on { localnets; localhost; }; + listen-on-v6 { localnets; localhost; }; + directory "/tmp"; + + // If your ISP provided one or more IP addresses for stable + // nameservers, you probably want to use them as forwarders. + // Uncomment the following block, and insert the addresses replacing + // the all-0's placeholder. + + + auth-nxdomain no; # conform to RFC1035 +}; + +#acl trusted { 10.2.0.7; 10.2.0.3; 10.2.0.2; }; +acl "trusted" { 10.2.0.7; }; +view "trusted" { + match-clients { "trusted"; }; + forwarders { + 1.1.1.1 ; + 1.0.0.1 ; + 2606:4700:4700::1111 ; + 2606:4700:4700::1001 ; + }; + forward only ; + + // prime the server with knowledge of the root servers + zone "." { + type hint; + file "/etc/bind/db.root"; + }; + + // be authoritative for the localhost forward and reverse zones, and for + // broadcast zones as per RFC 1912 + + zone "localhost" { + type master; + file "/etc/bind/db.local"; + }; + + zone "127.in-addr.arpa" { + type master; + file "/etc/bind/db.127"; + }; + + zone "0.in-addr.arpa" { + type master; + file "/etc/bind/db.0"; + }; + + zone "255.in-addr.arpa" { + type master; + file "/etc/bind/db.255"; + }; + + zone "0.2.10.in-addr.arpa" { + type master; + file "/etc/bind/db.0.2.10.in-addr.arpa"; + }; +}; + + +acl "guest" { localnets; localhost; }; +view "guest" { + match-clients { "guest"; }; + + forwarders { + 1.1.1.3 ; + 1.0.0.3 ; + 2606:4700:4700::1113 ; + 2606:4700:4700::1003 ; + }; + forward only ; + // prime the server with knowledge of the root servers + zone "." { + type hint; + file "/etc/bind/db.root"; + }; + + // be authoritative for the localhost forward and reverse zones, and for + // broadcast zones as per RFC 1912 + + zone "localhost" { + type master; + file "/etc/bind/db.local"; + }; + + zone "127.in-addr.arpa" { + type master; + file "/etc/bind/db.127"; + }; + + zone "0.in-addr.arpa" { + type master; + file "/etc/bind/db.0"; + }; + + zone "255.in-addr.arpa" { + type master; + file "/etc/bind/db.255"; + }; + + zone "0.2.10.in-addr.arpa" { + type master; + file "/etc/bind/db.0.2.10.in-addr.arpa"; + }; +}; diff --git a/bind/named.conf.upstream b/bind/named.conf.upstream new file mode 100644 index 0000000..ca52cb8 --- /dev/null +++ b/bind/named.conf.upstream @@ -0,0 +1,45 @@ +// This is the primary configuration file for the BIND DNS server named. + +options { + directory "/tmp"; + + // If your ISP provided one or more IP addresses for stable + // nameservers, you probably want to use them as forwarders. + // Uncomment the following block, and insert the addresses replacing + // the all-0's placeholder. + + // forwarders { + // 0.0.0.0; + // }; + + auth-nxdomain no; # conform to RFC1035 +}; + +// prime the server with knowledge of the root servers +zone "." { + type hint; + file "/etc/bind/db.root"; +}; + +// be authoritative for the localhost forward and reverse zones, and for +// broadcast zones as per RFC 1912 + +zone "localhost" { + type master; + file "/etc/bind/db.local"; +}; + +zone "127.in-addr.arpa" { + type master; + file "/etc/bind/db.127"; +}; + +zone "0.in-addr.arpa" { + type master; + file "/etc/bind/db.0"; +}; + +zone "255.in-addr.arpa" { + type master; + file "/etc/bind/db.255"; +}; diff --git a/chboot b/chboot new file mode 120000 index 0000000..b311a15 --- /dev/null +++ b/chboot @@ -0,0 +1 @@ +fai/config/files/boot/chboot/DEFAULT \ No newline at end of file diff --git a/chost b/chost new file mode 100755 index 0000000..a26529f --- /dev/null +++ b/chost @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +# chost: get canonical hostname + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + +host=$1 +# ||: because if we are using 2+ resolvers, 1 may fail, causing error, but we still get +# a valid address and we just use that +addr=$(host $host | sed -rn 's/^\S+ has address //p;T;q' ||:) +h=$(host $addr) +h=${h##* } +echo $h diff --git a/debian-preseed b/debian-preseed new file mode 100755 index 0000000..e3df0dc --- /dev/null +++ b/debian-preseed @@ -0,0 +1,144 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + +usage() { + cat <>$preseed + ;; + debian-jessie) + wget -q https://www.debian.org/releases/jessie/$preseed + wget -qN http://ftp.nl.debian.org/debian/dists/jessie/$neboot_path + cat >>$preseed <<'EOF' +tasksel tasksel/first multiselect ssh-server +EOF + if ! $interactive_partition; then + cat >>$preseed <> $preseed <> $preseed <> /home/$user/.ssh/authorized_keys"; \ +in-target chown -R $user:$user /home/$user; \ +in-target chmod -R go-rwx /home/$user/.ssh/authorized_keys; \ +in-target cp -r /home/$user/.ssh /root; \ +in-target usermod -a -G sudo $user; +EOF diff --git a/debian-pxe-preseed b/debian-pxe-preseed new file mode 100755 index 0000000..aaef9a6 --- /dev/null +++ b/debian-pxe-preseed @@ -0,0 +1,46 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +# 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 should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# WARNING: outdated! needs docs and update to debian-stretch + +x="$(readlink -f "$BASH_SOURCE")"; source "${x%/*}/bash-trace" + +[[ $EUID == 0 ]] || exec sudo "$BASH_SOURCE" "$@" + +src=$(readlink -f "${BASH_SOURCE%/*}") + +e() { echo "$*"; "$@"; } + +mount_dir=$(mktemp -d) + +err-cleanup() { cd; umount -f $mount_dir; } +e mount -o users cmc:/mnt/usb $mount_dir + + +cd $mount_dir +e rm -rf debian-wheezy +mkdir debian-wheezy +cd debian-wheezy +e $src/debian-preseed "$@" # my script +cd .. +e rm -f tftpboot +e ln -s debian-wheezy tftpboot + +cd / +e umount $mount_dir +e $src/pxe-server default plain # my script diff --git a/devbyid b/devbyid new file mode 120000 index 0000000..9a02442 --- /dev/null +++ b/devbyid @@ -0,0 +1 @@ +fai/config/distro-install-common/devbyid \ No newline at end of file diff --git a/dsfull b/dsfull new file mode 100755 index 0000000..709ddab --- /dev/null +++ b/dsfull @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [[ -s ~/.bashrc ]];then . ~/.bashrc;fi + +reboot=true +if [[ $1 == -r ]]; then + reboot=false + shift +fi + +usage() { + cat </dev/null 2>&1 + [ "${quiet}" = "y" ] && CSQUIET=">/dev/null" + + # Get keyfile if specified + ckeyfile="/crypto_keyfile.bin" + if [ -n "$cryptkey" ]; then + IFS=: read ckdev ckarg1 ckarg2 </dev/null 2>&1 + umount /ckey + ;; + *) + # Read raw data from the block device + # ckarg1 is numeric: ckarg1=offset, ckarg2=length + dd if="$resolved" of="$ckeyfile" bs=1 skip="$ckarg1" count="$ckarg2" >/dev/null 2>&1 + ;; + esac + fi + [ ! -f ${ckeyfile} ] && echo "Keyfile could not be opened. Reverting to passphrase." + fi + + for cryptdev in ${cryptdevices//,/ }; do + cryptname=crypt_dev_${cryptdev##*/} + + if [ -n "${cryptoptions}" ]; then + cryptargs="${cryptargs} --allow-discards" + fi + for cryptopt in ${cryptoptions//,/ }; do + case ${cryptopt} in + no-allow-discards) + cryptargs="" + ;; + *) + echo "Encryption option '${cryptopt}' not known, ignoring." >&2 + ;; + esac + done + + if resolved=$(resolve_device "${cryptdev}" ${rootdelay}); then + if cryptsetup isLuks ${resolved} >/dev/null 2>&1; then + dopassphrase=1 + # If keyfile exists, try to use that + if [ -f ${ckeyfile} ]; then + if eval cryptsetup --key-file ${ckeyfile} open --type luks ${resolved} ${cryptname} ${cryptargs} ${CSQUIET}; then + dopassphrase=0 + else + echo "Invalid keyfile. Reverting to passphrase." + fi + fi + # Ask for a passphrase + if [ ${dopassphrase} -gt 0 ]; then + echo "" + echo "A password is required to access the ${cryptname} volume:" + + #loop until we get a real password + while ! eval cryptsetup open --type luks ${resolved} ${cryptname} ${cryptargs} ${CSQUIET}; do + sleep 2; + done + fi + if [ -e "/dev/mapper/${cryptname}" ]; then + if [ ${DEPRECATED_CRYPT} -eq 1 ]; then + export root="/dev/mapper/root" + fi + else + err "Password succeeded, but ${cryptname} creation failed, aborting..." + exit 1 + fi + elif [ -n "${crypto}" ]; then + msg "Non-LUKS encrypted device found..." + if echo "$crypto" | awk -F: '{ exit(NF == 5) }'; then + err "Verify parameter format: crypto=hash:cipher:keysize:offset:skip" + err "Non-LUKS decryption not attempted..." + return 1 + fi + exe="cryptsetup open --type plain $resolved $cryptname $cryptargs" + IFS=: read c_hash c_cipher c_keysize c_offset c_skip </dev/null 2>&1 + [ "${quiet}" = "y" ] && CSQUIET=">/dev/null" + + # Get keyfile if specified + ckeyfile="/crypto_keyfile.bin" + if [ -n "$cryptkey" ]; then + IFS=: read ckdev ckarg1 ckarg2 </dev/null 2>&1 + umount /ckey + ;; + *) + # Read raw data from the block device + # ckarg1 is numeric: ckarg1=offset, ckarg2=length + dd if="$resolved" of="$ckeyfile" bs=1 skip="$ckarg1" count="$ckarg2" >/dev/null 2>&1 + ;; + esac + fi + [ ! -f ${ckeyfile} ] && echo "Keyfile could not be opened. Reverting to passphrase." + fi + + if [ -n "${cryptdevice}" ]; then + DEPRECATED_CRYPT=0 + IFS=: read cryptdev cryptname cryptoptions <&2 + ;; + esac + done + + if resolved=$(resolve_device "${cryptdev}" ${rootdelay}); then + if cryptsetup isLuks ${resolved} >/dev/null 2>&1; then + [ ${DEPRECATED_CRYPT} -eq 1 ] && warn_deprecated + dopassphrase=1 + # If keyfile exists, try to use that + if [ -f ${ckeyfile} ]; then + if eval cryptsetup --key-file ${ckeyfile} open --type luks ${resolved} ${cryptname} ${cryptargs} ${CSQUIET}; then + dopassphrase=0 + else + echo "Invalid keyfile. Reverting to passphrase." + fi + fi + # Ask for a passphrase + if [ ${dopassphrase} -gt 0 ]; then + echo "" + echo "A password is required to access the ${cryptname} volume:" + + #loop until we get a real password + while ! eval cryptsetup open --type luks ${resolved} ${cryptname} ${cryptargs} ${CSQUIET}; do + sleep 2; + done + fi + if [ -e "/dev/mapper/${cryptname}" ]; then + if [ ${DEPRECATED_CRYPT} -eq 1 ]; then + export root="/dev/mapper/root" + fi + else + err "Password succeeded, but ${cryptname} creation failed, aborting..." + exit 1 + fi + elif [ -n "${crypto}" ]; then + [ ${DEPRECATED_CRYPT} -eq 1 ] && warn_deprecated + msg "Non-LUKS encrypted device found..." + if echo "$crypto" | awk -F: '{ exit(NF == 5) }'; then + err "Verify parameter format: crypto=hash:cipher:keysize:offset:skip" + err "Non-LUKS decryption not attempted..." + return 1 + fi + exe="cryptsetup open --type plain $resolved $cryptname $cryptargs" + IFS=: read c_hash c_cipher c_keysize c_offset c_skip <&2' ERR + +readonly this_file="$(readlink -f -- "${BASH_SOURCE[0]}")"; cd "${this_file%/*}" + +usage() { + cat <> /srv/fai/config/class/LAST.var +note FAI_ACTION might be able to be set elsewhere, like in grub for this case + +-d DISTRO DISTRO for setting up fai class DESKTOP packages, for preinstalling stuff. +-t TARGET_HOST Copy only secrets for TARGET_HOST into the config space. Useful for virtual server + on hardware we don't control. +-h|--help Print help and exit + +Note: uses paths specific to authors machine. +EOF + exit $1 +} + +##### begin command line parsing ######## + +# ensure we can handle args with spaces or empty. +ret=0; getopt -T || ret=$? +[[ $ret == 4 ]] || { echo "Install util-linux for enhanced getopt" >&2; exit 1; } + +temp=$(getopt -l help hd:t: "$@") || usage 1 +eval set -- "$temp" +while true; do + case $1 in + -d) distro=$2; shift ;; + -t) target=$2; shift ;; + -h|--help) usage ;; + --) shift; break ;; + *) echo "$0: unexpected args: $*" >&2 ; usage 1 ;; + esac + shift +done +host=${1:-faiserver} + +readonly host distro target + +##### end command line parsing ######## + +# i use faiserver as a dns alias, but ssh key is associated with +# a canonical hostname and we will have ssh warning spam unless we +# use it, so look it up just to avoid the warning spam. +faiserver_host=$(chost $host) || faiserver_host=$host + +rsync -rlpt --delete --relative --exclude /fai/config/basefiles/ fai/config root@$faiserver_host:/srv + +sudo rsync -a /root/.ssh/home.pub \ + root@$faiserver_host:/srv/fai/config/files/root/.ssh/authorized_keys/STANDARD +# todo: automatically disable faiserver after a period so +# these files are not available. + +if [[ $target ]]; then + if sudo test -e /q/root/shadow/$target; then + shadowfile=shadow/$target # empty otherwise + fi + sudo rsync -lpt --files-from=- /q/root root@$faiserver_host:/srv/fai/config/distro-install-common </dev/null ||: # broken pipe + + +rsync -rplt --include '/*.gz' --exclude '/**' --delete-excluded $BASEFILE_DIR/ root@$faiserver_host:/srv/fai/config/basefiles/ +ssh root@$faiserver_host bash <<'EOF' +set -eE -o pipefail +# make it the root because pxe-kexec only looks there. +# It wouldn't be too hard to change if we needed. +# We could also just dump things in /srv/tftp, but fai +# has some defaults, which I don't even use, which expect +# the other directory, so it's kind of a tossup, whatever. +sed -ri 's,^ *(TFTP_DIRECTORY=).*,\1"/srv/tftp/fai",' /etc/default/tftpd-hpa +systemctl restart tftpd-hpa + +changed=false +f=/srv/fai/nfsroot/root/.ssh/known_hosts +install -d -m 700 /srv/fai/nfsroot/root/.ssh +# the known hosts entries that fai already sets up are like +# IP,HOSTNAME key_info... +# we are skipping the ip, because it doesn't block ssh +# with a prompt as long as you have the user supplied hostname, +# and i don't want to deal with getting it, it's not adding +# any important security in this case. +if ! grep -xFq "$line" $f &>/dev/null; then + changed=true + printf "%s\n" "$line" >>$f +fi + +if ! modprobe nfsd &>/dev/null; then + # no apt-cache on maru debian, because we are low on space already + sed -i '/^ *APTPROXY=/d' /srv/fai/config/class/DEBIAN.var + # maru debian doesn't have loopback devs created + if ! losetup -f; then + shopt -s nullglob + x=(/dev/loop*) + minor=0 + if (( ${#x[@]} )); then + minor=$(( ${x[-1]#/dev/loop} + 1 )) + fi + mknod -m660 /dev/loop$minor b 7 $minor + losetup -f + fi + # -B boo only iso, no nfsroot, no paritial miorr, no config space. + # -f = force, for overwriting + # -S = make squash image for http booting + # -d config space url, instead of putting it in the squash.img, + # this just makes it so that we don't have to regenerate the img + # when the config changes. + cd /srv/fai/config + tar czf /var/www/faiserver/html/config.tar.gz . + if $changed || [[ ! -e /var/www/faiserver/html/squash.img ]]; then + # note, on maru, selinux needs to be disabled in android before + # this will work. + mount + export debug=true + fai-cd -d http://faiserver:8080/config.tar.gz -f -M -S /var/www/faiserver/html/squash.img + mount + fi +fi +EOF diff --git a/fai-revm b/fai-revm new file mode 100755 index 0000000..0d117e6 --- /dev/null +++ b/fai-revm @@ -0,0 +1,198 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +# 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 should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + + +readonly this_file="$(readlink -f -- "${BASH_SOURCE[0]}")" +script_dir="${this_file%/*}" +# shellcheck source=./bash-trace +source "${script_dir}/bash-trace" +cd $script_dir +PATH="$PATH:$PWD" + +e() { echo "$*"; "$@"; } + + +usage() { + cat < 1 should be the only +# important things to test. +disk_count=1 + + +if ! ip l show br0 &>/dev/null; then + cat <<'EOF' +fai-rvm error: no bridge detected. add one to interfaces like this: +iface eth0 inet manual +iface br0 inet dhcp + bridge_ports eth0 + bridge_stp off + bridge_maxwait 0 +EOF + exit 1 +fi + +if [[ $script_dir == /a/bin/* ]]; then + # Copy our script elsewhere so we can develop it + # and save it at the same time it's running + rm -rf /tmp/faifreeze + cp -ar /a/bin/fai /tmp/faifreeze + exec /tmp/faifreeze/${BASH_SOURCE##*/} "${orig_args[@]}" +fi + + +is_arch_revm() { + [[ ${0##*/} == arch-revm ]] +} + +err-cleanup() { + echo "doing cleanup" + e ./pxe-server $dhcp_arg + ./faiserver-disable +} + +boot_arg=--pxe +if is_arch_revm; then + e ./pxe-server $dhcp_arg demohost arch + sleep 2 + # via osinfo-query os. guessing arch is closest to latest fedora. + variant=fedora22 +else + if $pxe; then + e ./pxe-server $dhcp_arg demohost fai + sleep 2 + else + killall fai-monitor &>/dev/null ||: + fai-monitor & + if [[ ! $BASEFILE_DIR ]]; then + BASEFILE_DIR=/tmp + fi + isopath=$BASEFILE_DIR/$iso + isosrc=$BASEFILE_DIR/BUSTER64.tar.gz + if [[ ! -e $isopath || $(stat -c %Y $isopath) -lt $(stat -c %Y $isosrc) ]]; then + e sudo fai-cd -g $(readlink -f grub.cfg.${iso%%.*}) -f -A $isopath + fi + boot_arg="--cdrom $isopath" + e fai-redep + e myfai-chboot default + fi + # I don't think these variants actually make a diff for us, but I + # use the appropriate one when trying a new distro just in case. + variant=ubuntu14.04 + #variant=ubuntu16.04 + #variant=debian8 +fi + +name=demohost + +e sudo virsh destroy $name ||: +e sudo virsh undefine $name ||: + + +disk_arg=() +for ((i=1; i <= disk_count; i++)); do + f=/var/lib/libvirt/images/${name}$i + disk_arg+=("--disk path=$f") + if $new_disk || [[ ! -e $f ]]; then + sudo rm -f $f + # https://btrfs.wiki.kernel.org/index.php/FAQ + sudo touch $f + chattr +C $f + e sudo qemu-img create -o preallocation=metadata -f qcow2 $f 50G + fi +done + +if [[ $SSH_CLIENT ]]; then + console_arg=--noautoconsole +fi + +# docker makes forward default to drop, which blocks the vm pxe on flidas. easiest solution: +e sudo iptables -P FORWARD ACCEPT + +# --cpu host: this causes mkfs.btrfs to fail with a stack trace which began +# something like: +# init_module+0x108/0x1000 [raid6_pq] +# +# uniq is to stop gtk-warning spam +# e sudo virt-install --os-variant $variant -n $name --pxe -r 2048 --vcpus 1 \ + # ${disk_arg[*]} -w bridge=br0,mac=52:54:00:9c:ef:ad $reboot_arg \ + # --graphics spice,listen=0.0.0.0 $console_arg |& grep -v '^ *$' | uniq & + +cpus=1 +if (( $(nproc) > 2 )); then + cpus=2 +fi + +e sudo systemctl start libvirtd +e sudo virt-install --rng /dev/urandom --os-variant $variant -n $name $boot_arg -r 2048 --vcpus $cpus \ + ${disk_arg[*]} -w bridge=br0,mac=52:54:00:9c:ef:ad $reboot_arg \ + --graphics spice,listen=0.0.0.0 $console_arg |& grep -v '^ *$' | uniq & + + +if [[ $SSH_CLIENT ]]; then + fg +fi + +sleep 90 +while ! timeout -s 9 10 ssh -oBatchMode=yes root@$name /bin/true; do + e sleep 5 +done +unset -f err-cleanup +e ./pxe-server $dhcp_arg +if is_arch_revm; then + ./arch-init-remote $name +fi diff --git a/fai-wrapper b/fai-wrapper new file mode 100644 index 0000000..5efa7f1 --- /dev/null +++ b/fai-wrapper @@ -0,0 +1,50 @@ +#!/bin/bash +# Copyright (C) 2019 Ian Kelling +# SPDX-License-Identifier: AGPL-3.0-or-later + +# For using some fai commands outside of fai. +# Usually this is sourced from another script. Note this has +# paths specific to Ian's machine. +# to set fai classes, export CLASS_CLASSNAME=true +# This wrapper can be detected by using this var: +export FAI_WRAPPER=true + +ifclass() { + local var=${1/#/CLASS_} + [[ $HOSTNAME == $1 || ${!var} ]] +} +fai-setclass() { + for class in "$@"; do + # export class vars with CLASS_ in front to avoid name collisions. + classes+=" $class" + export CLASS_$class=true + done + classes="${classes# }" + export classes +} +eval-fai-classfile() { + file=$1 + if [[ ! -s $file ]]; then + echo "$0: probably an error: eval-fai-classfile no such file: $file" + return 0 + fi + fai-setclass $(bash $file) +} +export -f ifclass +# DEFAULT is used by fcopy +classes="DEFAULT $(hostname)" +export CLASS_DEFAULT=true +if [[ ! -d $FAI_ROOT ]]; then + export FAI_ROOT=/ +fi +if [[ ! -d $FAI ]]; then + if [[ -d /a/bin/fai/fai/config ]]; then + export FAI=/a/bin/fai/fai/config + else + echo "$0: error: could not find directory to set for FAI. currently FAI=$FAI" + return 1 + fi +fi + +eval-fai-classfile $FAI/class/50-host-classes +eval-fai-classfile $FAI/class/51-multi-boot diff --git a/fai/config/basefiles/mk-basefile b/fai/config/basefiles/mk-basefile index 085b9a4..39471d8 100755 --- a/fai/config/basefiles/mk-basefile +++ b/fai/config/basefiles/mk-basefile @@ -1,5 +1,4 @@ #! /bin/bash - # mk-basefile, create basefiles for some distributions # # Thomas Lange, Uni Koeln, 2011-2021 @@ -22,6 +21,7 @@ # For the first stage, set the CentOS/SLC mirror in /etc/rinse/rinse.conf MIRROR_DEBIAN=http://deb.debian.org/debian/ MIRROR_UBUNTU=http://mirror.netcologne.de/ubuntu/ +MIRROR_TRISQUEL=http://mirror.fsf.org/trisquel/ MIRROR_CENTOS=http://mirror.netcologne.de/ EXCLUDE_SQUEEZE=isc-dhcp-client,isc-dhcp-common,info @@ -34,14 +34,19 @@ EXCLUDE_BOOKWORM= EXCLUDE_TRIXIE= EXCLUDE_SID= +EXCLUDE_BELENOS=dhcp3-client,dhcp3-common,info EXCLUDE_TRUSTY=dhcp3-client,dhcp3-common,info EXCLUDE_XENIAL=udhcpc,dibbler-client,info +EXCLUDE_FLIDAS=udhcpc,dibbler-client,info EXCLUDE_BIONIC=udhcpc,dibbler-client,info +EXCLUDE_ETIONA=udhcpc,dibbler-client,info EXCLUDE_FOCAL=udhcpc,dibbler-client,info +EXCLUDE_NABIA=udhcpc,dibbler-client,info # here you can add packages, that are needed very early INCLUDE_DEBIAN= - +INCLUDE_ETIONA=ifupdown +INCLUDE_NABIA=ifupdown setarch() { @@ -108,6 +113,14 @@ EOM cleanup-deb() { + if [[ $cmd ]]; then + if [[ -e $cmd ]]; then + cp "$cmd" $xtmp/tmp + chroot $xtmp "/tmp/$cmd" + else + chroot $xtmp $cmd + fi + fi chroot $xtmp apt-get clean rm -f $xtmp/etc/hostname $xtmp/etc/resolv.conf \ $xtmp/var/lib/apt/lists/*_* $xtmp/usr/bin/qemu-*-static \ @@ -179,12 +192,11 @@ debgeneric() { dist=${DIST%%[0-9][0-9]} local exc="EXCLUDE_$dist" [ -n "${!exc}" ] && exc="--exclude=${!exc}" || unset exc + local inc="INCLUDE_$dist" + [ -n "${!inc}" ] && inc="--include=${!inc}" || unset inc dist=${dist,,} check - if [ -n "$INCLUDE_DEBIAN" ]; then - local inc="--include=$INCLUDE_DEBIAN" - fi if [ -n "$arch" ]; then qemu-debootstrap --arch $arch ${exc} $inc $dist $xtmp $mirror @@ -214,8 +226,11 @@ prtdists() { SLC7_64 TRUSTY32 TRUSTY64 XENIAL32 XENIAL64 + FLIDAS64 BIONIC64 + ETIONA64 FOCAL64 + NABIA64 SQUEEZE32 SQUEEZE64 WHEEZY32 WHEEZY64 JESSIE32 JESSIE64 @@ -243,6 +258,8 @@ Usage: mk-basefile [OPTION] ... DISTRIBUTION -z Use gzip for compressing the tar file. -J Use xz for compressing the tar file. -k Keep the temporary subtree structure, do not remove it. + -x CMD Run CMD in chroot. If CMD exists as a file, copy it and run it. + Debian based only -h Print help. Usage example: mk-basefile -J STRETCH64 @@ -260,7 +277,7 @@ attributes= cleanup=1 attributes="--xattrs --selinux --acls" -while getopts ashzJd:kf: opt ; do +while getopts ashzJd:kf:x: opt ; do case "$opt" in a) echo "$0: Warning. -a is ignored, because xtattrs, acls and selinux are always added." ;; d) export TMPDIR=$OPTARG ;; @@ -270,6 +287,7 @@ while getopts ashzJd:kf: opt ; do k) cleanup=0 ;; h) usage ;; s) prtdists ; exit 0;; + x) cmd="$OPTARG" ;; ?) exit 3 ;; # error in option parsing esac done @@ -298,6 +316,8 @@ case "$target" in SLC6_32) slc i386 6 ;; SLC6_64) slc amd64 6 ;; SLC7_64) slc amd64 7 ;; + BELENOS*|FLIDAS*|ETIONA*|NABIA*) + debgeneric $target $MIRROR_TRISQUEL ;; TRUSTY*|XENIAL*|BIONIC*|FOCAL*) debgeneric $target $MIRROR_UBUNTU ;; SQUEEZE*|WHEEZY*|JESSIE*|STRETCH*|BUSTER*|BULLSEYE*|BOOKWORM*|TRIXIE*|SID*) diff --git a/fai/config/class/50-host-classes b/fai/config/class/50-host-classes index df38b88..f6b7caa 100755 --- a/fai/config/class/50-host-classes +++ b/fai/config/class/50-host-classes @@ -1,32 +1,146 @@ -#! /bin/bash +#!/bin/bash # assign classes to hosts based on their hostname # do not use this if a menu will be presented [ "$flag_menu" ] && exit 0 -# use a list of classes for our demo machine -case $HOSTNAME in - faiserver) - echo "FAIBASE DEBIAN DEMO FAISERVER" ;; - demohost|client*) - echo "FAIBASE DEBIAN DEMO" ;; - xfcehost) - echo "FAIBASE DEBIAN DEMO XORG XFCE LVM";; - gnomehost) - echo "FAIBASE DEBIAN DEMO XORG GNOME";; - ubuntuhost) - echo "FAIBASE DEBIAN DEMO UBUNTU FOCAL FOCAL64 XORG";; - centos) - echo "FAIBASE CENTOS" # you may want to add class XORG here - ifclass AMD64 && echo CENTOS8_64 - ;; - slchost) - # Scientific Linux Cern, is very similar to CentOS. SLC should alsways use the class CENTOS - echo "FAIBASE CENTOS SLC" # you may want to add class XORG here - ifclass I386 && echo SLC7_32 - ifclass AMD64 && echo SLC7_64 - ;; - *) - echo "FAIBASE DEBIAN DEMO" ;; -esac +# set these early so they are lowest priority. +echo FAIBASE STANDARD DEBIAN + + +# For multi-boot system. +# We check that we aren't in a pxe boot environment. +# There is probably a better way to do this. +# We check the reverse condition in 51-multi-boot, +# and set what os we are installing, but don't check it +# into git since it changes regularly. + +# +# +# Each host defines following: +# The base distro: +# UBUNTU or nothing. DEBIAN is always defined as a base. +# +# The base disto version, only use so far is the basefile name if it exists. +# Debian stable basefile gets built by faisetup and gets used otherwise. +# With X suffix, means it has gone through the dirinstall process and has eXtra +# things installed, to speed up installation. +# +# STRETCH64, BUSTER64, BULLSEYE64, +# FLIDAS64, FLIDAS64BIG, ETIONA64, NABIA64 +# XENIAL64, BIONIC64, FOCAL64, +# +# The distro subvol name, we can add as many of these as we want: +# VOL_TESTING, VOL_STRETCH, VOL_BUSTER, VOL_BULLSEYE, +# VOL_FLIDAS, VOL_ETIONA, VOL_NABIA +# VOL_XENIAL, VOL_BIONIC VOL_FOCAL +# VOL_BUSTER_BOOTSTRAP. +# Using VOL_BUSTER_BOOTSTRAP sets up the install to act like a pxe rom if +# grub sets a specific var. +# +# The apt sources files we want, +# STRETCH_FREE, STRETCH_NONFREE, +# BUSTER_FREE, BUSTER_NONFREE, +# BULLSEYE_FREE, BULLSEYE_NONFREE +# TESTING_FREE, TESTING_NONFREE, +# XENIAL_FREE, BIONIC, FOCAL, FLIDAS, ETIONA, NABIA, STRETCH_LINODE. +# +# It's all a little redundant in some cases, but it keeps things +# simpler. +# +# +# Other notable classes: +# +# INSTALL: for autodiscover iso, this is needed. We could also add it to +# the autodiscover grub, but then we have to burn a new iso if we want a +# non-install one. It sets the class for the corresponding INSTALL.var, +# which sets FAI_ACTION=INSTALL. I'm not sure if this variable overrides +# FAI_ACTION outside of autodiscover, todo: test it out, if it doesn't, +# make install be default in 51-multi-boot, and disable it if needed. +# +# DESKTOP: install a bunch of extra packages. For creating X suffix +# basefiles. See README. +# +# REPARTITION: we try to reuse partitions/filesystems to install a new +# os into a multi-os system, if we see some basic hueristics, like the +# right amount of them. This overrides that. +# +# PARTITION_PROMPT: If we don't see partitions to reuuse, prompt +# to make sure we really want to repartition and use a completely +# fresh install. I use this in case our repartition check has +# a bug in it, or I accidentally set REPARTITION. +# +# ROTATIONAL: in a system with ssd and hdd, install to the hdd +# instead of the default ssd. +# +# RAID0: Use raid 0 even if there are >= 4 disks with boot partititions. +# +# LINODE: For running a vm on linode, especially one created with fai-cd. + +###### begin Template for 51-multi-boot ###### +# +# It has reasonable combinations of above classes. +# It's a noop until we replace _ with host names. + +#!/bin/bash +if [[ ! -e /a/bin/fai/fai-wrapper || $FAI_ACTION == dirinstall ]]; then + case $HOSTNAME in + # buster based minimal recovery / bootstraping os: + _) echo BUSTER64 VOL_BUSTER_BOOTSTRAP BUSTER_FREE ;; + # flidas + _) echo UBUNTU FLIDAS64 VOL_FLIDAS FLIDAS ;; + # etiona + _) echo UBUNTU ETIONA64 VOL_ETIONA ETIONA ;; + # nabia + _) echo UBUNTU NABIA64 VOL_NABIA NABIA ;; + # stretch + _) echo STRETCH64 VOL_STRETCH STRETCH_FREE ;; + # buster + _) echo BUSTER64 VOL_BUSTER BUSTER_FREE ;; + # testing + _) echo STRETCH64 VOL_TESTING TESTING_FREE ;; + # xenial + _) echo UBUNTU XENIAL64 VOL_XENIAL XENIAL_FREE ;; + # bionic + _) echo UBUNTU BIONIC64 VOL_BIONIC BIONIC ;; + # focal + _) echo UBUNTU FOCAL64 VOL_FOCAL FOCAL ;; + esac +fi +###### end Template for 51-multi-boot ###### + +if [[ -e /a/bin/fai/fai-wrapper ]]; then + source /a/bin/distro-functions/src/identify-distros + if isdeb; then + codename=$(debian-codename) + echo ${codename^^} + distro=$(distro-name) + case $distro in + debian) + echo ${distro^^} + # nonfree repo is not going away any time soon due to + # gcc-doc being in nonfree + echo ${codename^^}_NONFREE + ;; + trisquel) + # easier to stay with fai example config if we just call it ubuntu + echo UBUNTU + ;; + esac + fi + case $HOSTNAME in + li|lj) echo "LINODE" ;; + bk|je) echo "NOCRYPT" ;; + esac +fi + + +#echo "PARTITION_PROMPT" +#echo REPARTITION + + +if grep ^52:54:00: /sys/class/net/eth0/address &>/dev/null; then + # if our eth0 mac is in the kvm range, we are a vm. + echo "VM" +fi diff --git a/fai/config/class/DEBIAN.var b/fai/config/class/DEBIAN.var index dc133a5..a00d0f8 100644 --- a/fai/config/class/DEBIAN.var +++ b/fai/config/class/DEBIAN.var @@ -1,6 +1,7 @@ -release=bullseye -apt_cdn=http://deb.debian.org -security_cdn=http://security.debian.org +# ian, commented, sources are set with fcopy +# release=bullseye +# apt_cdn=http://deb.debian.org +# security_cdn=http://security.debian.org # since bullseye Debian changed the suite name for security if [ $release = buster ]; then @@ -20,7 +21,8 @@ MODULESLIST="usbhid psmouse" # if you have enough RAM (>2GB) you may want to enable this line. It # also puts /var/cache into a ramdisk. -#FAI_RAMDISKS="$target/var/lib/dpkg $target/var/cache" +# ian: uncommented +FAI_RAMDISKS="$target/var/lib/dpkg $target/var/cache" # if you want to use the faiserver as APT proxy -#APTPROXY=http://faiserver:3142 +# APTPROXY=http://faiserver:3142 diff --git a/fai/config/class/DEFAULT.var b/fai/config/class/DEFAULT.var new file mode 100644 index 0000000..a999512 --- /dev/null +++ b/fai/config/class/DEFAULT.var @@ -0,0 +1,12 @@ +# according to fai-guide, required to enable saving logs +# remotely. + +LOGUSER=fai + +# when downloading from https intead of nfs, this is not set, +# it is used as the default for LOGSERVER, and for calling chboot. +# My faiserver's hostname is always faiserver, so just hardcoding it. +SERVER=faiserver + +# busted for debian, no time to troubleshoot atm +#APTPROXY=http://faiserver:3142 diff --git a/fai/config/class/FAIBASE.var b/fai/config/class/FAIBASE.var index 3112039..dc507c7 100644 --- a/fai/config/class/FAIBASE.var +++ b/fai/config/class/FAIBASE.var @@ -1,3 +1,5 @@ +#### from upstream example config, except where noted + # default values for installation. You can override them in your *.var files # allow installation of packages from unsigned repositories @@ -5,18 +7,11 @@ FAI_ALLOW_UNSIGNED=1 # Set UTC=yes if your system clock is set to UTC (GMT), and UTC=no if not. UTC=yes -TIMEZONE=Europe/Berlin - -# the hash of the root password for the new installed linux system -# pw is "fai" -ROOTPW='$1$kBnWcO.E$djxB128U7dMkrltJHPf6d1' +## changed from upstream. found in /usr/share/zoneinfo/, via fai-guide +TIMEZONE=US/Eastern # errors in tasks greater than this value will cause the installation to stop STOP_ON_ERROR=700 # set parameter for install_packages(8) MAXPACKAGES=800 - -# a user account will be created -username=demo -USERPW='$1$kBnWcO.E$djxB128U7dMkrltJHPf6d1' diff --git a/fai/config/class/LINODE.var b/fai/config/class/LINODE.var new file mode 100644 index 0000000..8f34a2c --- /dev/null +++ b/fai/config/class/LINODE.var @@ -0,0 +1,7 @@ +APTPROXY= +linode_ip=172.105.84.95 +linode_gw=172.105.84.1 +# this is the same at least in 2 regions +linode_if=enp0s3 +LOGSERVER=b8.nz +HOSTNAME=l2 diff --git a/fai/config/class/UBUNTU.var b/fai/config/class/UBUNTU.var index a258b6a..6a42495 100644 --- a/fai/config/class/UBUNTU.var +++ b/fai/config/class/UBUNTU.var @@ -1,2 +1,4 @@ -ubuntumirror=http://archive.ubuntu.com -ubuntudist=focal +#iank, i define these by classes. commenting +# to make sure these arent used +#ubuntumirror=http://archive.ubuntu.com +#ubuntudist=focal diff --git a/fai/config/disk_config/VM b/fai/config/disk_config/VM new file mode 100644 index 0000000..53c6527 --- /dev/null +++ b/fai/config/disk_config/VM @@ -0,0 +1,2 @@ +disk_config disk1 disklabel:gpt-bios bootable:1 fstabkey:uuid +primary / 100% ext4 noatime,errors=remount-ro diff --git a/fai/config/distro-install-common/devbyid b/fai/config/distro-install-common/devbyid new file mode 100755 index 0000000..056a83f --- /dev/null +++ b/fai/config/distro-install-common/devbyid @@ -0,0 +1,20 @@ +#!/bin/bash + +# input eg: /dev/sda1 or /dev/sda +# output: /dev/disk/by-id/model+serial, or if no link exists, the same as input + +short_dev=$1 + +# devices are identified by model+serial num +# and for ssd/hdd: wwn, and for nvme: eui. +# model+serial gives me more info, so use that. +shopt -s extglob +for id in /dev/disk/by-id/!(nvme-eui*|wwn*); do + [[ -e $id ]] || break # if we matched nothing + if [[ $(readlink -f $id) == "$short_dev" ]]; then + printf '%s\n' "$id" + exit + fi +done +# a vm may not have a by-id link. +printf '%s\n' "$short_dev" diff --git a/fai/config/distro-install-common/end b/fai/config/distro-install-common/end new file mode 100755 index 0000000..b0e0700 --- /dev/null +++ b/fai/config/distro-install-common/end @@ -0,0 +1,90 @@ +#!/bin/bash -x + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + +if [[ $EUID != 0 ]]; then + echo "$0: error: expected to be root." + exit 1 +fi + +# ssh host keys +# note, $BASH_SOURCE is not defined here under fai. + +src=$(dirname "$0")/p/c/machine_specific/$HOSTNAME/filesystem/etc/ssh +dst=$target/etc/ssh +if [[ -e $src && -e $dst ]]; then + # outside of fai context or setting up a brand new host, we skip this + cp -rT $src $dst +fi + +USER2PW=/q/root/shadow/user2 +# if doesn't exist, we dont set one +ROOTPW=/q/root/shadow/standard +if [[ ! -e $ROOTPW ]]; then + ROOTPW=/q/root/shadow/$HOSTNAME +fi + +chpw() { + # generating a hashed password: + # under debian, you can do + # mkpasswd -m sha-512 -s >/q/root/shadow/standard + # On arch, best seems to be copy your shadow file to a temp location, + # then passwd, get out the new pass, then copy the shadow file back. + + user=$1 + pwfile=$2 + if [[ $pwfile && -e $pwfile ]]; then + printf "$user:" | cat - "$pwfile" | $ROOTCMD chpasswd -e + else + echo "$0: warning: no pw set for $user" >&2 + fi +} +au() { # add user. i don't use adduser for portability + local user=${@: -1} + if ! $ROOTCMD getent passwd $user; then + $ROOTCMD useradd -c $user -Um -s /bin/bash $@ + fi +} + +chpw root "$ROOTPW" + +# only setup root pass for bootstrap vol +if ifclass VOL_BUSTER_BOOTSTRAP; then + exit 0 +fi + + +# return of 9 = user already exists. so we are idempotent. +au iank +chpw iank "$ROOTPW" + +au user2 +if ifclass frodo; then + chpw user2 "$USER2PW" +fi +# comparing iank's groups to user2, I see none she should join on arch +$ROOTCMD usermod -a -G user2 iank + + +$ROOTCMD getent group docker &>/dev/null || $ROOTCMD groupadd -r docker +$ROOTCMD usermod -a -G docker iank + +# based on unison error, with 8192 from +# sysctl -a | grep fs.inotify.max_user_watches +#http://stackoverflow.com/questions/535768/what-is-a-reasonable-amount-of-inotify-watches-with-linux +f=$target/etc/sysctl.d/99-sysctl.conf +key=fs.inotify.max_user_watches +if [[ -e $f ]]; then sed -ri --follow-symlinks "/^\s*$key\s*=/d" $f; fi +echo "fs.inotify.max_user_watches = 50000" >> $f +# applies it. it would be also be applied after a reboot +$ROOTCMD sysctl --system + +f=$target/etc/sudoers +line='iank ALL=(ALL) NOPASSWD: ALL' +if [[ ! -e $f ]] || ! grep -xF "$line" $f; then + echo "$line" >> $f +fi + + +au --system -s /bin/false --home-dir /var/lib/bitcoind bitcoin diff --git a/fai/config/distro-install-common/libreboot_grub.cfg b/fai/config/distro-install-common/libreboot_grub.cfg new file mode 100644 index 0000000..54cf468 --- /dev/null +++ b/fai/config/distro-install-common/libreboot_grub.cfg @@ -0,0 +1,72 @@ +#!/bin/sh +# shebang is for editor file mode detection only + +function save_vars { + if [ -s $envfile ]; then + for var in $@; do + save_env --file $envfile $var + done + fi +} + +function save_chosen { + save_vars did_fai_check last_boot +} + +# fai_check is so we can act like a pxe boot, but just for fai, and by +# using /buster_bootstrap to do it. We toggle on and off the grub var +# did_fai_check so we can do the check every other boot. Then +# /debian_bootstrap checks for that var on boot and if we want to do a +# fai check, it does it, then reboots. But fai-check also sets +# did_fai_check to a 3rd state os_true which means we did the fai check, +# and we don't want to do it again. This is useful for systems without +# libreboot, although it's not used yet. + +# We don't set this to fai check so we can't get into +# an infinite reboot cycle. We depend on the os to +# create the initial grubenv file. +set default=/debianbuster_bootstrap # could use 0 here. +set timeout=1 + +# grub_extn +for part in (ahci*7) (ata*7); do + envfile=$part/grubenv + if [ -s $envfile ]; then + load_env --file $envfile + if [ x$did_fai_check == xfalse -a x$last_boot != x$default ]; then + set default=fai-check + elif [ ! -z $last_boot ]; then + set default=$last_boot + fi + break + fi +done + +did_fai_check=false + +bs_dir=/debianbuster_bootstrap +menuentry $bs_dir --id=$bs_dir { + # note, we might be able to use $chosen and avoid setting this here, + # and set it inside save_chosen. but I haven't tested it, + # it's just one less line of repitition. + last_boot=$1 + save_chosen + configfile $bs_dir/boot/grub/grub.cfg +} + +for dir in /boot_*; do + if [ $dir == '/boot_*' ]; then + break + fi + menuentry $dir --id=$dir { + last_boot=$1 + save_chosen + configfile $1/grub/grub.cfg + } +done + +menuentry fai-check --id=fai-check { + did_fai_check=true + save_vars did_fai_check + configfile $bs_dir/boot/grub/grub.cfg +} diff --git a/fai/config/files/boot/bash-trace/DEFAULT b/fai/config/files/boot/bash-trace/DEFAULT new file mode 100644 index 0000000..dc1a218 --- /dev/null +++ b/fai/config/files/boot/bash-trace/DEFAULT @@ -0,0 +1,220 @@ +#!/bin/bash +# Copyright (C) 2019 Ian Kelling +# SPDX-License-Identifier: GPL-3.0-or-later + +# Commentary: Print stack trace and exit/return on errors, or use +# functions below for for more details and manual error handling. See +# end of file for credits etc. + +####################################### +# err-catch: Setup trap on ERR to print stack trace and exit (or return +# if the shell is interactive). This is the most common use case so we +# run it after defining it, you can call err-allow to undo that. +# +# This also sets pipefail because it's a good practice to catch more +# errors. +# +# Note: In interactive shell, stack calling line number is not +# available, so we print function definition lines. +# +# Globals +# +# err_catch_ignore Array containing glob patterns to test against +# filenames to ignore errors from in interactive +# shell. Initialized to ignore bash-completion +# scripts on debian based systems. +# +# err-cleanup If set, this command will run just before exiting. +# +# _err_func_last Used internally in err-bash-trace-interactive +# +####################################### +err-catch() { + set -E; + if [[ $- == *i* ]]; then + if ! test ${err_catch_ignore+defined}; then + err_catch_ignore=( + '/etc/bash_completion.d/*' + '*/bash-completion/*' + ) + fi + declare -i _err_func_last=0 + shopt -s extdebug + # shellcheck disable=SC2154 + trap '_err-bash-trace-interactive $? "$BASH_COMMAND" ${BASH_ARGC[0]} "${BASH_ARGV[@]}" || return $?' ERR + else + # Man bash on exdebug: "If set at shell invocation, arrange to + # execute the debugger". We want to avoid that, but I want this file + # to be sourceable from bash startup files. noninteractive ssh and + # sources .bashrc on invocation. login_shell sources things on + # invocation. + # + # extdebug allows us to print function arguments in our stack trace. + if ! shopt login_shell >/dev/null && [[ ! $SSH_CONNECTION ]]; then + shopt -s extdebug + fi + trap err-exit ERR + fi + set -o pipefail +} +# This is the most common use case so run it now. +err-catch + +####################################### +# Undo err-catch/err-catch-interactive +####################################### +err-allow() { + shopt -u extdebug + set +E +o pipefail + trap ERR +} + +####################################### +# err-exit: Print stack trace and exit +# +# Use this instead of the exit command to be more informative. +# +# usage: err-exit [-EXIT_CODE] [MESSAGE] +# +# EXIT_CODE Default: $? if it is nonzero, otherwise 1. +# MESSAGE Print MESSAGE to stderr. Default: +# ${BASH_SOURCE[1]}:${BASH_LINENO[0]}: `$BASH_COMMAND' returned $? +# +# Globals +# +# err-cleanup If set, this command will run just before exiting. +# +####################################### +err-exit() { + local err=$? + # This has to come before most things or vars get changed + local msg="${BASH_SOURCE[1]}:${BASH_LINENO[0]}: \`$BASH_COMMAND' returned $err" + set +x + if [[ $1 == -* ]]; then + err=${1#-} + shift + elif (( ! err )); then + err=1 + fi + if [[ $1 ]]; then + msg="$1" + fi + printf "%s\n" "$msg" >&2 + err-bash-trace 2 + set -e # err trap does not work within an error trap + if type -t err-cleanup >/dev/null; then + err-cleanup + fi + printf "%s: exiting with status %s\n" "$0" "$err" >&2 + exit $err +} + +####################################### +# Print stack trace +# +# usage: err-bash-trace [FRAME_START] +# +# This function is called by the other functions which print stack +# traces. +# +# It does not show function args unless you first run: +# shopt -s extdebug +# which err-catch does for you. +# +# FRAME_START Optional variable to set before calling. The frame to +# start printing on. default=1. If ${#FUNCNAME[@]} <= +# FRAME_START + 1, don't print anything because we are at +# the top level of the script and better off printing a +# general message, for example see what our callers print. +# +####################################### +err-bash-trace() { + local -i argc_index=0 frame i frame_start=${1:-1} + local source_loc + if (( ${#FUNCNAME[@]} <= frame_start + 1 )); then + return 0 + fi + for ((frame=0; frame < ${#FUNCNAME[@]}; frame++)); do + argc=${BASH_ARGC[frame]} + argc_index+=$argc + if ((frame < frame_start)); then continue; fi + if (( ${#BASH_SOURCE[@]} > 1 )); then + source_loc="${BASH_SOURCE[frame]}:${BASH_LINENO[frame-1]}:" + fi + printf " from %sin \`%s" "$source_loc" "${FUNCNAME[frame]}" >&2 + if shopt extdebug >/dev/null; then + for ((i=argc_index-1; i >= argc_index-argc; i--)); do + printf " %s" "${BASH_ARGV[i]}" >&2 + done + fi + echo \' >&2 + done + return 0 +} + +####################################### +# Internal function for err-catch. Prints stack trace from interactive +# shell trap. +# +# Usage: see err-catch-interactive +####################################### +_err-bash-trace-interactive() { + if (( ${#FUNCNAME[@]} <= 1 )); then + return 0 + fi + + for pattern in "${err_catch_ignore[@]}"; do + # shellcheck disable=SC2053 + if [[ ${BASH_SOURCE[1]} == $pattern ]]; then + return 0 + fi + done + + local ret bash_command argc pattern i last + last=$_err_func_last + _err_func_last=${#FUNCNAME[@]} + # We have these passed to us because they are lost inside the + # function. + ret=$1 + bash_command="$2" + argc=$(( $3 - 1 )) + shift 3 + argv=("$@") + # The trap returns a nonzero, then gets called again. This condition + # tells us if we are the first. + if (( _err_func_last > last )); then + printf "ERR: \`%s\' returned %s\n" "$bash_command" $ret >&2 + fi + printf " from \`%s" "${FUNCNAME[1]}" >&2 + if shopt extdebug >/dev/null; then + for ((i=argc; i >= 0; i--)); do + printf " %s" "${argv[i]}" >&2 + done + fi + printf "\' defined at %s:%s\n" "${BASH_SOURCE[1]}" "$(declare -F "${FUNCNAME[1]}"|awk "{print \$2}")" >&2 + if [[ -t 1 ]]; then + return $ret + else + # Part of an outgoing pipe, avoid getting get us stuck in a weird + # subshell if we returned nonzero, which would happen in a situation + # like this: + # + # tf() { while read -r line; do :; done < <(asdf); }; + # tf + # + # Note: exit $ret also avoids the stuck subshell problem, and I + # can't notice any difference, but this seems more proper. + return 0 + fi +} + +# Credits etc: +# +# Related: see my bash script template repo at https://iankelling.org/git. +# +# +# Please email me if you have a patches, bugs, feedback, or if you use +# it or republish it since I'm not aware of any users yet +# Ian Kelling . +# +# Tested on bash 4.4.20(1)-release (x86_64-pc-linux-gnu). If you test diff --git a/fai/config/files/boot/chboot/DEFAULT b/fai/config/files/boot/chboot/DEFAULT new file mode 100755 index 0000000..adfbe1c --- /dev/null +++ b/fai/config/files/boot/chboot/DEFAULT @@ -0,0 +1,143 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +# 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 should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +[[ $EUID == 0 ]] || exec sudo "$BASH_SOURCE" "$@" + + +x="$(readlink -f "$BASH_SOURCE")" +f="${x%/*}/bash-trace" +if [[ -e $f ]]; then + source $f +else + source ${x%/*}/../bash-trace/DEFAULT +fi + + +usage() { + cat </dev/null; then + mnt=/ +fi + +if [[ ! $distro ]]; then + echo "available distros:" + cur=$(btrfs subvol show $mnt| sed -rn 's/^.*Name:\s*(\S*).*/\1/p') + btrfs subvolume list $mnt | awk '{print $9}' | sed "s/$cur/$cur (current)/" + exit 0 +fi + +###### end command line parsing ##### + + +#### begin initial error checking ##### + +if ! btrfs subvolume list $mnt | grep "$distro$" &>/dev/null; then + echo "$0: error: $distro not found in btrfs subvolume list $mnt:" + btrfs subvolume list $mnt + exit 1 +fi + +#### end initial error checking ##### + +e() { echo "$@"; "$@"; } + +for boot_dev in $(btrfs fil show $mnt | sed -nr 's#.*path\s+(\S+)$#\1#p'); do + + mount_point=$(mktemp -d) + + e mount -o subvol=$distro $boot_dev $mount_point + + boot_disk=${boot_dev%%[0-9]*} + + # arch doesn't have $mount_point/grub/device.map, accoring to the grub manual, + # it just generates one if the file doesn't exist. + # https://www.gnu.org/software/grub/manual/html_node/Device-map.html + e grub-bios-setup -d $mount_point/grub/i386-pc -s -m $mount_point/grub/device.map $boot_disk + e umount $mount_point +done + +if [[ $(blockdev --getsize64 ${boot_disk}4) == 8388608 ]]; then + # old partition scheme + grub_dev=${boot_disk}4 +elif [[ $(blockdev --getsize64 ${boot_disk}5) == 8388608 ]]; then + grub_dev=${boot_disk}5 +else + grub_dev=${boot_disk}7 +fi + +e mount $grub_dev $mount_point +e grub-editenv $mount_point/grubenv set last_boot=/$distro +e grub-editenv $mount_point/grubenv set did_fai_check=true +e umount $mount_point +if $reboot; then + touch /tmp/keyscript-off + reboot now +fi diff --git a/fai/config/files/etc/apt/preferences.d/belenos/BELENOS b/fai/config/files/etc/apt/preferences.d/belenos/BELENOS new file mode 100644 index 0000000..1e59c86 --- /dev/null +++ b/fai/config/files/etc/apt/preferences.d/belenos/BELENOS @@ -0,0 +1,3 @@ +Package: * +Pin: release a=belenos-backports +Pin-Priority: 500 diff --git a/fai/config/files/etc/apt/preferences.d/etiona-bionic/ETIONA b/fai/config/files/etc/apt/preferences.d/etiona-bionic/ETIONA new file mode 100644 index 0000000..4790bbe --- /dev/null +++ b/fai/config/files/etc/apt/preferences.d/etiona-bionic/ETIONA @@ -0,0 +1,3 @@ +Package: * +Pin: release n=bionic,o=Ubuntu +Pin-Priority: -100 diff --git a/fai/config/files/etc/apt/preferences.d/etiona-flidas/ETIONA b/fai/config/files/etc/apt/preferences.d/etiona-flidas/ETIONA new file mode 100644 index 0000000..67e2f8c --- /dev/null +++ b/fai/config/files/etc/apt/preferences.d/etiona-flidas/ETIONA @@ -0,0 +1,11 @@ +Package: * +Pin: release a=flidas +Pin-Priority: -100 + +Package: * +Pin: release a=flidas-updates +Pin-Priority: -100 + +Package: * +Pin: release a=flidas-security +Pin-Priority: -100 diff --git a/fai/config/files/etc/apt/preferences.d/etiona-focal/ETIONA b/fai/config/files/etc/apt/preferences.d/etiona-focal/ETIONA new file mode 100644 index 0000000..1e6fc34 --- /dev/null +++ b/fai/config/files/etc/apt/preferences.d/etiona-focal/ETIONA @@ -0,0 +1,3 @@ +Package: * +Pin: release n=focal,o=Ubuntu +Pin-Priority: -100 diff --git a/fai/config/files/etc/apt/preferences.d/etiona/ETIONA b/fai/config/files/etc/apt/preferences.d/etiona/ETIONA new file mode 100644 index 0000000..223a9f4 --- /dev/null +++ b/fai/config/files/etc/apt/preferences.d/etiona/ETIONA @@ -0,0 +1,3 @@ +Package: * +Pin: release a=etiona-backports +Pin-Priority: 500 diff --git a/fai/config/files/etc/apt/preferences.d/flidas/FLIDAS b/fai/config/files/etc/apt/preferences.d/flidas/FLIDAS new file mode 100644 index 0000000..bd19b25 --- /dev/null +++ b/fai/config/files/etc/apt/preferences.d/flidas/FLIDAS @@ -0,0 +1,3 @@ +Package: * +Pin: release a=flidas-backports +Pin-Priority: 500 diff --git a/fai/config/files/etc/apt/preferences.d/nabia-focal/NABIA b/fai/config/files/etc/apt/preferences.d/nabia-focal/NABIA new file mode 100644 index 0000000..1e6fc34 --- /dev/null +++ b/fai/config/files/etc/apt/preferences.d/nabia-focal/NABIA @@ -0,0 +1,3 @@ +Package: * +Pin: release n=focal,o=Ubuntu +Pin-Priority: -100 diff --git a/fai/config/files/etc/apt/preferences.d/stretch/STRETCH b/fai/config/files/etc/apt/preferences.d/stretch/STRETCH new file mode 100644 index 0000000..f3a0d4b --- /dev/null +++ b/fai/config/files/etc/apt/preferences.d/stretch/STRETCH @@ -0,0 +1,21 @@ +Explanation: tar, cuz https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=819978 +Explanation: kernel & btrfs-progs, because btrfs is getting a lot of active +Explanation: dev, and their mailing list says better to use recent version +Explanation: to avoid bugs. linux-base is needed for the kernel, +Explanation: which you can find out by failing +Explanation: apt-get install linux-image-amd64/stretch-backports +Explanation: And then trying aptitude -s install, or +Explanation: apt-get -t stretch-backports install linux-image-amd64 +Explanation: +Explanation: +Package: tar linux-image-amd64 linux-base btrfs-progs +Pin: release a=stretch-backports +Pin-Priority: 500 + +Package: * +Pin: release a=buster +Pin-Priority: -10 + +Package: * +Pin: release a=buster-updates +Pin-Priority: -10 diff --git a/fai/config/files/etc/apt/preferences.d/unstable/DEBIAN b/fai/config/files/etc/apt/preferences.d/unstable/DEBIAN new file mode 100644 index 0000000..a88edb7 --- /dev/null +++ b/fai/config/files/etc/apt/preferences.d/unstable/DEBIAN @@ -0,0 +1,23 @@ +Explanation: https://debian-handbook.info/browse/stable/sect.apt-get.html#sect.apt.priorities +Explanation: And man apt_preferences +Explanation: Installed packages get 100 priority, so this won't upgrade testing +Explanation: packages unless explicitly asked to. +Explanation: Less than 0 won't install package unless you specify the archive. +Explanation: This is good, so you never just search for a package and install +Explanation: it without knowing it's from a different archive. +Explanation: Install with apt-get install package/testing. But if dependencies are +Explanation: needed, or need upgrading, +Explanation: apt-get -t testing package, setting testing to priority +Explanation: 990 just for that command. +Explanation: Use apt-cache policy to verify these settings. +Package: * +Pin: release a=unstable +Pin-Priority: -20 + +Package: * +Pin: release a=unstable-updates +Pin-Priority: -20 + +Package: * +Pin: release a=experimental +Pin-Priority: -40 diff --git a/fai/config/files/etc/apt/sources.list.d/aaa-etiona.list/ETIONA b/fai/config/files/etc/apt/sources.list.d/aaa-etiona.list/ETIONA new file mode 100644 index 0000000..0539b9b --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/aaa-etiona.list/ETIONA @@ -0,0 +1,12 @@ +deb http://mirror.fsf.org/trisquel/ etiona main +deb-src http://mirror.fsf.org/trisquel/ etiona main + +deb http://mirror.fsf.org/trisquel/ etiona-updates main +deb-src http://mirror.fsf.org/trisquel/ etiona-updates main + +deb http://archive.trisquel.info/trisquel/ etiona-security main +deb-src http://archive.trisquel.info/trisquel/ etiona-security main + +# Uncomment this lines to enable the backports optional repository +deb http://mirror.fsf.org/trisquel/ etiona-backports main +deb-src http://mirror.fsf.org/trisquel/ etiona-backports main diff --git a/fai/config/files/etc/apt/sources.list.d/aaa-nabia.list/NABIA b/fai/config/files/etc/apt/sources.list.d/aaa-nabia.list/NABIA new file mode 100644 index 0000000..85bf23c --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/aaa-nabia.list/NABIA @@ -0,0 +1,12 @@ +deb http://mirror.fsf.org/trisquel/ nabia main +deb-src http://mirror.fsf.org/trisquel/ nabia main + +deb http://mirror.fsf.org/trisquel/ nabia-updates main +deb-src http://mirror.fsf.org/trisquel/ nabia-updates main + +deb http://archive.trisquel.info/trisquel/ nabia-security main +deb-src http://archive.trisquel.info/trisquel/ nabia-security main + +# Uncomment this lines to enable the backports optional repository +deb http://mirror.fsf.org/trisquel/ nabia-backports main +deb-src http://mirror.fsf.org/trisquel/ nabia-backports main diff --git a/fai/config/files/etc/apt/sources.list.d/belenos.list/BELENOS b/fai/config/files/etc/apt/sources.list.d/belenos.list/BELENOS new file mode 100644 index 0000000..17b28dc --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/belenos.list/BELENOS @@ -0,0 +1,12 @@ +deb http://mirror.fsf.org/trisquel/ belenos main +deb-src http://mirror.fsf.org/trisquel/ belenos main + +deb http://mirror.fsf.org/trisquel/ belenos-updates main +deb-src http://mirror.fsf.org/trisquel/ belenos-updates main + +deb http://mirror.fsf.org/trisquel/ belenos-security main +deb-src http://mirror.fsf.org/trisquel/ belenos-security main + +# Uncomment this lines to enable the backports optional repository +deb http://mirror.fsf.org/trisquel/ belenos-backports main +deb-src http://mirror.fsf.org/trisquel/ belenos-backports main diff --git a/fai/config/files/etc/apt/sources.list.d/bionic.list/ETIONA b/fai/config/files/etc/apt/sources.list.d/bionic.list/ETIONA new file mode 100644 index 0000000..cb92b36 --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/bionic.list/ETIONA @@ -0,0 +1,6 @@ +deb http://us.archive.ubuntu.com/ubuntu/ bionic main universe multiverse +deb http://us.archive.ubuntu.com/ubuntu/ bionic-updates main universe multiverse +deb http://us.archive.ubuntu.com/ubuntu/ bionic-security main universe multiverse +deb-src http://us.archive.ubuntu.com/ubuntu/ bionic main universe multiverse +deb-src http://us.archive.ubuntu.com/ubuntu/ bionic-updates main universe multiverse +deb-src http://us.archive.ubuntu.com/ubuntu/ bionic-security main universe multiverse diff --git a/fai/config/files/etc/apt/sources.list.d/bulleye.list/BULLSEYE_FREE b/fai/config/files/etc/apt/sources.list.d/bulleye.list/BULLSEYE_FREE new file mode 100644 index 0000000..04e72ca --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/bulleye.list/BULLSEYE_FREE @@ -0,0 +1,11 @@ +deb http://http.us.debian.org/debian bullseye main +deb-src http://http.us.debian.org/debian bullseye main + +deb http://security.debian.org/ bullseye-security main +deb-src http://security.debian.org/ bullseye-security main + +deb http://http.us.debian.org/debian bullseye-updates main +deb-src http://http.us.debian.org/debian bullseye-updates main + +deb http://http.debian.net/debian bullseye-backports main +deb-src http://http.debian.net/debian bullseye-backports main diff --git a/fai/config/files/etc/apt/sources.list.d/bulleye.list/BULLSEYE_NONFREE b/fai/config/files/etc/apt/sources.list.d/bulleye.list/BULLSEYE_NONFREE new file mode 100644 index 0000000..2b5aa98 --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/bulleye.list/BULLSEYE_NONFREE @@ -0,0 +1,17 @@ +deb http://http.us.debian.org/debian bullseye main contrib non-free +deb-src http://http.us.debian.org/debian bullseye main contrib non-free + +deb http://security.debian.org/ bullseye-security main contrib non-free +deb-src http://security.debian.org/ bullseye-security main contrib non-free + +deb http://http.us.debian.org/debian bullseye-updates main contrib non-free +deb-src http://http.us.debian.org/debian bullseye-updates main contrib non-free + +deb http://http.debian.net/debian bullseye-backports main contrib non-free +deb-src http://http.debian.net/debian bullseye-backports main contrib non-free + +deb http://http.us.debian.org/debian unstable main contrib non-free +deb-src http://http.us.debian.org/debian unstable main contrib non-free + +deb http://http.us.debian.org/debian experimental main +deb-src http://http.us.debian.org/debian experimental main diff --git a/fai/config/files/etc/apt/sources.list.d/buster.list/BUSTER_FREE b/fai/config/files/etc/apt/sources.list.d/buster.list/BUSTER_FREE new file mode 100644 index 0000000..be9c7e3 --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/buster.list/BUSTER_FREE @@ -0,0 +1,11 @@ +deb http://http.us.debian.org/debian buster main +deb-src http://http.us.debian.org/debian buster main + +deb http://security.debian.org/ buster/updates main +deb-src http://security.debian.org/ buster/updates main + +deb http://http.us.debian.org/debian buster-updates main +deb-src http://http.us.debian.org/debian buster-updates main + +deb http://http.debian.net/debian buster-backports main +deb-src http://http.debian.net/debian buster-backports main diff --git a/fai/config/files/etc/apt/sources.list.d/buster.list/BUSTER_NONFREE b/fai/config/files/etc/apt/sources.list.d/buster.list/BUSTER_NONFREE new file mode 100644 index 0000000..fc58c98 --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/buster.list/BUSTER_NONFREE @@ -0,0 +1,17 @@ +deb http://http.us.debian.org/debian buster main contrib non-free +deb-src http://http.us.debian.org/debian buster main contrib non-free + +deb http://security.debian.org/ buster/updates main contrib non-free +deb-src http://security.debian.org/ buster/updates main contrib non-free + +deb http://http.us.debian.org/debian buster-updates main contrib non-free +deb-src http://http.us.debian.org/debian buster-updates main contrib non-free + +deb http://http.debian.net/debian buster-backports main contrib non-free +deb-src http://http.debian.net/debian buster-backports main contrib non-free + +deb http://http.us.debian.org/debian unstable main contrib non-free +deb-src http://http.us.debian.org/debian unstable main contrib non-free + +deb http://http.us.debian.org/debian experimental main +deb-src http://http.us.debian.org/debian experimental main diff --git a/fai/config/files/etc/apt/sources.list.d/flidas.list/FLIDAS b/fai/config/files/etc/apt/sources.list.d/flidas.list/FLIDAS new file mode 100644 index 0000000..faec0da --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/flidas.list/FLIDAS @@ -0,0 +1,12 @@ +deb http://mirror.fsf.org/trisquel/ flidas main +deb-src http://mirror.fsf.org/trisquel/ flidas main + +deb http://mirror.fsf.org/trisquel/ flidas-updates main +deb-src http://mirror.fsf.org/trisquel/ flidas-updates main + +deb http://mirror.fsf.org/trisquel/ flidas-security main +deb-src http://mirror.fsf.org/trisquel/ flidas-security main + +# Uncomment this lines to enable the backports optional repository +deb http://mirror.fsf.org/trisquel/ flidas-backports main +deb-src http://mirror.fsf.org/trisquel/ flidas-backports main diff --git a/fai/config/files/etc/apt/sources.list.d/focal.list/ETIONA b/fai/config/files/etc/apt/sources.list.d/focal.list/ETIONA new file mode 120000 index 0000000..25af0ff --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/focal.list/ETIONA @@ -0,0 +1 @@ +FOCAL \ No newline at end of file diff --git a/fai/config/files/etc/apt/sources.list.d/focal.list/FOCAL b/fai/config/files/etc/apt/sources.list.d/focal.list/FOCAL new file mode 100644 index 0000000..a317dfa --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/focal.list/FOCAL @@ -0,0 +1,14 @@ +# multiverse needed for libfdk-aac1, which is actually free +# https://www.gnu.org/licenses/license-list.html#fdk + +###### Ubuntu Main Repos +deb http://archive.ubuntu.com/ubuntu/ focal main universe multiverse +deb-src http://archive.ubuntu.com/ubuntu/ focal main universe multiverse + +###### Ubuntu Update Repos +deb http://archive.ubuntu.com/ubuntu/ focal-security main universe multiverse +deb http://archive.ubuntu.com/ubuntu/ focal-updates main universe multiverse +deb http://archive.ubuntu.com/ubuntu/ focal-backports main universe +deb-src http://archive.ubuntu.com/ubuntu/ focal-security main universe multiverse +deb-src http://archive.ubuntu.com/ubuntu/ focal-updates main universe multiverse +deb-src http://archive.ubuntu.com/ubuntu/ focal-backports main universe diff --git a/fai/config/files/etc/apt/sources.list.d/focal.list/NABIA b/fai/config/files/etc/apt/sources.list.d/focal.list/NABIA new file mode 120000 index 0000000..25af0ff --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/focal.list/NABIA @@ -0,0 +1 @@ +FOCAL \ No newline at end of file diff --git a/fai/config/files/etc/apt/sources.list.d/stretch.list/STRETCH_FREE b/fai/config/files/etc/apt/sources.list.d/stretch.list/STRETCH_FREE new file mode 100644 index 0000000..280fa0a --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/stretch.list/STRETCH_FREE @@ -0,0 +1,11 @@ +deb http://http.us.debian.org/debian stretch main +deb-src http://http.us.debian.org/debian stretch main + +deb http://security.debian.org/ stretch/updates main +deb-src http://security.debian.org/ stretch/updates main + +deb http://http.us.debian.org/debian stretch-updates main +deb-src http://http.us.debian.org/debian stretch-updates main + +deb http://http.debian.net/debian stretch-backports main +deb-src http://http.debian.net/debian stretch-backports main diff --git a/fai/config/files/etc/apt/sources.list.d/stretch.list/STRETCH_NONFREE b/fai/config/files/etc/apt/sources.list.d/stretch.list/STRETCH_NONFREE new file mode 100644 index 0000000..c022d31 --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/stretch.list/STRETCH_NONFREE @@ -0,0 +1,11 @@ +deb http://http.us.debian.org/debian stretch main contrib non-free +deb-src http://http.us.debian.org/debian stretch main contrib non-free + +deb http://security.debian.org/ stretch/updates main contrib non-free +deb-src http://security.debian.org/ stretch/updates main contrib non-free + +deb http://http.us.debian.org/debian stretch-updates main contrib non-free +deb-src http://http.us.debian.org/debian stretch-updates main contrib non-free + +deb http://http.debian.net/debian stretch-backports main contrib non-free +deb-src http://http.debian.net/debian stretch-backports main contrib non-free diff --git a/fai/config/files/etc/apt/sources.list.d/testing.list/TESTING_FREE b/fai/config/files/etc/apt/sources.list.d/testing.list/TESTING_FREE new file mode 100644 index 0000000..031bddf --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/testing.list/TESTING_FREE @@ -0,0 +1,11 @@ +deb http://http.us.debian.org/debian testing main +deb-src http://http.us.debian.org/debian testing main + +deb http://security.debian.org/ testing/updates main +deb-src http://security.debian.org/ testing/updates main + +deb http://http.us.debian.org/debian testing-updates main +deb-src http://http.us.debian.org/debian testing-updates main + +deb http://http.us.debian.org/debian unstable main +deb-src http://http.us.debian.org/debian unstable main diff --git a/fai/config/files/etc/apt/sources.list.d/testing.list/TESTING_NONFREE b/fai/config/files/etc/apt/sources.list.d/testing.list/TESTING_NONFREE new file mode 100644 index 0000000..3b57312 --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/testing.list/TESTING_NONFREE @@ -0,0 +1,11 @@ +deb http://http.us.debian.org/debian testing main contrib non-free +deb-src http://http.us.debian.org/debian testing main contrib non-free + +deb http://security.debian.org/ testing/updates main contrib non-free +deb-src http://security.debian.org/ testing/updates main contrib non-free + +deb http://http.us.debian.org/debian testing-updates main contrib non-free +deb-src http://http.us.debian.org/debian testing-updates main contrib non-free + +deb http://http.us.debian.org/debian unstable main contrib non-free +deb-src http://http.us.debian.org/debian unstable main contrib non-free diff --git a/fai/config/files/etc/apt/sources.list.d/xenial.list/XENIAL b/fai/config/files/etc/apt/sources.list.d/xenial.list/XENIAL new file mode 100644 index 0000000..452f266 --- /dev/null +++ b/fai/config/files/etc/apt/sources.list.d/xenial.list/XENIAL @@ -0,0 +1,11 @@ +###### Ubuntu Main Repos +deb http://us.archive.ubuntu.com/ubuntu/ xenial main universe +deb-src http://us.archive.ubuntu.com/ubuntu/ xenial main universe + +###### Ubuntu Update Repos +deb http://us.archive.ubuntu.com/ubuntu/ xenial-security main universe +deb http://us.archive.ubuntu.com/ubuntu/ xenial-updates main universe +deb http://us.archive.ubuntu.com/ubuntu/ xenial-backports main universe +deb-src http://us.archive.ubuntu.com/ubuntu/ xenial-security main universe +deb-src http://us.archive.ubuntu.com/ubuntu/ xenial-updates main universe +deb-src http://us.archive.ubuntu.com/ubuntu/ xenial-backports main universe diff --git a/fai/config/files/etc/apt/sources.list/DEFAULT b/fai/config/files/etc/apt/sources.list/DEFAULT new file mode 100644 index 0000000..0c5461c --- /dev/null +++ b/fai/config/files/etc/apt/sources.list/DEFAULT @@ -0,0 +1 @@ +# intentionaly left empty. only using sources.list.d diff --git a/fai/config/files/etc/apt/sources.list/GNOME b/fai/config/files/etc/apt/sources.list/GNOME deleted file mode 100644 index 20861df..0000000 --- a/fai/config/files/etc/apt/sources.list/GNOME +++ /dev/null @@ -1,3 +0,0 @@ -deb {%apt_cdn%}/debian {%release%} main -deb {%security_cdn%}/debian-security {%secsuite%} main -deb {%apt_cdn%}/debian {%release%}-updates main diff --git a/fai/config/files/etc/motd/FAIBASE b/fai/config/files/etc/motd/FAIBASE deleted file mode 100644 index 4e5a967..0000000 --- a/fai/config/files/etc/motd/FAIBASE +++ /dev/null @@ -1,3 +0,0 @@ - - -Plan your installation, and FAI installs your plan. diff --git a/fai/config/files/etc/systemd/system/faicheck.service/VOL_BUSTER_BOOTSTRAP b/fai/config/files/etc/systemd/system/faicheck.service/VOL_BUSTER_BOOTSTRAP new file mode 100644 index 0000000..61f5a1f --- /dev/null +++ b/fai/config/files/etc/systemd/system/faicheck.service/VOL_BUSTER_BOOTSTRAP @@ -0,0 +1,11 @@ +[Unit] +Description=check whether to kexec to fai, reboot, or do nothing +After=syslog.target network-online.target + +[Service] +Type=oneshot +ExecStart=/root/fai-check +TimeoutStartSec=60 + +[Install] +WantedBy=multi-user.target diff --git a/fai/config/files/root/.ssh/authorized_keys/.gitignore b/fai/config/files/root/.ssh/authorized_keys/.gitignore new file mode 100644 index 0000000..c078f52 --- /dev/null +++ b/fai/config/files/root/.ssh/authorized_keys/.gitignore @@ -0,0 +1,3 @@ +# empty directory +* +!.gitignore diff --git a/fai/config/files/root/fai-check/VOL_BUSTER_BOOTSTRAP b/fai/config/files/root/fai-check/VOL_BUSTER_BOOTSTRAP new file mode 100755 index 0000000..900c719 --- /dev/null +++ b/fai/config/files/root/fai-check/VOL_BUSTER_BOOTSTRAP @@ -0,0 +1,98 @@ +#!/bin/bash + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + + + +usage() { + cat < deadline )); then + echo "fai-check: hit $NETWORK_TIMOUT_SECS s tftp server timeout" + return 0 + fi + sleep 1 + done + m pxe-kexec -n --ignore-whitelist -l fai-generated faiserver ||: +} + +case $1 in + -f|--force) + try-kexec + exit + ;; +esac + + +first=true +for dev in $(btrfs fi show / | sed -rn 's#^\s*devid\s.*\s([^0-9 ]+)\S+$#\1#p' \ + |sort); do + + # Decide which is my grub_ext partition. see partition.DEFAULT file + # for details + if [[ $(blockdev --getsize64 ${dev}4) == 8388608 ]]; then + # Old partition scheme + grub_extn=${dev}4 + elif [[ $(blockdev --getsize64 ${dev}5) == 8388608 ]]; then + grub_extn=${dev}5 + else + grub_extn=${dev}7 + fi + mount $dev /mnt + if $first; then + if [[ -e /mnt/grubenv ]]; then + set -x + source <(grub-editenv /mnt/grubenv list) + set +x + fi + first=false + # we could just as well check if last_boot != /debianbuster_boostrap + # the intent with this one is just a little clearer. + if [[ $did_fai_check == true ]]; then + grub-editenv /mnt/grubenv set did_fai_check=os_true + # our service does not wait for network-online.target, + # because it will wait for too long when we don't have a network + # connection. So, we wait for 10 seconds. + # ref: https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/ + try-kexec ||: + fi + else + # we make sure there is only 1 grubenv, + # so grub can just find the first one, in whatever order + # if looks at them, which may not be the same as us. + # If the disk dies, we just lose the default boot option, + # we will have to do manual steps to replace it anyways. + rm -f /mnt/gruvenv + fi + umount /mnt +done + +# the check for last_boot is not needed afaik, just sanity check. +if [[ $did_fai_check == true && $last_boot != /debianbuster_boostrap ]]; then + # no need to reboot if we actually want to boot into this os. + reboot +fi diff --git a/fai/config/files/usr/bin/myncq/kd b/fai/config/files/usr/bin/myncq/kd new file mode 100755 index 0000000..2d65edb --- /dev/null +++ b/fai/config/files/usr/bin/myncq/kd @@ -0,0 +1,57 @@ +#!/bin/bash + +if ! test "$BASH_VERSION"; then echo "error: shell is not bash" >&2; exit 1; fi +shopt -s inherit_errexit 2>/dev/null ||: # ignore fail in bash < 4.4 +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" exit status: $?, PIPESTATUS: ${PIPESTATUS[*]}" >&2' ERR + +[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@" + +# https://wiki.archlinux.org/index.php/Solid_state_drive#Resolving_NCQ_errors +# evo-870 doesnt get along well with d16. +# Dmesg gives us an ata number we could disable specifically on the command line, but I've had that number change on me between oses, so reenabling ncq + +upgrub=true +if [[ $1 == no-upgrub ]]; then + upgrub=false +fi + +byid=/dev/disk/by-id/ata-Samsung_SSD_870_QVO_8TB_S5VUNG0N900656V +if [[ ! -e $byid ]]; then + # not plugged in we assume + exit 0 +fi + +dev=$(readlink $byid) +if [[ ! $dev ]]; then + exit 1 +fi + +dev=${dev##*/} + +depth=$(cat /sys/block/$dev/device/queue_depth) +if [[ $depth != 0 ]]; then + if grep -qF libata.force=noncq /proc/cmdline; then + echo $0: warning, cant change queue_depth due to globally disabled ncq + else + echo 1 >/sys/block/$dev/device/queue_depth + fi +fi + +sys=$(readlink /sys/block/$dev) +ata=${sys#*/*/*/*/ata} +ata=${ata%%/*} + +arg=libata.force=${ata}.00:noncq + +if ! grep "^GRUB_CMDLINE_LINUX_DEFAULT=.*[\" ]${arg//./\\.}[\" ]" /etc/default/grub; then + sed -ri "s/([\" ])libata.force=[^ ]+ */\1/g;s/^GRUB_CMDLINE_LINUX_DEFAULT=\"(.*)/GRUB_CMDLINE_LINUX_DEFAULT=\"$arg \1/" /etc/default/grub + if $upgrub; then + echo "$0: warning: grub updated. you may want to reboot" + if type -P update-grub2 &>/dev/null; then + update-grub2 + else + update-grub + fi + fi +fi diff --git a/fai/config/hooks/extrbase.DEFAULT b/fai/config/hooks/extrbase.DEFAULT new file mode 100755 index 0000000..1d1a931 --- /dev/null +++ b/fai/config/hooks/extrbase.DEFAULT @@ -0,0 +1,7 @@ +#!/bin/bash + +# exit for any vm which is not our test vm +if ifclass VM && ! ifclass demohost; then + exit 0 +fi + diff --git a/fai/config/hooks/instsoft.DEBIAN b/fai/config/hooks/instsoft.DEBIAN index 35ac306..34e6ebb 100755 --- a/fai/config/hooks/instsoft.DEBIAN +++ b/fai/config/hooks/instsoft.DEBIAN @@ -1,5 +1,6 @@ #! /bin/bash +set -x # if package locales will be installed, then install it early, before # other packages if [ $FAI_ACTION != "install" -a $FAI_ACTION != "dirinstall" ]; then @@ -7,7 +8,6 @@ if [ $FAI_ACTION != "install" -a $FAI_ACTION != "dirinstall" ]; then fi fcopy -Bi /etc/apt/apt.conf.d/force_confdef -ainsl -a /etc/ucf.conf "^conf_force_conffold=YES" # in case the locales are already included inside the base file (Ubuntu) if [ -f $target/usr/sbin/locale-gen ]; then diff --git a/fai/config/hooks/instsoft.DEFAULT b/fai/config/hooks/instsoft.DEFAULT new file mode 100755 index 0000000..07adc1d --- /dev/null +++ b/fai/config/hooks/instsoft.DEFAULT @@ -0,0 +1,44 @@ +#!/bin/bash + +# These are things we can do before package_config packages get installed. + +# exit for any vm except demohost, or if we are doing a dirinstall +if ifclass VM && ! ifclass demohost || ifclass VOL_BUSTER_BOOTSTRAP || [[ ! $FAI_ACTION || $FAI_ACTION = dirinstall ]]; then + exit 0 +fi + +keyfile=/var/lib/fai/config/distro-install-common/luks/host-$HOSTNAME +f=$target/root/keyscript +cat > $f <&2' ERR + +if [[ $EUID != 0 ]]; then + echo "$0: error: need to run as root" >&2 + exit 1 +fi + +# for calling outside of FAI: +# fai-redep +# +# source /b/fai/fai-wrapper +# - set any appropriate classes with: fai-setclass OPT1... which sets CLASS_OPT1=true... +# or run eval-fai-classfile FILE. +# - Set a VOL_DISTROVER (if not doing mkroot2) eg: +# fai-setclass VOL_NABIA +# +# OPTIONS: +# +# mkroot2: for running outside of fai and setting up the root2/boot2 luks and btrfs +# +# environment variables: +# +# HOSTNAME: if frodo, we exclude 2 devices from the /boot array, which +# the bios does not see. if demohost, we set the luks password to just +# 'x'. +# +# SPECIAL_DISK: For use outside of fai. A base disk name like +# /dev/sdk. If set, we just cryptsetup and partition this one disk then +# exit. This is useful for partitioning a disk in preparation to replace +# a failed or failing disk from a raid10 array. +# +# classes: +# +# REPARTITION: forces repartitioning even if we detect the proper amount +# of partitions already exist. +# +# NOWIPE: use existing subvolumes if they exist +# +# ROTATIONAL: forces to install onto hdds instead of sdds. normally sdds +# are chosen if they exist. +# +# PARTITION_PROMPT: command line prompt before partitioning +# +# RAID0: forces raid0 filesystem. Normally with 4+ devices, we use +# raid10. +# RAID1: forces raid1 filesystem. + +mkroot2=false +if [[ $1 ]]; then + case $1 in + mkroot2) + mkroot2=true + ;; + *) + echo "$0: error: unsupported arg: $1" >&2 + exit 1 + ;; + esac +fi + + +if [[ $SPECIAL_DISK ]]; then + export CLASS_REPARTITION=true +fi + +# # fai's setup-storage won't do btrfs on luks, +# # so we do it ourself :) +# inspiration taken from files in fai-setup-storage package + +# if we are not running in fai, skiptask won't be defined, so carry on. +skiptask partition || ! type skiptask + +if ! type -p devbyid; then + for d in $FAI/distro-install-common \ + /a/bin/fai/fai/config/distro-install-common $FAI $PWD; do + [[ -d $d ]] || continue + if [[ -e $d/devbyid ]]; then + devbyid=$d/devbyid + devbyid() { $devbyid "$@"; } + break + fi + done + if [[ ! $devbyid ]]; then + echo "$0: error: failed to find devbyid script" >&2 + exit 1 + fi +fi + + + +#### begin configuration + +# this is the ordering of the /dev/sdaX, but +# the ordering of the partition layout goes like this: +# bios_grub +# grub_ext +# efi +# root +# swap +# boot + +rootn=1 +root2n=2 +swapn=3 +bootn=4 +boot2n=5 +efin=6 +# ext partition so grub can write persistent variables, +# so it can do a one time boot. grub can't write to +# btrfs or any cow fs because it's more +# more complicated to do and they don't want to. +grub_extn=7 +# bios boot partition, +# https://wiki.archlinux.org/index.php/GRUB +bios_grubn=8 +even_bign=9 +lastn=$bios_grubn + + + +##### end configuration + + +add-part() { # add partition suffix to $dev + local d part + if [[ $# == 1 ]]; then + d=$dev + part=$1 + else + d=$1 + part=$2 + fi + echo $d-part$part +} + +rootdev() { add-part $@ $rootn; } +root2dev() { add-part $@ $root2n; } +swapdev() { add-part $@ $swapn; } +bootdev() { add-part $@ $bootn; } +boot2dev() { add-part $@ $boot2n; } +efidev() { add-part $@ $efin; } +grub_extdev() { add-part $@ $grub_extn; } +bios_grubdev() { add-part $@ $bios_grubn; } +even_bigdev() { add-part $@ $even_bign; } + +crypt-dev() { echo /dev/mapper/crypt_dev_${1##*/}; } +crypt-name() { echo crypt_dev_${1##*/}; } +root-cryptdev() { crypt-dev $(rootdev $@); } +root2-cryptdev() { crypt-dev $(root2dev $@); } +swap-cryptdev() { crypt-dev $(swapdev $@); } +root-cryptname() { crypt-name $(rootdev $@); } +root2-cryptname() { crypt-name $(root2dev $@); } +swap-cryptname() { crypt-name $(swapdev $@); } + +dev-mib() { + local d=${1:-$dev} + echo $(( $(parted -m $d unit MiB print | \ + sed -nr "s#^/dev/[^:]+:([0-9]+).*#\1#p") - 1)) +} + +luks-setup() { + local luksdev="$1" + # when we move to newer than trisquel 9, we can remove + # --type luks1. We can also check on cryptsetup --help | less /compil + # to see about the other settings. Default in debian 9 is luks2. + # You can convert from luks2 to luks 1 by adding a temporary key: + # cryptsetup luksAddKey --pbkdf pbkdf2 + # then remove the new format keys with cryptsetup luksRemoveKey + # then cryptsetup convert DEV --type luks1, then readd old keys and remove temp. + yes YES | cryptsetup luksFormat $luksdev $luks_file || [[ $? == 141 ]] + yes "$lukspw" | \ + cryptsetup luksAddKey --key-file $luks_file \ + $luksdev || [[ $? == 141 ]] + # background: Keyfile and password are treated just + # like 2 ways to input a passphrase, so we don't actually need to have + # different contents of keyfile and passphrase, but it makes some + # security sense to a really big randomly generated passphrase + # as much as possible, so we have both. + # + # This would remove the keyfile. + # yes 'test' | cryptsetup luksRemoveKey /dev/... \ + # /key/file || [[ $? == 141 ]] + cryptsetup luksOpen $luksdev $(crypt-name $luksdev) --key-file $luks_file +} + +##### end function defs + +if ifclass REPARTITION; then + partition=true # force a full wipe +else + partition=false # change to true to force a full wipe +fi +if ifclass NOWIPE; then + wipe=false +else + wipe=true +fi + +if (($(nproc) > 2)); then + mopts=,compress=zstd +fi + +declare -A disk_excludes +if ! $mkroot2 && ! ifclass USE_MOUNTED; then + ## ignore disks that are mounted, eg when running from fai-cd + while read -r l; do + eval "$l" + if [[ ! $PKNAME ]]; then + PKNAME="$KNAME" + fi + if [[ $MOUNTPOINT ]]; then + disk_excludes[$PKNAME]=true + fi + done < <(lsblk -nP -o KNAME,MOUNTPOINT,PKNAME) +fi + +hdds=() +ssds=() +# this excludes usb. note: i may encounter some other type in the future. +for disk in $(lsblk -do name,tran -n | awk '$2 ~ "^(sata|nvme)$" { print $1 }'); do + if [[ ${disk_excludes[$disk]} ]]; then + continue + fi + case $(cat /sys/block/$disk/queue/rotational) in + 0) ssds+=(/dev/$disk) ;; + 1) hdds+=(/dev/$disk) ;; + *) echo "$0: error: unknown /sys/block/$disk/queue/rotational: \ +$(cat $disk/queue/rotational)"; exit 1 ;; + esac +done + +# install all ssds, or if there are none, all hdds. +# Note, usb flash disks are seen as rotational, which is +# very odd, but convenient for ignoring them here. +# TODO: find a reliable way to ignore them. +if ! ifclass ROTATIONAL && (( ${#ssds[@]} > 0 )); then + short_devs=( ${ssds[@]} ) +else + short_devs=( ${hdds[@]} ) +fi + +# check if the partitions exist have the right filesystems +#blkid="$(blkid -s TYPE)" +for dev in ${short_devs[@]}; do + if $partition; then break; fi + y=$(readlink -f $dev) + arr=($y?*) + if (( ${#arr[@]} < lastn )); then + partition=true + fi + # On one system, blkid is missing some partitions. + # maybe we need a flag, like FUZZY_BLKID or something, so we + # can check that at least some exist. + # for x in "`rootdev`: TYPE=\"crypto_LUKS\"" "`bootdev`: TYPE=\"btrfs\""; do + # echo "$blkid" | grep -Fx "$x" &>/dev/null || partition=true + # done +done + +if $partition && ifclass PARTITION_PROMPT; then + echo "Press any key except ctrl-c to continue and partition these drives:" + echo " ${short_devs[*]}" + read -r +fi + +devs=() +shopt -s extglob +for short_dev in ${short_devs[@]}; do + devs+=($(devbyid $short_dev)) +done +if [[ ! ${devs[0]} ]]; then + echo "$0: error: failed to detect devs" >&2 + exit 1 +fi + +boot_space=0 +first=true +boot_devs=() +boot2_devs=() +for dev in ${devs[@]}; do + if ifclass frodo; then + # I ran into a machine where the bios doesn't know about some disks, + # so 1st stage of grub also doesn't know about them. + # Also, grub does not support mounting degraded btrfs as far as + # I can tell with some googling. + # From within an arch install env, I could detect them by noting + # their partitions were mixed with the next disk in /dev/disk/by-path, + # and I have mixed model disks, and I could see the 8 models which showed + # up in the bios, and thus see which 2 models were missing. + # hdparm -I /dev/sdh will give model info in linux. + # However, in fai on jessie, /dev/disk/by-path dir doesn't exist, + # and I don't see another way, so I'm hardcoding them. + # We still put grub on them and partition them the same, for uniformity + # and in case they get moved to a system that can recognize them, + # we just exclude them from the boot filesystem. + cd /dev/disk/by-id/ + bad_disk=false + for id in ata-TOSHIBA_MD04ACA500_8539K4TQFS9A \ + ata-TOSHIBA_MD04ACA500_Y5IFK6IJFS9A; do + if [[ $(readlink -f $id) == "$(readlink -f $dev)" ]]; then + bad_disk=true + break + fi + done + if ! $bad_disk; then + boot_devs+=($(bootdev)) + boot2_devs+=($(boot2dev)) + fi + else + boot_space=$(( boot_space + $(parted -m $dev unit MiB print | \ + sed -nr "s#^/dev/[^:]+:([0-9]+).*#\1#p") - 1)) + boot_devs+=($(bootdev)) + boot2_devs+=($(boot2dev)) + fi + if $first && [[ $boot_devs ]]; then + first_efi=$(efidev) + first_grub_extdev=$(grub_extdev) + first=false + fi +done +first_boot_dev=${boot_devs[0]} + +even_raid=false +if ifclass RAID0 || (( ${#boot_devs[@]} == 1 )); then + raid_level=0 +elif ifclass RAID1 || (( ${#boot_devs[@]} <= 3 )); then + if (( ${#boot_devs[@]} == 2 )); then + even_raid=true + fi + raid_level=1 +else + raid_level=10 +fi + +### Begin calculate boot partition space +# due to raid duplication +case $raid_level in + 1*) boot_space=$(( boot_space / 2 )) ;; +esac +if (( boot_space > 60000 )); then + # this is larger than needed for several /boot subvols, + # becuase I keep a minimal debian install on it for + # recovery needs and for doing pxe-kexec. + boot_mib=10000 + root2_mib=200000 + boot2_mib=2000 +elif (( boot_spa_ce > 30000 )); then + boot_mib=$(( 5000 + (boot_space - 30000) / 2 )) + root2_mib=100 + boot2_mib=100 +else + # Small vms don't have room for /boot recovery. With 3 kernels + # installed, i'm using 132M on t8, so this seems like plenty of + # room. note: rhel 8 recomments 1g for /boot. + boot_mib=500 + root2_mib=100 + boot2_mib=100 +fi +case $raid_level in + 1*) + boot_mib=$(( boot_mib * 2 )) + boot2_mib=$(( boot2_mib * 2 )) + root2_mib=$(( root2_mib * 2 )) + ;; +esac +### end calculate boot partition space + + + +if [[ ! $DISTRO ]]; then + if ifclass VOL_BUSTER_BOOTSTRAP; then + DISTRO=debianbuster_bootstrap + elif ifclass VOL_STRETCH; then + DISTRO=debianstretch + elif ifclass VOL_BUSTER; then + DISTRO=debianbuster + elif ifclass VOL_BULLSEYE; then + DISTRO=debianbullseye + elif ifclass VOL_TESTING; then + DISTRO=debiantesting + elif ifclass VOL_XENIAL; then + DISTRO=ubuntuxenial + elif ifclass VOL_BIONIC; then + DISTRO=ubuntubionic + elif ifclass VOL_FOCAL; then + DISTRO=ubuntufocal + elif ifclass VOL_FLIDAS; then + DISTRO=trisquelflidas + elif ifclass VOL_ETIONA; then + DISTRO=trisqueletiona + elif ifclass VOL_NABIA; then + DISTRO=trisquelnabia + elif $mkroot2; then + : + else + echo "PARTITIONER ERROR: no distro class/var set" >&2 + exit 1 + fi +fi + + +bpart() { # btrfs a partition + case $raid_level in + 0) mkfs.btrfs -f $@ ;; + 1) mkfs.btrfs -f -m raid1 -d raid1 $@ ;; + 10) mkfs.btrfs -f -m raid10 -d raid10 $@ ;; + esac +} + + +if [[ ! $luks_dir ]]; then + # see README for docs about how to create these + luks_dir=$FAI/distro-install-common/luks + if [[ ! -d $luks_dir ]]; then + luks_dir=/q/root/luks + fi + if [[ ! -d $luks_dir ]]; then + echo "$0: error: no luks_dir found" >&2 + exit 1 + fi +fi + +luks_file=$luks_dir/host-$HOSTNAME +if [[ ! -e $luks_file ]]; then + hostkeys=($luks_dir/host-*) + # if there is only one key, we might be deploying somewhere + # where dhcp doesnt give us a proper hostname, so use that. + if [[ ${#hostkeys[@]} == 1 && -e ${hostkeys[0]} ]]; then + luks_file=${hostkeys[0]} + else + echo "$0: error: no key for hostname at $luks_file" >&2 + exit 1 + fi +fi + +# # note, corresponding changes in /b/ds/keyscript-{on,off} +if ifclass demohost; then + lukspw=x +elif [[ -e $luks_dir/$HOSTNAME ]]; then + lukspw=$(cat $luks_dir/$HOSTNAME) +else + lukspw=$(cat $luks_dir/iank) +fi + + +first_root_crypt=$(root-cryptdev ${devs[0]}) + +# 1.5 x based on https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Installation_Guide/sect-disk-partitioning-setup-x86.html#sect-custom-partitioning-x86 +swap_mib=$(( $(grep ^MemTotal: /proc/meminfo | \ + awk '{print $2}') * 3/(${#devs[@]} * 2 ) / 1024 )) + +mkdir -p /tmp/fai +root_devs=() +for dev in ${devs[@]}; do + root_devs+=($(rootdev)) +done +shopt -s nullglob + +# We write to these files instead of just /etc/fstab, /etc/crypttab, +# because these are filesystems created after our current root, and so +# this allows us to update other root filesystems too. +rm -f /mnt/root/root2-{fs,crypt}tab +if $mkroot2; then + if $partition; then + echo $0: error: found partition=true but have mkroot2 arg + exit 1 + fi + for dev in ${devs[@]}; do + luks_file=$luks_dir/host-amy + lukspw=$(cat $luks_dir/amy) + luks-setup $(root2dev) + cat >>/mnt/root/root2-crypttab <>/mnt/root/root2-fstab < 0 )) || exit 1 + done + done + done + fi + ### end wipefs + + + # When we have 2 disks of at least 100g difference in size, + # make an extra partition on the end of the bigger one. + even_big_part=false + even_diff_min=100000 + if $even_raid; then + smalli=0 + bigi=1 + if (( $(dev-mib ${devs[0]}) >= $(dev-mib ${devs[1]}) )); then + smalli=1 + bigi=0 + fi + disk_mib=$(dev-mib ${devs[smalli]}) + even_big_dev=${devs[bigi]} + even_big_mib=$(dev-mib $even_big_dev) + if (( even_big_mib - disk_mib > even_diff_min )); then + even_big_part=true + fi + fi + + for dev in ${devs[@]}; do + if [[ $SPECIAL_DISK ]]; then + dev=$(devbyid $SPECIAL_DISK) + fi + + # parted will round up the disk size. Do -1 so we can have + # fully 1MiB unit partitions for easy resizing of the last partition. + # Otherwise we would pass in -0 for the end argument for the last partition. + # + # Note: parted print error output is expected. example: + # Error: /dev/vda: unrecognised disk label + if ! $even_raid; then + disk_mib=$(dev-mib) + fi + + boot_part_mib=$(( boot_mib / ${#boot_devs[@]} )) + boot2_part_mib=$(( boot2_mib / ${#boot_devs[@]} )) + root2_part_mib=$(( root2_mib / ${#root_devs[@]} )) + root_end=$(( disk_mib - root2_part_mib - swap_mib - boot_part_mib - boot2_part_mib )) + root2_end=$(( root_end + root2_part_mib )) + swap_end=$(( root2_end + swap_mib )) + boot_end=$(( swap_end + boot_part_mib )) + + parted -s $dev mklabel gpt + # MiB because parted complains about alignment otherwise. + pcmd="parted -a optimal -s -- $dev" + # root partition, the main big one + $pcmd mkpart primary ext3 524MiB ${root_end}MiB + # without naming, systemd gives us misc errors like: + # dev-disk-by\x2dpartlabel-primary.device: Dev dev-disk-by\x2dpartlabel-primary.device appeared twice + $pcmd name $rootn root + # root2 partition + $pcmd mkpart primary ext3 ${root_end}MiB ${root2_end}MiB + $pcmd name $root2n root2 + # normally a swap is type "linux-swap", but this is encrypted swap. using that + # label will confuse systemd. + # swap partition + $pcmd mkpart primary "" ${root2_end}MiB ${swap_end}MiB + $pcmd name $swapn swap + # boot partition + $pcmd mkpart primary "" ${swap_end}MiB ${boot_end}MiB + $pcmd name $bootn boot + # boot2 partition + $pcmd mkpart primary "" ${boot_end}MiB ${disk_mib}MiB + $pcmd name $boot2n boot2 + # uefi partition. efi sucks, half a gig, rediculous. + $pcmd mkpart primary "fat32" 12MiB 524MiB + $pcmd name $efin efi + $pcmd set $efin esp on + # note, this is shown here: https://support.system76.com/articles/bootloader/ + # but not mentioned https://wiki.archlinux.org/index.php/EFI_system_partition + # probably not needed + $pcmd set $bootn boot on + $pcmd set $boot2n boot on + # i only need a few k, but googling min size, + # I found someone saying that gparted required + # required at least 8 because of their hard drive cylinder size. + # And 8 is still very tiny. + # grub_ext partition + $pcmd mkpart primary "ext2" 4MiB 12MiB + $pcmd name $grub_extn grubext + # gpt ubuntu cloud image uses ~4 mb for this partition. fai uses 1 MiB. + # so, I use 3, whatever. + # note: parted manual saying cheap flash media + # should to start at 4. + # biols grub partition + $pcmd mkpart primary "" 1MiB 4MiB + $pcmd name $bios_grubn biosgrub + $pcmd set $bios_grubn bios_grub on + if $even_big_part && [[ $dev == "$even_big_dev" ]]; then + $pcmd mkpart primary ext3 ${disk_mib}MiB ${even_big_mib}MiB + $pcmd name $even_bign even_big + fi + + # the mkfs failed before on a vm, which prompted me to add + # sleep .1 + # then it failed again on a physical machine + # with: + # Device /dev/disk/by-id/foo doesn't exist or access denied, + # so I added a wait until it existed. + # Then I added the mkfs.ext2, which claimed to succeed, + # but then couldn't be found upon reboot. In that case we didn't + # wait at all. So I've added a 3 second minimum wait. + secs=0 + while [[ ! -e $(bios_grubdev) ]] && (( secs < 10 )); do + sleep 1 + secs=$((secs +1)) + done + sleep 3 + + mkfs.fat -F32 $(efidev) + + if $even_big_part && [[ $dev == "$even_big_dev" ]]; then + luks-setup $(even_bigdev) + mkfs.btrfs -f $(crypt-dev $(even_bigdev)) + fi + + # Holds just a single file, rarely written, so + # use ext2, like was often used for the /boot partition. + # This exists because grub can only persist data to a non-cow fs. + # And we use persisting a var in grub to do a one time boot. + # We could pass the data on the kernel command line and persist it + # to grubenv after booting, but that relies on the boot always succeeding. + # This is just a bit more robust, and it could work for booting + # into ipxe which can't persist data, if we ever got that working. + mkfs.ext2 $(grub_extdev) + luks-setup $(rootdev) + + if [[ $SPECIAL_DISK ]]; then + exit 0 + fi + done + ls -la /dev/btrfs-control # this was probably for debugging... + sleep 1 + bpart $(for dev in ${devs[@]}; do root-cryptdev; done) + bpart ${boot_devs[@]} +else + for dev in ${devs[@]}; do + if [[ -e /dev/mapper/$(root-cryptname) ]]; then + continue + fi + cryptsetup luksOpen $(rootdev) $(root-cryptname) \ + --key-file $luks_file + done + sleep 1 +fi + + +if $wipe && [[ $DISTRO != debianbuster_bootstrap ]]; then + # bootstrap distro doesn't use separate encrypted root. + mount -o subvolid=0 $first_root_crypt /mnt + # systemd creates subvolumes we want to delete. + s=($(btrfs subvolume list --sort=-path /mnt | + sed -rn "s#^.*path\s*(root_$DISTRO/\S+)\s*\$#\1#p")) + for subvol in ${s[@]}; do btrfs subvolume delete /mnt/$subvol; done + btrfs subvolume set-default 0 /mnt + [[ ! -e /mnt/root_$DISTRO ]] || btrfs subvolume delete /mnt/root_$DISTRO + + ## create subvols ## + cd /mnt + + btrfs subvolume create root_$DISTRO + + # could set default subvol like this, but no reason to. + # btrfs subvolume set-default \ + # $(btrfs subvolume list . | grep "root_$DISTRO$" | awk '{print $2}') . + + # For raid systems, cow allows for error correction, for non-raid systems, + # protects root fs from having the plug pulled. Reprovisioning a root + # subvol is not my favorite thing to do. + # # no cow on the root filesystem. it's setup is fully scripted, + # # if it's messed up, we will just recreated it, + # # and we can get better perf with this. + # # I can't remember exactly why, but this is preferable to mounting with + # # -o nodatacow, I think because subvolumes inherit that. + # chattr -Rf +C root_$DISTRO + cd / + umount /mnt +fi + +mount -o subvolid=0 $first_boot_dev /mnt +cd /mnt +btrfs subvolume set-default 0 /mnt # already default, just ensuring it. + +# for libreboot systems. grub2 only reads from subvolid=0 +mkdir -p /mnt/grub2 +cp $FAI/distro-install-common/libreboot_grub.cfg /mnt/grub2 + +if [[ $DISTRO == debianbuster_bootstrap ]]; then + # this is just convenience for the libreboot_grub config + # so we can glob the other ones easier. + boot_vol=$DISTRO +else + boot_vol=boot_$DISTRO +fi +if $wipe && [[ -e /mnt/$boot_vol ]]; then + btrfs subvolume delete /mnt/$boot_vol +fi +if [[ ! -e /mnt/$boot_vol ]]; then + btrfs subvolume create $boot_vol +fi +cd / +umount /mnt +## end create subvols ## + +dev=${boot_devs[0]} +mount $first_grub_extdev /mnt +grub-editenv /mnt/grubenv set did_fai_check=true +grub-editenv /mnt/grubenv set last_boot=/$boot_vol +umount /mnt + +fstabstd=x-systemd.device-timeout=30s,x-systemd.mount-timeout=30s +if [[ $DISTRO == debianbuster_bootstrap ]]; then + cat > /tmp/fai/fstab </tmp/fai/disk_var.sh < /tmp/fai/fstab <>/tmp/fai/crypttab <> /tmp/fai/fstab </tmp/fai/disk_var.sh <>/tmp/fai/crypttab <> /tmp/fai/fstab < $target/etc/apt/sources.list -# external mirror -deb $ubuntumirror/ubuntu $ubuntudist main restricted universe multiverse -deb $ubuntumirror/ubuntu $ubuntudist-updates main restricted universe multiverse -deb $ubuntumirror/ubuntu $ubuntudist-security main restricted universe multiverse -EOM - - # https://lists.uni-koeln.de/pipermail/linux-fai/2016-July/011398.html # In Ubuntu 16.04 (but not 14.04), the locales configuration mechanism has # changed. There is a /var/lib/dpkg/info/locales.config file, which diff --git a/fai/config/package_config/DEBIAN b/fai/config/package_config/DEBIAN index fe7cff7..c1cb0bf 100644 --- a/fai/config/package_config/DEBIAN +++ b/fai/config/package_config/DEBIAN @@ -1,19 +1,6 @@ -PACKAGES install-norec -apt-transport-https # is only needed for stretch -debconf-utils -file -less -linuxlogo -rsync -openssh-client openssh-server -time -procinfo -nullmailer -eject -locales -console-setup kbd -pciutils usbutils -unattended-upgrades +# otherwise sshd takes like 10 seconds to start +PACKAGES install BUSTER +haveged PACKAGES install NONFREE # you may want these non-free kernel drivers @@ -34,6 +21,8 @@ memtest86+ PACKAGES install CHROOT linux-image-686-pae- linux-image-amd64- +initramfs-tools-core- +dropbear-initramfs- PACKAGES install AMD64 linux-image-amd64 @@ -43,11 +32,13 @@ PACKAGES install ARM64 grub-efi-arm64 linux-image-arm64 -PACKAGES install GRUB_PC -grub-pc +# this is duplicate with STANDARD. +#PACKAGES install GRUB_PC +#grub-pc + +#PACKAGES install GRUB_EFI +#grub-efi -PACKAGES install GRUB_EFI -grub-efi PACKAGES install LVM lvm2 diff --git a/fai/config/package_config/FLIDAS b/fai/config/package_config/FLIDAS new file mode 100644 index 0000000..9aab2d5 --- /dev/null +++ b/fai/config/package_config/FLIDAS @@ -0,0 +1,6 @@ +PACKAGES install +# resolvconf because if we don't install it now we have to reboot for it to +# take effect. This is explained when you do dpkg-reconfigure resolvconf, +# and may be fixed in future releases. in newer than flidas, we use +# systemd-resolved, so this is not needed. +resolvconf diff --git a/fai/config/package_config/STANDARD b/fai/config/package_config/STANDARD index de178ae..413254f 100644 --- a/fai/config/package_config/STANDARD +++ b/fai/config/package_config/STANDARD @@ -18,20 +18,64 @@ man-db manpages mime-support ncurses-term -netcat-traditional openssh-client pciutils perl +# ian: newer distros dont have python, it gets naturally removed +python +python-minimal +python3 +python3-minimal reportbug telnet traceroute ucf xz-utils +# ian standard packages +# lsof is used in my btrfs util scritps. +# netcat is used for proxy. +keyutils +cryptsetup +btrfs-progs +sudo +bridge-utils +netcat-openbsd +lsof +debconf-utils +file +less +rsync +openssh-client openssh-server +time +procinfo +locales +console-setup kbd +pciutils usbutils +unattended-upgrades +initramfs-tools-core +dropbear-initramfs +apt-transport-https +# ifupdown because etiona doesnt have it by default +# and fai scripts want to call ifquery. +ifupdown +netplan.io- +libnss-resolve +publicsuffix +iso-codes +# new package buster/nabia+ +cryptsetup-initramfs +# https://wiki.debian.org/UsrMerge +usrmerge +# for btrbk +zstd -PACKAGES install-norec STRETCH BUSTER -python -python-minimal +# iank, copied from DEBIAN so it goes into ubuntu too +PACKAGES install GRUB_PC +grub-pc -PACKAGES install-norec BULLSEYE -python3 -python3-minimal +PACKAGES install GRUB_EFI +# normally would have just grub-efi +# but theres a dependency problem with it in nabia: for some reason it depends on +# a version in security, but theres a later version in updates that the system +# really wants to install. +grub-efi-amd64 diff --git a/fai/config/package_config/UBUNTU b/fai/config/package_config/UBUNTU index 47e9e73..e672026 100644 --- a/fai/config/package_config/UBUNTU +++ b/fai/config/package_config/UBUNTU @@ -9,12 +9,13 @@ PACKAGES install AMD64 linux-image-generic memtest86+ -PACKAGES install GRUB_PC -grub-pc -PACKAGES install -ubuntu-minimal -ubuntu-server +PACKAGES install FLIDAS64 XENIAL64 +linux-image-generic-hwe-8.0 + +PACKAGES install NABIA64 FOCAL64 +linux-image-generic- +linux-image-generic-hwe-20.04 PACKAGES install GERMAN language-pack-gnome-de diff --git a/fai/config/package_config/UBUNTU.asc b/fai/config/package_config/UBUNTU.asc new file mode 100644 index 0000000..932dea0 --- /dev/null +++ b/fai/config/package_config/UBUNTU.asc @@ -0,0 +1,597 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2 + +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 +=yMYl +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +Twx6DKLF+3rF5nf1F3Q= +=PBAe +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQGiBEHUUngRBAChnb3mDLFxN/2A/2m2VdF4VduvwWqdzD2AXanEBud8G5HiPYxr +y+nqu5xaiTpcwKxtjgCENd8dhmNA/uDmuoMBlZa7xLTdeGixdmj+VOce7fa6Guq1 +UOhDe/UtjDbRp9bLBhW5qDewL0RLJ1VElnl7rx1Acty9KUz3qQWtIzc4NwCgn/5b +eM2PUbQMHv8CTWf3nYWEFf8EAJSnXbfe1k8R6B+iSqralm7JJPpFRuCsI5Katcw1 +lrZW1Nm1KGTMy2yzi25DRQgQmxbhDgrjAwc+WzVLipXnNfUY1/E7XskwZeIw+TZ+ +jBRJYBRSW0u4vz4bqe/8IoRd9pVHO5By1o5wAi+WnS/2h//QYEmWlULbo6TBentT +mS7GA/9iwKv8F/nFrodffBgw4LSZnNV3dbZGIr5h/ncPMS1g+2QVchsrJyzVjOoK +fO4Gx5/h3Q8keCPaVs/7Dmq8LOIGUfZjG5MCn5rCHHMSOy3x4cU3xd0j/VipJl/b +oF+E8Hll+s87W2RxyfmuSb+BKMCbobac+x664t2R3iUqHQsZQbQ6VWJ1bnR1IENE +IEltYWdlIEF1dG9tYXRpYyBTaWduaW5nIEtleSA8Y2RpbWFnZUB1YnVudHUuY29t +PoheBBMRAgAeBQJB1FJ4AhsDBgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEEYYFDP7 +t1RRrtQAn3lQd/AWEQgasJhvSuaEKE3dX3WjAJwIQPr+zjqUg0b2jRvvHqSviXXU +74hGBBMRAgAGBQJB1KChAAoJEPbdMwIQ+kzR784AoIZy8LRoinb6q2Wf+pD6Hqi7 +IMMoAJ40CFDbgnNiynFZ3GR2oJN9yHIf5YhGBBARAgAGBQJEktmNAAoJEILX1Yqw +qGAr3BQAmgMkTLx3nl6RT2gnpivlVbTLLp5LAJ9h457Bn5ltNr1VLXGu3KZC//M9 +g4hGBBARAgAGBQJElC+xAAoJEDofCI5h4RFTt4IAoJD/UQUco5ooL80k9GouG2zq +vHRRAJ40YXoS/epf8LgVbkPb4dZjemzJL4hGBBARAgAGBQJFB8KdAAoJEFsYwIFs +M98InFwAmwSyPe3rH1NM354zmWVhOXjb1JocAKDYTgJx5GevcIrcrB3ocGZb3I12 +H4hGBBARAgAGBQJFoAF5AAoJEFmBudKHS+vIpowAoIGO+EUF5Xf1hs2baKO5mZ37 +H0oHAJ4vpAexQJY+YHDqGWNkHsvIOWxpZohGBBARAgAGBQJF939rAAoJEDxjyj+g +s+iL5NcAni//R3GSb/5zCcpovhc35J3IEbVnAKCOs+PR2FkkipdYVC/9oRBMcPA5 +aohJBBARAgAJBQJEgFKZAgcAAAoJEFXlrhuO6QQREqUAoIqmXetBaIDlQEwllfH0 +s0Q+du0+AKCutoEkUCdcTw0quWBjOCPZ6alwP4hJBBARAgAJBQJEgcJmAgcAAAoJ +EJnmBLRVGFggKKgAoIYKZVWg8f2dVKm/J1NfNMa3xL7GAJ0c8M21PV5JjrN8mxqV +i6cnxLEA3YhJBBARAgAJBQJFm3DoAgcAAAoJEAeNJY2yIK3G294AnjKonrxlKETw +r/LyArS0bBNv3tmRAJ4wrnEvpFCBgMpOsD3bQ6VEsHzraIjcBBABAgAGBQJDb2Qe +AAoJENHZUgQJ6aHV1A0GALTFLl9rphqzqocobTkHOuORP8b/coYfY8H9sTZGGRV5 +YyWKRXVcf9dvAHxxXFoFSmDnCJL2IQMvwXDCtRWB3DW83cHj4s066RLvdM3Bb7oz +C8MlCiDqQMJ34ui7phVLb3ewkacAwAujzmIzJ9tFijgFV9F/vd0OeYZ6Z500U9Cc +zz5H7/cwCGV/nTMK1298m5t0ULkidupe6+U0zgWC52Wr7VBQODCXnuEJ4qwZngBN +Ld2vHL247soTtYhhwW9v9okBHAQQAQIABgUCROOo9gAKCRBpZyJzLMORIBo2B/4/ +XhrNUZwzu/SsFV/E9o31WSzOjYwpB1GsyrxGSIXCl9oGq2NRWbenl5W2J9gnYsmU +5dniz94c4eQx0gc5cVm1QbFlHTaTVxDMrcHP/348LIWxUNrvpowyO44Yc0W8UtiN +dzKcszsVdK6ksKWrYY7hE/pHhE8Lkiz26v9KRZvgtM08zlD3a6kMJRKO+7YlrQ5y +HMyIl5q40AZpY/6r2qpWwfQgOdr+5qJt8XVmngMGpaj06nsh+ZLOYGuzFYRqa8rG +wa4sNMRPwZe+2p88BKUn611DQGPi6m2Vu+UqfrsaJj7XBu398HTThOxhJnoImX2T ++RSEEHiE12aH7nPd666riQEcBBABAgAGBQJE47ItAAoJEGlnInMsw5EgnroIAIN8 +Q03TbUFG343G0cSst++9xpNWj327nFEUa/80dhnBqoJjwFKs5tyvMaX2+YvCwnBq +oTp0dPe85iVeaSYDt459A9szGuLW0CU+nXbES9jOJ0G2arl+Qd5jsNkihiQYyMjZ +93675WPu2I+4KmNZPfWlE4B7zeMG4fUbHRjujOYrmzHujeIpSDeZCq2DuNWayXzm +MsoSon0QBu2sYZrsKO162vWF1nReiqaXtwMlsqWz0fHjKaEZT7VKeHiXIykj0+X+ ++5WtPFouQURjN8MWkhlfstXqNxaOfOJH5k8+u1Pl40fpbwGUrKT4lbXsXnsCLyex +X/tSpX8f03ojArJb26aJARwEMAECAAYFAkTjqiEACgkQaWcicyzDkSDXDwf/a/f1 +T4443Hg7DFC7FnS/OQe2X3/koIAxztEK/NFdX/fiYRPPtla3vI9OlQrUCsTLeW/q +A/uM8JC/psLqzoid9A+Qx3VNnd87nLaLQtbHxDKf6R0OwRYDOwYOfOY9/Hwnqn2M +v8DcMu+qJl8P0VlzWo6KdkjoLzGaqX1dVHfh4TXoQy+BQqO/8tk/F1zd76KbIB+I +K3YyaZO47B8453RD7OVSs6/xMuxVBY3C2Xwp9LxrBw+k1B2JZ+3PWlEBSXJwKHN6 +DbZWfTVv0CQnj5cgUIl77MMDFb9hPPw/2fwM6OGT8V5hP8UJQZY+6i627IWCMY+g +SBpjScD+JobaCEi03IkBHAQwAQIABgUCROO0uwAKCRBpZyJzLMORIL07B/0cVMwF +kEzQ7NPLm4415ggCgyrc8NgMHHTzR9YmBAk0Rgn1ARZERkuZyrtgbjUY1AjZiHaA +VrNvF/DtrhWcKNQ7snBJdlU3GBVyzEuKTwtmmFsPxrFa/mWmy3S8b6SqejqzKMbh +XtG+LpSXGzidPRzcTUkWZzlIAI9OTL3Ot03z17x/hjRnvnAcOIL6gmEdPMsua4nT +BQIDxnzWoqKqO4dgW3Ooprb63UtutnioEGA4Zz5Eh9qQeRgEleoKLwpy57NZ4aae +T9gD2DX7ffYYuHx5CaCGz73S+0CPK9HrMADS1Pr/xnTMZAmOkxTaA8TMHqlWlM/t +q7kg1wm7u78NVztAiQIcBBABAgAGBQJHNMaeAAoJEAv7hH8/Jy9b3qYP/j9s/GTS +kSg92FZwp7uTxnCHUZjxbA3dzP87zU18S8TOcP7Ce2y1TI0Xbn7lUA8MMhq1mj9/ +NahdHaU8gvLuLHQLBsUU5KvCP+R7Qdns7XC27ohHfmwD1967jDSXXUDVNiyw8L0w +mgtSct8rOPpvYXWPU0gIFcJCzil8W3J7S6Xz/BmUm1gpE0ZYXBWbYot1fbAng0CJ +vuzi1UlwRGsCu+3esHI0x6URQcsibVwmsGK+Ow9u7CaRNyTxJJdnJ52JaAsqh35b +SQVw2IsBztpeerLZq/mJPOMcDRhzbpHL8M0gocO2OrjQuJN0+GXUaQa4c1/8/h5h +1AOBrQJY+YTougjRupa+Koqdd3AljxK9jDtCsKjbbIbTb2tchP0OsShrgreocfWV +7k4kHPSHMlHR3bnRRLgF4lWtrQGYWgCF4YeNQdcsw/upCk8Xar9YhM6e3sRnQzvQ +4jMoyUN2fK0TDwgjM+lWTLfGKQBrXEtfhKBKMb+3npcMKfsCwAajBIJBZX927oHh +XNBrHo+iv81KlmHQU3n32Rqvn5oqc+cbyQJMe9Va5YJEevPzefJVRkeNMmxRtQIf +m/q30ZdEzAbx8BM0qYPNrKeEBoWLKdZS2iZVCI4iNsogLB3EWgyajumC/bbL4p5v +qnIlKN70FUMxdKabTsePWdIAB2DVOz1Cx6bw +=p3ci +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=yMYl +-----END PGP PUBLIC KEY BLOCK----- diff --git a/fai/config/scripts/DEBIAN/10-rootpw b/fai/config/scripts/DEBIAN/10-rootpw index 329e2f6..539f2eb 100755 --- a/fai/config/scripts/DEBIAN/10-rootpw +++ b/fai/config/scripts/DEBIAN/10-rootpw @@ -7,11 +7,6 @@ if [ -n "$ROOTPW" ]; then $ROOTCMD chpasswd --encrypted <<< "root:${ROOTPW}" elif [ -n "$username" ]; then $ROOTCMD usermod -L root - # enable sudo for user - ainsl /etc/sudoers "$username ALL = ALL" - if [ ! -f $target/usr/bin/sudo ]; then - echo "WARNING. Package sudo is not installed" - fi fi exit $error diff --git a/fai/config/scripts/DEBIAN/20-capabilities b/fai/config/scripts/DEBIAN/20-capabilities index ea650fa..b057587 100755 --- a/fai/config/scripts/DEBIAN/20-capabilities +++ b/fai/config/scripts/DEBIAN/20-capabilities @@ -4,6 +4,9 @@ # Restore them here. # +# note on an ubuntu 16.04 system, these caps were set without this script +# running. I wonder if it is actually needed on a debian 8 system. + set -e if [ ! -x $target/sbin/setcap ] ; then diff --git a/fai/config/scripts/DEBIAN/30-interface b/fai/config/scripts/DEBIAN/30-interface deleted file mode 100755 index 4b0dcf4..0000000 --- a/fai/config/scripts/DEBIAN/30-interface +++ /dev/null @@ -1,118 +0,0 @@ -#! /bin/bash - -netplan_yaml() { - # network configuration using ubuntu's netplan.io - local IFNAME="$1" - local METHOD="$2" - echo "Generating netplan configuration for $IFNAME ($METHOD)" >&2 - echo "# generated by FAI" - echo "network:" - echo " version: 2" - echo " renderer: $RENDERER" - case "$RENDERER" in - networkd) - echo " ethernets:" - echo " $IFNAME:" - case "$METHOD" in - dhcp) - echo " dhcp4: true" - ;; - static) - echo " addresses: [$CIDR]" - echo " gateway4: $GATEWAYS_1" - echo " nameservers:" - echo " search: [$DOMAIN]" - echo " addresses: [${DNSSRVS// /, }]" - ;; - esac - esac -} - -iface_stanza() { - # classic network configuration using /etc/network/interfaces - local IFNAME="$1" - local METHOD="$2" - echo "Generating interface configuration for $IFNAME ($METHOD)" >&2 - echo "# generated by FAI" - echo "auto $IFNAME" - echo "iface $IFNAME inet $METHOD" - case "$METHOD" in - static) - echo " address $CIDR" - echo " gateway $GATEWAYS" - ;; - esac -} - -newnicnames() { - - # determine predictable network names only for stretch and above - local name - - [ $do_init_tasks -eq 0 ] && return - [ -z "$NIC1" ] && return - - fields="ID_NET_NAME_FROM_DATABASE ID_NET_NAME_ONBOARD ID_NET_NAME_SLOT ID_NET_NAME_PATH" - for field in $fields; do - name=$(udevadm info /sys/class/net/$NIC1 | sed -rn "s/^E: $field=(.+)/\1/p") - if [[ $name ]]; then - NIC1=$name - return - fi - done - - # try to get altname net dev - name=$(ip link show $NIC1 | awk '/altname / { print $2 }') - if [[ $name ]]; then - NIC1=$name - return - else - echo "$0: error: could not find systemd predictable network name. Using $NIC1." - fi -} - -if [ -z "$NIC1" ]; then - echo "WARNING: \$NIC1 is not defined. Cannot add ethernet to /etc/network/interfaces." -fi -CIDR=$(ip --br ad sh $NIC1|awk '{print $3}') -newnicnames - -case "$FAI_ACTION" in - install|dirinstall) - ifclass DHCPC && METHOD=dhcp || METHOD=static - ifclass XORG && RENDERER=NetworkManager || RENDERER=networkd - - if [ -d $target/etc/netplan ]; then - # Ubuntu >= 17.10 with netplan.io - if [ -n "$NIC1" ]; then - netplan_yaml $NIC1 $METHOD > $target/etc/netplan/01-${NIC1}.yaml - fi - elif [ -d $target/etc/network/interfaces.d ]; then - # ifupdown >= 0.7.41 (Debian >= 8, Ubuntu >= 14.04) - iface_stanza lo loopback > $target/etc/network/interfaces.d/lo - - if [ -n "$NIC1" -a ! -f $target/etc/NetworkManager/NetworkManager.conf ]; then - iface_stanza $NIC1 $METHOD > $target/etc/network/interfaces.d/$NIC1 - fi - else - ( - iface_stanza lo loopback - iface_stanza $NIC1 $METHOD - ) > $target/etc/network/interfaces - fi - - if ! ifclass DHCPC ; then - [ -n "$NETWORK" ] && echo "localnet $NETWORK" > $target/etc/networks - if [ ! -L $target/etc/resolv.conf -a -e /etc/resolv.conf ]; then - cp -p /etc/resolv.conf $target/etc - fi - fi - ;; -esac - -# here fcopy is mostly used, when installing a client for running in a -# different subnet than during the installation -fcopy -iM /etc/resolv.conf -fcopy -iM /etc/network/interfaces /etc/networks - -exit $error diff --git a/fai/config/scripts/DEBIAN/40-misc b/fai/config/scripts/DEBIAN/40-misc index 714be55..54ca499 100755 --- a/fai/config/scripts/DEBIAN/40-misc +++ b/fai/config/scripts/DEBIAN/40-misc @@ -3,6 +3,22 @@ # (c) Thomas Lange, 2001-2016, lange@debian.org # (c) Michael Goetze, 2010-2011, mgoetze@mgoetze.net + +# on ubuntu 16.04 which didn't run this script, some things which didn't +# apply: +# /etc/dpkg/dpkg.cfg.d/fai didn't exist, +# machine-id was already setup. + +# on that system and a debian stretch system, after reboot, +# some things done here don't seem to persist: +# some thin/etc/mtab is symlink somewhere else, +# and mailname is $HOSTNAME.lan + +# the adjtime thing is to support changing the system clock +# from representing UTC (the default) to localtime (windows default). + +# afaik, the only useful thing here for me is setting /etc/hostname + error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code # a list of modules which are loaded at boot time diff --git a/fai/config/scripts/DEMO/10-misc b/fai/config/scripts/DEMO/10-misc deleted file mode 100755 index d77c048..0000000 --- a/fai/config/scripts/DEMO/10-misc +++ /dev/null @@ -1,39 +0,0 @@ -#! /bin/bash - -# (c) Thomas Lange, 2001-2017, lange@debian.org - -error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code - -ifclass XORG && { - fcopy -M /etc/X11/xorg.conf -} - -if ifclass UBUNTU; then - groups="adm cdrom sudo dip plugdev lpadmin sambashare" - $ROOTCMD addgroup --system lpadmin || true - $ROOTCMD addgroup --system sambashare || true -fi - -# add additional user account -if [ -n "$username" ]; then - if ! $ROOTCMD getent passwd $username ; then - $ROOTCMD adduser --disabled-login --gecos "$username user" $username - $ROOTCMD usermod -p "$USERPW" $username - userdir=$($ROOTCMD getent passwd "$username" | cut -d: -f6 ) - - # disable xfce question about default or empty panel - if [ -f $target/etc/xdg/xfce4/panel/default.xml ]; then - xfdir=$userdir/.config/xfce4/xfconf/xfce-perchannel-xml - if [ ! -d $target/$xfdir ]; then - $ROOTCMD mkdir -p $xfdir - $ROOTCMD cp /etc/xdg/xfce4/panel/default.xml $xfdir/xfce4-panel.xml - # group name is the same as user name - $ROOTCMD chown -R $username.$username $userdir/.config - fi - fi - - for g in $groups; do - $ROOTCMD adduser $username $g - done - fi -fi diff --git a/fai/config/scripts/FLIDAS/12-iank b/fai/config/scripts/FLIDAS/12-iank new file mode 100755 index 0000000..27e285e --- /dev/null +++ b/fai/config/scripts/FLIDAS/12-iank @@ -0,0 +1,14 @@ +#!/bin/bash -x + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + +if [[ $EUID != 0 ]]; then + echo "$0: error: expected to be root." + exit 1 +fi + + +# this is needed to enable resolvconf, making /etc/resolv.conf be a symlink. +# why? i dun know, it\'s really dumb. +dpkg-reconfigure -fnoninteractive resolvconf diff --git a/fai/config/scripts/GRUB_EFI/11-iank b/fai/config/scripts/GRUB_EFI/11-iank new file mode 120000 index 0000000..e135aad --- /dev/null +++ b/fai/config/scripts/GRUB_EFI/11-iank @@ -0,0 +1 @@ +../GRUB_PC/11-iank \ No newline at end of file diff --git a/fai/config/scripts/GRUB_PC/10-setup b/fai/config/scripts/GRUB_PC/10-setup index 270b356..e26aa26 100755 --- a/fai/config/scripts/GRUB_PC/10-setup +++ b/fai/config/scripts/GRUB_PC/10-setup @@ -3,6 +3,7 @@ error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code +set -x set -a # do not set up grub during dirinstall @@ -55,6 +56,7 @@ fi # Check if RAID is used for the boot device if [[ $BOOT_DEVICE =~ '/dev/md' ]]; then + GROOT=$($ROOTCMD grub-probe -tdrive -d $BOOT_DEVICE) raiddev=${BOOT_DEVICE#/dev/} # install grub on all members of RAID for device in $(LC_ALL=C perl -ne 'if(/^'$raiddev'\s.+raid\d+\s(.+)/){ $_=$1; s/\d+\[\d+\]//g; s/(nvme.+?)p/$1/g; print }' /proc/mdstat); do @@ -70,13 +72,15 @@ if [[ $BOOT_DEVICE =~ '/dev/md' ]]; then # remove last , mbrdevices=${mbrdevices%, } else - mbrdevices=$(get_stable_devname $BOOT_DEVICE) + for dev in $BOOT_DEVICE; do + mbrdevices=$(get_stable_devname $dev) if [ -z "$mbrdevices" ]; then - # if we cannot find a persistent name (for e.g. in a VM) use old name - mbrdevices=$BOOT_DEVICE + # if we cannot find a persistent name (for e.g. in a VM) use old name + mbrdevices=$dev fi - echo "Installing grub on $BOOT_DEVICE = $mbrdevices" + echo "Installing grub on $dev = $mbrdevices" $ROOTCMD grub-install --no-floppy "$mbrdevices" + done fi echo "grub-pc grub-pc/install_devices multiselect $mbrdevices" | $ROOTCMD debconf-set-selections diff --git a/fai/config/scripts/GRUB_PC/11-iank b/fai/config/scripts/GRUB_PC/11-iank new file mode 100755 index 0000000..8143d4e --- /dev/null +++ b/fai/config/scripts/GRUB_PC/11-iank @@ -0,0 +1,378 @@ +#!/bin/bash -x + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + +if [[ $EUID != 0 ]]; then + echo "$0: error: expected to be root." + exit 1 +fi + +if ! type -t fcopy &>/dev/null; then + sudo apt-get -y install fai-client +fi + +if [[ -e /a/bin/fai/fai-wrapper ]]; then + chroot() { + shift + "$@" + } +fi + + + +# -r = recursive +# -i = ignore non-matching class warnings, always exit 0 +# -B = no backup files +fcopy -riB /boot +# this is also done by FABASE/10-misc by default (without B) +fcopy -riB /root + + +src=$FAI/distro-install-common/shadow +dst=/q/root/shadow +if [[ ! -e $dst && -e $src ]]; then + # outside of fai context, we skip this + mkdir -p $dst + mount -o bind $src $dst +fi + +$FAI/distro-install-common/end + + + +### begin sources install + updates +# these get copied in an earlier stage by fai, but leaving it here since +# I run this as a single post-fai script to update things that have changed. +tmpfile1=$(mktemp) +# this can fail if we need an apt update +chroot $FAI_ROOT /usr/bin/apt-cache policy >$tmpfile1 ||: +fcopy -riBM /etc/apt +tmpfile2=$(mktemp) +chroot $FAI_ROOT /usr/bin/apt-cache policy >$tmpfile2 +if ! diff -q $tmpfile1 $tmpfile2; then + chroot $FAI_ROOT /usr/bin/apt update +fi +# outside of fai, this seems to regularly lead to +# E: Could not get lock /var/lib/apt/lists/lock - open (11: Resource temporarily unavailable) +# so add a sleep. 1 sec is probably way more than needed. +sleep 1 +f=$FAI_ROOT/var/cache/apt/pkgcache.bin +if [[ ! -r $f ]] || (( $(( $(date +%s) - $(stat -c %Y $f ) )) > 60*60*2 )); then + i=0 + while fuser $FAI_ROOT/var/lib/dpkg/lock &>/dev/null; do + sleep 1 + i=$(( i+1 )) + if (( i > 300 )); then + echo "error: timed out waiting for /var/lib/dpkg/lock" >&2 + exit 1 + fi + $ROOTCMD apt-get update + done +fi +### end sources install + updates + + +#### misc configurations +chroot $FAI_ROOT bash <<'EOFOUTER' +if getent group systemd-journal >/dev/null; then + # makes the journal be saved to disk. + mkdir -p /var/log/journal + chmod 755 /var/log/journal +fi +debconf-set-selections <$target/etc/systemd/system/myncq.service <<'EOF' +[Unit] +Description=fix ncq errors + +[Service] +Type=oneshot +ExecStart=/usr/bin/myncq +TimeoutStartSec=20 + +[Install] +# https://www.enricozini.org/blog/2017/debian/systemd-07-devices/ +WantedBy=dev-disk-by\x2did-ata\x2dSamsung_SSD_870_QVO_8TB_S5VUNG0N900656V.device +EOF + + chroot $FAI_ROOT bash <<'EOFOUTER' +systemctl enable myncq.service +/usr/bin/myncq no-upgrub +EOFOUTER + + ;; + # per rubens suggestion to make a d16 more stable + kd|kw) cmdline+=" pci=realloc=off" ;; + esac + fi + + cat >$FAI_ROOT/etc/grub.d/40_custom </dev/null; then + update-grub2 +else + update-grub +fi + +EOF +fi ##### end != dirinstall && != NOCRYPT + + +###### begin network setup #### + +# use old names. the idea of them changing between boots has never +# happened to me and I usually only have 1 wired or other type. +# If I ever do need to care about it, I will. +# Strangely this didn't work on kw, so I added kernel cmdline parameter. +# https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/ +ln -sf /dev/null $target/etc/systemd/network/99-default.link + + +# bitfolk installer handles the rest +case $HOSTNAME in + bk|je) exit 0 ;; +esac + + +# bug fix, somewhere between t9's xorg 1.19.6 +# and 1.20.1-3ubuntu2 +# xserver-xorg-video-nouveau 1:1.0.15-3 +# xorg stopped load nouveau +# https://www.linuxquestions.org/questions/slackware-14/kernel-modules-conflicting-with-nouveau-driver-4175623867/ +# https://nouveau.freedesktop.org/InstallNouveau.html +if lspci|grep -q 'GeForce GTX 6[0-9][0-9]\]'; then + mkdir -p $target/etc/X11/xorg.conf.d/ + cat >$target/etc/X11/xorg.conf.d/10-nouveau.conf <<'EOF' +Section "Device" +Identifier "Device0" +Driver "nouveau" +EndSection +EOF +fi + +# use networkmanager if this host has wireless. +if type -p iw &>/dev/null && [[ $(iw dev) ]]; then + chroot $FAI_ROOT bash <$target/etc/NetworkManager/conf.d/99-iank.conf <<'EOF' +[main] +dns=systemd-resolved +EOF + if [[ $HOSTNAME == frodo ]]; then + cat > $target/etc/network/interfaces <<-EOF +# generated by FAI +auto lo eth0 +iface lo inet loopback +iface eth0 inet static +address 10.3.0.2/16 +EOF + fi + +else + cat > $target/etc/network/interfaces <<-EOF +# generated by FAI +auto lo eth0 +iface lo inet loopback +iface eth0 inet dhcp +iface eth0 inet6 auto +EOF + + # previously had an else condition after + #elif ifclass VM || ifclass LINODE; then + # iface $NIC1 inet manual + # iface br0 inet dhcp + # bridge_ports $NIC1 + # bridge_stp off + # bridge_maxwait 0 + # however, on t9, on startup, br0, became + # rename1 and didn't come up. i dunno why, + # but the bridge is for vms that I rarely use, + # so not bothering to figure it out. + + +fi + +if ifclass LINODE; then + mkdir -p $target/etc/initramfs-tools/conf.d + cat >$target/etc/initramfs-tools/conf.d/mine < $target/etc/network/interfaces <<-EOF +# generated by FAI +auto lo eth0 +iface lo inet loopback +iface eth0 inet dhcp +# for the standard network config, uncomment this and comment the lines after it. +#iface eth0 inet6 auto + +iface eth0 inet6 static +# this is really a /128. it seems like we need to assign it for ipv6 to work. +address 2600:3c00::f03c:91ff:fe6d:baf8/64 +gateway fe80::1 + +iface eth0 inet6 static +# from a requested /64 pool +address 2600:3c00:e000:280::2/64 +EOF + fi +fi + +# I prefer to stick with ifup/down for now. a. networkd is not in its +# own package, so cant use in other init systems. b. it works fine. +chroot $FAI_ROOT bash </dev/null; then + usermod -aG $g iank + fi +done + +if getent group systemd-journal >/dev/null; then + usermod -aG systemd-journal iank +fi +EOFOUTER + +rm -f $target/etc/resolv.conf +ln -s ../run/systemd/resolve/stub-resolv.conf $target/etc/resolv.conf +# needed for bitfolk image +if [[ -e /a/bin/fai/fai-wrapper ]]; then + systemctl enable systemd-resolved + systemctl start systemd-resolved +fi + + + +# reading through the groups that iank is in but user2 isn't, +for g in plugdev audio video cdrom; do + $ROOTCMD usermod -a -G $g user2 +done diff --git a/fai/config/scripts/LAST/50-misc b/fai/config/scripts/LAST/50-misc index a573f50..687700a 100755 --- a/fai/config/scripts/LAST/50-misc +++ b/fai/config/scripts/LAST/50-misc @@ -15,13 +15,15 @@ else fi fi - usedm=$(dmsetup ls 2>/dev/null | egrep -v '^live-rw|^live-base|^No devices found' | wc -l) - if [ $usedm -ne 0 ]; then - if [ ! -d $target/etc/lvm ]; then - echo ERROR: Found lvm devices, but the lvm2 package was not installed - error=1 - fi - fi + # i use dm for crypt, not lvm, so this gives false positive. todo, send patch to remove this + # upstream. + # usedm=$(dmsetup ls 2>/dev/null | egrep -v '^live-rw|^live-base|^No devices found' | wc -l) + # if [ $usedm -ne 0 ]; then + # if [ ! -d $target/etc/lvm ]; then + # echo ERROR: Found lvm devices, but the lvm2 package was not installed + # error=1 + # fi + # fi fi # remove backup files from cfengine, but only if cfengine is installed @@ -45,7 +47,7 @@ if [ $do_init_tasks -eq 1 ] ; then fi # Make sure everything is configured properly -if ifclass DEBIAN ; then +if ifclass DEBIAN || ifclass UBUNTU; then $ROOTCMD apt-get -f install -y fi diff --git a/fai/config/scripts/UBUNTU/90-apt b/fai/config/scripts/UBUNTU/90-apt index 4da7029..440ffb2 100755 --- a/fai/config/scripts/UBUNTU/90-apt +++ b/fai/config/scripts/UBUNTU/90-apt @@ -1,11 +1,16 @@ #! /bin/bash +# iank: we already set mirrors, i dont want to have to add "external mirror" +# to every sources.list. Leaving the rest of this file so future merges will flag up +# changes easier +exit 0 + # check if we already use an external mirror grep -q "external mirror" $target/etc/apt/sources.list && exit 0 cat < $target/etc/apt/sources.list # external mirror -deb $ubuntumirror/ubuntu $ubuntudist main restricted universe multiverse -deb $ubuntumirror/ubuntu $ubuntudist-updates main restricted universe multiverse -deb $ubuntumirror/ubuntu $ubuntudist-security main restricted universe multiverse +deb $ubuntumirror/ubuntu $ubuntudist main universe +deb $ubuntumirror/ubuntu $ubuntudist-updates main universe +deb $ubuntumirror/ubuntu $ubuntudist-security main universe EOM diff --git a/faiserver-disable b/faiserver-disable new file mode 100755 index 0000000..0a9ad8d --- /dev/null +++ b/faiserver-disable @@ -0,0 +1,27 @@ +#!/bin/bash + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + +usage() { + cat </dev/null; then + sed -ri --follow-symlinks '\%^/srv/fai/%d' /etc/exports + exportfs -ra +else + rm -f /etc/apache2/sites-enabled/faiserver.conf + systemctl reload apache2 +fi +EOF diff --git a/faiserver-revm b/faiserver-revm new file mode 100755 index 0000000..bb4650e --- /dev/null +++ b/faiserver-revm @@ -0,0 +1,49 @@ +#!/bin/bash +# Copyright (C) 2019 Ian Kelling +# SPDX-License-Identifier: AGPL-3.0-or-later +set -x + +x="$(readlink -f "$BASH_SOURCE")"; source "${x%/*}/bash-trace" +cd ${x%/*} + +usage() { + cat <&2 + exit 1 +fi + +if [[ ! -d $BASEFILE_DIR ]]; then + printf "%s\n" "$0: error BASEFILE_DIR=$BASEFILE_DIR does not exist" >&2 + exit 1 +fi + + +if ! type -p wget &>/dev/null; then + apt-get install -y wget +fi + +armhf() { + [[ $(dpkg --print-architecture) == armhf ]] +} + +# fai on ubuntu only has official support using the universe repo, but newer +# tends to have less bugs. +wget -O - https://fai-project.org/download/2BF8D9FE074BCDE4.asc | apt-key add - + +update=false +case $base in + stretch|buster|bullseye) + if ! grep -qFx "deb https://fai-project.org/download $base koeln" /etc/apt/sources.list.d/fai.list; then + update=true + fi + cat >/etc/apt/sources.list.d/fai.list <&2 + exit 1 + ;; +esac + +f=/var/cache/apt/pkgcache.bin; +if [[ -r $f ]]; then + cachetime=$(stat -c %Y $f ); + now=$(date +%s) + limittime=$(( now - 60*60*2 )) + if (( cachtime > limittime )); then + update=true + fi +fi + +if $update; then + apt-get update +fi + +# Relevant packages from fai-quickstart depends and fai-server recommends. +# I especially do not wait isc-dhcp-server or an inetd. Also excludes +# nfs-kernel-server. On an android chroot, we don\'t have nfs in the +# kernel, or the ability to install it. +# xorriso is for running fai-cd -a, not strictly need for fai-server +# perl-tk is for fai-monitor-gui +pkgs=(fai-doc tftpd-hpa tar reprepro squashfs-tools binutils xorriso perl-tk) +if modprobe nfsd &>/dev/null; then + pkgs+=(nfs-kernel-server) +else + pkgs+=(apache2) +fi + + +e apt-get install -y ${pkgs[@]} +# confnew since we edit /etc/fai/NFSROOT in an automated way +# fai-client is already a fai-server dependency, but make sure it gets upgraded +e apt-get install --no-install-recommends -y -o Dpkg::Options::=--no-force-confdef -o Dpkg::Options::=--force-confnew fai-server fai-client + +r=http://http.us.debian.org/debian +# like default, but scrap httpredir, and nonfree. +# All my systems should be able to get along without nonfree +# for a base working system afaik. + +cat >/etc/fai/apt/sources.list <>/etc/fai/apt/sources.list <>/etc/fai/apt/sources.list <>/etc/fai/apt/sources.list <>/etc/fai/apt/sources.list <<'EOF' +# deb http://ftp.debian.org/debian buster-backports main +# EOF +# # note, fai doesn\'t look at /etc/fai/apt/preferences.d +# cat >/etc/fai/apt/preferences <<'EOF' +# Package: linux-* firmware-linux-free btrfs-progs +# Pin: release a=buster-backports +# Pin-Priority: 500 +# EOF +# fi + + +$sed -f - /etc/fai/nfsroot.conf <>/etc/fai/fai.conf +# note if this isnt set, the user isnt created +echo "LOGUSER=fai" >>/etc/fai/fai.conf + +# from man fai-make-nfsroot, +# figured out after partitioning ignored my crypt partition + + +cedit /etc/fai/NFSROOT <<'EOF' || [[ $? == 1 ]] +# inserted by faserver-setup +PACKAGES install +cryptsetup +# default one is linux-image-server, doesnt exist anymore +linux-image-amd64 +# default is btrfs-tools which doesnt exist anymore +btrfs-progs +iw +# got an error in error.log about not having gpg. +# system seemed to still install ok, so i havent tested if this fixes it. +gpg +EOF + +if armhf; then + cd /srv/fai + e rm -rf nfsroot + e tar Jxf $basefile + # background: Can't build the nfsroot on my arm system now. First, + # fai-make-nfsroot won't work out of the box. One idea to make it work + # is by installing qemu-user-static, then copying qemu-x86_64-static + # into the nfsroot, and prepending it to chroot commands in + # fai-make-nfsroot, but that fails in odd ways. ls has permissions + # problems on reading directories, various programs segfault + # immediately, cat can't open a file, etc. + + NFSROOT=/srv/fai/nfsroot + TFTPROOT=/srv/tftp/fai + + # test if our copy of setup_tftp has changed in fai-make-nfsroot, + # and if not, run it. + setup_tftp(){ + + # tftp environment + local pxebin + + # jessie+ path + pxebin=$NFSROOT/usr/lib/syslinux/pxelinux.0 + + rm -f $NFSROOT/boot/*.bak + mkdir -p $TFTPROOT/pxelinux.cfg + if ! chmod a+r $NFSROOT/boot/initrd.img-*; then + echo "$0: error: No initrd was created. Check the package name of the linux-image package in /etc/fai/NFSROOT." + exit 1 + fi + cp -p $v $NFSROOT/boot/vmlinu?-* $NFSROOT/boot/initrd.img-* $TFTPROOT + cp -u $pxebin $TFTPROOT + if [ -f $NFSROOT/usr/lib/syslinux/modules/bios/ldlinux.c32 ]; then + cp -u $NFSROOT/usr/lib/syslinux/modules/bios/ldlinux.c32 $TFTPROOT + fi + if [ X$verbose = X1 ]; then + echo "TFTP environment prepared. Enable DHCP and start the TFTP daemon on root $TFTPROOT." + fi + } + diff -u <(type setup_tftp) <(cat <(sed -n '/^setup_tftp(){/,/^}/p' $(which fai-make-nfsroot) ) - <<'EOF' |bash +type setup_tftp +EOF + ) + e setup_tftp + + # -g causes skipping set_root_pw() in fai-make-nfsroot, -ag + # is the only way to make it run without chrooting. the options + # seem contradictory, but it works. + e fai-setup -evag + +else # not armhf + # note, this copies the -B arg to + # /srv/fai/nfsroot/var/tmp/base.tar.xz + e fai-setup -evf -B $basefile + # fai-setup expert mode avoids writing to /var/log/fai/variables + # at least config_src is needed for autodiscover + $sed '/^FAI_CONFIGDIR|^FAI_CONFIG_SRC|^LOGUSER/d' /var/log/fai/variables + tee -a /var/log/fai/variables <<'EOF' +LOGUSER=fai +FAI_CONFIGDIR=/srv/fai/config +FAI_CONFIG_SRC=nfs://faiserver/srv/fai/config +EOF + # make the faiserver also the apt proxy server + apt-get -y install apt-cacher-ng +fi + +rm -f /srv/fai/nfsroot/root/.ssh/known_hosts +if [[ $HOSTNAME == kd ]]; then + keyscan_arg="-p 8989" + fi +key=$(ssh-keyscan $keyscan_arg localhost |& grep -o "ecdsa-sha2-nistp256.*") +for ip in faiserver $(ip addr show up| grep -w '^ *inet' | awk '{print $2}'| cut -d / -f 1 | grep -vF 127.0.0.1); do + echo "$ip $key" >>/srv/fai/nfsroot/root/.ssh/known_hosts +done + + +# serial console +# mainly from +# https://wiki.archlinux.org/index.php/working_with_the_serial_console +# at runtime, running this from ssh worked: +# https://unix.stackexchange.com/questions/242778/what-is-the-easiest-way-to-configure-serial-port-on-linux +# stty -F /dev/ttyS0 115200 cs8 -cstopb -parenb +# /sbin/agetty 115200 ttyS0 linux +# dated info, but validation that this might work on debian: +# https://help.ubuntu.com/community/SerialConsoleHowto +# note in the nfsroot, systemd is not running. +echo "c0:2345:respawn:/sbin/agetty 115200 ttyS0 linux" >>/srv/fai/nfsroot/etc/inittab + +# initially did the basic fai-chboot -Iv $std_arg default +# but found in console that it wanted to mount nfsroot +# to be the same as my dhcp server. +# Figured out to change the root= parameter from googling, +# and seeing fai-chboot -L +# using hostname failed. +# for -f, combined the 2 defaults so it will reboot and print to screen. + +# Add debug to -f flag for more verbose output. + + +# background on choosing apt-cacher-ng: +# googling around a bit finds 2 main solutions: +# http://askubuntu.com/questions/3503/best-way-to-cache-apt-downloads-on-a-lan +# apt-cacher-ng doesn\'t have zeroconf. +# It touts having minimal dependencies, but I don\'t care. +# The downside to squid-deb-proxy is that it\'s config is for specific repos, +# you have to add all the repos you use. +# That is the main reason I use apt-cacher-ng. +# It has a web portal, at http://faiserver:3142/acng-report.html + + +# random fai note: as far as I can tell, profiles are just for putting +# in a selectable boot menu, which I don\'t want. + +# the logsave prompted because the hostname faiserver was uknown. +# Here it was faiserver.lan when running from a faiserver vm. +# When running from a normal host with faiserver alias, it was the normal hosts name. +$sed 's/(^[^,]+,)\S+/\1faiserver/' /srv/fai/nfsroot/root/.ssh/known_hosts +# ditch the logo banner up top which screws with less. +touch /srv/fai/nfsroot/.nocolorlogo diff --git a/faiserver-uninstall b/faiserver-uninstall new file mode 100755 index 0000000..71a4ea0 --- /dev/null +++ b/faiserver-uninstall @@ -0,0 +1,36 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +# 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 should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + +[[ $EUID == 0 ]] || exec sudo "${BASH_SOURCE}" "$@" + +usage() { + cat <. + +TODO: only tested on stretch. deactivation of swap on reboot +probably needs to be fixed on other oses. Even on stretch, +we get 1.5 minutes of waiting for the crypt_dev and normal +boot .device units. + +Warning!!! Backup your data. This script could have bugs in it. + +-n Dry run. Note, this likely won't be the exact commands, + for example, if you are running outside a vm, there will + probably be a reboot required in the middle so the kernel + can know about partition changes. +-r Reboot right away if it's needed. +-f Force running on a distro that has not been tested. +-h|--help Print help and exit. + +SIZE is MiB, or if g is specified, GiB. + +If using multiple devices, SIZE is applied to each device, so total change is +SIZE * devices. + +Note: Uses GNU getopt options parsing style +EOF + exit $1 +} + +reboot_not=false +dry_run=false +force=false + +temp=$(getopt -l help rnfh "$@") || usage 1 +eval set -- "$temp" +while true; do + case $1 in + -r) reboot_now=true; shift ;; + -n) dry_run=true; shift ;; + -f) force=true; shift ;; + -h|--help) usage ;; + --) shift; break ;; + *) echo "$0: Internal error!" ; exit 1 ;; + esac +done + +#### begin arg error checking #### + +if [[ $# != 2 ]]; then + echo "$0: error: expected 2 arguments" + usage 1 +fi + +if [[ $1 != [+-][0-9]* ]]; then + echo "$0: error: bad 1st arg: $1" + usage 1 +fi + +if ! which parted &>/dev/null; then + echo "$0: error: install parted" + exit 1 +fi + +case $2 in swap|boot) : ;; *) echo "$0: error: bad 2nd arg"; usage 1 ;; esac + +if ! $force && ! grep -q 'VERSION=.*stretch' /etc/os-release; then + echo "$0: error: This distro is untested. Only tested version atm is Stretch." + exit 1 +fi + +#### end arg error checking #### + + +boot=true +[[ $2 == boot ]] || boot=false + +op_size=$1 # operator plus size +if [[ $op_size == *g ]]; then + op_size=${op_size%g} + size=${op_size#?} + op=${op_size%$size} + size=$(( $size * 1024 )) + op_size=$op$size +else + size=${op_size#?} +fi + +if [[ $op_size == +* ]]; then + op_size_rev=-$size # rev = reverse + grow=true +else + op_size_rev=+$size + grow=false +fi + +##### end command line parsing ######## + +rootn=1 +swapn=2 +bootn=3 +needs_reboot=false +reboot_script_initialized=false + +pmk() { # partition make + part=$1 + start_op=$2 + end_op=$3 + fs_type="$4" + + # This fails outside a vm, but actually succeeds. also prints this + # message: + # Error: Partition(s) 2 on /dev/sda have been written, but + # we have been unable to inform the kernel of the change, probably + # because it/they are in use. As a result, the old partition(s) + # will remain in use. You should reboot now before making further + # changes. + + if ! p mkpart primary "$fs_type" \ + $((${ptable[start$part]} $start_op)) $((${ptable[end$part]} $end_op)); then + echo "$0: warning: ignoring failure return of mkpart" + fi +} + +def-e() { + if $dry_run; then + e() { echo "+ $@"; } + else + e() { echo "+ $@"; "$@"; } + fi +} + +def-e + + +while read devid dev; do + case $dev in + /dev/dm-[0-9]) + # older oses, it points to /dev/dm-x + dev=$(dmsetup info $dev | sed -rn 's/^\s*Name:\s*(\S*)/\1/p') + ;; + /dev/mapper/*) + dev=${dev#/dev/mapper/} + ;; + *) + echo "$0: error: could not find devicemapper root dev, +make sure you are running from a encrypted root this script is resizing" + exit 1 + ;; + esac + if [[ $dev != crypt_dev_*-part$rootn ]]; then + echo "$0: error: unexpected root device name, +make sure you are running from a encrypted root this script is resizing" + exit 1 + fi + dev=${dev#crypt_dev_} + dev=${dev%-part$rootn} + devpath=/dev/disk/by-id/$dev + echo skip=$size + def-e + declare -A ptable + while IFS=: read id start end psize _; do + [[ $id == [0-9] ]] || continue + ptable[start$id]=start=${start%%[^0-9]*} + ptable[end$id]=${end%%[^0-9]*} + ptable[size$id]=${psize%%[^0-9]*} + done < <(parted -m $devpath unit MiB print) + parted $devpath unit MiB print | tee /root/backup_partition_table_$dev + p() { e parted -a optimal -s -- $devpath unit MiB "$@"; } + unit=systemd-cryptsetup@crypt_dev_$dev-part$swapn + # note systemctl show can test if a unit exists. + if ! e systemctl stop $unit; then + e swapoff -a + fi + # there is a bug in jessie. this and the .swap unit are + # generated from /etc/fstab, and it escapes - to x2d, then doesn't escape it + # when looking for the file to use as swap. so, no swap is working on jessie + # right now. + sleep 1 # dunno if this is needed, + # but systemd likes to do these kind of things in the background. + + # These partition comments seems a little verbose now, but I bet they + # will be helpfull if I read this in more than a week from now. + # <> = deleted partition, () = partition + p rm $swapn # ( root )< swap >( boot ) + + root_resize_cmd="e btrfs fi resize $devid:${op_size_rev}M /" + if $grow; then $root_resize_cmd; fi + # if $grow; then + # < root >< swap >( boot ) + # ( root ) >< swap >( boot ) + # else + # < root >< swap >( boot ) + # ( root >< ) swap >( boot ) + + out=$(p rm $rootn 2>&1) + echo "$out" + + pmk $rootn "" $op_size_rev + + if echo "$out" | \ + grep "but we have been unable to inform the kernel" &>/dev/null; then + needs_reboot=true + fi + if $needs_reboot; then + # note: even if these units don't exist, this will succeed. + e systemctl mask dev-mapper-crypt_swap_$dev$swapn.swap + e systemctl mask systemd-cryptsetup@crypt_swap_$dev$swapn.service + e() { echo "$@" >> /root/finish-resize; } + if ! $reboot_script_initialized; then + reboot_script_initialized=true + rm -rf /root/finish-resize + cat >/root/finish-resize <<'EOF' +#!/bin/bash -x +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR +EOF + chmod +x /root/finish-resize + fi + e swapoff -a + e systemctl unmask systemd-cryptsetup@crypt_swap_$dev$swapn.service + e systemctl unmask dev-mapper-crypt_swap_$dev$swapn.swap + fi + if ! $grow; then + $root_resize_cmd + fi + if $boot; then + # non by-id path, to match what btrfs fi show will tell us + boot_dev_path=$(readlink -f $devpath-part$bootn) + boot_devid=$(btrfs fi show /boot | \ + sed -rn "s#^\s*devid\s+(\S+)\s.*$boot_dev_path#\1#p") + + if ! $grow; then + # shrink boot, move it to a temp file + e btrfs fi resize $boot_devid:${op_size}M /boot + e umount /boot + temp_boot=/root/temp_boot_$dev + e dd bs=1M if=$boot_dev_path of=$temp_boot \ + count=$((${ptable[size$bootn]} $op_size)) + else + e umount /boot + fi + # if $grow; then + # ( root ) >< swap >< boot > + # ( root )( >< swap ) >< boot > + # ( root )( >< swap )( >< boot ) + # else + # ( root >< ) swap >< boot > + # ( root >< )( swap >< ) boot > + # ( root >< )( swap >< )( boot ) + p rm $bootn + pmk $swapn $op_size_rev $op_size_rev "linux-swap" + pmk $bootn $op_size_rev "" + + if $grow; then + e dd bs=1M if=$boot_dev_path of=$boot_dev_path skip=$size + e mount /boot + e btrfs fi resize $boot_devid:${op_size}M /boot + else + e dd bs=1M if=$temp_boot of=$boot_dev_path + e mount /boot + fi + else + # if $grow; then ( root )( >< swap )( boot ) + # else ( root >< )( swap )( boot ) + pmk $swapn $op_size_rev "" "linux-swap" + e systemctl start systemd-cryptsetup@crypt_swap_$dev$swapn + fi +done < <(btrfs fi show / | sed -nr 's#^\s*devid\s*(\S+).* path (.*)$#\1 \2#p') + + +if $boot; then + e rm -rf "/root/temp_boot_*" + e rm -f /root/finish-resize +fi + +if $needs_reboot; then + echo "$0: Reboot, run /root/finish-resize. It's contents:" + cat /root/finish-resize + if $reboot_now; then + echo "$0: rebooting now" + reboot now + exit + fi +fi diff --git a/grub.cfg.autodiscover b/grub.cfg.autodiscover new file mode 100644 index 0000000..31bcb08 --- /dev/null +++ b/grub.cfg.autodiscover @@ -0,0 +1,66 @@ +## grub2 configuration +set default="FAI server via dns" +set timeout=20 + +# make sure we can access partitions +insmod part_msdos +insmod part_gpt +insmod all_video +insmod gfxterm + +set gfxmode=auto +set color_normal=white/black +set color_highlight=red/black +set menu_color_normal=white/black +set menu_color_highlight=black/yellow + + +# ian: Added this from fai +# note, we could replace faiserver with an ip if we didn't want to mess with dns. +# args are copied from myfai-chboot-local. +# Note, for a real cd or usb flash, if it is the default boot device, we would need to remove the disk +# after install is done very quickly, or else remove the reboot arg here +menuentry "FAI server via dns" { + set gfxpayload=$resolution + search --set=root --file /FAI-CD + linux /boot/vmlinuz libata.force=noncq FAI_FLAGS=verbose,sshd,createvt,reboot FAI_CONFIG_SRC=nfs://faiserver/srv/fai/config root=/dev/nfs nfsroot=faiserver:/srv/fai/nfsroot,vers=3,nolock rootovl ip=dhcp + initrd /boot/initrd.img +} + +menuentry "FAI server via dns, no reboot" { + set gfxpayload=$resolution + search --set=root --file /FAI-CD + linux /boot/vmlinuz libata.force=noncq FAI_FLAGS=verbose,sshd,createvt FAI_CONFIG_SRC=nfs://faiserver/srv/fai/config root=/dev/nfs nfsroot=faiserver:/srv/fai/nfsroot,vers=3,nolock rootovl ip=dhcp + initrd /boot/initrd.img +} + +# ro,noatime,vers=3,rsize=1048576,wsize=same,namelen=255,hard,nolock,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=10.2.0.2,nountvers=3,mountport=49179,mountproto=udp,lock_lock=all,addr=10.2.0.2 +menuentry "Autodiscover the FAI server" { + search --set=root --file /FAI-CD + linux /boot/vmlinuz libata.force=noncq FAI_FLAGS="menu,verbose,createvt" fai.discover rootovl root=/dev/nfs ip=dhcp quiet + initrd /boot/initrd.img +} + +menuentry "Boot OS from first partition on first disk" { + if [ "$grub_platform" = "efi" ]; then + if [ -f (hd0,gpt1)/efi/debian/grub.cfg ]; then + configfile (hd0,gpt1)/efi/debian/grub.cfg + elif [ -f (hd1,gpt1)/efi/debian/grub.cfg ]; then + configfile (hd1,gpt1)/efi/debian/grub.cfg + elif [ -f (hd0,gpt2)/boot/grub/grub.cfg ]; then + configfile (hd0,gpt2)/boot/grub/grub.cfg + elif [ -f (hd1,gpt2)/boot/grub/grub.cfg ]; then + configfile (hd1,gpt2)/boot/grub/grub.cfg + else + echo "cannot find grub.cfg" + sleep 7 + fi + # legacy BIOS booting + elif [ -d (cd) ]; then + set root=(hd0) + chainloader +1 + else + set root=(hd1) + chainloader +1 + fi +} diff --git a/grub.cfg.netinst b/grub.cfg.netinst new file mode 100644 index 0000000..489af69 --- /dev/null +++ b/grub.cfg.netinst @@ -0,0 +1,78 @@ +## grub2 configuration +set default="Netinstall" +set timeout=2 +set resolution=1024x768 + +if loadfont /boot/grub/unicode.pf2 ; then + insmod png + set gfxmode=640x480 + insmod gfxterm + insmod vbe + terminal_output gfxterm +fi + +if background_image /boot/grub/fai.png ; then + set color_normal=black/black + set color_highlight=red/black + set menu_color_normal=black/black + set menu_color_highlight=black/yellow +else + set menu_color_normal=white/black + set menu_color_highlight=black/yellow +fi + +# make sure we can access partitions +insmod part_msdos +insmod part_gpt + +if [ ${iso_path} ] ; then + set loopback="findiso=${iso_path}" +fi + +menuentry "" --unrestricted { + set gfxpayload=$resolution +} +menuentry " +------------------------------------------------------+" --unrestricted { + set gfxpayload=$resolution +} + +menuentry " | Fully Automatic Installation |" --unrestricted { + set gfxpayload=$resolution + +} +menuentry " | _VERSIONSTRING_ |" --unrestricted { + set gfxpayload=$resolution + +} +menuentry " | (c) Thomas Lange lange@debian.org |" --unrestricted { + set gfxpayload=$resolution +} +menuentry " +------------------------------------------------------+" --unrestricted { + set gfxpayload=$resolution +} +} +menuentry "" --unrestricted { + set gfxpayload=$resolution +} + +menuentry "Netinstall" { + set gfxpayload=$resolution + linux /boot/vmlinuz libata.force=noncq console=ttyS0,19200n8 FAI_FLAGS="verbose,sshd,createvt,reboot" FAI_ACTION=install FAI_CONFIG_SRC=file:///var/lib/fai/config rd.live.image root=live:CDLABEL=FAI_CD rd.neednet ip=dhcp quiet + initrd /boot/initrd.img +} + + +menuentry "Boot OS of first partition on first disk" --unrestricted { + if [ -d (cd) ]; then + chainloader (hd0)+1 + fi + + if [ "$root" = "hd1" ]; then + chainloader (hd0)+1 + fi + + if [ "$root" = "hd0" ]; then + set root=(hd1) + chainloader (hd1)+1 + fi +} diff --git a/grub.cfg.netinst-noreboot b/grub.cfg.netinst-noreboot new file mode 100644 index 0000000..3db6a80 --- /dev/null +++ b/grub.cfg.netinst-noreboot @@ -0,0 +1,78 @@ +## grub2 configuration +set default="Netinstall" +set timeout=2 +set resolution=1024x768 + +if loadfont /boot/grub/unicode.pf2 ; then + insmod png + set gfxmode=640x480 + insmod gfxterm + insmod vbe + terminal_output gfxterm +fi + +if background_image /boot/grub/fai.png ; then + set color_normal=black/black + set color_highlight=red/black + set menu_color_normal=black/black + set menu_color_highlight=black/yellow +else + set menu_color_normal=white/black + set menu_color_highlight=black/yellow +fi + +# make sure we can access partitions +insmod part_msdos +insmod part_gpt + +if [ ${iso_path} ] ; then + set loopback="findiso=${iso_path}" +fi + +menuentry "" --unrestricted { + set gfxpayload=$resolution +} +menuentry " +------------------------------------------------------+" --unrestricted { + set gfxpayload=$resolution +} + +menuentry " | Fully Automatic Installation |" --unrestricted { + set gfxpayload=$resolution + +} +menuentry " | _VERSIONSTRING_ |" --unrestricted { + set gfxpayload=$resolution + +} +menuentry " | (c) Thomas Lange lange@debian.org |" --unrestricted { + set gfxpayload=$resolution +} +menuentry " +------------------------------------------------------+" --unrestricted { + set gfxpayload=$resolution +} +} +menuentry "" --unrestricted { + set gfxpayload=$resolution +} + +menuentry "Netinstall" { + set gfxpayload=$resolution + linux /boot/vmlinuz libata.force=noncq console=ttyS0,19200n8 FAI_FLAGS="verbose,sshd,createvt" FAI_ACTION=install FAI_CONFIG_SRC=file:///var/lib/fai/config rd.live.image root=live:CDLABEL=FAI_CD rd.neednet ip=dhcp quiet + initrd /boot/initrd.img +} + + +menuentry "Boot OS of first partition on first disk" --unrestricted { + if [ -d (cd) ]; then + chainloader (hd0)+1 + fi + + if [ "$root" = "hd1" ]; then + chainloader (hd0)+1 + fi + + if [ "$root" = "hd0" ]; then + set root=(hd1) + chainloader (hd1)+1 + fi +} diff --git a/grub.cfg.sysinfo-linode b/grub.cfg.sysinfo-linode new file mode 100644 index 0000000..b5d1126 --- /dev/null +++ b/grub.cfg.sysinfo-linode @@ -0,0 +1,78 @@ +## grub2 configuration +set default="Netinstall" +set timeout=2 +set resolution=1024x768 + +if loadfont /boot/grub/unicode.pf2 ; then + insmod png + set gfxmode=640x480 + insmod gfxterm + insmod vbe + terminal_output gfxterm +fi + +if background_image /boot/grub/fai.png ; then + set color_normal=black/black + set color_highlight=red/black + set menu_color_normal=black/black + set menu_color_highlight=black/yellow +else + set menu_color_normal=white/black + set menu_color_highlight=black/yellow +fi + +# make sure we can access partitions +insmod part_msdos +insmod part_gpt + +if [ ${iso_path} ] ; then + set loopback="findiso=${iso_path}" +fi + +menuentry "" --unrestricted { + set gfxpayload=$resolution +} +menuentry " +------------------------------------------------------+" --unrestricted { + set gfxpayload=$resolution +} + +menuentry " | Fully Automatic Installation |" --unrestricted { + set gfxpayload=$resolution + +} +menuentry " | _VERSIONSTRING_ |" --unrestricted { + set gfxpayload=$resolution + +} +menuentry " | (c) Thomas Lange lange@debian.org |" --unrestricted { + set gfxpayload=$resolution +} +menuentry " +------------------------------------------------------+" --unrestricted { + set gfxpayload=$resolution +} +} +menuentry "" --unrestricted { + set gfxpayload=$resolution +} + +menuentry "Netinstall" { + set gfxpayload=$resolution + linux /boot/vmlinuz console=ttyS0,19200n8 FAI_FLAGS="verbose,sshd,createvt" FAI_ACTION=sysinfo FAI_CONFIG_SRC=file:///var/lib/fai/config rd.live.image root=live:CDLABEL=FAI_CD rd.neednet ip=dhcp quiet + initrd /boot/initrd.img +} + + +menuentry "Boot OS of first partition on first disk" --unrestricted { + if [ -d (cd) ]; then + chainloader (hd0)+1 + fi + + if [ "$root" = "hd1" ]; then + chainloader (hd0)+1 + fi + + if [ "$root" = "hd0" ]; then + set root=(hd1) + chainloader (hd1)+1 + fi +} diff --git a/install-chboot b/install-chboot new file mode 100755 index 0000000..acb6531 --- /dev/null +++ b/install-chboot @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +# 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 should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@" + +x="$(readlink -f "$BASH_SOURCE")"; source "${x%/*}/bash-trace" +cd ${x%/*} + +usage() { + cat </dev/null || continue + if [[ -e $dir/boot ]]; then + dir=$dir/boot + fi + e install -m 755 -o root -g root bash-trace $dir + e install -m 755 -o root -g root chboot $dir +done +e umount $mount_point +e rmdir $mount_point diff --git a/live-kexec b/live-kexec new file mode 120000 index 0000000..3baf2bb --- /dev/null +++ b/live-kexec @@ -0,0 +1 @@ +lk \ No newline at end of file diff --git a/lk b/lk new file mode 100755 index 0000000..d3d13ea --- /dev/null +++ b/lk @@ -0,0 +1,76 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +# 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 should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +usage() { + cat </dev/null 2>&1; then + apt-get update + apt-get install -y debconf + debconf-set-selections < /srv/fai/config/class/51-multi-boot + +rm -rf $t; mkdir -p $t + +LANG= fai -N -u hostname_does_not_matter dirinstall $t + +# Turn a dirinstall into a basefile. taken from mk-basefile +chroot $t apt-get clean +rm -f $t/etc/hostname $t/etc/resolv.conf \ + $t/var/lib/apt/lists/*_* $t/usr/bin/qemu-*-static \ + $t/etc/udev/rules.d/70-persistent-net.rules +echo | dd of=$t/etc/machine-id +tar --one-file-system -C $t -cf - . | gzip > /a/bin/fai-basefiles/basefiles/${distver^^}64BIG.tar.gz + + +cleanup +exit 0 diff --git a/myfai-chboot b/myfai-chboot new file mode 100755 index 0000000..7d775ea --- /dev/null +++ b/myfai-chboot @@ -0,0 +1,44 @@ +#!/bin/bash + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + +x=$(readlink -f "$BASH_SOURCE"); cd ${x%/*} + +usage() { + cat <&2' ERR + +kgped16=false +fai_action=install +fai_reboot_arg=,reboot +while [[ $1 == -* ]]; do + case $1 in + -h|--help) + echo "see help from myfai-chboot" + exit 0 + ;; + -S) + fai_action=sysinfo + fai_reboot_arg= + shift + ;; + -i) #inventory + fai_action=inventory + fai_reboot_arg= + shift + ;; + -k) + kgped16=true; + shift + ;; + esac +done + +pre="${0##*/}:" +m() { printf "$pre %s\n" "$*"; "$@"; } +e() { printf "$pre %s\n" "$*"; } +err() { echo "[$(date +'%Y-%m-%d %H:%M:%S%z')]: $pre: $*" >&2; } + +host=$1 + +rm -f /srv/tftp/fai/pxelinux.cfg/* +if [[ ! $1 ]]; then + echo "$0: clearing pxe config and exiting" + exit 0 +fi + +# assuming ipv4, or else we might need to deal with multiple addresses +# in an ipv4 + ipv6 network. +my_ip=$(ip -4 route get 8.8.8.8 | sed -nr 's,^.*src\s+(\S+).*,\1,p') +if [[ ! $my_ip || $my_ip =~ [[:space:]] ]]; then + echo "$0: error: failed to get \$my_ip, got: $my_ip" + exit 1 +fi + +if [[ $host == default ]]; then + ip='*' +elif [[ $host == [0-9]*.[0-9]*.[0-9]*.[0-9]* ]]; then + ip=$host/32 +else + type -t host &>/dev/null || apt-get -y install dnsutils + ip=$(host $host | sed -rn 's/^\S+ has address //p;T;q' ||:) + if [[ ! $ip || $ip =~ [[:space:]] ]]; then + echo "$0: error: failed to get \$ip, got: $ip" + exit 1 + fi + ip=$ip/32 + echo "$0: found ip of $host: $ip" +fi + +if modprobe nfsd &>/dev/null; then + std_arg="-u nfs://faiserver/srv/fai/config" + # nfsv4 wont do rw with overlayfs yet + # https://lists.uni-koeln.de/pipermail/linux-fai/2017-March/011641.html + root_arg="$my_ip:/srv/fai/nfsroot:vers=3" + # fai-setup without -e sets the ip to the local_ip/local_network, eg 192.168.1.3/24 + # I restrict it to one ip as simple but imperfect access control. + + # we may chattr +i /etc/exports if we dun want it modified + # for example, if we made these exports more widely available + # while doing multiple installs or a recovery. + if [[ -w /etc/exports ]]; then + sed -ri --follow-symlinks '\%^/srv/fai/%d' /etc/exports + cat >>/etc/exports < + Deny from all + Allow from $ip + +EOF +fi + + + +# man page doesn't explain this, but this deletes & thus disables +# all chboot systems. +m fai-chboot -iv $std_arg default # set it to default to get a val out of it next +kernel=$(fai-chboot -L '^default$' | awk '{print $3}') +default_k_args=$(fai-chboot -L '^default$' | \ + sed -r "s/^(\S+\s+){3}(.*)/\2/") +# example of default_k_args +# initrd=initrd.img-3.16.0-4-amd64 ip=dhcp root=192.168.1.3:/srv/fai/nfsroot FAI_CONFIG_SRC=nfs://faiserver/srv/fai/config FAI_ACTION=install + +# https://wiki.archlinux.org/index.php/Solid_state_drive#Resolving_NCQ_errors +# currently on needed on d16 samsung 870 qvo, but better to have this +# and not wait for more conditions where its needed. +k_args=(FAI_ACTION=$fai_action libata.force=noncq) +if $kgped16; then + k_args+=(console=tty0 console=ttyS0,115200) +fi + +for arg in $default_k_args; do + case $arg in + # default root arg is /srv/fai/nfsroot + root=*) k_args+=(root=$root_arg) ;; + *) k_args+=($arg) ;; + esac +done +rm -f /srv/tftp/fai/pxelinux.cfg/* +m fai-chboot -k "${k_args[*]}" -v -f verbose,sshd,createvt$fai_reboot_arg $std_arg $kernel "$host" + +# this is needed for autodiscover iso. i'm not sure, it might override +# the fai-chboot method of setting this, i'm not sure. +echo FAI_ACTION=$fai_action >> /srv/fai/config/class/LAST.var diff --git a/mymk-basefile b/mymk-basefile new file mode 100755 index 0000000..a784e00 --- /dev/null +++ b/mymk-basefile @@ -0,0 +1,66 @@ +#!/bin/bash + +x="$(readlink -f "$BASH_SOURCE")"; source "${x%/*}/bash-trace" +script_dir="${x%/*}" + +usage() { + cat < tftpboot + + +Note: Uses GNU getopt options parsing style +EOF + exit $1 +} + +pre="${0##*/}:" +m() { printf "$pre %s\n" "$*"; "$@"; } +e() { printf "$pre %s\n" "$*"; } +err() { echo "[$(date +'%Y-%m-%d %H:%M:%S%z')]: $pre: $*" >&2; } + +##### begin command line parsing ######## + +dhcp=true +redep=true +acks=2 +wait=false +fsf=false + +case $HOSTNAME in + x3|kw) fsf=true ;; +esac + +chboot_args=() +temp=$(getopt -l help adkrSwh "$@") || usage 1 +eval set -- "$temp" +while true; do + case $1 in + -a) wait=true; set=false; shift ;; + -d) dhcp=false; shift ;; + -k) chboot_args+=(-k); shift ;; + -r) redep=false; shift ;; + -S) chboot_args+=(-S); shift ;; + -w) wait=true; set=true; shift ;; + -h|--help) usage ;; + --) shift; break ;; + *) echo "$0: Internal error!" ; exit 1 ;; + esac +done + +read -r host type <<<"$@" + +case $# in + [01]);; + 2) + case $type in + arch|parabola) cmd=archlike ;; + fai) cmd=fai ;; + *) + echo "$0: error expected type of arch|parabola|fai" + echo + usage 1 + ;; + esac + ;; + *) + echo "$0: error: expected 0-2 arguments" + echo + usage 1 + ;; +esac + + +if $wait && ! $dhcp; then + echo "$0: error -w conflicts with -d, choose one or other" + exit 1 +fi + + +if [[ $host && $host != default ]]; then + host_tag="tag:$host," +fi + +##### end command line parsing ######## + +archlike() { + cat </dev/null || sudo apt-get -y install dnsutils +faiserverip=$(host faiserver | sed -rn 's/^\S+ has address //p;T;q' ||:) +if [[ ! $faiserverip || $faiserverip =~ [[:space:]] ]]; then + echo "$0: error: failed to get \$faiserverip, got: $faiserverip" + exit 1 +fi + + +if $set; then + set-pxe + if [[ $type == fai ]]; then + if $redep; then + m fai-redep + fi + m myfai-chboot ${chboot_args[@]} $host + else + # This will fail if faiserver is not setup, so ignore any + # failure and don't bother us about it. + myfai-chboot &>/dev/null ||: + fi +fi + +if $wait; then + # fai's debian jessie 8.5ish does 2 dhcp requests when booting, + # roughly 4 seconds apart. Earlier + # versions did just 1. Now testing on a vm, it does 1. + # bleh. + echo "waiting for $acks dhcp acks then disabling pxe" + ack-wait $acks + type= + unset cmd + set-pxe + + # previously tried waiting for one more ack then disabling faiserver, + # since it can contain sensitive info, so turn it off when not in use, + # but disabling that for now as it's inconvenient to clean this + # up and run it in the background etc. + + # if [[ $type == fai ]]; then + # echo "waiting for 1 dhcp ack then disabling fai server" + # ack-wait 1 + # faiserver-disable + # fi +fi diff --git a/wrt-disabled-firewall-rules b/wrt-disabled-firewall-rules new file mode 100644 index 0000000..b2cfdf0 --- /dev/null +++ b/wrt-disabled-firewall-rules @@ -0,0 +1,135 @@ +firewall rules, temporarily disabled until I get them working + + +# each port forward needs corresponding forward in the vpn server + + +#http/https + + + +config redirect + option name bittorrent + option src vpn + option src_dport 63324 + option dest_ip 192.168.1.2 + option dest lan +# making the port open (not sure if this is actually needed) +config rule + option src vpn + option target ACCEPT + option dest_port 63324 + + + +config redirect + option name kdsyncthing + option src vpn + option src_dport 22000 + option dest_ip 192.168.1.2 + option dest lan + option proto tcp +config rule + option src vpn + option target ACCEPT + option dest_port 22000 + + +config redirect + option name bithtpc + option src vpn + option src_dport 63325 + option dest_ip 192.168.1.4 + option dest lan +config rule + option src vpn + option target ACCEPT + option dest_port 63325 + + + +#### begin rules for nfs #### +# https://serverfault.com/questions/377170/which-ports-do-i-need-to-open-in-the-firewall-to-use-nfs +# https://wiki.debian.org/SecuringNFS +# I had no /etc/default/quota, or any process named quota anything, +# so, assumed that was unneeded. seems to work. +config redirect + option src wan + option src_dport 111 + option dest_ip 192.168.1.2 + option dest lan +config rule + option src wan + option target ACCEPT + option dest_port 111 +config redirect + option src wan + option src_dport 2049 + option dest_ip 192.168.1.2 + option dest lan +config rule + option src wan + option target ACCEPT + option dest_port 2049 +config redirect + option src wan + option src_dport 32764 + option dest_ip 192.168.1.2 + option dest lan +config rule + option src wan + option target ACCEPT + option dest_port 32764 +config redirect + option src wan + option src_dport 32765 + option dest_ip 192.168.1.2 + option dest lan +config rule + option src wan + option target ACCEPT + option dest_port 32765 +config redirect + option src wan + option src_dport 32766 + option dest_ip 192.168.1.2 + option dest lan +config rule + option src wan + option target ACCEPT + option dest_port 32766 +config redirect + option src wan + option src_dport 32767 + option dest_ip 192.168.1.2 + option dest lan +config rule + option src wan + option target ACCEPT + option dest_port 32767 +config redirect + option src wan + option src_dport 32768 + option dest_ip 192.168.1.2 + option dest lan +config rule + option src wan + option target ACCEPT + option dest_port 32768 +#### end rules for nfs #### + + +config redirect + option name mariadb + option src wan + option src_dport 3306 + option dest lan + option dest_ip 192.168.1.2 + option proto tcp +config rule + option src wan + option target ACCEPT + option dest_port 3306 + option proto tcp + + diff --git a/wrt-init b/wrt-init new file mode 100755 index 0000000..ebfac9c --- /dev/null +++ b/wrt-init @@ -0,0 +1,18 @@ +#!/bin/sh +set -x +# librecmc 1.5.1 is missing nfs-kernel-server and screen +source /etc/os-release +if [ "$ID" == librecmc ] && [ "$VERSION" == v1.5.1-core ]; then + cat >/etc/opkg/customfeeds.conf <<'EOF' +src/gz openwrt_packages http://downloads.openwrt.org/releases/19.07.3/packages/mips_24kc/packages +fi +EOF +fi + +if ! opkg list-installed|grep bash; then + opkg update + opkg install bash +fi +export HOME_DOMAIN=$1 +shift +wrt-setup-local "$@" diff --git a/wrt-setup b/wrt-setup new file mode 100755 index 0000000..db7f5c9 --- /dev/null +++ b/wrt-setup @@ -0,0 +1,81 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +# 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 should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + +x="$(readlink -f "$BASH_SOURCE")"; cd ${x%/*} + +usage() { + cat </dev/null +scp /a/work/libremanage/libremanage /a/bin/fai/wrt-init /a/bin/fai/wrt-setup-local /a/bin/cedit/cedit $h:/usr/bin +# relay is built for openwrt 18.06.2, r7676-cddd7b4c77 + +#/a/opt/openwrt/source/bin/packages/mips_24kc/mypackages/relay_1.0-1_mips_24kc.ipk \ + +sudo scp /q/root/shadow/router /p/c/machine_specific/wrt/etc/dropbear/dropbear_rsa_host_key \ + /p/router-secrets /p/c/machine_specific/wrt/etc/wg.{key,psk} $h: +scp ../openwrtkeyring/usign/* $h:/etc/opkg/keys + +ssh $h wrt-init ${HOME_DOMAIN:-b8.nz} "$@" diff --git a/wrt-setup-local b/wrt-setup-local new file mode 100755 index 0000000..2c28dca --- /dev/null +++ b/wrt-setup-local @@ -0,0 +1,1130 @@ +#!/bin/bash +# Copyright (C) 2016 Ian Kelling + +# 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 should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + + +usage() { + cat <&2; usage 1 ;; + esac + ;; + y) + zblock=false + rm -f /root/zblock + ;; + z) + zblock=true + touch /root/zblock + ;; + m) mac=$OPTARG ;; + *) echo "$0: Internal error! unexpected args: $*" >&2 ; usage 1 ;; + esac +done +shift "$((OPTIND-1))" # Discard the options and sentinel -- + +if [[ ! $mac ]] && ! $test && $secrets; then + # if we wanted to increment it + #mac=${mac:0: -1}$((${mac: -1} + 2)) + mac=${rwmac[$rmac]} +fi + +if (( $# != 0 )); then + usage 1 +fi + + +macpre=${mac:0: -1} +macsuf=${mac: -1} + + +p_updated=false +pmirror() { + if $p_updated; then + return + fi + # background: upgrading all packages is not recommended because it + # doesn't go into the firmware. build new firmware if you want + # lots of upgrades. I think /tmp/opkg-lists is a pre openwrt 14 location. + f=(/var/opkg-lists/*) + if ! (( $(date -r $f +%s) + 60*60*24 > $(date +%s) )); then + if ! opkg update; then + echo "$0: warning: opkg update failed" >&2 + fi + p_updated=true + fi +} + +pi() { + to_install=() + for p in "$@"; do + pname=${p##*/} + pname=${pname%%_*} + if [[ ! $(opkg list-installed "$pname") ]]; then + to_install+=($p) + pmirror + fi + done + if [[ $to_install ]]; then + opkg install ${to_install[@]} + fi +} + +v() { + printf "+ %s\n" "$*" + "$@" +} + +######### uci example:####### +# # https://wiki.openwrt.org/doc/uci +# wan_index=$(uci show firewall | sed -rn 's/firewall\.@zone\[([0-9])+\]\.name=wan/\1/p') +# wan="firewall.@zone[$wan_index]" +# if [[ $(uci get firewall.@forwarding[0].dest) != $forward_dest ]]; then +# # default is wan +# v uci set firewall.@forwarding[0].dest=$forward_dest +# uci commit firewall +# firewall_restart=true +# fi +####### end uci example ##### + +uset() { + printf "+ uset %s\n" "$*" + local key="$1" + local val="$2" + local service="${key%%.*}" + restart_var=${service}_restart + if [[ ! ${!restart_var} ]]; then + eval $restart_var=false + fi + if [[ $(uci get "$key") != "$val" ]]; then + v uci set "$key"="$val" + uci commit $service + eval $restart_var=true + fi +} + +udel() { + printf "+ udel %s\n" "$*" + local key="$1" + local val="$2" + local service="${key%%.*}" + restart_var=${service}_restart + if [[ ! ${!restart_var} ]]; then + eval $restart_var=false + fi + if uci get "$key" &>/dev/null; then + v uci set "$key"="$val" + uci commit $service + eval $restart_var=true + fi +} +cedit() { + v command cedit -v "$@" +} + + +### network config +### +lan=10.0.0.0 +if $test; then + lan=10.1.0.0 +elif [[ $hostname == cmc ]]; then + lan=10.2.0.0 +elif $client; then + lan=10.3.0.0 +fi + +if $test; then + ssid="gnuv3" +elif $secrets; then + ssid=${rssid[$rmac]} +fi + +: ${ssid:=librecmc} + + +if $secrets; then + key=${rkey[$rmac]} +fi +: ${key:=pictionary49} + +mask=255.255.0.0 +cidr=16 +l=${lan%.0} + +passwd -l root ||: #already locked fails + +sed -ibak '/^root:/d' /etc/shadow +# /root/router created by manually running passwd then copying the resulting +# line. We have no mkpasswd on wrt/librecmc, then we scp it in. +cat /root/router >>/etc/shadow +# otherwise, serial console gets root login with no password +uset system.@system[0].ttylogin 1 + + + +cat >/usr/bin/archlike-pxe-mount <<'EOFOUTER' +#!/bin/bash +# symlinks are collapsed for nfs mount points, so use a bind mount. +# tried putting this in /etc/config/fstab, +# then doing block mount, it didn't work. This doesn't persist across reboots, +# todo: figure that out +rm -f /etc/fstab +for d in /run/{arch,parabola}iso/bootmnt; do +cat >>/etc/fstab </dev/null || mount $d +done +/etc/init.d/nfsd restart +EOFOUTER +chmod +x /usr/bin/archlike-pxe-mount + +sed -i '/^root:/s,/bin/ash$,/bin/bash,' /etc/passwd + + + +uset dropbear.@dropbear[0].PasswordAuth 0 +uset dropbear.@dropbear[0].RootPasswordAuth 0 +uset dropbear.@dropbear[0].Port 2220 +if ! cmp -s /root/dropbear_rsa_host_key /etc/dropbear/dropbear_rsa_host_key; then + cp /root/dropbear_rsa_host_key /etc/dropbear/dropbear_rsa_host_key + dropbear_restart=true +fi + +if $dropbear_restart; then + v /etc/init.d/dropbear restart +fi + + +uset network.lan.ipaddr $l.$lanip +uset network.lan.netmask $mask +if $dev2 || $client; then + if $dev2; then + uset network.lan.gateway $l.1 + uset network.wan.proto none + uset network.wan6.proto none + fi + /etc/init.d/dnsmasq stop + /etc/init.d/dnsmasq disable + /etc/init.d/odhcpd stop + /etc/init.d/odhcpd disable + rm -f /etc/resolv.conf + cat >/etc/resolv.conf <<'EOF' +nameserver 8.8.8.8 +nameserver 8.8.4.4 +EOF + + # things i tried to keep dnsmasq running but not enabled except local dns, + # but it didnt work right and i dont need it anyways. + # uset dhcp.wan.ignore $dev2 # default is false + # uset dhcp.lan.ignore $dev2 # default is false + # uset dhcp.@dnsmasq[0].interface lo + # uset dhcp.@dnsmasq[0].localuse 0 + # uset dhcp.@dnsmasq[0].resolvfile /etc/dnsmasq.conf + # uset dhcp.@dnsmasq[0].noresolv 1 + # todo: populate /etc/resolv.conf with a static value + +else + # these are the defaults + uset network.lan.gateway '' + uset network.wan.proto dhcp + uset network.wan6.proto dhcpv6 + /etc/init.d/dnsmasq start + # todo: figure out why this returns 1 + /etc/init.d/dnsmasq enable ||: + /etc/init.d/odhcpd start + /etc/init.d/odhcpd enable +fi + +wireless_restart=false + +if $client; then + uset wireless.default_radio0.network 'wwan' + uset wireless.default_radio0.ssid ${rclientssid[$rmac]} + uset wireless.default_radio0.encryption 'psk2' + uset wireless.default_radio0.device 'radio0' + uset wireless.default_radio0.mode 'sta' + uset wireless.default_radio0.bssid ${rclientbssid[$rmac]} + # todo: look into whether 5g network is available. + uset wireless.default_radio0.key ${rclientkey[$rmac]} + uset wireless.radio0.disabled false + uset wireless.radio1.disabled true +else + # defaults, just reseting in case client config ran + uset wireless.default_radio0.network lan + uset wireless.default_radio0.mode ap + for x in 0 1; do + uset wireless.default_radio$x.ssid "$ssid" + uset wireless.default_radio$x.key $key + uset wireless.default_radio$x.encryption psk2 + if [[ $mac ]]; then + uset wireless.default_radio$x.macaddr $macpre$((macsuf + 2*x)) + fi + # secondary device has wireless disabled + uset wireless.radio$x.disabled $dev2 + done +fi + + + + + +# usb, screen, relay are for libremanage +# rsync is for brc +# +# relay package temporarily disabled +# /root/relay_1.0-1_mips_24kc.ipk +v pi kmod-usb-storage block-mount kmod-fs-ext4 nfs-kernel-server \ + tcpdump openvpn-openssl adblock libusb-compat \ + screen kmod-usb-serial-cp210x kmod-usb-serial-ftdi rsync\ + unbound-daemon-heavy unbound-checkconf + +cat >/etc/libremanage.conf </dev/null; then +# # cant mix cedit plus uci +# echo | cedit /etc/config/firewall ||: +# uci add_list firewall.@zone[1].network=wg0 +# uci commit firewall +# firewall-cedit ||: +# firewall_restart=true +# fi + + + +cedit /etc/hosts < [1614982580.5192] dhcp6 (wlan0): option dhcp6_name_servers => 'fd58:5801:8e02::1' +# but i dont want ipv6 dns, just keep it simple to ipv4. +# I know my isp doesnt have ipv6 right now, +# so just stop this thing. +# note: tried this, it didn't do anything: +# uset dhcp.@odhcpd[0].dns 10.2.0.1 +/etc/init.d/odhcpd stop +/etc/init.d/odhcpd disable +# todo: make the above conditional on which server this is. + +# avoid errors in log. current isp doesnt have ipv6 +uset unbound.@unbound[0].protocol ip4_only + +# todo: im not sure all these are needed, but they all look +# like good options. +# https://blog.cloudflare.com/dns-over-tls-for-openwrt/ +# https://gist.github.com/vqiu/7b32d3a19a7a09d32e108d998de166c2 +#https://blog.thestateofme.com/2018/04/04/howto-secure-your-dns-with-a-raspberry-pi-unbound-and-cloudflare-1-1-1-1/ +# +# # i found that the zone example was having no effect on the config +# # here: +# https://github.com/openwrt/packages/blob/openwrt-19.07/net/unbound/files/README.md +# +# # todo: unbound-control, i'm not sure what the purpose of that thing is, some +# # kind of coordination with dhcp of dnsmasq, but what? +# +# note: for debugging, edit /etc/init.d/unbound, change +# procd_set_param command $PROG -d -c $UB_TOTAL_CONF +# to: +# procd_set_param command $PROG -vvv -d -c $UB_TOTAL_CONF + +{ + cat <<'EOF' +do-tcp: yes +prefetch: yes +qname-minimisation: yes +rrset-roundrobin: yes +use-caps-for-id: yes +do-ip6: no +private-domain: b8.nz +local-zone: "10.in-addr.arpa." transparent +access-control-view: 10.2.0.31/32 "youtube" +EOF + + if $zblock; then + cat <<'EOF' +# amy, amyw, samsungtab +access-control-view: 10.2.0.8/32 "youtube" +access-control-view: 10.2.0.23/32 "youtube" +access-control-view: 10.2.0.32/32 "youtube" +EOF + fi +} | cedit /etc/unbound/unbound_srv.conf || restart_unbound=true + + +# dns based blocking vs ip based. with ip, same +# server can have multiple domains. in dns, +# you have to make sure clients to use the local dns. +# https dns will need to be blocked by ip in +# order to be comprehensive + +cedit /etc/unbound/unbound_ext.conf <<'EOF' || restart_unbound=true +local-data-ptr: "10.2.0.1 cmc.b8.nz" +local-data-ptr: "10.2.0.2 kd.b8.nz" +local-data-ptr: "10.2.0.3 sy.b8.nz" +local-data-ptr: "10.2.0.4 wrt2.b8.nz" +local-data-ptr: "10.2.0.5 x2.b8.nz" +local-data-ptr: "10.2.0.6 x2w.b8.nz" +local-data-ptr: "10.2.0.7 syw.b8.nz" +local-data-ptr: "10.2.0.8 amy.b8.nz" +local-data-ptr: "10.2.0.9 bb8.b8.nz" +local-data-ptr: "10.2.0.12 demohost.b8.nz" +local-data-ptr: "10.2.0.14 wrt3.b8.nz" +local-data-ptr: "10.2.0.19 brother.b8.nz" +local-data-ptr: "10.2.0.23 amyw.b8.nz" +local-data-ptr: "10.2.0.25 hp.b8.nz" +local-data-ptr: "10.2.0.31 amazontab.b8.nz" +local-data-ptr: "10.2.0.32 samsungtab.b8.nz" +local-data-ptr: "10.173.0.2 transmission.b8.nz" +local-data-ptr: "10.173.8.1 defaultnn.b8.nz" +local-data-ptr: "10.173.8.2 nn.b8.nz" + +forward-zone: + name: "." +# https://developers.cloudflare.com/1.1.1.1/1.1.1.1-for-families/setup-instructions/dns-over-https + forward-addr: 1.1.1.3@853#family.cloudflare-dns.com + forward-addr: 1.0.0.3@853#family.cloudflare-dns.com + forward-ssl-upstream: yes + forward-first: no + +view: + name: "youtube" + local-zone: "googlevideo.com." refuse + local-zone: "video.google.com." refuse + local-zone: "youtu.be." refuse + local-zone: "youtube-nocookie.com." refuse + local-zone: "youtube-ui.l.google.com." refuse + local-zone: "youtube.com." refuse + local-zone: "youtube.googleapis.com." refuse + local-zone: "youtubeeducation.com." refuse + local-zone: "youtubei.googleapis.com." refuse + local-zone: "yt3.ggpht.com." refuse + local-zone: "youtubekids.com." refuse + # try global if no match in view + view-first: yes +EOF + + +if $restart_unbound; then + /etc/init.d/unbound restart + if ! unbound-checkconf; then + echo $0: error: unbound-checkconf failed >&2 + exit 1 + fi +fi + + +# disabled for now. i want to selectively enable it +# for specific hosts. +if [[ $(uci get adblock.global.adb_enabled) != 0 ]]; then + v uci set adblock.global.adb_enabled=0 + uci commit adblock + /etc/init.d/adblock restart +fi +# https://github.com/openwrt/packages/tree/master/net/adblock/files +cat >/etc/crontabs/root <<'EOF' +0 06 * * * /etc/init.d/adblock reload +EOF + + +# useful: http://wiki.openwrt.org/doc/howto/dhcp.dnsmasq + +# sometimes /mnt/usb fails, cuz it's just a flash drive, +# so make sure we have this dir or else dnsmasq will fail +# to start. +mkdir -p /mnt/usb/tftpboot +cedit /etc/dnsmasq.conf < +# or on cmc, +# /etc/init.d/dnsmasq stop +# vi /tmp/dhcp.leases +# /etc/init.d/dnsmasq start + + +# default dhcp range is 100-150 +# bottom port, iPXE (PCI 03:00.0) in seabios boot menu +dhcp-host=c8:60:00:31:6b:75,set:kd,$l.2,kd +dhcp-host=94:05:bb:1e:2c:2e,set:sy,$l.3,sy +# top port, iPXE (PCI 04:00.0) in seabios boot menu +#dhcp-host=c8:60:00:2b:15:07,set:kd,$l.2,kd +# 4 is reserved for a staticly configured host wrt2 +# old x2 with bad fan +#dhcp-host=00:1f:16:16:39:24,set:x2,$l.5,x2 +dhcp-host=f0:de:f1:81:ec:88,set:x2,$l.5,x2 +dhcp-host=c4:8e:8f:44:f5:63,set:x2w,$l.6,x2w +dhcp-host=34:7d:f6:ed:ec:07,set:syw,$l.7,syw +dhcp-host=80:fa:5b:1c:6e:cf,set:amy,$l.8,amy +# This is so fai can have an explicit name to use for testing, +# or else any random machine which did a pxe boot would get +# reformatted. The mac is from doing a virt-install, cancelling it, +# and copying the generated mac, so it should be randomish. +dhcp-host=52:54:00:9c:ef:ad,set:demohost,$l.12,demohost +dhcp-host=62:03:cb:a8:3e:a3,set:trp,$1.13,trp +# 14 = wrt3 +dhcp-host=00:1f:16:14:01:d8,set:x3,$l.18,x3 +# BRN001BA98CA823 in dhcp logs +dhcp-host=00:1b:a9:8c:a8:23,set:brother,$l.19,brother + +dhcp-host=00:26:b6:f7:d4:d8,set:amyw,$l.23,amyw +dhcp-host=9a:c6:52:6f:ce:7c,set:onep9,$l.24,onep9 +dhcp-host=38:63:bb:07:5a:f9,set:hp,$l.25,hp +dhcp-host=00:26:b6:f6:0f:e9,set:frodow,$l.28,frodow +dhcp-host=6c:56:97:88:7b:74,set:amazontab,$l.31,amazontab +dhcp-host=0a:8a:9b:cf:b5:ec,set:samsungtab,$l.32,samsungtab + + + +# faiserver vm +dhcp-host=52:54:00:56:09:f9,set:faiserver,$l.15,faiserver + +# This is the ip it picks by default if dhcp fails, +# so might as well use it. +# hostname is the name it uses according to telnet +dhcp-host=b4:75:0e:94:29:ca,set:switch9429ca,$l.251,switch9429ca + +# template +# dhcp-host=,$l., + +# Just leave the tftp server up even if we aren't doing pxe boot. +# It has no sensitive info. +enable-tftp=br-lan +tftp-root=/mnt/usb/tftpboot +dhcp-optsfile=/etc/dnsmasq-dhcpopts.conf + +#log-queries=extra +EOF + + +if $dnsmasq_restart && ! $dev2; then + # todo: can our ptr records be put in /etc/hosts? + # eg: user normal /etc/hosts records, and they wont be used for A resolution + # due to the other settings, but will be used for ptr? then maybe + # we dont have to restart dnsmasq for a dns update? + # + # interesing link: + # https://www.redpill-linpro.com/techblog/2019/08/27/evaluating-local-dnssec-validators.html#toggling-dnssec-validation-1 + # we could turn on dnssec validation when wrt gets dnsmasq > 2.80. currently at 2.80. + # also we can turn off dnssec in systemd-resolved if we know the router is doing it. + # + # Also, reload of dnsmasq seems to break things, wifi + # clients were not getting internet connectivity. + + v /etc/init.d/dnsmasq restart +fi + +if $firewall_restart; then + v /etc/init.d/firewall restart +fi + +# this may just restart the network and take care of the network_restart below. +if $wireless_restart; then + v wifi +fi + +# todo: we should catch errors and still run this if needed +if $network_restart; then + reboot +fi + +exit 0