├── src ├── exp │ └── startx-killxdg.bash ├── pacman_hooks │ ├── hooks │ │ └── 90-dracut-install.hook │ └── scripts │ │ └── dracut-install ├── enter ├── exec ├── uth ├── chroot_setup ├── init ├── archbox └── archbox-desktop ├── INSTALL.md ├── CROS_INSTALL.md ├── NIXOS_INSTALL.md ├── install.sh ├── README.md └── LICENSE /src/exp/startx-killxdg.bash: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . /etc/archbox.conf 4 | 5 | startx 6 | $PRIV $PREFIX/share/archbox/bin/uth killxdg 7 | -------------------------------------------------------------------------------- /src/pacman_hooks/hooks/90-dracut-install.hook: -------------------------------------------------------------------------------- 1 | [Trigger] 2 | Type = Path 3 | Operation = Install 4 | Operation = Upgrade 5 | Target = usr/lib/modules/*/pkgbase 6 | Target = usr/lib/dracut/* 7 | 8 | [Action] 9 | Description = Updating linux initcpios in host... 10 | When = PostTransaction 11 | Exec = /usr/share/libalpm/scripts/dracut-install 12 | NeedsTargets 13 | -------------------------------------------------------------------------------- /src/enter: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . /etc/archbox.conf >/dev/null 2>&1 4 | . /tmp/archbox_env >/dev/null 2>&1 5 | 6 | REQ_ENV="DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS} XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR} DISPLAY=${DISPLAY} WAYLAND_DISPLAY=${WAYLAND_DISPLAY}" 7 | 8 | ENV="$REQ_ENV $ENV_VAR" 9 | COMMAND="$@" 10 | chroot $CHROOT /usr/bin/env $ENV /bin/su $ARCHBOX_USER 11 | -------------------------------------------------------------------------------- /src/exec: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . /etc/archbox.conf >/dev/null 2>&1 4 | . /tmp/archbox_env >/dev/null 2>&1 5 | 6 | REQ_ENV="DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS} XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR} DISPLAY=${DISPLAY} WAYLAND_DISPLAY=${WAYLAND_DISPLAY}" 7 | 8 | ENV="$REQ_ENV $ENV_VAR" 9 | COMMAND="$@" 10 | chroot $CHROOT /bin/su -c "/usr/bin/env $ENV $COMMAND" $ARCHBOX_USER 11 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | ## Dependencies 3 | - Bash 4 | - Sed 5 | - Curl 6 | - Wget (Optional: use ```wget``` when it's installed) 7 | - Aria2 (Optional: use ```aria2c``` when it's installed) 8 | - Tar 9 | - Desktop-file-utils 10 | - Xorg-xhost (Optional: allowing users in Archbox to access X server) 11 | - Zenity (Optional: for .desktop entry manager GUI) 12 | ## Installing Archbox 13 | Run : 14 | ```sh 15 | sudo env ARCHBOX_USER="$(whoami)" ./install.sh 16 | ``` 17 | -------------------------------------------------------------------------------- /src/uth: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . /etc/archbox.conf >/dev/null 2>&1 4 | . /tmp/archbox_env >/dev/null 2>&1 5 | 6 | case $1 in 7 | copyresolv) 8 | cp /etc/resolv.conf "${CHROOT}"/etc/resolv.conf 9 | ;; 10 | killxdg) 11 | umount -l "${CHROOT}"/run 12 | fuser -km $XDG_RUNTIME_DIR 13 | exit $? 14 | ;; 15 | runtimeonly) 16 | mkdir -p "${CHROOT}"${XDG_RUNTIME_DIR} 17 | umount -Rl "${CHROOT}"${XDG_RUNTIME_DIR} 2>/dev/null 18 | mount | grep "${CHROOT}"${XDG_RUNTIME_DIR} || \ 19 | mount --rbind $XDG_RUNTIME_DIR "${CHROOT}"${XDG_RUNTIME_DIR} 20 | exit $? 21 | ;; 22 | remountrun) 23 | umount -l "${CHROOT}"/run 2>/dev/null 24 | mount --rbind /run "${CHROOT}"/run 25 | exit $? 26 | ;; 27 | chownvar) 28 | chown $2 /tmp/archbox_env 29 | chmod 755 /tmp/archbox_env 30 | ;; 31 | esac 32 | -------------------------------------------------------------------------------- /src/pacman_hooks/scripts/dracut-install: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | kernels=() 4 | dracut_update=0 5 | 6 | while read -r line; do 7 | if [[ $line != 'usr/lib/modules/'+([^/])'/pkgbase' ]]; then 8 | dracut_update=1 # Dracut files have been updated 9 | continue 10 | fi 11 | 12 | read -r pkgbase < "/${line}" 13 | kernels+=("${pkgbase}") 14 | done 15 | 16 | if (( dracut_update )); then 17 | kernels=() 18 | for file in /lib/modules/*/pkgbase; do 19 | if read -r pkgbase &> /dev/null < "$file"; then 20 | kernels+=("${pkgbase}") 21 | fi 22 | done 23 | fi 24 | 25 | for kernel in "${kernels[@]}"; do 26 | path="$(grep -lE "^${kernel}\$" /usr/lib/modules/*/pkgbase)" 27 | version=$(basename "${path%/pkgbase}") 28 | read -r pkgbase < "$path" 29 | 30 | install -Dm0644 "/${path%'/pkgbase'}/vmlinuz" "/boot/vmlinuz-${pkgbase}" 31 | 32 | echo ":: Building initramfs for $kernel-$version in host..." 33 | chroot /var/host /bin/su -c "dracut -f \"/boot/initramfs-${kernel}.img\" --kver \"${version}\"" 34 | done 35 | -------------------------------------------------------------------------------- /CROS_INSTALL.md: -------------------------------------------------------------------------------- 1 | # Installation (ChromeOS) 2 | ## Prerequisites 3 | - Enabled developer mode 4 | ## Installing dependencies 5 | We'll install needed dependencies with chromebrew, head over to [chromebrew installation guide](https://github.com/skycocker/chromebrew#installation) and do : 6 | ```sh 7 | crew install sommelier wget 8 | crew install llvm # OPTIONAL: needed for AMD GPUs 9 | source ~/.bashrc 10 | ``` 11 | ## Installing Archbox 12 | Just follow [INSTALL.md](INSTALL.md) but with : 13 | 1. Now that `/usr/local` is owned by you, it's better to set `INSTALL_PATH` to somewhere in `/usr/local` in `archbox.conf`, for example `/usr/local/archbox` 14 | 2. Remove `/home` from `SHARED_FOLDER` in `archbox.conf` 15 | 16 | Then add : 17 | ```sh 18 | [[ $DBUS_SESSION_BUS_ADDRESS = "disabled:" ]] && eval "$(dbus-launch)" 19 | ``` 20 | to `~/.bashrc` in Archbox 21 | ## Miscs 22 | ### Init Archbox Automatically 23 | Add `archbox -m` to `~/.bashrc` in host. 24 | ### Uniform look with ChromeOS 25 | Install [`cros-adapta-gtk-theme`](https://aur.archlinux.org/packages/cros-adapta-gtk-theme/), `ttf-roboto`, and `papirus-icon-theme` and use it with : 26 | ```sh 27 | gsettings set org.gnome.desktop.interface gtk-theme "cros-adapta" 28 | gsettings set org.gnome.desktop.interface icon-theme "Papirus-Light" 29 | gsettings set org.gnome.desktop.interface font-name "Roboto 10" 30 | ``` 31 | 32 | For GTK2 apps, use `lxappearance` and for QT5 apps, use `qt5ct` 33 | 34 | ## Issues 35 | ### DBus 36 | Things that depends on `dbus` may broke if you execute it directly, e.g. : 37 | ``` 38 | archbox dconf-editor 39 | ``` 40 | You'll need to enter the shell to use it. 41 | 42 | ### Audio 43 | Audio doesn't seem to work at the moment, It's possible to start pulseaudio in chroot, but I didn't dive enough yet. 44 | -------------------------------------------------------------------------------- /NIXOS_INSTALL.md: -------------------------------------------------------------------------------- 1 | # Installation (NixOS) 2 | ## Install methods 3 | ### Declarative Nix 4 | To install with nix, create a `.nix` file like this and import it to your `configuration.nix` : 5 | ```nix 6 | { config, pkgs, ... }: 7 | 8 | let 9 | archbox = pkgs.stdenv.mkDerivation rec { 10 | name = "archbox"; 11 | src = pkgs.fetchFromGitHub { 12 | owner = "lemniskett"; 13 | repo = "archbox"; 14 | rev = "rev_here"; 15 | sha256 = "rev_sha256_here"; 16 | }; 17 | sourceRoot = "."; 18 | installPhase = '' 19 | mkdir -p $out 20 | cd source 21 | export FORCE_INSTALL_CONFIG=1 22 | export ETC_DIR=$out/etc 23 | export PREFIX=$out 24 | export ARCHBOX_USER=your_user_here 25 | export MOUNT_RUN=no 26 | ${pkgs.bash}/bin/bash install.sh 27 | ''; 28 | }; 29 | in 30 | { 31 | environment.systemPackages = [ archbox ]; 32 | environment.etc = { 33 | "archbox.conf" = { 34 | source = "${archbox}/etc/archbox.conf"; 35 | }; 36 | }; 37 | } 38 | ``` 39 | Replace `your_user_here`, `rev_here`, and `rev_sha256_here`. to get rev and sha256 you can do : 40 | ```sh 41 | nix-shell -p nix-prefetch-git 42 | nix-prefetch-git --url https://github.com/lemniskett/archbox.git 43 | ``` 44 | 45 | Configuration can be done by modifying `installPhase` e.g. : 46 | ```sh 47 | mkdir -p $out 48 | cd source 49 | export FORCE_INSTALL_CONFIG=1 50 | export ETC_DIR=$out/etc 51 | export PREFIX=$out 52 | export ARCHBOX_USER=lemni 53 | export MOUNT_RUN=no 54 | export ENV_VAR="TERM=foot" 55 | export SHARED_FOLDER="/home /var/www" 56 | ${pkgs.bash}/bin/bash install.sh 57 | ``` 58 | ### Regular Installation 59 | See [INSTALL.md](INSTALL.md) 60 | ## Issues 61 | See [issues](https://github.com/lemniskett/archbox/#nixos-specific-issues) 62 | -------------------------------------------------------------------------------- /src/chroot_setup: -------------------------------------------------------------------------------- 1 | # Text colors/formatting 2 | red='\033[1;31m' 3 | green='\033[1;32m' 4 | bold='\033[1m' 5 | reset='\033[m' 6 | 7 | err(){ 8 | printf "${red}${bold}%s${reset}\n" "==> $*" 1>&2 9 | exit 1 10 | } 11 | 12 | msg(){ 13 | printf "${green}${bold}%s${reset}\n" "==> $*" 1>&2 14 | } 15 | 16 | PATH=/usr/bin 17 | 18 | msg "Initializing pacman keyrings..." 19 | pacman-key --init 20 | pacman-key --populate archlinux 21 | msg "Installing essential packages..." 22 | pacman -Syu base base-devel nano --noconfirm 23 | printf "%s" "Do you want to use GUI apps? (y/n) " 24 | read INSTALL_GUI 25 | [ "$INSTALL_GUI" = "y" ] && pacman -Syu xorg pulseaudio --noconfirm 26 | msg "Installing archboxctl..." 27 | mkdir -p /usr/local/bin 28 | curl https://raw.githubusercontent.com/lemniskett/archboxctl/master/archboxctl.bash > /usr/local/bin/archboxctl 29 | chmod 755 /usr/local/bin/archboxctl 30 | msg "Setting up locale..." 31 | printf "%s" "Uncomment needed locale, enter to continue" 32 | read 33 | nano /etc/locale.gen 34 | locale-gen 35 | msg "Setting up timezone..." 36 | printf "%s\n" "Enter your timezone, for example : \"Asia/Jakarta\"" 37 | while true; do 38 | read TIMEZONE \ 39 | && [ -e /usr/share/zoneinfo/$TIMEZONE ] \ 40 | && rm -f /etc/localtime \ 41 | && ln -s /usr/share/zoneinfo/$TIMEZONE /etc/localtime \ 42 | && break \ 43 | || printf "%s\n" "Timezone not found, enter it again." 44 | done 45 | msg "Creating user account..." 46 | read CHROOT_USER < /tmp/archbox_user 47 | useradd -m $CHROOT_USER 48 | usermod -aG wheel $CHROOT_USER 49 | printf "%s\n" "Enter root password" 50 | while true; do 51 | passwd && break 52 | done 53 | printf "%s\n" "Enter $CHROOT_USER password" 54 | while true; do 55 | passwd $CHROOT_USER && break 56 | done 57 | 58 | sed -i 's/# %wheel ALL=(ALL:ALL) NOPASSWD: ALL/%wheel ALL=(ALL:ALL) NOPASSWD: ALL/g' sudoers 59 | printf "%s\n" "Don't forget to run \"archbox --mount\" in host on boot" 60 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | genconfig(){ 4 | cat << EOF 5 | ARCHBOX_USER="${ARCHBOX_USER:-root}" 6 | PRIV="${PRIV:-sudo}" 7 | INSTALL_PATH="${INSTALL_PATH:-/var/archlinux}" 8 | CHROOT="${CHROOT:-\$INSTALL_PATH/root.x86_64}" 9 | 10 | # Nix OS will breaks when you mount /run, change MOUNT_RUN to "no" 11 | # if you use Nix OS, don't forget to use \`archbox --mount-runtime-only\` 12 | # after user login. 13 | MOUNT_RUN="${MOUNT_RUN:-yes}" 14 | 15 | # Mount modules and boot directory, useful if you want to use kernels 16 | # from Arch Linux repo, otherwise it's best to remain disabled. 17 | MOUNT_MOD="${MOUNT_MOD:-no}" 18 | 19 | # Lazy unmounting, make sure you know what you're doing if enabling this! 20 | LAZY_UMOUNT="${LAZY_UMOUNT:-no}" 21 | 22 | # Put your desired enviroment variable here, for example: 23 | # 24 | # ENV_VAR="HOME=/var/home/lemniskett" 25 | # 26 | ENV_VAR="${ENV_VAR:-}" 27 | 28 | # Parse a Systemd service and executes it on boot, order matters, for example: 29 | # 30 | # SERVICES="vmware-networks-configuration vmware-networks vmware-usbarbitrator php-fpm:3 nginx" 31 | # 32 | # Keep in mind that this doesn't resolve service dependencies, so you may need to 33 | # enable the dependencies manually. 34 | SERVICES="${SERVICES:-}" 35 | 36 | # Share other host directories into Archbox, absolute path needed. 37 | SHARED_FOLDER="${SHARED_FOLDER:-/home}" 38 | EOF 39 | } 40 | 41 | ETC_DIR="${ETC_DIR:-/etc}" 42 | PREFIX="${PREFIX:-/usr/local}" 43 | 44 | mkdir -p $PREFIX/share/archbox/bin 45 | mkdir -p $ETC_DIR 46 | install -v -D -m 755 ./src/archbox $PREFIX/bin/archbox 47 | install -v -D -m 755 ./src/archbox-desktop $PREFIX/bin/archbox-desktop 48 | [[ ! -e /etc/archbox.conf || ! -z $FORCE_INSTALL_CONFIG ]] && genconfig > $ETC_DIR/archbox.conf 49 | install -v -D -m 755 ./src/exec $PREFIX/share/archbox/bin/exec 50 | install -v -D -m 755 ./src/enter $PREFIX/share/archbox/bin/enter 51 | install -v -D -m 755 ./src/chroot_setup $PREFIX/share/archbox/chroot_setup 52 | install -v -D -m 755 ./src/init $PREFIX/share/archbox/bin/init 53 | install -v -D -m 755 ./src/uth $PREFIX/share/archbox/bin/uth 54 | 55 | grep 'PREFIX=' $ETC_DIR/archbox.conf >/dev/null 2>&1 || cat << EOF >> $ETC_DIR/archbox.conf 56 | 57 | # Don't change this unless you know what you're doing. 58 | PREFIX="$PREFIX" 59 | EOF 60 | [[ -z $1 ]] && exit 0 61 | 62 | if [ $1 = "--exp" ]; then 63 | install -v -D -m 755 ./src/exp/startx-killxdg.bash $PREFIX/bin/startx-killxdg 64 | else 65 | echo "Unknown install option: $1" 66 | fi 67 | -------------------------------------------------------------------------------- /src/init: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . /etc/archbox.conf 4 | 5 | # Text colors/formatting 6 | red='\033[1;31m' 7 | green='\033[1;32m' 8 | bold='\033[1m' 9 | reset='\033[m' 10 | 11 | err(){ 12 | printf "${red}${bold}%s${reset}\n" "==> $*" 1>&2 13 | exit 1 14 | } 15 | 16 | msg(){ 17 | printf "${green}${bold}%s${reset}\n" "==> $*" 1>&2 18 | } 19 | 20 | checkmount(){ 21 | mount | grep "${CHROOT}${1}" >/dev/null 2>&1 22 | } 23 | 24 | rbind(){ 25 | if checkmount $1; then 26 | msg "${CHROOT}${1} already mounted." 27 | else 28 | mkdir -p "${CHROOT}${1}" 29 | mount -R $1 "${CHROOT}${1}" 30 | msg "${CHROOT}${1} mounted!" 31 | fi 32 | if [ "$2" = "make-rslave" ]; then 33 | mount --make-rslave ${CHROOT}${1} 34 | fi 35 | } 36 | 37 | rbind_diff() { 38 | if checkmount $2; then 39 | msg "${CHROOT}${2} already mounted." 40 | else 41 | mkdir -p "${CHROOT}${1}" 42 | mount -R $1 "${CHROOT}${2}" 43 | msg "${CHROOT}${2} mounted!" 44 | fi 45 | } 46 | 47 | bindproc() { 48 | if checkmount /proc; then 49 | msg "${CHROOT}/proc already mounted." 50 | else 51 | mount -t proc /proc "${CHROOT}"/proc 52 | msg "${CHROOT}/proc mounted!" 53 | fi 54 | } 55 | 56 | rmbind() { 57 | umount_args=-R 58 | [ "$LAZY_UMOUNT" = "yes" ] && umount_args=-Rl 59 | if checkmount $1; then 60 | umount $umount_args "${CHROOT}"${1} 61 | msg "${CHROOT}${1} unmounted!" 62 | fi 63 | } 64 | 65 | case $1 in 66 | start) 67 | bindproc 68 | rbind /tmp 69 | rbind /sys make-rslave 70 | rbind /dev make-rslave 71 | [ "$MOUNT_RUN" = "yes" ] && rbind /run 72 | if [ "$MOUNT_MOD" = "yes" ]; then 73 | rbind "$(readlink -f /lib/modules)" 74 | rbind /boot 75 | fi 76 | [ -d /var/lib/dbus ] && rbind /var/lib/dbus 77 | for i in $SHARED_FOLDER; do 78 | if [ $i = *:* ]; then 79 | source=$(printf "%s" "$i" | sed 's/:.*//') 80 | target=$(printf "%s" "$i" | sed 's/.*://') 81 | mkdir -p "${CHROOT}"${target} 82 | rbind_diff $source $target; 83 | else 84 | rbind $i; 85 | fi 86 | done 87 | msg "Starting services" 88 | for j in $SERVICES; do 89 | if [ $j = *:* ]; then 90 | delay=$(printf "%s" "$j" | sed 's/.*://') 91 | service=$(printf "%s" "$j" | sed 's/:.*//') 92 | chroot "$CHROOT" /bin/su -c "/usr/local/bin/archboxctl exec $service" > /dev/null 2>&1 & 93 | sleep $delay 94 | else 95 | chroot "$CHROOT" /bin/su -c "/usr/local/bin/archboxctl exec $j" > /dev/null 2>&1 & 96 | fi 97 | done 98 | if [ -e /etc/archbox.rc ]; then 99 | cp /etc/archbox.rc /tmp/archbox.rc 100 | chmod +x /tmp/archbox.rc 101 | chroot "$CHROOT" /bin/su -c '/tmp/archbox.rc' > /tmp/archbox.rc.log 2>&1 102 | rm /tmp/archbox.rc 103 | fi 104 | exit 0 105 | ;; 106 | stop) 107 | rmbind /proc 108 | rmbind /tmp 109 | rmbind /sys 110 | rmbind /dev 111 | [ $MOUNT_RUN = "yes" ] && rmbind /run 112 | if [ $MOUNT_MOD = "yes" ]; then 113 | rmbind $(readlink -f /lib/modules) 114 | rmbind /boot 115 | fi 116 | rmbind /var/lib/dbus 117 | for i in $SHARED_FOLDER; do 118 | if [ $i = *:* ]; then 119 | target=$(printf "%s" "$i" | sed 's/.*://') 120 | rmbind $target; 121 | else 122 | rmbind $i; 123 | fi 124 | done 125 | exit 0 126 | ;; 127 | esac 128 | -------------------------------------------------------------------------------- /src/archbox: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . /etc/archbox.conf 4 | 5 | # Text colors/formatting 6 | red='\033[1;31m' 7 | green='\033[1;32m' 8 | bold='\033[1m' 9 | reset='\033[m' 10 | 11 | err(){ 12 | printf "${red}${bold}%s${reset}\n" "==> $*" 1>&2 13 | exit 1 14 | } 15 | 16 | msg(){ 17 | printf "${green}${bold}%s${reset}\n" "==> $*" 18 | } 19 | 20 | checkdep(){ 21 | command -v $1 >/dev/null 2>&1 || err "Install $1!" 22 | } 23 | 24 | asroot(){ 25 | [ $(id -u) -eq 0 ] || err "Run this as root!" 26 | } 27 | 28 | storeenv() { 29 | printf "%s\n" "# This will be sourced when entering Archbox" > /tmp/archbox_env 30 | "$PRIV" ${PREFIX}/share/archbox/bin/uth chownvar $USER 31 | [ $WAYLAND_DISPLAY ] && \ 32 | printf "%s\n" "WAYLAND_DISPLAY=${WAYLAND_DISPLAY}" >> /tmp/archbox_env 33 | if [ $DISPLAY ]; then 34 | command -v xhost >/dev/null 2>&1 && xhost +local: > /dev/null 35 | printf "%s\n" "DISPLAY=${DISPLAY}" >> /tmp/archbox_env 36 | fi 37 | printf "%s\n" "DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS:-disabled:}" >> /tmp/archbox_env 38 | printf "%s\n" "XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-/tmp}" >> /tmp/archbox_env 39 | } 40 | 41 | help_text(){ 42 | printf "%s" " 43 | USAGE: $0 44 | 45 | OPTIONS: 46 | -c, --create URL Creates a chroot enviroment. 47 | -e, --enter Enters chroot enviroment. 48 | -h, --help Displays this help message. 49 | -m, --mount Mount Archbox directories. 50 | -u, --umount Unmount Archbox directories. 51 | --remount-run Remount /run in chroot enviroment. 52 | --mount-runtime-only Mount XDG_RUNTIME_DIR to chroot enviroment. 53 | 54 | " 55 | } 56 | 57 | fetch_tarball(){ 58 | if command -v aria2c 2>/dev/null; then 59 | aria2c -o archlinux.tar.gz $1 60 | elif command -v wget 2>/dev/null; then 61 | wget -O archlinux.tar.gz $1 62 | elif command -v curl 2>/dev/null; then 63 | curl -o archlinux.tar.gz $1 64 | else 65 | err "No supported downloader found." 66 | fi 67 | } 68 | 69 | case $1 in 70 | -c|--create) 71 | asroot 72 | echo $2 73 | [ ! $2 ] && err "Specify the link of Arch Linux bootstrap tarball!" 74 | msg "Creating chroot directory..." 75 | mkdir -p $INSTALL_PATH 76 | cd $INSTALL_PATH 77 | msg "Downloading Arch Linux tarball..." 78 | while true; do fetch_tarball $2 && break; done 79 | msg "Extracting the tarball..." 80 | checkdep tar 81 | tar xzf archlinux.tar.gz 82 | msg "Enabling internet connection in chroot enviroment..." 83 | cp /etc/resolv.conf "${CHROOT}"/etc/resolv.conf 84 | msg "You will need to edit which mirror you want to use, uncomment needed mirrors and save it." 85 | printf "%s " "Editor of your choice:" 86 | read MIRROR_EDITOR 87 | $MIRROR_EDITOR "${CHROOT}"/etc/pacman.d/mirrorlist || exit 1 88 | msg "Disabling Pacman's CheckSpace..." 89 | checkdep sed 90 | sed -i "s/CheckSpace/#CheckSpace/g" "${CHROOT}"/etc/pacman.conf 91 | msg "Mounting necessary filesystems..." 92 | "${PREFIX}"/share/archbox/bin/init start 93 | cp "${PREFIX}"/share/archbox/chroot_setup "${CHROOT}"/chroot_setup 94 | printf "%s" $ARCHBOX_USER > /tmp/archbox_user 95 | chroot $CHROOT /bin/sh /chroot_setup 96 | exit $? 97 | ;; 98 | -e|--enter) 99 | storeenv 100 | "$PRIV" "${PREFIX}"/share/archbox/bin/uth copyresolv 101 | "$PRIV" "${PREFIX}"/share/archbox/bin/enter 102 | exit $? 103 | ;; 104 | -m|--mount) 105 | "$PRIV" "${PREFIX}"/share/archbox/bin/init start 106 | ;; 107 | -u|--umount) 108 | "$PRIV" "${PREFIX}"/share/archbox/bin/init stop 109 | ;; 110 | --remount-run) 111 | "$PRIV" "${PREFIX}"/share/archbox/bin/uth remountrun 112 | exit $? 113 | ;; 114 | --mount-runtime-only) 115 | "$PRIV" "${PREFIX}"/share/archbox/bin/uth runtimeonly 116 | exit $? 117 | ;; 118 | -h|--help) 119 | help_text 120 | exit 0 121 | ;; 122 | "") 123 | help_text 124 | exit 1 125 | ;; 126 | -*) 127 | err "Unknown option: $1" 128 | ;; 129 | *) 130 | storeenv 131 | "$PRIV" "${PREFIX}"/share/archbox/bin/uth copyresolv 132 | "$PRIV" "${PREFIX}"/share/archbox/bin/exec $@ 133 | exit $? 134 | ;; 135 | esac 136 | -------------------------------------------------------------------------------- /src/archbox-desktop: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . /etc/archbox.conf >/dev/null 2>&1 4 | 5 | multiselect() { 6 | echo "\nSelect with , confirm with " 7 | 8 | # little helpers for terminal print control and key input 9 | ESC=$( printf "\033") 10 | cursor_blink_on() { printf "$ESC[?25h"; } 11 | cursor_blink_off() { printf "$ESC[?25l"; } 12 | cursor_to() { printf "$ESC[$1;${2:-1}H"; } 13 | print_inactive() { printf "$2 $1 "; } 14 | print_active() { printf "$2 $ESC[7m $1 $ESC[27m"; } 15 | get_cursor_row() { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; } 16 | key_input() { 17 | local key 18 | IFS= read -rsn1 key 2>/dev/null >&2 19 | if [[ $key = "" ]]; then echo enter; fi; 20 | if [[ $key = $'\x20' ]]; then echo space; fi; 21 | if [[ $key = $'\x1b' ]]; then 22 | read -rsn2 key 23 | if [[ $key = [A ]]; then echo up; fi; 24 | if [[ $key = [B ]]; then echo down; fi; 25 | fi 26 | } 27 | toggle_option() { 28 | local arr_name=$1 29 | eval "local arr=(\"\${${arr_name}[@]}\")" 30 | local option=$2 31 | if [[ ${arr[option]} == true ]]; then 32 | arr[option]= 33 | else 34 | arr[option]=true 35 | fi 36 | eval $arr_name='("${arr[@]}")' 37 | } 38 | 39 | local retval=$1 40 | local options 41 | local defaults 42 | 43 | IFS=';' read -r -a options <<< "$2" 44 | if [[ -z $3 ]]; then 45 | defaults=() 46 | else 47 | IFS=';' read -r -a defaults <<< "$3" 48 | fi 49 | local selected=() 50 | 51 | for ((i=0; i<${#options[@]}; i++)); do 52 | selected+=("${defaults[i]}") 53 | printf "\n" 54 | done 55 | 56 | # determine current screen position for overwriting the options 57 | local lastrow=`get_cursor_row` 58 | local startrow=$(($lastrow - ${#options[@]})) 59 | 60 | # ensure cursor and input echoing back on upon a ctrl+c during read -s 61 | trap "cursor_blink_on; stty echo; printf '\n'; exit" 2 62 | cursor_blink_off 63 | 64 | local active=0 65 | while true; do 66 | # print options by overwriting the last lines 67 | local idx=0 68 | for option in "${options[@]}"; do 69 | local prefix="[ ]" 70 | if [[ ${selected[idx]} == true ]]; then 71 | prefix="[x]" 72 | fi 73 | 74 | cursor_to $(($startrow + $idx)) 75 | if [ $idx -eq $active ]; then 76 | print_active "$option" "$prefix" 77 | else 78 | print_inactive "$option" "$prefix" 79 | fi 80 | ((idx++)) 81 | done 82 | 83 | # user key control 84 | case `key_input` in 85 | space) toggle_option selected $active;; 86 | enter) break;; 87 | up) ((active--)); 88 | if [ $active -lt 0 ]; then active=$((${#options[@]} - 1)); fi;; 89 | down) ((active++)); 90 | if [ $active -ge ${#options[@]} ]; then active=0; fi;; 91 | esac 92 | done 93 | 94 | # cursor position back to normal 95 | cursor_to $lastrow 96 | printf "\n" 97 | cursor_blink_on 98 | 99 | eval $retval='("${selected[@]}")' 100 | } 101 | 102 | # Text colors/formatting 103 | red='\033[1;31m' 104 | green='\033[1;32m' 105 | bold='\033[1m' 106 | reset='\033[m' 107 | 108 | err(){ 109 | printf "${red}${bold}%s${reset}\n" "==> $*" 1>&2 110 | exit 1 111 | } 112 | 113 | msg(){ 114 | printf "${green}${bold}%s${reset}\n" "==> $*" 1>&2 115 | } 116 | 117 | install_desktop(){ 118 | mkdir -p ~/.local/share/applications/archbox 119 | i="$(echo $1 | sed 's|.*/||')" 120 | archbox readlink /usr/share/applications/$i >/dev/null 2>&1 \ 121 | && cp "${CHROOT}"/$(archbox readlink /usr/share/applications/$i) $HOME/.local/share/applications/archbox/$i \ 122 | || cp "${CHROOT}"/usr/share/applications/$i "$HOME/.local/share/applications/archbox/$i" 123 | sed -i 's/Exec=/Exec=archbox\ /g' ~/.local/share/applications/archbox/$i 124 | sed -i '/TryExec=/d' ~/.local/share/applications/archbox/$i 125 | } 126 | 127 | checkdep(){ 128 | command -v $1 >/dev/null 2>&1 || err "Install $1!" 129 | } 130 | 131 | help_text(){ 132 | printf "%s" " 133 | USAGE: $0 134 | OPTIONS: 135 | Choice to install or uninstall desktop entries 136 | -i, --install FILE Installs desktop entries in /usr/share/applications 137 | -r, --remove FILE Removes desktop entries in ~/.local/share/applications/archbox 138 | -l, --list List available desktop entries 139 | -s, --list-installed List installed desktop entries 140 | -h, --help Displays this help message 141 | " 142 | } 143 | 144 | list(){ 145 | for i in $*/*; do 146 | printf "%s\n" "$i" 147 | done 148 | } 149 | 150 | case $1 in 151 | -i|--install) 152 | checkdep update-desktop-database 153 | install_desktop ${@#$1} 154 | update-desktop-database 155 | exit $? 156 | ;; 157 | -r|--remove) 158 | checkdep update-desktop-database 159 | selected_entry=${@#$1} 160 | for i in $selected_entry; do 161 | rm ~/.local/share/applications/archbox/$i 162 | done 163 | update-desktop-database 164 | exit $? 165 | ;; 166 | -h|--help) 167 | help_text 168 | exit 0 169 | ;; 170 | -l|--list) 171 | list "${CHROOT}"/usr/share/applications 172 | ;; 173 | -s|--list-installed) 174 | mkdir -p ~/.local/share/applications/archbox 175 | list ~/.local/share/applications/archbox 176 | ;; 177 | *) 178 | checkdep sed 179 | checkdep tr 180 | checkdep update-desktop-databse 181 | printf "What do you want to do?\nPress I to install desktop entries.\nPress R to remove desktop entries. (I/r)" 182 | read -rn 1 183 | case $REPLY in 184 | [rR]) 185 | LIST="$(list "${HOME}"/.local/share/applications/archbox)" 186 | printf "$LIST" >/tmp/archboxlist 187 | LIST2="$(cat /tmp/archboxlist | sed -z 's/\n/;/g;s/,$/\n/')" 188 | multiselect RESULT "${LIST2}" 189 | for i in "${!RESULT[@]}"; do 190 | if [ "${RESULT[$i]}" == "true" ]; then 191 | rm ${HOME}/.local/share/applications/archbox/"$(sed "$((i+1))q;d" /tmp/archboxlist | sed 's|.*/||')" 192 | fi 193 | done 194 | update-desktop-database 195 | rm /tmp/archboxlist 196 | exit $? 197 | ;; 198 | *) 199 | LIST="$(list "${CHROOT}"/usr/share/applications)" 200 | printf "$LIST" >/tmp/archboxlist 201 | LIST2="$(cat /tmp/archboxlist | sed -z 's/\n/;/g;s/,$/\n/')" 202 | multiselect RESULT "${LIST2}" 203 | for i in "${!RESULT[@]}"; do 204 | if [ "${RESULT[$i]}" == "true" ]; then 205 | install_desktop "$(sed "$((i+1))q;d" /tmp/archboxlist)" 206 | fi 207 | done 208 | update-desktop-database 209 | rm /tmp/archboxlist 210 | exit 0 211 | 212 | ;; 213 | esac 214 | ;; 215 | esac 216 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Archbox 2 | Installs Arch Linux inside a chroot environment. 3 | ## Why? 4 | Ever since I'm running some niche distros like Void, Solus, I had a problem finding softwares I need in their not-so-large repositories, also I don't like how flatpak and snap works. so i decided to create an Arch Linux chroot environment everytime I distrohop. Why Arch Linux? They have a really, really good repositories, oh and don't mention how big AUR is. 5 | ## Installation 6 | See [INSTALL.md](INSTALL.md) 7 | 8 | For NixOS users, [NIXOS_INSTALL.md](NIXOS_INSTALL.md) 9 | 10 | For ChromeOS users, [CROS_INSTALL.md](CROS_INSTALL.md) 11 | ## Using Archbox 12 | ### Installing chroot environment 13 | Before creating chroot environment, edit your chroot username in ```/etc/archbox.conf```, then do : 14 | ``` 15 | sudo archbox --create 16 | ``` 17 | ### Configuring filesystem automount 18 | Execute ```archbox --mount``` on boot. 19 | If you use systemd, you can create a systemd service with this syntax below (Assuming the install prefix is ```/usr/local```) : 20 | ``` 21 | [Unit] 22 | Description=Archbox init 23 | PartOf=multi-user.target 24 | 25 | [Service] 26 | ExecStart=/usr/local/share/archbox/bin/init start 27 | Type=oneshot 28 | User=root 29 | 30 | [Install] 31 | WantedBy=multi-user.target 32 | ``` 33 | Thanks to [@SamsiFPV](https://github.com/SamsiFPV) 34 | 35 | If you don't use systemd, either create your own init service, or create a @reboot cronjob : 36 | ``` 37 | @reboot /usr/local/share/archbox/bin/init start 38 | ``` 39 | ### Removing chroot environment 40 | **IMPORTANT**, Make sure you've unmounted everything in chroot environment, it's better to remove the init script and reboot to unmount everything. if you can't reboot for some reason, do : 41 | ``` 42 | archbox -u 43 | ``` 44 | then do (Assuming the INSTALL_PATH is /var/archlinux) : 45 | ``` 46 | mount | grep /var/archlinux 47 | ``` 48 | make sure there's no mounted Archbox directories and then delete the Arch Linux directory : 49 | ``` 50 | rm -rf /var/archlinux 51 | ``` 52 | ### Entering chroot environment 53 | To enter chroot, do : 54 | ``` 55 | archbox --enter 56 | ``` 57 | ### Executing commands in chroot environment 58 | To execute commands inside chroot environment, do : 59 | ``` 60 | archbox 61 | ``` 62 | for example, to update chroot, do : 63 | ``` 64 | archbox sudo pacman -Syu 65 | ``` 66 | ### Optional steps 67 | You may want to add these rules if you want to use Archbox without password (assuming the install prefix is ```/usr/local``` and you're in group ```wheel```) : 68 | #### Sudo 69 | ``` 70 | %wheel ALL=(root) NOPASSWD: /usr/local/share/archbox/bin/enter,/usr/local/share/archbox/bin/exec,/usr/local/share/archbox/bin/uth,/usr/local/share/archbox/bin/init 71 | ``` 72 | #### Doas 73 | ``` 74 | permit nopass :wheel as root cmd /usr/local/share/archbox/bin/enter 75 | permit nopass :wheel as root cmd /usr/local/share/archbox/bin/exec 76 | permit nopass :wheel as root cmd /usr/local/share/archbox/bin/uth 77 | permit nopass :wheel as root cmd /usr/local/share/archbox/bin/init 78 | ``` 79 | ### Misc 80 | #### Systemd services 81 | Use ```archboxctl``` command to manage systemd services. 82 | More info [here](https://github.com/lemniskett/archboxctl). 83 | 84 | This isn't actually using systemd to start services, rather it parses systemd .service files and executes it. 85 | 86 | ##### Autostart services 87 | To enable service on host boot, edit `/etc/archbox.conf` : 88 | ``` 89 | SERVICES="vmware-networks-configuration vmware-networks vmware-usbarbitrator nginx" 90 | ``` 91 | Keep in mind that this doesn't resolve service dependencies, so you may need to enable the dependencies manually. you can use ```archboxctl desc ``` to read the .service file 92 | 93 | ##### Post-exec delay 94 | Services are asynchronously started, if some services have some issues when starting together you may want to add post-exec delay. 95 | ``` 96 | SERVICES="php-fpm:3 nginx" 97 | ``` 98 | 99 | This will add 3 seconds delay after executing php-fpm. 100 | ##### Start services immediately 101 | To start services immediately, in Archbox, do : 102 | ```8 103 | sudo archboxctl exec 104 | ``` 105 | 106 | ##### Custom command on boot 107 | You can create a shell script located at ```/etc/archbox.rc``` and ```archboxinit``` will execute it in Archbox on boot. 108 | 109 | #### Desktop entries 110 | Use ```archbox-desktop``` to install desktop entries in chroot to host (installed to ```~/.local/share/applications/archbox```), you'll need to add ```sudo``` (or ```doas```) rules to launch archbox without a password. 111 | #### Lauching apps via rofi 112 | Instead of opening terminal or installing desktop entries everytime you want to run application inside chroot, you may want to launch rofi inside chroot, install rofi and do : 113 | ``` 114 | archbox rofi -show drun 115 | ``` 116 | Just like desktop entries, you'll need to add ```sudo``` (or ```doas```) rules to launch archbox without a password. 117 | #### Prompt 118 | If you use bash with nerd font you could add a nice little Arch Linux icon in your prompt, add : 119 | ``` 120 | [[ -e /etc/arch-release ]] && export PS1=" $PS1" 121 | ``` 122 | to your ```~/.bashrc``` 123 | #### Adding environment variables 124 | Edit ENV_VAR in ```/etc/archbox.conf```. For example, if you want to use qt5ct as Qt5 theme, edit it like this : 125 | ``` 126 | ENV_VAR="QT_QPA_PLATFORMTHEME=qt5ct" 127 | ``` 128 | An example with multiple environment variables. 129 | ``` 130 | ENV_VAR="QT_QPA_PLATFORMTHEME=qt5ct GTK_CSD=0 LD_PRELOAD=/var/home/lemniskett/git_repo/gtk3-nocsd/libgtk3-nocsd.so.0" 131 | ``` 132 | 133 | #### Adding more shared directories 134 | Edit SHARED_FOLDER in ```/etc/archbox.conf```. For example: 135 | ``` 136 | SHARED_FOLDER="/home /var/www" 137 | ``` 138 | To mount to different directory, use ```:``` separator : 139 | ``` 140 | SHARED_FOLDER="/home /var/www:/host_webroot" 141 | ``` 142 | ### Known issues 143 | #### NixOS-specific issues 144 | ##### /run mounting 145 | Mounting ```/run``` somehow breaks NixOS, set ```MOUNT_RUN``` in ```/etc/archbox.conf``` to anything other than ```yes``` to disable mounting ```/run```, then do : 146 | ``` 147 | archbox --mount-runtime-only 148 | ``` 149 | after user login to make XDG runtime directory accessible to chroot enviroment. make sure dbus unix:path is in XDG runtime directory too. 150 | ``` 151 | $ echo $XDG_RUNTIME_DIR 152 | /run/user/1000 153 | $ echo $DBUS_SESSION_BUS_ADDRESS 154 | unix:path=/run/user/1000/bus 155 | ``` 156 | Or alternatively if you use WM-only, just disable mounting ```/run``` entirely and manually set XDG_RUNTIME_DIR into ```/tmp``` like ```/tmp/$(whoami)```, this is not recommended if you use systemd, stuffs like Pipewire, Desktop portal, etc may broke. 157 | 158 | ##### Archbox didn't access resources in /usr/share 159 | In Archbox, Symlink ```/usr``` to ```/run/current-system/sw```: 160 | ``` 161 | sudo mkdir -p /run/current-system 162 | sudo ln -s /usr /run/current-system/sw 163 | ``` 164 | make sure /run isn't mounted. 165 | 166 | ##### Archbox didn't recognize commands 167 | Add ```PATH``` variable to ```/etc/archbox.conf```, for example: 168 | ``` 169 | ENV_VAR="PATH=/usr/bin:/usr/local/bin" 170 | ``` 171 | 172 | #### PulseAudio refused to connect 173 | This can be caused by different dbus machine-id between chroot and host, copying ```/etc/machine-id``` from host to chroot should do the job. 174 | #### XDG_RUNTIME_DIR is not visible in Archbox 175 | Although /run is mounted in chroot environment on boot, XDG_RUNTIME_DIR sometimes is not visible in chroot environment, remounting /run will make it visible. do : 176 | ``` 177 | archbox --remount-run 178 | ``` 179 | after user login, And sometimes you need to kill every process that runs in XDG_RUNTIME_DIR when you log out, You need to reinstall archbox with ```--exp``` flag and use ```startx-killxdg``` instead of ```startx```, or run : 180 | ``` 181 | /usr/local/share/archbox/bin/uth killxdg 182 | ``` 183 | on logout. you can put it in ```/etc/gdm/PostSession/Default``` if you use GDM, or just disable mounting ```/run``` entirely, set ```MOUNT_RUN``` in ```/etc/archbox.conf``` to anything other than ```yes``` to disable mounting ```/run``` and do : 184 | ``` 185 | archbox --remount-run 186 | ``` 187 | after user login. 188 | 189 | #### Polkit 190 | ```pkexec``` is kind of tricky to make it work in chroot, if you use rofi to launch GUI applications in chroot, you may not able to launch any ```.desktop``` files with ```Exec=pkexec...``` in it. If you really want them to work, you can do : 191 | ``` 192 | sudo ln -sf /usr/bin/sudo /usr/bin/pkexec 193 | ``` 194 | in chroot and prevent pacman from restoring ```/usr/bin/pkexec``` by editing ```NoExtract``` in ```/etc/pacman.conf```. 195 | 196 | #### No sudo password in chroot by default. 197 | You could use ```sudo``` in archbox, but you'll have no way to enter the password when doing e.g. ```archbox sudo pacman -Syu```. also you could enter the password if you do ```archbox -e < <(echo $COMMAND)```, but that would disable stdin entirely during $COMMAND. 198 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2021 Syahrial Agni Prasetya 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------