124 Commits

Author SHA1 Message Date
GitHub Actions
044ea2b034 Bump version to v3.21.2 2025-07-23 00:21:43 +00:00
GitHub Actions
b643ecf9b6 Bump version to v3.21.1 2025-06-19 00:20:36 +00:00
GitHub Actions
e788a0098e Bump version to v3.20.0 2025-05-16 00:20:00 +00:00
Simon Ungar Felding
4c7b9b9a8c fix version 2025-04-25 09:47:00 +02:00
Simon Ungar Felding
6b4a3e23a8 fix based on https://stackoverflow.com/questions/75521775/buildx-docker-image-claims-to-be-a-manifest-list 2025-04-25 00:20:40 +02:00
Simon Ungar Felding
e67c6cb97a fix push by digest 2025-04-24 23:36:08 +02:00
Simon Ungar Felding
84b7a76320 fix tags 2025-04-24 23:29:50 +02:00
Simon Ungar Felding
7e1b2d7104 fix build tags 2025-04-24 23:26:11 +02:00
Simon Ungar Felding
89d488b2fb fix build password 2025-04-24 23:11:47 +02:00
simonfelding
4ccd39856a improve build readability and speed (by parallelization) (#117) 2025-04-24 23:03:50 +02:00
GitHub Actions
540ba69528 Bump deb version to 3.19.0-1 2025-04-02 00:18:53 +00:00
GitHub Actions
546f813ea4 Bump build version to 3.19.0 2025-03-19 00:18:37 +00:00
GitHub Actions
794e58400a Bump deb version to 3.18.0-1 2025-03-07 00:17:55 +00:00
GitHub Actions
2bd42d97ca Bump build version to 3.18.0 2025-02-28 00:17:35 +00:00
GitHub Actions
c87479ac51 Bump deb version to 3.17.0-1 2025-02-20 00:17:27 +00:00
schklom
8ffef34853 Build when deb/* changes (#97)
The build calls to Protonmail's repo and builds from it. When that repo
changes (i.e. when deb/* changes), the image should be built again.

---------

Co-authored-by: Simon Ungar Felding <45149055+simonfelding@users.noreply.github.com>
2025-02-17 13:03:56 +01:00
simonfelding
2745c6eb57 deb build: make sure it has the necessary tools (#116) 2025-02-17 10:15:22 +01:00
simonfelding
d00645ffcc add vaulteditor and fix build on arm (#114)
first working build for a long time
2025-02-15 19:38:15 +01:00
simonfelding
a19458f703 fix builds by switching base layer to debian:sid-slim
tested locally, works fine.
debian has supported riscv64 in the sid image for some time.

this is the same thing the carlosedp/golang image did.

this also fixes the bug with the wrong glibc version, as the build
container now uses the same glibc version as the final container.
2025-02-15 17:07:15 +01:00
GitHub Actions
d2828adae6 Bump build version to 3.17.0 2025-02-14 00:17:18 +00:00
GitHub Actions
3d628a35e3 Bump deb version to 3.16.0-1 2025-02-14 00:17:17 +00:00
GitHub Actions
718ccfacc2 Bump build version to 3.20.12 2025-02-13 00:17:18 +00:00
GitHub Actions
6d4c8eee6c Bump deb version to 3.17.0-1 2025-02-11 00:17:05 +00:00
GitHub Actions
1cd0a1e01a Bump build version to 3.17.0 2025-01-30 00:16:31 +00:00
GitHub Actions
a92c7d34d6 Bump deb version to 3.16.0-1 2025-01-15 00:16:57 +00:00
GitHub Actions
c7cef79482 Bump build version to 3.16.0 2024-12-18 00:18:00 +00:00
GitHub Actions
7090760703 Bump deb version to 3.15.1-1 2024-12-12 00:18:23 +00:00
GitHub Actions
11cf98c1f4 Bump build version to 3.15.1 2024-12-06 00:18:35 +00:00
GitHub Actions
69fd67721a Bump deb version to 3.15.0-1 2024-11-26 00:18:12 +00:00
GitHub Actions
abf6dd9055 Bump build version to 3.15.0 2024-11-14 00:16:51 +00:00
GitHub Actions
363cef56c2 Bump deb version to 3.14.0-1 2024-10-23 00:16:59 +00:00
GitHub Actions
63e7e3098e Bump build version to 3.14.0 2024-10-01 00:18:58 +00:00
GitHub Actions
64b50d7e24 Bump build version to 3.13.0 2024-09-11 00:15:41 +00:00
GitHub Actions
f3da872c45 Bump deb version to 3.12.0-1 2024-07-03 00:14:31 +00:00
GitHub Actions
48717095db Bump build version to 3.12.0 2024-06-20 00:13:45 +00:00
GitHub Actions
8d820748ee Bump deb version to 3.11.1-1 2024-05-24 00:14:19 +00:00
GitHub Actions
471a00b96b Bump build version to 3.11.1 2024-05-22 00:13:26 +00:00
GitHub Actions
9b21cf69f1 Bump deb version to 3.11.0-1 2024-05-14 00:13:49 +00:00
GitHub Actions
3aee9f2e4a Bump build version to 3.11.0 2024-04-30 00:12:59 +00:00
GitHub Actions
3be7e930d9 Bump deb version to 3.10.0-1 2024-03-22 00:12:48 +00:00
GitHub Actions
47e204b047 Bump build version to 3.10.0 2024-03-13 00:12:46 +00:00
GitHub Actions
5b52d7c9aa Bump deb version to 3.9.1-1 2024-02-22 00:12:28 +00:00
GitHub Actions
bc9f21fa87 Bump build version to 3.9.1 2024-02-13 00:13:22 +00:00
Mark Monteiro
9d2bf07c78 Improve Docker Compose documentation and example (#95)
- Clean up the example `docker-compose.yml` file by removing unnecessary
configuration/comments and add missing volume declaration
- Update the project README.md with instructions on how to use the
project with Docker Compose
2024-02-08 11:06:43 +08:00
GitHub Actions
2ac707c0c3 Bump deb version to 3.8.2-1 2024-02-03 00:12:59 +00:00
GitHub Actions
64495cd318 Bump build version to 3.9.0 2024-02-01 00:13:28 +00:00
GitHub Actions
1a8b879f90 Bump deb version to 3.8.1-1 2024-01-13 00:13:25 +00:00
GitHub Actions
ca1fd017f0 Bump build version to 3.8.1 2023-12-13 00:13:09 +00:00
GitHub Actions
a1afacb63a Bump build version to 3.8.0 2023-12-12 00:13:22 +00:00
GitHub Actions
47e04a9690 Bump deb version to 3.7.1-1 2023-12-07 00:13:08 +00:00
GitHub Actions
5d94313662 Bump build version to 3.7.1 2023-11-23 00:13:20 +00:00
GitHub Actions
5fd66d65ef Bump build version to 3.7.0 2023-11-15 00:13:09 +00:00
GitHub Actions
43f5b98e9d Bump deb version to 3.6.1-2 2023-11-02 00:12:21 +00:00
GitHub Actions
0d0808a6cd Bump build version to 3.6.1 2023-10-21 00:12:01 +00:00
GitHub Actions
ad930ab89f Bump deb version to 3.5.4-1 2023-10-20 00:12:26 +00:00
GitHub Actions
1fe6a19bd5 Bump build version to 3.6.0 2023-10-18 00:12:28 +00:00
GitHub Actions
fc7540d86f Bump build version to 3.5.3 2023-10-13 00:12:40 +00:00
GitHub Actions
9fb8bc7aae Bump deb version to 3.5.3-1 2023-10-13 00:12:39 +00:00
GitHub Actions
e782f3fca6 Bump build version to 3.5.2 2023-10-11 00:12:13 +00:00
GitHub Actions
28068b7451 Bump deb version to 3.4.2-1 2023-10-07 00:12:24 +00:00
GitHub Actions
a262d3381a Bump deb version to 3.5.1-1 2023-10-05 00:12:20 +00:00
GitHub Actions
33196176b6 Bump build version to 3.5.1 2023-09-29 00:12:21 +00:00
GitHub Actions
7358ead1c0 Bump deb version to 3.4.2-1 2023-09-26 00:12:28 +00:00
GitHub Actions
b764f02f7a Bump build version to 3.5.0 2023-09-15 00:12:17 +00:00
GitHub Actions
3b069e5899 Bump build version to 3.4.2 2023-09-05 00:11:36 +00:00
GitHub Actions
1423a659e1 Bump build version to 3.4.1 2023-08-15 00:11:45 +00:00
GitHub Actions
932bc92e2a Bump build version to 3.4.0 2023-08-05 00:13:04 +00:00
GitHub Actions
0ed338435d Bump build version to 3.3.2 2023-07-14 00:15:56 +00:00
GitHub Actions
1b9e896e30 Bump deb version to 3.3.2-1 2023-07-14 00:15:56 +00:00
GitHub Actions
d9fec14796 Bump build version to 3.3.1 2023-07-08 00:16:29 +00:00
GitHub Actions
b6a470849e Bump deb version to 3.3.0-1 2023-06-22 00:14:57 +00:00
GitHub Actions
ddb3df2c7c Bump build version to 3.3.0 2023-06-09 00:17:58 +00:00
GitHub Actions
58cd2eee1d Bump deb version to 3.2.0-1 2023-05-27 00:13:19 +00:00
GitHub Actions
3cbc54a93b Bump build version to 3.2.0 2023-05-16 00:12:45 +00:00
GitHub Actions
868b1a48c6 Bump build version to 3.1.3 2023-05-11 00:12:36 +00:00
GitHub Actions
0419d36658 Bump deb version to 3.1.3-1 2023-05-11 00:12:35 +00:00
Daniel Nathan Gray
67415bd261 Add a docker compose file (#70)
It's quite the norm to include a docker-compose file, generally in the
README or the root for people to copy and modify. For example as
https://github.com/wfg/docker-openvpn-client has done so.

If there are [Environmental
variables](https://github.com/wfg/docker-openvpn-client#environment-variables),
they should also be documented - in this case there isn't.
2023-05-02 14:26:43 +08:00
GitHub Actions
d0e4bcd866 Bump build version to 3.1.2 2023-04-28 00:13:24 +00:00
GitHub Actions
5a0238e8f4 Bump deb version to 3.1.2-1 2023-04-28 00:13:23 +00:00
GitHub Actions
1dff35b541 Bump build version to 3.1.1 2023-04-12 00:12:15 +00:00
GitHub Actions
7790563b9f Bump build version to 3.1.0 2023-04-06 00:12:09 +00:00
GitHub Actions
7c0d8737dc Bump build version to 3.0.21 2023-03-24 00:13:03 +00:00
GitHub Actions
50ac4c2e44 Bump deb version to 3.0.21-1 2023-03-24 00:13:02 +00:00
Aziz Hasanain
b1b6706030 Update Ubuntu tag for deb to fix GLIBC dependency (#80)
GLIBC dependency issue highlighted in
https://github.com/shenxn/protonmail-bridge-docker/issues/79 is caused
by v3 of the bridge not supporting bionic. This PR simply updates the
"deb" version to match the "build" version which is already on
ubuntu:jammy.
2023-03-23 09:13:58 +08:00
GitHub Actions
b0eeddd83d Bump build version to 3.0.20 2023-03-11 00:12:48 +00:00
GitHub Actions
a264602469 Bump deb version to 3.0.20-1 2023-03-11 00:12:47 +00:00
GitHub Actions
6a492a15e7 Bump build version to 3.0.19 2023-03-02 00:15:24 +00:00
GitHub Actions
bb34034cbb Bump deb version to 3.0.19-1 2023-03-02 00:15:23 +00:00
GitHub Actions
109da843e7 Bump build version to 3.0.18 2023-02-25 00:14:35 +00:00
GitHub Actions
b5938721aa Bump deb version to 3.0.17-1 2023-02-23 00:15:10 +00:00
GitHub Actions
dc8590849b Bump build version to 3.0.16 2023-02-18 00:14:05 +00:00
GitHub Actions
8c80cf2d03 Bump build version to 3.0.15 2023-02-15 00:14:54 +00:00
GitHub Actions
e6319a0dda Bump build version to 3.0.14 2023-02-10 00:14:30 +00:00
GitHub Actions
da1b515c2f Bump build version to 3.0.12 2023-02-02 00:13:53 +00:00
GitHub Actions
18626db87f Bump build version to 3.0.10 2023-01-18 00:13:48 +00:00
Daniel Nathan Gray
89b3ef69f4 Rebase on Jammy (#71)
If you're going to build v3 you need to have Jammy, or you will get
glibc errors
2023-01-14 14:56:03 +08:00
GitHub Actions
04a2fae963 Bump build version to 3.0.9 2022-12-21 00:12:33 +00:00
GitHub Actions
bd9addf4f4 Bump build version to 3.0.7 2022-12-17 00:12:20 +00:00
GitHub Actions
c3140a3fa0 Bump build version to 3.0.6 2022-12-08 00:13:17 +00:00
GitHub Actions
51015361c5 Bump build version to 3.0.5 2022-12-06 00:12:45 +00:00
GitHub Actions
0e92386a93 Bump build version to 3.0.4 2022-12-03 00:12:21 +00:00
GitHub Actions
2e3bcdef1f Bump build version to 3.0.2 2022-11-30 00:15:14 +00:00
GitHub Actions
cf1e025209 Bump deb version to 2.3.0-1 2022-11-26 00:13:33 +00:00
GitHub Actions
4dbf2f806e Bump deb version to 2.4.8-1 2022-11-23 00:14:33 +00:00
Xiaonan Shen
712de23988 Add riscv64 support to CI docker builds (#54) 2022-11-21 00:14:03 +08:00
Olof Nord
0541f29d98 Add riscv64 support to docker builds
* Adjust GitHub CI to also build for riscv64
* Update base Ubuntu base for build from 18.04 LTS to 20.04 LTS as to support riscv64
* Minor: Exclude idea IDE files from git
2022-11-20 23:32:58 +08:00
Xiaonan Shen
252397a86d Switch to carlosedp/golang for riscv64 support 2022-11-20 23:12:46 +08:00
GitHub Actions
6a2a413d0a Bump build version to 2.4.8 2022-11-17 00:15:47 +00:00
GitHub Actions
60c8a9ecc4 Bump build version to 2.4.5 2022-11-09 00:16:36 +00:00
Xiaonan Shen
535c80379d Copy bridge executable to the image (fixes #66) 2022-11-05 14:30:33 +08:00
GitHub Actions
acefed1b95 Bump build version to 2.4.3 2022-10-26 00:16:54 +00:00
Xiaonan Shen
6decf657c2 Bump golang to 1.18 2022-10-16 15:04:58 +08:00
Xiaonan Shen
0fa5f9fc13 Fix entrypoint init fail issue 2022-10-16 14:49:38 +08:00
Xiaonan Shen
e0b0ce653c Add .vscode to .gitignore 2022-10-16 14:47:32 +08:00
GitHub Actions
fa4ddf7126 Bump build version to 2.4.0 2022-09-29 00:23:38 +00:00
GitHub Actions
07d3779fc6 Bump deb version to 2.3.0-1 2022-09-09 00:17:44 +00:00
GitHub Actions
2e9d95d90b Bump build version to 2.3.0 2022-09-02 00:15:28 +00:00
GitHub Actions
a8f5c0a096 Bump build version to 2.2.2 2022-07-28 00:15:49 +00:00
GitHub Actions
14cac1052d Bump deb version to 2.2.2-1 2022-07-28 00:15:47 +00:00
GitHub Actions
92b0c5bd5f Bump build version to 2.2.1 2022-07-22 00:16:20 +00:00
Xiaonan Shen
812646acb9 Fix entrypoint so it works correctly on init #57 2022-05-28 12:40:24 +08:00
GitHub Actions
664b5e924d Bump build version to 2.2.0 2022-05-26 00:14:14 +00:00
Nilesh
680e82076e Fix entrypoint so it works correctly on init
Ran into this issue when trying to use in kubernetes via k8s-at-home/protonmail-bridge. Took a bit of figuring out before I realized I had to manually kill the other instance. The only output from the failed load is a dbus issue, and an immediate exit.
2022-05-12 11:31:03 -07:00
GitHub Actions
86e10823e0 Bump deb version to 2.1.3-1 2022-04-28 00:15:49 +00:00
26 changed files with 535 additions and 877 deletions

View File

@@ -1,93 +1,232 @@
name: Build docker image name: build from source
on: on:
push: push:
branches: paths:
- master - .github/workflows/build.yaml
- beta - build/*
- dev - VERSION
- http-rest
pull_request: pull_request:
paths:
- .github/workflows/build.yaml
- build/*
workflow_dispatch:
env: env:
DOCKER_REPO: shenxn/protonmail-bridge GHCR_REPO: shenxn/protonmail-bridge-docker
DOCKER_REPO_DEV: ghcr.io/shenxn/protonmail-bridge-dev DOCKERHUB_REPO: shenxn/protonmail-bridge
PLATFORMS: linux/amd64,linux/arm64/v8,linux/arm/v7 DOCKER_REPO_DEV: ghcr.io/shenxn/protonmail-bridge
PLATFORMS: linux/amd64,linux/arm64/v8,linux/arm/v7,linux/riscv64
jobs: jobs:
build: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
services: if: github.ref != 'refs/heads/master'
registry:
image: registry:2
ports:
- 5000:5000
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@master uses: actions/checkout@master
- name: Set bridge version
- name: Set version
id: version id: version
run: | run: echo "version=`cat VERSION`" >> $GITHUB_ENV
echo "::set-output name=bridge_version::$(cat BRIDGE_VERSION)"
echo "::set-output name=version::$(cat VERSION)"
- name: Set repo
id: repo
run: |
if [[ $GITHUB_REF == "refs/heads/master" || $GITHUB_REF == "refs/heads/beta" ]]; then
echo "::set-output name=repo::${DOCKER_REPO}"
else
echo "::set-output name=repo::${DOCKER_REPO_DEV}"
fi
- name: Docker meta - name: Docker meta
id: docker_meta id: meta
uses: crazy-max/ghaction-docker-meta@v1 uses: docker/metadata-action@v5
with: with:
images: ${{ steps.repo.outputs.repo }} images: |
- name: Set up QEMU ${{ env.DOCKER_REPO_DEV }}
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx - name: Login to GHCR
uses: docker/setup-buildx-action@v1 uses: docker/login-action@v3
with:
driver-opts: network=host
- name: Build image without push to registry
uses: docker/build-push-action@v2
with:
platforms: ${{ env.PLATFORMS }}
build-args: BRIDGE_VERSION=${{ steps.version.outputs.bridge_version }}
push: true
tags: localhost:5000/protonmail-bridge:latest
- name: Scan image
id: scan
uses: anchore/scan-action@v2
with:
image: localhost:5000/protonmail-bridge:latest
fail-build: true
severity-cutoff: critical
acs-report-enable: true
- name: Upload Anchore scan SARIF report
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ${{ steps.scan.outputs.sarif }}
- name: Login to DockerHub
uses: docker/login-action@v1
if: ${{ github.event_name != 'pull_request' && steps.repo.outputs.repo == env.DOCKER_REPO }}
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' && steps.repo.outputs.repo == env.DOCKER_REPO_DEV }}
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ secrets.CR_PAT }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Push image
uses: docker/build-push-action@v2 - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with: with:
platforms: ${{ env.PLATFORMS }} driver-opts: network=host
build-args: BRIDGE_VERSION=${{ steps.version.outputs.bridge_version }}
- name: Build and push by digest
id: build
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 }}"
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 }}"
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'
build:
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64/v8
- linux/arm/v7
- linux/riscv64
steps:
- name: Checkout
uses: actions/checkout@master
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Set version
id: version
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 }}
- 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=name=${{ env.DOCKERHUB_REPO }},${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=false
context: ./build
file: ./build/Dockerfile
tags: | tags: |
${{ steps.repo.outputs.repo }}:beta "${{ env.DOCKERHUB_REPO }}:build"
${{ steps.repo.outputs.repo }}:${{ steps.version.outputs.version }} "${{ env.DOCKERHUB_REPO }}:${{ env.version }}-build"
labels: ${{ steps.docker_meta.outputs.labels }} "${{ env.GHCR_REPO }}:build"
push: ${{ github.event_name != 'pull_request' }} "${{ env.GHCR_REPO }}:${{ env.version }}-build"
provenance: false
sbom: false
build-args: |
version=${{ env.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:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
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 }}
- 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.DOCKERHUB_REPO }}
${{ env.GHCR_REPO }}
tags: |
type=raw,enable=true,value=${{ env.version }}-build
type=raw,enable=true,suffix=,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"
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.DOCKERHUB_REPO }}:${{ steps.meta.outputs.version }}
docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ steps.meta.outputs.version }}

79
.github/workflows/deb.yaml vendored Normal file
View File

@@ -0,0 +1,79 @@
name: pack from deb
on:
push:
paths:
- .github/workflows/deb.yaml
- deb/*
- VERSION
pull_request:
paths:
- .github/workflows/deb.yaml
- deb/*
workflow_dispatch:
env:
DOCKER_REPO: shenxn/protonmail-bridge
DOCKER_REPO_DEV: ghcr.io/shenxn/protonmail-bridge-dev
jobs:
deb:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master
- 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
- name: Docker meta
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v1
with:
images: ${{ steps.repo.outputs.repo }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Build image without push
uses: docker/build-push-action@v2
with:
context: ./deb
file: ./deb/Dockerfile
load: true
tags: protonmail-bridge:latest
- name: Scan image
id: scan
uses: anchore/scan-action@v2
with:
image: protonmail-bridge:latest
fail-build: true
severity-cutoff: critical
acs-report-enable: true
- name: Upload Anchore 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' }}
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.CR_PAT }}
- name: Push image
uses: docker/build-push-action@v2
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' }}

View File

@@ -2,9 +2,6 @@ name: update check
on: on:
push: push:
branches:
- master
- dev
paths: paths:
- .github/workflows/update-check.yaml - .github/workflows/update-check.yaml
- update-check.py - update-check.py

2
.gitignore vendored
View File

@@ -1 +1,3 @@
# Ignoring IDE-specific files
.idea/*
.vscode .vscode

View File

@@ -1 +0,0 @@
v2.2.0

View File

@@ -1,37 +0,0 @@
FROM golang:1.15 AS build
# Install dependencies
RUN apt-get update && apt-get install -y libsecret-1-dev
ARG BRIDGE_VERSION
# Build
WORKDIR /build/
COPY build.sh /build/
COPY http_rest_frontend /build/http_rest_frontend
RUN bash build.sh
FROM ubuntu:bionic
LABEL maintainer="Xiaonan Shen <s@sxn.dev>"
EXPOSE 25/tcp
EXPOSE 143/tcp
HEALTHCHECK --timeout=2s CMD nc -z 127.0.0.1 1025 && nc -z 127.0.0.1 1143
# Install dependencies and protonmail bridge
RUN apt-get update \
&& apt-get install -y --no-install-recommends socat pass libsecret-1-0 ca-certificates curl gosu netcat \
&& rm -rf /var/lib/apt/lists/*
RUN curl -sSL https://github.com/krallin/tini/releases/download/v0.19.0/tini-$(dpkg --print-architecture) -o /tini \
&& chmod +x /tini
# Copy bash scripts
COPY gpgparams entrypoint.sh run_protonmail_bridge.sh cli.sh /protonmail/script/
RUN ln -s /protonmail/script/cli.sh /usr/local/bin/cli
# Copy protonmail
COPY --from=build /build/proton-bridge/proton-bridge /usr/local/bin/
VOLUME [ "/protonmail/data" ]
ENTRYPOINT ["/tini", "--", "/protonmail/script/entrypoint.sh"]

107
README.md
View File

@@ -12,86 +12,15 @@ Docker Hub: [https://hub.docker.com/r/shenxn/protonmail-bridge](https://hub.dock
GitHub: [https://github.com/shenxn/protonmail-bridge-docker](https://github.com/shenxn/protonmail-bridge-docker) GitHub: [https://github.com/shenxn/protonmail-bridge-docker](https://github.com/shenxn/protonmail-bridge-docker)
## ProtonMail Bridge Docker 2.0 Announcement ## ARM Support
ProtonMail Bridge Docker 2.0 uses a completely different approach that makes the whole container much easier to use. First of all, it now supports setting up with environmental variables only. No longer messing with terminal commands. Secondly, it now provides a easy way to interact with the bridge, include getting account information, adding, and removing accounts, all after the first initialization. This version is now in beta. Feel free to test it by using the `beta` tag (`shenxn/protonmail-bridge:beta`). We now support ARM devices (`arm64` and `arm/v7`)! Use the images tagged with `build`. See next section for details.
### Environmental Variables ## Tags
name | default | description
-- | -- | --
`PROTON_USERNAME` | | Username of your Proton account.
`PROTON_PASSWORD` | | Password of your Proton account.
`PROTON_2FA` | | Two-factor authentication code of your Proton account. Only needed if you have two factor authentication enabled.
`PROTON_MAILBOX_PASSWORD` | | Mailbox password of your Proton account. Only needed if you have two-password mode enabled.
`PROTON_PRINT_ACCOUNT_INFO` | `true` | Whether to print the local connection information (username, password, ports, security, etc.) on successful auto logins. Set to `false` to turn it off.
`PROTON_IMAP_PORT` | `25` | IMAP port of the bridge.
`PROTON_SMTP_PORT` | `143` | SMTP port of the bridge.
`PROTON_SMTP_SECURITY` | `STARTTLS` | Connection security of SMTP. Can be set to `STARTTLS` or `SSL`.
`PROTON_MANAGEMENT_PORT` | `1080` | Port of the management HTTP server.
`PROTON_ALLOW_PROXY` | `true` | Allow or disallow the Bridge client to securely connect to Proton via a third party when it is being blocked.
`PROTON_UID` | `1001` | UID of the user to run the bridge.
`PROTON_GID` | `1001` | GID of the group to run the bridge.
### Data Volume
All data are stored under `/protonmail/data`.
### Auto Login
2.0 comes with auto login, a highly demanded feature. By set `PROTON_USERNAME`, `PROTON_PASSWORD`, `PROTON_2FA`, and `PROTON_MAILBOX_PASSWORD`, the container will automatically add your account to the bridge and print local connection info to the log. Note:
- The auto login feature only kicks in when the bridge has zero account added. If there is at least one account, auto login will be skipped. Changing the environmental variables will neither add another account to the bridge nor replace the account with the new one. To do so, use [CLI](#cli).
- Two factor authentication codes time out quickly (in 30 seconds). It is highly possible that the code is already expired at the time login take place. To help with that, you can try pull the image first before setting it. You can also wait for a new code so that the container will have full 30 seconds to boot up. If non of them works, try manual login with [CLI](#cli).
- If your container logs can be accessed by someone else, it is recommended to turn of the account info printing by set `PROTON_PRINT_ACCOUNT_INFO` to `false`. Then you can use [CLI](#cli) to fetch the account info.
### CLI
2.0 comes with a CLI to easily interact with the bridge. There is no need to modify the entrypoint, manually kill any process, or restart the container when you are done. Everything you need is to `exec` into the container and run `cli`. With that, you can add, remove, list accounts and print account info. Changing the address mode of an account is currently not supported. To do so, simply delete the account and add it back again. Example:
```
➜ docker exec -it protonmail cli
CLI to interacte with Proton Bridge HTTP REST interface
Available commands:
login: Calls up the login procedure to add or connect accounts.
delete <account>: Remove the account from keychain. You can use index or account name as the parameter.
list: Print list of your accounts.
info <account>: Print account configuration. You can use index or account name as the parameter.
help: Print help messages.
exit: Exit the CLI
>> info bob
Configuration for bob@proton.me
IMAP port: 143
IMAP security: STARTTLS
SMTP port: 25
SMTP security: STARTTLS
Username: bob@proton.me
Password: xxxxxxxxxxxxxxxxxxxxxx
>> exit
```
### Migrate from old version
To migrate, you just need to change the mount path from `/root` to `/protonmail/data` and the container will do the rest of the work. Note that this is a one way trip. There is no way to get back to the old version. You'll need to set up everything again from scratch to go back. Also, any bridge preferences (e.g. whether to use a proxy) will not be migrated. You'll need to set them again with the environmental variables. Not all preferences are supported yet. Feel free to open an issue or PR for options you want to change. If anything goes sideways, it can be caused by problematic migrating steps. You can try to clear your volume and start everything from the scratch.
## Supported architectures
architecture | status | note
-- | --
`amd64` | supported |
`arm64/v8` | supported |
`arm/v7` | supported | 32-bit platforms are no longer officially supported by Proton. Thanks to blumberg for the workaround [#40](https://github.com/shenxn/protonmail-bridge-docker/pull/40)
`riscv64` | WIP | Check progress at [#54](https://github.com/shenxn/protonmail-bridge-docker/pull/54)
## Legacy Documentation
This section contains information for the old version. They are kept here for reference and will be removed once 2.0 graduates from beta.
### Tags
There are two types of images. 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. - `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`, and `arm/v7`. Supporting to more architectures is possible. PRs are welcome. - `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.
tag | description tag | description
-- | -- -- | --
@@ -100,7 +29,7 @@ tag | description
`build` | latest `build` image `build` | latest `build` image
`[version]-build` | `build` images `[version]-build` | `build` images
### Initialization ## Initialization
To initialize and add account to the bridge, run the following command. To initialize and add account to the bridge, run the following command.
@@ -108,9 +37,15 @@ To initialize and add account to the bridge, run the following command.
docker run --rm -it -v protonmail:/root shenxn/protonmail-bridge init docker run --rm -it -v protonmail:/root shenxn/protonmail-bridge init
``` ```
Wait for the bridge to startup, use `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. 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:
### Run ```
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.
## Run
To run the container, use the following command. To run the container, use the following command.
@@ -118,13 +53,19 @@ 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 1025:25/tcp -p 1143:143/tcp --restart=unless-stopped shenxn/protonmail-bridge
``` ```
### Kubernetes Or, if using Docker Compose, use the following command.
```
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 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). 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 ## 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. 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.
@@ -134,15 +75,15 @@ docker run -d --name=protonmail-bridge -v protonmail:/root -p 127.0.0.1:1025:25/
Besides, you can publish only port 25 (SMTP) if you don't need to receive any email (e.g. as a email notification service). 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 ## 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 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.
### Bridge CLI Guide ## 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 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.
### Build ## 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 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
``` ```

View File

@@ -1 +1 @@
2.0.0-beta v3.21.2

View File

@@ -1,24 +0,0 @@
#!/bin/bash
set -ex
# Clone new code
git clone https://github.com/ProtonMail/proton-bridge.git
cd proton-bridge
git checkout ${BRIDGE_VERSION}
# Patch HTTP REST frontend
rm -rf internal/frontend/cli
cp -r /build/http_rest_frontend/cli internal/frontend/
# Build
if (! make build-nogui) && [[ $(getconf LONG_BIT) == "32" ]]; then
# If build fails it's probably because it is a 32bit
# system and there was a overflow error on the parser
# This is a workaround for this problem found at:
# https://github.com/antlr/antlr4/issues/2433#issuecomment-774514106
find $(go env GOPATH)/pkg/mod/github.com/\!proton\!mail/go-rfc5322*/ -type f -exec sed -i.bak 's/(1<</(int64(1)<</g' {} +
# Try again after implementing the workaround
make build-nogui
fi

33
build/Dockerfile Normal file
View File

@@ -0,0 +1,33 @@
# 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
ARG version
# Install dependencies
RUN apt-get update && apt-get install -y golang build-essential libsecret-1-dev
# Build
ADD https://github.com/ProtonMail/proton-bridge.git#${version} /build/
WORKDIR /build/
RUN make build-nogui vault-editor
FROM debian:sid-slim
LABEL maintainer="Simon Felding <sife@adm.ku.dk>"
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 \
&& rm -rf /var/lib/apt/lists/*
# Copy bash scripts
COPY gpgparams entrypoint.sh /protonmail/
# Copy protonmail
COPY --from=build /build/bridge /protonmail/
COPY --from=build /build/proton-bridge /protonmail/
COPY --from=build /build/vault-editor /protonmail/
ENTRYPOINT ["bash", "/protonmail/entrypoint.sh"]

35
build/entrypoint.sh Normal file
View File

@@ -0,0 +1,35 @@
#!/bin/bash
set -ex
# Initialize
if [[ $1 == init ]]; then
# Initialize pass
gpg --generate-key --batch /protonmail/gpgparams
pass init pass-key
# Kill the other instance as only one can be running at a time.
# This allows users to run entrypoint init inside a running conainter
# which is useful in a k8s environment.
# || true to make sure this would not fail in case there is no running instance.
pkill protonmail-bridge || true
# Login
/protonmail/proton-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/proton-bridge --cli $@
fi

79
cli.sh
View File

@@ -1,79 +0,0 @@
#!/bin/bash
set -e
URL_BASE=http://127.0.0.1:${PROTON_MANAGEMENT_PORT:-1080}
print_help() {
echo "Available commands:"
echo " login: Calls up the login procedure to add or connect accounts."
echo " delete <account>: Remove the account from keychain. You can use index or account name as the parameter."
echo " list: Print list of your accounts."
echo " info <account>: Print account configuration. You can use index or account name as the parameter."
echo " help: Print help messages."
echo " exit: Exit the CLI"
}
account_list() {
curl ${URL_BASE}/accounts
}
account_login() {
read -p "Username: " USERNAME
read -sp "Password: " PASSWORD
echo
read -p "2FA Code (leave empty if not set): " TWO_FACTOR
read -p "Mailbox Password (leave empty if not set): " MAILBOX_PASSWORD
read -p "Address Mode (combined / split): " ADDRESS_MODE
curl ${URL_BASE}/accounts -XPUT \
--data-urlencode "username=${USERNAME}" \
--data-urlencode "password=${PASSWORD}" \
--data-urlencode "two-factor=${TWO_FACTOR}" \
--data-urlencode "mailbox-password=${MAILBOX_PASSWORD}" \
--data-urlencode "address-mode=${ADDRESS_MODE}"
}
account_delete() {
if [[ -z $1 ]]; then
echo "Error: delete requires one parameter, which is the index or account name."
else
read -p "Are you sure you want to delete account $1? " REPLY
if [[ $REPLY =~ ^[Yy] ]]; then
curl ${URL_BASE}/accounts/$1 -XDELETE
else
echo "Abort"
fi
fi
}
account_info() {
if [[ -z $1 ]]; then
echo "Error: info requires one parameter, which is the index or account name."
else
curl ${URL_BASE}/accounts/$1
fi
}
echo "CLI to interacte with Proton Bridge HTTP REST interface"
print_help
while true; do
echo
read -p ">> " COMMAND ARG
case "$COMMAND" in
login)
account_login;;
delete)
account_delete $ARG;;
list)
account_list;;
info)
account_info $ARG;;
help)
print_help;;
exit)
exit 0;;
*)
echo "Invalid command"
esac
done

28
deb/Dockerfile Normal file
View File

@@ -0,0 +1,28 @@
### 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
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:sid-slim
LABEL maintainer="Simon Felding <sife@adm.ku.dk>"
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"]

1
deb/PACKAGE Normal file
View File

@@ -0,0 +1 @@
https://github.com/ProtonMail/proton-bridge/releases/download/v3.21.2/protonmail-bridge_3.21.2-1_amd64.deb

49
deb/entrypoint.sh Normal file
View File

@@ -0,0 +1,49 @@
#!/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

8
deb/gpgparams Normal file
View File

@@ -0,0 +1,8 @@
%no-protection
%echo Generating a basic OpenPGP key
Key-Type: RSA
Key-Length: 2048
Name-Real: pass-key
Expire-Date: 0
%commit
%echo done

16
deb/install.sh Normal file
View File

@@ -0,0 +1,16 @@
#!/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

14
docker-compose.yml Normal file
View File

@@ -0,0 +1,14 @@
version: '2.1'
services:
protonmail-bridge:
image: shenxn/protonmail-bridge
ports:
- 1025:25/tcp
- 1143:143/tcp
restart: unless-stopped
volumes:
- protonmail:/root
volumes:
protonmail:
name: protonmail

View File

@@ -1,37 +0,0 @@
#!/bin/bash
set -e
echo "Welcome to ProtonMail Bridge Docker 2.0. This version comes with plently of"
echo "improvements. This version is not compatible with old configs and data volumes."
echo "If you are coming from the old version, please clean up your volumes and set up"
echo "everything from scratch. For more information about the new version, check"
echo "https://github.com/shenxn/protonmail-bridge-docker"
echo
if [ -d /root/.config/protonmail ]; then
echo "Volume mount at `/root` for old version found. Please change your mount path to `/protonmail/data`."
echo "See https://github.com/shenxn/protonmail-bridge-docker for detailed migration guide."
echo "Exit in 30 seconds..."
sleep 30
exit 1
fi
groupadd -g ${PROTON_GID:-1001} proton
useradd -g proton -u ${PROTON_UID:-1001} -m proton
chown proton:proton /protonmail/data
# Migrate old version data
if [ -d /protonmail/data/.config/protonmail ]; then
echo "Migrating legacy data. Note that this operation is irreversible so it is impossible"
echo "to go back to the old version without clearing the volume."
echo
mv /protonmail/data/.config/protonmail /protonmail/data/config
rm -rf /protonmail/data/.config
mv /protonmail/data/.cache/protonmail /protonmail/data/cache
rm -rf /protonmail/data/.cache
chown proton:proton -R /protonmail/data
fi
exec gosu proton:proton /protonmail/script/run_protonmail_bridge.sh "$@"

View File

@@ -1,163 +0,0 @@
// Package cli provides HTTP interface of the bridge
package cli
import (
"context"
"fmt"
"io"
"net/http"
"os"
"strings"
"github.com/ProtonMail/proton-bridge/internal/config/settings"
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
"github.com/julienschmidt/httprouter"
"github.com/sirupsen/logrus"
)
func (f *frontendCLI) loginAccount(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
if err := r.ParseForm(); err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "ParseForm() err: %v", err)
return
}
username := r.FormValue("username")
password := r.FormValue("password")
twoFactor := r.FormValue("two-factor")
mailboxPassword := r.FormValue("mailbox-password")
addressMode := r.FormValue("address-mode")
if addressMode == "" {
addressMode = "combined"
}
if addressMode != "combined" && addressMode != "split" {
http.Error(w, fmt.Sprintf("%s is not a valid address mode. Choose from 'combined' and 'split'."), http.StatusBadRequest)
return
}
client, auth, err := f.bridge.Login(username, []byte(password))
if err != nil {
f.processAPIError(err)
http.Error(w, fmt.Sprintf("Server error: %s", err.Error()), http.StatusUnauthorized)
return
}
if auth.HasTwoFactor() {
if twoFactor == "" {
w.WriteHeader(http.StatusUnauthorized)
http.Error(w, "2FA enabled for the account but a 2FA code was not provided.", http.StatusUnauthorized)
return
}
err = client.Auth2FA(context.Background(), twoFactor)
if err != nil {
f.processAPIError(err)
http.Error(w, fmt.Sprintf("Server error: %s", err.Error()), http.StatusUnauthorized)
return
}
}
if auth.HasMailboxPassword() {
if mailboxPassword == "" {
http.Error(w, "Two password mode enabled but a mailbox password was not provided.", http.StatusUnauthorized)
return
}
} else {
mailboxPassword = password
}
user, err := f.bridge.FinishLogin(client, auth, []byte(mailboxPassword))
if err != nil {
f.processAPIError(err)
http.Error(w, fmt.Sprintf("Server error: %s", err.Error()), http.StatusUnauthorized)
return
}
fmt.Fprintf(w, "Account %s was added successfully.\n", user.Username())
if addressMode == "split" {
err = user.SwitchAddressMode()
if err != nil {
logrus.Errorf("Failed to switch address mode of %s to split: %s", user.Username(), err.Error())
http.Error(w, "Failed to switch address mode to split", http.StatusInternalServerError)
return
}
}
f.printAccountInfo(w, user)
}
func (f *frontendCLI) deleteAccount(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
account := params.ByName("account")
user := f.getUserByIndexOrName(account)
if user == nil {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Account %s does not exist.\n", account)
return
}
account = user.Username()
if err := f.bridge.DeleteUser(user.ID(), true); err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintln(w, "Cannot delete account: ", err)
return
}
fmt.Fprintf(w, "Account %s was deleted successfully.\n", account)
}
func (f *frontendCLI) listAccounts(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
users := f.bridge.GetUsers()
if len(users) == 0 {
fmt.Fprintln(w, "No account found.")
return
}
spacing := "%-2d: %-20s (%-15s, %-15s)\n"
fmt.Fprintf(w, strings.ReplaceAll(spacing, "d", "s"), "#", "account", "status", "address mode")
for idx, user := range users {
connected := "disconnected"
if user.IsConnected() {
connected = "connected"
}
mode := "split"
if user.IsCombinedAddressMode() {
mode = "combined"
}
fmt.Fprintf(w, spacing, idx, user.Username(), connected, mode)
}
}
func (f *frontendCLI) showAccountInfo(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
account := params.ByName("account")
user := f.getUserByIndexOrName(account)
if user == nil {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Account %s does not exist.\n", account)
return
}
if !user.IsConnected() {
fmt.Fprintf(w, "Please login to %s to get email client configuration.\n", user.Username())
return
}
f.printAccountInfo(w, user)
}
func (f *frontendCLI) printAccountInfo(w io.Writer, user types.User) {
if user.IsCombinedAddressMode() {
f.printAccountAddressInfo(w, user, user.GetPrimaryAddress())
} else {
for _, address := range user.GetAddresses() {
f.printAccountAddressInfo(w, user, address)
}
}
}
func (f *frontendCLI) printAccountAddressInfo(w io.Writer, user types.User, address string) {
fmt.Fprintln(w, "Configuration for", address)
smtpSecurity := "STARTTLS"
if f.settings.GetBool(settings.SMTPSSLKey) {
smtpSecurity = "SSL"
}
fmt.Fprintf(w, "IMAP port: %s\nIMAP security: %s\nSMTP port: %s\nSMTP security: %s\nUsername: %s\nPassword: %s\n",
os.Getenv("PROTON_IMAP_PORT"),
"STARTTLS",
os.Getenv("PROTON_SMTP_PORT"),
smtpSecurity,
address,
user.GetBridgePassword(),
)
fmt.Fprintln(w, "")
}

View File

@@ -1,24 +0,0 @@
package cli
import (
"strconv"
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
)
func (f *frontendCLI) getUserByIndexOrName(account string) types.User {
users := f.bridge.GetUsers()
numberOfAccounts := len(users)
if index, err := strconv.Atoi(account); err == nil {
if index < 0 || index >= numberOfAccounts {
return nil
}
return users[index]
}
for _, user := range users {
if user.Username() == account {
return user
}
}
return nil
}

View File

@@ -1,163 +0,0 @@
// Package cli provides HTTP interface of the bridge
package cli
import (
"context"
"fmt"
"net/http"
"os"
"strings"
"github.com/ProtonMail/proton-bridge/internal/config/settings"
"github.com/ProtonMail/proton-bridge/internal/events"
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
"github.com/ProtonMail/proton-bridge/internal/locations"
"github.com/ProtonMail/proton-bridge/internal/updater"
"github.com/ProtonMail/proton-bridge/pkg/listener"
"github.com/julienschmidt/httprouter"
"github.com/sirupsen/logrus"
)
type frontendCLI struct {
*httprouter.Router
locations *locations.Locations
settings *settings.Settings
eventListener listener.Listener
updater types.Updater
bridge types.Bridger
restarter types.Restarter
}
func New(
panicHandler types.PanicHandler,
locations *locations.Locations,
settings *settings.Settings,
eventListener listener.Listener,
updater types.Updater,
bridge types.Bridger,
restarter types.Restarter,
) *frontendCLI {
fe := &frontendCLI{
Router: httprouter.New(),
locations: locations,
settings: settings,
eventListener: eventListener,
updater: updater,
bridge: bridge,
restarter: restarter,
}
fe.PUT("/accounts", fe.loginAccount)
fe.GET("/accounts", fe.listAccounts)
fe.GET("/accounts/:account", fe.showAccountInfo)
fe.DELETE("/accounts/:account", fe.deleteAccount)
return fe
}
func (f *frontendCLI) loginWithEnv() {
if len(f.bridge.GetUsers()) > 0 {
fmt.Println("More than 0 accounts found. Skip auto login.")
return
}
username := os.Getenv("PROTON_USERNAME")
password := os.Getenv("PROTON_PASSWORD")
if username == "" {
logrus.Info("PROTON_USERNAME and PROTON_PASSWORD are not set. Skip auto login.")
return
}
client, auth, err := f.bridge.Login(username, []byte(password))
if err != nil {
f.processAPIError(err)
logrus.WithError(err).Warn("Login failed.")
return
}
if auth.HasTwoFactor() {
twoFactor := os.Getenv("PROTON_2FA")
if twoFactor == "" {
logrus.Warn("Login failed: 2FA enabled for the account but PROTON_2FA was not set.")
return
}
err = client.Auth2FA(context.Background(), twoFactor)
if err != nil {
f.processAPIError(err)
logrus.WithError(err).Warn("Login failed.")
return
}
}
mailboxPassword := password
if auth.HasMailboxPassword() {
mailboxPassword = os.Getenv("PROTON_MAILBOX_PASSWORD")
if mailboxPassword == "" {
logrus.Warn("Login failed: Two password mode enabled but PROTON_MAILBOX_PASSWORD was not set.")
return
}
}
user, err := f.bridge.FinishLogin(client, auth, []byte(mailboxPassword))
if err != nil {
f.processAPIError(err)
logrus.WithError(err).Warn("Login failed.")
return
}
logrus.Infof("Account %s was added successfully.\n", user.Username())
if strings.ToLower(os.Getenv("PROTON_PRINT_ACCOUNT_INFO")) != "false" {
f.printAccountInfo(os.Stdout, user)
}
}
func (f *frontendCLI) watchEvents() {
errorCh := f.eventListener.ProvideChannel(events.ErrorEvent)
credentialsErrorCh := f.eventListener.ProvideChannel(events.CredentialsErrorEvent)
internetConnChangedCh := f.eventListener.ProvideChannel(events.InternetConnChangedEvent)
addressChangedCh := f.eventListener.ProvideChannel(events.AddressChangedEvent)
addressChangedLogoutCh := f.eventListener.ProvideChannel(events.AddressChangedLogoutEvent)
logoutCh := f.eventListener.ProvideChannel(events.LogoutEvent)
certIssue := f.eventListener.ProvideChannel(events.TLSCertIssue)
for {
select {
case errorDetails := <-errorCh:
logrus.Error("Bridge failed:", errorDetails)
case <-credentialsErrorCh:
f.notifyCredentialsError()
case stat := <-internetConnChangedCh:
if stat == events.InternetOff {
f.notifyInternetOff()
}
if stat == events.InternetOn {
f.notifyInternetOn()
}
case address := <-addressChangedCh:
fmt.Printf("Address changed for %s. You may need to reconfigure your email client.", address)
case address := <-addressChangedLogoutCh:
f.notifyLogout(address)
case userID := <-logoutCh:
user, err := f.bridge.GetUser(userID)
if err != nil {
return
}
f.notifyLogout(user.Username())
case <-certIssue:
f.notifyCertIssue()
}
}
}
func (f *frontendCLI) Loop() error {
f.loginWithEnv()
managementPort := os.Getenv("PROTON_MANAGEMENT_PORT")
if managementPort == "" {
managementPort = "1080"
}
http.ListenAndServe(":"+managementPort, f)
return nil
}
func (f *frontendCLI) NotifyManualUpdate(update updater.VersionInfo, canInstall bool) {}
func (f *frontendCLI) WaitUntilFrontendIsReady() {}
func (f *frontendCLI) SetVersion(version updater.VersionInfo) {}
func (f *frontendCLI) NotifySilentUpdateInstalled() {}
func (f *frontendCLI) NotifySilentUpdateError(err error) {}

View File

@@ -1,57 +0,0 @@
package cli
import (
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
"github.com/sirupsen/logrus"
)
func (f *frontendCLI) processAPIError(err error) {
switch err {
case pmapi.ErrNoConnection:
f.notifyInternetOff()
case pmapi.ErrUpgradeApplication:
f.notifyNeedUpgrade()
}
}
func (f *frontendCLI) notifyInternetOff() {
logrus.Warn("Internet connection is not available.")
}
func (f *frontendCLI) notifyInternetOn() {
logrus.Info("Internet connection is available again.")
}
func (f *frontendCLI) notifyLogout(address string) {
logrus.Infof("Account %s is disconnected. Login to continue using this account with email client.", address)
}
func (f *frontendCLI) notifyNeedUpgrade() {
logrus.Info("Upgrade needed. Please download and install the newest version of application.")
}
func (f *frontendCLI) notifyCredentialsError() {
logrus.Error(`ProtonMail Bridge is not able to detect a supported password manager
(secret-service or pass). Please install and set up a supported password manager
and restart the application.
`)
}
func (f *frontendCLI) notifyCertIssue() {
// Print in 80-column width.
logrus.Error(`Connection security error: Your network connection to Proton services may
be insecure.
Description:
ProtonMail Bridge was not able to establish a secure connection to Proton
servers due to a TLS certificate error. This means your connection may
potentially be insecure and susceptible to monitoring by third parties.
Recommendation:
* If you trust your network operator, you can continue to use ProtonMail
as usual.
* If you don't trust your network operator, reconnect to ProtonMail over a VPN
(such as ProtonVPN) which encrypts your Internet connection, or use
a different network to access ProtonMail.
`)
}

View File

@@ -1,72 +0,0 @@
#!/bin/bash
set -e
# Generate gpg keys
GNUPG_PATH=/protonmail/data/.gnupg
export GNUPGHOME=${GNUPG_PATH}
if [ ! -d ${GNUPG_PATH} ]; then
echo "Generateing gpg keys..."
# set GNUPGHOME to a temp directory as a workaround for
#
# gpg-agent[106]: error binding socket to '/root/.gnupg/S.gpg-agent': File name too long
#
# when using docker volume mount
#
# ref: https://dev.gnupg.org/T2964
#
export GNUPGHOME=/tmp/gnupg
mkdir ${GNUPGHOME}
chmod 700 ${GNUPGHOME}
gpg --generate-key --batch /protonmail/script/gpgparams
pkill gpg-agent
mv ${GNUPGHOME} ${GNUPG_PATH}
export GNUPGHOME=${GNUPG_PATH}
fi
# Initialize pass
PASSWORD_STORE=/protonmail/data/.password-store
if [ ! -d ${PASSWORD_STORE} ]; then
echo "Initializing pass..."
pass init pass-key
# Move password store to /protonmail/data
mv ${HOME}/.password-store ${PASSWORD_STORE}
fi
# Link the password store back to ~/.password-store
# There is no easy way to change the path used by pass
ln -s ${PASSWORD_STORE} ${HOME}/.password-store
# Link config and cache folders to /protonmail/data
PROTON_CONFIG_PATH=/protonmail/data/config
PROTON_CACHE_PATH=/protonmail/data/cache
mkdir -p ${PROTON_CONFIG_PATH}
mkdir -p ${HOME}/.config
ln -s ${PROTON_CONFIG_PATH} ${HOME}/.config/protonmail
mkdir -p ${PROTON_CACHE_PATH}
mkdir ${HOME}/.cache
ln -s ${PROTON_CACHE_PATH} ${HOME}/.cache/protonmail
# Generateing perfs.json
mkdir -p ${PROTON_CONFIG_PATH}/bridge
if [ ${PROTON_SMTP_SECURITY:-STARTTLS} == "SSL" ]; then
PROTON_SSL_SMTP="true"
else
PROTON_SSL_SMTP="false"
fi
cat <<EOF > ${PROTON_CONFIG_PATH}/bridge/prefs.json
{
"allow_proxy": "${PROTON_ALLOW_PROXY:-true}",
"autoupdate": "false",
"user_ssl_smtp": "${PROTON_SSL_SMTP}"
}
EOF
export PROTON_SMTP_PORT=${PROTON_SMTP_PORT:-25}
export PROTON_IMAP_PORT=${PROTON_IMAP_PORT:=143}
# 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:${PROTON_SMTP_PORT},fork TCP:127.0.0.1:1025 &
socat TCP-LISTEN:${PROTON_IMAP_PORT},fork TCP:127.0.0.1:1143 &
exec proton-bridge --cli "$@"

View File

@@ -1,64 +1,37 @@
import sys import requests, os, sys
import os
import requests
import json
import re
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" is_pull_request = sys.argv[1] == "true"
print(f"is_pull_request={is_pull_request}")
if is_pull_request:
print("This is a pull request, skipping push step.")
exit(0)
def check_version(directory, new_version): if git("push") != 0:
print(f"Checking version for {directory}") print("Git push failed!")
exit(1)
if not new_version:
print("Failed to get new version. Exiting.")
exit(1)
with open(f"{directory}/VERSION", "r") as f:
old_version = f.read().rstrip()
print(f"Up-to-date version {new_version}")
print(f"Current version: {old_version}")
if old_version != new_version:
print(f"New release found: {new_version}")
# bump up to new release
with open(f"{directory}/VERSION", "w") as f:
f.write(new_version)
# commit
result = os.system(f"git config --local user.email 'actions@github.com' \
&& git config --local user.name 'GitHub Actions' \
&& git add {directory}/VERSION \
&& git commit -m 'Bump {directory} version to {new_version}'")
if result != 0:
print("Failed to commit the bump. Exiting")
exit(1)
if is_pull_request:
print("Action triggered by pull request. Do not push.")
else:
result = os.system("git push")
if result != 0:
print("Failed to push. Exiting")
exit(1)
else:
print(f"Already newest version {old_version}")
# check deb version
response = requests.get("https://protonmail.com/download/current_version_linux.json")
content = json.loads(response.content)
version = re.match(".*_([0-9.-]+)_amd64\.deb", content["DebFile"]).group(1)
check_version("deb", version)
# check build version
response = requests.get(
"https://api.github.com/repos/ProtonMail/proton-bridge/tags",
headers={"Accept": "application/vnd.github.v3+json"},
)
tags = json.loads(response.content)
version_re = re.compile("v\d+\.\d+\.\d+")
releases = [tag["name"][1:] for tag in tags if version_re.match(tag["name"])]
check_version("build", releases[0])