diff --git a/.github/workflows/ghcr.yml b/.github/workflows/ghcr.yml new file mode 100644 index 0000000..59fadbb --- /dev/null +++ b/.github/workflows/ghcr.yml @@ -0,0 +1,59 @@ +name: GHCR + +on: + push: + branches: [main] + tags: + - 'v*' + pull_request: + workflow_dispatch: + +permissions: + contents: read + packages: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to GHCR + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + tags: | + type=raw,value=latest,enable={{is_default_branch}} + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=ref,event=branch + type=sha + type=raw,value={{date 'YYYYMMDDHHmmss'}},enable=${{ github.event_name == 'workflow_dispatch' }} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + file: docker/Dockerfile + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64 + provenance: false + build-args: | + DSTACK_REV=${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/README.md b/README.md index f10333e..74c04ed 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,13 @@ docker run --rm --privileged --pid=host --net=host -v /:/host \ $NS/dstack-openssh-installer:latest ``` +**Import ssh public keys from multiple GitHub usernames:** +```bash +docker run --rm --privileged --pid=host --net=host -v /:/host \ + -e SSH_GITHUB_USER="alice,bob" \ + $NS/dstack-openssh-installer:latest +``` + **Custom port:** ```bash docker run --rm --privileged --pid=host --net=host -v /:/host \ @@ -44,7 +51,7 @@ docker run --rm --privileged --pid=host --net=host -v /:/host \ |----------|---------|-------------| | `SSH_PORT` | `22` | SSH listening port | | `SSH_PUBKEY` | - | SSH public key for root login | -| `SSH_GITHUB_USER` | - | GitHub username to import public keys from | +| `SSH_GITHUB_USER` | - | GitHub username(s) to import public keys from (comma-separated) | | `SSH_PERMIT_ROOT_LOGIN` | `prohibit-password` | Root login policy (`yes`, `no`, `prohibit-password`) | ## Usage After Installation diff --git a/docker/Dockerfile b/docker/Dockerfile index d39e2e8..3eb2be0 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,7 +10,8 @@ RUN apk add --no-cache \ openssl-libs-static \ zlib-dev \ zlib-static \ - wget + wget \ + file WORKDIR /build @@ -40,7 +41,7 @@ RUN wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${OPENSSH_ /build/install/usr/libexec/sshd-session # Verify static linking -RUN file /build/install/usr/sbin/sshd | grep -q "statically linked" && \ +RUN file /build/install/usr/sbin/sshd | grep -Eq "statically linked|static-pie linked" && \ echo "sshd is statically linked" # Final image diff --git a/scripts/install-openssh.sh b/scripts/install-openssh.sh index acc24ba..520b3ec 100644 --- a/scripts/install-openssh.sh +++ b/scripts/install-openssh.sh @@ -199,26 +199,36 @@ setup_authorized_keys() { keys_added=1 fi - # Fetch keys from GitHub user + # Fetch keys from GitHub user(s). SSH_GITHUB_USER accepts a comma-separated list. if [[ -n "${SSH_GITHUB_USER}" ]]; then - local github_url="https://github.com/${SSH_GITHUB_USER}.keys" - log_info "Fetching public keys from GitHub user: ${SSH_GITHUB_USER}..." - local fetched_keys - if fetched_keys=$(wget -qO- "${github_url}" 2>/dev/null); then - if [[ -n "${fetched_keys}" ]]; then - if [[ -n "${managed_keys}" ]]; then - managed_keys="${managed_keys}"$'\n'"${fetched_keys}" + local github_users + IFS=',' read -r -a github_users <<< "${SSH_GITHUB_USER}" + local github_user + for github_user in "${github_users[@]}"; do + github_user="${github_user//[[:space:]]/}" + if [[ -z "${github_user}" ]]; then + continue + fi + + local github_url="https://github.com/${github_user}.keys" + log_info "Fetching public keys from GitHub user: ${github_user}..." + local fetched_keys + if fetched_keys=$(wget -qO- "${github_url}" 2>/dev/null); then + if [[ -n "${fetched_keys}" ]]; then + if [[ -n "${managed_keys}" ]]; then + managed_keys="${managed_keys}"$'\n'"${fetched_keys}" + else + managed_keys="${fetched_keys}" + fi + keys_added=1 + log_success "Public keys imported from GitHub (${github_user})" else - managed_keys="${fetched_keys}" + log_warning "No keys found for GitHub user: ${github_user}" fi - keys_added=1 - log_success "Public keys imported from GitHub (${SSH_GITHUB_USER})" else - log_warning "No keys found for GitHub user: ${SSH_GITHUB_USER}" + log_error "Failed to fetch keys from GitHub for user: ${github_user}" fi - else - log_error "Failed to fetch keys from GitHub for user: ${SSH_GITHUB_USER}" - fi + done fi # Update authorized_keys file with markers @@ -304,6 +314,8 @@ AuthorizedKeysFile ${SSH_HOME_DIR}/%u/.ssh/authorized_keys PasswordAuthentication no PermitEmptyPasswords no KbdInteractiveAuthentication no +# dstack guest rootfs has / as 0777; sshd StrictModes would refuse AuthorizedKeysFile +StrictModes no # Security X11Forwarding no