From a5fa004c21fb98982770d8133d879a77ab3c3244 Mon Sep 17 00:00:00 2001 From: Max Mielchen <94404446+maxmielchen@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:36:52 +0000 Subject: [PATCH 01/10] fix readme bug --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed32eac..ed85c2f 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ docker pull ghcr.io/maxmielchen/sailbox:latest && docker image tag ghcr.io/maxmi Pull from main ```Bash -docker pull ghcr.io/maxmielchen/sailbox:latest && docker image tag ghcr.io/maxmielchen/sailbox:main sailbox:latest +docker pull ghcr.io/maxmielchen/sailbox:main && docker image tag ghcr.io/maxmielchen/sailbox:main sailbox:latest ``` Run instance From ab3d1596eab63412c083a0f90cfaf2eb7cc0e177 Mon Sep 17 00:00:00 2001 From: Max Mielchen <94404446+maxmielchen@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:37:09 +0000 Subject: [PATCH 02/10] simplify dockerrize --- .github/workflows/docker-publish.yml | 40 ---------------------------- 1 file changed, 40 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 5d10cd4..65a5027 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,22 +1,14 @@ name: Docker -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - on: push: branches: [ "main" ] - # Publish semver tags as releases. tags: [ 'v*.*.*' ] pull_request: branches: [ "main" ] env: - # Use docker.io for Docker Hub if empty REGISTRY: ghcr.io - # github.repository as / IMAGE_NAME: ${{ github.repository }} @@ -27,29 +19,15 @@ jobs: permissions: contents: read packages: write - # This is used to complete the identity challenge - # with sigstore/fulcio when running outside of PRs. id-token: write steps: - name: Checkout repository uses: actions/checkout@v3 - # Install the cosign tool except on PR - # https://github.com/sigstore/cosign-installer - - name: Install cosign - if: github.event_name != 'pull_request' - uses: sigstore/cosign-installer@f3c664df7af409cb4873aa5068053ba9d61a57b6 #v2.6.0 - with: - cosign-release: 'v1.13.1' - - - # Workaround: https://github.com/docker/build-push-action/issues/461 - name: Setup Docker buildx uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf - # Login against a Docker registry except on PR - # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} if: github.event_name != 'pull_request' uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c @@ -58,16 +36,12 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # Extract metadata (tags, labels) for Docker - # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - # Build and push Docker image with Buildx (don't push on PR) - # https://github.com/docker/build-push-action - name: Build and push Docker image id: build-and-push uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a @@ -78,17 +52,3 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - - - # Sign the resulting Docker image digest except on PRs. - # This will only write to the public Rekor transparency log when the Docker - # repository is public to avoid leaking data. If you would like to publish - # transparency data even for private images, pass --force to cosign below. - # https://github.com/sigstore/cosign - - name: Sign the published Docker image - if: ${{ github.event_name != 'pull_request' }} - env: - COSIGN_EXPERIMENTAL: "true" - # This step uses the identity token to provision an ephemeral certificate - # against the sigstore community Fulcio instance. - run: echo "${{ steps.meta.outputs.tags }}" | xargs -I {} cosign sign {}@${{ steps.build-and-push.outputs.digest }} From a7ff26371f190601afd2735d7bb927f2ecb20904 Mon Sep 17 00:00:00 2001 From: Max Mielchen <94404446+maxmielchen@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:46:47 +0000 Subject: [PATCH 03/10] implement sail-bash --- sail-bash/README.md | 9 +++++++ sail-bash/cli/action.sh | 19 +++++++++++++++ sail-bash/cli/dsl.sh | 22 +++++++++++++++++ sail-bash/lib/helpers.sh | 5 ++++ sail-bash/lib/user_create.sh | 47 ++++++++++++++++++++++++++++++++++++ sail-bash/lib/user_delete.sh | 22 +++++++++++++++++ sail-bash/lib/users.sh | 7 ++++++ sail-bash/sail-bash.sh | 18 ++++++++++++++ 8 files changed, 149 insertions(+) create mode 100644 sail-bash/README.md create mode 100644 sail-bash/cli/action.sh create mode 100644 sail-bash/cli/dsl.sh create mode 100644 sail-bash/lib/helpers.sh create mode 100644 sail-bash/lib/user_create.sh create mode 100644 sail-bash/lib/user_delete.sh create mode 100644 sail-bash/lib/users.sh create mode 100644 sail-bash/sail-bash.sh diff --git a/sail-bash/README.md b/sail-bash/README.md new file mode 100644 index 0000000..cdd277a --- /dev/null +++ b/sail-bash/README.md @@ -0,0 +1,9 @@ +# sail-bash + +Alternative zu `sail` komplett in Bash. Bietet die gleichen CLI-Kommandos für User-Management (create/delete, root/sudo). + +## Nutzung +```bash +./sail-bash.sh user create --username USER --password PASS [-r] [-s] +./sail-bash.sh user delete --username USER +``` diff --git a/sail-bash/cli/action.sh b/sail-bash/cli/action.sh new file mode 100644 index 0000000..55a492d --- /dev/null +++ b/sail-bash/cli/action.sh @@ -0,0 +1,19 @@ +# cli/action.sh +# Aktionen für user create/delete +. "$(dirname "$0")/../lib/users.sh" + +parse_user() { + case $1 in + create) + shift + user_create "$@" + ;; + delete) + shift + user_delete "$@" + ;; + *) + show_help + ;; + esac +} diff --git a/sail-bash/cli/dsl.sh b/sail-bash/cli/dsl.sh new file mode 100644 index 0000000..97cdd6e --- /dev/null +++ b/sail-bash/cli/dsl.sh @@ -0,0 +1,22 @@ +# cli/dsl.sh +# CLI-Argumente parsen und weiterreichen + +parse_cli() { + local args=("$@") + if [ ${#args[@]} -lt 1 ]; then + show_help + exit 1 + fi + case ${args[0]} in + user) + shift + parse_user "$@" + ;; + help|--help|-h) + show_help + ;; + *) + show_help + ;; + esac +} diff --git a/sail-bash/lib/helpers.sh b/sail-bash/lib/helpers.sh new file mode 100644 index 0000000..21c6688 --- /dev/null +++ b/sail-bash/lib/helpers.sh @@ -0,0 +1,5 @@ +# lib/helpers.sh + +user_exists() { + id -u "$1" >/dev/null 2>&1 +} diff --git a/sail-bash/lib/user_create.sh b/sail-bash/lib/user_create.sh new file mode 100644 index 0000000..9f7fec0 --- /dev/null +++ b/sail-bash/lib/user_create.sh @@ -0,0 +1,47 @@ +# lib/user_create.sh +. "$(dirname "$0")/helpers.sh" + +user_create() { + # ...Argumente parsen wie gehabt... + USERNAME="" + PASSWORD="" + ROOT=0 + SUDO=0 + while [[ $# -gt 0 ]]; do + case $1 in + --username) + USERNAME="$2"; shift 2;; + --password) + PASSWORD="$2"; shift 2;; + -r) + ROOT=1; shift;; + -s) + SUDO=1; shift;; + *) + shift;; + esac + done + if [ -z "$USERNAME" ]; then + read -p "Username: " USERNAME + fi + user_exists "$USERNAME" && { echo "User already exist!"; exit 1; } + if [ -z "$PASSWORD" ]; then + read -s -p "Password: " PASSWORD; echo + fi + sudo adduser --disabled-password --gecos "" "$USERNAME" + if [ $? -ne 0 ]; then echo "Could not create user!"; exit 1; fi + echo "$USERNAME:$PASSWORD" | sudo chpasswd + if [ $? -ne 0 ]; then sudo deluser --remove-home "$USERNAME"; echo "Could not set password!"; exit 1; fi + echo "AllowUsers $USERNAME" | sudo tee -a /etc/ssh/sshd_config > /dev/null + sudo mkdir -p "/home/$USERNAME/projects" + sudo chown -R "$USERNAME" "/home/$USERNAME" + sudo usermod -aG docker "$USERNAME" + if [ $ROOT -eq 1 ]; then + sudo usermod -G root "$USERNAME" && echo "Successfully rooting user!" || echo "Could not root" + fi + if [ $SUDO -eq 1 ]; then + sudo usermod -aG sudo "$USERNAME" && echo "Successfully give user sudo access!" || echo "Could not give sudo rights" + fi + echo "Successfully create user!" + echo "Please reboot die Sailbox, um den User komplett zu initialisieren!" +} diff --git a/sail-bash/lib/user_delete.sh b/sail-bash/lib/user_delete.sh new file mode 100644 index 0000000..6700526 --- /dev/null +++ b/sail-bash/lib/user_delete.sh @@ -0,0 +1,22 @@ +# lib/user_delete.sh +. "$(dirname "$0")/helpers.sh" + +user_delete() { + USERNAME="" + while [[ $# -gt 0 ]]; do + case $1 in + --username) + USERNAME="$2"; shift 2;; + *) + shift;; + esac + done + if [ -z "$USERNAME" ]; then + read -p "Username: " USERNAME + fi + user_exists "$USERNAME" || { echo "User does not exist!"; exit 1; } + sudo deluser --remove-home "$USERNAME" + sudo sed -i "/^AllowUsers $USERNAME/d" /etc/ssh/sshd_config + echo "Successfully delete user!" + echo "Please reboot die Sailbox, um den User komplett zu entfernen!" +} diff --git a/sail-bash/lib/users.sh b/sail-bash/lib/users.sh new file mode 100644 index 0000000..ac606c2 --- /dev/null +++ b/sail-bash/lib/users.sh @@ -0,0 +1,7 @@ +# lib/users.sh +. "$(dirname "$0")/user_create.sh" +. "$(dirname "$0")/user_delete.sh" +. "$(dirname "$0")/helpers.sh" + +# Fassade für Kompatibilität +# user_create und user_delete werden direkt importiert diff --git a/sail-bash/sail-bash.sh b/sail-bash/sail-bash.sh new file mode 100644 index 0000000..722e674 --- /dev/null +++ b/sail-bash/sail-bash.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# sail-bash: Alternative zu sail in Bash + +# Module einbinden +. "$(dirname "$0")/cli/dsl.sh" +. "$(dirname "$0")/cli/action.sh" +. "$(dirname "$0")/lib/users.sh" + +show_help() { + echo "sail-bash user create [--username USER] [--password PASS] [-r] [-s]" + echo "sail-bash user delete [--username USER]" +} + +main() { + parse_cli "$@" +} + +main "$@" From c2a42abcd706a43c4e9d38f0024a4a6e31990ae6 Mon Sep 17 00:00:00 2001 From: Max Mielchen <94404446+maxmielchen@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:49:56 +0000 Subject: [PATCH 04/10] Refactor script imports to use absolute paths for better reliability --- sail-bash/cli/action.sh | 1 - sail-bash/lib/user_create.sh | 3 ++- sail-bash/lib/user_delete.sh | 3 ++- sail-bash/lib/users.sh | 7 ++++--- sail-bash/sail-bash.sh | 8 +++++--- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/sail-bash/cli/action.sh b/sail-bash/cli/action.sh index 55a492d..9c5f36e 100644 --- a/sail-bash/cli/action.sh +++ b/sail-bash/cli/action.sh @@ -1,6 +1,5 @@ # cli/action.sh # Aktionen für user create/delete -. "$(dirname "$0")/../lib/users.sh" parse_user() { case $1 in diff --git a/sail-bash/lib/user_create.sh b/sail-bash/lib/user_create.sh index 9f7fec0..4e84310 100644 --- a/sail-bash/lib/user_create.sh +++ b/sail-bash/lib/user_create.sh @@ -1,5 +1,6 @@ # lib/user_create.sh -. "$(dirname "$0")/helpers.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +. "$SCRIPT_DIR/helpers.sh" user_create() { # ...Argumente parsen wie gehabt... diff --git a/sail-bash/lib/user_delete.sh b/sail-bash/lib/user_delete.sh index 6700526..5a3006d 100644 --- a/sail-bash/lib/user_delete.sh +++ b/sail-bash/lib/user_delete.sh @@ -1,5 +1,6 @@ # lib/user_delete.sh -. "$(dirname "$0")/helpers.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +. "$SCRIPT_DIR/helpers.sh" user_delete() { USERNAME="" diff --git a/sail-bash/lib/users.sh b/sail-bash/lib/users.sh index ac606c2..ac61550 100644 --- a/sail-bash/lib/users.sh +++ b/sail-bash/lib/users.sh @@ -1,7 +1,8 @@ # lib/users.sh -. "$(dirname "$0")/user_create.sh" -. "$(dirname "$0")/user_delete.sh" -. "$(dirname "$0")/helpers.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +. "$SCRIPT_DIR/user_create.sh" +. "$SCRIPT_DIR/user_delete.sh" +. "$SCRIPT_DIR/helpers.sh" # Fassade für Kompatibilität # user_create und user_delete werden direkt importiert diff --git a/sail-bash/sail-bash.sh b/sail-bash/sail-bash.sh index 722e674..3bd1caf 100644 --- a/sail-bash/sail-bash.sh +++ b/sail-bash/sail-bash.sh @@ -1,10 +1,12 @@ #!/bin/bash # sail-bash: Alternative zu sail in Bash +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + # Module einbinden -. "$(dirname "$0")/cli/dsl.sh" -. "$(dirname "$0")/cli/action.sh" -. "$(dirname "$0")/lib/users.sh" +. "$SCRIPT_DIR/cli/dsl.sh" +. "$SCRIPT_DIR/cli/action.sh" +. "$SCRIPT_DIR/lib/users.sh" show_help() { echo "sail-bash user create [--username USER] [--password PASS] [-r] [-s]" From aa82965d84c710b72e6c799617962c2a3fe47ea8 Mon Sep 17 00:00:00 2001 From: Max Mielchen <94404446+maxmielchen@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:54:56 +0000 Subject: [PATCH 05/10] Add user management functions and improve messaging in sail-bash scripts --- sail-bash.sh | 4 ++++ sail-bash/README.md | 4 ++-- sail-bash/lib/user_create.sh | 8 ++++---- sail-bash/lib/user_delete.sh | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 sail-bash.sh diff --git a/sail-bash.sh b/sail-bash.sh new file mode 100644 index 0000000..0e21cb8 --- /dev/null +++ b/sail-bash.sh @@ -0,0 +1,4 @@ +show_help() { + echo "sail-bash user create [--username USER] [--password PASS] [-r] [-s]" + echo "sail-bash user delete [--username USER]" +} \ No newline at end of file diff --git a/sail-bash/README.md b/sail-bash/README.md index cdd277a..396ac5b 100644 --- a/sail-bash/README.md +++ b/sail-bash/README.md @@ -1,8 +1,8 @@ # sail-bash -Alternative zu `sail` komplett in Bash. Bietet die gleichen CLI-Kommandos für User-Management (create/delete, root/sudo). +Alternative to `sail` completely in Bash. Provides the same CLI commands for user management (create/delete, root/sudo). -## Nutzung +## Usage ```bash ./sail-bash.sh user create --username USER --password PASS [-r] [-s] ./sail-bash.sh user delete --username USER diff --git a/sail-bash/lib/user_create.sh b/sail-bash/lib/user_create.sh index 4e84310..1fd436d 100644 --- a/sail-bash/lib/user_create.sh +++ b/sail-bash/lib/user_create.sh @@ -38,11 +38,11 @@ user_create() { sudo chown -R "$USERNAME" "/home/$USERNAME" sudo usermod -aG docker "$USERNAME" if [ $ROOT -eq 1 ]; then - sudo usermod -G root "$USERNAME" && echo "Successfully rooting user!" || echo "Could not root" + sudo usermod -G root "$USERNAME" && echo "Successfully added user to root group!" || echo "Could not add to root group." fi if [ $SUDO -eq 1 ]; then - sudo usermod -aG sudo "$USERNAME" && echo "Successfully give user sudo access!" || echo "Could not give sudo rights" + sudo usermod -aG sudo "$USERNAME" && echo "Successfully granted sudo access!" || echo "Could not grant sudo rights." fi - echo "Successfully create user!" - echo "Please reboot die Sailbox, um den User komplett zu initialisieren!" + echo "User created successfully!" + echo "Please reboot the Sailbox to fully initialize the user!" } diff --git a/sail-bash/lib/user_delete.sh b/sail-bash/lib/user_delete.sh index 5a3006d..40870da 100644 --- a/sail-bash/lib/user_delete.sh +++ b/sail-bash/lib/user_delete.sh @@ -18,6 +18,6 @@ user_delete() { user_exists "$USERNAME" || { echo "User does not exist!"; exit 1; } sudo deluser --remove-home "$USERNAME" sudo sed -i "/^AllowUsers $USERNAME/d" /etc/ssh/sshd_config - echo "Successfully delete user!" - echo "Please reboot die Sailbox, um den User komplett zu entfernen!" + echo "User deleted successfully!" + echo "Please reboot the Sailbox to fully remove the user!" } From a99bbf79bd249b1ac115df1640d78a680932481b Mon Sep 17 00:00:00 2001 From: Max Mielchen <94404446+maxmielchen@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:59:48 +0000 Subject: [PATCH 06/10] better docs --- sail-bash/README.md | 38 +++++++++++++++++++++++++++++-- sail-bash/cli/dsl.sh | 19 ++++++++++++++++ sail-bash/lib/helpers.sh | 43 ++++++++++++++++++++++++++++++++++++ sail-bash/lib/user_create.sh | 24 +++++++++----------- sail-bash/lib/user_delete.sh | 6 ++--- 5 files changed, 112 insertions(+), 18 deletions(-) diff --git a/sail-bash/README.md b/sail-bash/README.md index 396ac5b..b745988 100644 --- a/sail-bash/README.md +++ b/sail-bash/README.md @@ -3,7 +3,41 @@ Alternative to `sail` completely in Bash. Provides the same CLI commands for user management (create/delete, root/sudo). ## Usage + ```bash -./sail-bash.sh user create --username USER --password PASS [-r] [-s] -./sail-bash.sh user delete --username USER +./sail-bash.sh user create [--username USER] [--password PASS] [-r] [-s] +./sail-bash.sh user delete [--username USER] +./sail-bash.sh help ``` + +### Commands and Parameters + +- `user create` + Create a new user with the following options: + - `--username USER` : The username for the new user. If omitted, you will be prompted interactively. + - `--password PASS` : The password for the new user. If omitted, you will be prompted interactively (input is hidden). + - `-r` : Add the user to the `root` group (root privileges). + - `-s` : Add the user to the `sudo` group (sudo privileges). + +- `user delete` + Delete an existing user: + - `--username USER` : The username to delete. If omitted, you will be prompted interactively. + +- `help` or `--help` or `-h` + Show this help message with all available commands and options. + +### What happens when you create a user? +- The user is created on the system. +- The password is set. +- The user is added to the SSH AllowUsers list. +- A project directory is created at `/home/USER/projects`. +- The user is added to the `docker` group (Docker access). +- Optionally, the user is added to the `root` and/or `sudo` group if specified. + +### What happens when you delete a user? +- The user is removed from the system (including home directory). +- The user is removed from the SSH AllowUsers list. + +--- + +**Note:** After creating or deleting a user, you should reboot the Sailbox to fully apply the changes. diff --git a/sail-bash/cli/dsl.sh b/sail-bash/cli/dsl.sh index 97cdd6e..28d7f2f 100644 --- a/sail-bash/cli/dsl.sh +++ b/sail-bash/cli/dsl.sh @@ -20,3 +20,22 @@ parse_cli() { ;; esac } + +show_help() { + echo "Usage:" + echo " sail-bash user create [--username USER] [--password PASS] [-r] [-s]" + echo " sail-bash user delete [--username USER]" + echo " sail-bash help" + echo + echo "Commands:" + echo " user create Create a new user." + echo " --username USER The username for the new user. If omitted, you will be prompted." + echo " --password PASS The password for the new user. If omitted, you will be prompted (input is hidden)." + echo " -r Add the user to the root group (root privileges)." + echo " -s Add the user to the sudo group (sudo privileges)." + echo " user delete Delete an existing user." + echo " --username USER The username to delete. If omitted, you will be prompted." + echo " help, --help, -h Show this help message." + echo + echo "After creating or deleting a user, reboot the Sailbox to fully apply the changes." +} diff --git a/sail-bash/lib/helpers.sh b/sail-bash/lib/helpers.sh index 21c6688..fa82b55 100644 --- a/sail-bash/lib/helpers.sh +++ b/sail-bash/lib/helpers.sh @@ -3,3 +3,46 @@ user_exists() { id -u "$1" >/dev/null 2>&1 } + +prompt_username() { + read -p "Username: " USERNAME + echo "$USERNAME" +} + +prompt_password() { + read -s -p "Password: " PASSWORD; echo + echo "$PASSWORD" +} + +add_system_user() { + sudo adduser --disabled-password --gecos "" "$1" +} + +set_user_password() { + echo "$1:$2" | sudo chpasswd +} + +add_ssh_allowuser() { + echo "AllowUsers $1" | sudo tee -a /etc/ssh/sshd_config > /dev/null +} + +create_projects_dir() { + sudo mkdir -p "/home/$1/projects" + sudo chown -R "$1" "/home/$1" +} + +add_to_group() { + sudo usermod -aG "$2" "$1" +} + +overwrite_group() { + sudo usermod -G "$2" "$1" +} + +delete_system_user() { + sudo deluser --remove-home "$1" +} + +remove_ssh_allowuser() { + sudo sed -i "/^AllowUsers $1/d" /etc/ssh/sshd_config +} diff --git a/sail-bash/lib/user_create.sh b/sail-bash/lib/user_create.sh index 1fd436d..6db6646 100644 --- a/sail-bash/lib/user_create.sh +++ b/sail-bash/lib/user_create.sh @@ -3,7 +3,6 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" . "$SCRIPT_DIR/helpers.sh" user_create() { - # ...Argumente parsen wie gehabt... USERNAME="" PASSWORD="" ROOT=0 @@ -23,25 +22,24 @@ user_create() { esac done if [ -z "$USERNAME" ]; then - read -p "Username: " USERNAME + USERNAME=$(prompt_username) fi - user_exists "$USERNAME" && { echo "User already exist!"; exit 1; } + user_exists "$USERNAME" && { echo "User already exists!"; exit 1; } if [ -z "$PASSWORD" ]; then - read -s -p "Password: " PASSWORD; echo + PASSWORD=$(prompt_password) fi - sudo adduser --disabled-password --gecos "" "$USERNAME" + add_system_user "$USERNAME" if [ $? -ne 0 ]; then echo "Could not create user!"; exit 1; fi - echo "$USERNAME:$PASSWORD" | sudo chpasswd - if [ $? -ne 0 ]; then sudo deluser --remove-home "$USERNAME"; echo "Could not set password!"; exit 1; fi - echo "AllowUsers $USERNAME" | sudo tee -a /etc/ssh/sshd_config > /dev/null - sudo mkdir -p "/home/$USERNAME/projects" - sudo chown -R "$USERNAME" "/home/$USERNAME" - sudo usermod -aG docker "$USERNAME" + set_user_password "$USERNAME" "$PASSWORD" + if [ $? -ne 0 ]; then delete_system_user "$USERNAME"; echo "Could not set password!"; exit 1; fi + add_ssh_allowuser "$USERNAME" + create_projects_dir "$USERNAME" + add_to_group "$USERNAME" "docker" if [ $ROOT -eq 1 ]; then - sudo usermod -G root "$USERNAME" && echo "Successfully added user to root group!" || echo "Could not add to root group." + overwrite_group "$USERNAME" "root" && echo "Successfully added user to root group!" || echo "Could not add to root group." fi if [ $SUDO -eq 1 ]; then - sudo usermod -aG sudo "$USERNAME" && echo "Successfully granted sudo access!" || echo "Could not grant sudo rights." + add_to_group "$USERNAME" "sudo" && echo "Successfully granted sudo access!" || echo "Could not grant sudo rights." fi echo "User created successfully!" echo "Please reboot the Sailbox to fully initialize the user!" diff --git a/sail-bash/lib/user_delete.sh b/sail-bash/lib/user_delete.sh index 40870da..6f6c0f9 100644 --- a/sail-bash/lib/user_delete.sh +++ b/sail-bash/lib/user_delete.sh @@ -13,11 +13,11 @@ user_delete() { esac done if [ -z "$USERNAME" ]; then - read -p "Username: " USERNAME + USERNAME=$(prompt_username) fi user_exists "$USERNAME" || { echo "User does not exist!"; exit 1; } - sudo deluser --remove-home "$USERNAME" - sudo sed -i "/^AllowUsers $USERNAME/d" /etc/ssh/sshd_config + delete_system_user "$USERNAME" + remove_ssh_allowuser "$USERNAME" echo "User deleted successfully!" echo "Please reboot the Sailbox to fully remove the user!" } From 68a246ac528d817e3112551d9db453f8a0a2a2bb Mon Sep 17 00:00:00 2001 From: Max Mielchen <94404446+maxmielchen@users.noreply.github.com> Date: Mon, 9 Jun 2025 13:03:49 +0000 Subject: [PATCH 07/10] remove helper funktion --- sail-bash.sh | 4 ---- sail-bash/sail-bash.sh | 0 2 files changed, 4 deletions(-) delete mode 100644 sail-bash.sh mode change 100644 => 100755 sail-bash/sail-bash.sh diff --git a/sail-bash.sh b/sail-bash.sh deleted file mode 100644 index 0e21cb8..0000000 --- a/sail-bash.sh +++ /dev/null @@ -1,4 +0,0 @@ -show_help() { - echo "sail-bash user create [--username USER] [--password PASS] [-r] [-s]" - echo "sail-bash user delete [--username USER]" -} \ No newline at end of file diff --git a/sail-bash/sail-bash.sh b/sail-bash/sail-bash.sh old mode 100644 new mode 100755 From 8ac2007bc66eef421fd14255724e3c0dfee8c35f Mon Sep 17 00:00:00 2001 From: Max Mielchen <94404446+maxmielchen@users.noreply.github.com> Date: Mon, 9 Jun 2025 13:11:33 +0000 Subject: [PATCH 08/10] remove unused --- .devcontainer/devcontainer.json | 3 +- Dockerfile | 21 +---- sail/.dockerignore | 3 - sail/.gitignore | 2 - sail/Cargo.toml | 8 -- sail/sail.iml | 12 --- sail/src/cli/action.rs | 124 ------------------------- sail/src/cli/dsl.rs | 54 ----------- sail/src/cli/mod.rs | 2 - sail/src/lib/console/mod.rs | 1 - sail/src/lib/console/native.rs | 33 ------- sail/src/lib/mod.rs | 3 - sail/src/lib/users.rs | 154 -------------------------------- sail/src/main.rs | 14 --- 14 files changed, 2 insertions(+), 432 deletions(-) delete mode 100644 sail/.dockerignore delete mode 100644 sail/.gitignore delete mode 100644 sail/Cargo.toml delete mode 100644 sail/sail.iml delete mode 100644 sail/src/cli/action.rs delete mode 100644 sail/src/cli/dsl.rs delete mode 100644 sail/src/cli/mod.rs delete mode 100644 sail/src/lib/console/mod.rs delete mode 100644 sail/src/lib/console/native.rs delete mode 100644 sail/src/lib/mod.rs delete mode 100644 sail/src/lib/users.rs delete mode 100644 sail/src/main.rs diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 49be5dd..d14c921 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,7 +2,6 @@ "name": "Ubuntu", "image": "mcr.microsoft.com/devcontainers/base:jammy", "features": { - "ghcr.io/devcontainers/features/docker-in-docker:2": {}, - "ghcr.io/devcontainers/features/rust:1": {} + "ghcr.io/devcontainers/features/docker-in-docker:2": {} } } diff --git a/Dockerfile b/Dockerfile index e922c98..bcbb56f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,6 @@ -# -- SAIL-CLI -- # -FROM rustlang/rust:nightly AS sailcli - -# Mirror source -COPY /sail /sail - -# Build source -WORKDIR /sail -RUN cargo build --release - -# Place Unix Executable -RUN cp /sail/target/release/sail /usr/local/sbin/ - - - # -- SAILBOX -- # FROM ubuntu:jammy -ENV DEBIAN_FRONTEND noninteractive +ENV DEBIAN_FRONTEND=noninteractive RUN yes | unminimize # -- Configuration -- # @@ -56,10 +41,6 @@ RUN apt install curl -y COPY entrypoint.sh / RUN chmod +x /entrypoint.sh -# Sail-CLI -COPY --from=sailcli /usr/local/sbin/sail /usr/local/sbin/ -RUN chmod +x /usr/local/sbin/sail - # -- Post -- # diff --git a/sail/.dockerignore b/sail/.dockerignore deleted file mode 100644 index dfcab5e..0000000 --- a/sail/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -Cargo.lock -target -.gitignore \ No newline at end of file diff --git a/sail/.gitignore b/sail/.gitignore deleted file mode 100644 index cb117fd..0000000 --- a/sail/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -Cargo.lock -target \ No newline at end of file diff --git a/sail/Cargo.toml b/sail/Cargo.toml deleted file mode 100644 index 447785f..0000000 --- a/sail/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "sail" -version = "1.0.0" -edition = "2021" - -[dependencies] -clap = { version = "4.2.1", features = ["derive"] } -termios = "0.3.3" diff --git a/sail/sail.iml b/sail/sail.iml deleted file mode 100644 index 2fecef3..0000000 --- a/sail/sail.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/sail/src/cli/action.rs b/sail/src/cli/action.rs deleted file mode 100644 index d59fb9d..0000000 --- a/sail/src/cli/action.rs +++ /dev/null @@ -1,124 +0,0 @@ -use crate::cli::dsl::{Cli, Tool, User}; -use crate::lib; -use crate::lib::users; - -pub fn validate(parse : &Cli) -{ - match &parse.tool - { - Some(Tool::User {user}) => { - match user - { - Some(User::Create { username, password, root, sudo}) => { - - let username_encoded; - let password_encoded; - - match &username { - None => { - username_encoded = lib::console::native::read_input("Username: ").unwrap() - } - _ => { - username_encoded = username.clone().unwrap(); - } - } - - match users::exits_user(&username_encoded) { - Ok(exist) => { - if exist - { - println!("User already exist!"); - return; - } - } - Err(e) => { - println!("{}", e); - return; - } - } - - match &password { - None => { - password_encoded = lib::console::native::read_hidden("Password: ").unwrap(); - } - _ => { - password_encoded = password.clone().unwrap(); - } - } - - match users::add_user(&username_encoded, &password_encoded) { - Ok(_) => println!("Successfully create user!"), - Err(e) => { - println!("{}", e); - return; - } - } - if *root - { - match users::root_user(&username_encoded) { - Ok(_) => println!("Successfully rooting user!"), - Err(e) => { - println!("{}", e); - return; - } - } - } - if *sudo - { - match users::sudo_user(&username_encoded) { - Ok(_) => println!("Successfully give user sudo access!"), - Err(e) => { - println!("{}", e); - return; - } - } - } - println!("Please reboot the Sailbox to initialize the user complete!") - }, - Some(User::Delete {username}) => { - - let username_encoded; - - match &username { - None => { - username_encoded = lib::console::native::read_input("Username: ").unwrap() - } - _ => { - username_encoded = username.clone().unwrap(); - } - } - - match users::exits_user(&username_encoded) { - Ok(exist) => { - if !exist - { - println!("User does not exist!"); - return; - } - } - Err(e) => { - println!("{}", e); - return; - } - } - - match users::delete_user(&username_encoded) { - Ok(_) => println!("Successfully delete user!"), - Err(e) => { - println!("{}", e); - return; - } - } - - println!("Please reboot the Sailbox to remove the user complete!") - }, - None => { - println!("Too few arguments use # sail user --help") - } - } - }, - None => { - println!("Too few arguments use # sail --help") - } - } -} \ No newline at end of file diff --git a/sail/src/cli/dsl.rs b/sail/src/cli/dsl.rs deleted file mode 100644 index b43a4f0..0000000 --- a/sail/src/cli/dsl.rs +++ /dev/null @@ -1,54 +0,0 @@ -use clap::Subcommand; -use clap::Parser; - - -/// Tool to manage a Sailbox -#[derive(Parser)] -#[command()] -pub struct Cli -{ - #[command(subcommand)] - pub tool : Option, -} - -#[derive(Subcommand)] -#[command()] -pub enum Tool -{ - User - { - #[command(subcommand)] - user : Option, - } -} - -#[derive(Subcommand)] -#[command()] -pub enum User -{ - Create - { - /// Your username - #[arg(short, long, required = false)] - username : Option, - - /// Your password - #[arg(short, long, required = false)] - password : Option, - - /// Root rights - #[arg(short, long, default_value_t = false)] - root : bool, - - /// Sudo rights - #[arg(short, long, default_value_t = false)] - sudo : bool, - }, - - Delete - { - /// Your username - #[arg(short, long, required = false)] - username : Option, - } -} \ No newline at end of file diff --git a/sail/src/cli/mod.rs b/sail/src/cli/mod.rs deleted file mode 100644 index 1fd26b4..0000000 --- a/sail/src/cli/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod dsl; -pub mod action; \ No newline at end of file diff --git a/sail/src/lib/console/mod.rs b/sail/src/lib/console/mod.rs deleted file mode 100644 index 52d7353..0000000 --- a/sail/src/lib/console/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod native; \ No newline at end of file diff --git a/sail/src/lib/console/native.rs b/sail/src/lib/console/native.rs deleted file mode 100644 index 46d3eb8..0000000 --- a/sail/src/lib/console/native.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::io::{self, Write}; -use termios::{self, Termios}; -use std::os::unix::io::AsRawFd; - -pub fn read_hidden(prompt: &str) -> io::Result { - let mut term = Termios::from_fd(io::stdin().as_raw_fd())?; - let old = term.clone(); - term.c_lflag &= !termios::ECHO; - termios::tcsetattr(io::stdin().as_raw_fd(), termios::TCSANOW, &term)?; - let mut stdout = io::stdout(); - write!(stdout, "{}", prompt)?; - stdout.flush()?; - let mut input = String::new(); - io::stdin().read_line(&mut input)?; - termios::tcsetattr(io::stdin().as_raw_fd(), termios::TCSANOW, &old)?; - println!(); - Ok(input.trim().to_string()) -} - -pub fn read_input(prompt: &str) -> io::Result { - let mut term = Termios::from_fd(io::stdin().as_raw_fd())?; - let old = term.clone(); - term.c_lflag |= termios::ECHO; - termios::tcsetattr(io::stdin().as_raw_fd(), termios::TCSANOW, &term)?; - let mut stdout = io::stdout(); - write!(stdout, "{}", prompt)?; - stdout.flush()?; - let mut input = String::new(); - io::stdin().read_line(&mut input)?; - termios::tcsetattr(io::stdin().as_raw_fd(), termios::TCSANOW, &old)?; - Ok(input.trim().to_string()) -} - diff --git a/sail/src/lib/mod.rs b/sail/src/lib/mod.rs deleted file mode 100644 index c396dd5..0000000 --- a/sail/src/lib/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod users; -pub mod console; - diff --git a/sail/src/lib/users.rs b/sail/src/lib/users.rs deleted file mode 100644 index 66f8b3e..0000000 --- a/sail/src/lib/users.rs +++ /dev/null @@ -1,154 +0,0 @@ -use std::process::{Command, Stdio}; -use std::io::Write; -use std::fs; - -pub fn exits_user(username : &String) -> Result -{ - let output = Command::new("id") - .arg("-u") - .arg(&username) - .output(); - return match &output - { - Ok(_) => { - Ok(*&output.unwrap().status.success()) - } - Err(_) => { - Err("Could not check if user exist") - } - } -} - -pub fn add_user(username : &String, password: &String) -> Result<(), &'static str> -{ - if exits_user(username).unwrap() - { - return Err("User already exist!") - } - - // Add user - match Command::new("adduser") - .arg("--disabled-password") - .arg("--gecos") - .arg("''") - .arg(&username) - .output() { - Ok(output) => output, - Err(_) => return Err("Could not create user!") - }; - - // User set password - match match Command::new("chpasswd") - .stdin(Stdio::piped()) - .stdout(Stdio::null()) - .stderr(Stdio::inherit()) - .spawn() { - Ok(output) => output, - Err(_) => { - Command::new("deluser") - .arg("--remove-home") - .arg(&username) - .output().unwrap(); - return Err("Could not create user!") - } - } - .stdin - .unwrap() - .write_all(format!("{}:{}", &username, &password).as_bytes()) { - Ok(output) => output, - Err(_) => { - Command::new("deluser") - .arg("--remove-home") - .arg(&username) - .output().unwrap(); - return Err("Could not create user!") - } - }; - - // Add user to ssh config - Command::new("sh") - .arg("-c") - .arg(format!("echo \"AllowUsers {}\" >> /etc/ssh/sshd_config", &username)) - .output().unwrap(); - - // Add project dir - fs::create_dir(format!("/home/{}/projects", &username)).unwrap(); - - // Give user using rights - Command::new("chown") - .arg("-R") - .arg("-c") - .arg(&username) - .arg(format!("/home/{}", &username)) - .output().unwrap(); - - // Give user docker rights - Command::new("usermod") - .arg("-aG") - .arg("docker") - .arg(&username) - .output().unwrap(); - - return Ok(()) -} - -pub fn root_user(username : &String) -> Result<(), &'static str> -{ - if !exits_user(username).unwrap() - { - return Err("User does not exist!") - } - - match Command::new("usermod") - .arg("-G") - .arg("root") - .arg(&username) - .output() { - Ok(output) => output, - Err(_) => return Err("Could not root") - }; - return Ok(()) -} - -pub fn sudo_user(username : &String) -> Result<(), &'static str> -{ - if !exits_user(username).unwrap() - { - return Err("User does not exist!") - } - - match Command::new("usermod") - .arg("-aG") - .arg("sudo") - .arg(&username) - .output() { - Ok(output) => output, - Err(_) => return Err("Could not give sudo rights") - }; - return Ok(()) -} - -pub fn delete_user(username : &String) -> Result<(), &'static str> -{ - if !exits_user(username).unwrap() - { - return Err("User does not exist!") - } - - match Command::new("deluser") - .arg("--remove-home") - .arg(&username) - .output() { - Ok(output) => output, - Err(_) => return Err("Could not delete") - }; - match Command::new("sed") - .arg("-i") - .arg(format!("/^AllowUsers {}/d", &username)) - .arg("/etc/ssh/sshd_config") - .output() { - Ok(output) => output, - Err(_) => return Err("Could not remove from SSH-Server") - }; - return Ok(()) -} diff --git a/sail/src/main.rs b/sail/src/main.rs deleted file mode 100644 index 17a166e..0000000 --- a/sail/src/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -mod cli; -mod lib; - -use cli::dsl::Cli; -use cli::action::validate; - -use clap::Parser; - -fn main() -{ - let cli = Cli::parse(); - - validate(&cli) -} From 8fafd7d0d98eee2facc7cf576ec207ef8e5daf60 Mon Sep 17 00:00:00 2001 From: Max Mielchen <94404446+maxmielchen@users.noreply.github.com> Date: Mon, 9 Jun 2025 13:18:19 +0000 Subject: [PATCH 09/10] =?UTF-8?q?F=C3=BCge=20Symlink=20f=C3=BCr=20sail-Bas?= =?UTF-8?q?h-Skript=20hinzu=20und=20aktualisiere=20die=20README=20mit=20er?= =?UTF-8?q?weiterten=20Anweisungen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 3 ++ README.md | 115 +++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 102 insertions(+), 16 deletions(-) diff --git a/Dockerfile b/Dockerfile index bcbb56f..cc27414 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,6 +40,9 @@ RUN apt install curl -y # Load entrypoint COPY entrypoint.sh / RUN chmod +x /entrypoint.sh +COPY sail-bash /sail-bash +RUN chmod +x /sail-bash/sail-bash.sh \ + && ln -s /sail-bash/sail-bash.sh /usr/local/bin/sail # -- Post -- # diff --git a/README.md b/README.md index ed85c2f..69455ca 100644 --- a/README.md +++ b/README.md @@ -5,31 +5,114 @@ ![sailbox](https://img.shields.io/github/actions/workflow/status/maxmielchen/sailbox/docker-publish.yml?label=sailbox%3Alatest&style=flat-square) # Sailbox -Sailbox is a Docker image that simplifies the process of setting up a remote development environment. It includes basic tools for programming and provides CRUD options for managing SSH users. With Sailbox, you can easily set up a remote environment for any IDE or IDE-less coding setup. -## Basic usage +Sailbox is a Docker image that simplifies setting up a remote development environment. It includes essential programming tools and provides CRUD options for managing SSH users. With Sailbox, you can easily set up a remote environment for any IDE or even without an IDE. -Pull latest release -```Bash -docker pull ghcr.io/maxmielchen/sailbox:latest && docker image tag ghcr.io/maxmielchen/sailbox:latest sailbox:latest -``` +--- + +## Table of Contents +- [Features](#features) +- [Quickstart (Docker CLI)](#quickstart-docker-cli) +- [Quickstart (Docker Compose)](#quickstart-docker-compose) +- [Sail CLI Commands](#sail-cli-commands) +- [Useful Commands](#useful-commands) + +--- + +## Features +- SSH server out-of-the-box +- User management (CRUD) via the `sail` Bash CLI +- Docker-in-Docker support +- Preinstalled: Git, Vim, Neovim, Nano, curl, gh + +--- + +## Quickstart (Docker CLI) -Pull from main -```Bash -docker pull ghcr.io/maxmielchen/sailbox:main && docker image tag ghcr.io/maxmielchen/sailbox:main sailbox:latest +### Pull the image +```bash +docker pull ghcr.io/maxmielchen/sailbox:latest ``` -Run instance -```Bash -docker run --name box -p 201:22 -v /var/run/docker.sock:/var/run/docker.sock -d sailbox:latest +### Start a container +```bash +docker run --name box -p 201:22 -v /var/run/docker.sock:/var/run/docker.sock -d ghcr.io/maxmielchen/sailbox:latest ``` -Add user -```Bash +### Add a user +```bash docker exec -it box sail user create --username OUR_USERNAME --password OUR_PASSWORD -r -s ``` -Restart instance -```Bash +### Restart the container +```bash docker restart box ``` + +--- + +## Quickstart (Docker Compose) + +### Example `docker-compose.yml` +```yaml +services: + sailbox: + image: ghcr.io/maxmielchen/sailbox:latest + container_name: box + ports: + - "201:22" + volumes: + - /var/run/docker.sock:/var/run/docker.sock +``` + +### Start +```bash +docker compose up -d +``` + +### Add a user +```bash +docker exec -it box sail user create --username OUR_USERNAME --password OUR_PASSWORD -r -s +``` + +--- + +## Sail CLI Commands + +With the `sail` command (a symlink to the Bash script), you can manage users: + +- **Create a user:** + ```bash + sail user create --username USER --password PASS [-r] [-s] + # -r: Create user as root + # -s: Generate SSH key + ``` +- **Delete a user:** + ```bash + sail user delete --username USER + ``` +- **Show help:** + ```bash + sail help + ``` + +--- + +## Useful Commands + +- **Show logs:** + ```bash + docker logs box + ``` +- **Stop the container:** + ```bash + docker stop box + ``` +- **Remove the container:** + ```bash + docker rm box + ``` + +--- + +For more information, see the documentation in the `sail-bash/` folder. From 038147f727c2f000532f1b2e175770117b09a3e9 Mon Sep 17 00:00:00 2001 From: Max Mielchen <94404446+maxmielchen@users.noreply.github.com> Date: Mon, 9 Jun 2025 13:38:00 +0000 Subject: [PATCH 10/10] ready --- Dockerfile | 9 ++++++--- etc/ssh/sshd_config | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index cc27414..06937ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,10 +39,13 @@ RUN apt install curl -y # Load entrypoint COPY entrypoint.sh / -RUN chmod +x /entrypoint.sh COPY sail-bash /sail-bash -RUN chmod +x /sail-bash/sail-bash.sh \ - && ln -s /sail-bash/sail-bash.sh /usr/local/bin/sail +RUN chmod +x /sail-bash/sail-bash.sh +COPY etc/ssh/sshd_config /etc/ssh/ +# Wrapper-Skript für /usr/local/bin/sail +RUN echo '#!/bin/bash\nexec /sail-bash/sail-bash.sh "$@"' > /usr/local/bin/sail \ + && chmod +x /usr/local/bin/sail +RUN chmod +x /entrypoint.sh # -- Post -- # diff --git a/etc/ssh/sshd_config b/etc/ssh/sshd_config index 72a8e58..e176f74 100644 --- a/etc/ssh/sshd_config +++ b/etc/ssh/sshd_config @@ -4,4 +4,5 @@ LogLevel INFO UsePAM yes X11Forwarding yes PrintMotd no +PasswordAuthentication yes Subsystem sftp /usr/lib/openssh/sftp-server