251 lines
7.8 KiB
Bash
251 lines
7.8 KiB
Bash
#!/bin/bash
|
|
# nullpoint installer - run this from Hetzner rescue mode
|
|
# Use get.sh for wget piping: wget -qO- https://git.dominik-roth.eu/dodox/nullpoint/raw/branch/master/get.sh | bash
|
|
|
|
set -euo pipefail
|
|
|
|
BANNER=$(cat << "EOF"
|
|
:^7J5GB##&&##GPY?~:
|
|
^75B&@@@@@@&&&@@@@@@@#GJ~:
|
|
5&@@@&B5?7~^^^^^~!7YP#@@@@#!
|
|
Y##P7^ :~JB#B!
|
|
:: :
|
|
7PP?: :^~!!~^: :?PP7
|
|
:B@@B: !5B&@@@@&B5! :#@@B:
|
|
:!!: ^G@@@&BPPB@@@@G^ :!!:
|
|
:B@@@5^ ^5@@@B:
|
|
:7J7: !@@@# :&@@@~ :?J7:
|
|
J@@@5 :#@@@Y: :Y@@@B: 5@@@J
|
|
!@@@&^ ~B@@@&G55G&@@@B~ ~&@@@~
|
|
5@@@G: :7P#@@@@@@#P7: :B@@@Y
|
|
:P@@@B~ :~!77!~: ~B@@@P
|
|
Y@@@&Y^ ^5@@@@J
|
|
!G@@@&P7^ ^7P&@@@G~
|
|
!P&@@@&B? :: ?B&@@@&P!
|
|
^75#&&Y :P&&5: 5&&B57^
|
|
:^^ :P&&5: ^^:
|
|
^^
|
|
|
|
[nullpoint]
|
|
EOF
|
|
)
|
|
|
|
clear
|
|
echo -e "\n$BANNER"
|
|
echo -e "\n[+] nullpoint installer starting..."
|
|
|
|
# Check if we're in Hetzner rescue mode
|
|
if [ ! -f /etc/hetzner-build ]; then
|
|
echo "ERROR: This script must be run from Hetzner rescue mode!"
|
|
exit 1
|
|
fi
|
|
|
|
# Get SSH key from current session
|
|
echo "[+] Detecting SSH key from current session..."
|
|
SSH_KEY=$(grep "^ssh-" ~/.ssh/authorized_keys | head -1)
|
|
if [ -z "$SSH_KEY" ]; then
|
|
echo "ERROR: No SSH key found in authorized_keys!"
|
|
echo "Please enter your SSH public key:"
|
|
read -r SSH_KEY
|
|
if [ -z "$SSH_KEY" ]; then
|
|
echo "SSH key is required!"
|
|
exit 1
|
|
fi
|
|
fi
|
|
echo "Found SSH key: ${SSH_KEY:0:50}..."
|
|
|
|
# Ask for hostname
|
|
echo -e "\n[+] Server configuration"
|
|
read -r -p "Enter hostname [nullpoint]: " HOSTNAME < /dev/tty
|
|
HOSTNAME=${HOSTNAME:-nullpoint}
|
|
|
|
# Ask for username
|
|
read -r -p "Enter username for admin account [null]: " USERNAME < /dev/tty
|
|
USERNAME=${USERNAME:-null}
|
|
|
|
# Generate secure LUKS passphrase
|
|
echo -e "\n[+] Generating secure LUKS passphrase..."
|
|
LUKS_PASS=$(openssl rand -base64 30)
|
|
|
|
echo -e "\n================================================"
|
|
echo "LUKS PASSPHRASE (SAVE THIS!):"
|
|
echo "$LUKS_PASS"
|
|
echo "================================================"
|
|
echo -e "\nPress Enter when you've saved the passphrase..."
|
|
read -r < /dev/tty
|
|
|
|
# Check if we're already in the nullpoint directory or need to use it
|
|
if [ -f "install.conf" ] && [ -f "post-install.sh" ]; then
|
|
echo "[+] Using local nullpoint files..."
|
|
else
|
|
# Clean up any existing directory
|
|
if [ -d "/tmp/nullpoint" ]; then
|
|
rm -rf /tmp/nullpoint
|
|
fi
|
|
echo "[+] Downloading nullpoint configuration..."
|
|
git clone https://git.dominik-roth.eu/dodox/nullpoint.git /tmp/nullpoint
|
|
cd /tmp/nullpoint
|
|
fi
|
|
|
|
echo "[+] Configuring installation..."
|
|
|
|
# Auto-detect drives
|
|
echo "[+] Detecting drives..."
|
|
DRIVES=($(lsblk -dno NAME,TYPE | grep disk | awk '{print "/dev/"$1}' | sort))
|
|
if [ ${#DRIVES[@]} -lt 2 ]; then
|
|
echo "ERROR: Need at least 2 drives for RAID1, found ${#DRIVES[@]}"
|
|
exit 1
|
|
fi
|
|
DRIVE1="${DRIVES[0]}"
|
|
DRIVE2="${DRIVES[1]}"
|
|
echo " Found drives: $DRIVE1 and $DRIVE2"
|
|
# Update install.conf with detected drives
|
|
if ! sed -i "s|^DRIVE1 .*|DRIVE1 $DRIVE1|" install.conf; then
|
|
echo "ERROR: Failed to update DRIVE1 in install.conf"
|
|
exit 1
|
|
fi
|
|
if ! sed -i "s|^DRIVE2 .*|DRIVE2 $DRIVE2|" install.conf; then
|
|
echo "ERROR: Failed to update DRIVE2 in install.conf"
|
|
exit 1
|
|
fi
|
|
|
|
# Update hostname
|
|
if ! sed -i "s/^HOSTNAME .*/HOSTNAME $HOSTNAME/" install.conf; then
|
|
echo "ERROR: Failed to update HOSTNAME in install.conf"
|
|
exit 1
|
|
fi
|
|
|
|
# Use awk for CRYPTPASSWORD to handle special characters
|
|
if ! awk -v pass="$LUKS_PASS" '
|
|
/^CRYPTPASSWORD / { print "CRYPTPASSWORD " pass; next }
|
|
{ print }
|
|
' install.conf > install.conf.tmp; then
|
|
echo "ERROR: Failed to update CRYPTPASSWORD in install.conf"
|
|
exit 1
|
|
fi
|
|
mv install.conf.tmp install.conf
|
|
|
|
# Update post-install.sh
|
|
if ! sed -i "s/^ALMA_USER=.*/ALMA_USER=\"$USERNAME\"/" post-install.sh; then
|
|
echo "ERROR: Failed to update ALMA_USER in post-install.sh"
|
|
exit 1
|
|
fi
|
|
|
|
# Use awk to replace SSH_KEY line to avoid sed issues with special characters
|
|
if ! awk -v key="$SSH_KEY" '
|
|
/^SSH_KEY=/ { print "SSH_KEY=\"" key "\""; next }
|
|
{ print }
|
|
' post-install.sh > post-install.sh.tmp; then
|
|
echo "ERROR: Failed to update SSH_KEY in post-install.sh"
|
|
exit 1
|
|
fi
|
|
mv post-install.sh.tmp post-install.sh
|
|
|
|
# Copy to root directory where installimage expects them
|
|
if ! cp install.conf /root/; then
|
|
echo "ERROR: Failed to copy install.conf to /root/"
|
|
exit 1
|
|
fi
|
|
|
|
if ! cp post-install.sh /root/; then
|
|
echo "ERROR: Failed to copy post-install.sh to /root/"
|
|
exit 1
|
|
fi
|
|
|
|
chmod +x /root/post-install.sh
|
|
|
|
# Ask for optional features
|
|
echo -e "\n[+] Optional features:"
|
|
read -r -p "Do you have a TPM and want to use it? [y/N]: " USE_TPM < /dev/tty
|
|
if [[ "$USE_TPM" =~ ^[Yy]$ ]]; then
|
|
echo "TPM will be configured if available."
|
|
else
|
|
sed -i 's/^TPM_ENABLED=.*/TPM_ENABLED=false/' /root/post-install.sh
|
|
fi
|
|
|
|
read -r -p "Do you want to configure remote unlock Tang servers? [y/N]: " USE_TANG < /dev/tty
|
|
if [[ "$USE_TANG" =~ ^[Yy]$ ]]; then
|
|
echo "Configuring Tang servers..."
|
|
TANG_CONFIG=""
|
|
|
|
while true; do
|
|
read -r -p "Enter Tang server URL (or press Enter to finish): " TANG_URL < /dev/tty
|
|
if [ -z "$TANG_URL" ]; then
|
|
break
|
|
fi
|
|
|
|
read -r -p "Enter thumbprint for $TANG_URL: " TANG_THUMBPRINT < /dev/tty
|
|
if [ -n "$TANG_THUMBPRINT" ]; then
|
|
TANG_CONFIG+=" \"$TANG_URL $TANG_THUMBPRINT\"\n"
|
|
echo "Added Tang server: $TANG_URL"
|
|
else
|
|
echo "Skipping server (no thumbprint provided)"
|
|
fi
|
|
done
|
|
|
|
if [ -n "$TANG_CONFIG" ]; then
|
|
# Update the TANG_SERVERS array in post-install.sh
|
|
sed -i '/^TANG_SERVERS=(/,/^)/ {
|
|
/^TANG_SERVERS=(/ {
|
|
r /dev/stdin
|
|
d
|
|
}
|
|
/^)/ !d
|
|
}' /root/post-install.sh << EOF
|
|
TANG_SERVERS=(
|
|
$TANG_CONFIG)
|
|
EOF
|
|
echo "Configured Tang servers in post-install script."
|
|
else
|
|
echo "No Tang servers configured."
|
|
fi
|
|
fi
|
|
|
|
# Final confirmation
|
|
echo -e "\n[+] Ready to install with these settings:"
|
|
echo " Hostname: $HOSTNAME"
|
|
echo " Username: $USERNAME"
|
|
echo " SSH Key: ${SSH_KEY:0:50}..."
|
|
echo " LUKS Passphrase: $LUKS_PASS"
|
|
echo ""
|
|
read -r -p "Proceed with installation? [Y/n]: " CONFIRM < /dev/tty
|
|
if [[ "$CONFIRM" =~ ^[Nn]$ ]]; then
|
|
echo "Installation cancelled."
|
|
exit 1
|
|
fi
|
|
|
|
# Check if installimage exists
|
|
if ! command -v installimage &> /dev/null; then
|
|
echo "ERROR: installimage command not found!"
|
|
echo "This might not be a Hetzner rescue system, or installimage is not in PATH."
|
|
echo "On Hetzner rescue, installimage is usually at /root/.oldroot/nfs/install/installimage"
|
|
|
|
# Try common locations
|
|
if [ -x "/root/.oldroot/nfs/install/installimage" ]; then
|
|
echo "Found installimage at /root/.oldroot/nfs/install/installimage"
|
|
INSTALLIMAGE_CMD="/root/.oldroot/nfs/install/installimage"
|
|
else
|
|
echo "Could not find installimage. Please check your Hetzner rescue environment."
|
|
exit 1
|
|
fi
|
|
else
|
|
INSTALLIMAGE_CMD="installimage"
|
|
fi
|
|
|
|
# Run the installer
|
|
echo -e "\n[+] Starting Hetzner installimage..."
|
|
echo "The installer will now run. Follow any prompts if needed."
|
|
echo ""
|
|
if ! $INSTALLIMAGE_CMD -a -c /root/install.conf -x /root/post-install.sh; then
|
|
echo -e "\nERROR: Installation failed!"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "\n[+] Installation complete!"
|
|
echo ""
|
|
echo "IMPORTANT REMINDERS:"
|
|
echo "1. Save your LUKS passphrase securely!"
|
|
echo "2. After reboot, you'll need to enter it twice (once per disk)"
|
|
echo "3. SSH to the server as user '$USERNAME'"
|
|
echo ""
|
|
echo "The system is ready for use!" |