diff --git a/apps/devserver/Dockerfile b/apps/devserver/Dockerfile new file mode 100644 index 0000000..051787d --- /dev/null +++ b/apps/devserver/Dockerfile @@ -0,0 +1,60 @@ +FROM docker.io/library/python:3.12-slim-bookworm + +LABEL \ + maintainer="Liana64" \ + org.opencontainers.image.source="https://github.com/RareCompute/containers" + +ARG TARGETPLATFORM +ARG VERSION +ARG CHANNEL +ARG DEBIAN_FRONTEND=noninteractive + +ENV \ + NVIDIA_DRIVER_CAPABILITIES="compute,video,utility,graphics" \ + UMASK="0002" \ + LANG=C.UTF-8 \ + TZ="Etc/UTC" \ + PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + PYTHONFAULTHANDLER=1 \ + PIP_ROOT_USER_ACTION=ignore \ + PIP_NO_CACHE_DIR=1 \ + PIP_DISABLE_PIP_VERSION_CHECK=1 \ + PIP_BREAK_SYSTEM_PACKAGES=1 \ + UV_HTTP_TIMEOUT=1000 + +ENV \ + USER_NAME=rare \ + UID=1000 \ + GID=1000 \ + SUDO_ACCESS=false \ + LISTEN_PORT=2222 \ + PUBLIC_KEY="" + +USER root +WORKDIR /config + +COPY ./apps/devserver/root/ / + +RUN \ + && apt-get update && apt-get install -y --no-install-recommends \ + curl wget unzip catatonit jq lsb-release \ + nano vim tree tmux git htop net-tools sudo strace \ + socat rsync aria2 restic iftop iotop \ + less man fzf ffmpeg ripgrep \ + openssh-server pciutils \ + && mkdir -p /var/run/sshd /config/ssh \ + && chmod 755 /var/run/sshd \ + && printf "UpdateMethod=docker\nBranch=master\nPackageVersion=%s\nPackageAuthor=[RareCompute](https://github.com/RareCompute)\n" "${VERSION}" > /config/package_info \ + && chown -R ${UID}:${GID} /config && chmod -R 755 /config \ + && chmod 755 /entrypoint.sh \ + && apt-get autoremove -y \ + && apt-get clean \ + && rm -rf /root/.cache /var/lib/apt/lists/* /tmp/* /var/tmp/* \ + && chsh -s /bin/bash + +COPY ./apps/devserver/root/config/ssh/sshd_config.template /config/ssh/sshd_config.template +RUN chmod 600 /config/ssh/sshd_config.template + +EXPOSE ${LISTEN_PORT} +ENTRYPOINT ["/usr/bin/catatonit", "--", "/entrypoint.sh"] diff --git a/apps/devserver/ci/goss.yaml b/apps/devserver/ci/goss.yaml new file mode 100644 index 0000000..ddfc75c --- /dev/null +++ b/apps/devserver/ci/goss.yaml @@ -0,0 +1,5 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/goss-org/goss/master/docs/schema.yaml +file: + /app/LICENSE: + exists: true diff --git a/apps/devserver/ci/latest.sh b/apps/devserver/ci/latest.sh new file mode 100755 index 0000000..0bdfee5 --- /dev/null +++ b/apps/devserver/ci/latest.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +version="0.0.1" +printf "%s" "${version}" diff --git a/apps/devserver/metadata.yaml b/apps/devserver/metadata.yaml new file mode 100644 index 0000000..912e482 --- /dev/null +++ b/apps/devserver/metadata.yaml @@ -0,0 +1,11 @@ +--- +#yamllint disable +app: devserver +semver: true +channels: + - name: stable + platforms: ["linux/amd64"] + stable: true + tests: + enabled: false + type: cli diff --git a/apps/devserver/root/config/ssh/sshd_config.template b/apps/devserver/root/config/ssh/sshd_config.template new file mode 100644 index 0000000..cdca81b --- /dev/null +++ b/apps/devserver/root/config/ssh/sshd_config.template @@ -0,0 +1,17 @@ +Port 22 +Protocol 2 +HostKey /config/ssh/ssh_host_rsa_key +HostKey /config/ssh/ssh_host_ed25519_key + +UsePAM yes +PermitRootLogin no +PasswordAuthentication no +PubkeyAuthentication yes +ChallengeResponseAuthentication no +ClientAliveInterval 180 +ClientAliveCountMax 2 +StrictModes yes +HostbasedAuthentication no +AllowGroups ssh +PrintMotd yes +PrintLastLog no diff --git a/apps/devserver/root/entrypoint.sh b/apps/devserver/root/entrypoint.sh new file mode 100644 index 0000000..2060360 --- /dev/null +++ b/apps/devserver/root/entrypoint.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +set -euo pipefail + +USER_HOME="/config" +AUTH_KEYS="$USER_HOME/.ssh/authorized_keys" + +echo ' +Rare Compute Devserver +───────────────────────────────────────' +echo " +Username: ${USER_NAME} +User UID: ${UID} +User GID: ${GID} +Listen Port: ${LISTEN_PORT} +───────────────────────────────────────" + +if ! getent group "${GID}" >/dev/null; then + groupadd -g "${GID}" ssh +fi + +if ! id "$USER_NAME" &> /dev/null; then + useradd -u "${UID}" -g "${GID}" -d /config -s /bin/bash -m "$USER_NAME" +fi + +if [ "${SUDO_ACCESS}" = "true" ]; then + usermod -aG sudo "$USER_NAME" + echo "$USER_NAME ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/$USER_NAME + chmod 440 /etc/sudoers.d/$USER_NAME +fi + +chown -R root:root /config/ssh +chmod 700 /config/ssh + +if [ ! -f /config/ssh/sshd_config ]; then + cp /config/ssh/sshd_config.template /config/ssh/sshd_config + chown root:root /config/ssh/sshd_config + chmod 600 /config/ssh/sshd_config +fi + +if [ ! -f /config/ssh/ssh_host_rsa_key ]; then + echo "Host keys not found, generating..." + ssh-keygen -f /config/ssh/ssh_host_rsa_key -N '' -t rsa + ssh-keygen -f /config/ssh/ssh_host_ed25519_key -N '' -t ed25519 + chmod 600 /config/ssh/ssh_host_*_key +fi + +if [ ! -d "$USER_HOME/.ssh" ]; then + mkdir -p "$USER_HOME/.ssh" + chown -R "$UID":"$GID" "$USER_HOME/.ssh" + chmod 755 "$USER_HOME" + chmod 700 "$USER_HOME/.ssh" +fi + +if [ ! -f "$AUTH_KEYS" ]; then + touch "$AUTH_KEYS" + chmod 600 "$AUTH_KEYS" + chown "$UID":"$GID" "$AUTH_KEYS" + + if [ -n "$PUBLIC_KEY" ]; then + echo "$PUBLIC_KEY" >> "$AUTH_KEYS" + fi +fi + +sed -i '/pam_motd.so/d' /etc/pam.d/sshd + +if [ -d /custom-cont-init.d ]; then + for f in /custom-cont-init.d/*; do + if [ -f "$f" ]; then + echo "Running custom init script: $f" + if [ -x "$f" ]; then + "$f" + else + bash "$f" + fi + fi + done +fi + +exec \ + /usr/sbin/sshd \ + -p "$LISTEN_PORT" \ + -f /config/ssh/sshd_config \ + -D diff --git a/apps/devserver/root/etc/motd b/apps/devserver/root/etc/motd new file mode 100644 index 0000000..ab17369 --- /dev/null +++ b/apps/devserver/root/etc/motd @@ -0,0 +1 @@ +Welcome to Rare Compute