diff --git a/.editorconfig b/.editorconfig index a92f7df..5f150f3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -15,6 +15,6 @@ trim_trailing_whitespace = false indent_style = space indent_size = 2 -[{**.sh,root/etc/cont-init.d/**,root/etc/services.d/**}] +[{**.sh,root/etc/s6-overlay/s6-rc.d/**,root/etc/cont-init.d/**,root/etc/services.d/**}] indent_style = space indent_size = 4 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 92e2642..3a2e2ea 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -6,7 +6,7 @@ * Read, and fill the Pull Request template * If this is a fix for a typo (in code, documentation, or the README) please file an issue and let us sort it out. We do not need a PR * If the PR is addressing an existing issue include, closes #\, in the body of the PR commit message -* If you want to discuss changes, you can also bring it up in [#dev-talk](https://discordapp.com/channels/354974912613449730/757585807061155840) in our [Discord server](https://discord.gg/YWrKVTn) +* If you want to discuss changes, you can also bring it up in [#dev-talk](https://discordapp.com/channels/354974912613449730/757585807061155840) in our [Discord server](https://linuxserver.io/discord) ## Common files @@ -105,10 +105,10 @@ docker build \ -t linuxserver/kasm:latest . ``` -The ARM variants can be built on x86_64 hardware using `multiarch/qemu-user-static` +The ARM variants can be built on x86_64 hardware and vice versa using `lscr.io/linuxserver/qemu-static` ```bash -docker run --rm --privileged multiarch/qemu-user-static:register --reset +docker run --rm --privileged lscr.io/linuxserver/qemu-static --reset ``` Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64`. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 91ee0c0..618c04b 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ blank_issues_enabled: false contact_links: - name: Discord chat support - url: https://discord.gg/YWrKVTn + url: https://linuxserver.io/discord about: Realtime support / chat with the community and the team. - name: Discourse discussion forum diff --git a/.github/ISSUE_TEMPLATE/issue.bug.md b/.github/ISSUE_TEMPLATE/issue.bug.md deleted file mode 100644 index 24ba71e..0000000 --- a/.github/ISSUE_TEMPLATE/issue.bug.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve - ---- -[linuxserverurl]: https://linuxserver.io -[![linuxserver.io](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/linuxserver_medium.png)][linuxserverurl] - - - - - ------------------------------- - -## Expected Behavior - - -## Current Behavior - - -## Steps to Reproduce - - -1. -2. -3. -4. - -## Environment -**OS:** -**CPU architecture:** x86_64/arm32/arm64 -**How docker service was installed:** - - - -## Command used to create docker container (run/create/compose/screenshot) - - -## Docker logs - diff --git a/.github/ISSUE_TEMPLATE/issue.bug.yml b/.github/ISSUE_TEMPLATE/issue.bug.yml new file mode 100644 index 0000000..48781be --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue.bug.yml @@ -0,0 +1,76 @@ +# Based on the issue template +name: Bug report +description: Create a report to help us improve +title: "[BUG] " +labels: [Bug] +body: + - type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true + - type: textarea + attributes: + label: Current Behavior + description: Tell us what happens instead of the expected behavior. + validations: + required: true + - type: textarea + attributes: + label: Expected Behavior + description: Tell us what should happen. + validations: + required: false + - type: textarea + attributes: + label: Steps To Reproduce + description: Steps to reproduce the behavior. + placeholder: | + 1. In this environment... + 2. With this config... + 3. Run '...' + 4. See error... + validations: + required: true + - type: textarea + attributes: + label: Environment + description: | + examples: + - **OS**: Ubuntu 20.04 + - **How docker service was installed**: distro's packagemanager + value: | + - OS: + - How docker service was installed: + render: markdown + validations: + required: false + - type: dropdown + attributes: + label: CPU architecture + options: + - x86-64 + - arm64 + validations: + required: true + - type: textarea + attributes: + label: Docker creation + description: | + Command used to create docker container + Provide your docker create/run command or compose yaml snippet, or a screenshot of settings if using a gui to create the container + render: bash + validations: + required: true + - type: textarea + attributes: + description: | + Provide a full docker log, output of "docker logs kasm" + label: Container logs + placeholder: | + Output of `docker logs kasm` + render: bash + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/issue.feature.md b/.github/ISSUE_TEMPLATE/issue.feature.md deleted file mode 100644 index 20a91fd..0000000 --- a/.github/ISSUE_TEMPLATE/issue.feature.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project - ---- -[linuxserverurl]: https://linuxserver.io -[![linuxserver.io](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/linuxserver_medium.png)][linuxserverurl] - -<!--- If you are new to Docker or this application our issue tracker is **ONLY** used for reporting bugs or requesting features. Please use [our discord server](https://discord.gg/YWrKVTn) for general support. ---> - -<!--- If this acts as a feature request please ask yourself if this modification is something the whole userbase will benefit from ---> -<!--- If this is a specific change for corner case functionality or plugins please look at making a Docker Mod or local script https://blog.linuxserver.io/2019/09/14/customizing-our-containers/ --> - -<!--- Provide a general summary of the request in the Title above --> - ------------------------------- - -## Desired Behavior -<!--- Tell us what should happen --> - -## Current Behavior -<!--- Tell us what happens instead of the expected behavior --> - -## Alternatives Considered -<!--- Tell us what other options you have tried or considered --> diff --git a/.github/ISSUE_TEMPLATE/issue.feature.yml b/.github/ISSUE_TEMPLATE/issue.feature.yml new file mode 100644 index 0000000..099dcdb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue.feature.yml @@ -0,0 +1,31 @@ +# Based on the issue template +name: Feature request +description: Suggest an idea for this project +title: "[FEAT] <title>" +labels: [enhancement] +body: + - type: checkboxes + attributes: + label: Is this a new feature request? + description: Please search to see if a feature request already exists. + options: + - label: I have searched the existing issues + required: true + - type: textarea + attributes: + label: Wanted change + description: Tell us what you want to happen. + validations: + required: true + - type: textarea + attributes: + label: Reason for change + description: Justify your request, why do you want it, what is the benefit. + validations: + required: true + - type: textarea + attributes: + label: Proposed code change + description: Do you have a potential code change in mind? + validations: + required: false diff --git a/.github/workflows/call_issue_pr_tracker.yml b/.github/workflows/call_issue_pr_tracker.yml new file mode 100644 index 0000000..d07cf12 --- /dev/null +++ b/.github/workflows/call_issue_pr_tracker.yml @@ -0,0 +1,19 @@ +name: Issue & PR Tracker + +on: + issues: + types: [opened,reopened,labeled,unlabeled,closed] + pull_request_target: + types: [opened,reopened,review_requested,review_request_removed,labeled,unlabeled,closed] + pull_request_review: + types: [submitted,edited,dismissed] + +permissions: + contents: read + +jobs: + manage-project: + permissions: + issues: write + uses: linuxserver/github-workflows/.github/workflows/issue-pr-tracker.yml@v1 + secrets: inherit diff --git a/.github/workflows/call_issues_cron.yml b/.github/workflows/call_issues_cron.yml new file mode 100644 index 0000000..3c0a5ac --- /dev/null +++ b/.github/workflows/call_issues_cron.yml @@ -0,0 +1,16 @@ +name: Mark stale issues and pull requests +on: + schedule: + - cron: '16 9 * * *' + workflow_dispatch: + +permissions: + contents: read + +jobs: + stale: + permissions: + issues: write + pull-requests: write + uses: linuxserver/github-workflows/.github/workflows/issues-cron.yml@v1 + secrets: inherit diff --git a/.github/workflows/external_trigger.yml b/.github/workflows/external_trigger.yml index 197f508..db3c457 100644 --- a/.github/workflows/external_trigger.yml +++ b/.github/workflows/external_trigger.yml @@ -3,24 +3,42 @@ name: External Trigger Main on: workflow_dispatch: +permissions: + contents: read + jobs: external-trigger-master: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.3 + - uses: actions/checkout@v4.1.1 - name: External Trigger if: github.ref == 'refs/heads/master' + env: + SKIP_EXTERNAL_TRIGGER: ${{ vars.SKIP_EXTERNAL_TRIGGER }} run: | - if [ -n "${{ secrets.PAUSE_EXTERNAL_TRIGGER_KASM_MASTER }}" ]; then - echo "**** Github secret PAUSE_EXTERNAL_TRIGGER_KASM_MASTER is set; skipping trigger. ****" + printf "# External trigger for docker-kasm\n\n" >> $GITHUB_STEP_SUMMARY + if grep -q "^kasm_master_" <<< "${SKIP_EXTERNAL_TRIGGER}"; then + echo "> [!NOTE]" >> $GITHUB_STEP_SUMMARY + echo "> Github organizational variable \`SKIP_EXTERNAL_TRIGGER\` contains \`kasm_master_\`; will skip trigger if version matches." >> $GITHUB_STEP_SUMMARY + elif grep -q "^kasm_master" <<< "${SKIP_EXTERNAL_TRIGGER}"; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> Github organizational variable \`SKIP_EXTERNAL_TRIGGER\` contains \`kasm_master\`; skipping trigger." >> $GITHUB_STEP_SUMMARY exit 0 fi - echo "**** External trigger running off of master branch. To disable this trigger, set a Github secret named \"PAUSE_EXTERNAL_TRIGGER_KASM_MASTER\". ****" - echo "**** Retrieving external version ****" + echo "> [!NOTE]" >> $GITHUB_STEP_SUMMARY + echo "> External trigger running off of master branch. To disable this trigger, add \`kasm_master\` into the Github organizational variable \`SKIP_EXTERNAL_TRIGGER\`." >> $GITHUB_STEP_SUMMARY + printf "\n## Retrieving external version\n\n" >> $GITHUB_STEP_SUMMARY EXT_RELEASE=$(curl -u "${{ secrets.CR_USER }}:${{ secrets.CR_PAT }}" -sX GET "https://api.github.com/repos/kasmtech/kasm-install-wizard/releases/latest" | jq -r '. | .tag_name') + echo "Type is \`github_stable\`" >> $GITHUB_STEP_SUMMARY + if grep -q "^kasm_master_${EXT_RELEASE}" <<< "${SKIP_EXTERNAL_TRIGGER}"; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> Github organizational variable \`SKIP_EXTERNAL_TRIGGER\` matches current external release; skipping trigger." >> $GITHUB_STEP_SUMMARY + exit 0 + fi if [ -z "${EXT_RELEASE}" ] || [ "${EXT_RELEASE}" == "null" ]; then - echo "**** Can't retrieve external version, exiting ****" + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> Can't retrieve external version, exiting" >> $GITHUB_STEP_SUMMARY FAILURE_REASON="Can't retrieve external version for kasm branch master" GHA_TRIGGER_URL="https://github.com/linuxserver/docker-kasm/actions/runs/${{ github.run_id }}" curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 16711680, @@ -28,65 +46,102 @@ jobs: "username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }} exit 1 fi - EXT_RELEASE=$(echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g') - echo "**** External version: ${EXT_RELEASE} ****" - echo "**** Retrieving last pushed version ****" + EXT_RELEASE_SANITIZED=$(echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g') + echo "Sanitized external version: \`${EXT_RELEASE_SANITIZED}\`" >> $GITHUB_STEP_SUMMARY + echo "Retrieving last pushed version" >> $GITHUB_STEP_SUMMARY image="linuxserver/kasm" tag="latest" token=$(curl -sX GET \ "https://ghcr.io/token?scope=repository%3Alinuxserver%2Fkasm%3Apull" \ | jq -r '.token') - multidigest=$(curl -s \ + multidigest=$(curl -s \ + --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \ + --header "Accept: application/vnd.oci.image.index.v1+json" \ + --header "Authorization: Bearer ${token}" \ + "https://ghcr.io/v2/${image}/manifests/${tag}") + if jq -e '.layers // empty' <<< "${multidigest}" >/dev/null 2>&1; then + # If there's a layer element it's a single-arch manifest so just get that digest + digest=$(jq -r '.config.digest' <<< "${multidigest}") + else + # Otherwise it's multi-arch or has manifest annotations + if jq -e '.manifests[]?.annotations // empty' <<< "${multidigest}" >/dev/null 2>&1; then + # Check for manifest annotations and delete if found + multidigest=$(jq 'del(.manifests[] | select(.annotations))' <<< "${multidigest}") + fi + if [[ $(jq '.manifests | length' <<< "${multidigest}") -gt 1 ]]; then + # If there's still more than one digest, it's multi-arch + multidigest=$(jq -r ".manifests[] | select(.platform.architecture == \"amd64\").digest?" <<< "${multidigest}") + else + # Otherwise it's single arch + multidigest=$(jq -r ".manifests[].digest?" <<< "${multidigest}") + fi + if digest=$(curl -s \ --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \ + --header "Accept: application/vnd.oci.image.manifest.v1+json" \ --header "Authorization: Bearer ${token}" \ - "https://ghcr.io/v2/${image}/manifests/${tag}" \ - | jq -r 'first(.manifests[].digest)') - digest=$(curl -s \ - --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \ - --header "Authorization: Bearer ${token}" \ - "https://ghcr.io/v2/${image}/manifests/${multidigest}" \ - | jq -r '.config.digest') + "https://ghcr.io/v2/${image}/manifests/${multidigest}"); then + digest=$(jq -r '.config.digest' <<< "${digest}"); + fi + fi image_info=$(curl -sL \ --header "Authorization: Bearer ${token}" \ - "https://ghcr.io/v2/${image}/blobs/${digest}" \ - | jq -r '.container_config') + "https://ghcr.io/v2/${image}/blobs/${digest}") + if [[ $(echo $image_info | jq -r '.container_config') == "null" ]]; then + image_info=$(echo $image_info | jq -r '.config') + else + image_info=$(echo $image_info | jq -r '.container_config') + fi IMAGE_RELEASE=$(echo ${image_info} | jq -r '.Labels.build_version' | awk '{print $3}') IMAGE_VERSION=$(echo ${IMAGE_RELEASE} | awk -F'-ls' '{print $1}') if [ -z "${IMAGE_VERSION}" ]; then - echo "**** Can't retrieve last pushed version, exiting ****" + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "Can't retrieve last pushed version, exiting" >> $GITHUB_STEP_SUMMARY FAILURE_REASON="Can't retrieve last pushed version for kasm tag latest" curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 16711680, "description": "**Trigger Failed** \n**Reason:** '"${FAILURE_REASON}"' \n"}], "username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }} exit 1 fi - echo "**** Last pushed version: ${IMAGE_VERSION} ****" - if [ "${EXT_RELEASE}" == "${IMAGE_VERSION}" ]; then - echo "**** Version ${EXT_RELEASE} already pushed, exiting ****" + echo "Last pushed version: \`${IMAGE_VERSION}\`" >> $GITHUB_STEP_SUMMARY + if [ "${EXT_RELEASE_SANITIZED}" == "${IMAGE_VERSION}" ]; then + echo "Sanitized version \`${EXT_RELEASE_SANITIZED}\` already pushed, exiting" >> $GITHUB_STEP_SUMMARY exit 0 elif [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-kasm/job/master/lastBuild/api/json | jq -r '.building') == "true" ]; then - echo "**** New version ${EXT_RELEASE} found; but there already seems to be an active build on Jenkins; exiting ****" + echo "New version \`${EXT_RELEASE}\` found; but there already seems to be an active build on Jenkins; exiting" >> $GITHUB_STEP_SUMMARY exit 0 else - echo "**** New version ${EXT_RELEASE} found; old version was ${IMAGE_VERSION}. Triggering new build ****" - response=$(curl -iX POST \ - https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-kasm/job/master/buildWithParameters?PACKAGE_CHECK=false \ - --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} | grep -i location | sed "s|^[L|l]ocation: \(.*\)|\1|") - echo "**** Jenkins job queue url: ${response%$'\r'} ****" - echo "**** Sleeping 10 seconds until job starts ****" - sleep 10 - buildurl=$(curl -s "${response%$'\r'}api/json" | jq -r '.executable.url') - buildurl="${buildurl%$'\r'}" - echo "**** Jenkins job build url: ${buildurl} ****" - echo "**** Attempting to change the Jenkins job description ****" - curl -iX POST \ - "${buildurl}submitDescription" \ - --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} \ - --data-urlencode "description=GHA external trigger https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ - --data-urlencode "Submit=Submit" - echo "**** Notifying Discord ****" - TRIGGER_REASON="A version change was detected for kasm tag latest. Old version:${IMAGE_VERSION} New version:${EXT_RELEASE}" - curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 9802903, - "description": "**Build Triggered** \n**Reason:** '"${TRIGGER_REASON}"' \n**Build URL:** '"${buildurl}display/redirect"' \n"}], - "username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }} + if [[ "${artifacts_found}" == "false" ]]; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> New version detected, but not all artifacts are published yet; skipping trigger" >> $GITHUB_STEP_SUMMARY + FAILURE_REASON="New version ${EXT_RELEASE} for kasm tag latest is detected, however not all artifacts are uploaded to upstream release yet. Will try again later." + curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 9802903, + "description": "**Trigger Failed** \n**Reason:** '"${FAILURE_REASON}"' \n"}], + "username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }} + else + printf "\n## Trigger new build\n\n" >> $GITHUB_STEP_SUMMARY + echo "New sanitized version \`${EXT_RELEASE_SANITIZED}\` found; old version was \`${IMAGE_VERSION}\`. Triggering new build" >> $GITHUB_STEP_SUMMARY + if [[ "${artifacts_found}" == "true" ]]; then + echo "All artifacts seem to be uploaded." >> $GITHUB_STEP_SUMMARY + fi + response=$(curl -iX POST \ + https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-kasm/job/master/buildWithParameters?PACKAGE_CHECK=false \ + --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} | grep -i location | sed "s|^[L|l]ocation: \(.*\)|\1|") + echo "Jenkins [job queue url](${response%$'\r'})" >> $GITHUB_STEP_SUMMARY + echo "Sleeping 10 seconds until job starts" >> $GITHUB_STEP_SUMMARY + sleep 10 + buildurl=$(curl -s "${response%$'\r'}api/json" | jq -r '.executable.url') + buildurl="${buildurl%$'\r'}" + echo "Jenkins job [build url](${buildurl})" >> $GITHUB_STEP_SUMMARY + echo "Attempting to change the Jenkins job description" >> $GITHUB_STEP_SUMMARY + curl -iX POST \ + "${buildurl}submitDescription" \ + --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} \ + --data-urlencode "description=GHA external trigger https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ + --data-urlencode "Submit=Submit" + echo "**** Notifying Discord ****" + TRIGGER_REASON="A version change was detected for kasm tag latest. Old version:${IMAGE_VERSION} New version:${EXT_RELEASE_SANITIZED}" + curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 9802903, + "description": "**Build Triggered** \n**Reason:** '"${TRIGGER_REASON}"' \n**Build URL:** '"${buildurl}display/redirect"' \n"}], + "username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }} + fi fi diff --git a/.github/workflows/external_trigger_scheduler.yml b/.github/workflows/external_trigger_scheduler.yml index 5ac47cb..00529b1 100644 --- a/.github/workflows/external_trigger_scheduler.yml +++ b/.github/workflows/external_trigger_scheduler.yml @@ -2,42 +2,47 @@ name: External Trigger Scheduler on: schedule: - - cron: '03 * * * *' + - cron: '33 * * * *' workflow_dispatch: +permissions: + contents: read + jobs: external-trigger-scheduler: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.3 + - uses: actions/checkout@v4.1.1 with: fetch-depth: '0' - name: External Trigger Scheduler run: | - echo "**** Branches found: ****" - git for-each-ref --format='%(refname:short)' refs/remotes - echo "**** Pulling the yq docker image ****" - docker pull ghcr.io/linuxserver/yq - for br in $(git for-each-ref --format='%(refname:short)' refs/remotes) + printf "# External trigger scheduler for docker-kasm\n\n" >> $GITHUB_STEP_SUMMARY + printf "Found the branches:\n\n%s\n" "$(git for-each-ref --format='- %(refname:lstrip=3)' refs/remotes)" >> $GITHUB_STEP_SUMMARY + for br in $(git for-each-ref --format='%(refname:lstrip=3)' refs/remotes) do - br=$(echo "$br" | sed 's|origin/||g') - echo "**** Evaluating branch ${br} ****" - ls_branch=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-kasm/${br}/jenkins-vars.yml \ - | docker run --rm -i --entrypoint yq ghcr.io/linuxserver/yq -r .ls_branch) - if [ "$br" == "$ls_branch" ]; then - echo "**** Branch ${br} appears to be live; checking workflow. ****" + if [[ "${br}" == "HEAD" ]]; then + printf "\nSkipping %s.\n" ${br} >> $GITHUB_STEP_SUMMARY + continue + fi + printf "\n## Evaluating \`%s\`\n\n" ${br} >> $GITHUB_STEP_SUMMARY + ls_jenkins_vars=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-kasm/${br}/jenkins-vars.yml) + ls_branch=$(echo "${ls_jenkins_vars}" | yq -r '.ls_branch') + ls_trigger=$(echo "${ls_jenkins_vars}" | yq -r '.external_type') + if [[ "${br}" == "${ls_branch}" ]] && [[ "${ls_trigger}" != "os" ]]; then + echo "Branch appears to be live and trigger is not os; checking workflow." >> $GITHUB_STEP_SUMMARY if curl -sfX GET https://raw.githubusercontent.com/linuxserver/docker-kasm/${br}/.github/workflows/external_trigger.yml > /dev/null 2>&1; then - echo "**** Workflow exists. Triggering external trigger workflow for branch ${br} ****." + echo "Triggering external trigger workflow for branch." >> $GITHUB_STEP_SUMMARY curl -iX POST \ -H "Authorization: token ${{ secrets.CR_PAT }}" \ -H "Accept: application/vnd.github.v3+json" \ -d "{\"ref\":\"refs/heads/${br}\"}" \ https://api.github.com/repos/linuxserver/docker-kasm/actions/workflows/external_trigger.yml/dispatches else - echo "**** Workflow doesn't exist; skipping trigger. ****" + echo "Skipping branch due to no external trigger workflow present." >> $GITHUB_STEP_SUMMARY fi else - echo "**** ${br} appears to be a dev branch; skipping trigger. ****" + echo "Skipping branch due to being detected as dev branch or having no external version." >> $GITHUB_STEP_SUMMARY fi done diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml index 7dd6442..a64f2e2 100644 --- a/.github/workflows/greetings.yml +++ b/.github/workflows/greetings.yml @@ -2,12 +2,18 @@ name: Greetings on: [pull_request_target, issues] +permissions: + contents: read + jobs: greeting: + permissions: + issues: write + pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/first-interaction@v1 with: - issue-message: 'Thanks for opening your first issue here! Be sure to follow the [bug](https://github.com/linuxserver/docker-kasm/blob/master/.github/ISSUE_TEMPLATE/issue.bug.md) or [feature](https://github.com/linuxserver/docker-kasm/blob/master/.github/ISSUE_TEMPLATE/issue.feature.md) issue templates!' + issue-message: 'Thanks for opening your first issue here! Be sure to follow the relevant issue templates, or risk having this issue marked as invalid.' pr-message: 'Thanks for opening this pull request! Be sure to follow the [pull request template](https://github.com/linuxserver/docker-kasm/blob/master/.github/PULL_REQUEST_TEMPLATE.md)!' repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/package_trigger.yml b/.github/workflows/package_trigger.yml deleted file mode 100644 index b956bfe..0000000 --- a/.github/workflows/package_trigger.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Package Trigger Main - -on: - workflow_dispatch: - -jobs: - package-trigger-master: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2.3.3 - - - name: Package Trigger - if: github.ref == 'refs/heads/master' - run: | - if [ -n "${{ secrets.PAUSE_PACKAGE_TRIGGER_KASM_MASTER }}" ]; then - echo "**** Github secret PAUSE_PACKAGE_TRIGGER_KASM_MASTER is set; skipping trigger. ****" - exit 0 - fi - if [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-kasm/job/master/lastBuild/api/json | jq -r '.building') == "true" ]; then - echo "**** There already seems to be an active build on Jenkins; skipping package trigger ****" - exit 0 - fi - echo "**** Package trigger running off of master branch. To disable, set a Github secret named \"PAUSE_PACKAGE_TRIGGER_KASM_MASTER\". ****" - response=$(curl -iX POST \ - https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-kasm/job/master/buildWithParameters?PACKAGE_CHECK=true \ - --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} | grep -i location | sed "s|^[L|l]ocation: \(.*\)|\1|") - echo "**** Jenkins job queue url: ${response%$'\r'} ****" - echo "**** Sleeping 10 seconds until job starts ****" - sleep 10 - buildurl=$(curl -s "${response%$'\r'}api/json" | jq -r '.executable.url') - buildurl="${buildurl%$'\r'}" - echo "**** Jenkins job build url: ${buildurl} ****" - echo "**** Attempting to change the Jenkins job description ****" - curl -iX POST \ - "${buildurl}submitDescription" \ - --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} \ - --data-urlencode "description=GHA package trigger https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ - --data-urlencode "Submit=Submit" diff --git a/.github/workflows/package_trigger_scheduler.yml b/.github/workflows/package_trigger_scheduler.yml index 9a7744f..3c24c7e 100644 --- a/.github/workflows/package_trigger_scheduler.yml +++ b/.github/workflows/package_trigger_scheduler.yml @@ -2,49 +2,102 @@ name: Package Trigger Scheduler on: schedule: - - cron: '54 11 * * 0' + - cron: '31 21 * * 2' workflow_dispatch: +permissions: + contents: read + jobs: package-trigger-scheduler: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.3 + - uses: actions/checkout@v4.1.1 with: fetch-depth: '0' - name: Package Trigger Scheduler + env: + SKIP_PACKAGE_TRIGGER: ${{ vars.SKIP_PACKAGE_TRIGGER }} run: | - echo "**** Branches found: ****" - git for-each-ref --format='%(refname:short)' refs/remotes - echo "**** Pulling the yq docker image ****" - docker pull ghcr.io/linuxserver/yq - for br in $(git for-each-ref --format='%(refname:short)' refs/remotes) + printf "# Package trigger scheduler for docker-kasm\n\n" >> $GITHUB_STEP_SUMMARY + printf "Found the branches:\n\n%s\n" "$(git for-each-ref --format='- %(refname:lstrip=3)' refs/remotes)" >> $GITHUB_STEP_SUMMARY + for br in $(git for-each-ref --format='%(refname:lstrip=3)' refs/remotes) do - br=$(echo "$br" | sed 's|origin/||g') - echo "**** Evaluating branch ${br} ****" - ls_branch=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-kasm/${br}/jenkins-vars.yml \ - | docker run --rm -i --entrypoint yq ghcr.io/linuxserver/yq -r .ls_branch) - if [ "${br}" == "${ls_branch}" ]; then - echo "**** Branch ${br} appears to be live; checking workflow. ****" - if curl -sfX GET https://raw.githubusercontent.com/linuxserver/docker-kasm/${br}/.github/workflows/package_trigger.yml > /dev/null 2>&1; then - echo "**** Workflow exists. Triggering package trigger workflow for branch ${br}. ****" - triggered_branches="${triggered_branches}${br} " - curl -iX POST \ - -H "Authorization: token ${{ secrets.CR_PAT }}" \ - -H "Accept: application/vnd.github.v3+json" \ - -d "{\"ref\":\"refs/heads/${br}\"}" \ - https://api.github.com/repos/linuxserver/docker-kasm/actions/workflows/package_trigger.yml/dispatches - sleep 30 + if [[ "${br}" == "HEAD" ]]; then + printf "\nSkipping %s.\n" ${br} >> $GITHUB_STEP_SUMMARY + continue + fi + printf "\n## Evaluating \`%s\`\n\n" ${br} >> $GITHUB_STEP_SUMMARY + JENKINS_VARS=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-kasm/${br}/jenkins-vars.yml) + if ! curl -sfX GET https://raw.githubusercontent.com/linuxserver/docker-kasm/${br}/Jenkinsfile >/dev/null 2>&1; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> No Jenkinsfile found. Branch is either deprecated or is an early dev branch." >> $GITHUB_STEP_SUMMARY + skipped_branches="${skipped_branches}${br} " + elif [[ "${br}" == $(yq -r '.ls_branch' <<< "${JENKINS_VARS}") ]]; then + echo "Branch appears to be live; checking workflow." >> $GITHUB_STEP_SUMMARY + README_VARS=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-kasm/${br}/readme-vars.yml) + if [[ $(yq -r '.project_deprecation_status' <<< "${README_VARS}") == "true" ]]; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> Branch appears to be deprecated; skipping trigger." >> $GITHUB_STEP_SUMMARY + skipped_branches="${skipped_branches}${br} " + elif [[ $(yq -r '.skip_package_check' <<< "${JENKINS_VARS}") == "true" ]]; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> Skipping branch ${br} due to \`skip_package_check\` being set in \`jenkins-vars.yml\`." >> $GITHUB_STEP_SUMMARY + skipped_branches="${skipped_branches}${br} " + elif grep -q "^kasm_${br}" <<< "${SKIP_PACKAGE_TRIGGER}"; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> Github organizational variable \`SKIP_PACKAGE_TRIGGER\` contains \`kasm_${br}\`; skipping trigger." >> $GITHUB_STEP_SUMMARY + skipped_branches="${skipped_branches}${br} " + elif [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-kasm/job/${br}/lastBuild/api/json | jq -r '.building' 2>/dev/null) == "true" ]; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> There already seems to be an active build on Jenkins; skipping package trigger for ${br}" >> $GITHUB_STEP_SUMMARY + skipped_branches="${skipped_branches}${br} " else - echo "**** Workflow doesn't exist; skipping trigger. ****" + echo "> [!NOTE]" >> $GITHUB_STEP_SUMMARY + echo "> Triggering package trigger for branch ${br}" >> $GITHUB_STEP_SUMMARY + printf "> To disable, add \`kasm_%s\` into the Github organizational variable \`SKIP_PACKAGE_TRIGGER\`.\n\n" "${br}" >> $GITHUB_STEP_SUMMARY + triggered_branches="${triggered_branches}${br} " + response=$(curl -iX POST \ + https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-kasm/job/${br}/buildWithParameters?PACKAGE_CHECK=true \ + --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} | grep -i location | sed "s|^[L|l]ocation: \(.*\)|\1|") + if [[ -z "${response}" ]]; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> Jenkins build could not be triggered. Skipping branch." + continue + fi + echo "Jenkins [job queue url](${response%$'\r'})" >> $GITHUB_STEP_SUMMARY + echo "Sleeping 10 seconds until job starts" >> $GITHUB_STEP_SUMMARY + sleep 10 + buildurl=$(curl -s "${response%$'\r'}api/json" | jq -r '.executable.url') + buildurl="${buildurl%$'\r'}" + echo "Jenkins job [build url](${buildurl})" >> $GITHUB_STEP_SUMMARY + echo "Attempting to change the Jenkins job description" >> $GITHUB_STEP_SUMMARY + if ! curl -ifX POST \ + "${buildurl}submitDescription" \ + --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} \ + --data-urlencode "description=GHA package trigger https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ + --data-urlencode "Submit=Submit"; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> Unable to change the Jenkins job description." + fi + sleep 20 fi else - echo "**** ${br} appears to be a dev branch; skipping trigger. ****" + echo "Skipping branch ${br} due to being detected as dev branch." >> $GITHUB_STEP_SUMMARY fi done - echo "**** Package check build(s) triggered for branch(es): ${triggered_branches} ****" - echo "**** Notifying Discord ****" - curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 9802903, - "description": "**Package Check Build(s) Triggered for kasm** \n**Branch(es):** '"${triggered_branches}"' \n**Build URL:** '"https://ci.linuxserver.io/blue/organizations/jenkins/Docker-Pipeline-Builders%2Fdocker-kasm/activity/"' \n"}], - "username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }} + if [[ -n "${triggered_branches}" ]] || [[ -n "${skipped_branches}" ]]; then + if [[ -n "${triggered_branches}" ]]; then + NOTIFY_BRANCHES="**Triggered:** ${triggered_branches} \n" + NOTIFY_BUILD_URL="**Build URL:** https://ci.linuxserver.io/blue/organizations/jenkins/Docker-Pipeline-Builders%2Fdocker-kasm/activity/ \n" + echo "**** Package check build(s) triggered for branch(es): ${triggered_branches} ****" + fi + if [[ -n "${skipped_branches}" ]]; then + NOTIFY_BRANCHES="${NOTIFY_BRANCHES}**Skipped:** ${skipped_branches} \n" + fi + echo "**** Notifying Discord ****" + curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 9802903, + "description": "**Package Check Build(s) for kasm** \n'"${NOTIFY_BRANCHES}"''"${NOTIFY_BUILD_URL}"'"}], + "username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }} + fi diff --git a/.github/workflows/permissions.yml b/.github/workflows/permissions.yml new file mode 100644 index 0000000..02e1bdb --- /dev/null +++ b/.github/workflows/permissions.yml @@ -0,0 +1,12 @@ +name: Permission check +on: + pull_request_target: + paths: + - '**/run' + - '**/finish' + - '**/check' + - 'root/migrations/*' + +jobs: + permission_check: + uses: linuxserver/github-workflows/.github/workflows/init-svc-executable-permissions.yml@v1 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml deleted file mode 100644 index 3b3846e..0000000 --- a/.github/workflows/stale.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Mark stale issues and pull requests - -on: - schedule: - - cron: "30 1 * * *" - -jobs: - stale: - - runs-on: ubuntu-latest - - steps: - - uses: actions/stale@v3 - with: - stale-issue-message: "This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions." - stale-pr-message: "This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions." - stale-issue-label: 'no-issue-activity' - stale-pr-label: 'no-pr-activity' - days-before-stale: 30 - days-before-close: 365 - exempt-issue-labels: 'awaiting-approval,work-in-progress' - exempt-pr-labels: 'awaiting-approval,work-in-progress' - repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/Dockerfile b/Dockerfile index 94200f7..7ffec63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,48 +1,56 @@ -FROM ghcr.io/linuxserver/baseimage-alpine:3.16 +# syntax=docker/dockerfile:1 + +FROM ghcr.io/linuxserver/baseimage-ubuntu:noble # set version label ARG BUILD_DATE ARG KASM_VERSION +ARG VERSION LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" -LABEL maintainer="thelamer" +LABEL maintainer="thespad" # Env ENV DOCKER_TLS_CERTDIR="" +ENV TINI_SUBREAPER=true + +#Add needed nvidia environment variables for https://github.com/NVIDIA/nvidia-docker +ENV NVIDIA_DRIVER_CAPABILITIES="compute,graphics,video,utility" # Container setup RUN \ - echo "**** install build packages ****" && \ - apk add --no-cache --virtual=build-dependencies \ - alpine-sdk \ - npm && \ echo "**** install packages ****" && \ - apk add --no-cache \ - bash \ + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \ + echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu noble stable" > \ + /etc/apt/sources.list.d/docker.list && \ + curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ + && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ + sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ + tee /etc/apt/sources.list.d/nvidia-container-toolkit.list && \ + curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ + printf "Package: docker-ce docker-ce-cli docker-ce-rootless-extras\nPin: version 5:28.* \nPin-Priority: 1001" > /etc/apt/preferences.d/docker && \ + apt-get install -y --no-install-recommends \ btrfs-progs \ - ca-certificates \ - coreutils \ - curl \ - docker \ - docker-cli-compose \ + build-essential \ + containerd.io \ + docker-ce \ + docker-ce-cli \ + docker-compose-plugin \ e2fsprogs \ - e2fsprogs-extra \ - findutils \ fuse-overlayfs \ - ip6tables \ + iproute2 \ iptables \ - jq \ + lsof \ nodejs \ + nvidia-container-toolkit \ openssl \ pigz \ python3 \ - shadow-uidmap \ sudo \ - xfsprogs \ - xz \ - zfs && \ + uidmap \ + xfsprogs && \ echo "**** dind setup ****" && \ - addgroup -S dockremap && \ - adduser -S -G dockremap dockremap && \ + useradd -U dockremap && \ + usermod -G dockremap dockremap && \ echo 'dockremap:165536:65536' >> /etc/subuid && \ echo 'dockremap:165536:65536' >> /etc/subgid && \ curl -o \ @@ -56,6 +64,7 @@ RUN \ KASM_VERSION=$(curl -sX GET 'https://api.github.com/repos/kasmtech/kasm-install-wizard/releases/latest' \ | jq -r '.name'); \ fi && \ + echo "${KASM_VERSION}" > /version.txt && \ curl -o \ /tmp/wizard.tar.gz -L \ "https://github.com/kasmtech/kasm-install-wizard/archive/refs/tags/${KASM_VERSION}.tar.gz" && \ @@ -71,20 +80,39 @@ RUN \ tar xf \ /tmp/kasm.tar.gz -C \ / && \ + ALVERSION=$(cat /kasm_release/conf/database/seed_data/default_properties.yaml |awk '/alembic_version/ {print $2}') && \ + curl -o \ + /tmp/images.tar.gz -L \ + "https://kasm-ci.s3.amazonaws.com/${KASM_VERSION}-images-combined.tar.gz" && \ + tar xf \ + /tmp/images.tar.gz -C \ + / && \ + sed -i \ + '/alembic_version/s/.*/alembic_version: '${ALVERSION}'/' \ + /kasm_release/conf/database/seed_data/default_images_a* && \ + sed -i 's/-N -e -H/-N -B -e -H/g' /kasm_release/upgrade.sh && \ + echo "exit 0" > /kasm_release/install_dependencies.sh && \ + /kasm_release/bin/utils/yq_$(uname -m) -i \ + '.services.proxy.volumes += "/kasm_release/www/img/thumbnails:/srv/www/img/thumbnails"' \ + /kasm_release/docker/docker-compose-all.yaml && \ echo "**** copy assets ****" && \ cp \ - /kasm_release/www/img/thumbnails/*.png \ + /kasm_release/www/img/thumbnails/*.png /kasm_release/www/img/thumbnails/*.svg \ /wizard/public/img/thumbnails/ && \ cp \ /kasm_release/conf/database/seed_data/default_images_a* \ /wizard/ && \ + useradd -u 70 kasm_db && \ + useradd kasm && \ + printf "Linuxserver.io version: ${VERSION}\nBuild-date: ${BUILD_DATE}" > /build_version && \ echo "**** cleanup ****" && \ - apk del --purge \ - build-dependencies && \ + apt-get remove -y g++ gcc make && \ + apt-get -y autoremove && \ + apt-get clean && \ rm -rf \ - /root/.npm \ - /root/.cache \ - /tmp/* + /tmp/* \ + /var/lib/apt/lists/* \ + /var/tmp/* # add init files COPY root/ / diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index cb8b417..2ffb5ee 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -1,48 +1,56 @@ -FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.16 +# syntax=docker/dockerfile:1 + +FROM ghcr.io/linuxserver/baseimage-ubuntu:arm64v8-noble # set version label ARG BUILD_DATE ARG KASM_VERSION +ARG VERSION LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" -LABEL maintainer="thelamer" +LABEL maintainer="thespad" # Env ENV DOCKER_TLS_CERTDIR="" +ENV TINI_SUBREAPER=true + +#Add needed nvidia environment variables for https://github.com/NVIDIA/nvidia-docker +ENV NVIDIA_DRIVER_CAPABILITIES="compute,graphics,video,utility" # Container setup RUN \ - echo "**** install build packages ****" && \ - apk add --no-cache --virtual=build-dependencies \ - alpine-sdk \ - npm && \ echo "**** install packages ****" && \ - apk add --no-cache \ - bash \ + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \ + echo "deb [arch=arm64] https://download.docker.com/linux/ubuntu noble stable" > \ + /etc/apt/sources.list.d/docker.list && \ + curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ + && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ + sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ + tee /etc/apt/sources.list.d/nvidia-container-toolkit.list && \ + curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ + printf "Package: docker-ce docker-ce-cli docker-ce-rootless-extras\nPin: version 5:28.* \nPin-Priority: 1001" > /etc/apt/preferences.d/docker && \ + apt-get install -y --no-install-recommends \ btrfs-progs \ - ca-certificates \ - coreutils \ - curl \ - docker \ - docker-cli-compose \ + build-essential \ + containerd.io \ + docker-ce \ + docker-ce-cli \ + docker-compose-plugin \ e2fsprogs \ - e2fsprogs-extra \ - findutils \ fuse-overlayfs \ - ip6tables \ + iproute2 \ iptables \ - jq \ + lsof \ nodejs \ + nvidia-container-toolkit \ openssl \ pigz \ python3 \ - shadow-uidmap \ sudo \ - xfsprogs \ - xz \ - zfs && \ + uidmap \ + xfsprogs && \ echo "**** dind setup ****" && \ - addgroup -S dockremap && \ - adduser -S -G dockremap dockremap && \ + useradd -U dockremap && \ + usermod -G dockremap dockremap && \ echo 'dockremap:165536:65536' >> /etc/subuid && \ echo 'dockremap:165536:65536' >> /etc/subgid && \ curl -o \ @@ -56,6 +64,7 @@ RUN \ KASM_VERSION=$(curl -sX GET 'https://api.github.com/repos/kasmtech/kasm-install-wizard/releases/latest' \ | jq -r '.name'); \ fi && \ + echo "${KASM_VERSION}" > /version.txt && \ curl -o \ /tmp/wizard.tar.gz -L \ "https://github.com/kasmtech/kasm-install-wizard/archive/refs/tags/${KASM_VERSION}.tar.gz" && \ @@ -71,20 +80,39 @@ RUN \ tar xf \ /tmp/kasm.tar.gz -C \ / && \ + ALVERSION=$(cat /kasm_release/conf/database/seed_data/default_properties.yaml |awk '/alembic_version/ {print $2}') && \ + curl -o \ + /tmp/images.tar.gz -L \ + "https://kasm-ci.s3.amazonaws.com/${KASM_VERSION}-images-combined.tar.gz" && \ + tar xf \ + /tmp/images.tar.gz -C \ + / && \ + sed -i \ + '/alembic_version/s/.*/alembic_version: '${ALVERSION}'/' \ + /kasm_release/conf/database/seed_data/default_images_a* && \ + sed -i 's/-N -e -H/-N -B -e -H/g' /kasm_release/upgrade.sh && \ + echo "exit 0" > /kasm_release/install_dependencies.sh && \ + /kasm_release/bin/utils/yq_$(uname -m) -i \ + '.services.proxy.volumes += "/kasm_release/www/img/thumbnails:/srv/www/img/thumbnails"' \ + /kasm_release/docker/docker-compose-all.yaml && \ echo "**** copy assets ****" && \ cp \ - /kasm_release/www/img/thumbnails/*.png \ + /kasm_release/www/img/thumbnails/*.png /kasm_release/www/img/thumbnails/*.svg \ /wizard/public/img/thumbnails/ && \ cp \ /kasm_release/conf/database/seed_data/default_images_a* \ /wizard/ && \ + useradd -u 70 kasm_db && \ + useradd kasm && \ + printf "Linuxserver.io version: ${VERSION}\nBuild-date: ${BUILD_DATE}" > /build_version && \ echo "**** cleanup ****" && \ - apk del --purge \ - build-dependencies && \ + apt-get remove -y g++ gcc make && \ + apt-get -y autoremove && \ + apt-get clean && \ rm -rf \ - /root/.npm \ - /root/.cache \ - /tmp/* + /tmp/* \ + /var/lib/apt/lists/* \ + /var/tmp/* # add init files COPY root/ / diff --git a/Dockerfile.armhf b/Dockerfile.armhf deleted file mode 100644 index 195ac5f..0000000 --- a/Dockerfile.armhf +++ /dev/null @@ -1,10 +0,0 @@ -FROM ghcr.io/linuxserver/baseimage-alpine:arm32v7-3.16 - -# set version label -ARG BUILD_DATE -ARG KASM_VERSION -LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" -LABEL maintainer="thelamer" - -# add init files -COPY root-armhf/ / diff --git a/Jenkinsfile b/Jenkinsfile index cef42db..879ff02 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -8,7 +8,7 @@ pipeline { } // Input to determine if this is a package check parameters { - string(defaultValue: 'false', description: 'package check run', name: 'PACKAGE_CHECK') + string(defaultValue: 'false', description: 'package check run', name: 'PACKAGE_CHECK') } // Configuration for the variables used for this specific repo environment { @@ -16,8 +16,9 @@ pipeline { GITHUB_TOKEN=credentials('498b4638-2d02-4ce5-832d-8a57d01d97ab') GITLAB_TOKEN=credentials('b6f0f1dd-6952-4cf6-95d1-9c06380283f0') GITLAB_NAMESPACE=credentials('gitlab-namespace-id') - SCARF_TOKEN=credentials('scarf_api_key') - EXT_GIT_BRANCH = 'develop' + DOCKERHUB_TOKEN=credentials('docker-hub-ci-pat') + QUAYIO_API_TOKEN=credentials('quayio-repo-api-token') + GIT_SIGNING_KEY=credentials('484fbca6-9a4f-455e-b9e3-97ac98785f5f') EXT_USER = 'kasmtech' EXT_REPO = 'kasm-install-wizard' BUILD_VERSION_ARG = 'KASM_VERSION' @@ -27,25 +28,57 @@ pipeline { DOCKERHUB_IMAGE = 'linuxserver/kasm' DEV_DOCKERHUB_IMAGE = 'lsiodev/kasm' PR_DOCKERHUB_IMAGE = 'lspipepr/kasm' - DIST_IMAGE = 'alpine' + DIST_IMAGE = 'ubuntu' MULTIARCH='true' CI='true' - CI_WEB='true' + CI_WEB='false' CI_PORT='3000' CI_SSL='true' CI_DELAY='120' - CI_DOCKERENV='TEST=true' - CI_AUTH='user:password' + CI_DOCKERENV='' + CI_AUTH='' CI_WEBPATH='' } stages { + stage("Set git config"){ + steps{ + sh '''#!/bin/bash + cat ${GIT_SIGNING_KEY} > /config/.ssh/id_sign + chmod 600 /config/.ssh/id_sign + ssh-keygen -y -f /config/.ssh/id_sign > /config/.ssh/id_sign.pub + echo "Using $(ssh-keygen -lf /config/.ssh/id_sign) to sign commits" + git config --global gpg.format ssh + git config --global user.signingkey /config/.ssh/id_sign + git config --global commit.gpgsign true + ''' + } + } // Setup all the basic environment variables needed for the build stage("Set ENV Variables base"){ steps{ + echo "Running on node: ${NODE_NAME}" + sh '''#! /bin/bash + echo "Pruning builder" + docker builder prune -f --builder container || : + containers=$(docker ps -q) + if [[ -n "${containers}" ]]; then + BUILDX_CONTAINER_ID=$(docker ps -qf 'name=buildx_buildkit') + for container in ${containers}; do + if [[ "${container}" == "${BUILDX_CONTAINER_ID}" ]]; then + echo "skipping buildx container in docker stop" + else + echo "Stopping container ${container}" + docker stop ${container} + fi + done + fi + docker system prune -f --volumes || : + docker image prune -af || : + ''' script{ env.EXIT_STATUS = '' env.LS_RELEASE = sh( - script: '''docker run --rm ghcr.io/linuxserver/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' || : ''', + script: '''docker run --rm quay.io/skopeo/stable:v1 inspect docker://ghcr.io/${LS_USER}/${CONTAINER_NAME}: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' ''', @@ -56,11 +89,20 @@ pipeline { env.COMMIT_SHA = sh( script: '''git rev-parse HEAD''', returnStdout: true).trim() + env.GH_DEFAULT_BRANCH = sh( + script: '''git remote show origin | grep "HEAD branch:" | sed 's|.*HEAD branch: ||' ''', + 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.TEMPLATED_FILES = 'Jenkinsfile README.md LICENSE .editorconfig ./.github/CONTRIBUTING.md ./.github/FUNDING.yml ./.github/ISSUE_TEMPLATE/config.yml ./.github/ISSUE_TEMPLATE/issue.bug.md ./.github/ISSUE_TEMPLATE/issue.feature.md ./.github/PULL_REQUEST_TEMPLATE.md ./.github/workflows/external_trigger_scheduler.yml ./.github/workflows/greetings.yml ./.github/workflows/package_trigger_scheduler.yml ./.github/workflows/stale.yml ./.github/workflows/external_trigger.yml ./.github/workflows/package_trigger.yml' + env.TEMPLATED_FILES = 'Jenkinsfile README.md LICENSE .editorconfig ./.github/CONTRIBUTING.md ./.github/FUNDING.yml ./.github/ISSUE_TEMPLATE/config.yml ./.github/ISSUE_TEMPLATE/issue.bug.yml ./.github/ISSUE_TEMPLATE/issue.feature.yml ./.github/PULL_REQUEST_TEMPLATE.md ./.github/workflows/external_trigger_scheduler.yml ./.github/workflows/greetings.yml ./.github/workflows/package_trigger_scheduler.yml ./.github/workflows/call_issue_pr_tracker.yml ./.github/workflows/call_issues_cron.yml ./.github/workflows/permissions.yml ./.github/workflows/external_trigger.yml' + if ( env.SYFT_IMAGE_TAG == null ) { + env.SYFT_IMAGE_TAG = 'latest' + } } + echo "Using syft image tag ${SYFT_IMAGE_TAG}" + sh '''#! /bin/bash + echo "The default github branch detected as ${GH_DEFAULT_BRANCH}" ''' script{ env.LS_RELEASE_NUMBER = sh( script: '''echo ${LS_RELEASE} |sed 's/^.*-ls//g' ''', @@ -125,7 +167,7 @@ pipeline { steps{ script{ env.EXT_RELEASE_CLEAN = sh( - script: '''echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g' ''', + script: '''echo ${EXT_RELEASE} | sed 's/[~,%@+;:/ ]//g' ''', returnStdout: true).trim() def semver = env.EXT_RELEASE_CLEAN =~ /(\d+)\.(\d+)\.(\d+)/ @@ -143,7 +185,7 @@ pipeline { } if (env.SEMVER != null) { - if (BRANCH_NAME != "master" && BRANCH_NAME != "main") { + if (BRANCH_NAME != "${env.GH_DEFAULT_BRANCH}") { env.SEMVER = "${env.SEMVER}-${BRANCH_NAME}" } println("SEMVER: ${env.SEMVER}") @@ -167,13 +209,15 @@ pipeline { env.GITLABIMAGE = 'registry.gitlab.com/linuxserver.io/' + env.LS_REPO + '/' + env.CONTAINER_NAME env.QUAYIMAGE = 'quay.io/linuxserver.io/' + env.CONTAINER_NAME 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 + env.CI_TAGS = 'amd64-' + 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.VERSION_TAG = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER env.META_TAG = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN + env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache' + env.CITEST_IMAGETAG = 'latest' } } } @@ -190,7 +234,7 @@ pipeline { env.GITLABIMAGE = 'registry.gitlab.com/linuxserver.io/' + env.LS_REPO + '/lsiodev-' + env.CONTAINER_NAME env.QUAYIMAGE = 'quay.io/linuxserver.io/lsiodev-' + env.CONTAINER_NAME 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 + env.CI_TAGS = 'amd64-' + 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 } @@ -198,6 +242,8 @@ pipeline { env.META_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DEV_DOCKERHUB_IMAGE + '/tags/' + env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache' + env.CITEST_IMAGETAG = 'develop' } } } @@ -213,15 +259,17 @@ pipeline { env.GITLABIMAGE = 'registry.gitlab.com/linuxserver.io/' + env.LS_REPO + '/lspipepr-' + env.CONTAINER_NAME env.QUAYIMAGE = 'quay.io/linuxserver.io/lspipepr-' + env.CONTAINER_NAME 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 + env.CI_TAGS = 'amd64-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '-pr-' + env.PULL_REQUEST + '|arm64v8-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '-pr-' + env.PULL_REQUEST } else { - env.CI_TAGS = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST + env.CI_TAGS = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '-pr-' + env.PULL_REQUEST } - env.VERSION_TAG = 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.VERSION_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '-pr-' + env.PULL_REQUEST + env.META_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '-pr-' + env.PULL_REQUEST env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN 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/' + env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache' + env.CITEST_IMAGETAG = 'develop' } } } @@ -238,19 +286,18 @@ pipeline { script{ env.SHELLCHECK_URL = 'https://ci-tests.linuxserver.io/' + env.IMAGE + '/' + env.META_TAG + '/shellcheck-result.xml' } - sh '''curl -sL https://raw.githubusercontent.com/linuxserver/docker-shellcheck/master/checkrun.sh | /bin/bash''' + sh '''curl -sL https://raw.githubusercontent.com/linuxserver/docker-jenkins-builder/master/checkrun.sh | /bin/bash''' sh '''#! /bin/bash - set -e - docker pull ghcr.io/linuxserver/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=\"${S3_SECRET}\" \ - -e ACCESS_KEY=\"${S3_KEY}\" \ - -t ghcr.io/linuxserver/lsiodev-spaces-file-upload:latest \ - python /upload.py''' + -v ${WORKSPACE}:/mnt \ + -e AWS_ACCESS_KEY_ID=\"${S3_KEY}\" \ + -e AWS_SECRET_ACCESS_KEY=\"${S3_SECRET}\" \ + ghcr.io/linuxserver/baseimage-alpine:3 s6-envdir -fn -- /var/run/s6/container_environment /bin/bash -c "\ + apk add --no-cache python3 && \ + python3 -m venv /lsiopy && \ + pip install --no-cache-dir -U pip && \ + pip install --no-cache-dir s3cmd && \ + s3cmd put --no-preserve --acl-public -m text/xml /mnt/shellcheck-result.xml s3://ci-tests.linuxserver.io/${IMAGE}/${META_TAG}/shellcheck-result.xml" || :''' } } } @@ -268,8 +315,15 @@ pipeline { set -e TEMPDIR=$(mktemp -d) docker pull ghcr.io/linuxserver/jenkins-builder:latest - docker run --rm -e CONTAINER_NAME=${CONTAINER_NAME} -e GITHUB_BRANCH=master -v ${TEMPDIR}:/ansible/jenkins ghcr.io/linuxserver/jenkins-builder:latest - # Stage 1 - Jenkinsfile update + # Cloned repo paths for templating: + # ${TEMPDIR}/docker-${CONTAINER_NAME}: Cloned branch master of ${LS_USER}/${LS_REPO} for running the jenkins builder on + # ${TEMPDIR}/repo/${LS_REPO}: Cloned branch master of ${LS_USER}/${LS_REPO} for commiting various templated file changes and pushing back to Github + # ${TEMPDIR}/docs/docker-documentation: Cloned docs repo for pushing docs updates to Github + # ${TEMPDIR}/unraid/docker-templates: Cloned docker-templates repo to check for logos + # ${TEMPDIR}/unraid/templates: Cloned templates repo for commiting unraid template changes and pushing back to Github + git clone --branch master --depth 1 https://github.com/${LS_USER}/${LS_REPO}.git ${TEMPDIR}/docker-${CONTAINER_NAME} + docker run --rm -v ${TEMPDIR}/docker-${CONTAINER_NAME}:/tmp -e LOCAL=true -e PUID=$(id -u) -e PGID=$(id -g) ghcr.io/linuxserver/jenkins-builder:latest + echo "Starting Stage 1 - Jenkinsfile update" if [[ "$(md5sum Jenkinsfile | awk '{ print $1 }')" != "$(md5sum ${TEMPDIR}/docker-${CONTAINER_NAME}/Jenkinsfile | awk '{ print $1 }')" ]]; then mkdir -p ${TEMPDIR}/repo git clone https://github.com/${LS_USER}/${LS_REPO}.git ${TEMPDIR}/repo/${LS_REPO} @@ -278,16 +332,17 @@ pipeline { cp ${TEMPDIR}/docker-${CONTAINER_NAME}/Jenkinsfile ${TEMPDIR}/repo/${LS_REPO}/ git add Jenkinsfile git commit -m 'Bot Updating Templated Files' - git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git --all + git pull https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git master + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git master echo "true" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} - echo "Updating Jenkinsfile" + echo "Updating Jenkinsfile and exiting build, new one will trigger based on commit" rm -Rf ${TEMPDIR} exit 0 else echo "Jenkinsfile is up to date." fi - # Stage 2 - Delete old templates - OLD_TEMPLATES=".github/ISSUE_TEMPLATE.md" + echo "Starting Stage 2 - Delete old templates" + OLD_TEMPLATES=".github/ISSUE_TEMPLATE.md .github/ISSUE_TEMPLATE/issue.bug.md .github/ISSUE_TEMPLATE/issue.feature.md .github/workflows/call_invalid_helper.yml .github/workflows/stale.yml .github/workflows/package_trigger.yml" for i in ${OLD_TEMPLATES}; do if [[ -f "${i}" ]]; then TEMPLATES_TO_DELETE="${i} ${TEMPLATES_TO_DELETE}" @@ -302,15 +357,45 @@ pipeline { git rm "${i}" done git commit -m 'Bot Updating Templated Files' - git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git --all + git pull https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git master + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git master echo "true" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} - echo "Deleting old templates" + echo "Deleting old/deprecated templates and exiting build, new one will trigger based on commit" rm -Rf ${TEMPDIR} exit 0 else echo "No templates to delete" fi - # Stage 3 - Update templates + echo "Starting Stage 2.5 - Update init diagram" + if ! grep -q 'init_diagram:' readme-vars.yml; then + echo "Adding the key 'init_diagram' to readme-vars.yml" + sed -i '\\|^#.*changelog.*$|d' readme-vars.yml + sed -i 's|^changelogs:|# init diagram\\ninit_diagram:\\n\\n# changelog\\nchangelogs:|' readme-vars.yml + fi + mkdir -p ${TEMPDIR}/d2 + docker run --rm -v ${TEMPDIR}/d2:/output -e PUID=$(id -u) -e PGID=$(id -g) -e RAW="true" ghcr.io/linuxserver/d2-builder:latest ${CONTAINER_NAME}:latest + ls -al ${TEMPDIR}/d2 + yq -ei ".init_diagram |= load_str(\\"${TEMPDIR}/d2/${CONTAINER_NAME}-latest.d2\\")" readme-vars.yml + if [[ $(md5sum readme-vars.yml | cut -c1-8) != $(md5sum ${TEMPDIR}/docker-${CONTAINER_NAME}/readme-vars.yml | cut -c1-8) ]]; then + echo "'init_diagram' has been updated. Updating repo and exiting build, new one will trigger based on commit." + mkdir -p ${TEMPDIR}/repo + git clone https://github.com/${LS_USER}/${LS_REPO}.git ${TEMPDIR}/repo/${LS_REPO} + cd ${TEMPDIR}/repo/${LS_REPO} + git checkout -f master + cp ${WORKSPACE}/readme-vars.yml ${TEMPDIR}/repo/${LS_REPO}/readme-vars.yml + git add readme-vars.yml + git commit -m 'Bot Updating Templated Files' + git pull https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git master + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git master + echo "true" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} + echo "Updating templates and exiting build, new one will trigger based on commit" + rm -Rf ${TEMPDIR} + exit 0 + else + echo "false" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} + echo "Init diagram is unchanged" + fi + echo "Starting Stage 3 - Update templates" CURRENTHASH=$(grep -hs ^ ${TEMPLATED_FILES} | md5sum | cut -c1-8) cd ${TEMPDIR}/docker-${CONTAINER_NAME} NEWHASH=$(grep -hs ^ ${TEMPLATED_FILES} | md5sum | cut -c1-8) @@ -323,47 +408,70 @@ pipeline { mkdir -p ${TEMPDIR}/repo/${LS_REPO}/.github/workflows mkdir -p ${TEMPDIR}/repo/${LS_REPO}/.github/ISSUE_TEMPLATE cp --parents ${TEMPLATED_FILES} ${TEMPDIR}/repo/${LS_REPO}/ || : + cp --parents readme-vars.yml ${TEMPDIR}/repo/${LS_REPO}/ || : cd ${TEMPDIR}/repo/${LS_REPO}/ if ! grep -q '.jenkins-external' .gitignore 2>/dev/null; then echo ".jenkins-external" >> .gitignore git add .gitignore fi - git add ${TEMPLATED_FILES} + git add readme-vars.yml ${TEMPLATED_FILES} git commit -m 'Bot Updating Templated Files' - git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git --all + git pull https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git master + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git master echo "true" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} + echo "Updating templates and exiting build, new one will trigger based on commit" + rm -Rf ${TEMPDIR} + exit 0 else echo "false" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} + echo "No templates to update" fi - mkdir -p ${TEMPDIR}/gitbook - git clone https://github.com/linuxserver/docker-documentation.git ${TEMPDIR}/gitbook/docker-documentation - if [[ ("${BRANCH_NAME}" == "master") || ("${BRANCH_NAME}" == "main") ]] && [[ (! -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}/docker-${CONTAINER_NAME}/.jenkins-external/docker-${CONTAINER_NAME}.md | awk '{ print $1 }')") ]]; then - cp ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/docker-${CONTAINER_NAME}.md ${TEMPDIR}/gitbook/docker-documentation/images/ - cd ${TEMPDIR}/gitbook/docker-documentation/ - git add images/docker-${CONTAINER_NAME}.md + echo "Starting Stage 4 - External repo updates: Docs, Unraid Template and Readme Sync to Docker Hub" + mkdir -p ${TEMPDIR}/docs + git clone --depth=1 https://github.com/linuxserver/docker-documentation.git ${TEMPDIR}/docs/docker-documentation + if [[ "${BRANCH_NAME}" == "${GH_DEFAULT_BRANCH}" ]] && [[ (! -f ${TEMPDIR}/docs/docker-documentation/docs/images/docker-${CONTAINER_NAME}.md) || ("$(md5sum ${TEMPDIR}/docs/docker-documentation/docs/images/docker-${CONTAINER_NAME}.md | awk '{ print $1 }')" != "$(md5sum ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/docker-${CONTAINER_NAME}.md | awk '{ print $1 }')") ]]; then + cp ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/docker-${CONTAINER_NAME}.md ${TEMPDIR}/docs/docker-documentation/docs/images/ + cd ${TEMPDIR}/docs/docker-documentation + GH_DOCS_DEFAULT_BRANCH=$(git remote show origin | grep "HEAD branch:" | sed 's|.*HEAD branch: ||') + git add docs/images/docker-${CONTAINER_NAME}.md + echo "Updating docs repo" git commit -m 'Bot Updating Documentation' - git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/linuxserver/docker-documentation.git --all + git pull https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/linuxserver/docker-documentation.git ${GH_DOCS_DEFAULT_BRANCH} --rebase + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/linuxserver/docker-documentation.git ${GH_DOCS_DEFAULT_BRANCH} || \ + (MAXWAIT="10" && echo "Push to docs failed, trying again in ${MAXWAIT} seconds" && \ + sleep $((RANDOM % MAXWAIT)) && \ + git pull https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/linuxserver/docker-documentation.git ${GH_DOCS_DEFAULT_BRANCH} --rebase && \ + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/linuxserver/docker-documentation.git ${GH_DOCS_DEFAULT_BRANCH}) + else + echo "Docs update not needed, skipping" fi - mkdir -p ${TEMPDIR}/unraid - git clone https://github.com/linuxserver/docker-templates.git ${TEMPDIR}/unraid/docker-templates - git clone https://github.com/linuxserver/templates.git ${TEMPDIR}/unraid/templates - if [[ -f ${TEMPDIR}/unraid/docker-templates/linuxserver.io/img/${CONTAINER_NAME}-logo.png ]]; then - sed -i "s|master/linuxserver.io/img/linuxserver-ls-logo.png|master/linuxserver.io/img/${CONTAINER_NAME}-logo.png|" ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/${CONTAINER_NAME}.xml - fi - if [[ ("${BRANCH_NAME}" == "master") || ("${BRANCH_NAME}" == "main") ]] && [[ (! -f ${TEMPDIR}/unraid/templates/unraid/${CONTAINER_NAME}.xml) || ("$(md5sum ${TEMPDIR}/unraid/templates/unraid/${CONTAINER_NAME}.xml | awk '{ print $1 }')" != "$(md5sum ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/${CONTAINER_NAME}.xml | awk '{ print $1 }')") ]]; then - cd ${TEMPDIR}/unraid/templates/ - if grep -wq "${CONTAINER_NAME}" ${TEMPDIR}/unraid/templates/unraid/ignore.list; then - echo "Image is on the ignore list, marking Unraid template as deprecated" - cp ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/${CONTAINER_NAME}.xml ${TEMPDIR}/unraid/templates/unraid/ - git add -u unraid/${CONTAINER_NAME}.xml - git mv unraid/${CONTAINER_NAME}.xml unraid/deprecated/${CONTAINER_NAME}.xml || : - git commit -m 'Bot Moving Deprecated Unraid Template' || : + if [[ "${BRANCH_NAME}" == "${GH_DEFAULT_BRANCH}" ]]; then + if [[ $(cat ${TEMPDIR}/docker-${CONTAINER_NAME}/README.md | wc -m) -gt 25000 ]]; then + echo "Readme is longer than 25,000 characters. Syncing the lite version to Docker Hub" + DH_README_SYNC_PATH="${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/README.lite" else - cp ${TEMPDIR}/docker-${CONTAINER_NAME}/.jenkins-external/${CONTAINER_NAME}.xml ${TEMPDIR}/unraid/templates/unraid/ - git add unraid/${CONTAINER_NAME}.xml - git commit -m 'Bot Updating Unraid Template' + echo "Syncing readme to Docker Hub" + DH_README_SYNC_PATH="${TEMPDIR}/docker-${CONTAINER_NAME}/README.md" fi - git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/linuxserver/templates.git --all + if curl -s https://hub.docker.com/v2/namespaces/${DOCKERHUB_IMAGE%%/*}/repositories/${DOCKERHUB_IMAGE##*/}/tags | jq -r '.message' | grep -q 404; then + echo "Docker Hub endpoint doesn't exist. Creating endpoint first." + DH_TOKEN=$(curl -d '{"username":"linuxserverci", "password":"'${DOCKERHUB_TOKEN}'"}' -H "Content-Type: application/json" -X POST https://hub.docker.com/v2/users/login | jq -r '.token') + curl -s \ + -H "Authorization: JWT ${DH_TOKEN}" \ + -H "Content-Type: application/json" \ + -X POST \ + -d '{"name":"'${DOCKERHUB_IMAGE##*/}'", "namespace":"'${DOCKERHUB_IMAGE%%/*}'"}' \ + https://hub.docker.com/v2/repositories/ || : + fi + DH_TOKEN=$(curl -d '{"username":"linuxserverci", "password":"'${DOCKERHUB_TOKEN}'"}' -H "Content-Type: application/json" -X POST https://hub.docker.com/v2/users/login | jq -r '.token') + curl -s \ + -H "Authorization: JWT ${DH_TOKEN}" \ + -H "Content-Type: application/json" \ + -X PATCH \ + -d "{\\"full_description\\":$(jq -Rsa . ${DH_README_SYNC_PATH})}" \ + https://hub.docker.com/v2/repositories/${DOCKERHUB_IMAGE} || : + else + echo "Not the default Github branch. Skipping readme sync to Docker Hub." fi rm -Rf ${TEMPDIR}''' script{ @@ -389,54 +497,48 @@ pipeline { } } } + // If this is a master build check the S6 service file perms + stage("Check S6 Service file Permissions"){ + when { + branch "master" + environment name: 'CHANGE_ID', value: '' + environment name: 'EXIT_STATUS', value: '' + } + steps { + script{ + sh '''#! /bin/bash + WRONG_PERM=$(find ./ -path "./.git" -prune -o \\( -name "run" -o -name "finish" -o -name "check" \\) -not -perm -u=x,g=x,o=x -print) + if [[ -n "${WRONG_PERM}" ]]; then + echo "The following S6 service files are missing the executable bit; canceling the faulty build: ${WRONG_PERM}" + exit 1 + else + echo "S6 service file perms look good." + fi ''' + } + } + } /* ####################### - GitLab Mirroring + GitLab Mirroring and Quay.io Repo Visibility ####################### */ - // Ping into Gitlab to mirror this repo and have a registry endpoint - stage("GitLab Mirror"){ + // Ping into Gitlab to mirror this repo and have a registry endpoint & mark this repo on Quay.io as public + stage("GitLab Mirror and Quay.io Visibility"){ when { environment name: 'EXIT_STATUS', value: '' } steps{ sh '''curl -H "Content-Type: application/json" -H "Private-Token: ${GITLAB_TOKEN}" -X POST https://gitlab.com/api/v4/projects \ - -d '{"namespace_id":'${GITLAB_NAMESPACE}',\ - "name":"'${LS_REPO}'", - "mirror":true,\ - "import_url":"https://github.com/linuxserver/'${LS_REPO}'.git",\ - "issues_access_level":"disabled",\ - "merge_requests_access_level":"disabled",\ - "repository_access_level":"enabled",\ - "visibility":"public"}' ''' - } - } - /* ####################### - Scarf.sh package registry - ####################### */ - // Add package to Scarf.sh and set permissions - stage("Scarf.sh package registry"){ - when { - branch "master" - environment name: 'EXIT_STATUS', value: '' - } - steps{ - sh '''#! /bin/bash - set -e - PACKAGE_UUID=$(curl -X GET -H "Authorization: Bearer ${SCARF_TOKEN}" https://scarf.sh/api/v1/organizations/linuxserver-ci/packages | jq -r '.[] | select(.name=="linuxserver/kasm") | .uuid') - if [ -z "${PACKAGE_UUID}" ]; then - echo "Adding package to Scarf.sh" - curl -sX POST https://scarf.sh/api/v1/organizations/linuxserver-ci/packages \ - -H "Authorization: Bearer ${SCARF_TOKEN}" \ - -H "Content-Type: application/json" \ - -d '{"name":"linuxserver/kasm",\ - "shortDescription":"example description",\ - "libraryType":"docker",\ - "website":"https://github.com/linuxserver/docker-kasm",\ - "backendUrl":"https://ghcr.io/linuxserver/kasm",\ - "publicUrl":"https://lscr.io/linuxserver/kasm"}' || : - else - echo "Package already exists on Scarf.sh" - fi - ''' + -d '{"namespace_id":'${GITLAB_NAMESPACE}',\ + "name":"'${LS_REPO}'", + "mirror":true,\ + "import_url":"https://github.com/linuxserver/'${LS_REPO}'.git",\ + "issues_access_level":"disabled",\ + "merge_requests_access_level":"disabled",\ + "repository_access_level":"enabled",\ + "visibility":"public"}' ''' + sh '''curl -H "Private-Token: ${GITLAB_TOKEN}" -X PUT "https://gitlab.com/api/v4/projects/Linuxserver.io%2F${LS_REPO}" \ + -d "mirror=true&import_url=https://github.com/linuxserver/${LS_REPO}.git" ''' + sh '''curl -H "Content-Type: application/json" -H "Authorization: Bearer ${QUAYIO_API_TOKEN}" -X POST "https://quay.io/api/v1/repository${QUAYIMAGE/quay.io/}/changevisibility" \ + -d '{"visibility":"public"}' ||: ''' } } /* ############### @@ -452,7 +554,8 @@ pipeline { } steps { echo "Running on node: ${NODE_NAME}" - sh "docker build \ + sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile" + sh "docker buildx build \ --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ --label \"org.opencontainers.image.authors=linuxserver.io\" \ --label \"org.opencontainers.image.url=https://github.com/linuxserver/docker-kasm/packages\" \ @@ -465,8 +568,46 @@ pipeline { --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ --label \"org.opencontainers.image.title=Kasm\" \ --label \"org.opencontainers.image.description=[Kasm](https://www.kasmweb.com/?utm_campaign=LinuxServer&utm_source=listing) Workspaces is a docker container streaming platform for delivering browser-based access to desktops, applications, and web services. Kasm uses devops-enabled Containerized Desktop Infrastructure (CDI) to create on-demand, disposable, docker containers that are accessible via web browser. Example use-cases include Remote Browser Isolation (RBI), Data Loss Prevention (DLP), Desktop as a Service (DaaS), Secure Remote Access Services (RAS), and Open Source Intelligence (OSINT) collections. The rendering of the graphical-based containers is powered by the open-source project [KasmVNC](https://www.kasmweb.com/kasmvnc.html?utm_campaign=LinuxServer&utm_source=kasmvnc). \" \ - --no-cache --pull -t ${IMAGE}:${META_TAG} \ + --no-cache --pull -t ${IMAGE}:${META_TAG} --platform=linux/amd64 \ + --provenance=true --sbom=true --builder=container --load \ --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + sh '''#! /bin/bash + set -e + IFS=',' read -ra CACHE <<< "$BUILDCACHE" + for i in "${CACHE[@]}"; do + docker tag ${IMAGE}:${META_TAG} ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} + done + ''' + withCredentials([ + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: 'Quay.io-Robot', + usernameVariable: 'QUAYUSER', + passwordVariable: 'QUAYPASS' + ] + ]) { + retry_backoff(5,5) { + sh '''#! /bin/bash + set -e + echo $DOCKERHUB_TOKEN | docker login -u linuxserverci --password-stdin + echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin + echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin + echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin + + if [[ "${PACKAGE_CHECK}" != "true" ]]; then + declare -A pids + IFS=',' read -ra CACHE <<< "$BUILDCACHE" + for i in "${CACHE[@]}"; do + docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & + pids[$!]="$i" + done + for p in "${!pids[@]}"; do + wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; } + done + fi + ''' + } + } } } // Build MultiArch Docker containers for push to LS Repo @@ -482,7 +623,8 @@ pipeline { stage('Build X86') { steps { echo "Running on node: ${NODE_NAME}" - sh "docker build \ + sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile" + sh "docker buildx build \ --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ --label \"org.opencontainers.image.authors=linuxserver.io\" \ --label \"org.opencontainers.image.url=https://github.com/linuxserver/docker-kasm/packages\" \ @@ -495,42 +637,46 @@ pipeline { --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ --label \"org.opencontainers.image.title=Kasm\" \ --label \"org.opencontainers.image.description=[Kasm](https://www.kasmweb.com/?utm_campaign=LinuxServer&utm_source=listing) Workspaces is a docker container streaming platform for delivering browser-based access to desktops, applications, and web services. Kasm uses devops-enabled Containerized Desktop Infrastructure (CDI) to create on-demand, disposable, docker containers that are accessible via web browser. Example use-cases include Remote Browser Isolation (RBI), Data Loss Prevention (DLP), Desktop as a Service (DaaS), Secure Remote Access Services (RAS), and Open Source Intelligence (OSINT) collections. The rendering of the graphical-based containers is powered by the open-source project [KasmVNC](https://www.kasmweb.com/kasmvnc.html?utm_campaign=LinuxServer&utm_source=kasmvnc). \" \ - --no-cache --pull -t ${IMAGE}:amd64-${META_TAG} \ + --no-cache --pull -t ${IMAGE}:amd64-${META_TAG} --platform=linux/amd64 \ + --provenance=true --sbom=true --builder=container --load \ --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." - } - } - stage('Build ARMHF') { - agent { - label 'ARMHF' - } - steps { - echo "Running on node: ${NODE_NAME}" - echo 'Logging into Github' sh '''#! /bin/bash - echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin + set -e + IFS=',' read -ra CACHE <<< "$BUILDCACHE" + for i in "${CACHE[@]}"; do + docker tag ${IMAGE}:amd64-${META_TAG} ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} + done ''' - sh "docker build \ - --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ - --label \"org.opencontainers.image.authors=linuxserver.io\" \ - --label \"org.opencontainers.image.url=https://github.com/linuxserver/docker-kasm/packages\" \ - --label \"org.opencontainers.image.documentation=https://docs.linuxserver.io/images/docker-kasm\" \ - --label \"org.opencontainers.image.source=https://github.com/linuxserver/docker-kasm\" \ - --label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \ - --label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.vendor=linuxserver.io\" \ - --label \"org.opencontainers.image.licenses=GPL-3.0-only\" \ - --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.title=Kasm\" \ - --label \"org.opencontainers.image.description=[Kasm](https://www.kasmweb.com/?utm_campaign=LinuxServer&utm_source=listing) Workspaces is a docker container streaming platform for delivering browser-based access to desktops, applications, and web services. Kasm uses devops-enabled Containerized Desktop Infrastructure (CDI) to create on-demand, disposable, docker containers that are accessible via web browser. Example use-cases include Remote Browser Isolation (RBI), Data Loss Prevention (DLP), Desktop as a Service (DaaS), Secure Remote Access Services (RAS), and Open Source Intelligence (OSINT) collections. The rendering of the graphical-based containers is powered by the open-source project [KasmVNC](https://www.kasmweb.com/kasmvnc.html?utm_campaign=LinuxServer&utm_source=kasmvnc). \" \ - --no-cache --pull -f Dockerfile.armhf -t ${IMAGE}:arm32v7-${META_TAG} \ - --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." - sh "docker tag ${IMAGE}:arm32v7-${META_TAG} ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER}" - retry(5) { - sh "docker push ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER}" + withCredentials([ + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: 'Quay.io-Robot', + usernameVariable: 'QUAYUSER', + passwordVariable: 'QUAYPASS' + ] + ]) { + retry_backoff(5,5) { + sh '''#! /bin/bash + set -e + echo $DOCKERHUB_TOKEN | docker login -u linuxserverci --password-stdin + echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin + echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin + echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin + + if [[ "${PACKAGE_CHECK}" != "true" ]]; then + declare -A pids + IFS=',' read -ra CACHE <<< "$BUILDCACHE" + for i in "${CACHE[@]}"; do + docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & + pids[$!]="$i" + done + for p in "${!pids[@]}"; do + wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; } + done + fi + ''' + } } - sh '''docker rmi \ - ${IMAGE}:arm32v7-${META_TAG} \ - ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} || :''' } } stage('Build ARM64') { @@ -539,11 +685,8 @@ pipeline { } steps { echo "Running on node: ${NODE_NAME}" - echo 'Logging into Github' - sh '''#! /bin/bash - echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin - ''' - sh "docker build \ + sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile.aarch64" + sh "docker buildx build \ --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ --label \"org.opencontainers.image.authors=linuxserver.io\" \ --label \"org.opencontainers.image.url=https://github.com/linuxserver/docker-kasm/packages\" \ @@ -556,15 +699,53 @@ pipeline { --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ --label \"org.opencontainers.image.title=Kasm\" \ --label \"org.opencontainers.image.description=[Kasm](https://www.kasmweb.com/?utm_campaign=LinuxServer&utm_source=listing) Workspaces is a docker container streaming platform for delivering browser-based access to desktops, applications, and web services. Kasm uses devops-enabled Containerized Desktop Infrastructure (CDI) to create on-demand, disposable, docker containers that are accessible via web browser. Example use-cases include Remote Browser Isolation (RBI), Data Loss Prevention (DLP), Desktop as a Service (DaaS), Secure Remote Access Services (RAS), and Open Source Intelligence (OSINT) collections. The rendering of the graphical-based containers is powered by the open-source project [KasmVNC](https://www.kasmweb.com/kasmvnc.html?utm_campaign=LinuxServer&utm_source=kasmvnc). \" \ - --no-cache --pull -f Dockerfile.aarch64 -t ${IMAGE}:arm64v8-${META_TAG} \ + --no-cache --pull -f Dockerfile.aarch64 -t ${IMAGE}:arm64v8-${META_TAG} --platform=linux/arm64 \ + --provenance=true --sbom=true --builder=container --load \ --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." - sh "docker tag ${IMAGE}:arm64v8-${META_TAG} ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}" - retry(5) { - sh "docker push ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}" + sh '''#! /bin/bash + set -e + IFS=',' read -ra CACHE <<< "$BUILDCACHE" + for i in "${CACHE[@]}"; do + docker tag ${IMAGE}:arm64v8-${META_TAG} ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} + done + ''' + withCredentials([ + [ + $class: 'UsernamePasswordMultiBinding', + credentialsId: 'Quay.io-Robot', + usernameVariable: 'QUAYUSER', + passwordVariable: 'QUAYPASS' + ] + ]) { + retry_backoff(5,5) { + sh '''#! /bin/bash + set -e + echo $DOCKERHUB_TOKEN | docker login -u linuxserverci --password-stdin + echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin + echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin + echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin + if [[ "${PACKAGE_CHECK}" != "true" ]]; then + declare -A pids + IFS=',' read -ra CACHE <<< "$BUILDCACHE" + for i in "${CACHE[@]}"; do + docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} & + pids[$!]="$i" + done + for p in "${!pids[@]}"; do + wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; } + done + fi + ''' + } } - sh '''docker rmi \ - ${IMAGE}:arm64v8-${META_TAG} \ - ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || :''' + sh '''#! /bin/bash + containers=$(docker ps -aq) + if [[ -n "${containers}" ]]; then + docker stop ${containers} + fi + docker system prune -f --volumes || : + docker image prune -af || : + ''' } } } @@ -580,31 +761,17 @@ pipeline { sh '''#! /bin/bash set -e TEMPDIR=$(mktemp -d) - if [ "${MULTIARCH}" == "true" ] && [ "${PACKAGE_CHECK}" == "false" ]; then + if [ "${MULTIARCH}" == "true" ] && [ "${PACKAGE_CHECK}" != "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' - elif [ "${DIST_IMAGE}" == "fedora" ]; then - docker run --rm --entrypoint '/bin/sh' -v ${TEMPDIR}:/tmp ${LOCAL_CONTAINER} -c '\ - rpm -qa > /tmp/package_versions.txt && \ - sort -o /tmp/package_versions.txt /tmp/package_versions.txt && \ - chmod 777 /tmp/package_versions.txt' - elif [ "${DIST_IMAGE}" == "arch" ]; then - docker run --rm --entrypoint '/bin/sh' -v ${TEMPDIR}:/tmp ${LOCAL_CONTAINER} -c '\ - pacman -Q > /tmp/package_versions.txt && \ - chmod 777 /tmp/package_versions.txt' - fi + touch ${TEMPDIR}/package_versions.txt + docker run --rm \ + -v /var/run/docker.sock:/var/run/docker.sock:ro \ + -v ${TEMPDIR}:/tmp \ + ghcr.io/anchore/syft:${SYFT_IMAGE_TAG} \ + ${LOCAL_CONTAINER} -o table=/tmp/package_versions.txt 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 @@ -615,7 +782,8 @@ pipeline { 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 + git pull https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git master + git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git master echo "true" > /tmp/packages-${COMMIT_SHA}-${BUILD_NUMBER} echo "Package tag updated, stopping build process" else @@ -639,13 +807,6 @@ pipeline { environment name: 'EXIT_STATUS', value: '' } steps { - sh '''#! /bin/bash - echo "Packages were updated. Cleaning up the image and exiting." - if [ "${MULTIARCH}" == "true" ] && [ "${PACKAGE_CHECK}" == "false" ]; then - docker rmi ${IMAGE}:amd64-${META_TAG} - else - docker rmi ${IMAGE}:${META_TAG} - fi''' script{ env.EXIT_STATUS = 'ABORTED' } @@ -663,13 +824,6 @@ pipeline { } } steps { - sh '''#! /bin/bash - echo "There are no package updates. Cleaning up the image and exiting." - if [ "${MULTIARCH}" == "true" ] && [ "${PACKAGE_CHECK}" == "false" ]; then - docker rmi ${IMAGE}:amd64-${META_TAG} - else - docker rmi ${IMAGE}:${META_TAG} - fi''' script{ env.EXIT_STATUS = 'ABORTED' } @@ -691,23 +845,31 @@ pipeline { ]) { script{ env.CI_URL = 'https://ci-tests.linuxserver.io/' + env.IMAGE + '/' + env.META_TAG + '/index.html' + env.CI_JSON_URL = 'https://ci-tests.linuxserver.io/' + env.IMAGE + '/' + env.META_TAG + '/report.json' } sh '''#! /bin/bash set -e - docker pull ghcr.io/linuxserver/ci:latest + if grep -q 'docker-baseimage' <<< "${LS_REPO}"; then + echo "Detected baseimage, setting LSIO_FIRST_PARTY=true" + if [ -n "${CI_DOCKERENV}" ]; then + CI_DOCKERENV="LSIO_FIRST_PARTY=true|${CI_DOCKERENV}" + else + CI_DOCKERENV="LSIO_FIRST_PARTY=true" + fi + fi + docker pull ghcr.io/linuxserver/ci:${CITEST_IMAGETAG} if [ "${MULTIARCH}" == "true" ]; then - docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} - docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} - docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm32v7-${META_TAG} + docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} --platform=arm64 docker tag ghcr.io/linuxserver/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 DOCKER_LOGS_TIMEOUT=\"${CI_DELAY}\" \ -e TAGS=\"${CI_TAGS}\" \ -e META_TAG=\"${META_TAG}\" \ + -e RELEASE_TAG=\"latest\" \ -e PORT=\"${CI_PORT}\" \ -e SSL=\"${CI_SSL}\" \ -e BASE=\"${DIST_IMAGE}\" \ @@ -717,10 +879,12 @@ pipeline { -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 ghcr.io/linuxserver/ci:latest \ - python /ci/ci.py''' + -e NODE_NAME=\"${NODE_NAME}\" \ + -e SYFT_IMAGE_TAG=\"${CI_SYFT_IMAGE_TAG:-${SYFT_IMAGE_TAG}}\" \ + -e COMMIT_SHA=\"${COMMIT_SHA}\" \ + -e BUILD_NUMBER=\"${BUILD_NUMBER}\" \ + -t ghcr.io/linuxserver/ci:${CITEST_IMAGETAG} \ + python3 test_build.py''' } } } @@ -734,54 +898,25 @@ pipeline { environment name: 'EXIT_STATUS', value: '' } steps { - withCredentials([ - [ - $class: 'UsernamePasswordMultiBinding', - credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', - usernameVariable: 'DOCKERUSER', - passwordVariable: 'DOCKERPASS' - ], - [ - $class: 'UsernamePasswordMultiBinding', - credentialsId: 'Quay.io-Robot', - usernameVariable: 'QUAYUSER', - passwordVariable: 'QUAYPASS' - ] - ]) { - retry(5) { - sh '''#! /bin/bash - set -e - echo $DOCKERPASS | docker login -u $DOCKERUSER --password-stdin - echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin - echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin - echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin - for PUSHIMAGE in "${GITHUBIMAGE}" "${GITLABIMAGE}" "${QUAYIMAGE}" "${IMAGE}"; do - docker tag ${IMAGE}:${META_TAG} ${PUSHIMAGE}:${META_TAG} - docker tag ${PUSHIMAGE}:${META_TAG} ${PUSHIMAGE}:latest - docker tag ${PUSHIMAGE}:${META_TAG} ${PUSHIMAGE}:${EXT_RELEASE_TAG} - if [ -n "${SEMVER}" ]; then - docker tag ${PUSHIMAGE}:${META_TAG} ${PUSHIMAGE}:${SEMVER} - fi - docker push ${PUSHIMAGE}:latest - docker push ${PUSHIMAGE}:${META_TAG} - docker push ${PUSHIMAGE}:${EXT_RELEASE_TAG} - if [ -n "${SEMVER}" ]; then - docker push ${PUSHIMAGE}:${SEMVER} - fi - done - ''' - } + retry_backoff(5,5) { sh '''#! /bin/bash - for DELETEIMAGE in "${GITHUBIMAGE}" "${GITLABIMAGE}" "${QUAYIMAGE}" "${IMAGE}"; do - docker rmi \ - ${DELETEIMAGE}:${META_TAG} \ - ${DELETEIMAGE}:${EXT_RELEASE_TAG} \ - ${DELETEIMAGE}:latest || : + set -e + for PUSHIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do + [[ ${PUSHIMAGE%%/*} =~ \\. ]] && PUSHIMAGEPLUS="${PUSHIMAGE}" || PUSHIMAGEPLUS="docker.io/${PUSHIMAGE}" + IFS=',' read -ra CACHE <<< "$BUILDCACHE" + for i in "${CACHE[@]}"; do + if [[ "${PUSHIMAGEPLUS}" == "$(cut -d "/" -f1 <<< ${i})"* ]]; then + CACHEIMAGE=${i} + fi + done + docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${META_TAG} -t ${PUSHIMAGE}:latest -t ${PUSHIMAGE}:${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; } if [ -n "${SEMVER}" ]; then - docker rmi ${DELETEIMAGE}:${SEMVER} || : + docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; } fi done - ''' + ''' } } } @@ -792,112 +927,41 @@ pipeline { environment name: 'EXIT_STATUS', value: '' } steps { - withCredentials([ - [ - $class: 'UsernamePasswordMultiBinding', - credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', - usernameVariable: 'DOCKERUSER', - passwordVariable: 'DOCKERPASS' - ], - [ - $class: 'UsernamePasswordMultiBinding', - credentialsId: 'Quay.io-Robot', - usernameVariable: 'QUAYUSER', - passwordVariable: 'QUAYPASS' - ] - ]) { - retry(5) { - sh '''#! /bin/bash - set -e - echo $DOCKERPASS | docker login -u $DOCKERUSER --password-stdin - echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin - echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin - echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin - if [ "${CI}" == "false" ]; then - docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} - docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} - docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm32v7-${META_TAG} - docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} - fi - for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do - docker tag ${IMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} - docker tag ${IMAGE}:arm32v7-${META_TAG} ${MANIFESTIMAGE}:arm32v7-${META_TAG} - docker tag ${IMAGE}:arm64v8-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} - docker tag ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:amd64-latest - docker tag ${MANIFESTIMAGE}:arm32v7-${META_TAG} ${MANIFESTIMAGE}:arm32v7-latest - docker tag ${MANIFESTIMAGE}:arm64v8-${META_TAG} ${MANIFESTIMAGE}:arm64v8-latest - docker tag ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} - docker tag ${MANIFESTIMAGE}:arm32v7-${META_TAG} ${MANIFESTIMAGE}:arm32v7-${EXT_RELEASE_TAG} - docker tag ${MANIFESTIMAGE}:arm64v8-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} - if [ -n "${SEMVER}" ]; then - docker tag ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:amd64-${SEMVER} - docker tag ${MANIFESTIMAGE}:arm32v7-${META_TAG} ${MANIFESTIMAGE}:arm32v7-${SEMVER} - docker tag ${MANIFESTIMAGE}:arm64v8-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${SEMVER} - fi - docker push ${MANIFESTIMAGE}:amd64-${META_TAG} - docker push ${MANIFESTIMAGE}:arm32v7-${META_TAG} - docker push ${MANIFESTIMAGE}:arm64v8-${META_TAG} - docker push ${MANIFESTIMAGE}:amd64-latest - docker push ${MANIFESTIMAGE}:arm32v7-latest - docker push ${MANIFESTIMAGE}:arm64v8-latest - docker push ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} - docker push ${MANIFESTIMAGE}:arm32v7-${EXT_RELEASE_TAG} - docker push ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} - if [ -n "${SEMVER}" ]; then - docker push ${MANIFESTIMAGE}:amd64-${SEMVER} - docker push ${MANIFESTIMAGE}:arm32v7-${SEMVER} - docker push ${MANIFESTIMAGE}:arm64v8-${SEMVER} - fi - docker manifest push --purge ${MANIFESTIMAGE}:latest || : - docker manifest create ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:amd64-latest ${MANIFESTIMAGE}:arm32v7-latest ${MANIFESTIMAGE}:arm64v8-latest - docker manifest annotate ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:arm32v7-latest --os linux --arch arm - docker manifest annotate ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:arm64v8-latest --os linux --arch arm64 --variant v8 - docker manifest push --purge ${MANIFESTIMAGE}:${META_TAG} || : - docker manifest create ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:arm32v7-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} - docker manifest annotate ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:arm32v7-${META_TAG} --os linux --arch arm - docker manifest annotate ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} --os linux --arch arm64 --variant v8 - docker manifest push --purge ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} || : - docker manifest create ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm32v7-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} - docker manifest annotate ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm32v7-${EXT_RELEASE_TAG} --os linux --arch arm - docker manifest annotate ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} --os linux --arch arm64 --variant v8 - if [ -n "${SEMVER}" ]; then - docker manifest push --purge ${MANIFESTIMAGE}:${SEMVER} || : - docker manifest create ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER} ${MANIFESTIMAGE}:arm32v7-${SEMVER} ${MANIFESTIMAGE}:arm64v8-${SEMVER} - docker manifest annotate ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:arm32v7-${SEMVER} --os linux --arch arm - docker manifest annotate ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:arm64v8-${SEMVER} --os linux --arch arm64 --variant v8 - fi - docker manifest push --purge ${MANIFESTIMAGE}:latest - docker manifest push --purge ${MANIFESTIMAGE}:${META_TAG} - docker manifest push --purge ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} - if [ -n "${SEMVER}" ]; then - docker manifest push --purge ${MANIFESTIMAGE}:${SEMVER} - fi - done - ''' - } + retry_backoff(5,5) { sh '''#! /bin/bash - for DELETEIMAGE in "${GITHUBIMAGE}" "${GITLABIMAGE}" "${QUAYIMAGE}" "${IMAGE}"; do - docker rmi \ - ${DELETEIMAGE}:amd64-${META_TAG} \ - ${DELETEIMAGE}:amd64-latest \ - ${DELETEIMAGE}:amd64-${EXT_RELEASE_TAG} \ - ${DELETEIMAGE}:arm32v7-${META_TAG} \ - ${DELETEIMAGE}:arm32v7-latest \ - ${DELETEIMAGE}:arm32v7-${EXT_RELEASE_TAG} \ - ${DELETEIMAGE}:arm64v8-${META_TAG} \ - ${DELETEIMAGE}:arm64v8-latest \ - ${DELETEIMAGE}:arm64v8-${EXT_RELEASE_TAG} || : + set -e + for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do + [[ ${MANIFESTIMAGE%%/*} =~ \\. ]] && MANIFESTIMAGEPLUS="${MANIFESTIMAGE}" || MANIFESTIMAGEPLUS="docker.io/${MANIFESTIMAGE}" + IFS=',' read -ra CACHE <<< "$BUILDCACHE" + for i in "${CACHE[@]}"; do + if [[ "${MANIFESTIMAGEPLUS}" == "$(cut -d "/" -f1 <<< ${i})"* ]]; then + CACHEIMAGE=${i} + fi + done + docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${META_TAG} -t ${MANIFESTIMAGE}:amd64-latest -t ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; } + docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${META_TAG} -t ${MANIFESTIMAGE}:arm64v8-latest -t ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; } if [ -n "${SEMVER}" ]; then - docker rmi \ - ${DELETEIMAGE}:amd64-${SEMVER} \ - ${DELETEIMAGE}:arm32v7-${SEMVER} \ - ${DELETEIMAGE}:arm64v8-${SEMVER} || : + docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; } + docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ + { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; } fi done - docker rmi \ - ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} \ - ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || : - ''' + for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do + docker buildx imagetools create -t ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:amd64-latest ${MANIFESTIMAGE}:arm64v8-latest || \ + { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; } + docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} || \ + { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; } + docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} || \ + { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; } + if [ -n "${SEMVER}" ]; then + docker buildx imagetools create -t ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER} ${MANIFESTIMAGE}:arm64v8-${SEMVER} || \ + { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; } + fi + done + ''' } } } @@ -912,68 +976,154 @@ pipeline { environment name: 'EXIT_STATUS', value: '' } steps { - echo "Pushing New tag for current commit ${META_TAG}" - sh '''curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/git/tags \ - -d '{"tag":"'${META_TAG}'",\ - "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 - curl -H "Authorization: token ${GITHUB_TOKEN}" -s https://api.github.com/repos/${EXT_USER}/${EXT_REPO}/releases/latest | jq '. |.body' | sed 's:^.\\(.*\\).$:\\1:' > releasebody.json - echo '{"tag_name":"'${META_TAG}'",\ - "target_commitish": "master",\ - "name": "'${META_TAG}'",\ - "body": "**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n\\n**'${EXT_REPO}' 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''' + echo "Auto-generating release notes" + if [ "$(git tag --points-at HEAD)" != "" ]; then + echo "Existing tag points to current commit, suggesting no new LS changes" + AUTO_RELEASE_NOTES="No changes" + else + AUTO_RELEASE_NOTES=$(curl -fsL -H "Authorization: token ${GITHUB_TOKEN}" -H "Accept: application/vnd.github+json" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases/generate-notes \ + -d '{"tag_name":"'${META_TAG}'",\ + "target_commitish": "master"}' \ + | jq -r '.body' | sed 's|## What.s Changed||') + fi + echo "Pushing New tag for current commit ${META_TAG}" + curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/git/tags \ + -d '{"tag":"'${META_TAG}'",\ + "object": "'${COMMIT_SHA}'",\ + "message": "Tagging Release '${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}' to master",\ + "type": "commit",\ + "tagger": {"name": "LinuxServer-CI","email": "ci@linuxserver.io","date": "'${GITHUB_DATE}'"}}' + echo "Pushing New release for Tag" + curl -H "Authorization: token ${GITHUB_TOKEN}" -s https://api.github.com/repos/${EXT_USER}/${EXT_REPO}/releases/latest | jq -r '. |.body' > releasebody.json + jq -n \ + --arg tag_name "$META_TAG" \ + --arg target_commitish "master" \ + --arg ci_url "${CI_URL:-N/A}" \ + --arg ls_notes "$AUTO_RELEASE_NOTES" \ + --arg remote_notes "$(cat releasebody.json)" \ + '{ + "tag_name": $tag_name, + "target_commitish": $target_commitish, + "name": $tag_name, + "body": ("**CI Report:**\\n\\n" + $ci_url + "\\n\\n**LinuxServer Changes:**\\n\\n" + $ls_notes + "\\n\\n**Remote Changes:**\\n\\n" + $remote_notes), + "draft": false, + "prerelease": false }' > 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') { + // Add protection to the release branch + stage('Github-Release-Branch-Protection') { when { + branch "master" 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 - set -e - TEMPDIR=$(mktemp -d) - docker pull ghcr.io/linuxserver/jenkins-builder:latest - docker run --rm -e CONTAINER_NAME=${CONTAINER_NAME} -e GITHUB_BRANCH="${BRANCH_NAME}" -v ${TEMPDIR}:/ansible/jenkins ghcr.io/linuxserver/jenkins-builder:latest - docker pull ghcr.io/linuxserver/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 \ - -v ${TEMPDIR}/docker-${CONTAINER_NAME}:/mnt \ - ghcr.io/linuxserver/readme-sync bash -c 'node sync' - rm -Rf ${TEMPDIR} ''' - } + echo "Setting up protection for release branch master" + sh '''#! /bin/bash + curl -H "Authorization: token ${GITHUB_TOKEN}" -X PUT https://api.github.com/repos/${LS_USER}/${LS_REPO}/branches/master/protection \ + -d $(jq -c . << EOF + { + "required_status_checks": null, + "enforce_admins": false, + "required_pull_request_reviews": { + "dismiss_stale_reviews": false, + "require_code_owner_reviews": false, + "require_last_push_approval": false, + "required_approving_review_count": 1 + }, + "restrictions": null, + "required_linear_history": false, + "allow_force_pushes": false, + "allow_deletions": false, + "block_creations": false, + "required_conversation_resolution": true, + "lock_branch": false, + "allow_fork_syncing": false, + "required_signatures": false + } +EOF + ) ''' } } // 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}'"}' ''' + sh '''#! /bin/bash + # Function to retrieve JSON data from URL + get_json() { + local url="$1" + local response=$(curl -s "$url") + if [ $? -ne 0 ]; then + echo "Failed to retrieve JSON data from $url" + return 1 + fi + local json=$(echo "$response" | jq .) + if [ $? -ne 0 ]; then + echo "Failed to parse JSON data from $url" + return 1 + fi + echo "$json" + } + + build_table() { + local data="$1" + + # Get the keys in the JSON data + local keys=$(echo "$data" | jq -r 'to_entries | map(.key) | .[]') + + # Check if keys are empty + if [ -z "$keys" ]; then + echo "JSON report data does not contain any keys or the report does not exist." + return 1 + fi + + # Build table header + local header="| Tag | Passed |\\n| --- | --- |\\n" + + # Loop through the JSON data to build the table rows + local rows="" + for build in $keys; do + local status=$(echo "$data" | jq -r ".[\\"$build\\"].test_success") + if [ "$status" = "true" ]; then + status="✅" + else + status="❌" + fi + local row="| "$build" | "$status" |\\n" + rows="${rows}${row}" + done + + local table="${header}${rows}" + local escaped_table=$(echo "$table" | sed 's/\"/\\\\"/g') + echo "$escaped_table" + } + + if [[ "${CI}" = "true" ]]; then + # Retrieve JSON data from URL + data=$(get_json "$CI_JSON_URL") + # Create table from JSON data + table=$(build_table "$data") + echo -e "$table" + + curl -X POST -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "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}\\n${table}\\"}" + else + curl -X POST -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/$LS_USER/$LS_REPO/issues/$PULL_REQUEST/comments" \ + -d "{\\"body\\": \\"I am a bot, here is the pushed image/manifest for this PR: \\n\\n\\`${GITHUBIMAGE}:${META_TAG}\\`\\"}" + fi + ''' + } } } @@ -982,24 +1132,94 @@ pipeline { ###################### */ post { always { + sh '''#!/bin/bash + rm -rf /config/.ssh/id_sign + rm -rf /config/.ssh/id_sign.pub + git config --global --unset gpg.format + git config --global --unset user.signingkey + git config --global --unset commit.gpgsign + ''' script{ + env.JOB_DATE = sh( + script: '''date '+%Y-%m-%dT%H:%M:%S%:z' ''', + returnStdout: true).trim() if (env.EXIT_STATUS == "ABORTED"){ sh 'echo "build aborted"' - } - else if (currentBuild.currentResult == "SUCCESS"){ - sh ''' curl -X POST -H "Content-Type: application/json" --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 -H "Content-Type: application/json" --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"}],\ + }else{ + if (currentBuild.currentResult == "SUCCESS"){ + if (env.GITHUBIMAGE =~ /lspipepr/){ + env.JOB_WEBHOOK_STATUS='Success' + env.JOB_WEBHOOK_COLOUR=3957028 + env.JOB_WEBHOOK_FOOTER='PR Build' + }else if (env.GITHUBIMAGE =~ /lsiodev/){ + env.JOB_WEBHOOK_STATUS='Success' + env.JOB_WEBHOOK_COLOUR=3957028 + env.JOB_WEBHOOK_FOOTER='Dev Build' + }else{ + env.JOB_WEBHOOK_STATUS='Success' + env.JOB_WEBHOOK_COLOUR=1681177 + env.JOB_WEBHOOK_FOOTER='Live Build' + } + }else{ + if (env.GITHUBIMAGE =~ /lspipepr/){ + env.JOB_WEBHOOK_STATUS='Failure' + env.JOB_WEBHOOK_COLOUR=12669523 + env.JOB_WEBHOOK_FOOTER='PR Build' + }else if (env.GITHUBIMAGE =~ /lsiodev/){ + env.JOB_WEBHOOK_STATUS='Failure' + env.JOB_WEBHOOK_COLOUR=12669523 + env.JOB_WEBHOOK_FOOTER='Dev Build' + }else{ + env.JOB_WEBHOOK_STATUS='Failure' + env.JOB_WEBHOOK_COLOUR=16711680 + env.JOB_WEBHOOK_FOOTER='Live Build' + } + } + sh ''' curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/jenkins-avatar.png","embeds": [{"'color'": '${JOB_WEBHOOK_COLOUR}',\ + "footer": {"text" : "'"${JOB_WEBHOOK_FOOTER}"'"},\ + "timestamp": "'${JOB_DATE}'",\ + "description": "**Build:** '${BUILD_NUMBER}'\\n**CI Results:** '${CI_URL}'\\n**ShellCheck Results:** '${SHELLCHECK_URL}'\\n**Status:** '${JOB_WEBHOOK_STATUS}'\\n**Job:** '${RUN_DISPLAY_URL}'\\n**Change:** '${CODE_URL}'\\n**External Release:**: '${RELEASE_LINK}'\\n**DockerHub:** '${DOCKERHUB_LINK}'\\n"}],\ "username": "Jenkins"}' ${BUILDS_DISCORD} ''' } } } cleanup { + sh '''#! /bin/bash + echo "Pruning builder!!" + docker builder prune -f --builder container || : + containers=$(docker ps -q) + if [[ -n "${containers}" ]]; then + BUILDX_CONTAINER_ID=$(docker ps -qf 'name=buildx_buildkit') + for container in ${containers}; do + if [[ "${container}" == "${BUILDX_CONTAINER_ID}" ]]; then + echo "skipping buildx container in docker stop" + else + echo "Stopping container ${container}" + docker stop ${container} + fi + done + fi + docker system prune -f --volumes || : + docker image prune -af || : + ''' cleanWs() } } } + +def retry_backoff(int max_attempts, int power_base, Closure c) { + int n = 0 + while (n < max_attempts) { + try { + c() + return + } catch (err) { + if ((n + 1) >= max_attempts) { + throw err + } + sleep(power_base ** n) + n++ + } + } + return +} diff --git a/README.md b/README.md index 87115bd..5982b44 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,10 @@ -<!-- DO NOT EDIT THIS FILE MANUALLY --> -<!-- Please read the https://github.com/linuxserver/docker-kasm/blob/master/.github/CONTRIBUTING.md --> - +<!-- DO NOT EDIT THIS FILE MANUALLY --> +<!-- Please read https://github.com/linuxserver/docker-kasm/blob/master/.github/CONTRIBUTING.md --> [![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?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&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?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=Discord&logo=discord)](https://discord.gg/YWrKVTn "realtime support / chat with the community and the team.") +[![Discord](https://img.shields.io/discord/354974912613449730.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=Discord&logo=discord)](https://linuxserver.io/discord "realtime support / chat with the community and the team.") [![Discourse](https://img.shields.io/discourse/https/discourse.linuxserver.io/topics.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=discourse)](https://discourse.linuxserver.io "post on our community forum.") -[![Fleet](https://img.shields.io/static/v1.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=linuxserver.io&message=Fleet)](https://fleet.linuxserver.io "an online web interface which displays all of our maintained images.") [![GitHub](https://img.shields.io/static/v1.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=linuxserver.io&message=GitHub&logo=github)](https://github.com/linuxserver "view the source for all of our repositories.") [![Open Collective](https://img.shields.io/opencollective/all/linuxserver.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=Supporters&logo=open%20collective)](https://opencollective.com/linuxserver "please consider helping us by either donating or contributing to our budget") @@ -21,15 +19,14 @@ The [LinuxServer.io](https://linuxserver.io) team brings you another container r 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. +* [Discord](https://linuxserver.io/discord) - 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. * [GitHub](https://github.com/linuxserver) - view the source for all of our repositories. * [Open Collective](https://opencollective.com/linuxserver) - please consider helping us by either donating or contributing to our budget # [linuxserver/kasm](https://github.com/linuxserver/docker-kasm) -[![Scarf.io pulls](https://scarf.sh/installs-badge/linuxserver-ci/linuxserver%2Fkasm?color=94398d&label-color=555555&logo-color=ffffff&style=for-the-badge&package-type=docker)](https://scarf.sh/gateway/linuxserver-ci/docker/linuxserver%2Fkasm) +[![Scarf.io pulls](https://scarf.sh/installs-badge/linuxserver-ci/linuxserver%2Fkasm?color=94398d&label-color=555555&logo-color=ffffff&style=for-the-badge&package-type=docker)](https://scarf.sh) [![GitHub Stars](https://img.shields.io/github/stars/linuxserver/docker-kasm.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=github)](https://github.com/linuxserver/docker-kasm) [![GitHub Release](https://img.shields.io/github/release/linuxserver/docker-kasm.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=github)](https://github.com/linuxserver/docker-kasm/releases) [![GitHub Package Repository](https://img.shields.io/static/v1.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=linuxserver.io&message=GitHub%20Package&logo=github)](https://github.com/linuxserver/docker-kasm/packages) @@ -48,7 +45,7 @@ The rendering of the graphical-based containers is powered by the open-source pr ## Supported Architectures -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/). +We utilise the docker manifest for multi-platform awareness. More information is available from docker [here](https://distribution.github.io/distribution/spec/manifest-v2-2/#manifest-list) and our announcement [here](https://blog.linuxserver.io/2019/02/21/the-lsio-pipeline-project/). Simply pulling `lscr.io/linuxserver/kasm:latest` should retrieve the correct image for your arch, but you can also pull specific arch images via tags. @@ -58,21 +55,15 @@ The architectures supported by this image are: | :----: | :----: | ---- | | x86-64 | ✅ | amd64-\<version tag\> | | arm64 | ✅ | arm64v8-\<version tag\> | -| armhf| ❌ | | - -## Version Tags - -This image provides various versions that are available via tags. Please read the descriptions carefully and exercise caution when using unstable or development tags. - -| Tag | Available | Description | -| :----: | :----: |--- | -| latest | ✅ | Stable Kasm releases | -| develop | ✅ | Tip of develop | ## Application Setup This container uses [Docker in Docker](https://www.docker.com/blog/docker-can-now-run-within-docker/) and requires being run in `privileged` mode. This container also requires an initial setup that runs on port 3000. +**Unlike other containers the web interface port (default 443) needs to be set for the env variable `KASM_PORT` and both the inside and outside port IE for 4443 `KASM_PORT=4443` `-p 4443:4443`** + +**Unraid users due to the DinD storage layer `/opt/` should be mounted directly to a disk IE `/mnt/disk1/appdata/path` or optimally with a cache disk at `/mnt/cache/appdata/path`** + Access the installation wizard at https://`your ip`:3000 and follow the instructions there. Once setup is complete access https://`your ip`:443 and login with the credentials you entered during setup. The default users are: * admin@kasm.local @@ -80,28 +71,59 @@ Access the installation wizard at https://`your ip`:3000 and follow the instruct Currently Synology systems are not supported due to them blocking CPU scheduling in their Kernel. +### Updating KASM + +In order to update kasm, first make sure you are using the latest docker image, and then perform the in app update in the admin panel. Docker image update and recreation of container alone won't update kasm. + +### GPU Support + +During installation an option will be presented to force all Workspace containers to mount in and use a specific GPU. If using an NVIDIA GPU you will need to pass `-e NVIDIA_VISIBLE_DEVICES=all` or `--gpus all` and have the [NVIDIA Container Runtime](https://github.com/NVIDIA/nvidia-container-runtime) installed on the host. Also if using NVIDIA, Kasm Workspaces has [native NVIDIA support](https://www.kasmweb.com/docs/latest/how_to/gpu.html) so you can optionally opt to simply use that instead of he manual override during installation. + +### Gamepad support + +In order to properly create virtual Gamepads you will need to mount from your host `/dev/input` and `/run/udev/data`. Please see [HERE](https://www.kasmweb.com/docs/develop/guide/gamepad_passthrough.html) for instructions on enabling gamepad support. + +### Persistant profiles + +In order to use persistant profiles in Workspaces you will need to mount in a folder to use from your host to `/profiles`. From there when configuring a workspace you can set the `Persistant Profile Path` to IE `/profiles/ubuntu-focal/{username}/`, more infomation can be found [HERE](https://www.kasmweb.com/docs/latest/how_to/persistent_profiles.html). + +### Reverse proxy + +A sample for [SWAG](https://github.com/linuxserver/docker-swag) can be found [here](https://raw.githubusercontent.com/linuxserver/reverse-proxy-confs/master/kasm.subdomain.conf.sample). Post installation you will need to modify the "Proxy Port" setting under the default zone to 0 as outlined [here](https://www.kasmweb.com/docs/latest/how_to/reverse_proxy.html#update-zones) to launch Workspaces sessions. + +### Strict reverse proxies + +This image uses a self-signed certificate by default. This naturally means the scheme is `https`. +If you are using a reverse proxy which validates certificates, you need to [disable this check for the container](https://docs.linuxserver.io/faq#strict-proxy). + ## Usage -Here are some example snippets to help you get started creating a container. +To help you get started creating a container from this image you can either use docker-compose or the docker cli. + +>[!NOTE] +>Unless a parameter is flaged as 'optional', it is *mandatory* and a value must be provided. ### docker-compose (recommended, [click here for more info](https://docs.linuxserver.io/general/docker-compose)) ```yaml --- -version: "2.1" services: kasm: image: lscr.io/linuxserver/kasm:latest container_name: kasm privileged: true + security_opt: + - apparmor:rootlesskit #optional environment: - KASM_PORT=443 - - TZ=Europe/London - DOCKER_HUB_USERNAME=USER #optional - DOCKER_HUB_PASSWORD=PASS #optional + - DOCKER_MTU=1500 #optional volumes: - - /path/to/data:/opt - - /path/to/profiles:/profiles #optional + - /path/to/kasm/data:/opt + - /path/to/kasm/profiles:/profiles #optional + - /dev/input:/dev/input #optional + - /run/udev/data:/run/udev/data #optional ports: - 3000:3000 - 443:443 @@ -114,32 +136,38 @@ services: docker run -d \ --name=kasm \ --privileged \ + --security-opt apparmor=rootlesskit `#optional` \ -e KASM_PORT=443 \ - -e TZ=Europe/London \ -e DOCKER_HUB_USERNAME=USER `#optional` \ -e DOCKER_HUB_PASSWORD=PASS `#optional` \ + -e DOCKER_MTU=1500 `#optional` \ -p 3000:3000 \ -p 443:443 \ - -v /path/to/data:/opt \ - -v /path/to/profiles:/profiles `#optional` \ + -v /path/to/kasm/data:/opt \ + -v /path/to/kasm/profiles:/profiles `#optional` \ + -v /dev/input:/dev/input `#optional` \ + -v /run/udev/data:/run/udev/data `#optional` \ --restart unless-stopped \ lscr.io/linuxserver/kasm:latest ``` ## Parameters -Container images are configured using parameters passed at runtime (such as those above). These parameters are separated by a colon and indicate `<external>:<internal>` 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. +Containers are configured using parameters passed at runtime (such as those above). These parameters are separated by a colon and indicate `<external>:<internal>` 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 3000` | Kasm Installation wizard. (https) | -| `-p 443` | Kasm Workspaces interface. (https) | +| `-p 3000:3000` | Kasm Installation wizard. (https) | +| `-p 443:443` | Kasm Workspaces interface. (https) | | `-e KASM_PORT=443` | Specify the port you bind to the outside for Kasm Workspaces. | -| `-e TZ=Europe/London` | Specify a timezone to use EG Europe/London. | | `-e DOCKER_HUB_USERNAME=USER` | Optionally specify a DockerHub Username to pull private images. | | `-e DOCKER_HUB_PASSWORD=PASS` | Optionally specify a DockerHub password to pull private images. | +| `-e DOCKER_MTU=1500` | Optionally specify the mtu options passed to dockerd. | | `-v /opt` | Docker and installation storage. | | `-v /profiles` | Optionally specify a path for persistent profile storage. | +| `-v /dev/input` | Optional for gamepad support. | +| `-v /run/udev/data` | Optional for gamepad support. | +| `--security-opt apparmor=rootlesskit` | Some hosts require this on top of privileged for namespacing to work properly inside the DinD layer. | ## Environment variables from files (Docker secrets) @@ -148,10 +176,10 @@ You can set any environment variable from a file by using a special prepend `FIL As an example: ```bash --e FILE__PASSWORD=/run/secrets/mysecretpassword +-e FILE__MYVAR=/run/secrets/mysecretvariable ``` -Will set the environment variable `PASSWORD` based on the contents of the `/run/secrets/mysecretpassword` file. +Will set the environment variable `MYVAR` based on the contents of the `/run/secrets/mysecretvariable` file. ## Umask for running applications @@ -166,53 +194,101 @@ We publish various [Docker Mods](https://github.com/linuxserver/docker-mods) to ## Support Info -* Shell access whilst the container is running: `docker exec -it kasm /bin/bash` -* To monitor the logs of the container in realtime: `docker logs -f kasm` -* container version number - * `docker inspect -f '{{ index .Config.Labels "build_version" }}' kasm` -* image version number - * `docker inspect -f '{{ index .Config.Labels "build_version" }}' lscr.io/linuxserver/kasm:latest` +* Shell access whilst the container is running: + + ```bash + docker exec -it kasm /bin/bash + ``` + +* To monitor the logs of the container in realtime: + + ```bash + docker logs -f kasm + ``` + +* Container version number: + + ```bash + docker inspect -f '{{ index .Config.Labels "build_version" }}' kasm + ``` + +* Image version number: + + ```bash + docker inspect -f '{{ index .Config.Labels "build_version" }}' lscr.io/linuxserver/kasm:latest + ``` ## 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. +Most of our images are static, versioned, and require an image update and container recreation to update the app inside. With some exceptions (noted in the relevant readme.md), 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 Compose -* Update all images: `docker-compose pull` - * or update a single image: `docker-compose pull kasm` -* Let compose update all containers as necessary: `docker-compose up -d` - * or update a single container: `docker-compose up -d kasm` -* You can also remove the old dangling images: `docker image prune` +* Update images: + * All images: + + ```bash + docker-compose pull + ``` + + * Single image: + + ```bash + docker-compose pull kasm + ``` + +* Update containers: + * All containers: + + ```bash + docker-compose up -d + ``` + + * Single container: + + ```bash + docker-compose up -d kasm + ``` + +* You can also remove the old dangling images: + + ```bash + docker image prune + ``` ### Via Docker Run -* Update the image: `docker pull lscr.io/linuxserver/kasm:latest` -* Stop the running container: `docker stop kasm` -* Delete the container: `docker rm kasm` +* Update the image: + + ```bash + docker pull lscr.io/linuxserver/kasm:latest + ``` + +* Stop the running container: + + ```bash + docker stop kasm + ``` + +* Delete the container: + + ```bash + docker rm kasm + ``` + * Recreate a new container with the same docker run parameters as instructed above (if mapped correctly to a host folder, your `/config` folder and settings will be preserved) -* You can also remove the old dangling images: `docker image prune` +* You can also remove the old dangling images: -### Via Watchtower auto-updater (only use 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: - - ```bash - docker run --rm \ - -v /var/run/docker.sock:/var/run/docker.sock \ - containrrr/watchtower \ - --run-once kasm - ``` - -* You can also remove the old dangling images: `docker image prune` - -**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](https://docs.linuxserver.io/general/docker-compose). + ```bash + docker image prune + ``` ### Image Update Notifications - Diun (Docker Image Update Notifier) -* We recommend [Diun](https://crazymax.dev/diun/) for update notifications. Other tools that automatically update containers unattended are not recommended or supported. +>[!TIP] +>We recommend [Diun](https://crazymax.dev/diun/) for update notifications. Other tools that automatically update containers unattended are not recommended or supported. ## Building locally @@ -227,14 +303,27 @@ docker build \ -t lscr.io/linuxserver/kasm:latest . ``` -The ARM variants can be built on x86_64 hardware using `multiarch/qemu-user-static` +The ARM variants can be built on x86_64 hardware and vice versa using `lscr.io/linuxserver/qemu-static` ```bash -docker run --rm --privileged multiarch/qemu-user-static:register --reset +docker run --rm --privileged lscr.io/linuxserver/qemu-static --reset ``` Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64`. ## Versions +* **13.11.25:** - Pin docker to v28 to avoid API deprecation issues. +* **22.10.25:** - Update for 1.18.0 release. +* **08.06.25:** - Deprecate develop branch. +* **03.06.25:** - Rebase to Ubuntu Noble. Update for 1.17.0 release. +* **09.11.24:** - Update base image for 1.16.1 release. +* **24.09.24:** - Add base users in docker build logic to survive container upgrades. +* **17.09.24:** - Update base image for 1.16.0 release and fix Nvidia support. +* **16.02.24:** - Update base image for 1.15.0 release. +* **22.08.23:** - Update base image for 1.14.0 release. +* **07.04.23:** - Add mod layer for ingesting LSIO images for 1.13.0 release. +* **28.03.23:** - Pin compose to 2.5.0 to be in sync with upstream requirements. +* **05.11.22:** - Rebase to Jammy, add support for GPUs, add support for Gamepads. +* **23.09.22:** - Migrate to s6v3. * **02.07.22:** - Initial Release. diff --git a/jenkins-vars.yml b/jenkins-vars.yml index 960107a..49c7488 100644 --- a/jenkins-vars.yml +++ b/jenkins-vars.yml @@ -7,7 +7,6 @@ release_type: stable release_tag: latest ls_branch: master repo_vars: - - EXT_GIT_BRANCH = 'develop' - EXT_USER = 'kasmtech' - EXT_REPO = 'kasm-install-wizard' - BUILD_VERSION_ARG = 'KASM_VERSION' @@ -17,13 +16,13 @@ repo_vars: - DOCKERHUB_IMAGE = 'linuxserver/kasm' - DEV_DOCKERHUB_IMAGE = 'lsiodev/kasm' - PR_DOCKERHUB_IMAGE = 'lspipepr/kasm' - - DIST_IMAGE = 'alpine' + - DIST_IMAGE = 'ubuntu' - MULTIARCH='true' - CI='true' - - CI_WEB='true' + - CI_WEB='false' - CI_PORT='3000' - CI_SSL='true' - CI_DELAY='120' - - CI_DOCKERENV='TEST=true' - - CI_AUTH='user:password' + - CI_DOCKERENV='' + - CI_AUTH='' - CI_WEBPATH='' diff --git a/package_versions.txt b/package_versions.txt index 7e78c1f..ff3be76 100755 --- a/package_versions.txt +++ b/package_versions.txt @@ -1,96 +1,922 @@ -alpine-baselayout-3.2.0-r22 -alpine-baselayout-data-3.2.0-r22 -alpine-keys-2.4-r1 -apk-tools-2.12.9-r3 -bash-5.1.16-r2 -brotli-libs-1.0.9-r6 -btrfs-progs-5.17-r0 -busybox-1.35.0-r14 -c-ares-1.18.1-r0 -ca-certificates-20211220-r0 -ca-certificates-bundle-20211220-r0 -containerd-1.6.6-r0 -coreutils-9.1-r0 -curl-7.83.1-r2 -device-mapper-libs-2.02.187-r2 -docker-20.10.16-r0 -docker-cli-20.10.16-r0 -docker-cli-compose-2.5.0-r1 -docker-engine-20.10.16-r0 -e2fsprogs-1.46.5-r0 -e2fsprogs-extra-1.46.5-r0 -e2fsprogs-libs-1.46.5-r0 -eudev-libs-3.2.11-r0 -expat-2.4.8-r0 -findutils-4.9.0-r0 -fuse-common-3.11.0-r0 -fuse-overlayfs-1.8.2-r0 -fuse3-3.11.0-r0 -fuse3-libs-3.11.0-r0 -gdbm-1.23-r0 -gmp-6.2.1-r2 -icu-data-en-71.1-r2 -icu-libs-71.1-r2 -inih-55-r0 -ip6tables-1.8.8-r1 -iptables-1.8.8-r1 -jq-1.6-r1 -keyutils-libs-1.6.3-r1 -krb5-conf-1.0-r2 -krb5-libs-1.19.3-r0 -libacl-2.3.1-r0 -libattr-2.5.1-r1 -libblkid-2.38-r1 -libbz2-1.0.8-r1 -libc-utils-0.7.2-r3 -libcom_err-1.46.5-r0 -libcrypto1.1-1.1.1p-r0 -libcurl-7.83.1-r2 -libffi-3.4.2-r1 -libgcc-11.2.1_git20220219-r2 -libintl-0.21-r2 -libmnl-1.0.5-r0 -libnftnl-1.2.1-r0 -libproc-3.3.17-r1 -libseccomp-2.5.2-r1 -libssl1.1-1.1.1p-r0 -libstdc++-11.2.1_git20220219-r2 -libtirpc-1.3.2-r0 -libtirpc-conf-1.3.2-r0 -libuuid-2.38-r1 -libverto-0.3.2-r0 -linux-pam-1.5.2-r0 -lzo-2.10-r3 -mpdecimal-2.5.1-r1 -musl-1.2.3-r0 -musl-utils-1.2.3-r0 -ncurses-libs-6.3_p20220521-r0 -ncurses-terminfo-base-6.3_p20220521-r0 -nghttp2-libs-1.47.0-r0 -nodejs-16.15.0-r1 -oniguruma-6.9.8-r0 -openssl-1.1.1q-r0 -pigz-2.7-r0 -procps-3.3.17-r1 -python3-3.10.4-r0 -readline-8.1.2-r0 -runc-1.1.2-r0 -scanelf-1.3.4-r0 -shadow-4.10-r3 -shadow-libs-4.10-r3 -shadow-subids-4.10-r3 -skalibs-2.11.2.0-r0 -sqlite-libs-3.38.5-r0 -ssl_client-1.35.0-r14 -sudo-1.9.10-r0 -tini-static-0.19.0-r0 -tzdata-2022a-r0 -userspace-rcu-0.13.1-r0 -utmps-libs-0.1.2.0-r0 -xfsprogs-5.16.0-r1 -xz-5.2.5-r1 -xz-libs-5.2.5-r1 -zfs-2.1.5-r0 -zfs-libs-2.1.5-r0 -zlib-1.2.12-r1 -zstd-libs-1.5.2-r1 +NAME VERSION TYPE +1to2 1.0.0 npm +@balena/dockerignore 1.0.2 npm +@isaacs/cliui 8.0.2 npm +@isaacs/string-locale-compare 1.1.0 npm +@npmcli/agent 2.2.2 npm +@npmcli/arborist 7.5.4 npm +@npmcli/config 8.3.4 npm +@npmcli/fs 3.1.1 npm +@npmcli/git 5.0.8 npm +@npmcli/installed-package-contents 2.1.0 npm +@npmcli/map-workspaces 3.0.6 npm +@npmcli/metavuln-calculator 7.1.1 npm +@npmcli/name-from-folder 2.0.0 npm +@npmcli/node-gyp 3.0.0 npm +@npmcli/package-json 5.2.0 npm +@npmcli/promise-spawn 7.0.2 npm +@npmcli/query 3.1.0 npm +@npmcli/redact 2.0.1 npm +@npmcli/run-script 8.1.0 npm +@pkgjs/parseargs 0.11.0 npm +@sigstore/bundle 2.3.2 npm +@sigstore/core 1.1.0 npm +@sigstore/protobuf-specs 0.3.2 npm +@sigstore/sign 2.3.2 npm +@sigstore/tuf 2.3.4 npm +@sigstore/verify 1.2.1 npm +@socket.io/component-emitter 3.1.2 npm +@socket.io/component-emitter UNKNOWN npm (+1 duplicate) +@tufjs/canonical-json 2.0.0 npm +@tufjs/models 2.0.1 npm +@types/cors 2.8.19 npm +@types/node 25.0.9 npm +abbrev 2.0.0 npm +accepts 1.3.8 npm +adduser 3.137ubuntu1 deb +agent-base 7.1.1 npm +aggregate-error 3.1.0 npm +ansi-regex 5.0.1 npm +ansi-regex 6.0.1 npm (+1 duplicate) +ansi-styles 4.3.0 npm +ansi-styles 6.2.1 npm +aproba 2.0.0 npm +apt 2.8.3 deb +apt-transport-https 2.8.3 deb +apt-utils 2.8.3 deb +archy 1.0.0 npm +argparse 2.0.1 npm +array-flatten 1.1.1 npm +asn1 0.2.6 npm +balanced-match 1.0.2 npm +base-files 13ubuntu10.3 deb +base-passwd 3.6.3build1 deb +base64-js 1.5.1 npm +base64id 2.0.0 npm +bash 5.2.21-2ubuntu4 deb +bcrypt-pbkdf 1.0.2 npm +bin-links 4.0.4 npm +binary-extensions 2.3.0 npm +binutils-common 2.42-4ubuntu2.8 deb +bl 4.1.0 npm +body-parser 1.20.4 npm +brace-expansion 2.0.1 npm +bsdutils 1:2.39.3-9ubuntu6.4 deb +btrfs-progs 6.6.3-1.1build2 deb +buffer 5.7.1 npm +buildcheck 0.0.7 npm +bytes 3.1.2 npm +ca-certificates 20240203 deb +cacache 18.0.3 npm +call-bind-apply-helpers 1.0.2 npm +call-bound 1.0.4 npm +catatonit 0.1.7-1 deb +chalk 5.3.0 npm +chownr 1.1.4 npm +chownr 2.0.0 npm +ci-info 4.0.0 npm +cidr-regex 4.1.1 npm +clean-stack 2.2.0 npm +cli-columns 4.0.0 npm +cloud.google.com/go/compute/metadata v0.6.0 go-module +cloud.google.com/go/logging v1.9.0 go-module +cloud.google.com/go/longrunning v0.5.5 go-module +cmd-shim 6.0.3 npm +code.cloudfoundry.org/clock v1.37.0 go-module +color-convert 2.0.1 npm +color-name 1.1.4 npm +common-ancestor-path 1.0.1 npm +containerd.io 2.2.1-1~ubuntu.24.04~noble deb +content-disposition 0.5.4 npm +content-type 1.0.5 npm +cookie 0.7.2 npm +cookie-signature 1.0.7 npm +corepack 0.34.1 npm +coreutils 9.4-3ubuntu6.1 deb +cors 2.8.5 npm +cpp 4:13.2.0-7ubuntu1 deb +cpu-features 0.0.10 npm +cron 3.0pl1-184ubuntu2 deb +cron-daemon-common 3.0pl1-184ubuntu2 deb +cross-spawn 7.0.3 npm +cssesc 3.0.0 npm +curl 8.5.0-2ubuntu10.6 deb +dario.cat/mergo v1.0.2 go-module (+1 duplicate) +dash 0.5.12-6ubuntu5 deb +debconf 1.5.86ubuntu1 deb +debianutils 5.17build1 deb +debug 2.6.9 npm (+3 duplicates) +debug 4.3.5 npm +debug 4.4.3 npm +depd 2.0.0 npm +destroy 1.2.0 npm +diff 5.2.0 npm +diffutils 1:3.10-1build1 deb +dirmngr 2.4.4-2ubuntu17.4 deb +docker-ce 5:28.5.2-1~ubuntu.24.04~noble deb +docker-ce-cli 5:28.5.2-1~ubuntu.24.04~noble deb +docker-compose-plugin 5.0.1-1~ubuntu.24.04~noble deb +docker-modem 3.0.8 npm +dockerode 3.3.5 npm +dpkg 1.22.6ubuntu6.5 deb +dpkg-dev 1.22.6ubuntu6.5 deb +dunder-proto 1.0.1 npm +e2fsprogs 1.47.0-2.4~exp1ubuntu4.1 deb +eastasianwidth 0.2.0 npm +ee-first 1.1.1 npm +emoji-regex 8.0.0 npm +emoji-regex 9.2.2 npm (+1 duplicate) +encodeurl 2.0.0 npm +encoding 0.1.13 npm +end-of-stream 1.4.5 npm +engine.io 6.6.5 npm +engine.io-parser 5.2.3 npm +engine.io-parser UNKNOWN npm (+1 duplicate) +env-paths 2.2.1 npm +err-code 2.0.3 npm +es-define-property 1.0.1 npm +es-errors 1.3.0 npm +es-object-atoms 1.1.1 npm +escape-html 1.0.3 npm +etag 1.8.1 npm +exponential-backoff 3.1.1 npm +express 4.22.1 npm +fastest-levenshtein 1.0.16 npm +finalhandler 1.3.2 npm +findutils 4.9.0-5build1 deb +foreground-child 3.2.1 npm +forwarded 0.2.0 npm +fresh 0.5.2 npm +fs-constants 1.0.0 npm +fs-minipass 2.1.0 npm +fs-minipass 3.0.3 npm +function-bind 1.1.2 npm +fuse-overlayfs 1.13-1 deb +fuse3 3.14.0-5build1 deb +gcc-14-base 14.2.0-4ubuntu2~24.04 deb +get-intrinsic 1.3.0 npm +get-proto 1.0.1 npm +github.com/AlecAivazis/survey/v2 v2.3.7 go-module +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 go-module +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 go-module +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0 go-module +github.com/DefangLabs/secret-detector v0.0.0-20250403165618-22662109213e go-module +github.com/Graylog2/go-gelf v0.0.0-20191017102106-1550ee647df0 go-module +github.com/Microsoft/hcsshim v0.13.0 go-module +github.com/Microsoft/hcsshim v0.14.0-rc.1 go-module (+1 duplicate) +github.com/NVIDIA/go-nvlib v0.8.1 go-module (+3 duplicates) +github.com/NVIDIA/go-nvml v0.13.0-1 go-module (+3 duplicates) +github.com/NVIDIA/nvidia-container-toolkit v1.18.1 go-module (+3 duplicates) +github.com/RackSec/srslog v0.0.0-20180709174129-a4725f04ec91 go-module +github.com/a8m/envsubst v1.4.2 go-module (+1 duplicate) +github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d go-module +github.com/agext/levenshtein v1.2.3 go-module +github.com/alecthomas/participle/v2 v2.1.4 go-module (+1 duplicate) +github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 go-module +github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 go-module +github.com/armon/go-metrics v0.4.1 go-module +github.com/aws/aws-sdk-go-v2 v1.30.3 go-module +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 go-module +github.com/aws/aws-sdk-go-v2/config v1.27.27 go-module +github.com/aws/aws-sdk-go-v2/credentials v1.17.27 go-module +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 go-module +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 go-module +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 go-module +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 go-module +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.32.0 go-module +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 go-module +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 go-module +github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 go-module +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 go-module +github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 go-module +github.com/aws/smithy-go v1.20.3 go-module +github.com/beorn7/perks v1.0.1 go-module (+2 duplicates) +github.com/bits-and-blooms/bitset v1.13.0 go-module +github.com/buger/goterm v1.0.4 go-module +github.com/cenkalti/backoff/v4 v4.3.0 go-module (+1 duplicate) +github.com/cenkalti/backoff/v5 v5.0.3 go-module +github.com/cespare/xxhash/v2 v2.3.0 go-module (+2 duplicates) +github.com/checkpoint-restore/checkpointctl v1.4.0 go-module +github.com/checkpoint-restore/go-criu/v6 v6.3.0 go-module +github.com/checkpoint-restore/go-criu/v7 v7.2.0 go-module +github.com/cilium/ebpf v0.16.0 go-module (+2 duplicates) +github.com/cilium/ebpf v0.17.3 go-module (+1 duplicate) +github.com/cloudflare/cfssl v1.6.4 go-module +github.com/compose-spec/compose-go/v2 v2.10.0 go-module +github.com/container-storage-interface/spec v1.5.0 go-module +github.com/containerd/accelerated-container-image v1.3.0 go-module +github.com/containerd/btrfs/v2 v2.0.0 go-module +github.com/containerd/cgroups/v3 v3.0.5 go-module +github.com/containerd/cgroups/v3 v3.1.2 go-module (+2 duplicates) +github.com/containerd/console v1.0.5 go-module (+5 duplicates) +github.com/containerd/containerd/api v1.10.0 go-module (+3 duplicates) +github.com/containerd/containerd/api v1.9.0 go-module +github.com/containerd/containerd/v2 v2.1.4 go-module +github.com/containerd/containerd/v2 v2.2.1 go-module (+2 duplicates) +github.com/containerd/containerd/v2 v2.2.1-0.20251115011841-efd86f2b0bc2 go-module +github.com/containerd/continuity v0.4.5 go-module (+4 duplicates) +github.com/containerd/errdefs v1.0.0 go-module (+4 duplicates) +github.com/containerd/errdefs/pkg v0.3.0 go-module (+4 duplicates) +github.com/containerd/fifo v1.1.0 go-module (+3 duplicates) +github.com/containerd/go-cni v1.1.12 go-module +github.com/containerd/go-cni v1.1.13 go-module (+1 duplicate) +github.com/containerd/go-runc v1.1.0 go-module (+3 duplicates) +github.com/containerd/imgcrypt/v2 v2.0.1 go-module +github.com/containerd/log v0.1.0 go-module (+5 duplicates) +github.com/containerd/nri v0.11.0 go-module +github.com/containerd/otelttrpc v0.1.0 go-module +github.com/containerd/platforms v1.0.0-rc.1 go-module +github.com/containerd/platforms v1.0.0-rc.2 go-module (+2 duplicates) +github.com/containerd/plugin v1.0.0 go-module (+3 duplicates) +github.com/containerd/stargz-snapshotter/estargz v0.16.3 go-module +github.com/containerd/ttrpc v1.2.7 go-module (+4 duplicates) +github.com/containerd/typeurl/v2 v2.2.3 go-module (+4 duplicates) +github.com/containerd/zfs/v2 v2.0.0 go-module +github.com/containernetworking/cni v1.3.0 go-module (+2 duplicates) +github.com/containernetworking/plugins v1.7.1 go-module +github.com/containernetworking/plugins v1.9.0 go-module +github.com/containers/ocicrypt v1.2.1 go-module +github.com/coreos/go-systemd/v22 v22.5.0 go-module (+1 duplicate) +github.com/coreos/go-systemd/v22 v22.6.0 go-module (+2 duplicates) +github.com/cyphar/filepath-securejoin v0.4.1 go-module +github.com/cyphar/filepath-securejoin v0.5.1 go-module (+3 duplicates) +github.com/cyphar/filepath-securejoin v0.5.2 go-module +github.com/davecgh/go-spew v1.1.1 go-module (+2 duplicates) +github.com/deckarep/golang-set/v2 v2.3.0 go-module +github.com/dimchansky/utfbom v1.1.1 go-module (+2 duplicates) +github.com/distribution/reference v0.6.0 go-module (+3 duplicates) +github.com/docker/buildx v0.30.1 go-module +github.com/docker/cli v28.5.2+incompatible go-module +github.com/docker/cli-docs-tool v0.11.0 go-module +github.com/docker/cli/cmd/docker UNKNOWN go-module +github.com/docker/compose/v5 v0.0.0-20251218103533-c89b8a2d6b44 go-module +github.com/docker/distribution v2.8.3+incompatible go-module (+1 duplicate) +github.com/docker/docker v28.5.2 go-module (+1 duplicate) +github.com/docker/docker v28.5.2+incompatible go-module +github.com/docker/docker-credential-helpers v0.9.3 go-module +github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c go-module +github.com/docker/go-connections v0.5.0 go-module +github.com/docker/go-connections v0.6.0 go-module +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c go-module +github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 go-module +github.com/docker/go-metrics v0.0.1 go-module (+2 duplicates) +github.com/docker/go-units v0.5.0 go-module (+5 duplicates) +github.com/docker/libtrust v0.0.0-20150526203908-9cbd2a1374f4 go-module +github.com/dustin/go-humanize v1.0.0 go-module +github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 go-module +github.com/elliotchance/orderedmap v1.8.0 go-module (+1 duplicate) +github.com/emicklei/go-restful/v3 v3.13.0 go-module +github.com/fatih/color v1.18.0 go-module (+1 duplicate) +github.com/felixge/httpsnoop v1.0.4 go-module (+3 duplicates) +github.com/fernet/fernet-go v0.0.0-20240119011108-303da6aec611 go-module +github.com/fluent/fluent-logger-golang v1.9.0 go-module +github.com/fsnotify/fsnotify v1.7.0 go-module (+3 duplicates) +github.com/fsnotify/fsnotify v1.9.0 go-module (+2 duplicates) +github.com/fvbommel/sortorder v1.1.0 go-module +github.com/fxamacker/cbor/v2 v2.9.0 go-module (+1 duplicate) +github.com/go-jose/go-jose/v4 v4.1.2 go-module +github.com/go-logr/logr v1.4.2 go-module +github.com/go-logr/logr v1.4.3 go-module (+2 duplicates) +github.com/go-logr/stdr v1.2.2 go-module (+3 duplicates) +github.com/go-viper/mapstructure/v2 v2.4.0 go-module +github.com/goccy/go-json v0.10.5 go-module (+1 duplicate) +github.com/goccy/go-yaml v1.13.3 go-module (+1 duplicate) +github.com/godbus/dbus/v5 v5.1.0 go-module (+4 duplicates) +github.com/gofrs/flock v0.12.1 go-module +github.com/gofrs/flock v0.13.0 go-module +github.com/gogo/protobuf v1.3.2 go-module (+4 duplicates) +github.com/golang-jwt/jwt/v5 v5.2.2 go-module +github.com/golang-jwt/jwt/v5 v5.3.0 go-module +github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2 go-module +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da go-module +github.com/golang/protobuf v1.5.4 go-module (+2 duplicates) +github.com/google/btree v1.1.2 go-module +github.com/google/certificate-transparency-go v1.1.4 go-module +github.com/google/go-cmp v0.7.0 go-module (+4 duplicates) +github.com/google/s2a-go v0.1.7 go-module +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 go-module (+1 duplicate) +github.com/google/uuid v1.6.0 go-module (+6 duplicates) +github.com/googleapis/enterprise-certificate-proxy v0.3.2 go-module +github.com/googleapis/gax-go/v2 v2.12.0 go-module +github.com/gorilla/mux v1.8.1 go-module (+1 duplicate) +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 go-module +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 go-module +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 go-module +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 go-module +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 go-module (+1 duplicate) +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 go-module +github.com/hashicorp/errwrap v1.1.0 go-module (+1 duplicate) +github.com/hashicorp/go-immutable-radix v1.3.1 go-module +github.com/hashicorp/go-immutable-radix/v2 v2.1.0 go-module +github.com/hashicorp/go-memdb v1.3.2 go-module +github.com/hashicorp/go-msgpack v0.5.5 go-module +github.com/hashicorp/go-multierror v1.1.1 go-module (+1 duplicate) +github.com/hashicorp/go-sockaddr v1.0.2 go-module +github.com/hashicorp/go-version v1.8.0 go-module +github.com/hashicorp/golang-lru v0.5.4 go-module +github.com/hashicorp/golang-lru/v2 v2.0.7 go-module +github.com/hashicorp/memberlist v0.4.0 go-module +github.com/hashicorp/serf v0.8.5 go-module +github.com/in-toto/in-toto-golang v0.9.0 go-module (+1 duplicate) +github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf go-module +github.com/intel/goresctrl v0.10.0 go-module (+1 duplicate) +github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2 go-module (+1 duplicate) +github.com/jinzhu/copier v0.4.0 go-module (+1 duplicate) +github.com/jmoiron/sqlx v1.3.3 go-module +github.com/jonboulle/clockwork v0.5.0 go-module +github.com/json-iterator/go v1.1.12 go-module +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 go-module +github.com/klauspost/compress v1.18.0 go-module +github.com/klauspost/compress v1.18.1 go-module (+2 duplicates) +github.com/knqyf263/go-plugin v0.9.0 go-module +github.com/magiconair/properties v1.8.9 go-module (+1 duplicate) +github.com/mattn/go-colorable v0.1.13 go-module (+1 duplicate) +github.com/mattn/go-colorable v0.1.14 go-module +github.com/mattn/go-isatty v0.0.20 go-module (+2 duplicates) +github.com/mattn/go-runewidth v0.0.16 go-module +github.com/mattn/go-shellwords v1.0.12 go-module +github.com/mdlayher/socket v0.5.1 go-module (+2 duplicates) +github.com/mdlayher/vsock v1.2.1 go-module (+2 duplicates) +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b go-module +github.com/miekg/dns v1.1.66 go-module +github.com/miekg/pkcs11 v1.1.1 go-module +github.com/mikefarah/yq/v4 v0.0.0-20250410031946-f00e28295f0c go-module (+1 duplicate) +github.com/mistifyio/go-zfs/v3 v3.0.1 go-module (+1 duplicate) +github.com/mitchellh/copystructure v1.2.0 go-module +github.com/mitchellh/hashstructure/v2 v2.0.2 go-module (+1 duplicate) +github.com/mitchellh/reflectwalk v1.0.2 go-module +github.com/moby/buildkit v0.25.2 go-module +github.com/moby/buildkit v0.26.3 go-module +github.com/moby/docker-image-spec v1.3.1 go-module (+1 duplicate) +github.com/moby/go-archive v0.1.0 go-module (+1 duplicate) +github.com/moby/ipvs v1.1.0 go-module +github.com/moby/locker v1.0.1 go-module (+3 duplicates) +github.com/moby/patternmatcher v0.6.0 go-module (+1 duplicate) +github.com/moby/profiles/apparmor v0.1.0 go-module +github.com/moby/profiles/seccomp v0.1.0 go-module +github.com/moby/pubsub v1.0.0 go-module +github.com/moby/spdystream v0.5.0 go-module +github.com/moby/swarmkit/v2 v2.0.0 go-module +github.com/moby/sys/atomicwriter v0.1.0 go-module (+1 duplicate) +github.com/moby/sys/capability v0.4.0 go-module (+7 duplicates) +github.com/moby/sys/mount v0.3.4 go-module +github.com/moby/sys/mountinfo v0.7.2 go-module (+4 duplicates) +github.com/moby/sys/reexec v0.1.0 go-module (+2 duplicates) +github.com/moby/sys/sequential v0.6.0 go-module (+1 duplicate) +github.com/moby/sys/signal v0.7.1 go-module (+3 duplicates) +github.com/moby/sys/symlink v0.3.0 go-module (+4 duplicates) +github.com/moby/sys/user v0.3.0 go-module +github.com/moby/sys/user v0.4.0 go-module (+3 duplicates) +github.com/moby/sys/userns v0.1.0 go-module (+5 duplicates) +github.com/moby/term v0.5.2 go-module (+1 duplicate) +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd go-module +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee go-module +github.com/morikuni/aec v1.0.0 go-module +github.com/morikuni/aec v1.1.0 go-module +github.com/mrunalp/fileutils v0.5.1 go-module +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 go-module (+2 duplicates) +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f go-module +github.com/opencontainers/cgroups v0.0.3 go-module +github.com/opencontainers/cgroups v0.0.4 go-module +github.com/opencontainers/go-digest v1.0.0 go-module (+4 duplicates) +github.com/opencontainers/image-spec v1.1.1 go-module (+4 duplicates) +github.com/opencontainers/runc v1.3.3 go-module (+1 duplicate) +github.com/opencontainers/runc v1.3.4 go-module +github.com/opencontainers/runtime-spec v1.2.1 go-module (+1 duplicate) +github.com/opencontainers/runtime-spec v1.3.0 go-module (+6 duplicates) +github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 go-module +github.com/opencontainers/runtime-tools v0.9.1-0.20251114084447-edf4cb3d2116 go-module (+5 duplicates) +github.com/opencontainers/selinux v1.12.0 go-module +github.com/opencontainers/selinux v1.13.1 go-module (+2 duplicates) +github.com/package-url/packageurl-go v0.1.1 go-module +github.com/pelletier/go-toml v1.9.5 go-module (+5 duplicates) +github.com/pelletier/go-toml/v2 v2.2.3 go-module (+1 duplicate) +github.com/pelletier/go-toml/v2 v2.2.4 go-module (+2 duplicates) +github.com/philhofer/fwd v1.1.2 go-module +github.com/pkg/errors v0.9.1 go-module (+1 duplicate) +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 go-module (+1 duplicate) +github.com/pmezard/go-difflib v1.0.0 go-module (+1 duplicate) +github.com/prometheus/client_golang v1.22.0 go-module +github.com/prometheus/client_golang v1.23.2 go-module (+1 duplicate) +github.com/prometheus/client_model v0.6.1 go-module +github.com/prometheus/client_model v0.6.2 go-module (+1 duplicate) +github.com/prometheus/common v0.62.0 go-module +github.com/prometheus/common v0.66.1 go-module (+1 duplicate) +github.com/prometheus/procfs v0.15.1 go-module +github.com/prometheus/procfs v0.16.1 go-module (+1 duplicate) +github.com/rivo/uniseg v0.2.0 go-module +github.com/rootless-containers/rootlesskit/v2 v2.3.4 go-module +github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 go-module +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 go-module +github.com/seccomp/libseccomp-golang v0.10.0 go-module +github.com/secure-systems-lab/go-securesystemslib v0.6.0 go-module +github.com/secure-systems-lab/go-securesystemslib v0.9.1 go-module +github.com/shibumi/go-pathspec v1.3.0 go-module (+1 duplicate) +github.com/sirupsen/logrus v1.9.3 go-module (+10 duplicates) +github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 go-module +github.com/smallstep/pkcs7 v0.1.1 go-module +github.com/spdx/tools-golang v0.5.5 go-module +github.com/spf13/cobra v1.10.2 go-module +github.com/spf13/cobra v1.8.1 go-module (+1 duplicate) +github.com/spf13/cobra v1.9.1 go-module +github.com/spf13/pflag v1.0.10 go-module +github.com/spf13/pflag v1.0.6 go-module (+2 duplicates) +github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 go-module +github.com/stretchr/testify v1.10.0 go-module +github.com/stretchr/testify v1.11.1 go-module +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 go-module +github.com/tchap/go-patricia/v2 v2.3.3 go-module +github.com/tetratelabs/wazero v1.10.1 go-module +github.com/theupdateframework/notary v0.7.0 go-module +github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 go-module +github.com/tinylib/msgp v1.1.8 go-module +github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 go-module (+1 duplicate) +github.com/tonistiigi/fsutil v0.0.0-20250605211040-586307ad452f go-module (+1 duplicate) +github.com/tonistiigi/go-actions-cache v0.0.0-20250626083717-378c5ed1ddd9 go-module +github.com/tonistiigi/go-archvariant v1.0.0 go-module +github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 go-module (+1 duplicate) +github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea go-module (+1 duplicate) +github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab go-module +github.com/urfave/cli v1.22.16 go-module +github.com/urfave/cli-altsrc/v3 v3.1.0 go-module +github.com/urfave/cli/v2 v2.27.7 go-module (+1 duplicate) +github.com/urfave/cli/v3 v3.4.1 go-module (+1 duplicate) +github.com/vbatts/tar-split v0.12.1 go-module +github.com/vishvananda/netlink v1.3.0 go-module +github.com/vishvananda/netlink v1.3.1 go-module (+1 duplicate) +github.com/vishvananda/netns v0.0.4 go-module +github.com/vishvananda/netns v0.0.5 go-module (+1 duplicate) +github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b go-module +github.com/x448/float16 v0.8.4 go-module (+1 duplicate) +github.com/xhit/go-str2duration/v2 v2.1.0 go-module +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 go-module (+1 duplicate) +github.com/yuin/gopher-lua v1.1.1 go-module (+1 duplicate) +github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc go-module +github.com/zmap/zlint/v3 v3.1.0 go-module +glob 10.4.2 npm +gnupg 2.4.4-2ubuntu17.4 deb +gnupg-l10n 2.4.4-2ubuntu17.4 deb +gnupg-utils 2.4.4-2ubuntu17.4 deb +go.etcd.io/bbolt v1.4.3 go-module (+1 duplicate) +go.etcd.io/etcd/client/pkg/v3 v3.5.16 go-module +go.etcd.io/etcd/pkg/v3 v3.5.16 go-module +go.etcd.io/etcd/raft/v3 v3.5.16 go-module +go.etcd.io/etcd/server/v3 v3.5.16 go-module +go.opencensus.io v0.24.0 go-module +go.opentelemetry.io/auto/sdk v1.1.0 go-module (+2 duplicates) +go.opentelemetry.io/auto/sdk v1.2.1 go-module +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 go-module (+1 duplicate) +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 go-module +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 go-module +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0 go-module +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 go-module (+2 duplicates) +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 go-module +go.opentelemetry.io/contrib/processors/baggagecopy v0.4.0 go-module +go.opentelemetry.io/otel v1.35.0 go-module +go.opentelemetry.io/otel v1.37.0 go-module (+1 duplicate) +go.opentelemetry.io/otel v1.38.0 go-module +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 go-module +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 go-module +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 go-module +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0 go-module +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 go-module (+1 duplicate) +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 go-module +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 go-module (+1 duplicate) +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 go-module +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 go-module (+1 duplicate) +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 go-module +go.opentelemetry.io/otel/metric v1.35.0 go-module +go.opentelemetry.io/otel/metric v1.37.0 go-module (+1 duplicate) +go.opentelemetry.io/otel/metric v1.38.0 go-module +go.opentelemetry.io/otel/sdk v1.35.0 go-module +go.opentelemetry.io/otel/sdk v1.37.0 go-module +go.opentelemetry.io/otel/sdk v1.38.0 go-module +go.opentelemetry.io/otel/sdk/metric v1.35.0 go-module +go.opentelemetry.io/otel/sdk/metric v1.38.0 go-module +go.opentelemetry.io/otel/trace v1.35.0 go-module +go.opentelemetry.io/otel/trace v1.37.0 go-module (+1 duplicate) +go.opentelemetry.io/otel/trace v1.38.0 go-module +go.opentelemetry.io/proto/otlp v1.5.0 go-module (+1 duplicate) +go.opentelemetry.io/proto/otlp v1.7.1 go-module +go.uber.org/atomic v1.9.0 go-module +go.uber.org/mock v0.6.0 go-module +go.uber.org/multierr v1.8.0 go-module +go.uber.org/zap v1.21.0 go-module +go.yaml.in/yaml/v2 v2.4.2 go-module (+2 duplicates) +go.yaml.in/yaml/v4 v4.0.0-rc.3 go-module +golang.org/x/crypto v0.37.0 go-module +golang.org/x/crypto v0.45.0 go-module (+1 duplicate) +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f go-module (+2 duplicates) +golang.org/x/mod v0.24.0 go-module +golang.org/x/mod v0.29.0 go-module (+5 duplicates) +golang.org/x/net v0.35.0 go-module +golang.org/x/net v0.39.0 go-module (+3 duplicates) +golang.org/x/net v0.47.0 go-module (+3 duplicates) +golang.org/x/oauth2 v0.29.0 go-module +golang.org/x/oauth2 v0.30.0 go-module +golang.org/x/sync v0.16.0 go-module +golang.org/x/sync v0.18.0 go-module (+2 duplicates) +golang.org/x/sync v0.19.0 go-module +golang.org/x/sys v0.30.0 go-module +golang.org/x/sys v0.32.0 go-module (+1 duplicate) +golang.org/x/sys v0.33.0 go-module (+1 duplicate) +golang.org/x/sys v0.37.0 go-module (+3 duplicates) +golang.org/x/sys v0.38.0 go-module (+2 duplicates) +golang.org/x/sys v0.39.0 go-module +golang.org/x/term v0.37.0 go-module (+1 duplicate) +golang.org/x/text v0.24.0 go-module (+2 duplicates) +golang.org/x/text v0.31.0 go-module (+2 duplicates) +golang.org/x/time v0.11.0 go-module +golang.org/x/time v0.14.0 go-module (+1 duplicate) +google.golang.org/api v0.160.0 go-module +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de go-module +google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a go-module +google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b go-module +google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 go-module +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a go-module +google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b go-module (+2 duplicates) +google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 go-module +google.golang.org/grpc v1.72.2 go-module +google.golang.org/grpc v1.76.0 go-module (+2 duplicates) +google.golang.org/grpc v1.77.0 go-module +google.golang.org/protobuf v1.36.10 go-module (+3 duplicates) +google.golang.org/protobuf v1.36.5 go-module +google.golang.org/protobuf v1.36.9 go-module +gopd 1.2.0 npm +gopkg.in/inf.v0 v0.9.1 go-module (+1 duplicate) +gopkg.in/ini.v1 v1.67.0 go-module +gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 go-module (+1 duplicate) +gopkg.in/yaml.v3 v3.0.1 go-module (+9 duplicates) +gpg 2.4.4-2ubuntu17.4 deb +gpg-agent 2.4.4-2ubuntu17.4 deb +gpg-wks-client 2.4.4-2ubuntu17.4 deb +gpgconf 2.4.4-2ubuntu17.4 deb +gpgsm 2.4.4-2ubuntu17.4 deb +gpgv 2.4.4-2ubuntu17.4 deb +graceful-fs 4.2.11 npm +grep 3.11-4build1 deb +gzip 1.12-1ubuntu3.1 deb +has-symbols 1.1.0 npm +hasown 2.0.2 npm +hosted-git-info 7.0.2 npm +hostname 3.23+nmu2ubuntu2 deb +http-cache-semantics 4.1.1 npm +http-errors 2.0.1 npm +http-proxy-agent 7.0.2 npm +https-proxy-agent 7.0.5 npm +iconv-lite 0.4.24 npm +iconv-lite 0.6.3 npm +ieee754 1.2.1 npm +ignore-walk 6.0.5 npm +imurmurhash 0.1.4 npm +indent-string 4.0.0 npm +inherits 2.0.4 npm +ini 4.1.3 npm +init-package-json 6.0.3 npm +init-system-helpers 1.66ubuntu1 deb +ip-address 9.0.5 npm +ip-regex 5.0.0 npm +ipaddr.js 1.9.1 npm +iproute2 6.1.0-1ubuntu6.2 deb +iptables 1.8.10-3ubuntu2 deb +is-cidr 5.1.0 npm +is-fullwidth-code-point 3.0.0 npm +is-lambda 1.0.1 npm +isexe 2.0.0 npm +isexe 3.1.1 npm +jackspeak 3.4.0 npm +jq 1.7.1-3ubuntu0.24.04.1 deb +js-yaml 4.1.1 npm +jsbn 1.1.0 npm +json-parse-even-better-errors 3.0.2 npm +json-stringify-nice 1.1.4 npm +jsonparse 1.3.1 npm +just-diff 6.0.2 npm +just-diff-apply 5.5.0 npm +k8s.io/api v0.34.1 go-module +k8s.io/apimachinery v0.34.1 go-module (+1 duplicate) +k8s.io/client-go v0.34.1 go-module +k8s.io/cri-api v0.34.1 go-module +k8s.io/klog/v2 v2.130.1 go-module (+1 duplicate) +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 go-module +kasm-wizard 0.0.1 npm +keyboxd 2.4.4-2ubuntu17.4 deb +krb5-locales 1.20.1-6ubuntu2.6 deb +libacl1 2.3.2-1build1.1 deb +libapparmor1 4.0.1really4.0.1-0ubuntu0.24.04.5 deb +libapt-pkg6.0t64 2.8.3 deb +libassuan0 2.5.6-1build1 deb +libattr1 1:2.5.2-1build1.1 deb +libaudit-common 1:3.1.2-2.1build1.1 deb +libaudit1 1:3.1.2-2.1build1.1 deb +libblkid1 2.39.3-9ubuntu6.4 deb +libbpf1 1:1.3.0-2build2 deb +libbrotli1 1.1.0-2build2 deb +libbsd0 0.12.1-1build1.1 deb +libbz2-1.0 1.0.8-5.1build0.1 deb +libc-bin 2.39-0ubuntu8.6 deb +libc6 2.39-0ubuntu8.6 deb +libcap-ng0 0.8.4-2build2 deb +libcap2 1:2.66-5ubuntu2.2 deb +libcap2-bin 1:2.66-5ubuntu2.2 deb +libcom-err2 1.47.0-2.4~exp1ubuntu4.1 deb +libcrypt-dev 1:4.4.36-4build1 deb +libcrypt1 1:4.4.36-4build1 deb +libcurl4t64 8.5.0-2ubuntu10.6 deb +libdb5.3t64 5.3.28+dfsg2-7 deb +libdebconfclient0 0.271ubuntu3 deb +libdevmapper1.02.1 2:1.02.185-3ubuntu3.2 deb +libedit2 3.1-20230828-1build1 deb +libelf1t64 0.190-1.1ubuntu0.1 deb +libexpat1 2.6.1-2ubuntu0.3 deb +libext2fs2t64 1.47.0-2.4~exp1ubuntu4.1 deb +libffi8 3.4.6-1build1 deb +libfuse3-3 3.14.0-5build1 deb +libgcc-s1 14.2.0-4ubuntu2~24.04 deb +libgcrypt20 1.10.3-2build1 deb +libgmp10 2:6.3.0+dfsg-2ubuntu6.1 deb +libgnutls30t64 3.8.3-1.1ubuntu3.4 deb +libgpg-error0 1.47-3build2.1 deb +libgssapi-krb5-2 1.20.1-6ubuntu2.6 deb +libhogweed6t64 3.9.1-2.2build1.1 deb +libicu74 74.2-1ubuntu3.1 deb +libidn2-0 2.3.7-2build1.1 deb +libinih1 55-1ubuntu2 deb +libip4tc2 1.8.10-3ubuntu2 deb +libip6tc2 1.8.10-3ubuntu2 deb +libjansson4 2.14-2build2 deb +libjq1 1.7.1-3ubuntu0.24.04.1 deb +libk5crypto3 1.20.1-6ubuntu2.6 deb +libkeyutils1 1.6.3-3build1 deb +libkrb5-3 1.20.1-6ubuntu2.6 deb +libkrb5support0 1.20.1-6ubuntu2.6 deb +libksba8 1.6.6-1build1 deb +libldap-common 2.6.7+dfsg-1~exp1ubuntu8.2 deb +libldap2 2.6.7+dfsg-1~exp1ubuntu8.2 deb +liblz4-1 1.9.4-1build1.1 deb +liblzma5 5.6.1+really5.4.5-1ubuntu0.2 deb +liblzo2-2 2.10-2build4 deb +libmd0 1.1.0-2build1.1 deb +libmnl0 1.0.5-2build1 deb +libmount1 2.39.3-9ubuntu6.4 deb +libncursesw6 6.4+20240113-1ubuntu2 deb +libnetfilter-conntrack3 1.0.9-6build1 deb +libnettle8t64 3.9.1-2.2build1.1 deb +libnfnetlink0 1.0.2-2build1 deb +libnftables1 1.0.9-1build1 deb +libnftnl11 1.2.6-2build1 deb +libnghttp2-14 1.59.0-1ubuntu0.2 deb +libnpmaccess 8.0.6 npm +libnpmdiff 6.1.4 npm +libnpmexec 8.1.3 npm +libnpmfund 5.0.12 npm +libnpmhook 10.0.5 npm +libnpmorg 6.0.6 npm +libnpmpack 7.0.4 npm +libnpmpublish 9.0.9 npm +libnpmsearch 7.0.6 npm +libnpmteam 6.0.5 npm +libnpmversion 6.0.3 npm +libnpth0t64 1.6-3.1build1 deb +libnvidia-container-tools 1.18.1-1 deb +libnvidia-container1 1.18.1-1 deb +libonig5 6.9.9-1build1 deb +libp11-kit0 0.25.3-4ubuntu2.1 deb +libpam-modules 1.5.3-5ubuntu5.5 deb +libpam-modules-bin 1.5.3-5ubuntu5.5 deb +libpam-runtime 1.5.3-5ubuntu5.5 deb +libpam0g 1.5.3-5ubuntu5.5 deb +libpcre2-8-0 10.42-4ubuntu2.1 deb +libproc2-0 2:4.0.4-4ubuntu3.2 deb +libpsl5t64 0.21.2-1.1build1 deb +libpython3-stdlib 3.12.3-0ubuntu2.1 deb +libpython3.12-minimal 3.12.3-1ubuntu0.10 deb +libpython3.12-stdlib 3.12.3-1ubuntu0.10 deb +libreadline8t64 8.2-4build1 deb +libreiserfscore0t64 1:3.6.27-7.1build1 deb +librtmp1 2.4+20151223.gitfa8646d.1-2build7 deb +libsasl2-2 2.1.28+dfsg1-5ubuntu3.1 deb +libsasl2-modules 2.1.28+dfsg1-5ubuntu3.1 deb +libsasl2-modules-db 2.1.28+dfsg1-5ubuntu3.1 deb +libseccomp2 2.5.5-1ubuntu3.1 deb +libselinux1 3.5-2ubuntu2.1 deb +libsemanage-common 3.5-1build5 deb +libsemanage2 3.5-1build5 deb +libsepol2 3.5-2build1 deb +libsmartcols1 2.39.3-9ubuntu6.4 deb +libsqlite3-0 3.45.1-1ubuntu2.5 deb +libss2 1.47.0-2.4~exp1ubuntu4.1 deb +libssh-4 0.10.6-2ubuntu0.2 deb +libssl3t64 3.0.13-0ubuntu3.6 deb +libstdc++6 14.2.0-4ubuntu2~24.04 deb +libsubid4 1:4.13+dfsg1-4ubuntu3.2 deb +libsystemd0 255.4-1ubuntu8.12 deb +libtasn1-6 4.19.0-3ubuntu0.24.04.2 deb +libtinfo6 6.4+20240113-1ubuntu2 deb +libtirpc-common 1.3.4+ds-1.1build1 deb +libtirpc3t64 1.3.4+ds-1.1build1 deb +libudev1 255.4-1ubuntu8.12 deb +libunistring5 1.1-2build1.1 deb +liburcu8t64 0.14.0-3.1build1 deb +libuuid1 2.39.3-9ubuntu6.4 deb +libxtables12 1.8.10-3ubuntu2 deb +libxxhash0 0.8.2-2build1 deb +libzstd1 1.5.5+dfsg2-2build1.1 deb +locales 2.39-0ubuntu8.6 deb +lodash 4.17.21 npm +login 1:4.13+dfsg1-4ubuntu3.2 deb +logsave 1.47.0-2.4~exp1ubuntu4.1 deb +lru-cache 10.2.2 npm +lsof 4.95.0-1build3 deb +make-fetch-happen 13.0.1 npm +math-intrinsics 1.1.0 npm +mawk 1.3.4.20240123-1build1 deb +media-typer 0.3.0 npm +media-types 10.1.0 deb +merge-descriptors 1.0.3 npm +methods 1.1.2 npm +mime 1.6.0 npm +mime-db 1.52.0 npm +mime-types 2.1.35 npm +minimatch 9.0.5 npm +minipass 3.3.6 npm (+4 duplicates) +minipass 5.0.0 npm +minipass 7.1.2 npm +minipass-collect 2.0.1 npm +minipass-fetch 3.0.5 npm +minipass-flush 1.0.5 npm +minipass-pipeline 1.2.4 npm +minipass-sized 1.0.3 npm +minizlib 2.1.2 npm +mkdirp 1.0.4 npm +mkdirp-classic 0.5.3 npm +mount 2.39.3-9ubuntu6.4 deb +ms 2.0.0 npm (+3 duplicates) +ms 2.1.2 npm +ms 2.1.3 npm (+1 duplicate) +mute-stream 1.0.0 npm +nan 2.24.0 npm +ncurses-base 6.4+20240113-1ubuntu2 deb +ncurses-bin 6.4+20240113-1ubuntu2 deb +negotiator 0.6.3 npm (+1 duplicate) +netbase 6.4 deb +netcat-openbsd 1.226-1ubuntu2 deb +nftables 1.0.9-1build1 deb +node-gyp 10.1.0 npm +node-pty 0.10.1 npm +nodejs 20.20.0-1nodesource1 deb +nopt 7.2.1 npm +normalize-package-data 6.0.2 npm +npm 10.8.2 npm +npm-audit-report 5.0.0 npm +npm-bundled 3.0.1 npm +npm-install-checks 6.3.0 npm +npm-normalize-package-bin 3.0.1 npm +npm-package-arg 11.0.2 npm +npm-packlist 8.0.2 npm +npm-pick-manifest 9.1.0 npm +npm-profile 10.0.0 npm +npm-registry-fetch 17.1.0 npm +npm-user-validate 2.0.1 npm +nvidia-container-toolkit 1.18.1-1 deb +nvidia-container-toolkit-base 1.18.1-1 deb +object-assign 4.1.1 npm +object-inspect 1.13.4 npm +on-finished 2.4.1 npm +once 1.4.0 npm +openssl 3.0.13-0ubuntu3.6 deb +p-map 4.0.0 npm +package-json-from-dist 1.0.0 npm +pacote 18.0.6 npm +pagent UNKNOWN binary +parse-conflict-json 3.0.1 npm +parseurl 1.3.3 npm +passwd 1:4.13+dfsg1-4ubuntu3.2 deb +path-key 3.1.1 npm +path-scurry 1.11.1 npm +path-to-regexp 0.1.12 npm +perl 5.38.2-3.2ubuntu0.2 deb +perl-base 5.38.2-3.2ubuntu0.2 deb +pigz 2.8-1 deb +pinentry-curses 1.2.1-3ubuntu5 deb +postcss-selector-parser 6.1.0 npm +proc-log 3.0.0 npm +proc-log 4.2.0 npm +procps 2:4.0.4-4ubuntu3.2 deb +proggy 2.0.0 npm +promise-all-reject-late 1.0.1 npm +promise-call-limit 3.0.1 npm +promise-inflight 1.0.1 npm +promise-retry 2.0.1 npm +promzard 1.0.2 npm +proxy-addr 2.0.7 npm +publicsuffix 20231001.0357-0.1 deb +pump 3.0.3 npm +python3 3.12.3-0ubuntu2.1 deb +python3-minimal 3.12.3-0ubuntu2.1 deb +python3.12 3.12.3-1ubuntu0.10 deb +python3.12-minimal 3.12.3-1ubuntu0.10 deb +qrcode-terminal 0.12.0 npm +qs 6.14.1 npm +range-parser 1.2.1 npm +raw-body 2.5.3 npm +read 3.0.1 npm +read-cmd-shim 4.0.0 npm +read-package-json-fast 3.0.2 npm +readable-stream 3.6.2 npm +readline-common 8.2-4build1 deb +resenje.org/singleflight v0.4.3 go-module +retry 0.12.0 npm +safe-buffer 5.2.1 npm +safer-buffer 2.1.2 npm (+1 duplicate) +sed 4.9-2build1 deb +semver 7.6.2 npm +send 0.19.2 npm +sensible-utils 0.0.22 deb +serve-static 1.16.3 npm +setprototypeof 1.2.0 npm +shebang-command 2.0.0 npm +shebang-regex 3.0.0 npm +side-channel 1.1.0 npm +side-channel-list 1.0.0 npm +side-channel-map 1.0.1 npm +side-channel-weakmap 1.0.2 npm +signal-exit 4.1.0 npm +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 go-module (+1 duplicate) +sigs.k8s.io/randfill v1.0.0 go-module +sigs.k8s.io/structured-merge-diff/v6 v6.3.0 go-module +sigs.k8s.io/yaml v1.4.0 go-module (+4 duplicates) +sigs.k8s.io/yaml v1.6.0 go-module (+1 duplicate) +sigstore 2.3.1 npm +smart-buffer 4.2.0 npm +socket.io 4.8.3 npm +socket.io-adapter 2.5.6 npm +socket.io-parser 4.2.5 npm +socks 2.8.3 npm +socks-proxy-agent 8.0.4 npm +spdx-correct 3.2.0 npm +spdx-exceptions 2.5.0 npm +spdx-expression-parse 3.0.1 npm (+1 duplicate) +spdx-expression-parse 4.0.0 npm +spdx-license-ids 3.0.18 npm +split-ca 1.0.1 npm +sprintf-js 1.1.3 npm +ssh2 1.17.0 npm +ssri 10.0.6 npm +statuses 2.0.2 npm +stdlib go1.24.11 go-module (+4 duplicates) +stdlib go1.24.2 go-module (+1 duplicate) +stdlib go1.25.3 go-module (+2 duplicates) +stdlib go1.25.4 go-module (+3 duplicates) +string-width 4.2.3 npm (+1 duplicate) +string-width 5.1.2 npm (+1 duplicate) +string_decoder 1.3.0 npm +strip-ansi 6.0.1 npm (+1 duplicate) +strip-ansi 7.1.0 npm (+1 duplicate) +sudo 1.9.15p5-3ubuntu5.24.04.1 deb +supports-color 9.4.0 npm +systemd-standalone-sysusers 255.4-1ubuntu8.12 deb +systeminformation 5.30.5 npm +sysvinit-utils 3.08-6ubuntu3 deb +tags.cncf.io/container-device-interface v1.0.1 go-module +tags.cncf.io/container-device-interface v1.0.2-0.20251114135136-1b24d969689f go-module (+3 duplicates) +tags.cncf.io/container-device-interface v1.1.0 go-module (+2 duplicates) +tags.cncf.io/container-device-interface/specs-go v1.0.0 go-module (+4 duplicates) +tags.cncf.io/container-device-interface/specs-go v1.1.0 go-module (+1 duplicate) +tar 1.35+dfsg-3build1 deb +tar 6.2.1 npm +tar-fs 2.0.1 npm +tar-stream 2.2.0 npm +text-table 0.2.0 npm +tiny-relative-date 1.3.0 npm +toidentifier 1.0.1 npm +treeverse 3.0.0 npm +tuf-js 2.2.1 npm +tweetnacl 0.14.5 npm +type-is 1.6.18 npm +tzdata 2025b-0ubuntu0.24.04.1 deb +ubuntu-keyring 2023.11.28.1 deb +uidmap 1:4.13+dfsg1-4ubuntu3.2 deb +undici-types 7.16.0 npm +unique-filename 3.0.0 npm +unique-slug 4.0.0 npm +unminimize 0.2.1 deb +unpipe 1.0.0 npm +util-deprecate 1.0.2 npm (+1 duplicate) +util-linux 2.39.3-9ubuntu6.4 deb +utils-merge 1.0.1 npm +validate-npm-package-license 3.0.4 npm +validate-npm-package-name 5.0.1 npm +vary 1.1.2 npm +walk-up-path 3.0.1 npm +which 2.0.2 npm +which 4.0.0 npm +wrap-ansi 7.0.0 npm +wrap-ansi 8.1.0 npm +wrappy 1.0.2 npm +write-file-atomic 5.0.1 npm +ws 8.18.3 npm +xfsprogs 6.6.0-1ubuntu2.1 deb +xz-utils 5.6.1+really5.4.5-1ubuntu0.2 deb +yallist 4.0.0 npm +zlib1g 1:1.3.dfsg-3.1ubuntu2.1 deb diff --git a/readme-vars.yml b/readme-vars.yml index b48d6e3..cb9c974 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -6,85 +6,137 @@ project_blurb: | [{{ project_name|capitalize }}]({{ project_url }}) Workspaces is a docker container streaming platform for delivering browser-based access to desktops, applications, and web services. Kasm uses devops-enabled Containerized Desktop Infrastructure (CDI) to create on-demand, disposable, docker containers that are accessible via web browser. Example use-cases include Remote Browser Isolation (RBI), Data Loss Prevention (DLP), Desktop as a Service (DaaS), Secure Remote Access Services (RAS), and Open Source Intelligence (OSINT) collections. The rendering of the graphical-based containers is powered by the open-source project [KasmVNC](https://www.kasmweb.com/kasmvnc.html?utm_campaign=LinuxServer&utm_source=kasmvnc). - project_lsio_github_repo_url: "https://github.com/linuxserver/docker-{{ project_name }}" - -project_blurb_optional_extras_enabled: false -project_blurb_optional_extras: [] - +project_categories: "Remote Desktop,Business" # supported architectures available_architectures: - - { arch: "{{ arch_x86_64 }}", tag: "amd64-latest"} - - { arch: "{{ arch_arm64 }}", tag: "arm64v8-latest"} - + - {arch: "{{ arch_x86_64 }}", tag: "amd64-latest"} + - {arch: "{{ arch_arm64 }}", tag: "arm64v8-latest"} # development version -development_versions: true -development_versions_items: - - { tag: "latest", desc: "Stable Kasm releases" } - - { tag: "develop", desc: "Tip of develop" } - +development_versions: false # container parameters common_param_env_vars_enabled: false param_container_name: "{{ project_name }}" - param_usage_include_net: false - param_usage_include_env: true param_env_vars: - - { env_var: "KASM_PORT", env_value: "443", desc: "Specify the port you bind to the outside for Kasm Workspaces." } - - { env_var: "TZ", env_value: "Europe/London", desc: "Specify a timezone to use EG Europe/London." } - - + - {env_var: "KASM_PORT", env_value: "443", desc: "Specify the port you bind to the outside for Kasm Workspaces."} param_usage_include_vols: true param_volumes: - - { vol_path: "/opt", vol_host_path: "/path/to/data", desc: "Docker and installation storage." } - -param_device_map: false -param_devices: [] - + - {vol_path: "/opt", vol_host_path: "/path/to/{{ project_name }}/data", desc: "Docker and installation storage."} param_usage_include_ports: true param_ports: - - { external_port: "3000", internal_port: "3000", port_desc: "Kasm Installation wizard. (https)" } - - { external_port: "443", internal_port: "443", port_desc: "Kasm Workspaces interface. (https)" } - + - {external_port: "3000", internal_port: "3000", port_desc: "Kasm Installation wizard. (https)"} + - {external_port: "443", internal_port: "443", port_desc: "Kasm Workspaces interface. (https)"} # optional container parameters opt_param_usage_include_env: true opt_param_env_vars: - - { env_var: "DOCKER_HUB_USERNAME", env_value: "USER", desc: "Optionally specify a DockerHub Username to pull private images." } - - { env_var: "DOCKER_HUB_PASSWORD", env_value: "PASS", desc: "Optionally specify a DockerHub password to pull private images." } - + - {env_var: "DOCKER_HUB_USERNAME", env_value: "USER", desc: "Optionally specify a DockerHub Username to pull private images."} + - {env_var: "DOCKER_HUB_PASSWORD", env_value: "PASS", desc: "Optionally specify a DockerHub password to pull private images."} + - {env_var: "DOCKER_MTU", env_value: "1500", desc: "Optionally specify the mtu options passed to dockerd."} opt_param_usage_include_vols: true opt_param_volumes: - - { vol_path: "/profiles", vol_host_path: "/path/to/profiles", desc: "Optionally specify a path for persistent profile storage." } - -opt_param_usage_include_ports: false -opt_param_ports: [] - -opt_param_device_map: false -opt_param_devices: [] - -cap_add_param: false -cap_add_param_vars: [] - -opt_cap_add_param: false -opt_cap_add_param_vars: [] -optional_block_1: false -optional_block_1_items: "" - + - {vol_path: "/profiles", vol_host_path: "/path/to/{{ project_name }}/profiles", desc: "Optionally specify a path for persistent profile storage."} + - {vol_path: "/dev/input", vol_host_path: "/dev/input", desc: "Optional for gamepad support."} + - {vol_path: "/run/udev/data", vol_host_path: "/run/udev/data", desc: "Optional for gamepad support."} +opt_security_opt_param: true +opt_security_opt_param_vars: + - {run_var: "apparmor=rootlesskit", compose_var: "apparmor:rootlesskit", desc: "Some hosts require this on top of privileged for namespacing to work properly inside the DinD layer."} +unraid_template: false privileged: true - # application setup block app_setup_block_enabled: true app_setup_block: | This container uses [Docker in Docker](https://www.docker.com/blog/docker-can-now-run-within-docker/) and requires being run in `privileged` mode. This container also requires an initial setup that runs on port 3000. + **Unlike other containers the web interface port (default 443) needs to be set for the env variable `KASM_PORT` and both the inside and outside port IE for 4443 `KASM_PORT=4443` `-p 4443:4443`** + + **Unraid users due to the DinD storage layer `/opt/` should be mounted directly to a disk IE `/mnt/disk1/appdata/path` or optimally with a cache disk at `/mnt/cache/appdata/path`** + Access the installation wizard at https://`your ip`:3000 and follow the instructions there. Once setup is complete access https://`your ip`:443 and login with the credentials you entered during setup. The default users are: * admin@kasm.local * user@kasm.local - Currently Synology systems are not supported due to them blocking CPU scheduling in their Kernel. + Currently Synology systems are not supported due to them blocking CPU scheduling in their Kernel. + ### Updating KASM + + In order to update kasm, first make sure you are using the latest docker image, and then perform the in app update in the admin panel. Docker image update and recreation of container alone won't update kasm. + + ### GPU Support + + During installation an option will be presented to force all Workspace containers to mount in and use a specific GPU. If using an NVIDIA GPU you will need to pass `-e NVIDIA_VISIBLE_DEVICES=all` or `--gpus all` and have the [NVIDIA Container Runtime](https://github.com/NVIDIA/nvidia-container-runtime) installed on the host. Also if using NVIDIA, Kasm Workspaces has [native NVIDIA support](https://www.kasmweb.com/docs/latest/how_to/gpu.html) so you can optionally opt to simply use that instead of he manual override during installation. + + ### Gamepad support + + In order to properly create virtual Gamepads you will need to mount from your host `/dev/input` and `/run/udev/data`. Please see [HERE](https://www.kasmweb.com/docs/develop/guide/gamepad_passthrough.html) for instructions on enabling gamepad support. + + ### Persistant profiles + + In order to use persistant profiles in Workspaces you will need to mount in a folder to use from your host to `/profiles`. From there when configuring a workspace you can set the `Persistant Profile Path` to IE `/profiles/ubuntu-focal/{username}/`, more infomation can be found [HERE](https://www.kasmweb.com/docs/latest/how_to/persistent_profiles.html). + + ### Reverse proxy + + A sample for [SWAG](https://github.com/linuxserver/docker-swag) can be found [here](https://raw.githubusercontent.com/linuxserver/reverse-proxy-confs/master/kasm.subdomain.conf.sample). Post installation you will need to modify the "Proxy Port" setting under the default zone to 0 as outlined [here](https://www.kasmweb.com/docs/latest/how_to/reverse_proxy.html#update-zones) to launch Workspaces sessions. +# init diagram +init_diagram: | + "kasm:latest": { + docker-mods + base { + fix-attr +\nlegacy cont-init + } + docker-mods -> base + legacy-services + custom services + init-services -> legacy-services + init-services -> custom services + custom services -> legacy-services + legacy-services -> ci-service-check + init-migrations -> init-adduser + init-os-end -> init-config + init-config -> init-config-end + init-config-kasm -> init-config-end + init-crontab-config -> init-config-end + init-config -> init-config-kasm + init-config -> init-crontab-config + init-mods-end -> init-custom-files + init-adduser -> init-device-perms + base -> init-envfile + base -> init-migrations + init-config-end -> init-mods + init-mods-package-install -> init-mods-end + init-mods -> init-mods-package-install + init-adduser -> init-os-end + init-device-perms -> init-os-end + init-envfile -> init-os-end + init-custom-files -> init-services + init-services -> svc-cron + svc-cron -> legacy-services + init-config-kasm -> svc-docker + init-services -> svc-docker + svc-docker -> legacy-services + init-config-kasm -> svc-kasm-wizard + init-services -> svc-kasm-wizard + svc-kasm-wizard -> legacy-services + } + Base Images: { + "baseimage-ubuntu:noble" + } + "kasm:latest" <- Base Images # changelog changelogs: - - { date: "02.07.22:", desc: "Initial Release." } + - {date: "13.11.25:", desc: "Pin docker to v28 to avoid API deprecation issues."} + - {date: "22.10.25:", desc: "Update for 1.18.0 release."} + - {date: "08.06.25:", desc: "Deprecate develop branch."} + - {date: "03.06.25:", desc: "Rebase to Ubuntu Noble. Update for 1.17.0 release."} + - {date: "09.11.24:", desc: "Update base image for 1.16.1 release."} + - {date: "24.09.24:", desc: "Add base users in docker build logic to survive container upgrades."} + - {date: "17.09.24:", desc: "Update base image for 1.16.0 release and fix Nvidia support."} + - {date: "16.02.24:", desc: "Update base image for 1.15.0 release."} + - {date: "22.08.23:", desc: "Update base image for 1.14.0 release."} + - {date: "07.04.23:", desc: "Add mod layer for ingesting LSIO images for 1.13.0 release."} + - {date: "28.03.23:", desc: "Pin compose to 2.5.0 to be in sync with upstream requirements."} + - {date: "05.11.22:", desc: "Rebase to Jammy, add support for GPUs, add support for Gamepads."} + - {date: "23.09.22:", desc: "Migrate to s6v3."} + - {date: "02.07.22:", desc: "Initial Release."} diff --git a/root-armhf/etc/cont-init.d/30-disabled b/root-armhf/etc/cont-init.d/30-disabled deleted file mode 100644 index 2a7552e..0000000 --- a/root-armhf/etc/cont-init.d/30-disabled +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/with-contenv bash - -for i in {1..10}; do - echo "Armhf/Arm32v7 is not supported" -done diff --git a/root/etc/cont-init.d/30-setup b/root/etc/cont-init.d/30-setup deleted file mode 100644 index 19f227a..0000000 --- a/root/etc/cont-init.d/30-setup +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/with-contenv bash - -# Create directories -if [ ! -d "/opt/docker" ]; then - mkdir -p /opt/docker -fi - -# Login to Dockerhub -if [ ! -z "${DOCKER_HUB_USERNAME}" ]; then - docker login --username $DOCKER_HUB_USERNAME --password $DOCKER_HUB_PASSWORD -fi - -# Generate self cert for wizard -if [ ! -f "/opt/kasm/certs/kasm_wizard.crt" ]; then - mkdir -p /opt/kasm/certs - openssl req -x509 -nodes -days 1825 -newkey rsa:2048 \ - -keyout /opt/kasm/certs/kasm_wizard.key \ - -out /opt/kasm/certs/kasm_wizard.crt \ - -subj "/C=US/ST=VA/L=None/O=None/OU=DoFu/CN=$(hostname)/emailAddress=none@none.none" -fi diff --git a/root/etc/docker/daemon.json b/root/etc/docker/daemon.json new file mode 100644 index 0000000..c561d62 --- /dev/null +++ b/root/etc/docker/daemon.json @@ -0,0 +1,8 @@ +{ + "runtimes": { + "nvidia": { + "args": [], + "path": "nvidia-container-runtime" + } + } +} diff --git a/root/etc/s6-overlay/s6-rc.d/init-config-end/dependencies.d/init-config-kasm b/root/etc/s6-overlay/s6-rc.d/init-config-end/dependencies.d/init-config-kasm new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/init-config-kasm/dependencies.d/init-config b/root/etc/s6-overlay/s6-rc.d/init-config-kasm/dependencies.d/init-config new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/init-config-kasm/run b/root/etc/s6-overlay/s6-rc.d/init-config-kasm/run new file mode 100755 index 0000000..f72dd96 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-config-kasm/run @@ -0,0 +1,31 @@ +#!/usr/bin/with-contenv bash + +# Create directories +if [[ ! -d "/opt/docker" ]]; then + mkdir -p /opt/docker +fi + +# Workaround for running in a rootless docker environment +sed -i '/set -e/d' /etc/init.d/docker + +# Login to Dockerhub +if [[ -n "${DOCKER_HUB_USERNAME}" ]]; then + docker login --username "${DOCKER_HUB_USERNAME}" --password "${DOCKER_HUB_PASSWORD}" +fi + +# Generate self cert for wizard +if [[ ! -f "/opt/kasm/certs/kasm_wizard.crt" ]]; then + mkdir -p /opt/kasm/certs + openssl req -x509 -nodes -days 1825 -newkey rsa:2048 \ + -keyout /opt/kasm/certs/kasm_wizard.key \ + -out /opt/kasm/certs/kasm_wizard.crt \ + -subj "/C=US/ST=VA/L=None/O=None/OU=DoFu/CN=$(hostname)/emailAddress=none@none.none" +fi + +# Create plugin directory +if [[ ! -L "/var/lib/docker-plugins" ]]; then + mkdir -p /opt/docker-plugins + ln -s /opt/docker-plugins /var/lib/docker-plugins + mkdir -p /var/lib/docker-plugins/rclone/config + mkdir -p /var/lib/docker-plugins/rclone/cache +fi diff --git a/root/etc/s6-overlay/s6-rc.d/init-config-kasm/type b/root/etc/s6-overlay/s6-rc.d/init-config-kasm/type new file mode 100644 index 0000000..bdd22a1 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-config-kasm/type @@ -0,0 +1 @@ +oneshot diff --git a/root/etc/s6-overlay/s6-rc.d/init-config-kasm/up b/root/etc/s6-overlay/s6-rc.d/init-config-kasm/up new file mode 100644 index 0000000..cd5b530 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-config-kasm/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/init-config-kasm/run diff --git a/root/etc/s6-overlay/s6-rc.d/svc-docker/dependencies.d/init-config-kasm b/root/etc/s6-overlay/s6-rc.d/svc-docker/dependencies.d/init-config-kasm new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/svc-docker/dependencies.d/init-services b/root/etc/s6-overlay/s6-rc.d/svc-docker/dependencies.d/init-services new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/svc-docker/run b/root/etc/s6-overlay/s6-rc.d/svc-docker/run new file mode 100755 index 0000000..710a540 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-docker/run @@ -0,0 +1,14 @@ +#!/usr/bin/with-contenv bash + +_term() { + if [ -f "/opt/kasm/bin/stop" ]; then + echo "Caught SIGTERM signal!" + echo "Stopping Kasm Containers" + /opt/kasm/bin/stop + pid=$(pidof stop) + # terminate when the stop process dies + tail --pid=${pid} -f /dev/null + fi +} + +exec /usr/local/bin/dockerd-entrypoint.sh -l error --data-root /opt/docker diff --git a/root/etc/s6-overlay/s6-rc.d/svc-docker/type b/root/etc/s6-overlay/s6-rc.d/svc-docker/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-docker/type @@ -0,0 +1 @@ +longrun diff --git a/root/etc/s6-overlay/s6-rc.d/svc-kasm-wizard/dependencies.d/init-config-kasm b/root/etc/s6-overlay/s6-rc.d/svc-kasm-wizard/dependencies.d/init-config-kasm new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/svc-kasm-wizard/dependencies.d/init-services b/root/etc/s6-overlay/s6-rc.d/svc-kasm-wizard/dependencies.d/init-services new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/svc-kasm-wizard/run b/root/etc/s6-overlay/s6-rc.d/svc-kasm-wizard/run new file mode 100755 index 0000000..a3dd2ea --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-kasm-wizard/run @@ -0,0 +1,17 @@ +#!/usr/bin/with-contenv bash + +# Wait for docker to be up +while true; do + if [[ -S "/var/run/docker.sock" ]]; then + break + fi + sleep 1 +done + +# Don't do anything if wizard is disabled +if [[ -f "/opt/NO_WIZARD" ]]; then + sleep infinity +fi + +cd /wizard || exit 1 +/usr/bin/node index.js diff --git a/root/etc/s6-overlay/s6-rc.d/svc-kasm-wizard/type b/root/etc/s6-overlay/s6-rc.d/svc-kasm-wizard/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-kasm-wizard/type @@ -0,0 +1 @@ +longrun diff --git a/root/etc/s6-overlay/s6-rc.d/user/contents.d/init-config-kasm b/root/etc/s6-overlay/s6-rc.d/user/contents.d/init-config-kasm new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-docker b/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-docker new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-kasm-wizard b/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-kasm-wizard new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/services.d/docker/run b/root/etc/services.d/docker/run deleted file mode 100644 index b59d67d..0000000 --- a/root/etc/services.d/docker/run +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/with-contenv bash - -_term() { - if [ -f "/opt/kasm/bin/stop" ]; then - echo "Caught SIGTERM signal!" - echo "Stopping Kasm Containers" - /opt/kasm/bin/stop - pid=$(pidof stop) - # terminate when the stop process dies - tail --pid=${pid} -f /dev/null - fi -} - -exec /usr/local/bin/dockerd-entrypoint.sh -l error --data-root /opt/docker diff --git a/root/etc/services.d/wizard/run b/root/etc/services.d/wizard/run deleted file mode 100644 index b124ad2..0000000 --- a/root/etc/services.d/wizard/run +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/with-contenv bash - -# Wait for docker to be up -while true; do - if [ -S "/var/run/docker.sock" ]; then - break - fi - sleep 1 -done - -cd /wizard -/usr/bin/node index.js diff --git a/root/gpuinfo.sh b/root/gpuinfo.sh new file mode 100755 index 0000000..234731e --- /dev/null +++ b/root/gpuinfo.sh @@ -0,0 +1,28 @@ +#! /bin/bash + +# Get list of drm devices +IFS=$'\n' +CARDS=$(ls -la /sys/class/drm/renderD*/device/driver 2>/dev/null | awk '{print $11}' | awk -F/ '{print $NF}') +if [ -z "$CARDS" ]; then + echo '{}' + exit 0 +fi +for CARD in ${CARDS}; do + LAST_CARD=${CARD} +done + +# Add them to the json string +JSON='{' +COUNTER=0 +for CARD in $CARDS; do + JSON="${JSON}\"/dev/dri/card$COUNTER\":\"${CARD^^}\"" + if [ ${CARD} == ${LAST_CARD} ]; then + JSON="${JSON}}" + else + JSON="${JSON}," + fi + COUNTER=$(( COUNTER + 1 )) +done + +# Print json string +echo $JSON diff --git a/root/usr/local/bin/dockerd-entrypoint.sh b/root/usr/local/bin/dockerd-entrypoint.sh index 0f843e0..47cd35d 100755 --- a/root/usr/local/bin/dockerd-entrypoint.sh +++ b/root/usr/local/bin/dockerd-entrypoint.sh @@ -116,6 +116,7 @@ if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then ; then # generate certs and use TLS if requested/possible (default in 19.03+) set -- dockerd \ + --mtu="${DOCKER_MTU:-1500}" \ --host="$dockerSocket" \ --host=tcp://0.0.0.0:2376 \ --tlsverify \ @@ -127,6 +128,7 @@ if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then else # TLS disabled (-e DOCKER_TLS_CERTDIR='') or missing certs set -- dockerd \ + --mtu="${DOCKER_MTU:-1500}" \ --host="$dockerSocket" \ "$@" DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="${DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS:-} -p 0.0.0.0:2375:2375/tcp"