Compare commits
2 Commits
4f6ee7cc88
...
3898aa52be
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3898aa52be | ||
![]() |
28de550295 |
110
README.md
Normal file
110
README.md
Normal file
@ -0,0 +1,110 @@
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
We want users to be able to use a variety of erlang programs, which means they
|
||||
need to know how to install an erlang runtime that can run our programs. On any
|
||||
given day this will have a well defined answer, but as erlang changes, and as
|
||||
our dependencies change, the exact installation process might change too. In
|
||||
order to reliably recreate the experience of a new user, on a variety of
|
||||
possible distributions, we create a collection of chroot environments, one for
|
||||
each distribution we want to document, and then use those chroot environments
|
||||
to develop and maintain install scripts.
|
||||
|
||||
These install scripts will check *every* dependency needed, even on a totally
|
||||
fresh installation of the corresponding linux distribution, because that is
|
||||
exactly what the chroot environments will be. This means that the install
|
||||
scripts will work on any install, whether it has been used for a long time, or
|
||||
whether it is also a fresh install, if you're mining on a VPS, or custom
|
||||
hardware, or whatever else.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
At the moment there is only one distribution, Debian, which you can test in the
|
||||
`chroot_sandboxes/debian` subdirectory. From there you can run a variety of
|
||||
posix shell scripts to create, enter, and delete chroot environments.
|
||||
|
||||
Create Environment
|
||||
------------------
|
||||
|
||||
cd into `debian` and run `sudo ./create_environment` to automatically download
|
||||
`debootstrap` from [debian.org](https://www.debian.org), and create a debian
|
||||
system with it. If you already have `debootstrap` installed, then that version
|
||||
will be used instead. `debootstrap` can be installed with `apt`, if you are
|
||||
already on an `apt`y system. Running `make install` in `debian/debootstrap` is
|
||||
not recommended, since your distribution's package manager won't be able to
|
||||
uninstall it for you.
|
||||
|
||||
A minimal debian system will be created under `debian/clean_environment`, and
|
||||
then copied over to `debian/test_environment`. This way if you run
|
||||
`sudo ./create_environment` again, instead of downloading the whole
|
||||
distribution again, it can simply overwrite `test_environment` with a new
|
||||
copy, allowing rapid iteration of install scripts, run on totally fresh
|
||||
systems every time.
|
||||
|
||||
The script also sets up the mount points and /tmp directory in
|
||||
`debian/test_environment`, each time that it is copied from
|
||||
`debian/clean_environment`. This means `debian/clean_environment` is always an
|
||||
ordinary file hierarchy with no mount points, that can be recursively deleted,
|
||||
whereas `debian/test_environment` needs to be handled more carefully, see
|
||||
[Destroy Environment](#destroy-environment) for instructions.
|
||||
|
||||
Finally, the script will copy all install scripts in `debian/install_scripts`
|
||||
into the chroot environment, and perform the chroot itself. The chroot is
|
||||
instructed to run `install_scripts/user_setup` with this new root directory,
|
||||
and this script will install sudo, create a user with passwordless `sudo`
|
||||
rights, and `su` into that user. You can then freely test whatever scripts you
|
||||
want as that user, and leave the environment.
|
||||
|
||||
If you don't want to do anything interactive as that user, but instead want to
|
||||
run a single script and then exit, pass that script and its arguments to
|
||||
`sudo ./create_environment` and they will be passed down into the chroot
|
||||
environment, and run instead of the default `/bin/bash` that is normally run
|
||||
by `su`. Remember that the command will be run inside the chroot environment,
|
||||
with `/home/user` as the working directory, so the script will need to be
|
||||
accessed relative to that. e.g.
|
||||
`sudo ./create_environment ./install_scripts/your_script`
|
||||
or
|
||||
`sudo ./create_environment ~/install_scripts/your_script`.
|
||||
|
||||
Destroy Environment
|
||||
-------------------
|
||||
|
||||
The `create_environment` and `enter_environment` scripts try to clean up the
|
||||
mounts that they create, and the mounts will all disappear on reboot, but just
|
||||
in case they are still present, you can run `sudo ./cleanup` to delete the
|
||||
`test_environment` safely. If you want to delete both environments and
|
||||
`debootstrap` in one go, then `sudo ./cleanup everything` will safely unmount
|
||||
`test_environment` and then delete all three directories.
|
||||
|
||||
`cleanup` has other options too. For example, if you want to chroot into the
|
||||
environment as root, you can manually add the mount points back using
|
||||
`sudo ./cleanup add_mounts`, and then chroot in yourself. There is also
|
||||
`sudo ./cleanup mounts` to remove the mounts manually without deleting
|
||||
`test_environment`.
|
||||
|
||||
Reuse an Existing Environment
|
||||
-----------------------------
|
||||
|
||||
If you want to enter an environment again, run `sudo ./enter_environment`, and
|
||||
it will chroot into the environment without deleting and recreating it,
|
||||
without installing `sudo` again, and without creating a new user.
|
||||
|
||||
To run a script, just like with `create_environment`, you can pass arguments,
|
||||
as long as the paths involved are relative to the new root and home directory.
|
||||
e.g. `sudo ./enter_environment ~/install_scripts/your_script`.
|
||||
|
||||
If you reboot your machine, the mount points of the chroot environment will be
|
||||
missing, (unless you put them in your system-wide fstab, you sicko,) but
|
||||
`sudo ./enter_environment` will detect this and add the mount points back
|
||||
automatically.
|
||||
|
||||
If you are iterating an install script, then it's usually more useful to just
|
||||
run the whole thing again using `create_environment`, but if you want to
|
||||
compose multiple operations together in a script outside of the chroot, or if
|
||||
you want to enter an interactive environment again after running some more
|
||||
expensive script, then this might be useful. For example, you could test
|
||||
`create_environment` itself on other distributions, by running it inside of a
|
||||
chroot.
|
||||
|
90
debian/cleanup
vendored
Executable file
90
debian/cleanup
vendored
Executable file
@ -0,0 +1,90 @@
|
||||
#!/bin/sh
|
||||
|
||||
if test `id -u` -ne 0
|
||||
then
|
||||
echo "$0 must be run as root."
|
||||
return
|
||||
fi
|
||||
|
||||
FRESH=clean_environment
|
||||
ROOT=test_environment
|
||||
|
||||
add_mount() {
|
||||
if mountpoint "$ROOT$1" > /dev/null
|
||||
then
|
||||
echo "$ROOT$1 already mounted."
|
||||
else
|
||||
echo "Mounting $1 to $ROOT$1"
|
||||
mkdir -p "$ROOT$1"
|
||||
mount -o bind "$1" "$ROOT$1"
|
||||
fi
|
||||
}
|
||||
|
||||
remove_mount() {
|
||||
if mountpoint "$ROOT$1" > /dev/null
|
||||
then
|
||||
echo "Unmounting $ROOT$1"
|
||||
umount "$ROOT$1"
|
||||
fi
|
||||
}
|
||||
|
||||
add_mounts() {
|
||||
add_mount /proc
|
||||
add_mount /sys
|
||||
add_mount /dev
|
||||
add_mount /dev/pts
|
||||
}
|
||||
|
||||
remove_mounts() {
|
||||
remove_mount /dev/pts
|
||||
remove_mount /dev
|
||||
remove_mount /sys
|
||||
remove_mount /proc
|
||||
}
|
||||
|
||||
remove_environment() {
|
||||
if test -d "$ROOT"
|
||||
then
|
||||
# Call this script that automatically unmounts the mount points too.
|
||||
remove_mounts
|
||||
echo "Removing $ROOT"
|
||||
rm -r "$ROOT"
|
||||
else
|
||||
echo "No environment found at $ROOT. Doing nothing."
|
||||
fi
|
||||
}
|
||||
|
||||
remove_everything() {
|
||||
if test -d "$ROOT"
|
||||
then
|
||||
# Call this script that automatically unmounts the mount points too.
|
||||
remove_environment
|
||||
fi
|
||||
|
||||
if test -d "$FRESH"
|
||||
then
|
||||
echo "Removing $FRESH"
|
||||
rm -r "$FRESH"
|
||||
fi
|
||||
|
||||
if test -d debootstrap
|
||||
then
|
||||
echo "Removing debootstrap"
|
||||
rm -r debootstrap
|
||||
fi
|
||||
|
||||
if test -f debootstrap.tar.gz
|
||||
then
|
||||
echo "Removing debootstrap.tar.gz"
|
||||
rm debootstrap.tar.gz
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
everything) remove_everything ;;
|
||||
mounts) remove_mounts ;;
|
||||
add_mounts) add_mounts ;;
|
||||
environment) remove_environment ;;
|
||||
"") remove_environment ;;
|
||||
esac
|
||||
|
32
debian/cleanup_everything
vendored
32
debian/cleanup_everything
vendored
@ -1,32 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if test `id -u` -ne 0
|
||||
then
|
||||
echo "$0 must be run as root."
|
||||
return
|
||||
fi
|
||||
|
||||
if test -d test_environment
|
||||
then
|
||||
# Call this script that automatically unmounts the mount points too.
|
||||
./destroy_environment
|
||||
fi
|
||||
|
||||
if test -d clean_environment
|
||||
then
|
||||
echo "Removing clean_environment"
|
||||
rm -r clean_environment
|
||||
fi
|
||||
|
||||
if test -d debootstrap
|
||||
then
|
||||
echo "Removing debootstrap"
|
||||
rm -r debootstrap
|
||||
fi
|
||||
|
||||
if test -f debootstrap.tar.gz
|
||||
then
|
||||
echo "Removing debootstrap.tar.gz"
|
||||
rm debootstrap.tar.gz
|
||||
fi
|
||||
|
26
debian/create_environment
vendored
26
debian/create_environment
vendored
@ -17,26 +17,26 @@ else
|
||||
./get_debootstrap --arch i386 sid "$FRESH" http://deb.debian.org/debian/
|
||||
fi
|
||||
|
||||
cleanup_mount() {
|
||||
if mountpoint "$1" > /dev/null
|
||||
then
|
||||
echo "Unmounting $1"
|
||||
umount "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
if test -e "$ROOT"
|
||||
then
|
||||
echo "Existing installation found at $ROOT, removing."
|
||||
./destroy_environment
|
||||
./cleanup
|
||||
fi
|
||||
|
||||
echo "Copying $FRESH to $ROOT."
|
||||
cp -r "$FRESH" "$ROOT"
|
||||
|
||||
echo "Initializing $ROOT."
|
||||
mkdir -p "$ROOT/proc"
|
||||
mount proc $ROOT/proc -t proc
|
||||
mkdir -p "$ROOT/sys"
|
||||
mount sysfs $ROOT/sys -t sysfs
|
||||
|
||||
./cleanup add_mounts
|
||||
|
||||
# Don't bother creating a new tmpfs. We don't want to leak files in, and we
|
||||
# don't want to waste more RAM on a second tmpfs. The whole thing is
|
||||
# temporary, after all.
|
||||
chmod 1777 "$ROOT/tmp"
|
||||
|
||||
cp -r install_scripts "$ROOT/root"
|
||||
|
||||
chroot "$ROOT" /root/install_scripts/user_setup "$@"
|
||||
|
||||
./cleanup mounts
|
||||
|
28
debian/destroy_environment
vendored
28
debian/destroy_environment
vendored
@ -1,28 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if test `id -u` -ne 0
|
||||
then
|
||||
echo "$0 must be run as root."
|
||||
return
|
||||
fi
|
||||
|
||||
ROOT=test_environment
|
||||
|
||||
cleanup_mount() {
|
||||
if mountpoint "$1" > /dev/null
|
||||
then
|
||||
echo "Unmounting $1"
|
||||
umount "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
if test -e "$ROOT"
|
||||
then
|
||||
cleanup_mount "$ROOT/proc"
|
||||
cleanup_mount "$ROOT/sys"
|
||||
echo "Removing $ROOT"
|
||||
rm -r "$ROOT"
|
||||
else
|
||||
echo "No environment found at $ROOT. Doing nothing."
|
||||
fi
|
||||
|
22
debian/enter_environment
vendored
Executable file
22
debian/enter_environment
vendored
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
if test `id -u` -ne 0
|
||||
then
|
||||
echo "$0 must be run as root."
|
||||
return
|
||||
fi
|
||||
|
||||
ROOT=test_environment
|
||||
|
||||
if test -e "$ROOT"
|
||||
then
|
||||
echo "Using existing environment in $ROOT."
|
||||
else
|
||||
./create_environment
|
||||
fi
|
||||
|
||||
./cleanup add_mounts
|
||||
|
||||
chroot "$ROOT" sudo -iu user "$@"
|
||||
|
||||
./cleanup mounts
|
3
debian/install_scripts/get_erlang_zx
vendored
Executable file
3
debian/install_scripts/get_erlang_zx
vendored
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
sudo apt install erlang-base
|
||||
wget -q https://zxq9.com/projects/zomp/get_zx && bash get_zx
|
25
debian/install_scripts/user_setup
vendored
Executable file
25
debian/install_scripts/user_setup
vendored
Executable file
@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Noninteractive, so that other scripts can install things with apt.
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Overwrite locale setting specified before the chroot
|
||||
export LANG=C
|
||||
export LC_ALL=C
|
||||
|
||||
# Install sudo, since most user-facing scripts will use sudo
|
||||
apt install sudo
|
||||
|
||||
# Add a passwordless sudoer
|
||||
useradd -m -s /bin/bash -G sudo user
|
||||
passwd -d user
|
||||
echo "user ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/user"
|
||||
chmod 0440 "/etc/sudoers.d/user"
|
||||
|
||||
# Copy the install scripts into their home directory
|
||||
cp -r ~/install_scripts /home/user
|
||||
chown -R user:user /home/user/install_scripts
|
||||
|
||||
# su to this new user... Or sudo -iu, since we want to pass in arguments too.
|
||||
cd /home/user
|
||||
sudo -iu user "$@"
|
25
debian/mountpoints
vendored
Executable file
25
debian/mountpoints
vendored
Executable file
@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
|
||||
if test `id -u` -ne 0
|
||||
then
|
||||
echo "$0 must be run as root."
|
||||
return
|
||||
fi
|
||||
|
||||
ROOT=test_environment
|
||||
|
||||
check_mount() {
|
||||
if mountpoint "$ROOT$1" > /dev/null
|
||||
then
|
||||
echo "$ROOT$1 already mounted."
|
||||
else
|
||||
mkdir -p "$ROOT$1"
|
||||
mount -o bind "$1" "$ROOT$1"
|
||||
fi
|
||||
}
|
||||
|
||||
check_mount /proc
|
||||
check_mount /sys
|
||||
check_mount /dev
|
||||
check_mount /dev/pts
|
||||
|
Loading…
x
Reference in New Issue
Block a user