diff --git a/container/README.md b/container/README.md deleted file mode 100644 index fbcf31c..0000000 --- a/container/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# container - -The container directory contains scripts to generate build containers -from various linux distributions. diff --git a/container/debian.sh b/container/debian.sh deleted file mode 100755 index 91def96..0000000 --- a/container/debian.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -set -x - -echo "building debian container..." -ctrid=$(buildah from debian:latest) -buildah run "$ctrid" -- apt update -buildah run "$ctrid" -- apt install build-essential git libfuse-dev libudev-dev libsqlite3-dev libmbedtls-dev zlib1g-dev libboost-system-dev libboost-program-options-dev fuse llvm gdb -export ctrid=$(buildah commit "$ctrid" "$USER/debian-build") -echo "done! you can use $ctrid to start a container" -set +x diff --git a/container/fedora.sh b/container/fedora.sh deleted file mode 100755 index f8451b9..0000000 --- a/container/fedora.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -set -x - -echo "building fedora container..." -ctrid=$(buildah from fedora:latest) -buildah run "$ctrid" -- dnf update -y -buildah run "$ctrid" -- dnf group install -y "C Development Tools and Libraries" -buildah run "$ctrid" -- dnf install -y git fuse fuse-devel sqlite-devel mbedtls-devel zlib-devel boost-system boost-devel boost-program-options udev systemd-devel libasan -export ctrid=$(buildah commit "$ctrid" "$USER/fedora-build") -echo "done! the container name is: $USER/fedora-build" - -set +x diff --git a/container/ubuntu.sh b/container/ubuntu.sh deleted file mode 100755 index 89322f5..0000000 --- a/container/ubuntu.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -set -x - -echo "building ubuntu container..." -ctrid=$(buildah from ubuntu:latest) -buildah run "$ctrid" -- apt update -y -buildah run "$ctrid" -- apt install -y build-essential git libfuse-dev libudev-dev libsqlite3-dev libmbedtls-dev zlib1g-dev libboost-system-dev libboost-program-options-dev fuse llvm gdb -export ctrid=$(buildah commit "$ctrid" "$USER/ubuntu-build") -echo "done! the container name is: $USER/ubuntu-build" -set +x diff --git a/dev/README.md b/dev/README.md new file mode 100644 index 0000000..f9aef50 --- /dev/null +++ b/dev/README.md @@ -0,0 +1,118 @@ +# DevHost Setup Scripts + +This repository contains scripts to set up development environments using Podman containers. The scripts allow you to create and manage development hosts based on Fedora or Debian/Ubuntu, and sync your project files between the host and the container. + +## Scripts + +1. `devhost-fedora.sh`: Sets up a Fedora-based development environment. +2. `devhost-debian.sh`: Sets up a Debian or Ubuntu-based development environment. +3. `sync.sh`: Syncs project files between the host and the container. + +## Prerequisites + +- Podman installed on your host system +- FUSE support on your host system +- SSH key pair for authentication (optional, but recommended) + +## Usage + +### Setting up a Development Host + +#### Fedora-based Host + +```bash +./devhost-fedora.sh [OPTIONS] +``` + +#### Debian/Ubuntu-based Host + +```bash +./devhost-debian.sh [OPTIONS] +``` + +Common options for both scripts: + +- `-n, --name NAME`: Specify the name for the container (default: devhost-[distro]-[username]) +- `-u, --user USER`: Specify the username to create (default: dev) +- `-p, --password PASS`: Specify the user's password (default: devhost) +- `-s, --ssh-port PORT`: Specify the SSH port to forward (default: 2222) +- `-r, --remove`: Stop and remove the container if it exists +- `-e, --enter`: Enter the container as the specified user (builds if not exists) +- `-h, --help`: Display the help message + +Additional option for devhost-debian.sh: + +- `-d, --distro DISTRO`: Specify the distribution (debian or ubuntu) (default: debian) + +### Examples + +1. Create a Fedora-based development host: + ```bash + ./devhost-fedora.sh + ``` + +2. Create an Ubuntu-based development host: + ```bash + ./devhost-debian.sh -d ubuntu + ``` + +3. Create a Debian-based host with a custom name and SSH port: + ```bash + ./devhost-debian.sh -n mydevhost -s 2345 + ``` + +4. Enter an existing container: + ```bash + ./devhost-fedora.sh -e + ``` + +5. Remove an existing container: + ```bash + ./devhost-debian.sh -r + ``` + +### Syncing Project Files + +To sync your project files from the host to the container, use the `sync.sh` script: + +```bash +./sync.sh [OPTIONS] -c CONTAINER_NAME +``` + +Options: + +- `-c, --container CONTAINER_NAME`: Specify the devhost container name (required) +- `-s, --source DIR`: Specify the source directory on the host (default: current directory) +- `-d, --dest DIR`: Specify the destination directory in the container +- `-u, --user USER`: Specify the user in the container (default: dev) +- `-p, --port PORT`: Specify the SSH port (default: 2222) +- `-o, --once`: Sync files once and exit +- `-w, --watch`: Watch for changes and sync continuously (default) +- `-h, --help`: Display the help message + +Example: + +```bash +./sync.sh -c mydevhost-fedora -s /path/to/project -d /src/project -u dev -p 2222 -w +``` + +This will sync files from `/path/to/project` on the host to `/src/project` in the container named `mydevhost-fedora`, using the user `dev` and SSH port 2222. It will continue to watch for changes and sync automatically. + +Note: +- The script syncs files one-way: from the host to the container. +- The `-c` or `--container` option is required. +- By default, it watches for changes and syncs continuously. Use the `-o` or `--once` option for a single sync. +- Make sure you have `rsync` installed on your host, and `watchexec` if you want to use the watch feature. + +## Notes + +- The scripts assume they are located in a 'dev' subdirectory of the source root. +- The entire source root will be copied to /src/ in the container. +- SSH public keys from $HOME/.ssh/*.pub will be copied to the container for key-based authentication. +- FUSE support is enabled in the containers, allowing for advanced filesystem operations. + +## Troubleshooting + +If you encounter issues with FUSE support, ensure that FUSE is properly installed and loaded on your host system. You may need to run `sudo modprobe fuse` on the host system. + +For any other issues or questions, please open an issue in the repository. diff --git a/dev/container-build.sh b/dev/container-build.sh new file mode 100755 index 0000000..43e5802 --- /dev/null +++ b/dev/container-build.sh @@ -0,0 +1,142 @@ +#!/bin/bash + +# This script 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 script 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 script. If not, see . + +set -e + +# Function to display supported distributions +show_supported_distros() { + echo "Supported distributions:" + echo " - debian" + echo " - ubuntu" + echo " - fedora" + echo " - archlinux" + echo " - opensuse/tumbleweed" + echo " - opensuse/leap" +} + +# Function to display help +show_help() { + echo "Usage: $0 [OPTIONS]" + echo "Build a container with development tools and compile the project." + echo + echo "Options:" + echo " -i, --image IMAGE Specify the base image (default: debian)" + echo " -t, --tag TAG Specify the tag for the base image (default: latest)" + echo " -n, --name NAME Specify the name for the container (default: debian-build)" + echo " -l, --list List supported distributions" + echo " -h, --help Display this help message" + echo + echo "Examples:" + echo " $0 -i ubuntu -t 20.04 -n ubuntu-build" + echo " $0 --image debian --tag buster --name debian-buster-build" + echo " $0 --image fedora --tag 34 --name fedora-build" + echo " $0 --image archlinux --tag latest --name arch-build" + echo " $0 --image opensuse/tumbleweed --tag latest --name opensuse-build" + echo " $0 --image opensuse/leap --tag 15.3 --name opensuse-leap-build" + echo + echo "Use -l or --list to see supported distributions" +} + +# Default values +IMAGE="debian" +TAG="latest" +NAME="debian-build" + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -i|--image) + IMAGE="$2" + shift 2 + ;; + -t|--tag) + TAG="$2" + shift 2 + ;; + -n|--name) + NAME="$2" + shift 2 + ;; + -l|--list) + show_supported_distros + exit 0 + ;; + -h|--help) + show_help + exit 0 + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +FULL_IMAGE="${IMAGE}:${TAG}" +echo "Building $NAME container from $FULL_IMAGE..." + +case $IMAGE in + debian|ubuntu) + echo "Setting up Debian/Ubuntu-based container..." + ctrid=$(buildah from "$FULL_IMAGE") + buildah run "$ctrid" -- apt update + buildah run "$ctrid" -- apt install -y build-essential git libfuse-dev libudev-dev libsqlite3-dev libmbedtls-dev zlib1g-dev libboost-system-dev libboost-program-options-dev fuse llvm gdb + ;; + fedora) + echo "Setting up Fedora-based container..." + ctrid=$(buildah from "$FULL_IMAGE") + buildah run "$ctrid" -- dnf update -y + buildah run "$ctrid" -- dnf group install -y "C Development Tools and Libraries" + buildah run "$ctrid" -- dnf install -y git fuse-devel systemd-devel sqlite-devel mbedtls-devel zlib-devel boost-devel boost-program-options fuse llvm gdb fuse udev libasan + ;; + archlinux|arch) + echo "Setting up Arch Linux-based container..." + ctrid=$(buildah from "$FULL_IMAGE") + buildah run "$ctrid" -- pacman -Syu --noconfirm + buildah run "$ctrid" -- pacman -S --noconfirm base-devel git fuse2 systemd sqlite mbedtls2 zlib boost boost-libs llvm gdb udev gcc make + ;; + opensuse/tumbleweed|opensuse/leap) + echo "Setting up openSUSE-based container..." + ctrid=$(buildah from "$FULL_IMAGE") + buildah run "$ctrid" -- zypper refresh + buildah run "$ctrid" -- zypper install -y gcc gcc-c++ make git fuse-devel systemd-devel sqlite3-devel zlib-devel libboost_system-devel libboost_program_options-devel fuse llvm gdb udev mbedtls-2-devel + ;; + *) + echo "Unsupported image: $IMAGE" + echo "Use -l or --list to see supported distributions" + show_help + exit 1 + ;; +esac + +echo "Creating /src directory in the container..." +buildah run "$ctrid" -- mkdir -p /src + +echo "Committing changes to the container..." +ctrid=$(buildah commit "$ctrid" "$USER/${IMAGE}-build:$TAG") + +# Assuming this script is in ./dev subdirectory of the source root +SOURCE_ROOT=$(dirname "$(dirname "$(readlink -f "$0")")") +SOURCE_DIR_NAME=$(basename "$SOURCE_ROOT") + +echo "Building the project inside the container..." +if [[ $IMAGE == opensuse/* ]]; then + podman run --rm -v "$SOURCE_ROOT:/src" "$USER/${IMAGE}-build:$TAG" /bin/bash -c "cd /src && CFLAGS='-I/usr/include/mbedtls-2' LDFLAGS='-L/usr/lib64 -lmbedtls-2 -lmbedx509-2 -lmbedcrypto-2' make" +else + podman run --rm -v "$SOURCE_ROOT:/src" "$USER/${IMAGE}-build:$TAG" /bin/bash -c "cd /src && make" +fi + +echo "Build complete. The binary should now be in your source root directory." diff --git a/dev/devhost-debian.sh b/dev/devhost-debian.sh new file mode 100755 index 0000000..c3121f1 --- /dev/null +++ b/dev/devhost-debian.sh @@ -0,0 +1,223 @@ +#!/bin/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 . + +# 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/ 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 + + # 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 pubkey in "$HOME"/.ssh/*.pub; do + if [ -f "$pubkey" ]; then + 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" diff --git a/dev/devhost-fedora.sh b/dev/devhost-fedora.sh new file mode 100755 index 0000000..3278da7 --- /dev/null +++ b/dev/devhost-fedora.sh @@ -0,0 +1,206 @@ +#!/bin/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 . + +# This script builds a development host based on Fedora. + +set -e + +HOST_USER="$USER" +CONTAINER_NAME="devhost-fedora-${HOST_USER}" +IMAGE="fedora:latest" +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 Fedora 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-fedora-${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 " -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/ 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 Fedora 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" dnf update -y + podman exec "$CONTAINER_NAME" dnf install -y \ + sudo vim nano curl wget git htop tmux man-db \ + bash-completion ca-certificates openssh-server \ + gcc gcc-c++ make fuse-devel systemd-devel sqlite-devel \ + mbedtls-devel zlib-devel boost-devel fuse llvm gdb iproute \ + rsync + + # 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" useradd -m -s /bin/bash "$USERNAME" + podman exec "$CONTAINER_NAME" bash -c "echo $USERNAME:$USER_PASSWORD | chpasswd" + podman exec "$CONTAINER_NAME" usermod -aG wheel "$USERNAME" + + podman exec "$CONTAINER_NAME" bash -c 'echo "%wheel ALL=(ALL) ALL" > /etc/sudoers.d/wheel-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/lib64/" >> /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 pubkey in "$HOME"/.ssh/*.pub; do + if [ -f "$pubkey" ]; then + 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" ssh-keygen -A + 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" /usr/sbin/sshd + + # mop up + podman exec "$CONTAINER_NAME" dnf clean all + + echo "Fedora 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/lib64/ 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 + ;; + -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" diff --git a/dev/sync.sh b/dev/sync.sh new file mode 100755 index 0000000..7707aef --- /dev/null +++ b/dev/sync.sh @@ -0,0 +1,147 @@ +#!/bin/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 . + + +# This script syncs the source tree in the devhost with the local +# source tree. + +set -e + +SOURCE_DIR="$(pwd)" +CONTAINER_USER="dev" +DEST_DIR="/src/$(basename "$SOURCE_DIR")" +SSH_PORT="2222" + +get_container_ip() { + podman exec "$CONTAINER_NAME" bash -c "ip -4 addr show | grep -v '127.0.0.1' | grep 'inet ' | grep 'scope global' | head -n 1 | awk '{print \$2}' | cut -d/ -f1" +} + +check_ssh_connection() { + local container_ip=$1 + ssh-keyscan -p "$SSH_PORT" "$container_ip" > /dev/null 2>&1 || { + echo "Error: Unable to establish SSH connection to $container_ip:$SSH_PORT" + exit 1 + } +} + +sync_files() { + local container_ip=$(get_container_ip) + if [ -z "$container_ip" ]; then + echo "Error: Unable to get container IP address. Is the container running?" + exit 1 + fi + + check_ssh_connection "$container_ip" + + echo "Syncing files to $CONTAINER_NAME ($container_ip)..." + rsync -avz --delete \ + -e "ssh -p $SSH_PORT -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=5" \ + --exclude '.git' \ + --exclude 'target' \ + --exclude '*.tmp' \ + --exclude '*.o' \ + --exclude 'pcloudcc' \ + --exclude '*.log' \ + --exclude '.cache' \ + "$SOURCE_DIR/" \ + "${CONTAINER_USER}@${container_ip}:${DEST_DIR}/" || { + echo "Error: rsync failed. Exiting." + exit 1 + } + + echo "Sync completed at $(date)" +} + +show_help() { + echo "Usage: $0 [OPTIONS] -c CONTAINER_NAME" + echo "Sync files to a devhost container using rsync and watchexec." + echo + echo "Options:" + echo " -c, --container CONTAINER_NAME Specify the devhost container name (required)" + echo " -s, --source DIR Specify the source directory (default: current directory)" + echo " -d, --dest DIR Specify the destination directory in the container" + echo " -u, --user USER Specify the user in the container (default: dev)" + echo " -p, --port PORT Specify the SSH port (default: 2222)" + echo " -o, --once Sync files once and exit" + echo " -w, --watch Watch for changes and sync continuously (default)" + echo " -h, --help Display this help message" +} + +WATCH=true +while [[ $# -gt 0 ]]; do + case $1 in + -c|--container) + CONTAINER_NAME="$2" + shift 2 + ;; + -s|--source) + SOURCE_DIR="$2" + shift 2 + ;; + -d|--dest) + DEST_DIR="$2" + shift 2 + ;; + -u|--user) + CONTAINER_USER="$2" + shift 2 + ;; + -p|--port) + SSH_PORT="$2" + shift 2 + ;; + -o|--once) + WATCH=false + shift + ;; + -w|--watch) + WATCH=true + shift + ;; + -h|--help) + show_help + exit 0 + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +if [ -z "$CONTAINER_NAME" ]; then + echo "Error: Devhost container name is required. Use -c or --container to specify it." + show_help + exit 1 +fi + +if ! command -v watchexec &> /dev/null && [ "$WATCH" = true ]; then + echo "Error: watchexec is not installed. Please install it to use the watch feature." + echo "You can install it using: cargo install watchexec-cli" + exit 1 +fi + +if ! command -v rsync &> /dev/null; then + echo "Error: rsync is not installed. Please install it to use this script." + exit 1 +fi + +if [ "$WATCH" = true ]; then + echo "Watching for changes in $SOURCE_DIR" + watchexec -w "$SOURCE_DIR" --on-busy-update=restart -- "$0" --once -c "$CONTAINER_NAME" -s "$SOURCE_DIR" -d "$DEST_DIR" -u "$CONTAINER_USER" -p "$SSH_PORT" +else + sync_files +fi