From 71d16e9d09cf8b319ccec9bde2e64ed9298a6d95 Mon Sep 17 00:00:00 2001 From: aptalca Date: Fri, 4 Oct 2019 15:14:09 -0400 Subject: [PATCH 1/5] Initial release --- .dockerignore | 6 + .gitattributes | 17 + .github/FUNDING.yml | 1 + .github/ISSUE_TEMPLATE.md | 21 + .github/PULL_REQUEST_TEMPLATE.md | 15 + .gitignore | 43 ++ Dockerfile | 20 + Dockerfile.aarch64 | 20 + Dockerfile.armhf | 20 + Jenkinsfile | 681 +++++++++++++++++++++++++ LICENSE | 0 README.md | 206 +++++++- jenkins-vars.yml | 27 + readme-vars.yml | 62 +++ root/etc/cont-init.d/50-config | 35 ++ root/etc/services.d/openssh-server/run | 4 + 16 files changed, 1177 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 .gitattributes create mode 100755 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Dockerfile.aarch64 create mode 100644 Dockerfile.armhf create mode 100644 Jenkinsfile mode change 100644 => 100755 LICENSE create mode 100644 jenkins-vars.yml create mode 100644 readme-vars.yml create mode 100644 root/etc/cont-init.d/50-config create mode 100644 root/etc/services.d/openssh-server/run diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cdb1a82 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.git +.gitignore +.github +.gitattributes +READMETEMPLATE.md +README.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bdb0cab --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100755 index 0000000..7972213 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +open_collective: linuxserver diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..c73c33b --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,21 @@ + + +[linuxserverurl]: https://linuxserver.io +[![linuxserver.io](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/linuxserver_medium.png)][linuxserverurl] + + + + + + + + + + + + + + + +## Thanks, team linuxserver.io + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..f6a6381 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,15 @@ + + +[linuxserverurl]: https://linuxserver.io +[![linuxserver.io](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/linuxserver_medium.png)][linuxserverurl] + + + + + + + + + +## Thanks, team linuxserver.io + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96374c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + +.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0545ed8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM lsiobase/alpine:3.10 + +# set version label +ARG BUILD_DATE +ARG VERSION +LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" +LABEL maintainer="aptalca" + +RUN \ + echo "**** install runtime packages ****" && \ + apk add --no-cache --upgrade \ + openssh-server && \ + echo "**** setup openssh environment ****" && \ + sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config && \ + ssh-keygen -A && \ + rm -rf \ + /tmp/* + +# add local files +COPY /root / \ No newline at end of file diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 new file mode 100644 index 0000000..ff11435 --- /dev/null +++ b/Dockerfile.aarch64 @@ -0,0 +1,20 @@ +FROM lsiobase/alpine:arm64v8-3.10 + +# set version label +ARG BUILD_DATE +ARG VERSION +LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" +LABEL maintainer="aptalca" + +RUN \ + echo "**** install runtime packages ****" && \ + apk add --no-cache --upgrade \ + openssh-server && \ + echo "**** setup openssh environment ****" && \ + sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config && \ + ssh-keygen -A && \ + rm -rf \ + /tmp/* + +# add local files +COPY /root / \ No newline at end of file diff --git a/Dockerfile.armhf b/Dockerfile.armhf new file mode 100644 index 0000000..db812d8 --- /dev/null +++ b/Dockerfile.armhf @@ -0,0 +1,20 @@ +FROM lsiobase/alpine:arm32v7-3.10 + +# set version label +ARG BUILD_DATE +ARG VERSION +LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" +LABEL maintainer="aptalca" + +RUN \ + echo "**** install runtime packages ****" && \ + apk add --no-cache --upgrade \ + openssh-server && \ + echo "**** setup openssh environment ****" && \ + sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config && \ + ssh-keygen -A && \ + rm -rf \ + /tmp/* + +# add local files +COPY /root / \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..55e7dd6 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,681 @@ +pipeline { + agent { + label 'X86-64-MULTI' + } + // Input to determine if this is a package check + parameters { + string(defaultValue: 'false', description: 'package check run', name: 'PACKAGE_CHECK') + } + // Configuration for the variables used for this specific repo + environment { + BUILDS_DISCORD=credentials('build_webhook_url') + GITHUB_TOKEN=credentials('498b4638-2d02-4ce5-832d-8a57d01d97ab') + CONTAINER_NAME = 'openssh-server' + BUILD_VERSION_ARG = 'OPENSSH_RELEASE' + LS_USER = 'linuxserver' + LS_REPO = 'docker-openssh-server' + DOCKERHUB_IMAGE = 'linuxserver/openssh-server' + DEV_DOCKERHUB_IMAGE = 'lsiodev/openssh-server' + PR_DOCKERHUB_IMAGE = 'lspipepr/openssh-server' + DIST_IMAGE = 'alpine' + MULTIARCH='true' + CI='true' + CI_WEB='false' + CI_PORT='80' + CI_SSL='false' + CI_DELAY='120' + CI_DOCKERENV='TZ=US/Pacific' + CI_AUTH='user:password' + CI_WEBPATH='' + } + stages { + // Setup all the basic environment variables needed for the build + stage("Set ENV Variables base"){ + steps{ + script{ + env.EXIT_STATUS = '' + env.LS_RELEASE = sh( + script: '''docker run --rm alexeiled/skopeo sh -c 'skopeo inspect docker://docker.io/'${DOCKERHUB_IMAGE}':latest 2>/dev/null' | jq -r '.Labels.build_version' | awk '{print $3}' | grep '\\-ls' || : ''', + returnStdout: true).trim() + env.LS_RELEASE_NOTES = sh( + script: '''cat readme-vars.yml | awk -F \\" '/date: "[0-9][0-9].[0-9][0-9].[0-9][0-9]:/ {print $4;exit;}' | sed -E ':a;N;$!ba;s/\\r{0,1}\\n/\\\\n/g' ''', + returnStdout: true).trim() + env.GITHUB_DATE = sh( + script: '''date '+%Y-%m-%dT%H:%M:%S%:z' ''', + returnStdout: true).trim() + env.COMMIT_SHA = sh( + script: '''git rev-parse HEAD''', + returnStdout: true).trim() + env.CODE_URL = 'https://github.com/' + env.LS_USER + '/' + env.LS_REPO + '/commit/' + env.GIT_COMMIT + env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DOCKERHUB_IMAGE + '/tags/' + env.PULL_REQUEST = env.CHANGE_ID + env.LICENSE_TAG = sh( + script: '''#!/bin/bash + if [ -e LICENSE ] ; then + cat LICENSE | md5sum | cut -c1-8 + else + echo none + fi''', + returnStdout: true).trim() + env.FUNDING_TAG = sh( + script: '''#!/bin/bash + if [ -e ./.github/FUNDING.yml ] ; then + cat ./.github/FUNDING.yml | md5sum | cut -c1-8 + else + echo none + fi''', + returnStdout: true).trim() + } + script{ + env.LS_RELEASE_NUMBER = sh( + script: '''echo ${LS_RELEASE} |sed 's/^.*-ls//g' ''', + returnStdout: true).trim() + } + script{ + env.LS_TAG_NUMBER = sh( + script: '''#! /bin/bash + tagsha=$(git rev-list -n 1 ${LS_RELEASE} 2>/dev/null) + if [ "${tagsha}" == "${COMMIT_SHA}" ]; then + echo ${LS_RELEASE_NUMBER} + elif [ -z "${GIT_COMMIT}" ]; then + echo ${LS_RELEASE_NUMBER} + else + echo $((${LS_RELEASE_NUMBER} + 1)) + fi''', + returnStdout: true).trim() + } + } + } + /* ####################### + Package Version Tagging + ####################### */ + // Grab the current package versions in Git to determine package tag + stage("Set Package tag"){ + steps{ + script{ + env.PACKAGE_TAG = sh( + script: '''#!/bin/bash + if [ -e package_versions.txt ] ; then + cat package_versions.txt | md5sum | cut -c1-8 + else + echo none + fi''', + returnStdout: true).trim() + } + } + } + /* ######################## + External Release Tagging + ######################## */ + // If this is a custom command to determine version use that command + stage("Set tag custom bash"){ + steps{ + script{ + env.EXT_RELEASE = sh( + script: ''' curl -s http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/ |awk -F '(openssh-server-|.apk)' '/openssh-server.*.apk/ {print $2; exit}' ''', + returnStdout: true).trim() + env.RELEASE_LINK = 'custom_command' + } + } + } + // Sanitize the release tag and strip illegal docker or github characters + stage("Sanitize tag"){ + steps{ + script{ + env.EXT_RELEASE_CLEAN = sh( + script: '''echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g' ''', + returnStdout: true).trim() + } + } + } + // If this is a master build use live docker endpoints + stage("Set ENV live build"){ + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + } + steps { + script{ + env.IMAGE = env.DOCKERHUB_IMAGE + if (env.MULTIARCH == 'true') { + env.CI_TAGS = 'amd64-' + env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + '|arm32v7-' + env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + '|arm64v8-' + env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + } else { + env.CI_TAGS = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + } + env.META_TAG = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + } + } + } + // If this is a dev build use dev docker endpoints + stage("Set ENV dev build"){ + when { + not {branch "master"} + environment name: 'CHANGE_ID', value: '' + } + steps { + script{ + env.IMAGE = env.DEV_DOCKERHUB_IMAGE + if (env.MULTIARCH == 'true') { + env.CI_TAGS = 'amd64-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '|arm32v7-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '|arm64v8-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + } else { + env.CI_TAGS = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + } + env.META_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DEV_DOCKERHUB_IMAGE + '/tags/' + } + } + } + // If this is a pull request build use dev docker endpoints + stage("Set ENV PR build"){ + when { + not {environment name: 'CHANGE_ID', value: ''} + } + steps { + script{ + env.IMAGE = env.PR_DOCKERHUB_IMAGE + if (env.MULTIARCH == 'true') { + env.CI_TAGS = 'amd64-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST + '|arm32v7-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST + '|arm64v8-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST + } else { + env.CI_TAGS = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST + } + env.META_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST + env.CODE_URL = 'https://github.com/' + env.LS_USER + '/' + env.LS_REPO + '/pull/' + env.PULL_REQUEST + env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.PR_DOCKERHUB_IMAGE + '/tags/' + } + } + } + // Run ShellCheck + stage('ShellCheck') { + when { + environment name: 'CI', value: 'true' + } + steps { + withCredentials([ + string(credentialsId: 'spaces-key', variable: 'DO_KEY'), + string(credentialsId: 'spaces-secret', variable: 'DO_SECRET') + ]) { + script{ + env.SHELLCHECK_URL = 'https://lsio-ci.ams3.digitaloceanspaces.com/' + env.IMAGE + '/' + env.META_TAG + '/shellcheck-result.xml' + } + sh '''curl -sL https://raw.githubusercontent.com/linuxserver/docker-shellcheck/master/checkrun.sh | /bin/bash''' + sh '''#! /bin/bash + set -e + docker pull lsiodev/spaces-file-upload:latest + docker run --rm \ + -e DESTINATION=\"${IMAGE}/${META_TAG}/shellcheck-result.xml\" \ + -e FILE_NAME="shellcheck-result.xml" \ + -e MIMETYPE="text/xml" \ + -v ${WORKSPACE}:/mnt \ + -e SECRET_KEY=\"${DO_SECRET}\" \ + -e ACCESS_KEY=\"${DO_KEY}\" \ + -t lsiodev/spaces-file-upload:latest \ + python /upload.py''' + } + } + } + // Use helper containers to render templated files + stage('Update-Templates') { + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + expression { + env.CONTAINER_NAME != null + } + } + steps { + sh '''#! /bin/bash + set -e + TEMPDIR=$(mktemp -d) + docker pull linuxserver/jenkins-builder:latest + docker run --rm -e CONTAINER_NAME=${CONTAINER_NAME} -e GITHUB_BRANCH=master -v ${TEMPDIR}:/ansible/jenkins linuxserver/jenkins-builder:latest + docker pull linuxserver/doc-builder:latest + docker run --rm -e CONTAINER_NAME=${CONTAINER_NAME} -e GITHUB_BRANCH=master -v ${TEMPDIR}:/ansible/readme linuxserver/doc-builder:latest + if [ "$(md5sum ${TEMPDIR}/${LS_REPO}/Jenkinsfile | awk '{ print $1 }')" != "$(md5sum Jenkinsfile | awk '{ print $1 }')" ] || \ + [ "$(md5sum ${TEMPDIR}/${CONTAINER_NAME}/README.md | awk '{ print $1 }')" != "$(md5sum README.md | awk '{ print $1 }')" ] || \ + [ "$(cat ${TEMPDIR}/${LS_REPO}/LICENSE | md5sum | cut -c1-8)" != "${LICENSE_TAG}" ] || \ + [ "$(cat ${TEMPDIR}/${LS_REPO}/.github/FUNDING.yml | md5sum | cut -c1-8)" != "${FUNDING_TAG}" ]; then + mkdir -p ${TEMPDIR}/repo + git clone https://github.com/${LS_USER}/${LS_REPO}.git ${TEMPDIR}/repo/${LS_REPO} + git --git-dir ${TEMPDIR}/repo/${LS_REPO}/.git checkout -f master + cp ${TEMPDIR}/${CONTAINER_NAME}/README.md ${TEMPDIR}/repo/${LS_REPO}/ + cp ${TEMPDIR}/docker-${CONTAINER_NAME}/Jenkinsfile ${TEMPDIR}/repo/${LS_REPO}/ + cp ${TEMPDIR}/docker-${CONTAINER_NAME}/LICENSE ${TEMPDIR}/repo/${LS_REPO}/ + mkdir -p ${TEMPDIR}/repo/${LS_REPO}/.github + cp ${TEMPDIR}/docker-${CONTAINER_NAME}/.github/FUNDING.yml ${TEMPDIR}/repo/${LS_REPO}/.github/FUNDING.yml + cd ${TEMPDIR}/repo/${LS_REPO}/ + git --git-dir ${TEMPDIR}/repo/${LS_REPO}/.git add Jenkinsfile README.md LICENSE ./.github/FUNDING.yml + git --git-dir ${TEMPDIR}/repo/${LS_REPO}/.git commit -m 'Bot Updating Templated Files' + git --git-dir ${TEMPDIR}/repo/${LS_REPO}/.git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git --all + echo "true" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} + else + echo "false" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} + fi + mkdir -p ${TEMPDIR}/gitbook + git clone https://github.com/linuxserver/docker-documentation.git ${TEMPDIR}/gitbook/docker-documentation + if [[ "${BRANCH_NAME}" == "master" ]] && [[ (! -f ${TEMPDIR}/gitbook/docker-documentation/images/docker-${CONTAINER_NAME}.md) || ("$(md5sum ${TEMPDIR}/gitbook/docker-documentation/images/docker-${CONTAINER_NAME}.md | awk '{ print $1 }')" != "$(md5sum ${TEMPDIR}/${CONTAINER_NAME}/docker-${CONTAINER_NAME}.md | awk '{ print $1 }')") ]]; then + cp ${TEMPDIR}/${CONTAINER_NAME}/docker-${CONTAINER_NAME}.md ${TEMPDIR}/gitbook/docker-documentation/images/ + cd ${TEMPDIR}/gitbook/docker-documentation/ + git add images/docker-${CONTAINER_NAME}.md + git commit -m 'Bot Updating Templated Files' + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/linuxserver/docker-documentation.git --all + fi + rm -Rf ${TEMPDIR}''' + script{ + env.FILES_UPDATED = sh( + script: '''cat /tmp/${COMMIT_SHA}-${BUILD_NUMBER}''', + returnStdout: true).trim() + } + } + } + // Exit the build if the Templated files were just updated + stage('Template-exit') { + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + environment name: 'FILES_UPDATED', value: 'true' + expression { + env.CONTAINER_NAME != null + } + } + steps { + script{ + env.EXIT_STATUS = 'ABORTED' + } + } + } + /* ############### + Build Container + ############### */ + // Build Docker container for push to LS Repo + stage('Build-Single') { + when { + environment name: 'MULTIARCH', value: 'false' + environment name: 'EXIT_STATUS', value: '' + } + steps { + sh "docker build --no-cache --pull -t ${IMAGE}:${META_TAG} \ + --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${META_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + } + } + // Build MultiArch Docker containers for push to LS Repo + stage('Build-Multi') { + when { + environment name: 'MULTIARCH', value: 'true' + environment name: 'EXIT_STATUS', value: '' + } + parallel { + stage('Build X86') { + steps { + sh "docker build --no-cache --pull -t ${IMAGE}:amd64-${META_TAG} \ + --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${META_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + } + } + stage('Build ARMHF') { + agent { + label 'ARMHF' + } + steps { + withCredentials([ + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', + usernameVariable: 'DOCKERUSER', + passwordVariable: 'DOCKERPASS' + ] + ]) { + echo 'Logging into DockerHub' + sh '''#! /bin/bash + echo $DOCKERPASS | docker login -u $DOCKERUSER --password-stdin + ''' + sh "docker build --no-cache --pull -f Dockerfile.armhf -t ${IMAGE}:arm32v7-${META_TAG} \ + --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${META_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + sh "docker tag ${IMAGE}:arm32v7-${META_TAG} lsiodev/buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER}" + sh "docker push lsiodev/buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER}" + sh '''docker rmi \ + ${IMAGE}:arm32v7-${META_TAG} \ + lsiodev/buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} || :''' + } + } + } + stage('Build ARM64') { + agent { + label 'ARM64' + } + steps { + withCredentials([ + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', + usernameVariable: 'DOCKERUSER', + passwordVariable: 'DOCKERPASS' + ] + ]) { + echo 'Logging into DockerHub' + sh '''#! /bin/bash + echo $DOCKERPASS | docker login -u $DOCKERUSER --password-stdin + ''' + sh "docker build --no-cache --pull -f Dockerfile.aarch64 -t ${IMAGE}:arm64v8-${META_TAG} \ + --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${META_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + sh "docker tag ${IMAGE}:arm64v8-${META_TAG} lsiodev/buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}" + sh "docker push lsiodev/buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}" + sh '''docker rmi \ + ${IMAGE}:arm64v8-${META_TAG} \ + lsiodev/buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || :''' + } + } + } + } + } + // Take the image we just built and dump package versions for comparison + stage('Update-packages') { + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + environment name: 'EXIT_STATUS', value: '' + } + steps { + sh '''#! /bin/bash + set -e + TEMPDIR=$(mktemp -d) + if [ "${MULTIARCH}" == "true" ]; then + LOCAL_CONTAINER=${IMAGE}:amd64-${META_TAG} + else + LOCAL_CONTAINER=${IMAGE}:${META_TAG} + fi + if [ "${DIST_IMAGE}" == "alpine" ]; then + docker run --rm --entrypoint '/bin/sh' -v ${TEMPDIR}:/tmp ${LOCAL_CONTAINER} -c '\ + apk info -v > /tmp/package_versions.txt && \ + sort -o /tmp/package_versions.txt /tmp/package_versions.txt && \ + chmod 777 /tmp/package_versions.txt' + elif [ "${DIST_IMAGE}" == "ubuntu" ]; then + docker run --rm --entrypoint '/bin/sh' -v ${TEMPDIR}:/tmp ${LOCAL_CONTAINER} -c '\ + apt list -qq --installed | sed "s#/.*now ##g" | cut -d" " -f1 > /tmp/package_versions.txt && \ + sort -o /tmp/package_versions.txt /tmp/package_versions.txt && \ + chmod 777 /tmp/package_versions.txt' + fi + NEW_PACKAGE_TAG=$(md5sum ${TEMPDIR}/package_versions.txt | cut -c1-8 ) + echo "Package tag sha from current packages in buit container is ${NEW_PACKAGE_TAG} comparing to old ${PACKAGE_TAG} from github" + if [ "${NEW_PACKAGE_TAG}" != "${PACKAGE_TAG}" ]; then + git clone https://github.com/${LS_USER}/${LS_REPO}.git ${TEMPDIR}/${LS_REPO} + git --git-dir ${TEMPDIR}/${LS_REPO}/.git checkout -f master + cp ${TEMPDIR}/package_versions.txt ${TEMPDIR}/${LS_REPO}/ + cd ${TEMPDIR}/${LS_REPO}/ + wait + git add package_versions.txt + git commit -m 'Bot Updating Package Versions' + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git --all + echo "true" > /tmp/packages-${COMMIT_SHA}-${BUILD_NUMBER} + echo "Package tag updated, stopping build process" + else + echo "false" > /tmp/packages-${COMMIT_SHA}-${BUILD_NUMBER} + echo "Package tag is same as previous continue with build process" + fi + rm -Rf ${TEMPDIR}''' + script{ + env.PACKAGE_UPDATED = sh( + script: '''cat /tmp/packages-${COMMIT_SHA}-${BUILD_NUMBER}''', + returnStdout: true).trim() + } + } + } + // Exit the build if the package file was just updated + stage('PACKAGE-exit') { + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + environment name: 'PACKAGE_UPDATED', value: 'true' + environment name: 'EXIT_STATUS', value: '' + } + steps { + script{ + env.EXIT_STATUS = 'ABORTED' + } + } + } + // Exit the build if this is just a package check and there are no changes to push + stage('PACKAGECHECK-exit') { + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + environment name: 'PACKAGE_UPDATED', value: 'false' + environment name: 'EXIT_STATUS', value: '' + expression { + params.PACKAGE_CHECK == 'true' + } + } + steps { + script{ + env.EXIT_STATUS = 'ABORTED' + } + } + } + /* ####### + Testing + ####### */ + // Run Container tests + stage('Test') { + when { + environment name: 'CI', value: 'true' + environment name: 'EXIT_STATUS', value: '' + } + steps { + withCredentials([ + string(credentialsId: 'spaces-key', variable: 'DO_KEY'), + string(credentialsId: 'spaces-secret', variable: 'DO_SECRET') + ]) { + script{ + env.CI_URL = 'https://lsio-ci.ams3.digitaloceanspaces.com/' + env.IMAGE + '/' + env.META_TAG + '/index.html' + } + sh '''#! /bin/bash + set -e + docker pull lsiodev/ci:latest + if [ "${MULTIARCH}" == "true" ]; then + docker pull lsiodev/buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} + docker pull lsiodev/buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} + docker tag lsiodev/buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm32v7-${META_TAG} + docker tag lsiodev/buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} + fi + docker run --rm \ + --shm-size=1gb \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -e IMAGE=\"${IMAGE}\" \ + -e DELAY_START=\"${CI_DELAY}\" \ + -e TAGS=\"${CI_TAGS}\" \ + -e META_TAG=\"${META_TAG}\" \ + -e PORT=\"${CI_PORT}\" \ + -e SSL=\"${CI_SSL}\" \ + -e BASE=\"${DIST_IMAGE}\" \ + -e SECRET_KEY=\"${DO_SECRET}\" \ + -e ACCESS_KEY=\"${DO_KEY}\" \ + -e DOCKER_ENV=\"${CI_DOCKERENV}\" \ + -e WEB_SCREENSHOT=\"${CI_WEB}\" \ + -e WEB_AUTH=\"${CI_AUTH}\" \ + -e WEB_PATH=\"${CI_WEBPATH}\" \ + -e DO_REGION="ams3" \ + -e DO_BUCKET="lsio-ci" \ + -t lsiodev/ci:latest \ + python /ci/ci.py''' + } + } + } + /* ################## + Release Logic + ################## */ + // If this is an amd64 only image only push a single image + stage('Docker-Push-Single') { + when { + environment name: 'MULTIARCH', value: 'false' + environment name: 'EXIT_STATUS', value: '' + } + steps { + withCredentials([ + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', + usernameVariable: 'DOCKERUSER', + passwordVariable: 'DOCKERPASS' + ] + ]) { + echo 'Logging into DockerHub' + sh '''#! /bin/bash + echo $DOCKERPASS | docker login -u $DOCKERUSER --password-stdin + ''' + sh "docker tag ${IMAGE}:${META_TAG} ${IMAGE}:latest" + sh "docker push ${IMAGE}:latest" + sh "docker push ${IMAGE}:${META_TAG}" + sh '''docker rmi \ + ${IMAGE}:${META_TAG} \ + ${IMAGE}:latest || :''' + + } + } + } + // If this is a multi arch release push all images and define the manifest + stage('Docker-Push-Multi') { + when { + environment name: 'MULTIARCH', value: 'true' + environment name: 'EXIT_STATUS', value: '' + } + steps { + withCredentials([ + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', + usernameVariable: 'DOCKERUSER', + passwordVariable: 'DOCKERPASS' + ] + ]) { + sh '''#! /bin/bash + echo $DOCKERPASS | docker login -u $DOCKERUSER --password-stdin + ''' + sh '''#! /bin/bash + if [ "${CI}" == "false" ]; then + docker pull lsiodev/buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} + docker pull lsiodev/buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} + docker tag lsiodev/buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm32v7-${META_TAG} + docker tag lsiodev/buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} + fi''' + sh "docker tag ${IMAGE}:amd64-${META_TAG} ${IMAGE}:amd64-latest" + sh "docker tag ${IMAGE}:arm32v7-${META_TAG} ${IMAGE}:arm32v7-latest" + sh "docker tag ${IMAGE}:arm64v8-${META_TAG} ${IMAGE}:arm64v8-latest" + sh "docker push ${IMAGE}:amd64-${META_TAG}" + sh "docker push ${IMAGE}:arm32v7-${META_TAG}" + sh "docker push ${IMAGE}:arm64v8-${META_TAG}" + sh "docker push ${IMAGE}:amd64-latest" + sh "docker push ${IMAGE}:arm32v7-latest" + sh "docker push ${IMAGE}:arm64v8-latest" + sh "docker manifest push --purge ${IMAGE}:latest || :" + sh "docker manifest create ${IMAGE}:latest ${IMAGE}:amd64-latest ${IMAGE}:arm32v7-latest ${IMAGE}:arm64v8-latest" + sh "docker manifest annotate ${IMAGE}:latest ${IMAGE}:arm32v7-latest --os linux --arch arm" + sh "docker manifest annotate ${IMAGE}:latest ${IMAGE}:arm64v8-latest --os linux --arch arm64 --variant v8" + sh "docker manifest push --purge ${IMAGE}:${META_TAG} || :" + sh "docker manifest create ${IMAGE}:${META_TAG} ${IMAGE}:amd64-${META_TAG} ${IMAGE}:arm32v7-${META_TAG} ${IMAGE}:arm64v8-${META_TAG}" + sh "docker manifest annotate ${IMAGE}:${META_TAG} ${IMAGE}:arm32v7-${META_TAG} --os linux --arch arm" + sh "docker manifest annotate ${IMAGE}:${META_TAG} ${IMAGE}:arm64v8-${META_TAG} --os linux --arch arm64 --variant v8" + sh "docker manifest push --purge ${IMAGE}:latest" + sh "docker manifest push --purge ${IMAGE}:${META_TAG}" + sh '''docker rmi \ + ${IMAGE}:amd64-${META_TAG} \ + ${IMAGE}:amd64-latest \ + ${IMAGE}:arm32v7-${META_TAG} \ + ${IMAGE}:arm32v7-latest \ + ${IMAGE}:arm64v8-${META_TAG} \ + ${IMAGE}:arm64v8-latest \ + lsiodev/buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} \ + lsiodev/buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || :''' + } + } + } + // If this is a public release tag it in the LS Github + stage('Github-Tag-Push-Release') { + when { + branch "master" + expression { + env.LS_RELEASE != env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + } + environment name: 'CHANGE_ID', value: '' + environment name: 'EXIT_STATUS', value: '' + } + steps { + echo "Pushing New tag for current commit ${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}" + sh '''curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/git/tags \ + -d '{"tag":"'${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}'",\ + "object": "'${COMMIT_SHA}'",\ + "message": "Tagging Release '${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}' to master",\ + "type": "commit",\ + "tagger": {"name": "LinuxServer Jenkins","email": "jenkins@linuxserver.io","date": "'${GITHUB_DATE}'"}}' ''' + echo "Pushing New release for Tag" + sh '''#! /bin/bash + echo "Updating to ${EXT_RELEASE_CLEAN}" > releasebody.json + echo '{"tag_name":"'${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}'",\ + "target_commitish": "master",\ + "name": "'${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}'",\ + "body": "**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n**Remote Changes:**\\n\\n' > start + printf '","draft": false,"prerelease": false}' >> releasebody.json + paste -d'\\0' start releasebody.json > releasebody.json.done + curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases -d @releasebody.json.done''' + } + } + // Use helper container to sync the current README on master to the dockerhub endpoint + stage('Sync-README') { + when { + environment name: 'CHANGE_ID', value: '' + environment name: 'EXIT_STATUS', value: '' + } + steps { + withCredentials([ + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', + usernameVariable: 'DOCKERUSER', + passwordVariable: 'DOCKERPASS' + ] + ]) { + sh '''#! /bin/bash + docker pull lsiodev/readme-sync + docker run --rm=true \ + -e DOCKERHUB_USERNAME=$DOCKERUSER \ + -e DOCKERHUB_PASSWORD=$DOCKERPASS \ + -e GIT_REPOSITORY=${LS_USER}/${LS_REPO} \ + -e DOCKER_REPOSITORY=${IMAGE} \ + -e GIT_BRANCH=master \ + lsiodev/readme-sync bash -c 'node sync' ''' + } + } + } + // If this is a Pull request send the CI link as a comment on it + stage('Pull Request Comment') { + when { + not {environment name: 'CHANGE_ID', value: ''} + environment name: 'CI', value: 'true' + environment name: 'EXIT_STATUS', value: '' + } + steps { + sh '''curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/issues/${PULL_REQUEST}/comments \ + -d '{"body": "I am a bot, here are the test results for this PR: \\n'${CI_URL}' \\n'${SHELLCHECK_URL}'"}' ''' + } + } + } + /* ###################### + Send status to Discord + ###################### */ + post { + always { + script{ + if (env.EXIT_STATUS == "ABORTED"){ + sh 'echo "build aborted"' + } + else if (currentBuild.currentResult == "SUCCESS"){ + sh ''' curl -X POST --data '{"avatar_url": "https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png","embeds": [{"color": 1681177,\ + "description": "**Build:** '${BUILD_NUMBER}'\\n**CI Results:** '${CI_URL}'\\n**ShellCheck Results:** '${SHELLCHECK_URL}'\\n**Status:** Success\\n**Job:** '${RUN_DISPLAY_URL}'\\n**Change:** '${CODE_URL}'\\n**External Release:**: '${RELEASE_LINK}'\\n**DockerHub:** '${DOCKERHUB_LINK}'\\n"}],\ + "username": "Jenkins"}' ${BUILDS_DISCORD} ''' + } + else { + sh ''' curl -X POST --data '{"avatar_url": "https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png","embeds": [{"color": 16711680,\ + "description": "**Build:** '${BUILD_NUMBER}'\\n**CI Results:** '${CI_URL}'\\n**ShellCheck Results:** '${SHELLCHECK_URL}'\\n**Status:** failure\\n**Job:** '${RUN_DISPLAY_URL}'\\n**Change:** '${CODE_URL}'\\n**External Release:**: '${RELEASE_LINK}'\\n**DockerHub:** '${DOCKERHUB_LINK}'\\n"}],\ + "username": "Jenkins"}' ${BUILDS_DISCORD} ''' + } + } + } + } +} diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md index 63964ae..33af24d 100644 --- a/README.md +++ b/README.md @@ -1 +1,205 @@ -# docker-openssh-server \ No newline at end of file +[![linuxserver.io](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/linuxserver_medium.png)](https://linuxserver.io) + +[![Blog](https://img.shields.io/static/v1.svg?style=flat-square&color=E68523&label=linuxserver.io&message=Blog)](https://blog.linuxserver.io "all the things you can do with our containers including How-To guides, opinions and much more!") +[![Discord](https://img.shields.io/discord/354974912613449730.svg?style=flat-square&color=E68523&label=Discord&logo=discord&logoColor=FFFFFF)](https://discord.gg/YWrKVTn "realtime support / chat with the community and the team.") +[![Discourse](https://img.shields.io/discourse/https/discourse.linuxserver.io/topics.svg?style=flat-square&color=E68523&logo=discourse&logoColor=FFFFFF)](https://discourse.linuxserver.io "post on our community forum.") +[![Fleet](https://img.shields.io/static/v1.svg?style=flat-square&color=E68523&label=linuxserver.io&message=Fleet)](https://fleet.linuxserver.io "an online web interface which displays all of our maintained images.") +[![Podcast](https://img.shields.io/static/v1.svg?style=flat-square&color=E68523&label=linuxserver.io&message=Podcast)](https://anchor.fm/linuxserverio "on hiatus. Coming back soon (late 2018).") +[![Open Collective](https://img.shields.io/opencollective/all/linuxserver.svg?style=flat-square&color=E68523&label=Open%20Collective%20Supporters)](https://opencollective.com/linuxserver "please consider helping us by either donating or contributing to our budget") + +The [LinuxServer.io](https://linuxserver.io) team brings you another container release featuring :- + + * regular and timely application updates + * easy user mappings (PGID, PUID) + * custom base image with s6 overlay + * weekly base OS updates with common layers across the entire LinuxServer.io ecosystem to minimise space usage, down time and bandwidth + * regular security updates + +Find us at: +* [Blog](https://blog.linuxserver.io) - all the things you can do with our containers including How-To guides, opinions and much more! +* [Discord](https://discord.gg/YWrKVTn) - realtime support / chat with the community and the team. +* [Discourse](https://discourse.linuxserver.io) - post on our community forum. +* [Fleet](https://fleet.linuxserver.io) - an online web interface which displays all of our maintained images. +* [Podcast](https://anchor.fm/linuxserverio) - on hiatus. Coming back soon (late 2018). +* [Open Collective](https://opencollective.com/linuxserver) - please consider helping us by either donating or contributing to our budget + +# [linuxserver/openssh-server](https://github.com/linuxserver/docker-openssh-server) +[![GitHub Release](https://img.shields.io/github/release/linuxserver/docker-openssh-server.svg?style=flat-square&color=E68523)](https://github.com/linuxserver/docker-openssh-server/releases) +[![MicroBadger Layers](https://img.shields.io/microbadger/layers/linuxserver/openssh-server.svg?style=flat-square&color=E68523)](https://microbadger.com/images/linuxserver/openssh-server "Get your own version badge on microbadger.com") +[![MicroBadger Size](https://img.shields.io/microbadger/image-size/linuxserver/openssh-server.svg?style=flat-square&color=E68523)](https://microbadger.com/images/linuxserver/openssh-server "Get your own version badge on microbadger.com") +[![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/openssh-server.svg?style=flat-square&color=E68523)](https://hub.docker.com/r/linuxserver/openssh-server) +[![Docker Stars](https://img.shields.io/docker/stars/linuxserver/openssh-server.svg?style=flat-square&color=E68523)](https://hub.docker.com/r/linuxserver/openssh-server) +[![Build Status](https://ci.linuxserver.io/view/all/job/Docker-Pipeline-Builders/job/docker-openssh-server/job/master/badge/icon?style=flat-square)](https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-openssh-server/job/master/) +[![](https://lsio-ci.ams3.digitaloceanspaces.com/linuxserver/openssh-server/latest/badge.svg)](https://lsio-ci.ams3.digitaloceanspaces.com/linuxserver/openssh-server/latest/index.html) + +[Openssh-server](https://www.openssh.com/) is a sandboxed environment that allows ssh access without giving keys to the entire server. +Giving ssh access via private key often means giving full access to the server. This container creates a limited and sandboxed environment that others can ssh into. +The users only have access to the folders mapped and the processes running inside this container. + +[![openssh-server](https://upload.wikimedia.org/wikipedia/en/6/65/OpenSSH_logo.png)](https://www.openssh.com/) + +## Supported Architectures + +Our images support multiple architectures such as `x86-64`, `arm64` and `armhf`. We utilise the docker manifest for multi-platform awareness. More information is available from docker [here](https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-2.md#manifest-list) and our announcement [here](https://blog.linuxserver.io/2019/02/21/the-lsio-pipeline-project/). + +Simply pulling `linuxserver/openssh-server` should retrieve the correct image for your arch, but you can also pull specific arch images via tags. + +The architectures supported by this image are: + +| Architecture | Tag | +| :----: | --- | +| x86-64 | amd64-latest | +| arm64 | arm64v8-latest | +| armhf | arm32v7-latest | + + +## Usage + +Here are some example snippets to help you get started creating a container. + +### docker + +``` +docker create \ + --name=openssh-server \ + -e PUID=1000 \ + -e PGID=1000 \ + -e TZ=Europe/London \ + -e PUBLIC_KEY=ssh-rsa AAAAAxxxxxxxxxxxx `#optional` \ + -p 22:22 \ + -v /path/to/appdata/config:/config \ + --restart unless-stopped \ + linuxserver/openssh-server +``` + + +### docker-compose + +Compatible with docker-compose v2 schemas. + +``` +--- +version: "2" +services: + openssh-server: + image: linuxserver/openssh-server + container_name: openssh-server + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/London + - PUBLIC_KEY=ssh-rsa AAAAAxxxxxxxxxxxx #optional + volumes: + - /path/to/appdata/config:/config + ports: + - 22:22 + restart: unless-stopped +``` + +## Parameters + +Container images are configured using parameters passed at runtime (such as those above). These parameters are separated by a colon and indicate `:` respectively. For example, `-p 8080:80` would expose port `80` from inside the container to be accessible from the host's IP on port `8080` outside the container. + +| Parameter | Function | +| :----: | --- | +| `-p 22` | ssh port | +| `-e PUID=1000` | for UserID - see below for explanation | +| `-e PGID=1000` | for GroupID - see below for explanation | +| `-e TZ=Europe/London` | Specify a timezone to use EG Europe/London | +| `-e PUBLIC_KEY=ssh-rsa AAAAAxxxxxxxxxxxx` | Optional ssh public key, which will automatically be added to authorized_keys. | +| `-v /config` | Contains all relevant configuration files. | + +## User / Group Identifiers + +When using volumes (`-v` flags) permissions issues can arise between the host OS and the container, we avoid this issue by allowing you to specify the user `PUID` and group `PGID`. + +Ensure any volume directories on the host are owned by the same user you specify and any permissions issues will vanish like magic. + +In this instance `PUID=1000` and `PGID=1000`, to find yours use `id user` as below: + +``` + $ id username + uid=1000(dockeruser) gid=1000(dockergroup) groups=1000(dockergroup) +``` + + +  +## Application Setup + +If `PUBLIC_KEY` variable is set, it will automatically be added to `authorized_keys`. If not, the keys can manually be added to `/config/authorized_keys` and the container should be restarted. +Removing `PUBLIC_KEY` variable from docker run environment variables will not remove the key from `authorized_keys`. + +The users only have access to the folders mapped and the processes running inside this container. +Add any volume mappings you like for the users to have access to. +To install packages or services for users to access, use the LinuxServer container customization methods described [in this blog article](https://blog.linuxserver.io/2019/09/14/customizing-our-containers/). + +Sample use case is when a server admin would like to have automated incoming backups from a remote server to the local server, but they might not want all the other admins of the remote server to have full access to the local server. +This container can be set up with a mounted folder for incoming backups, and rsync installed via LinuxServer container customization described above, so that the incoming backups can proceed, but remote server and its admins' access would be limited to the backup folder. + + + +## Support Info + +* Shell access whilst the container is running: `docker exec -it openssh-server /bin/bash` +* To monitor the logs of the container in realtime: `docker logs -f openssh-server` +* container version number + * `docker inspect -f '{{ index .Config.Labels "build_version" }}' openssh-server` +* image version number + * `docker inspect -f '{{ index .Config.Labels "build_version" }}' linuxserver/openssh-server` + +## Updating Info + +Most of our images are static, versioned, and require an image update and container recreation to update the app inside. With some exceptions (ie. nextcloud, plex), we do not recommend or support updating apps inside the container. Please consult the [Application Setup](#application-setup) section above to see if it is recommended for the image. + +Below are the instructions for updating containers: + +### Via Docker Run/Create +* Update the image: `docker pull linuxserver/openssh-server` +* Stop the running container: `docker stop openssh-server` +* Delete the container: `docker rm openssh-server` +* Recreate a new container with the same docker create parameters as instructed above (if mapped correctly to a host folder, your `/config` folder and settings will be preserved) +* Start the new container: `docker start openssh-server` +* You can also remove the old dangling images: `docker image prune` + +### Via Docker Compose +* Update all images: `docker-compose pull` + * or update a single image: `docker-compose pull openssh-server` +* Let compose update all containers as necessary: `docker-compose up -d` + * or update a single container: `docker-compose up -d openssh-server` +* You can also remove the old dangling images: `docker image prune` + +### Via Watchtower auto-updater (especially useful if you don't remember the original parameters) +* Pull the latest image at its tag and replace it with the same env variables in one run: + ``` + docker run --rm \ + -v /var/run/docker.sock:/var/run/docker.sock \ + containrrr/watchtower \ + --run-once openssh-server + ``` + +**Note:** We do not endorse the use of Watchtower as a solution to automated updates of existing Docker containers. In fact we generally discourage automated updates. However, this is a useful tool for one-time manual updates of containers where you have forgotten the original parameters. In the long term, we highly recommend using Docker Compose. + +* You can also remove the old dangling images: `docker image prune` + +## Building locally + +If you want to make local modifications to these images for development purposes or just to customize the logic: +``` +git clone https://github.com/linuxserver/docker-openssh-server.git +cd docker-openssh-server +docker build \ + --no-cache \ + --pull \ + -t linuxserver/openssh-server:latest . +``` + +The ARM variants can be built on x86_64 hardware using `multiarch/qemu-user-static` +``` +docker run --rm --privileged multiarch/qemu-user-static:register --reset +``` + +Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64`. + +## Versions + +* **04.10.19:** - Initial Release. diff --git a/jenkins-vars.yml b/jenkins-vars.yml new file mode 100644 index 0000000..08cf659 --- /dev/null +++ b/jenkins-vars.yml @@ -0,0 +1,27 @@ +--- + +# jenkins variables +project_name: docker-openssh-server +external_type: na +custom_version_command: "curl -s http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/ |awk -F '(openssh-server-|.apk)' '/openssh-server.*.apk/ {print $2; exit}'" +release_type: stable +release_tag: latest +ls_branch: master +repo_vars: + - CONTAINER_NAME = 'openssh-server' + - BUILD_VERSION_ARG = 'OPENSSH_RELEASE' + - LS_USER = 'linuxserver' + - LS_REPO = 'docker-openssh-server' + - DOCKERHUB_IMAGE = 'linuxserver/openssh-server' + - DEV_DOCKERHUB_IMAGE = 'lsiodev/openssh-server' + - PR_DOCKERHUB_IMAGE = 'lspipepr/openssh-server' + - DIST_IMAGE = 'alpine' + - MULTIARCH='true' + - CI='true' + - CI_WEB='false' + - CI_PORT='80' + - CI_SSL='false' + - CI_DELAY='120' + - CI_DOCKERENV='TZ=US/Pacific' + - CI_AUTH='user:password' + - CI_WEBPATH='' diff --git a/readme-vars.yml b/readme-vars.yml new file mode 100644 index 0000000..2a15a5b --- /dev/null +++ b/readme-vars.yml @@ -0,0 +1,62 @@ +--- + +# project information +project_name: openssh-server +project_url: "https://www.openssh.com/" +project_logo: "https://upload.wikimedia.org/wikipedia/en/6/65/OpenSSH_logo.png" +project_blurb: "[{{ project_name|capitalize }}]({{ project_url }}) is a sandboxed environment that allows ssh access without giving keys to the entire server. + +Giving ssh access via private key often means giving full access to the server. This container creates a limited and sandboxed environment that others can ssh into. + +The users only have access to the folders mapped and the processes running inside this container." +project_lsio_github_repo_url: "https://github.com/linuxserver/docker-{{ project_name }}" + +# supported architectures +available_architectures: + - { arch: "{{ arch_x86_64 }}", tag: "amd64-latest"} + - { arch: "{{ arch_arm64 }}", tag: "arm64v8-latest"} + - { arch: "{{ arch_armhf }}", tag: "arm32v7-latest"} + +# development version +development_versions: false +development_versions_items: + - { tag: "latest", desc: "Stable releases" } + +# container parameters +common_param_env_vars_enabled: true +param_container_name: "{{ project_name }}" +param_usage_include_vols: true +param_volumes: + - { vol_path: "/config", vol_host_path: "/path/to/appdata/config", desc: "Contains all relevant configuration files." } +param_usage_include_ports: true +param_ports: + - { external_port: "22", internal_port: "22", port_desc: "ssh port" } +param_usage_include_env: true +param_env_vars: + - { env_var: "TZ", env_value: "Europe/London", desc: "Specify a timezone to use EG Europe/London"} + +# optional container parameters +opt_param_usage_include_env: true +opt_param_env_vars: + - { env_var: "PUBLIC_KEY", env_value: "ssh-rsa AAAAAxxxxxxxxxxxx", desc: "Optional ssh public key, which will automatically be added to authorized_keys."} + +optional_block_1: false +optional_block_1_items: "" + +# application setup block +app_setup_block_enabled: true +app_setup_block: | + If `PUBLIC_KEY` variable is set, it will automatically be added to `authorized_keys`. If not, the keys can manually be added to `/config/authorized_keys` and the container should be restarted. + Removing `PUBLIC_KEY` variable from docker run environment variables will not remove the key from `authorized_keys`. + + The users only have access to the folders mapped and the processes running inside this container. + Add any volume mappings you like for the users to have access to. + To install packages or services for users to access, use the LinuxServer container customization methods described [in this blog article](https://blog.linuxserver.io/2019/09/14/customizing-our-containers/). + + Sample use case is when a server admin would like to have automated incoming backups from a remote server to the local server, but they might not want all the other admins of the remote server to have full access to the local server. + This container can be set up with a mounted folder for incoming backups, and rsync installed via LinuxServer container customization described above, so that the incoming backups can proceed, but remote server and its admins' access would be limited to the backup folder. + + +# changelog +changelogs: + - { date: "04.10.19:", desc: "Initial Release." } diff --git a/root/etc/cont-init.d/50-config b/root/etc/cont-init.d/50-config new file mode 100644 index 0000000..99ad748 --- /dev/null +++ b/root/etc/cont-init.d/50-config @@ -0,0 +1,35 @@ +#!/usr/bin/with-contenv bash + +# create folders +mkdir -p \ + /config \ + /root/.ssh + +# set random password for root to unlock it +usermod -p $(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-8};echo;) root + +if [ ! -d /config/ssh ];then + cp -R /etc/ssh /config/ +fi + +if [ ! -f /config/authorized_keys ];then + touch /config/authorized_keys +fi + +[[ -n "$PUBLIC_KEY" ]] && \ + [[ ! $(grep "$PUBLIC_KEY" /config/authorized_keys) ]] && \ + echo "$PUBLIC_KEY" >> /config/authorized_keys + +cp -R /config/ssh /etc/ +cp /config/authorized_keys /root/.ssh/ + +# permissions +chown -R abc:abc \ + /config +chown -R root:root \ + /root \ + /etc/ssh +chmod 700 \ + /root/.ssh +chmod 600 \ + /config/authorized_keys \ No newline at end of file diff --git a/root/etc/services.d/openssh-server/run b/root/etc/services.d/openssh-server/run new file mode 100644 index 0000000..aba779d --- /dev/null +++ b/root/etc/services.d/openssh-server/run @@ -0,0 +1,4 @@ +#!/usr/bin/with-contenv bash + +exec \ + /usr/sbin/sshd -D -e \ No newline at end of file From b672e602e044cd9664ed0c2f8ec34a4e404fe1f5 Mon Sep 17 00:00:00 2001 From: aptalca Date: Fri, 4 Oct 2019 16:36:57 -0400 Subject: [PATCH 2/5] update readme, reduce ci delay --- Jenkinsfile | 2 +- README.md | 4 +++- jenkins-vars.yml | 2 +- readme-vars.yml | 4 +++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 55e7dd6..af1f172 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -23,7 +23,7 @@ pipeline { CI_WEB='false' CI_PORT='80' CI_SSL='false' - CI_DELAY='120' + CI_DELAY='60' CI_DOCKERENV='TZ=US/Pacific' CI_AUTH='user:password' CI_WEBPATH='' diff --git a/README.md b/README.md index 33af24d..8b03b0e 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,9 @@ Add any volume mappings you like for the users to have access to. To install packages or services for users to access, use the LinuxServer container customization methods described [in this blog article](https://blog.linuxserver.io/2019/09/14/customizing-our-containers/). Sample use case is when a server admin would like to have automated incoming backups from a remote server to the local server, but they might not want all the other admins of the remote server to have full access to the local server. -This container can be set up with a mounted folder for incoming backups, and rsync installed via LinuxServer container customization described above, so that the incoming backups can proceed, but remote server and its admins' access would be limited to the backup folder. +This container can be set up with a mounted folder for incoming backups, and rsync installed via LinuxServer container customization described above, so that the incoming backups can proceed, but remote server and its admins' access would be limited to the backup folder. + +It is also possible to run multiple copies of this containers with different ports mapped, different folders mounted and access to different private keys for compartmentalized access. diff --git a/jenkins-vars.yml b/jenkins-vars.yml index 08cf659..55781b2 100644 --- a/jenkins-vars.yml +++ b/jenkins-vars.yml @@ -21,7 +21,7 @@ repo_vars: - CI_WEB='false' - CI_PORT='80' - CI_SSL='false' - - CI_DELAY='120' + - CI_DELAY='60' - CI_DOCKERENV='TZ=US/Pacific' - CI_AUTH='user:password' - CI_WEBPATH='' diff --git a/readme-vars.yml b/readme-vars.yml index 2a15a5b..8e53627 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -54,7 +54,9 @@ app_setup_block: | To install packages or services for users to access, use the LinuxServer container customization methods described [in this blog article](https://blog.linuxserver.io/2019/09/14/customizing-our-containers/). Sample use case is when a server admin would like to have automated incoming backups from a remote server to the local server, but they might not want all the other admins of the remote server to have full access to the local server. - This container can be set up with a mounted folder for incoming backups, and rsync installed via LinuxServer container customization described above, so that the incoming backups can proceed, but remote server and its admins' access would be limited to the backup folder. + This container can be set up with a mounted folder for incoming backups, and rsync installed via LinuxServer container customization described above, so that the incoming backups can proceed, but remote server and its admins' access would be limited to the backup folder. + + It is also possible to run multiple copies of this containers with different ports mapped, different folders mounted and access to different private keys for compartmentalized access. # changelog From 89b281e377bf09ce696d8d76862c78e0f6b0e8ba Mon Sep 17 00:00:00 2001 From: aptalca Date: Fri, 4 Oct 2019 16:53:17 -0400 Subject: [PATCH 3/5] fix param --- README.md | 6 +++--- readme-vars.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8b03b0e..5fc4262 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ docker create \ -e PUID=1000 \ -e PGID=1000 \ -e TZ=Europe/London \ - -e PUBLIC_KEY=ssh-rsa AAAAAxxxxxxxxxxxx `#optional` \ + -e PUBLIC_KEY=yourpublickey `#optional` \ -p 22:22 \ -v /path/to/appdata/config:/config \ --restart unless-stopped \ @@ -88,7 +88,7 @@ services: - PUID=1000 - PGID=1000 - TZ=Europe/London - - PUBLIC_KEY=ssh-rsa AAAAAxxxxxxxxxxxx #optional + - PUBLIC_KEY=yourpublickey #optional volumes: - /path/to/appdata/config:/config ports: @@ -106,7 +106,7 @@ Container images are configured using parameters passed at runtime (such as thos | `-e PUID=1000` | for UserID - see below for explanation | | `-e PGID=1000` | for GroupID - see below for explanation | | `-e TZ=Europe/London` | Specify a timezone to use EG Europe/London | -| `-e PUBLIC_KEY=ssh-rsa AAAAAxxxxxxxxxxxx` | Optional ssh public key, which will automatically be added to authorized_keys. | +| `-e PUBLIC_KEY=yourpublickey` | Optional ssh public key, which will automatically be added to authorized_keys. | | `-v /config` | Contains all relevant configuration files. | ## User / Group Identifiers diff --git a/readme-vars.yml b/readme-vars.yml index 8e53627..d701637 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -38,7 +38,7 @@ param_env_vars: # optional container parameters opt_param_usage_include_env: true opt_param_env_vars: - - { env_var: "PUBLIC_KEY", env_value: "ssh-rsa AAAAAxxxxxxxxxxxx", desc: "Optional ssh public key, which will automatically be added to authorized_keys."} + - { env_var: "PUBLIC_KEY", env_value: "yourpublickey", desc: "Optional ssh public key, which will automatically be added to authorized_keys."} optional_block_1: false optional_block_1_items: "" From ec4cccf3111996088db29f26e8657d8405021511 Mon Sep 17 00:00:00 2001 From: aptalca Date: Sat, 5 Oct 2019 19:23:50 -0400 Subject: [PATCH 4/5] change ssh user from root to abc --- Dockerfile | 6 ++++-- Dockerfile.aarch64 | 6 ++++-- Dockerfile.armhf | 6 ++++-- README.md | 14 +++++++++++-- readme-vars.yml | 10 +++++++-- root/etc/cont-init.d/50-config | 37 ++++++++++++++++++++-------------- 6 files changed, 54 insertions(+), 25 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0545ed8..0921398 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,12 +9,14 @@ LABEL maintainer="aptalca" RUN \ echo "**** install runtime packages ****" && \ apk add --no-cache --upgrade \ - openssh-server && \ + openssh-server \ + sudo && \ echo "**** setup openssh environment ****" && \ sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config && \ ssh-keygen -A && \ + usermod --shell /bin/bash abc && \ rm -rf \ - /tmp/* + /tmp/* # add local files COPY /root / \ No newline at end of file diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index ff11435..bb97923 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -9,12 +9,14 @@ LABEL maintainer="aptalca" RUN \ echo "**** install runtime packages ****" && \ apk add --no-cache --upgrade \ - openssh-server && \ + openssh-server \ + sudo && \ echo "**** setup openssh environment ****" && \ sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config && \ ssh-keygen -A && \ + usermod --shell /bin/bash abc && \ rm -rf \ - /tmp/* + /tmp/* # add local files COPY /root / \ No newline at end of file diff --git a/Dockerfile.armhf b/Dockerfile.armhf index db812d8..e3230db 100644 --- a/Dockerfile.armhf +++ b/Dockerfile.armhf @@ -9,12 +9,14 @@ LABEL maintainer="aptalca" RUN \ echo "**** install runtime packages ****" && \ apk add --no-cache --upgrade \ - openssh-server && \ + openssh-server \ + sudo && \ echo "**** setup openssh environment ****" && \ sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config && \ ssh-keygen -A && \ + usermod --shell /bin/bash abc && \ rm -rf \ - /tmp/* + /tmp/* # add local files COPY /root / \ No newline at end of file diff --git a/README.md b/README.md index 5fc4262..bc52256 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,8 @@ docker create \ -e PGID=1000 \ -e TZ=Europe/London \ -e PUBLIC_KEY=yourpublickey `#optional` \ + -e SUDO_ACCESS=false `#optional` \ + -e SUDO_PASSWORD=password `#optional` \ -p 22:22 \ -v /path/to/appdata/config:/config \ --restart unless-stopped \ @@ -89,6 +91,8 @@ services: - PGID=1000 - TZ=Europe/London - PUBLIC_KEY=yourpublickey #optional + - SUDO_ACCESS=false #optional + - SUDO_PASSWORD=password #optional volumes: - /path/to/appdata/config:/config ports: @@ -107,6 +111,8 @@ Container images are configured using parameters passed at runtime (such as thos | `-e PGID=1000` | for GroupID - see below for explanation | | `-e TZ=Europe/London` | Specify a timezone to use EG Europe/London | | `-e PUBLIC_KEY=yourpublickey` | Optional ssh public key, which will automatically be added to authorized_keys. | +| `-e SUDO_ACCESS=false` | Set to `true` to allow `abc`, the ssh user, sudo access. Without `SUDO_PASSWORD` set, this will allow passwordless sudo access. | +| `-e SUDO_PASSWORD=password` | Optionally set a sudo password for `abc`, the ssh user. If this is not set but `SUDO_ACCESS` is set to true, the user will have passwordless sudo access. | | `-v /config` | Contains all relevant configuration files. | ## User / Group Identifiers @@ -126,9 +132,13 @@ In this instance `PUID=1000` and `PGID=1000`, to find yours use `id user` as bel   ## Application Setup -If `PUBLIC_KEY` variable is set, it will automatically be added to `authorized_keys`. If not, the keys can manually be added to `/config/authorized_keys` and the container should be restarted. +If `PUBLIC_KEY` variable is set, it will automatically be added to `authorized_keys`. If not, the keys can manually be added to `/config/.ssh/authorized_keys` and the container should be restarted. Removing `PUBLIC_KEY` variable from docker run environment variables will not remove the key from `authorized_keys`. +Connect to server via `ssh -i /path/to/private/key -p PORT abc@SERVERIP` + +Setting `SUDO_ACCESS` to `true` by itself will allow passwordless sudo. `SUDO_PASSWORD` allows setting an optional sudo password. + The users only have access to the folders mapped and the processes running inside this container. Add any volume mappings you like for the users to have access to. To install packages or services for users to access, use the LinuxServer container customization methods described [in this blog article](https://blog.linuxserver.io/2019/09/14/customizing-our-containers/). @@ -136,7 +146,7 @@ To install packages or services for users to access, use the LinuxServer contain Sample use case is when a server admin would like to have automated incoming backups from a remote server to the local server, but they might not want all the other admins of the remote server to have full access to the local server. This container can be set up with a mounted folder for incoming backups, and rsync installed via LinuxServer container customization described above, so that the incoming backups can proceed, but remote server and its admins' access would be limited to the backup folder. -It is also possible to run multiple copies of this containers with different ports mapped, different folders mounted and access to different private keys for compartmentalized access. +It is also possible to run multiple copies of this container with different ports mapped, different folders mounted and access to different private keys for compartmentalized access. diff --git a/readme-vars.yml b/readme-vars.yml index d701637..90c08b5 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -39,6 +39,8 @@ param_env_vars: opt_param_usage_include_env: true opt_param_env_vars: - { env_var: "PUBLIC_KEY", env_value: "yourpublickey", desc: "Optional ssh public key, which will automatically be added to authorized_keys."} + - { env_var: "SUDO_ACCESS", env_value: "false", desc: "Set to `true` to allow `abc`, the ssh user, sudo access. Without `SUDO_PASSWORD` set, this will allow passwordless sudo access."} + - { env_var: "SUDO_PASSWORD", env_value: "password", desc: "Optionally set a sudo password for `abc`, the ssh user. If this is not set but `SUDO_ACCESS` is set to true, the user will have passwordless sudo access."} optional_block_1: false optional_block_1_items: "" @@ -46,9 +48,13 @@ optional_block_1_items: "" # application setup block app_setup_block_enabled: true app_setup_block: | - If `PUBLIC_KEY` variable is set, it will automatically be added to `authorized_keys`. If not, the keys can manually be added to `/config/authorized_keys` and the container should be restarted. + If `PUBLIC_KEY` variable is set, it will automatically be added to `authorized_keys`. If not, the keys can manually be added to `/config/.ssh/authorized_keys` and the container should be restarted. Removing `PUBLIC_KEY` variable from docker run environment variables will not remove the key from `authorized_keys`. + Connect to server via `ssh -i /path/to/private/key -p PORT abc@SERVERIP` + + Setting `SUDO_ACCESS` to `true` by itself will allow passwordless sudo. `SUDO_PASSWORD` allows setting an optional sudo password. + The users only have access to the folders mapped and the processes running inside this container. Add any volume mappings you like for the users to have access to. To install packages or services for users to access, use the LinuxServer container customization methods described [in this blog article](https://blog.linuxserver.io/2019/09/14/customizing-our-containers/). @@ -56,7 +62,7 @@ app_setup_block: | Sample use case is when a server admin would like to have automated incoming backups from a remote server to the local server, but they might not want all the other admins of the remote server to have full access to the local server. This container can be set up with a mounted folder for incoming backups, and rsync installed via LinuxServer container customization described above, so that the incoming backups can proceed, but remote server and its admins' access would be limited to the backup folder. - It is also possible to run multiple copies of this containers with different ports mapped, different folders mounted and access to different private keys for compartmentalized access. + It is also possible to run multiple copies of this container with different ports mapped, different folders mounted and access to different private keys for compartmentalized access. # changelog diff --git a/root/etc/cont-init.d/50-config b/root/etc/cont-init.d/50-config index 99ad748..fae8bde 100644 --- a/root/etc/cont-init.d/50-config +++ b/root/etc/cont-init.d/50-config @@ -2,34 +2,41 @@ # create folders mkdir -p \ - /config \ - /root/.ssh + /config/.ssh -# set random password for root to unlock it -usermod -p $(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-8};echo;) root +# set password for abc to unlock it and set sudo access +sed -i '/abc ALL.*/d' /etc/sudoers +if [ "$SUDO_ACCESS" == "true" ]; then + if [ -n "$SUDO_PASSWORD" ]; then + echo "abc ALL=(ALL) ALL" >> /etc/sudoers + else + echo "abc ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + fi +fi +SUDO_PASSWORD=${SUDO_PASSWORD:-$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-8};echo;)} +echo "abc:$SUDO_PASSWORD" | chpasswd -if [ ! -d /config/ssh ];then - cp -R /etc/ssh /config/ +if [ ! -d /config/ssh_host_keys ];then + cp -R /etc/ssh /config/ssh_host_keys fi -if [ ! -f /config/authorized_keys ];then - touch /config/authorized_keys +if [ ! -f /config/.ssh/authorized_keys ];then + touch /config/.ssh/authorized_keys fi [[ -n "$PUBLIC_KEY" ]] && \ - [[ ! $(grep "$PUBLIC_KEY" /config/authorized_keys) ]] && \ - echo "$PUBLIC_KEY" >> /config/authorized_keys + [[ ! $(grep "$PUBLIC_KEY" /config/.ssh/authorized_keys) ]] && \ + echo "$PUBLIC_KEY" >> /config/.ssh/authorized_keys -cp -R /config/ssh /etc/ -cp /config/authorized_keys /root/.ssh/ +rm -rf /etc/ssh +cp -R /config/ssh_host_keys /etc/ssh # permissions chown -R abc:abc \ /config chown -R root:root \ - /root \ /etc/ssh chmod 700 \ - /root/.ssh + /config/.ssh chmod 600 \ - /config/authorized_keys \ No newline at end of file + /config/.ssh/authorized_keys \ No newline at end of file From c98121e61f305a4c7b86d6270c8eebcc0444e998 Mon Sep 17 00:00:00 2001 From: aptalca Date: Sun, 6 Oct 2019 14:13:45 -0400 Subject: [PATCH 5/5] Add USER_NAME support --- README.md | 5 ++++- readme-vars.yml | 3 ++- root/etc/cont-init.d/10-adduser | 37 +++++++++++++++++++++++++++++++++ root/etc/cont-init.d/50-config | 12 ++++++----- 4 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 root/etc/cont-init.d/10-adduser diff --git a/README.md b/README.md index bc52256..6f0d88f 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ docker create \ -e PUBLIC_KEY=yourpublickey `#optional` \ -e SUDO_ACCESS=false `#optional` \ -e SUDO_PASSWORD=password `#optional` \ + -e USER_NAME=abc `#optional` \ -p 22:22 \ -v /path/to/appdata/config:/config \ --restart unless-stopped \ @@ -93,6 +94,7 @@ services: - PUBLIC_KEY=yourpublickey #optional - SUDO_ACCESS=false #optional - SUDO_PASSWORD=password #optional + - USER_NAME=abc #optional volumes: - /path/to/appdata/config:/config ports: @@ -113,6 +115,7 @@ Container images are configured using parameters passed at runtime (such as thos | `-e PUBLIC_KEY=yourpublickey` | Optional ssh public key, which will automatically be added to authorized_keys. | | `-e SUDO_ACCESS=false` | Set to `true` to allow `abc`, the ssh user, sudo access. Without `SUDO_PASSWORD` set, this will allow passwordless sudo access. | | `-e SUDO_PASSWORD=password` | Optionally set a sudo password for `abc`, the ssh user. If this is not set but `SUDO_ACCESS` is set to true, the user will have passwordless sudo access. | +| `-e USER_NAME=abc` | Optionally specify a user name (Default:`abc`) | | `-v /config` | Contains all relevant configuration files. | ## User / Group Identifiers @@ -135,7 +138,7 @@ In this instance `PUID=1000` and `PGID=1000`, to find yours use `id user` as bel If `PUBLIC_KEY` variable is set, it will automatically be added to `authorized_keys`. If not, the keys can manually be added to `/config/.ssh/authorized_keys` and the container should be restarted. Removing `PUBLIC_KEY` variable from docker run environment variables will not remove the key from `authorized_keys`. -Connect to server via `ssh -i /path/to/private/key -p PORT abc@SERVERIP` +Connect to server via `ssh -i /path/to/private/key -p PORT USER_NAME@SERVERIP` Setting `SUDO_ACCESS` to `true` by itself will allow passwordless sudo. `SUDO_PASSWORD` allows setting an optional sudo password. diff --git a/readme-vars.yml b/readme-vars.yml index 90c08b5..6dd00ee 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -41,6 +41,7 @@ opt_param_env_vars: - { env_var: "PUBLIC_KEY", env_value: "yourpublickey", desc: "Optional ssh public key, which will automatically be added to authorized_keys."} - { env_var: "SUDO_ACCESS", env_value: "false", desc: "Set to `true` to allow `abc`, the ssh user, sudo access. Without `SUDO_PASSWORD` set, this will allow passwordless sudo access."} - { env_var: "SUDO_PASSWORD", env_value: "password", desc: "Optionally set a sudo password for `abc`, the ssh user. If this is not set but `SUDO_ACCESS` is set to true, the user will have passwordless sudo access."} + - { env_var: "USER_NAME", env_value: "abc", desc: "Optionally specify a user name (Default:`abc`)"} optional_block_1: false optional_block_1_items: "" @@ -51,7 +52,7 @@ app_setup_block: | If `PUBLIC_KEY` variable is set, it will automatically be added to `authorized_keys`. If not, the keys can manually be added to `/config/.ssh/authorized_keys` and the container should be restarted. Removing `PUBLIC_KEY` variable from docker run environment variables will not remove the key from `authorized_keys`. - Connect to server via `ssh -i /path/to/private/key -p PORT abc@SERVERIP` + Connect to server via `ssh -i /path/to/private/key -p PORT USER_NAME@SERVERIP` Setting `SUDO_ACCESS` to `true` by itself will allow passwordless sudo. `SUDO_PASSWORD` allows setting an optional sudo password. diff --git a/root/etc/cont-init.d/10-adduser b/root/etc/cont-init.d/10-adduser new file mode 100644 index 0000000..eca366f --- /dev/null +++ b/root/etc/cont-init.d/10-adduser @@ -0,0 +1,37 @@ +#!/usr/bin/with-contenv bash + +USER_NAME=${USER_NAME:-abc} + +PUID=${PUID:-911} +PGID=${PGID:-911} + +[[ ! "$USER_NAME" == "abc" ]] && \ + usermod -l "$USER_NAME" abc && \ + groupmod -n "$USER_NAME" abc + +groupmod -o -g "$PGID" "$USER_NAME" +usermod -o -u "$PUID" "$USER_NAME" + +echo ' +------------------------------------- + _ () + | | ___ _ __ + | | / __| | | / \ + | | \__ \ | | | () | + |_| |___/ |_| \__/ + + +Brought to you by linuxserver.io +We gratefully accept donations at: +https://www.linuxserver.io/donate/ +------------------------------------- +GID/UID +-------------------------------------' +echo " +User uid: $(id -u "$USER_NAME") +User gid: $(id -g "$USER_NAME") +------------------------------------- +" +chown "$USER_NAME":"$USER_NAME" /app +chown "$USER_NAME":"$USER_NAME" /config +chown "$USER_NAME":"$USER_NAME" /defaults \ No newline at end of file diff --git a/root/etc/cont-init.d/50-config b/root/etc/cont-init.d/50-config index fae8bde..0ebc0d7 100644 --- a/root/etc/cont-init.d/50-config +++ b/root/etc/cont-init.d/50-config @@ -4,17 +4,19 @@ mkdir -p \ /config/.ssh +USER_NAME=${USER_NAME:-abc} + # set password for abc to unlock it and set sudo access -sed -i '/abc ALL.*/d' /etc/sudoers +sed -i "/${USER_NAME} ALL.*/d" /etc/sudoers if [ "$SUDO_ACCESS" == "true" ]; then if [ -n "$SUDO_PASSWORD" ]; then - echo "abc ALL=(ALL) ALL" >> /etc/sudoers + echo "${USER_NAME} ALL=(ALL) ALL" >> /etc/sudoers else - echo "abc ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + echo "${USER_NAME} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers fi fi SUDO_PASSWORD=${SUDO_PASSWORD:-$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-8};echo;)} -echo "abc:$SUDO_PASSWORD" | chpasswd +echo "${USER_NAME}:${SUDO_PASSWORD}" | chpasswd if [ ! -d /config/ssh_host_keys ];then cp -R /etc/ssh /config/ssh_host_keys @@ -32,7 +34,7 @@ rm -rf /etc/ssh cp -R /config/ssh_host_keys /etc/ssh # permissions -chown -R abc:abc \ +chown -R "${USER_NAME}":"${USER_NAME}" \ /config chown -R root:root \ /etc/ssh