707 lines
15 KiB
Bash
Executable file
707 lines
15 KiB
Bash
Executable file
#!/bin/bash
|
|
#
|
|
set -e
|
|
echo (){
|
|
/bin/echo "#########################################"
|
|
/bin/echo "$@"
|
|
/bin/echo "#########################################"
|
|
}
|
|
#LICENSE#{{{
|
|
# Copyright (c) 2012 Tom Wambold
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
#}}}
|
|
# CONFIGURE THESE VARIABLES{{{
|
|
# Drive to install to.
|
|
DRIVE='/dev/sda'
|
|
|
|
# Hostname of the installed machine.
|
|
HOSTNAME='arch'
|
|
|
|
# Encrypt everything (except /boot). true or false
|
|
ENCRYPT_DRIVE=true
|
|
|
|
# Passphrase used to encrypt the drive (leave blank to be prompted).
|
|
DRIVE_PASSPHRASE=''
|
|
|
|
# Root password (leave blank to be prompted).
|
|
ROOT_PASSWORD=''
|
|
|
|
# Main user to create (by default, added to wheel group, and others).
|
|
USER_NAME='lelgenio'
|
|
# Link to users dotfiles repo(git)
|
|
# Assumed to have stow-able modules on its root(cd .dotfiles;stow*/)
|
|
DOTFILES_URL="https://gitlab.com/$USER_NAME/dotfiles"
|
|
USER_SHELL='fish'
|
|
|
|
# The main user's password (leave blank to be prompted).
|
|
USER_PASSWORD=''
|
|
|
|
# System timezone.
|
|
TIMEZONE='America/Sao_Paulo'
|
|
|
|
# Country code for pacman repos
|
|
COUNTRY='brazil'
|
|
|
|
# Have /tmp on a tmpfs or not. Leave blank to disable.
|
|
# Only leave this blank on systems with very little RAM.
|
|
TMP_ON_TMPFS='TRUE'
|
|
|
|
KEYMAP='br-abnt2'
|
|
# KEYMAP='dvorak'
|
|
|
|
LANG=pt_BR.UTF-8
|
|
|
|
#}}}
|
|
# Initial Setup{{{
|
|
# Base install{{{
|
|
setup() {
|
|
local boot_dev="$DRIVE"1
|
|
|
|
if "$ENCRYPT_DRIVE"
|
|
then
|
|
local crypt_dev="$DRIVE"2
|
|
local lvm_dev="/dev/mapper/lvm"
|
|
else
|
|
local lvm_dev="$DRIVE"2
|
|
fi
|
|
|
|
echo 'Cleaning disk'
|
|
disk_clean "$lvm_dev" "$DRIVE"2
|
|
|
|
echo 'Creating partitions'
|
|
partition_drive "$DRIVE"
|
|
|
|
if "$ENCRYPT_DRIVE"
|
|
then
|
|
|
|
if [ -z "$DRIVE_PASSPHRASE" ];then
|
|
echo 'Enter a passphrase to encrypt the disk:'
|
|
read -s DRIVE_PASSPHRASE
|
|
fi
|
|
|
|
echo 'Encrypting partition'
|
|
encrypt_drive "$crypt_dev" "$DRIVE_PASSPHRASE" lvm
|
|
fi
|
|
|
|
echo 'Setting up LVM'
|
|
setup_lvm "$lvm_dev" vg00
|
|
|
|
echo 'Formatting filesystems'
|
|
format_filesystems "$boot_dev"
|
|
|
|
echo 'Mounting filesystems'
|
|
mount_filesystems "$boot_dev"
|
|
|
|
echo 'Setting repos'
|
|
set_repos
|
|
|
|
echo 'Installing base system'
|
|
install_base
|
|
|
|
echo 'Setting fstab'
|
|
set_fstab
|
|
|
|
echo 'Chrooting into installed system to continue setup...'
|
|
cp "$0" "/mnt/setup.sh"
|
|
chmod +x "/mnt/setup.sh"
|
|
arch-chroot /mnt "./setup.sh"
|
|
|
|
if [ -f "/mnt/setup.sh" ];then
|
|
echo 'ERROR: Something failed inside the chroot, not unmounting filesystems so you can investigate.'
|
|
echo 'Make sure you unmount everything before you try to run this script again.'
|
|
else
|
|
echo 'Unmounting filesystems'
|
|
unmount_filesystems
|
|
echo 'Done! Reboot system.'
|
|
fi
|
|
}
|
|
#}}}
|
|
# Remove old LVMs{{{
|
|
disk_clean(){
|
|
|
|
local lvm_dev="$1"
|
|
local disk="$2"
|
|
|
|
echo 'cleaning disk'
|
|
|
|
umount --recursive --quiet /mnt || true
|
|
swapoff -a
|
|
|
|
pvs "$lvm_dev" || return 0
|
|
|
|
for vg in $(pvs -o vg_name --nohead "$lvm_dev")
|
|
do
|
|
vgremove "$vg" --yes
|
|
done
|
|
|
|
pvremove "$lvm_dev"
|
|
|
|
if "$ENCRYPT_DRIVE"
|
|
then
|
|
cryptsetup close lvm
|
|
fi
|
|
|
|
wipefs -a "$disk"
|
|
|
|
}
|
|
#}}}
|
|
# Partition Drive{{{
|
|
partition_drive() {
|
|
local dev="$1"; shift
|
|
|
|
# 100 MB /boot partition, everything else under LVM
|
|
if $IS_BIOS;then
|
|
parted \
|
|
--align optimal \
|
|
--script "$dev" \
|
|
mklabel msdos \
|
|
mkpart primary fat32 1M 100M \
|
|
mkpart primary ext4 100M 100% \
|
|
set 1 boot on \
|
|
set 2 lvm on
|
|
else
|
|
parted \
|
|
--align optimal \
|
|
--script "$dev" \
|
|
mklabel gpt \
|
|
mkpart boot 1 100M \
|
|
mkpart lvm 100M 100% \
|
|
set 1 boot on \
|
|
set 2 lvm on
|
|
fi
|
|
}
|
|
#}}}
|
|
# Encrypt_drive {{{
|
|
encrypt_drive() {
|
|
local dev="$1"; shift
|
|
local passphrase="$1"; shift
|
|
local name="$1"; shift
|
|
|
|
/bin/echo -en "$passphrase" | cryptsetup luksFormat "$dev"
|
|
/bin/echo -en "$passphrase" | cryptsetup luksOpen "$dev" lvm
|
|
}
|
|
#}}}
|
|
# setup_lvm{{{
|
|
setup_lvm() {
|
|
local partition="$1"; shift
|
|
local volgroup="$1"; shift
|
|
|
|
local d_size=$(lsblk --noheadings --nodeps --bytes --raw --output SIZE $DRIVE)
|
|
|
|
local swap_size=$(free -b | awk '/^Mem/ { printf "%.0fG", 2*$2*10**-9}')
|
|
|
|
pvcreate "$partition"
|
|
vgcreate "$volgroup" "$partition"
|
|
|
|
# Create a swap partition that is twice the amount of RAM
|
|
lvcreate --yes -L$swap_size "$volgroup" -n swap
|
|
|
|
# if the disk has more than 100Gb
|
|
if [ "$d_size" -gt $( echo "100*10^9" | bc ) ]
|
|
then
|
|
# Create a 50GB root partition
|
|
lvcreate --yes -L '50G' "$volgroup" -n root
|
|
else
|
|
# Create root partition on 50% of free space
|
|
lvcreate --yes -l '+50%FREE' "$volgroup" -n root
|
|
fi
|
|
|
|
# Use the rest of the space for home
|
|
lvcreate --yes -l '+100%FREE' "$volgroup" -n home
|
|
|
|
# Enable the new volumes
|
|
vgchange -ay
|
|
|
|
}
|
|
#}}}
|
|
# format_filesystems #{{{
|
|
format_filesystems() {
|
|
local boot_dev="$1"; shift
|
|
|
|
mkfs.fat "$boot_dev"
|
|
mkfs.ext4 -L root /dev/vg00/root
|
|
mkfs.ext4 -L home /dev/vg00/home
|
|
mkswap /dev/vg00/swap
|
|
}
|
|
#}}}
|
|
# mount_filesystems #{{{
|
|
mount_filesystems() {
|
|
local boot_dev="$1"; shift
|
|
|
|
mount /dev/vg00/root /mnt
|
|
mkdir /mnt/home
|
|
mount /dev/vg00/home /mnt/home
|
|
mkdir /mnt/boot
|
|
mount "$boot_dev" /mnt/boot
|
|
swapon /dev/vg00/swap
|
|
}
|
|
#}}}
|
|
# set_repos() {{{{
|
|
set_repos() {
|
|
# /etc/pacman.conf{{{
|
|
cat > /etc/pacman.conf <<EOF
|
|
#
|
|
# GENERAL OPTIONS
|
|
#
|
|
[options]
|
|
HoldPkg = pacman glibc
|
|
Architecture = auto
|
|
|
|
# Misc options
|
|
#UseSyslog
|
|
Color
|
|
ILoveCandy
|
|
#TotalDownload
|
|
CheckSpace
|
|
#VerbosePkgLists
|
|
|
|
SigLevel = Required DatabaseOptional
|
|
LocalFileSigLevel = Optional
|
|
#RemoteFileSigLevel = Required
|
|
|
|
#
|
|
# REPOSITORIES
|
|
#
|
|
|
|
#[testing]
|
|
#Include = /etc/pacman.d/mirrorlist
|
|
|
|
[core]
|
|
Include = /etc/pacman.d/mirrorlist
|
|
|
|
[extra]
|
|
Include = /etc/pacman.d/mirrorlist
|
|
|
|
#[community-testing]
|
|
#Include = /etc/pacman.d/mirrorlist
|
|
|
|
[community]
|
|
Include = /etc/pacman.d/mirrorlist
|
|
|
|
|
|
#[multilib-testing]
|
|
#Include = /etc/pacman.d/mirrorlist
|
|
|
|
[multilib]
|
|
Include = /etc/pacman.d/mirrorlist
|
|
|
|
EOF
|
|
#}}}
|
|
# /etc/pacman.d/mirrorlist{{{
|
|
pacman -Sy reflector --noconfirm --needed
|
|
|
|
reflector -c $COUNTRY -f 10 -p http -p https
|
|
#}}}
|
|
|
|
mkdir -p /mnt/etc/pacman.d
|
|
cp -r /mnt/etc/pacman* /etc/
|
|
}
|
|
#}}}
|
|
# install_base #{{{
|
|
install_base() {
|
|
pacstrap /mnt \
|
|
base base-devel linux-zen linux-firmware intel-ucode grub \
|
|
fish bluez cronie git man-db \
|
|
iwd dhcpcd
|
|
}
|
|
#}}}
|
|
# Set fstab {{{
|
|
set_fstab() {
|
|
genfstab -Up /mnt > /mnt/etc/fstab
|
|
}
|
|
#}}}
|
|
# Unmount filesystems #{{{
|
|
unmount_filesystems() {
|
|
umount -R /mnt
|
|
swapoff /dev/vg00/swap
|
|
vgchange -an
|
|
if $ENCRYPT_DRIVE
|
|
then
|
|
cryptsetup luksClose lvm
|
|
fi
|
|
}
|
|
#}}}
|
|
# is_bios{{{
|
|
if ls /sys/firmware/efi/efivars/ &> /dev/null
|
|
then
|
|
IS_BIOS=false
|
|
else
|
|
IS_BIOS=true
|
|
fi
|
|
#}}}
|
|
#}}}
|
|
# Configuration{{{
|
|
# configure() {#{{{
|
|
configure() {
|
|
local boot_dev="$DRIVE"1
|
|
local lvm_dev="$DRIVE"2
|
|
|
|
echo 'Setting hostname'
|
|
set_hostname "$HOSTNAME"
|
|
|
|
echo 'Setting timezone'
|
|
set_timezone "$TIMEZONE"
|
|
|
|
echo 'Setting locale'
|
|
set_locale
|
|
|
|
echo 'Setting console keymap'
|
|
set_inputs
|
|
|
|
echo 'Configuring initial ramdisk'
|
|
set_initcpio
|
|
|
|
echo 'Configuring Bluetooth'
|
|
set_bluetooth
|
|
|
|
echo 'Configuring bootloader'
|
|
set_bootctl "$boot_dev" "$lvm_dev"
|
|
|
|
echo 'Configuring sudo'
|
|
set_sudoers
|
|
|
|
echo 'Configuring PAM'
|
|
set_pam
|
|
|
|
echo 'Configuring logind'
|
|
set_logind
|
|
|
|
if [ -z "$ROOT_PASSWORD" ];then
|
|
echo 'Enter the root password:'
|
|
read -s ROOT_PASSWORD
|
|
fi
|
|
|
|
echo 'Setting root password'
|
|
set_root_password "$ROOT_PASSWORD"
|
|
|
|
if [ -z "$USER_PASSWORD" ];then
|
|
echo "Enter the password for user $USER_NAME"
|
|
read -s USER_PASSWORD
|
|
fi
|
|
|
|
echo 'Creating initial user'
|
|
create_user "$USER_NAME" "$USER_PASSWORD"
|
|
|
|
echo 'setting up user'
|
|
cp $0 "/home/$USER_NAME/setup.sh"
|
|
chown $USER_NAME "/home/$USER_NAME/setup.sh"
|
|
su $USER_NAME -c "/home/$USER_NAME/setup.sh"
|
|
|
|
shred "/home/$USER_NAME/setup.sh"
|
|
rm "/home/$USER_NAME/setup.sh"
|
|
|
|
echo 'Setting initial daemons'
|
|
set_daemons "$TMP_ON_TMPFS"
|
|
|
|
echo 'Updating pkgfile database'
|
|
update_pkgfile
|
|
|
|
}
|
|
#}}}
|
|
# set_hostname() {#{{{
|
|
set_hostname() {
|
|
local hostname="$1"; shift
|
|
|
|
/bin/echo "$hostname" > /etc/hostname
|
|
|
|
cat > /etc/hosts <<EOF
|
|
127.0.0.1 localhost.localdomain localhost $hostname
|
|
::1 localhost.localdomain localhost $hostname
|
|
EOF
|
|
}
|
|
#}}}
|
|
# set_timezone() {#{{{
|
|
set_timezone() {
|
|
local timezone="$1"; shift
|
|
|
|
ln -sfT "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime
|
|
|
|
timedatectl set-ntp on
|
|
|
|
hwclock --systohc || echo FAILED TO SET HW CLOCK
|
|
}
|
|
#}}}
|
|
# set_locale() {#{{{
|
|
set_locale() {
|
|
cat > /etc/locale.conf <<EOF
|
|
LANG=$LANG
|
|
LC_COLLATE=C
|
|
EOF
|
|
|
|
cat > /etc/locale.gen <<EOF
|
|
en_US.UTF-8 UTF-8
|
|
$LANG UTF-8
|
|
EOF
|
|
|
|
locale-gen
|
|
}
|
|
#}}}
|
|
# set_inputs() {#{{{
|
|
set_inputs() {
|
|
localectl set-keymap $KEYMAP
|
|
mkdir -p /etc/X11/xorg.conf.d/
|
|
cat > /etc/X11/xorg.conf.d/30-touchpad.conf <<EOF
|
|
Section "InputClass"
|
|
MatchIsTouchpad "on"
|
|
Identifier "devname"
|
|
Driver "libinput"
|
|
Option "Tapping" "on"
|
|
Option "ClickMethod" "clickfinger"
|
|
Option "NaturalScrolling" "true"
|
|
EndSection
|
|
EOF
|
|
|
|
}
|
|
#}}}
|
|
# set_initcpio() {#{{{
|
|
set_initcpio() {
|
|
local vid
|
|
|
|
if [ "$VIDEO_DRIVER" = "i915" ];then
|
|
vid='i915'
|
|
elif [ "$VIDEO_DRIVER" = "nouveau" ];then
|
|
vid='nouveau'
|
|
elif [ "$VIDEO_DRIVER" = "radeon" ];then
|
|
vid='radeon'
|
|
fi
|
|
|
|
local encrypt=""
|
|
if $ENCRYPT_DRIVE
|
|
then
|
|
encrypt="encrypt keyboard"
|
|
fi
|
|
|
|
cat > /etc/mkinitcpio.conf <<EOF
|
|
# vim:set ft=sh
|
|
MODULES=(ext4 $vid)
|
|
|
|
BINARIES=()
|
|
|
|
FILES=()
|
|
|
|
HOOKS=(base udev autodetect block $encrypt lvm2 filesystems fsck)
|
|
|
|
EOF
|
|
|
|
# Intall kernel, if necessary
|
|
[ -f /boot/vmlinuz-linux-zen ] ||
|
|
mkinitcpio -P
|
|
}
|
|
#}}}
|
|
# set_daemons() {#{{{
|
|
set_daemons() {
|
|
local tmp_on_tmpfs="$1"; shift
|
|
if [ -z "$tmp_on_tmpfs" ];then
|
|
systemctl mask tmp.mount
|
|
fi
|
|
|
|
systemctl enable \
|
|
cronie.service \
|
|
iwd.service \
|
|
dhcpcd.service \
|
|
ly.service \
|
|
|
|
# Ly{{{
|
|
mkdir -p /etc/ly/
|
|
cat > /etc/ly/config.ini << EOF
|
|
animate = true
|
|
blank_box = true
|
|
hide_borders = true
|
|
lang = br
|
|
EOF
|
|
#}}}
|
|
}
|
|
#}}}
|
|
# set_bluetooth{{{
|
|
set_bluetooth() {
|
|
mkdir -p /etc/bluetooth/
|
|
cat > /etc/bluetooth/main.conf <<EOF
|
|
|
|
[General]
|
|
DiscoverableTimeout = 0
|
|
Discoverable = true
|
|
|
|
AlwaysPairable = true
|
|
|
|
[Policy]
|
|
AutoEnable=true
|
|
|
|
EOF
|
|
}
|
|
#}}}
|
|
# set_boot_loader() {{{
|
|
set_bootctl() {
|
|
local boot_dev="$1"; shift
|
|
local lvm_dev="$1"; shift
|
|
|
|
local lvm_uuid=$(get_uuid "/dev/vg00/root")
|
|
|
|
local k_args="root=UUID=$lvm_uuid"
|
|
|
|
if $IS_BIOS;then
|
|
cat >> /etc/default/grub <<EOF
|
|
GRUB_CMDLINE_LINUX_DEFAULT="$k_args"
|
|
# GRUB_CMDLINE_LINUX_DEFAULT="quiet splash loglevel=3 vga=current rd.udev.log_priority=3 rd.systemd.show_status=auto vt.global_cursor_default=0 nmi_watchdog=0 $k_args"
|
|
EOF
|
|
|
|
grub-install "$DRIVE"
|
|
grub-mkconfig -o /boot/grub/grub.cfg
|
|
else
|
|
bootctl install
|
|
cat > /boot/loader/entries/arch.conf <<EOF
|
|
title arch
|
|
|
|
linux vmlinuz-linux-zen
|
|
initrd intel-ucode.img
|
|
initrd initramfs-linux-zen.img
|
|
|
|
options $k_args
|
|
# options quiet splash loglevel=3 vga=current rd.udev.log_priority=3 rd.systemd.show_status=auto vt.global_cursor_default=0 nmi_watchdog=0
|
|
EOF
|
|
|
|
fi
|
|
}
|
|
#}}}
|
|
# set_sudoers() {#{{{
|
|
set_sudoers() {
|
|
cat > /etc/sudoers <<EOF
|
|
##
|
|
## User privilege specification
|
|
##
|
|
root ALL=(ALL) ALL
|
|
|
|
## Uncomment to allow members of group wheel to execute any command
|
|
# %wheel ALL=(ALL) ALL
|
|
|
|
## Same thing without a password
|
|
%wheel ALL=(ALL) NOPASSWD: ALL
|
|
|
|
|
|
## Read drop-in files from /etc/sudoers.d
|
|
## (the '#' here does not indicate a comment)
|
|
#includedir /etc/sudoers.d
|
|
EOF
|
|
|
|
chmod 440 /etc/sudoers
|
|
}
|
|
#}}}
|
|
# set_pam{{{
|
|
set_pam() {
|
|
cat > /etc/pam.d/system-local-login <<EOF
|
|
auth include system-login
|
|
account include system-login
|
|
password include system-login
|
|
session include system-login
|
|
|
|
auth optional pam_gnupg.so
|
|
session optional pam_gnupg.so
|
|
EOF
|
|
|
|
}
|
|
#}}}
|
|
# set_logind{{{
|
|
set_logind(){
|
|
mkdir -p /etc/systemd
|
|
cat > /etc/systemd/logind.conf <<EOF
|
|
[Login]
|
|
HandlePowerKey=suspend
|
|
HandleSuspendKey=suspend
|
|
HandleLidSwitch=ignore
|
|
EOF
|
|
}
|
|
#}}}
|
|
# set_root_password() {#{{{
|
|
set_root_password() {
|
|
local password="$1"; shift
|
|
|
|
/bin/echo -en "$password\n$password" | passwd
|
|
}
|
|
#}}}
|
|
# create_user() {#{{{
|
|
create_user() {
|
|
local name="$1"; shift
|
|
local password="$1"; shift
|
|
|
|
grep "^$name" /etc/passwd ||
|
|
useradd -m -s /usr/bin/$USER_SHELL -G adm,systemd-journal,wheel,rfkill,games,network,video,audio,optical,floppy,storage,scanner,power,input "$name"
|
|
/bin/echo -en "$password\n$password" | passwd "$name"
|
|
}
|
|
#}}}
|
|
# update_pkgfile() {#{{{
|
|
update_pkgfile() {
|
|
pkgfile -u
|
|
}
|
|
#}}}
|
|
# get_uuid() {#{{{
|
|
get_uuid() {
|
|
lsblk --noheadings --nodeps --output UUID "$1"
|
|
}
|
|
#}}}
|
|
# is_chroot(){{{{
|
|
is_chroot(){
|
|
test "$(ls -id / | cut -d' ' -f1)" == "2"
|
|
}
|
|
#}}}
|
|
#}}}
|
|
# User setup{{{
|
|
user_setup() {
|
|
|
|
echo 'Installing packages'
|
|
install_aur_packages
|
|
|
|
echo 'Installing dotfiles'
|
|
install_dots
|
|
}
|
|
# Install AUR helper #{{{
|
|
install_aur_packages() {
|
|
|
|
sudo pacman -S --needed git
|
|
|
|
# getting yay
|
|
if ! command -v yay
|
|
then
|
|
git clone http://aur.archlinux.org/yay.git ~/yay
|
|
cd ~/yay
|
|
makepkg -si --noconfirm
|
|
cd -
|
|
fi
|
|
}
|
|
#}}}
|
|
# Install dotfiles{{{
|
|
install_dots() {
|
|
if [ ! -d ~/.dotfiles ];then
|
|
git clone $DOTFILES_URL ~/.dotfiles
|
|
fi
|
|
if [ -f ~/.dotfiles/config.y*ml ]; then
|
|
dotdrop --cfg ~/.dotfiles/config.y*ml install --force --no-banner
|
|
fi
|
|
}
|
|
#}}}
|
|
#}}}
|
|
|
|
if [ ! "$USER" == "root" ];then
|
|
user_setup
|
|
elif is_chroot;then
|
|
configure
|
|
else
|
|
setup
|
|
fi
|
|
|
|
# vim:foldmethod=marker
|