228 lines
8.8 KiB
Bash
Executable File
228 lines
8.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
# This script builds a development host based on Debian or Ubuntu.
|
|
|
|
set -e
|
|
|
|
HOST_USER="$USER"
|
|
CONTAINER_NAME="devhost-debian-${HOST_USER}"
|
|
IMAGE="debian:latest"
|
|
DISTRO="debian"
|
|
USERNAME="dev"
|
|
USER_PASSWORD="devhost"
|
|
SOURCE_DIR="$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
|
|
SOURCE_NAME="$(basename "$SOURCE_DIR")"
|
|
SSH_PORT="2222"
|
|
|
|
show_help() {
|
|
echo "Usage: $0 [OPTIONS]"
|
|
echo "Set up a fully-fledged Debian or Ubuntu distribution in a Podman container with FUSE support and SSH access."
|
|
echo
|
|
echo "Options:"
|
|
echo " -n, --name NAME Specify the name for the container (default: devhost-debian-${HOST_USER})"
|
|
echo " -u, --user USER Specify the username to create (default: dev)"
|
|
echo " -p, --password PASS Specify the user's password (default: devhost)"
|
|
echo " -s, --ssh-port PORT Specify the SSH port to forward (default: 2222)"
|
|
echo " -d, --distro DISTRO Specify the distribution (debian or ubuntu) (default: debian)"
|
|
echo " -r, --remove Stop and remove the container if it exists"
|
|
echo " -e, --enter Enter the container as the specified user (builds if not exists)"
|
|
echo " -h, --help Display this help message"
|
|
echo
|
|
echo "Note: This script assumes it's located in a 'dev' subdirectory of the source root."
|
|
echo " The entire source root will be copied to /src/<source_root_name> in the container."
|
|
echo " The container name will include the host username: ${CONTAINER_NAME}"
|
|
echo " SSH public keys from $HOME/.ssh/*.pub will be copied to the container for key-based authentication."
|
|
}
|
|
|
|
check_fuse() {
|
|
if [ ! -e /dev/fuse ]; then
|
|
echo "ERROR: FUSE is not available on the host. Please ensure FUSE is installed and loaded."
|
|
echo "You may need to run 'sudo modprobe fuse' on the host system."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
stop_and_remove_container() {
|
|
if podman ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
echo "Stopping container ${CONTAINER_NAME}..."
|
|
podman stop "${CONTAINER_NAME}"
|
|
echo "Removing container ${CONTAINER_NAME}..."
|
|
podman rm "${CONTAINER_NAME}"
|
|
echo "Container ${CONTAINER_NAME} has been stopped and removed."
|
|
exit 0
|
|
else
|
|
echo "Container ${CONTAINER_NAME} does not exist."
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
enter_container() {
|
|
if ! podman ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
echo "Container ${CONTAINER_NAME} does not exist. Building it now..."
|
|
build_container
|
|
fi
|
|
|
|
if ! podman ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
echo "Starting container ${CONTAINER_NAME}..."
|
|
podman start "${CONTAINER_NAME}"
|
|
fi
|
|
echo "Entering container ${CONTAINER_NAME} as user ${USERNAME}..."
|
|
podman exec -it -u "${USERNAME}" "${CONTAINER_NAME}" /bin/bash
|
|
exit 0
|
|
}
|
|
|
|
build_container() {
|
|
echo "Setting up ${DISTRO^} container: $CONTAINER_NAME"
|
|
echo "Source root directory: $SOURCE_DIR"
|
|
echo "Source name: $SOURCE_NAME"
|
|
echo "SSH Port: $SSH_PORT"
|
|
|
|
# create container
|
|
check_fuse
|
|
podman run --name "$CONTAINER_NAME" -d \
|
|
--device /dev/fuse \
|
|
--cap-add SYS_ADMIN \
|
|
--security-opt apparmor:unconfined \
|
|
-p ${SSH_PORT}:22 \
|
|
"$IMAGE" sleep infinity
|
|
|
|
# install system
|
|
podman exec "$CONTAINER_NAME" apt update
|
|
podman exec "$CONTAINER_NAME" apt upgrade -y
|
|
podman exec "$CONTAINER_NAME" apt install -y \
|
|
sudo vim nano curl wget git htop tmux man-db locales \
|
|
bash-completion ca-certificates ssh systemd systemd-sysv \
|
|
build-essential libfuse-dev libudev-dev libsqlite3-dev \
|
|
libmbedtls-dev zlib1g-dev libboost-system-dev \
|
|
libboost-program-options-dev fuse llvm gdb iproute2 \
|
|
openssh-server rsync libreadline-dev
|
|
|
|
# verify fuse
|
|
if ! podman exec "$CONTAINER_NAME" ls /dev/fuse > /dev/null 2>&1; then
|
|
echo "WARNING: FUSE device not found in the container. FUSE might not work properly."
|
|
fi
|
|
|
|
# setup system
|
|
podman exec "$CONTAINER_NAME" sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen
|
|
podman exec "$CONTAINER_NAME" locale-gen
|
|
podman exec "$CONTAINER_NAME" update-locale LANG=en_US.UTF-8
|
|
podman exec "$CONTAINER_NAME" useradd -m -s /bin/bash "$USERNAME"
|
|
podman exec "$CONTAINER_NAME" bash -c "echo $USERNAME:$USER_PASSWORD | chpasswd"
|
|
podman exec "$CONTAINER_NAME" usermod -aG sudo "$USERNAME"
|
|
|
|
podman exec "$CONTAINER_NAME" bash -c 'echo "%sudo ALL=(ALL) ALL" > /etc/sudoers.d/sudo-group'
|
|
|
|
podman exec --user "$USERNAME" "$CONTAINER_NAME" bash -c 'echo "export PS1=\"\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ \"" >> ~/.bashrc'
|
|
|
|
# setup /src tree
|
|
podman exec "$CONTAINER_NAME" mkdir -p "/src/$SOURCE_NAME"
|
|
podman exec "$CONTAINER_NAME" chown -R "$USERNAME:$USERNAME" /src
|
|
|
|
# setup ld.so.conf
|
|
podman exec "$CONTAINER_NAME" bash -c 'echo "/usr/lib/x86_64-linux-gnu/" >> /etc/ld.so.conf'
|
|
podman exec "$CONTAINER_NAME" ldconfig
|
|
|
|
# setup ssh authentication
|
|
podman exec "$CONTAINER_NAME" mkdir -p "/home/$USERNAME/.ssh"
|
|
podman exec "$CONTAINER_NAME" touch "/home/$USERNAME/.ssh/authorized_keys"
|
|
podman exec "$CONTAINER_NAME" chown -R "$USERNAME:$USERNAME" "/home/$USERNAME/.ssh"
|
|
podman exec "$CONTAINER_NAME" chmod 700 "/home/$USERNAME/.ssh"
|
|
podman exec "$CONTAINER_NAME" chmod 600 "/home/$USERNAME/.ssh/authorized_keys"
|
|
for privkey in "$HOME"/.ssh/id_*; do
|
|
podman cp "$privkey" "$CONTAINER_NAME:/home/$USERNAME/.ssh"
|
|
done
|
|
for pubkey in "$HOME"/.ssh/id_*.pub; do
|
|
if [ -f "$pubkey" ]; then
|
|
podman cp "$pubkey" "$CONTAINER_NAME:/home/$USERNAME/.ssh"
|
|
podman cp "$pubkey" "$CONTAINER_NAME:/tmp/$(basename "$pubkey")"
|
|
podman exec "$CONTAINER_NAME" bash -c "cat /tmp/$(basename "$pubkey") >> /home/$USERNAME/.ssh/authorized_keys"
|
|
podman exec "$CONTAINER_NAME" rm "/tmp/$(basename "$pubkey")"
|
|
fi
|
|
done
|
|
|
|
# setup and run sshd
|
|
podman exec "$CONTAINER_NAME" sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
|
|
podman exec "$CONTAINER_NAME" sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config
|
|
podman exec "$CONTAINER_NAME" service ssh start
|
|
|
|
# mop up
|
|
podman exec "$CONTAINER_NAME" apt clean
|
|
podman exec "$CONTAINER_NAME" rm -rf /var/lib/apt/lists/*
|
|
|
|
echo "${DISTRO^} container setup complete!"
|
|
echo "Container name: $CONTAINER_NAME"
|
|
echo "Username: $USERNAME"
|
|
echo "Source root copied to: /src/$SOURCE_NAME"
|
|
echo "Ownership of /src changed to $USERNAME recursively"
|
|
echo "/usr/lib/x86_64-linux-gnu/ added to system library search path"
|
|
echo "FUSE support enabled (check warning messages, if any)"
|
|
echo "SSH server enabled and configured for key-based authentication"
|
|
echo "SSH public keys copied from $HOME/.ssh/*.pub to /home/$USERNAME/.ssh/authorized_keys"
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-n|--name)
|
|
CONTAINER_NAME="$2-${HOST_USER}"
|
|
shift 2
|
|
;;
|
|
-u|--user)
|
|
USERNAME="$2"
|
|
shift 2
|
|
;;
|
|
-p|--password)
|
|
USER_PASSWORD="$2"
|
|
shift 2
|
|
;;
|
|
-s|--ssh-port)
|
|
SSH_PORT="$2"
|
|
shift 2
|
|
;;
|
|
-d|--distro)
|
|
DISTRO="$2"
|
|
if [[ "$DISTRO" != "debian" && "$DISTRO" != "ubuntu" ]]; then
|
|
echo "Error: Invalid distribution. Use 'debian' or 'ubuntu'."
|
|
exit 1
|
|
fi
|
|
IMAGE="${DISTRO}:latest"
|
|
CONTAINER_NAME="devhost-${DISTRO}-${HOST_USER}"
|
|
shift 2
|
|
;;
|
|
-r|--remove)
|
|
stop_and_remove_container
|
|
;;
|
|
-e|--enter)
|
|
enter_container
|
|
;;
|
|
-h|--help)
|
|
show_help
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
build_container
|
|
|
|
echo
|
|
echo "You can start the container with: podman start $CONTAINER_NAME"
|
|
echo "To enter the container, use: $0 -e"
|
|
echo "To stop and remove the container, use: $0 -r"
|
|
echo "To SSH into the container, use: ssh -p $SSH_PORT $USERNAME@localhost"
|