From e7d93b941748ade4484c9ffc741e3833119b17c5 Mon Sep 17 00:00:00 2001 From: Trent Maetzold Date: Wed, 11 Mar 2026 11:47:14 -0500 Subject: [PATCH 01/24] fix: add libfido2 deps for v3.22+, update maintainer --- build/Dockerfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index e90ff25..3047940 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -4,7 +4,7 @@ FROM debian:sid-slim AS build ARG version # Install dependencies -RUN apt-get update && apt-get install -y golang build-essential libsecret-1-dev +RUN apt-get update && apt-get install -y golang build-essential libsecret-1-dev libfido2-dev libcbor-dev # Build ADD https://github.com/ProtonMail/proton-bridge.git#${version} /build/ @@ -12,14 +12,15 @@ WORKDIR /build/ RUN make build-nogui vault-editor FROM debian:sid-slim -LABEL maintainer="Simon Felding " +LABEL maintainer="Trent Maetzold " +LABEL org.opencontainers.image.source="https://github.com/trent-maetzold/protonmail-bridge-docker" EXPOSE 25/tcp EXPOSE 143/tcp # Install dependencies and protonmail bridge RUN apt-get update \ - && apt-get install -y --no-install-recommends socat pass libsecret-1-0 ca-certificates \ + && apt-get install -y --no-install-recommends socat pass libsecret-1-0 libfido2-1 ca-certificates \ && rm -rf /var/lib/apt/lists/* # Copy bash scripts From d1f474d31dcac23c038dc30a50ce31d9ff8d4982 Mon Sep 17 00:00:00 2001 From: Trent Maetzold Date: Wed, 11 Mar 2026 11:47:25 -0500 Subject: [PATCH 02/24] chore: update maintainer labels in deb Dockerfile --- deb/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deb/Dockerfile b/deb/Dockerfile index a0d8e2c..07e1f43 100644 --- a/deb/Dockerfile +++ b/deb/Dockerfile @@ -10,7 +10,8 @@ RUN apt-get update && apt-get install -y wget binutils RUN bash /install.sh FROM debian:sid-slim -LABEL maintainer="Simon Felding " +LABEL maintainer="Trent Maetzold " +LABEL org.opencontainers.image.source="https://github.com/trent-maetzold/protonmail-bridge-docker" EXPOSE 25/tcp EXPOSE 143/tcp From edcac8976a3402e2adc6c1e2b8cc4ea78f80266d Mon Sep 17 00:00:00 2001 From: Trent Maetzold Date: Wed, 11 Mar 2026 11:47:32 -0500 Subject: [PATCH 03/24] security: bind to localhost, use GHCR image --- docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index fa91e7d..4cadb84 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,10 +2,10 @@ version: '2.1' services: protonmail-bridge: - image: shenxn/protonmail-bridge + image: ghcr.io/trent-maetzold/protonmail-bridge:build ports: - - 1025:25/tcp - - 1143:143/tcp + - 127.0.0.1:1025:25/tcp + - 127.0.0.1:1143:143/tcp restart: unless-stopped volumes: - protonmail:/root From 80c7e31b190e258ee49385bcd6da16b91f46115a Mon Sep 17 00:00:00 2001 From: Trent Maetzold Date: Wed, 11 Mar 2026 11:47:39 -0500 Subject: [PATCH 04/24] docs: update README for fork --- README.md | 86 ++++++++++++++++++++++++------------------------------- 1 file changed, 38 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index e772fde..9fb66bb 100644 --- a/README.md +++ b/README.md @@ -1,93 +1,83 @@ # ProtonMail IMAP/SMTP Bridge Docker Container -![version badge](https://img.shields.io/docker/v/shenxn/protonmail-bridge) -![image size badge](https://img.shields.io/docker/image-size/shenxn/protonmail-bridge/build) -![docker pulls badge](https://img.shields.io/docker/pulls/shenxn/protonmail-bridge) -![deb badge](https://github.com/shenxn/protonmail-bridge-docker/workflows/pack%20from%20deb/badge.svg) -![build badge](https://github.com/shenxn/protonmail-bridge-docker/workflows/build%20from%20source/badge.svg) +> Fork of [shenxn/protonmail-bridge-docker](https://github.com/shenxn/protonmail-bridge-docker) with build fixes, updated dependencies, and GHCR publishing. + +![build badge](https://github.com/trent-maetzold/protonmail-bridge-docker/workflows/build%20from%20source/badge.svg) This is an unofficial Docker container of the [ProtonMail Bridge](https://protonmail.com/bridge/). Some of the scripts are based on [Hendrik Meyer's work](https://gitlab.com/T4cC0re/protonmail-bridge-docker). -Docker Hub: [https://hub.docker.com/r/shenxn/protonmail-bridge](https://hub.docker.com/r/shenxn/protonmail-bridge) +GHCR: `ghcr.io/trent-maetzold/protonmail-bridge` -GitHub: [https://github.com/shenxn/protonmail-bridge-docker](https://github.com/shenxn/protonmail-bridge-docker) +## Changes from upstream + +- Fixed build for proton-bridge v3.22+ (added `libfido2` dependency) +- Removed DockerHub publishing (GHCR only) +- Removed Gitee mirror workflow +- Updated all GitHub Actions to current versions +- Replaced deprecated Anchore scan with Trivy +- Default docker-compose binds to localhost only (security) +- Updated maintainer labels ## ARM Support -We now support ARM devices (`arm64` and `arm/v7`)! Use the images tagged with `build`. See next section for details. +ARM devices (`arm64` and `arm/v7`) are supported. Use the images tagged with `build`. ## Tags -There are two types of images. - - `deb`: Images based on the official [.deb release](https://protonmail.com/bridge/install). It only supports the `amd64` architecture. - - `build`: Images based on the [source code](https://github.com/ProtonMail/proton-bridge). It supports `amd64`, `arm64`, `arm/v7` and `riscv64`. Supporting to more architectures is possible. PRs are welcome. +There are two types of images: +- `deb`: Images based on the official [.deb release](https://protonmail.com/bridge/install). `amd64` only. +- `build`: Images compiled from [source code](https://github.com/ProtonMail/proton-bridge). Supports `amd64`, `arm64`, `arm/v7`, and `riscv64`. -tag | description - -- | -- -`latest` | latest `deb` image -`[version]` | `deb` images -`build` | latest `build` image -`[version]-build` | `build` images +| tag | description | +| -- | -- | +| `latest` | latest `deb` image | +| `[version]` | `deb` images | +| `build` | latest `build` image | +| `[version]-build` | `build` images | ## Initialization -To initialize and add account to the bridge, run the following command. +To initialize and add an account to the bridge: ``` -docker run --rm -it -v protonmail:/root shenxn/protonmail-bridge init +docker run --rm -it -v protonmail:/root ghcr.io/trent-maetzold/protonmail-bridge:build init ``` -If you want to use Docker Compose instead, you can create a copy of the provided example [docker-compose.yml](docker-compose.yml) file, modify it to suit your needs, and then run the following command: +Or with Docker Compose: ``` docker compose run protonmail-bridge init ``` -Wait for the bridge to startup, then you will see a prompt appear for [Proton Mail Bridge interactive shell](https://proton.me/support/bridge-cli-guide). Use the `login` command and follow the instructions to add your account into the bridge. Then use `info` to see the configuration information (username and password). After that, use `exit` to exit the bridge. You may need `CTRL+C` to exit the docker entirely. +Wait for the bridge to start, use `login` to add your account, `info` to see credentials, then `exit`. You may need `CTRL+C` to fully exit. ## Run -To run the container, use the following command. - ``` -docker run -d --name=protonmail-bridge -v protonmail:/root -p 1025:25/tcp -p 1143:143/tcp --restart=unless-stopped shenxn/protonmail-bridge +docker run -d --name=protonmail-bridge -v protonmail:/root \ + -p 127.0.0.1:1025:25/tcp -p 127.0.0.1:1143:143/tcp \ + --restart=unless-stopped ghcr.io/trent-maetzold/protonmail-bridge:build ``` -Or, if using Docker Compose, use the following command. +Or with Docker Compose: ``` docker compose up -d ``` -## Kubernetes - -If you want to run this image in a Kubernetes environment. You can use the [Helm](https://helm.sh/) chart (https://github.com/k8s-at-home/charts/tree/master/charts/stable/protonmail-bridge) created by [@Eagleman7](https://github.com/Eagleman7). More details can be found in [#23](https://github.com/shenxn/protonmail-bridge-docker/issues/23). - -If you don't want to use Helm, you can also reference to the guide ([#6](https://github.com/shenxn/protonmail-bridge-docker/issues/6)) written by [@ghudgins](https://github.com/ghudgins). - ## Security -Please be aware that running the command above will expose your bridge to the network. Remember to use firewall if you are going to run this in an untrusted network or on a machine that has public IP address. You can also use the following command to publish the port to only localhost, which is the same behavior as the official bridge package. - -``` -docker run -d --name=protonmail-bridge -v protonmail:/root -p 127.0.0.1:1025:25/tcp -p 127.0.0.1:1143:143/tcp --restart=unless-stopped shenxn/protonmail-bridge -``` - -Besides, you can publish only port 25 (SMTP) if you don't need to receive any email (e.g. as a email notification service). - -## Compatibility - -The bridge currently only supports some of the email clients. More details can be found on the official website. I've tested this on a Synology DiskStation and it runs well. However, you may need ssh onto it to run the interactive docker command to add your account. The main reason of using this instead of environment variables is that it seems to be the best way to support two-factor authentication. +The default configuration binds ports to localhost only. If you need network access, update the port bindings — but use a firewall on untrusted networks. ## Bridge CLI Guide -The initialization step exposes the bridge CLI so you can do things like switch between combined and split mode, change proxy, etc. The [official guide](https://protonmail.com/support/knowledge-base/bridge-cli-guide/) gives more information on to use the CLI. +The initialization step exposes the bridge CLI for configuration (combined/split mode, proxy, etc.). See the [official guide](https://protonmail.com/support/knowledge-base/bridge-cli-guide/). ## Build -For anyone who want to build this container on your own (for development or security concerns), here is the guide to do so. First, you need to `cd` into the directory (`deb` or `build`, depending on which type of image you want). Then just run the docker build command -``` -docker build . -``` +To build locally: -That's it. The `Dockerfile` and bash scripts handle all the downloading, building, and packing. You can also add tags, push to your favorite docker registry, or use `buildx` to build multi architecture images. +``` +cd build +docker build --build-arg version=v3.22.0 . +``` From aac8004a5106b4f5e3f0667bef925a577f94c865 Mon Sep 17 00:00:00 2001 From: Trent Maetzold Date: Wed, 11 Mar 2026 11:47:46 -0500 Subject: [PATCH 05/24] ci: update build workflow for GHCR, remove DockerHub --- .github/workflows/build.yaml | 68 +++++++++++------------------------- 1 file changed, 20 insertions(+), 48 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index defc7de..e52af44 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -13,9 +13,7 @@ on: workflow_dispatch: env: - GHCR_REPO: shenxn/protonmail-bridge-docker - DOCKERHUB_REPO: shenxn/protonmail-bridge - DOCKER_REPO_DEV: ghcr.io/shenxn/protonmail-bridge + GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge PLATFORMS: linux/amd64,linux/arm64/v8,linux/arm/v7,linux/riscv64 jobs: @@ -24,18 +22,16 @@ jobs: if: github.ref != 'refs/heads/master' steps: - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@v4 - name: Set version - id: version - run: echo "version=`cat VERSION`" >> $GITHUB_ENV + run: echo "version=$(cat VERSION)" >> $GITHUB_ENV - name: Docker meta id: meta uses: docker/metadata-action@v5 with: - images: | - ${{ env.DOCKER_REPO_DEV }} + images: ${{ env.GHCR_REPO }} - name: Login to GHCR uses: docker/login-action@v3 @@ -49,22 +45,21 @@ jobs: with: driver-opts: network=host - - name: Build and push by digest - id: build + - name: Build and push uses: docker/build-push-action@v6 with: labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,"name=${{ env.DOCKER_REPO_DEV }}",push-by-digest=false,name-canonical=true,push=true context: ./build file: ./build/Dockerfile - tags: "${{ env.DOCKER_REPO_DEV }}:dev-${{ github.ref_name }}" + tags: "${{ env.GHCR_REPO }}:dev-${{ github.ref_name }}" + push: true build-args: | version=${{ env.version }} - name: Run Trivy vulnerability scan uses: aquasecurity/trivy-action@0.30.0 with: - image-ref: "${{ env.DOCKER_REPO_DEV }}:dev-${{ github.ref_name }}" + image-ref: "${{ env.GHCR_REPO }}:dev-${{ github.ref_name }}" format: 'sarif' exit-code: 0 severity: 'CRITICAL,HIGH' @@ -88,7 +83,7 @@ jobs: - linux/riscv64 steps: - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@v4 - name: Prepare run: | @@ -96,22 +91,13 @@ jobs: echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - name: Set version - id: version - run: echo "version=`cat VERSION`" >> $GITHUB_ENV + run: echo "version=$(cat VERSION)" >> $GITHUB_ENV - name: Docker meta id: meta uses: docker/metadata-action@v5 with: - images: | - ${{ env.DOCKERHUB_REPO }} - ${{ env.GHCR_REPO }} - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.REGISTRY_USERNAME }} - password: ${{ secrets.REGISTRY_PASSWORD }} + images: ${{ env.GHCR_REPO }} - name: Login to GHCR uses: docker/login-action@v3 @@ -132,14 +118,9 @@ jobs: with: platforms: ${{ matrix.platform }} labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,"name=name=${{ env.DOCKERHUB_REPO }},${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=false + outputs: type=image,"name=${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=true context: ./build file: ./build/Dockerfile - tags: | - "${{ env.DOCKERHUB_REPO }}:build" - "${{ env.DOCKERHUB_REPO }}:${{ env.version }}-build" - "${{ env.GHCR_REPO }}:build" - "${{ env.GHCR_REPO }}:${{ env.version }}-build" provenance: false sbom: false build-args: | @@ -159,12 +140,14 @@ jobs: if-no-files-found: error retention-days: 1 - merge: runs-on: ubuntu-latest needs: - build steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Download digests uses: actions/download-artifact@v4 with: @@ -173,14 +156,7 @@ jobs: merge-multiple: true - name: Set version - id: version - run: echo "version=`cat VERSION`" >> $GITHUB_ENV - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.REGISTRY_USERNAME }} - password: ${{ secrets.REGISTRY_PASSWORD }} + run: echo "version=$(cat VERSION)" >> $GITHUB_ENV - name: Login to GHCR uses: docker/login-action@v3 @@ -198,29 +174,26 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: | - ${{ env.DOCKERHUB_REPO }} - ${{ env.GHCR_REPO }} + images: ${{ env.GHCR_REPO }} tags: | type=raw,enable=true,value=${{ env.version }}-build - type=raw,enable=true,suffix=,value=build + type=raw,enable=true,value=build - name: Create manifest list and push working-directory: ${{ runner.temp }}/digests run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.DOCKERHUB_REPO }}@sha256:%s ' *) docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ $(printf '${{ env.GHCR_REPO }}@sha256:%s ' *) - name: Run Trivy vulnerability scan uses: aquasecurity/trivy-action@0.30.0 with: - image-ref: "${{ env.DOCKERHUB_REPO }}:${{ env.version }}-build" + image-ref: "${{ env.GHCR_REPO }}:${{ env.version }}-build" format: 'sarif' exit-code: 0 severity: 'CRITICAL,HIGH' output: 'trivy-results.sarif' + - name: Upload Trivy scan SARIF report uses: github/codeql-action/upload-sarif@v3 with: @@ -228,5 +201,4 @@ jobs: - name: Inspect image run: | - docker buildx imagetools inspect ${{ env.DOCKERHUB_REPO }}:${{ steps.meta.outputs.version }} docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ steps.meta.outputs.version }} From 985d3ba428c12b26bb1ec27407a9bd7c2c661f28 Mon Sep 17 00:00:00 2001 From: Trent Maetzold Date: Wed, 11 Mar 2026 11:47:53 -0500 Subject: [PATCH 06/24] ci: modernize deb workflow actions, GHCR only --- .github/workflows/deb.yaml | 72 ++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/.github/workflows/deb.yaml b/.github/workflows/deb.yaml index ddf4c99..b938d12 100644 --- a/.github/workflows/deb.yaml +++ b/.github/workflows/deb.yaml @@ -13,67 +13,65 @@ on: workflow_dispatch: env: - DOCKER_REPO: shenxn/protonmail-bridge - DOCKER_REPO_DEV: ghcr.io/shenxn/protonmail-bridge-dev + GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge jobs: deb: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@v4 + - name: Set version - id: version - run: echo "version=`cat VERSION`" >> $GITHUB_ENV - - name: Set repo - id: repo - run: if [[ $GITHUB_REF == "refs/heads/master" ]]; then echo "::set-output name=repo::${DOCKER_REPO}"; else echo "::set-output name=repo::${DOCKER_REPO_DEV}"; fi + run: echo "version=$(cat VERSION)" >> $GITHUB_ENV + - name: Docker meta - id: docker_meta - uses: crazy-max/ghaction-docker-meta@v1 + id: meta + uses: docker/metadata-action@v5 with: - images: ${{ steps.repo.outputs.repo }} + images: ${{ env.GHCR_REPO }} + - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 + - name: Build image without push - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v6 with: context: ./deb file: ./deb/Dockerfile load: true tags: protonmail-bridge:latest - - name: Scan image - id: scan - uses: anchore/scan-action@v2 + + - name: Run Trivy vulnerability scan + uses: aquasecurity/trivy-action@0.30.0 with: - image: protonmail-bridge:latest - fail-build: true - severity-cutoff: critical - acs-report-enable: true - - name: Upload Anchore scan SARIF report + image-ref: protonmail-bridge:latest + format: 'sarif' + exit-code: 0 + severity: 'CRITICAL,HIGH' + output: 'trivy-results.sarif' + + - name: Upload Trivy scan SARIF report uses: github/codeql-action/upload-sarif@v3 with: - sarif_file: ${{ steps.scan.outputs.sarif }} - - name: Login to DockerHub - uses: docker/login-action@v1 - if: ${{ github.event_name != 'pull_request' }} - with: - username: ${{ secrets.REGISTRY_USERNAME }} - password: ${{ secrets.REGISTRY_PASSWORD }} - - name: Login to GitHub Container Registry - uses: docker/login-action@v1 - if: ${{ github.event_name != 'pull_request' }} + sarif_file: 'trivy-results.sarif' + + - name: Login to GHCR + uses: docker/login-action@v3 + if: github.event_name != 'pull_request' with: registry: ghcr.io username: ${{ github.repository_owner }} - password: ${{ secrets.CR_PAT }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Push image - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v6 + if: github.event_name != 'pull_request' with: context: ./deb file: ./deb/Dockerfile tags: | - ${{ steps.repo.outputs.repo }}:latest - ${{ steps.repo.outputs.repo }}:${{ env.version }} - labels: ${{ steps.docker_meta.outputs.labels }} - push: ${{ github.event_name != 'pull_request' }} + ${{ env.GHCR_REPO }}:latest + ${{ env.GHCR_REPO }}:${{ env.version }} + labels: ${{ steps.meta.outputs.labels }} + push: true From 6066049d5fd8770ae0b379dcda6974370ed3d6de Mon Sep 17 00:00:00 2001 From: Trent Maetzold Date: Wed, 11 Mar 2026 11:47:59 -0500 Subject: [PATCH 07/24] ci: update checkout action to v4 --- .github/workflows/update-check.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-check.yaml b/.github/workflows/update-check.yaml index 0c46ab4..f6b1960 100644 --- a/.github/workflows/update-check.yaml +++ b/.github/workflows/update-check.yaml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@v4 with: token: ${{ secrets.PERSONAL_TOKEN }} - name: Check Update From 47526d1b62a3b22903b963975cbfc60911b9d292 Mon Sep 17 00:00:00 2001 From: Trent Maetzold Date: Wed, 11 Mar 2026 12:30:24 -0500 Subject: [PATCH 08/24] Switch base image from debian:sid to debian:trixie (stable) --- build/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index 3047940..897e651 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,5 +1,5 @@ -# The build image could be golang, but it currently does not support riscv64. Only debian:sid does, at the time of writing. -FROM debian:sid-slim AS build +# Trixie (Debian 13) supports golang on all target platforms including riscv64. +FROM debian:trixie-slim AS build ARG version @@ -11,7 +11,7 @@ ADD https://github.com/ProtonMail/proton-bridge.git#${version} /build/ WORKDIR /build/ RUN make build-nogui vault-editor -FROM debian:sid-slim +FROM debian:trixie-slim LABEL maintainer="Trent Maetzold " LABEL org.opencontainers.image.source="https://github.com/trent-maetzold/protonmail-bridge-docker" From 23dd9aab52d099ee00d408be320185d1a378a967 Mon Sep 17 00:00:00 2001 From: Trent Maetzold Date: Wed, 11 Mar 2026 12:40:58 -0500 Subject: [PATCH 09/24] Merge version check into build workflow, add scheduled trigger --- .github/workflows/build.yaml | 50 ++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e52af44..428dc9e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -10,6 +10,8 @@ on: paths: - .github/workflows/build.yaml - build/* + schedule: + - cron: '0 6 * * *' workflow_dispatch: env: @@ -17,9 +19,44 @@ env: PLATFORMS: linux/amd64,linux/arm64/v8,linux/arm/v7,linux/riscv64 jobs: + version-check: + runs-on: ubuntu-latest + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + outputs: + updated: ${{ steps.check.outputs.updated }} + version: ${{ steps.check.outputs.version }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check for new version + id: check + run: | + current=$(cat VERSION) + latest=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') + echo "Current: $current, Latest: $latest" + if [ "$current" != "$latest" ]; then + echo "$latest" > VERSION + echo "updated=true" >> $GITHUB_OUTPUT + echo "version=$latest" >> $GITHUB_OUTPUT + else + echo "Version unchanged" + echo "updated=false" >> $GITHUB_OUTPUT + echo "version=$current" >> $GITHUB_OUTPUT + fi + + - name: Commit version bump + if: steps.check.outputs.updated == 'true' + run: | + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + git add VERSION + git commit -m "Bump version to ${{ steps.check.outputs.version }}" + git push + test: runs-on: ubuntu-latest - if: github.ref != 'refs/heads/master' + if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref != 'refs/heads/master') steps: - name: Checkout uses: actions/checkout@v4 @@ -72,7 +109,11 @@ jobs: build: runs-on: ubuntu-latest - if: github.event_name == 'push' && github.ref == 'refs/heads/master' + if: | + (github.event_name == 'push' && github.ref == 'refs/heads/master') || + (needs.version-check.result == 'success' && needs.version-check.outputs.updated == 'true') + needs: + - version-check strategy: fail-fast: false matrix: @@ -84,6 +125,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + ref: master - name: Prepare run: | @@ -147,6 +190,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + ref: master - name: Download digests uses: actions/download-artifact@v4 @@ -178,6 +223,7 @@ jobs: tags: | type=raw,enable=true,value=${{ env.version }}-build type=raw,enable=true,value=build + type=raw,enable=true,value=latest - name: Create manifest list and push working-directory: ${{ runner.temp }}/digests From 88ce12ea30fbbed877807475102ffb5f88128763 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 17:44:59 +0000 Subject: [PATCH 10/24] Remove obsolete workflows and update-check script --- .github/workflows/mirror.yaml | 27 --------------------- .github/workflows/update-check.yaml | 24 ------------------- update-check.py | 37 ----------------------------- 3 files changed, 88 deletions(-) delete mode 100644 .github/workflows/mirror.yaml delete mode 100644 .github/workflows/update-check.yaml delete mode 100644 update-check.py diff --git a/.github/workflows/mirror.yaml b/.github/workflows/mirror.yaml deleted file mode 100644 index 4e2409b..0000000 --- a/.github/workflows/mirror.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Mirroring - -# yamllint disable-line rule:truthy -on: - push: - branches: - - master - - dev - -jobs: - mirror_gitee: - name: Mirror to Gitee - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Push to Gitee - env: - SSH_KEY: ${{ secrets.GITEE_KEY }} - run: | - mkdir -p ~/.ssh - echo "${SSH_KEY}" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - export GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no -l git" - git remote add gitee git@gitee.com:shenxn/protonmail-bridge-docker.git - git push --tags --force --prune gitee "refs/remotes/origin/*:refs/heads/*" diff --git a/.github/workflows/update-check.yaml b/.github/workflows/update-check.yaml deleted file mode 100644 index f6b1960..0000000 --- a/.github/workflows/update-check.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: update check - -on: - push: - paths: - - .github/workflows/update-check.yaml - - update-check.py - pull_request: - paths: - - .github/workflows/update-check.yaml - - update-check.py - schedule: - - cron: '0 0 * * *' # runs everyday at midnight - -jobs: - check: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - token: ${{ secrets.PERSONAL_TOKEN }} - - name: Check Update - run: python3 update-check.py ${{ github.event_name == 'pull_request' }} diff --git a/update-check.py b/update-check.py deleted file mode 100644 index 19666d6..0000000 --- a/update-check.py +++ /dev/null @@ -1,37 +0,0 @@ -import requests, os, sys - -def git(command): - return os.system(f"git {command}") - - -release = requests.get("https://api.github.com/repos/protonmail/proton-bridge/releases/latest").json() -version = release['tag_name'] -deb = [asset for asset in release ['assets'] if asset['name'].endswith('.deb')][0]['browser_download_url'] - -print(f"Latest release is: {version}") - -with open("VERSION", 'w') as f: - f.write(version) - -with open("deb/PACKAGE", 'w') as f: - f.write(deb) - -git("config --local user.name 'GitHub Actions'") -git("config --local user.email 'actions@github.com'") - -git("add -A") - -if git("diff --cached --quiet") == 0: # Returns 0 if there are no changes - print("Version didn't change") - exit(0) - -git(f"commit -m 'Bump version to {version}'") -is_pull_request = sys.argv[1] == "true" - -if is_pull_request: - print("This is a pull request, skipping push step.") - exit(0) - -if git("push") != 0: - print("Git push failed!") - exit(1) From e812ae128d75b577bed8edadfce132639dbb665e Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 17:53:34 +0000 Subject: [PATCH 11/24] Version bump via PR instead of direct push to master --- .github/workflows/build.yaml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 428dc9e..736a9ec 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -45,14 +45,23 @@ jobs: echo "version=$current" >> $GITHUB_OUTPUT fi - - name: Commit version bump + - name: Create version bump PR if: steps.check.outputs.updated == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | + branch="auto/bump-${{ steps.check.outputs.version }}" git config user.name 'github-actions[bot]' git config user.email 'github-actions[bot]@users.noreply.github.com' + git checkout -b "$branch" git add VERSION git commit -m "Bump version to ${{ steps.check.outputs.version }}" - git push + git push origin "$branch" + gh pr create \ + --title "Bump proton-bridge to ${{ steps.check.outputs.version }}" \ + --body "Auto-detected new upstream release. Merging will trigger the build pipeline." \ + --base master \ + --head "$branch" test: runs-on: ubuntu-latest From 5ed92b2701582ae0332c759ad9deb4611870f2f5 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 17:54:36 +0000 Subject: [PATCH 12/24] Auto-merge version bump PRs --- .github/workflows/build.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 736a9ec..9a4588a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -57,11 +57,12 @@ jobs: git add VERSION git commit -m "Bump version to ${{ steps.check.outputs.version }}" git push origin "$branch" - gh pr create \ + pr_url=$(gh pr create \ --title "Bump proton-bridge to ${{ steps.check.outputs.version }}" \ - --body "Auto-detected new upstream release. Merging will trigger the build pipeline." \ + --body "Auto-detected new upstream release." \ --base master \ - --head "$branch" + --head "$branch") + gh pr merge "$pr_url" --squash --auto test: runs-on: ubuntu-latest From 1068b943c7f0b40de97b72edfe8520f3bcd54919 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 18:02:44 +0000 Subject: [PATCH 13/24] Remove shenxn funding, update SECURITY.md, deb Dockerfile to trixie, add acknowledgments to README --- .github/FUNDING.yml | 12 ------------ README.md | 17 +++++++++++++---- SECURITY.md | 4 +++- deb/Dockerfile | 4 ++-- 4 files changed, 18 insertions(+), 19 deletions(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 8be4aa5..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,12 +0,0 @@ -# These are supported funding model platforms - -github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -patreon: # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -otechie: # Replace with a single Otechie username -custom: ['https://www.buymeacoffee.com/shenxn'] diff --git a/README.md b/README.md index 9fb66bb..52ff6fa 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,21 @@ ![build badge](https://github.com/trent-maetzold/protonmail-bridge-docker/workflows/build%20from%20source/badge.svg) -This is an unofficial Docker container of the [ProtonMail Bridge](https://protonmail.com/bridge/). Some of the scripts are based on [Hendrik Meyer's work](https://gitlab.com/T4cC0re/protonmail-bridge-docker). +This is an unofficial Docker container of the [ProtonMail Bridge](https://protonmail.com/bridge/). GHCR: `ghcr.io/trent-maetzold/protonmail-bridge` ## Changes from upstream - Fixed build for proton-bridge v3.22+ (added `libfido2` dependency) +- Switched base image from `debian:sid` to `debian:trixie` (stable) - Removed DockerHub publishing (GHCR only) - Removed Gitee mirror workflow +- Merged version check into build workflow with scheduled auto-update - Updated all GitHub Actions to current versions - Replaced deprecated Anchore scan with Trivy - Default docker-compose binds to localhost only (security) -- Updated maintainer labels +- Updated maintainer labels and security policy ## ARM Support @@ -30,8 +32,7 @@ There are two types of images: | tag | description | | -- | -- | -| `latest` | latest `deb` image | -| `[version]` | `deb` images | +| `latest` | latest `build` image | | `build` | latest `build` image | | `[version]-build` | `build` images | @@ -81,3 +82,11 @@ To build locally: cd build docker build --build-arg version=v3.22.0 . ``` + +## Acknowledgments + +This project is a fork of [shenxn/protonmail-bridge-docker](https://github.com/shenxn/protonmail-bridge-docker) by [Xiaonan Shen](https://github.com/shenxn), which provided the original Dockerfiles, entrypoint scripts, and CI pipeline. Some scripts are based on [Hendrik Meyer's work](https://gitlab.com/T4cC0re/protonmail-bridge-docker). + +## License + +[GPLv3](LICENSE) diff --git a/SECURITY.md b/SECURITY.md index ac1a029..0e93770 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,4 +2,6 @@ ## Reporting a Vulnerability -Before reporting any vulnerability, make sure that it is caused by this project (i.e., this is not a vulnarability of the bridge itself). To report a vulnerabilitiy, you can send me an email (s@sxn.dev). My PGP public key is available [here](https://api.protonmail.ch/pks/lookup?op=get&search=s@sxn.dev). +Before reporting any vulnerability, make sure that it is caused by this project (i.e., not a vulnerability of the bridge itself). + +To report a vulnerability, please [open a private security advisory](https://github.com/trent-maetzold/protonmail-bridge-docker/security/advisories/new) on this repository. diff --git a/deb/Dockerfile b/deb/Dockerfile index 07e1f43..383f8b7 100644 --- a/deb/Dockerfile +++ b/deb/Dockerfile @@ -1,7 +1,7 @@ ### The Deb install is just a repack of the official ProtonMail Bridge deb package with less dependencies. ### I recommend you don't use this. It's here for legacy reasons. -FROM debian:sid-slim AS build +FROM debian:trixie-slim AS build COPY install.sh PACKAGE / RUN apt-get update && apt-get install -y wget binutils @@ -9,7 +9,7 @@ RUN apt-get update && apt-get install -y wget binutils # Repack deb (removes unnecessary dependencies and produces /protonmail.deb) RUN bash /install.sh -FROM debian:sid-slim +FROM debian:trixie-slim LABEL maintainer="Trent Maetzold " LABEL org.opencontainers.image.source="https://github.com/trent-maetzold/protonmail-bridge-docker" From ee526c8d44dbd4b7e92dbcb8f4f3d83b97f0ef3c Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 18:30:25 +0000 Subject: [PATCH 14/24] Remove VERSION file, query GHCR tags for version check --- .github/workflows/build.yaml | 90 ++++++++++++------------------------ VERSION | 1 - 2 files changed, 29 insertions(+), 62 deletions(-) delete mode 100644 VERSION diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 9a4588a..cf9cb92 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -5,7 +5,6 @@ on: paths: - .github/workflows/build.yaml - build/* - - VERSION pull_request: paths: - .github/workflows/build.yaml @@ -21,59 +20,40 @@ env: jobs: version-check: runs-on: ubuntu-latest - if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' outputs: - updated: ${{ steps.check.outputs.updated }} version: ${{ steps.check.outputs.version }} + build_needed: ${{ steps.check.outputs.build_needed }} steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Check for new version + - name: Get latest upstream release id: check run: | - current=$(cat VERSION) latest=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') - echo "Current: $current, Latest: $latest" - if [ "$current" != "$latest" ]; then - echo "$latest" > VERSION - echo "updated=true" >> $GITHUB_OUTPUT - echo "version=$latest" >> $GITHUB_OUTPUT - else - echo "Version unchanged" - echo "updated=false" >> $GITHUB_OUTPUT - echo "version=$current" >> $GITHUB_OUTPUT - fi + echo "Latest upstream: $latest" + echo "version=$latest" >> $GITHUB_OUTPUT - - name: Create version bump PR - if: steps.check.outputs.updated == 'true' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - branch="auto/bump-${{ steps.check.outputs.version }}" - git config user.name 'github-actions[bot]' - git config user.email 'github-actions[bot]@users.noreply.github.com' - git checkout -b "$branch" - git add VERSION - git commit -m "Bump version to ${{ steps.check.outputs.version }}" - git push origin "$branch" - pr_url=$(gh pr create \ - --title "Bump proton-bridge to ${{ steps.check.outputs.version }}" \ - --body "Auto-detected new upstream release." \ - --base master \ - --head "$branch") - gh pr merge "$pr_url" --squash --auto + if [[ "${{ github.event_name }}" == "schedule" ]]; then + # Check if we already have this version in GHCR + token=$(curl -s "https://ghcr.io/token?scope=repository:trent-maetzold/protonmail-bridge:pull" | jq -r '.token') + tags=$(curl -s -H "Authorization: Bearer $token" "https://ghcr.io/v2/trent-maetzold/protonmail-bridge/tags/list" | jq -r '.tags[]?' 2>/dev/null || echo "") + if echo "$tags" | grep -qx "${latest}-build"; then + echo "Version ${latest} already built" + echo "build_needed=false" >> $GITHUB_OUTPUT + else + echo "New version ${latest} detected" + echo "build_needed=true" >> $GITHUB_OUTPUT + fi + else + echo "build_needed=true" >> $GITHUB_OUTPUT + fi test: runs-on: ubuntu-latest + needs: version-check if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref != 'refs/heads/master') steps: - name: Checkout uses: actions/checkout@v4 - - name: Set version - run: echo "version=$(cat VERSION)" >> $GITHUB_ENV - - name: Docker meta id: meta uses: docker/metadata-action@v5 @@ -101,7 +81,7 @@ jobs: tags: "${{ env.GHCR_REPO }}:dev-${{ github.ref_name }}" push: true build-args: | - version=${{ env.version }} + version=${{ needs.version-check.outputs.version }} - name: Run Trivy vulnerability scan uses: aquasecurity/trivy-action@0.30.0 @@ -119,11 +99,11 @@ jobs: build: runs-on: ubuntu-latest + needs: version-check if: | - (github.event_name == 'push' && github.ref == 'refs/heads/master') || - (needs.version-check.result == 'success' && needs.version-check.outputs.updated == 'true') - needs: - - version-check + needs.version-check.outputs.build_needed == 'true' && + (github.event_name != 'pull_request') && + (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/master')) strategy: fail-fast: false matrix: @@ -135,17 +115,12 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - ref: master - name: Prepare run: | platform=${{ matrix.platform }} echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - - name: Set version - run: echo "version=$(cat VERSION)" >> $GITHUB_ENV - - name: Docker meta id: meta uses: docker/metadata-action@v5 @@ -177,7 +152,7 @@ jobs: provenance: false sbom: false build-args: | - version=${{ env.version }} + version=${{ needs.version-check.outputs.version }} - name: Export digest run: | @@ -196,13 +171,9 @@ jobs: merge: runs-on: ubuntu-latest needs: + - version-check - build steps: - - name: Checkout - uses: actions/checkout@v4 - with: - ref: master - - name: Download digests uses: actions/download-artifact@v4 with: @@ -210,9 +181,6 @@ jobs: pattern: digests-* merge-multiple: true - - name: Set version - run: echo "version=$(cat VERSION)" >> $GITHUB_ENV - - name: Login to GHCR uses: docker/login-action@v3 with: @@ -231,7 +199,7 @@ jobs: with: images: ${{ env.GHCR_REPO }} tags: | - type=raw,enable=true,value=${{ env.version }}-build + type=raw,enable=true,value=${{ needs.version-check.outputs.version }}-build type=raw,enable=true,value=build type=raw,enable=true,value=latest @@ -244,7 +212,7 @@ jobs: - name: Run Trivy vulnerability scan uses: aquasecurity/trivy-action@0.30.0 with: - image-ref: "${{ env.GHCR_REPO }}:${{ env.version }}-build" + image-ref: "${{ env.GHCR_REPO }}:${{ needs.version-check.outputs.version }}-build" format: 'sarif' exit-code: 0 severity: 'CRITICAL,HIGH' @@ -257,4 +225,4 @@ jobs: - name: Inspect image run: | - docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ steps.meta.outputs.version }} + docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ needs.version-check.outputs.version }}-build diff --git a/VERSION b/VERSION deleted file mode 100644 index 6420a93..0000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -v3.22.0 \ No newline at end of file From 08380e548e1bbfd908f3baeac14ad9229a463541 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 18:31:50 +0000 Subject: [PATCH 15/24] Always build on push to master and workflow_dispatch, gate only scheduled runs --- .github/workflows/build.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index cf9cb92..8d6aadd 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -101,9 +101,12 @@ jobs: runs-on: ubuntu-latest needs: version-check if: | - needs.version-check.outputs.build_needed == 'true' && (github.event_name != 'pull_request') && - (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/master')) + ( + (github.event_name == 'push' && github.ref == 'refs/heads/master') || + (github.event_name == 'workflow_dispatch') || + (github.event_name == 'schedule' && needs.version-check.outputs.build_needed == 'true') + ) strategy: fail-fast: false matrix: From b8703845db7e427287bd84593bc8e0c22edf80a9 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 18:34:08 +0000 Subject: [PATCH 16/24] Split into two workflows: build (push/PR/dispatch) and scheduled-update (daily version check) --- .github/workflows/build.yaml | 52 ++------ .github/workflows/scheduled-update.yaml | 160 ++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/scheduled-update.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8d6aadd..f7427f6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -9,47 +9,27 @@ on: paths: - .github/workflows/build.yaml - build/* - schedule: - - cron: '0 6 * * *' workflow_dispatch: env: GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge - PLATFORMS: linux/amd64,linux/arm64/v8,linux/arm/v7,linux/riscv64 jobs: - version-check: + resolve-version: runs-on: ubuntu-latest outputs: - version: ${{ steps.check.outputs.version }} - build_needed: ${{ steps.check.outputs.build_needed }} + version: ${{ steps.resolve.outputs.version }} steps: - name: Get latest upstream release - id: check + id: resolve run: | latest=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') - echo "Latest upstream: $latest" echo "version=$latest" >> $GITHUB_OUTPUT - if [[ "${{ github.event_name }}" == "schedule" ]]; then - # Check if we already have this version in GHCR - token=$(curl -s "https://ghcr.io/token?scope=repository:trent-maetzold/protonmail-bridge:pull" | jq -r '.token') - tags=$(curl -s -H "Authorization: Bearer $token" "https://ghcr.io/v2/trent-maetzold/protonmail-bridge/tags/list" | jq -r '.tags[]?' 2>/dev/null || echo "") - if echo "$tags" | grep -qx "${latest}-build"; then - echo "Version ${latest} already built" - echo "build_needed=false" >> $GITHUB_OUTPUT - else - echo "New version ${latest} detected" - echo "build_needed=true" >> $GITHUB_OUTPUT - fi - else - echo "build_needed=true" >> $GITHUB_OUTPUT - fi - test: runs-on: ubuntu-latest - needs: version-check - if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref != 'refs/heads/master') + needs: resolve-version + if: github.event_name == 'pull_request' steps: - name: Checkout uses: actions/checkout@v4 @@ -81,7 +61,7 @@ jobs: tags: "${{ env.GHCR_REPO }}:dev-${{ github.ref_name }}" push: true build-args: | - version=${{ needs.version-check.outputs.version }} + version=${{ needs.resolve-version.outputs.version }} - name: Run Trivy vulnerability scan uses: aquasecurity/trivy-action@0.30.0 @@ -99,14 +79,8 @@ jobs: build: runs-on: ubuntu-latest - needs: version-check - if: | - (github.event_name != 'pull_request') && - ( - (github.event_name == 'push' && github.ref == 'refs/heads/master') || - (github.event_name == 'workflow_dispatch') || - (github.event_name == 'schedule' && needs.version-check.outputs.build_needed == 'true') - ) + needs: resolve-version + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' strategy: fail-fast: false matrix: @@ -155,7 +129,7 @@ jobs: provenance: false sbom: false build-args: | - version=${{ needs.version-check.outputs.version }} + version=${{ needs.resolve-version.outputs.version }} - name: Export digest run: | @@ -174,7 +148,7 @@ jobs: merge: runs-on: ubuntu-latest needs: - - version-check + - resolve-version - build steps: - name: Download digests @@ -202,7 +176,7 @@ jobs: with: images: ${{ env.GHCR_REPO }} tags: | - type=raw,enable=true,value=${{ needs.version-check.outputs.version }}-build + type=raw,enable=true,value=${{ needs.resolve-version.outputs.version }}-build type=raw,enable=true,value=build type=raw,enable=true,value=latest @@ -215,7 +189,7 @@ jobs: - name: Run Trivy vulnerability scan uses: aquasecurity/trivy-action@0.30.0 with: - image-ref: "${{ env.GHCR_REPO }}:${{ needs.version-check.outputs.version }}-build" + image-ref: "${{ env.GHCR_REPO }}:${{ needs.resolve-version.outputs.version }}-build" format: 'sarif' exit-code: 0 severity: 'CRITICAL,HIGH' @@ -228,4 +202,4 @@ jobs: - name: Inspect image run: | - docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ needs.version-check.outputs.version }}-build + docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ needs.resolve-version.outputs.version }}-build diff --git a/.github/workflows/scheduled-update.yaml b/.github/workflows/scheduled-update.yaml new file mode 100644 index 0000000..de493ff --- /dev/null +++ b/.github/workflows/scheduled-update.yaml @@ -0,0 +1,160 @@ +name: scheduled version check + +on: + schedule: + - cron: '0 6 * * *' + +env: + GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge + +jobs: + check: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.check.outputs.version }} + build_needed: ${{ steps.check.outputs.build_needed }} + steps: + - name: Check for new upstream version + id: check + run: | + latest=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') + echo "Latest upstream: $latest" + echo "version=$latest" >> $GITHUB_OUTPUT + + token=$(curl -s "https://ghcr.io/token?scope=repository:trent-maetzold/protonmail-bridge:pull" | jq -r '.token') + tags=$(curl -s -H "Authorization: Bearer $token" "https://ghcr.io/v2/trent-maetzold/protonmail-bridge/tags/list" | jq -r '.tags[]?' 2>/dev/null || echo "") + + if echo "$tags" | grep -qx "${latest}-build"; then + echo "Version ${latest} already built" + echo "build_needed=false" >> $GITHUB_OUTPUT + else + echo "New version ${latest} detected" + echo "build_needed=true" >> $GITHUB_OUTPUT + fi + + build: + needs: check + if: needs.check.outputs.build_needed == 'true' + strategy: + fail-fast: false + matrix: + platform: + - linux/amd64 + - linux/arm64/v8 + - linux/arm/v7 + - linux/riscv64 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Prepare + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.GHCR_REPO }} + + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + platforms: ${{ matrix.platform }} + labels: ${{ steps.meta.outputs.labels }} + outputs: type=image,"name=${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=true + context: ./build + file: ./build/Dockerfile + provenance: false + sbom: false + build-args: | + version=${{ needs.check.outputs.version }} + + - name: Export digest + run: | + mkdir -p ${{ runner.temp }}/digests + digest="${{ steps.build.outputs.digest }}" + touch "${{ runner.temp }}/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digests-${{ env.PLATFORM_PAIR }} + path: ${{ runner.temp }}/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + runs-on: ubuntu-latest + needs: + - check + - build + steps: + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: ${{ runner.temp }}/digests + pattern: digests-* + merge-multiple: true + + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver-opts: network=host + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.GHCR_REPO }} + tags: | + type=raw,enable=true,value=${{ needs.check.outputs.version }}-build + type=raw,enable=true,value=build + type=raw,enable=true,value=latest + + - name: Create manifest list and push + working-directory: ${{ runner.temp }}/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.GHCR_REPO }}@sha256:%s ' *) + + - name: Run Trivy vulnerability scan + uses: aquasecurity/trivy-action@0.30.0 + with: + image-ref: "${{ env.GHCR_REPO }}:${{ needs.check.outputs.version }}-build" + format: 'sarif' + exit-code: 0 + severity: 'CRITICAL,HIGH' + output: 'trivy-results.sarif' + + - name: Upload Trivy scan SARIF report + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: 'trivy-results.sarif' + + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ needs.check.outputs.version }}-build From fbbfab435d1b367a18c5a0ac5afabd5775cb1620 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 18:55:34 +0000 Subject: [PATCH 17/24] Fix PR test tag: use pr number instead of ref_name to avoid slash in tag --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f7427f6..ee1dd70 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -58,7 +58,7 @@ jobs: labels: ${{ steps.meta.outputs.labels }} context: ./build file: ./build/Dockerfile - tags: "${{ env.GHCR_REPO }}:dev-${{ github.ref_name }}" + tags: "${{ env.GHCR_REPO }}:dev-pr${{ github.event.pull_request.number }}" push: true build-args: | version=${{ needs.resolve-version.outputs.version }} @@ -66,7 +66,7 @@ jobs: - name: Run Trivy vulnerability scan uses: aquasecurity/trivy-action@0.30.0 with: - image-ref: "${{ env.GHCR_REPO }}:dev-${{ github.ref_name }}" + image-ref: "${{ env.GHCR_REPO }}:dev-pr${{ github.event.pull_request.number }}" format: 'sarif' exit-code: 0 severity: 'CRITICAL,HIGH' From ed4d5d491abd6a3127da7f11e42395739b0126ad Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 19:06:37 +0000 Subject: [PATCH 18/24] Add workflow permissions for GHCR write and security-events --- .github/workflows/build.yaml | 5 +++++ .github/workflows/scheduled-update.yaml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ee1dd70..1273d85 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -11,6 +11,11 @@ on: - build/* workflow_dispatch: +permissions: + contents: read + packages: write + security-events: write + env: GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge diff --git a/.github/workflows/scheduled-update.yaml b/.github/workflows/scheduled-update.yaml index de493ff..34b19d4 100644 --- a/.github/workflows/scheduled-update.yaml +++ b/.github/workflows/scheduled-update.yaml @@ -4,6 +4,11 @@ on: schedule: - cron: '0 6 * * *' +permissions: + contents: read + packages: write + security-events: write + env: GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge From c7d1ba9d28050bc5e28b5ca53dda863d44d09fe5 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 19:20:47 +0000 Subject: [PATCH 19/24] Test job: build only, no push to GHCR --- .github/workflows/build.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 1273d85..3884a2c 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -57,21 +57,21 @@ jobs: with: driver-opts: network=host - - name: Build and push + - name: Build uses: docker/build-push-action@v6 with: labels: ${{ steps.meta.outputs.labels }} context: ./build file: ./build/Dockerfile - tags: "${{ env.GHCR_REPO }}:dev-pr${{ github.event.pull_request.number }}" - push: true + load: true + tags: "protonmail-bridge:test" build-args: | version=${{ needs.resolve-version.outputs.version }} - name: Run Trivy vulnerability scan uses: aquasecurity/trivy-action@0.30.0 with: - image-ref: "${{ env.GHCR_REPO }}:dev-pr${{ github.event.pull_request.number }}" + image-ref: "protonmail-bridge:test" format: 'sarif' exit-code: 0 severity: 'CRITICAL,HIGH' From 36a706b6274054591d1e797b138711b84ffbe68a Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 19:26:37 +0000 Subject: [PATCH 20/24] Fix test job: use docker driver for load, drop SARIF upload and GHCR login --- .github/workflows/build.yaml | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3884a2c..e363b3b 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -45,22 +45,14 @@ jobs: with: images: ${{ env.GHCR_REPO }} - - name: Login to GHCR - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: - driver-opts: network=host + driver: docker - name: Build uses: docker/build-push-action@v6 with: - labels: ${{ steps.meta.outputs.labels }} context: ./build file: ./build/Dockerfile load: true @@ -72,15 +64,9 @@ jobs: uses: aquasecurity/trivy-action@0.30.0 with: image-ref: "protonmail-bridge:test" - format: 'sarif' + format: 'table' exit-code: 0 severity: 'CRITICAL,HIGH' - output: 'trivy-results.sarif' - - - name: Upload Trivy scan SARIF report - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: 'trivy-results.sarif' build: runs-on: ubuntu-latest From 3ae2d2dee57e9052a359ba8ad3ac807bf2edc8c3 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 19:49:03 +0000 Subject: [PATCH 21/24] Fix Trivy: run directly via docker instead of action to avoid exit code issues --- .github/workflows/build.yaml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e363b3b..c7a5f2d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -61,12 +61,13 @@ jobs: version=${{ needs.resolve-version.outputs.version }} - name: Run Trivy vulnerability scan - uses: aquasecurity/trivy-action@0.30.0 - with: - image-ref: "protonmail-bridge:test" - format: 'table' - exit-code: 0 - severity: 'CRITICAL,HIGH' + continue-on-error: true + run: | + docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + aquasec/trivy:latest image \ + --severity CRITICAL,HIGH \ + --exit-code 0 \ + protonmail-bridge:test build: runs-on: ubuntu-latest From 21ae9d5b7eb3a980a85c07d3e3b000568dce2f05 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 20:07:05 +0000 Subject: [PATCH 22/24] Rewrite CI from scratch: clean build + scheduled update, remove deb workflow --- .github/workflows/build.yaml | 188 +++++------------------- .github/workflows/deb.yaml | 77 ---------- .github/workflows/scheduled-update.yaml | 150 ++++--------------- deb/Dockerfile | 29 ---- deb/PACKAGE | 1 - deb/entrypoint.sh | 49 ------ deb/gpgparams | 8 - deb/install.sh | 16 -- 8 files changed, 65 insertions(+), 453 deletions(-) delete mode 100644 .github/workflows/deb.yaml delete mode 100644 deb/Dockerfile delete mode 100644 deb/PACKAGE delete mode 100644 deb/entrypoint.sh delete mode 100644 deb/gpgparams delete mode 100644 deb/install.sh diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c7a5f2d..c84fefe 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,14 +1,15 @@ -name: build from source +name: Build and Push on: push: + branches: [master] paths: - .github/workflows/build.yaml - - build/* + - build/** pull_request: paths: - .github/workflows/build.yaml - - build/* + - build/** workflow_dispatch: permissions: @@ -17,181 +18,58 @@ permissions: security-events: write env: - GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge + IMAGE: ghcr.io/${{ github.repository_owner }}/protonmail-bridge jobs: resolve-version: runs-on: ubuntu-latest outputs: - version: ${{ steps.resolve.outputs.version }} + version: ${{ steps.version.outputs.version }} steps: - name: Get latest upstream release - id: resolve + id: version run: | - latest=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') - echo "version=$latest" >> $GITHUB_OUTPUT + version=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') + echo "version=$version" >> $GITHUB_OUTPUT + echo "Resolved version: $version" - test: - runs-on: ubuntu-latest + build: needs: resolve-version - if: github.event_name == 'pull_request' + runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} + - uses: docker/setup-buildx-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + if: github.event_name != 'pull_request' with: - driver: docker + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Build uses: docker/build-push-action@v6 with: context: ./build - file: ./build/Dockerfile - load: true - tags: "protonmail-bridge:test" - build-args: | - version=${{ needs.resolve-version.outputs.version }} - - - name: Run Trivy vulnerability scan - continue-on-error: true - run: | - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ - aquasec/trivy:latest image \ - --severity CRITICAL,HIGH \ - --exit-code 0 \ - protonmail-bridge:test - - build: - runs-on: ubuntu-latest - needs: resolve-version - if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' - strategy: - fail-fast: false - matrix: - platform: - - linux/amd64 - - linux/arm64/v8 - - linux/arm/v7 - - linux/riscv64 - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Prepare - run: | - platform=${{ matrix.platform }} - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} - - - name: Login to GHCR - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build and push by digest - id: build - uses: docker/build-push-action@v6 - with: - platforms: ${{ matrix.platform }} - labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,"name=${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=true - context: ./build - file: ./build/Dockerfile - provenance: false - sbom: false - build-args: | - version=${{ needs.resolve-version.outputs.version }} - - - name: Export digest - run: | - mkdir -p ${{ runner.temp }}/digests - digest="${{ steps.build.outputs.digest }}" - touch "${{ runner.temp }}/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@v4 - with: - name: digests-${{ env.PLATFORM_PAIR }} - path: ${{ runner.temp }}/digests/* - if-no-files-found: error - retention-days: 1 - - merge: - runs-on: ubuntu-latest - needs: - - resolve-version - - build - steps: - - name: Download digests - uses: actions/download-artifact@v4 - with: - path: ${{ runner.temp }}/digests - pattern: digests-* - merge-multiple: true - - - name: Login to GHCR - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - driver-opts: network=host - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} + push: ${{ github.event_name != 'pull_request' }} + load: ${{ github.event_name == 'pull_request' }} tags: | - type=raw,enable=true,value=${{ needs.resolve-version.outputs.version }}-build - type=raw,enable=true,value=build - type=raw,enable=true,value=latest + ${{ env.IMAGE }}:latest + ${{ env.IMAGE }}:${{ needs.resolve-version.outputs.version }} + build-args: | + version=${{ needs.resolve-version.outputs.version }} - - name: Create manifest list and push - working-directory: ${{ runner.temp }}/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.GHCR_REPO }}@sha256:%s ' *) - - - name: Run Trivy vulnerability scan + - name: Trivy scan uses: aquasecurity/trivy-action@0.30.0 with: - image-ref: "${{ env.GHCR_REPO }}:${{ needs.resolve-version.outputs.version }}-build" - format: 'sarif' - exit-code: 0 - severity: 'CRITICAL,HIGH' - output: 'trivy-results.sarif' + image-ref: ${{ env.IMAGE }}:${{ needs.resolve-version.outputs.version }} + format: sarif + output: trivy-results.sarif + severity: CRITICAL,HIGH - - name: Upload Trivy scan SARIF report + - name: Upload Trivy results uses: github/codeql-action/upload-sarif@v3 + if: always() with: - sarif_file: 'trivy-results.sarif' - - - name: Inspect image - run: | - docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ needs.resolve-version.outputs.version }}-build + sarif_file: trivy-results.sarif diff --git a/.github/workflows/deb.yaml b/.github/workflows/deb.yaml deleted file mode 100644 index b938d12..0000000 --- a/.github/workflows/deb.yaml +++ /dev/null @@ -1,77 +0,0 @@ -name: pack from deb - -on: - push: - paths: - - .github/workflows/deb.yaml - - deb/* - - VERSION - pull_request: - paths: - - .github/workflows/deb.yaml - - deb/* - workflow_dispatch: - -env: - GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge - -jobs: - deb: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set version - run: echo "version=$(cat VERSION)" >> $GITHUB_ENV - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build image without push - uses: docker/build-push-action@v6 - with: - context: ./deb - file: ./deb/Dockerfile - load: true - tags: protonmail-bridge:latest - - - name: Run Trivy vulnerability scan - uses: aquasecurity/trivy-action@0.30.0 - with: - image-ref: protonmail-bridge:latest - format: 'sarif' - exit-code: 0 - severity: 'CRITICAL,HIGH' - output: 'trivy-results.sarif' - - - name: Upload Trivy scan SARIF report - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: 'trivy-results.sarif' - - - name: Login to GHCR - uses: docker/login-action@v3 - if: github.event_name != 'pull_request' - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Push image - uses: docker/build-push-action@v6 - if: github.event_name != 'pull_request' - with: - context: ./deb - file: ./deb/Dockerfile - tags: | - ${{ env.GHCR_REPO }}:latest - ${{ env.GHCR_REPO }}:${{ env.version }} - labels: ${{ steps.meta.outputs.labels }} - push: true diff --git a/.github/workflows/scheduled-update.yaml b/.github/workflows/scheduled-update.yaml index 34b19d4..6b8a331 100644 --- a/.github/workflows/scheduled-update.yaml +++ b/.github/workflows/scheduled-update.yaml @@ -1,4 +1,4 @@ -name: scheduled version check +name: Check for new upstream release on: schedule: @@ -10,156 +10,70 @@ permissions: security-events: write env: - GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge + IMAGE: ghcr.io/${{ github.repository_owner }}/protonmail-bridge jobs: check: runs-on: ubuntu-latest outputs: version: ${{ steps.check.outputs.version }} - build_needed: ${{ steps.check.outputs.build_needed }} + needed: ${{ steps.check.outputs.needed }} steps: - - name: Check for new upstream version + - name: Compare upstream to registry id: check run: | - latest=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') - echo "Latest upstream: $latest" - echo "version=$latest" >> $GITHUB_OUTPUT + version=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') + echo "version=$version" >> $GITHUB_OUTPUT - token=$(curl -s "https://ghcr.io/token?scope=repository:trent-maetzold/protonmail-bridge:pull" | jq -r '.token') - tags=$(curl -s -H "Authorization: Bearer $token" "https://ghcr.io/v2/trent-maetzold/protonmail-bridge/tags/list" | jq -r '.tags[]?' 2>/dev/null || echo "") + token=$(curl -s "https://ghcr.io/token?scope=repository:${{ github.repository_owner }}/protonmail-bridge:pull" | jq -r '.token') + exists=$(curl -s -o /dev/null -w '%{http_code}' \ + -H "Authorization: Bearer $token" \ + "https://ghcr.io/v2/${{ github.repository_owner }}/protonmail-bridge/manifests/$version") - if echo "$tags" | grep -qx "${latest}-build"; then - echo "Version ${latest} already built" - echo "build_needed=false" >> $GITHUB_OUTPUT + if [ "$exists" = "200" ]; then + echo "needed=false" >> $GITHUB_OUTPUT + echo "$version already exists in registry" else - echo "New version ${latest} detected" - echo "build_needed=true" >> $GITHUB_OUTPUT + echo "needed=true" >> $GITHUB_OUTPUT + echo "New version $version — building" fi build: needs: check - if: needs.check.outputs.build_needed == 'true' - strategy: - fail-fast: false - matrix: - platform: - - linux/amd64 - - linux/arm64/v8 - - linux/arm/v7 - - linux/riscv64 + if: needs.check.outputs.needed == 'true' runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Prepare - run: | - platform=${{ matrix.platform }} - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + - uses: docker/setup-buildx-action@v3 - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} - - - name: Login to GHCR - uses: docker/login-action@v3 + - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build and push by digest - id: build + - name: Build and push uses: docker/build-push-action@v6 with: - platforms: ${{ matrix.platform }} - labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,"name=${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=true context: ./build - file: ./build/Dockerfile - provenance: false - sbom: false + push: true + tags: | + ${{ env.IMAGE }}:latest + ${{ env.IMAGE }}:${{ needs.check.outputs.version }} build-args: | version=${{ needs.check.outputs.version }} - - name: Export digest - run: | - mkdir -p ${{ runner.temp }}/digests - digest="${{ steps.build.outputs.digest }}" - touch "${{ runner.temp }}/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@v4 - with: - name: digests-${{ env.PLATFORM_PAIR }} - path: ${{ runner.temp }}/digests/* - if-no-files-found: error - retention-days: 1 - - merge: - runs-on: ubuntu-latest - needs: - - check - - build - steps: - - name: Download digests - uses: actions/download-artifact@v4 - with: - path: ${{ runner.temp }}/digests - pattern: digests-* - merge-multiple: true - - - name: Login to GHCR - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - driver-opts: network=host - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} - tags: | - type=raw,enable=true,value=${{ needs.check.outputs.version }}-build - type=raw,enable=true,value=build - type=raw,enable=true,value=latest - - - name: Create manifest list and push - working-directory: ${{ runner.temp }}/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.GHCR_REPO }}@sha256:%s ' *) - - - name: Run Trivy vulnerability scan + - name: Trivy scan uses: aquasecurity/trivy-action@0.30.0 with: - image-ref: "${{ env.GHCR_REPO }}:${{ needs.check.outputs.version }}-build" - format: 'sarif' - exit-code: 0 - severity: 'CRITICAL,HIGH' - output: 'trivy-results.sarif' + image-ref: ${{ env.IMAGE }}:${{ needs.check.outputs.version }} + format: sarif + output: trivy-results.sarif + severity: CRITICAL,HIGH - - name: Upload Trivy scan SARIF report + - name: Upload Trivy results uses: github/codeql-action/upload-sarif@v3 + if: always() with: - sarif_file: 'trivy-results.sarif' - - - name: Inspect image - run: | - docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ needs.check.outputs.version }}-build + sarif_file: trivy-results.sarif diff --git a/deb/Dockerfile b/deb/Dockerfile deleted file mode 100644 index 383f8b7..0000000 --- a/deb/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -### The Deb install is just a repack of the official ProtonMail Bridge deb package with less dependencies. -### I recommend you don't use this. It's here for legacy reasons. - -FROM debian:trixie-slim AS build - -COPY install.sh PACKAGE / -RUN apt-get update && apt-get install -y wget binutils - -# Repack deb (removes unnecessary dependencies and produces /protonmail.deb) -RUN bash /install.sh - -FROM debian:trixie-slim -LABEL maintainer="Trent Maetzold " -LABEL org.opencontainers.image.source="https://github.com/trent-maetzold/protonmail-bridge-docker" - -EXPOSE 25/tcp -EXPOSE 143/tcp - -WORKDIR /protonmail - -# Copy bash scripts -COPY gpgparams entrypoint.sh PACKAGE /protonmail/ -COPY --from=build /protonmail.deb /tmp/protonmail.deb - -RUN apt-get update \ - && apt-get install -y --no-install-recommends /tmp/protonmail.deb socat pass libsecret-1-0 ca-certificates procps \ - && rm -rf /var/lib/apt/lists/* - -CMD ["bash", "/protonmail/entrypoint.sh"] diff --git a/deb/PACKAGE b/deb/PACKAGE deleted file mode 100644 index 6d4eacd..0000000 --- a/deb/PACKAGE +++ /dev/null @@ -1 +0,0 @@ -https://github.com/ProtonMail/proton-bridge/releases/download/v3.22.0/protonmail-bridge_3.22.0-1_amd64.deb \ No newline at end of file diff --git a/deb/entrypoint.sh b/deb/entrypoint.sh deleted file mode 100644 index 13637e5..0000000 --- a/deb/entrypoint.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -set -ex - -# Initialize -if [[ $1 == init ]]; then - - # # Parse parameters - # TFP="" # Default empty two factor passcode - # shift # skip `init` - # while [[ $# -gt 0 ]]; do - # key="$1" - # case $key in - # -u|--username) - # USERNAME="$2" - # ;; - # -p|--password) - # PASSWORD="$2" - # ;; - # -t|--twofactor) - # TWOFACTOR="$2" - # ;; - # esac - # shift - # shift - # done - - # Initialize pass - gpg --generate-key --batch /protonmail/gpgparams - pass init pass-key - - # Login - protonmail-bridge --cli - -else - - # socat will make the conn appear to come from 127.0.0.1 - # ProtonMail Bridge currently expects that. - # It also allows us to bind to the real ports :) - socat TCP-LISTEN:25,fork TCP:127.0.0.1:1025 & - socat TCP-LISTEN:143,fork TCP:127.0.0.1:1143 & - - # Start protonmail - # Fake a terminal, so it does not quit because of EOF... - rm -f faketty - mkfifo faketty - cat faketty | protonmail-bridge --cli - -fi diff --git a/deb/gpgparams b/deb/gpgparams deleted file mode 100644 index 355568e..0000000 --- a/deb/gpgparams +++ /dev/null @@ -1,8 +0,0 @@ -%no-protection -%echo Generating a basic OpenPGP key -Key-Type: RSA -Key-Length: 2048 -Name-Real: pass-key -Expire-Date: 0 -%commit -%echo done diff --git a/deb/install.sh b/deb/install.sh deleted file mode 100644 index 9593725..0000000 --- a/deb/install.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -set -ex - -# Repack deb (remove unnecessary dependencies) -mkdir deb -wget -i /PACKAGE -O /deb/protonmail.deb -cd deb -ar x -v protonmail.deb -mkdir control -tar zxvf control.tar.gz -C control -sed -i "s/^Depends: .*$/Depends: libgl1, libc6, libsecret-1-0, libstdc++6, libgcc1/" control/control -cd control -tar zcvf ../control.tar.gz . -cd ../ - -ar rcs -v /protonmail.deb debian-binary control.tar.gz data.tar.gz From b3cca778fa2bde5bbd2fc5f88347f1886ebf7564 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 20:14:05 +0000 Subject: [PATCH 23/24] Update Trivy action to 0.35.0 --- .github/workflows/build.yaml | 2 +- .github/workflows/scheduled-update.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c84fefe..ad72eb1 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -61,7 +61,7 @@ jobs: version=${{ needs.resolve-version.outputs.version }} - name: Trivy scan - uses: aquasecurity/trivy-action@0.30.0 + uses: aquasecurity/trivy-action@0.35.0 with: image-ref: ${{ env.IMAGE }}:${{ needs.resolve-version.outputs.version }} format: sarif diff --git a/.github/workflows/scheduled-update.yaml b/.github/workflows/scheduled-update.yaml index 6b8a331..9c03269 100644 --- a/.github/workflows/scheduled-update.yaml +++ b/.github/workflows/scheduled-update.yaml @@ -65,7 +65,7 @@ jobs: version=${{ needs.check.outputs.version }} - name: Trivy scan - uses: aquasecurity/trivy-action@0.30.0 + uses: aquasecurity/trivy-action@0.35.0 with: image-ref: ${{ env.IMAGE }}:${{ needs.check.outputs.version }} format: sarif From 5a8e960374ba973c19580fbe149a62ca703ff347 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 20:15:25 +0000 Subject: [PATCH 24/24] Use latest Trivy action --- .github/workflows/build.yaml | 2 +- .github/workflows/scheduled-update.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ad72eb1..e122e1f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -61,7 +61,7 @@ jobs: version=${{ needs.resolve-version.outputs.version }} - name: Trivy scan - uses: aquasecurity/trivy-action@0.35.0 + uses: aquasecurity/trivy-action@master with: image-ref: ${{ env.IMAGE }}:${{ needs.resolve-version.outputs.version }} format: sarif diff --git a/.github/workflows/scheduled-update.yaml b/.github/workflows/scheduled-update.yaml index 9c03269..0a2bbdc 100644 --- a/.github/workflows/scheduled-update.yaml +++ b/.github/workflows/scheduled-update.yaml @@ -65,7 +65,7 @@ jobs: version=${{ needs.check.outputs.version }} - name: Trivy scan - uses: aquasecurity/trivy-action@0.35.0 + uses: aquasecurity/trivy-action@master with: image-ref: ${{ env.IMAGE }}:${{ needs.check.outputs.version }} format: sarif