282 lines
8.5 KiB
Bash
Executable File
282 lines
8.5 KiB
Bash
Executable File
#!/bin/sh
|
|
# Fallar ante cualquier error
|
|
set -e
|
|
|
|
# Por ahora sólo soportamos x86_64
|
|
uname -m | grep -q x86_64 || exit 1
|
|
|
|
DIR="$(dirname "$(realpath "$0")")"
|
|
ROOT="$(dirname "$DIR")"
|
|
SELF="$(basename "$0")"
|
|
SSH_ADHOC=false
|
|
|
|
# Sólo se puede correr desde el directorio de Sutty
|
|
if test "$ROOT" != "$(dirname "$PWD")" && test "$ROOT" != "$PWD"; then
|
|
echo "¡No estás corriendo dentro de una carpeta de Sutty!" >&2
|
|
fi
|
|
|
|
# Necesitamos bubblewrap
|
|
if ! test "$HAIN_ENV" && ! type bwrap >/dev/null 2>&1 ; then
|
|
echo "Por favor, instala el paquete bubblewrap" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if test -f /proc/sys/kernel/unprivileged_userns_clone && test "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -ne 1 ; then
|
|
echo "Necesitamos configurar tu sistema, ingresa tu contraseña para correr el comando" >&2
|
|
echo "sudo sysctl -a kernel.unprivileged_userns_clone=1" >&2
|
|
sudo sysctl -a kernel.unprivileged_userns_clone=1
|
|
fi
|
|
|
|
# Si estamos corriendo el comando desde la raíz de trabajo no hay que
|
|
# agregar el directorio.
|
|
if test "$ROOT" = "$PWD"; then
|
|
WORKDIR="/Sutty"
|
|
else
|
|
WORKDIR="/Sutty/${PWD##*/}/"
|
|
fi
|
|
|
|
# Podemos cambiar el entorno
|
|
ENTORNO=${ENTORNO:-${ROOT}/hain}
|
|
|
|
correr() {
|
|
echo "> $1" >&2
|
|
|
|
if test "$AS_ROOT"; then
|
|
SET_UID=0
|
|
SET_GID=0
|
|
else
|
|
SET_UID="$(id -u)"
|
|
SET_GID="$(id -g)"
|
|
fi
|
|
|
|
env -i \
|
|
DISPLAY="$DISPLAY" \
|
|
TERM="$TERM" \
|
|
USER="suttier" \
|
|
HOME="/home/suttier" \
|
|
HAIN_ENV=true \
|
|
RAILS_ENV="${RAILS_ENV:-development}" \
|
|
JEKYLL_ENV="${JEKYLL_ENV:-development}" \
|
|
$(test -f "$ENV_FILE" && (grep -v '^#' "$ENV_FILE" | xargs -0) || true) \
|
|
EDITOR="nano" \
|
|
PAGER="less -niSFX" \
|
|
SSH_AUTH_SOCK="${SSH_AUTH_SOCK}" \
|
|
bwrap \
|
|
--die-with-parent \
|
|
--unshare-user \
|
|
--uid "$SET_UID" \
|
|
--gid "$SET_GID" \
|
|
--unshare-ipc \
|
|
--unshare-uts \
|
|
--unshare-cgroup-try \
|
|
--bind "$ENTORNO" / \
|
|
--bind "$ROOT" /Sutty \
|
|
$(test -f ~/.Xauthority && echo "--ro-bind $HOME/.Xauthority /home/suttier/.Xauthority") \
|
|
--ro-bind /etc/hosts /etc/hosts \
|
|
--ro-bind /etc/resolv.conf /etc/resolv.conf \
|
|
--ro-bind /etc/localtime /etc/localtime \
|
|
--dev-bind /dev /dev \
|
|
--dev-bind /sys /sys \
|
|
--dev-bind /proc /proc \
|
|
--dev-bind /tmp /tmp \
|
|
--chdir "$WORKDIR" \
|
|
/bin/sh -l -c "$1" < "${stdin:-/dev/null}"
|
|
}
|
|
|
|
generar_certificado() {
|
|
chmod 700 "$ENTORNO/etc/ssl/private"
|
|
|
|
ca_key="/etc/ssl/private/ca-sutty.key"
|
|
ca_crt="/usr/local/share/ca-certificates/ca-sutty.crt"
|
|
|
|
domain_key="/etc/ssl/private/sutty.local.key"
|
|
domain_csr="/etc/ssl/private/sutty.local.csr"
|
|
domain_crt="/etc/ssl/certs/sutty.local.crt"
|
|
|
|
if test -f "$ROOT/sutty.local/domain/sutty.local.crt"; then
|
|
SUTTY_LOCAL="$ROOT/sutty.local"
|
|
|
|
echo "Migrando certificados de sutty.local..." >&2
|
|
|
|
cp "$SUTTY_LOCAL/ca/key.key" "$ENTORNO$ca_key"
|
|
cp "$SUTTY_LOCAL/ca/crt.crt" "$ENTORNO$ca_crt"
|
|
|
|
cp "$SUTTY_LOCAL/domain/sutty.local.key" "$ENTORNO$domain_key"
|
|
cp "$SUTTY_LOCAL/domain/sutty.local.csr" "$ENTORNO$domain_csr"
|
|
cp "$SUTTY_LOCAL/domain/sutty.local.crt" "$ENTORNO$domain_crt"
|
|
return
|
|
fi
|
|
|
|
echo "Generando certificados..." >&2
|
|
|
|
correr "openssl req -x509 -nodes -new -sha256 -days 3650 -newkey rsa:2048 \
|
|
-keyout $ca_key -out $ca_crt.pem -subj '/C=AR/CN=Sutty-Local-CA'"
|
|
correr "openssl x509 -outform pem -in $ca_crt.pem -out $ca_crt"
|
|
|
|
correr "update-ca-certificates"
|
|
|
|
correr "openssl req -new -nodes -newkey rsa:2048 \
|
|
-keyout $domain_key -out $domain_csr \
|
|
-subj '/C=AR/ST=Ninguno/L=Interdimension/O=Sutty-Local/CN=sutty.local'"
|
|
correr "openssl x509 -req -sha256 -days 3650 \
|
|
-in $domain_csr -CA $ca_crt -CAkey $ca_key \
|
|
-CAcreateserial -extfile /Sutty/haini.sh/domains.ext -out $domain_crt"
|
|
|
|
rm "$ENTORNO$ca_crt.pem"
|
|
|
|
echo "Instalando certificados..." >&2
|
|
if which update-ca-certificates 2>/dev/null; then
|
|
sudo install -Dm 644 "$ENTORNO$ca_crt" /usr/share/ca-certificates/extra/sutty.crt
|
|
sudo dpkg-reconfigure ca-certificates
|
|
sudo update-ca-certificates
|
|
else
|
|
sudo trust anchor "$ENTORNO$ca_crt"
|
|
fi
|
|
}
|
|
|
|
crear_entorno() {
|
|
ALPINE="3.13.5"
|
|
ALPINE_URL="https://dl-cdn.alpinelinux.org/alpine/v${ALPINE%.*}/releases/x86_64/alpine-minirootfs-${ALPINE}-x86_64.tar.gz"
|
|
|
|
# Definir si vamos a usar wget o curl
|
|
type wget >/dev/null 2>&1 && download="wget -O -"
|
|
type busybox >/dev/null 2>&1 && download="busybox wget -O -"
|
|
type curl >/dev/null 2>&1 && download="curl"
|
|
|
|
# Si no hay ninguno de los dos, salir
|
|
test -z "${download}" && exit 1
|
|
|
|
# Darle permiso de lectura a otres también
|
|
umask 022
|
|
|
|
# Crear el directorio de trabajo
|
|
mkdir -p "$ENTORNO"
|
|
|
|
# Descargar y extraer Alpine
|
|
test -f "$ENTORNO/etc/os-release" || ${download} "${ALPINE_URL}" | tar xz --directory "$ENTORNO"
|
|
# Configurar los repositorios de Sutty
|
|
grep -q sutty "$ENTORNO/etc/apk/repositories" || echo "https://alpine.sutty.nl/alpine/v${ALPINE%\.*}/sutty" >> "$ENTORNO/etc/apk/repositories"
|
|
test -f "$ENTORNO/etc/apk/keys/alpine@sutty.nl-5ea884cd.rsa.pub" || wget https://alpine.sutty.nl/alpine/sutty.pub -O "$ENTORNO/etc/apk/keys/alpine@sutty.nl-5ea884cd.rsa.pub"
|
|
|
|
# Instalar las dependencias solo si cambiaron
|
|
if test "$ENTORNO/etc/apk/world" -ot "$DIR/packages"; then
|
|
echo "Instalando paquetes..." >&2
|
|
packages="$(tr "\n" " " < "$DIR/packages")"
|
|
correr "apk add --no-cache $packages"
|
|
fi
|
|
|
|
# Habilitar la instalación de gemas binarias
|
|
sed -re "s/#(@platforms = )/\1/" -i "$ENTORNO/usr/lib/ruby/2.7.0/rubygems.rb"
|
|
|
|
# Deshabilitar el usuario de nginx
|
|
sed -re "/user nginx/d" -i "$ENTORNO/etc/nginx/nginx.conf"
|
|
|
|
# Crear el directorio del PID
|
|
install -dm 755 "$ENTORNO/run/nginx"
|
|
# Instalar la configuración
|
|
install -m 640 "$DIR/nginx.conf" "$ENTORNO/etc/nginx/http.d/default.conf"
|
|
|
|
mkdir -p "$ENTORNO/home"
|
|
# migrar de versiones anteriores de hainish
|
|
test -d "$ENTORNO$HOME" && test ! -d "$ENTORNO/home/suttier" \
|
|
&& mv "$ENTORNO$HOME" "$ENTORNO/home/suttier"
|
|
mkdir -p "$ENTORNO/home/suttier"
|
|
|
|
if ! grep ^suttier: "$ENTORNO/etc/group" >/dev/null 2>&1 ; then
|
|
AS_ROOT=true correr "addgroup \
|
|
-g $(id -g) \
|
|
suttier"
|
|
fi
|
|
if ! correr "id suttier" >/dev/null 2>&1 ; then
|
|
AS_ROOT=true correr "adduser \
|
|
--disabled-password \
|
|
--gecos '' \
|
|
--home /home/suttier \
|
|
--no-create-home \
|
|
--uid $(id -u) \
|
|
--ingroup suttier \
|
|
suttier"
|
|
fi
|
|
|
|
# Configurar rubygems para que descargue las gemas desde Sutty
|
|
install -m 640 "$DIR/.gemrc" "$ENTORNO/home/suttier/.gemrc"
|
|
|
|
# Resaltado de sintaxis en nano
|
|
grep -q "^include " "$ENTORNO/etc/nanorc" || echo "include \"/usr/share/nano/*.nanorc\"" >> "$ENTORNO/etc/nanorc"
|
|
|
|
# Instalar scripts
|
|
for script in "$DIR/bin/"*; do
|
|
install -m 755 "$script" "$ENTORNO/usr/local/bin/${script##*/}"
|
|
done
|
|
|
|
# Configurar SSH
|
|
install -m 700 -d "$ENTORNO/home/suttier/.ssh"
|
|
install -m 644 "$DIR/ssh/known_hosts" "$ENTORNO/home/suttier/.ssh/known_hosts"
|
|
|
|
test -f "$ENTORNO/etc/ssl/certs/sutty.local.crt" || generar_certificado
|
|
test -f "$ENTORNO/usr/local/share/ca-certificates/ca-sutty.crt" || mv "$ENTORNO/etc/ssl/certs/ca-sutty.crt" "$ENTORNO/usr/local/share/ca-certificates/ca-sutty.crt"
|
|
}
|
|
|
|
# Auto-actualizar una vez por hora
|
|
actualizar() {
|
|
test ! "$TERM" = "dumb" || return
|
|
|
|
last_update="$(find "$DIR/.git/FETCH_HEAD" -mmin +60 | wc -l)"
|
|
|
|
if test ! $last_update -ne 0; then
|
|
return
|
|
fi
|
|
|
|
echo -n "Actualizando haini.sh... " >&2
|
|
if ping -q -c 1 0xacab.org >/dev/null 2>&1; then
|
|
git -C "$DIR" pull --ff-only
|
|
|
|
if test "$DIR/.git/FETCH_HEAD" -ot "$DIR/.git/ORIG_HEAD"; then
|
|
echo "haini.sh se actualizó, por favor volvé a ejecutar el comando" >&2
|
|
exit 0
|
|
fi
|
|
else
|
|
echo "no se pudo conectar 0xacab.org, intentando la próxima vez." >&2
|
|
fi
|
|
}
|
|
|
|
DEFAULT="sh"
|
|
|
|
case $1 in
|
|
init)
|
|
echo "Advertencia: haini.sh init está deprecado, usá \`export PATH=$DIR:\$PATH\`." >&2
|
|
echo "export PATH=$DIR:\$PATH"
|
|
exit
|
|
;;
|
|
serve) shift; DEFAULT=nginx ;;
|
|
*)
|
|
if ! test "$HAIN_ENV" && ! type "$SELF" >/dev/null 2>&1 ; then
|
|
echo "Tip: Usá \`export PATH=$DIR:\$PATH\` para poder correr comandos de haini.sh con solo 'haini.sh'" >&2
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
if test "$HAIN_ENV"; then
|
|
${*:-$DEFAULT}
|
|
else
|
|
if test -z "${SSH_AUTH_SOCK}"; then
|
|
if ! type ssh-agent >/dev/null 2>&1 ; then
|
|
echo "Instala ssh-agent para poder trabajar con git remoto dentro de haini.sh" >&2
|
|
else
|
|
SSH_ADHOC=true
|
|
|
|
echo "Iniciando un ssh-agent temporal." >&2
|
|
eval "$(ssh-agent)"
|
|
ssh-add
|
|
fi
|
|
fi
|
|
|
|
actualizar
|
|
crear_entorno
|
|
stdin="$(test "$TERM" = "dumb" || echo "/dev/stdin")" correr "${*:-$DEFAULT}" ; salida=$?
|
|
|
|
${SSH_ADHOC} && ssh-agent -k
|
|
|
|
exit $salida
|
|
fi
|