SSH

How to Use Shell/SSH Remote Connection in VKUBE

Tool Injection

VKUBE provides a Tool Injection feature. For details, please refer to Tool Injection.

Using this feature, users can currently choose from three tools:

  • sshd: sshd (Secure Shell Daemon) is the SSH server process provided by OpenSSH, allowing remote users to securely connect to a Linux server via the SSH protocol.

  • ttyd: ttyd is a tool that maps a command-line terminal (TTY) to a webpage via WebSocket, enabling users to access the server terminal through a browser.

  • rsync: rsync (Remote Sync) is an efficient remote synchronization tool used for local and remote file synchronization, supporting incremental copying and compressed transmission.

VKUBE will perform the following configurations based on the user's selection:

  • Select sshd: VKUBE will help the user download and run sshd in a specified container. sshd can only be authenticated and encrypted using public key/private key. The public key will be written into the container's environment variables. Subsequently, the user's container will start sshd, and the user can log in to the specified container via ssh.

  • Select ttyd: VKUBE will help the user download and run ttyd in a specified container. ttyd will start a web-based program allowing users to connect to the corresponding container via a webpage. Users need to enter a username and password, and the password must meet the following criteria: at least one uppercase letter, at least one lowercase letter, at least one number, and at least one special character.

  • Select rsync: This requires sshd to be enabled first. VKUBE will help the user download and use rsync in a specified container.

Downloading and running are achieved through the execution of the following script. Note: VKUBE will make its best effort to help users download and run sshd. However, current tests show that recent versions of Ubuntu, Alpine, and Debian-based images are suitable. Other Linux distributions might not succeed. Additionally, downloading ttyd is not supported in Debian.

Image customization

Users can also start sshd themselves when creating an image. For example, using an Ubuntu base image:

RUN /bin/sh -c service ssh start # buildkit

RUN /bin/sh -c echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config # buildkit

RUN /bin/sh -c echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config # buildkit

RUN /bin/sh -c echo "PasswordAuthentication no" >> /etc/ssh/sshd_config # buildkit

RUN apt-get update \
 && apt-get install -y openssh-server \
 && cp /etc/ssh/sshd_config /etc/ssh/sshd_config-original \
 && sed -i 's/^#\s*Port.*/Port 2222/' /etc/ssh/sshd_config \
 && sed -i 's/^#\s*PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config \
 && mkdir -p /root/.ssh \
 && chmod 700 /root/.ssh \
 && mkdir /var/run/sshd \
 && chmod 755 /var/run/sshd \
 && rm -rf /var/lib/apt/lists /var/cache/apt/archives

Alternatively, you can copy our script directly into the image and execute it during the docker build process.

Script

#!/bin/sh

# Check for root privileges
if [ "$(id -u)" -ne 0 ]; then
    echo "This script must be run as root" >&2
    exit 1
fi
# Function to get the correct package name for a tool based on the package manager
get_package_name() {
    local tool="$1"
    case "$tool" in
        openssh)
            case "$PACKAGE_MANAGER" in
                apt) echo "openssh-server" ;;
                dnf|yum) echo "openssh-server" ;;
                pacman) echo "openssh" ;;
                zypper) echo "openssh" ;;
                apk) echo "openssh" ;;
                emerge) echo "net-misc/openssh" ;;
                *) echo "$tool" ;;  # Default to the original name if unrecognized
            esac
            ;;
        rsync)
            case "$PACKAGE_MANAGER" in
                apt) echo "rsync" ;;
                dnf|yum) echo "rsync" ;;
                pacman) echo "rsync" ;;
                zypper) echo "rsync" ;;
                apk) echo "rsync" ;;
                emerge) echo "net-misc/rsync" ;;
                *) echo "$tool" ;;
            esac
            ;;
        ttyd)
            echo "ttyd"
            ;;
        # Add more tools here if needed
        *)
            echo "$tool"  # Default to the original name
            ;;
    esac
}

# Function to determine the package manager, update repositories, and install the specified package
determine_package_manager() {
    # Check if /etc/os-release exists
    if [ ! -f /etc/os-release ]; then
        echo "Cannot determine the OS. /etc/os-release file not found." >&2
        exit 1
    fi

    # Source the /etc/os-release file to get OS information
    . /etc/os-release

    # Initialize variables
    PACKAGE_MANAGER=""

    # Determine package manager based on ID and ID_LIKE
    case "$ID" in
        ubuntu|debian)
            PACKAGE_MANAGER="apt"
            ;;
        fedora)
            PACKAGE_MANAGER="dnf"
            ;;
        centos|rhel)
            if command -v dnf >/dev/null 2>&1; then
                PACKAGE_MANAGER="dnf"
            else
                PACKAGE_MANAGER="yum"
            fi
            ;;
        arch)
            PACKAGE_MANAGER="pacman"
            ;;
        opensuse*|suse)
            PACKAGE_MANAGER="zypper"
            ;;
        alpine)
            PACKAGE_MANAGER="apk"
            ;;
        gentoo)
            PACKAGE_MANAGER="emerge"
            ;;
        *)
            if [ -n "$ID_LIKE" ]; then
                case "$ID_LIKE" in
                    *debian*)
                        PACKAGE_MANAGER="apt"
                        ;;
                    *rhel*|*fedora*)
                        if command -v dnf >/dev/null 2>&1; then
                            PACKAGE_MANAGER="dnf"
                        else
                            PACKAGE_MANAGER="yum"
                        fi
                        ;;
                    *arch*)
                        PACKAGE_MANAGER="pacman"
                        ;;
                    *suse*)
                        PACKAGE_MANAGER="zypper"
                        ;;
                    *alpine*)
                        PACKAGE_MANAGER="apk"
                        ;;
                    *gentoo*)
                        PACKAGE_MANAGER="emerge"
                        ;;
                    *)
                        PACKAGE_MANAGER=""
                        ;;
                esac
            fi
            ;;
    esac
}

install_package() {
    local package_name=$1
    PACKAGE_INSTALL_NAME=$(get_package_name "$package_name")
    if [ -n "$PACKAGE_MANAGER" ]; then
        echo "Installing $PACKAGE_INSTALL_NAME using $PACKAGE_MANAGER"
        case "$PACKAGE_MANAGER" in
            apt)
                apt update && apt install -y "$PACKAGE_INSTALL_NAME"
                if [ "$package_name" = "openssh" ]; then
                    mkdir -p /run/sshd
                    chmod 755 /run/sshd
                fi
                ;;
            dnf)
                dnf makecache && dnf install -y "$PACKAGE_INSTALL_NAME"
                ;;
            yum)
                yum makecache fast && yum install -y "$PACKAGE_INSTALL_NAME"
                ;;
            pacman)
                pacman -Sy --noconfirm "$PACKAGE_INSTALL_NAME"
                ;;
            zypper)
                zypper refresh && zypper install -y "$PACKAGE_INSTALL_NAME"
                ;;
            apk)
                apk update && apk add "$PACKAGE_INSTALL_NAME"
                ;;
            emerge)
                emerge --sync && emerge "$PACKAGE_INSTALL_NAME"
                ;;
            *)
                echo "Error: Unsupported package manager." >&2
                exit 1
                ;;
        esac
    else
        echo "Unsupported or unknown Linux distribution: $NAME" >&2
        exit 1
    fi
}

create_user() {
    local username="$1"
    local password="$2"

    if [ -z "$username" ]; then
        echo "Error: VKUBE_TTYD_USER is required." >&2
        return 1
    fi

    if id "$username" >/dev/null 2>&1; then
        echo "User $username already exists."

        # Check if the existing user has a password (for Alpine, check /etc/shadow)
        user_info=$(getent shadow "$username")
        if [ -n "$user_info" ] && echo "$user_info" | cut -d: -f2 | grep -q "^\*$\|^!$"; then
            if [ -z "$password" ]; then
                echo "Error: User $username does not have a password. VKUBE_TTYD_PASSWORD is required." >&2
                return 1
            fi
        fi

        # If a password is provided, update it
        if [ -n "$password" ]; then
            echo "$username:$password" | chpasswd
            echo "Password for $username has been updated."
        fi
    else
        # If the user does not exist, a password must be entered
        if [ -z "$password" ]; then
            echo "Error: User $username does not exist. VKUBE_TTYD_PASSWORD is required to create a new user." >&2
            return 1
        fi

        # Create the user (handling different distributions)
        if command -v useradd >/dev/null 2>&1; then
            useradd -m -s /bin/bash "$username"
        elif command -v adduser >/dev/null 2>&1; then
            adduser -D -s /bin/sh "$username"
        else
            echo "Error: No compatible user creation command found." >&2
            return 1
        fi

        echo "$username:$password" | chpasswd
        echo "User $username has been created with a password."
    fi
    
    # Special handling for root user in Alpine Linux: Add pts/0 to /etc/securetty
    if [ "$username" = "root" ]; then
        echo "pts/0" >> /etc/securetty
    fi
}

determine_package_manager

# Install packages based on environment variables
[ -n "$VKUBE_SSH_PUB_KEY" ] && install_package openssh
[ -n "$VKUBE_RSYNC" ] && install_package rsync
[ -n "$VKUBE_TTYD_USER" ] && install_package ttyd

# Configure SSH if SSH key is provided
if [ -n "$VKUBE_SSH_PUB_KEY" ]; then
    ssh-keygen -A
    mkdir -p /root/.ssh
    echo "$VKUBE_SSH_PUB_KEY" > /root/.ssh/authorized_keys
    chmod 600 /root/.ssh/authorized_keys

    echo "PermitRootLogin prohibit-password" >> /etc/ssh/sshd_config
    echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
    echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config

    /usr/sbin/sshd
    echo "SSHD service configured for key-based authentication only."
fi

# Configute TTYD if TTYD key is provided
if [ -n "$VKUBE_TTYD_USER" ]; then
    create_user "$VKUBE_TTYD_USER" "$VKUBE_TTYD_PASSWORD"
    /usr/bin/ttyd -W --port=27681 login > /dev/null 2>&1 < /dev/null &
fi
Last Updated: 9/9/2025, 2:24:03 AM