summaryrefslogtreecommitdiff
path: root/f3s/protonbridge/helm-chart/templates/deployment.yaml
blob: 9394bafd265b451310c62633d691870a7a94bd9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
apiVersion: apps/v1
kind: Deployment
metadata:
  name: protonbridge
  namespace: services
spec:
  replicas: 1
  # Recreate so the old pod fully terminates before the new one starts —
  # prevents two bridge instances racing for the same vault on NFS.
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: protonbridge
  template:
    metadata:
      labels:
        app: protonbridge
    spec:
      initContainers:
      - name: nfs-check-data
        image: busybox:stable
        command:
        - sh
        - -c
        - |
          test -f /mnt/.nfs-sentinel || (
            echo "ERROR: NFS sentinel missing at /mnt/.nfs-sentinel"
            echo "refusing to start; node likely has NFS unmounted"
            echo "pod would otherwise bind-mount the local-XFS shadow"
            exit 1
          )
        volumeMounts:
        - name: protonbridge-data
          mountPath: /mnt
          readOnly: true
      - name: setup-pass
        # Initializes GPG + pass on first run so Bridge v3 has a working keychain.
        # All state is written to /bridge-data (the PVC) so it persists across restarts.
        # No-op on subsequent starts (idempotency checks on pubring.kbx + password-store).
        image: shenxn/protonmail-bridge:latest
        command:
        - /bin/sh
        - -c
        - |
          export GNUPGHOME=/bridge-data/.gnupg
          export PASSWORD_STORE_DIR=/bridge-data/.password-store
          if [ ! -f "${GNUPGHOME}/pubring.kbx" ]; then
            echo "First run: initializing GPG key..."
            mkdir -p "${GNUPGHOME}" && chmod 700 "${GNUPGHOME}"
            printf "allow-loopback-pinentry\n" > "${GNUPGHOME}/gpg-agent.conf"
            printf "pinentry-mode loopback\n" > "${GNUPGHOME}/gpg.conf"
            gpg --batch --gen-key <<'GPGEOF'
          Key-Type: RSA
          Key-Length: 2048
          Name-Real: protonbridge
          Name-Email: protonbridge@local
          Expire-Date: 0
          %no-protection
          %commit
          GPGEOF
            echo "GPG key created."
          fi
          FINGERPRINT=$(gpg --list-secret-keys --with-colons 2>/dev/null | awk -F: '/^fpr/{print $10; exit}')
          if [ -n "$FINGERPRINT" ] && [ ! -d "${PASSWORD_STORE_DIR}" ]; then
            echo "Initializing pass with key $FINGERPRINT..."
            pass init "$FINGERPRINT"
          fi
          echo "Pass setup complete."
        volumeMounts:
        - name: protonbridge-data
          mountPath: /bridge-data
      containers:
      - name: protonbridge
        # Bridge v3 daemon. IMAP and SMTP stay available while account management
        # is performed through a separate CLI process.
        #
        # Session persists in pass on NFS PVC; subsequent restarts reconnect automatically.
        #
        # ACCOUNT LOGIN (when Bridge reports no active accounts):
        #   1. Get pod name: kubectl get pod -n services -l app=protonbridge
        #   2. Start a CLI connected to the daemon:
        #        kubectl exec -it -n services <pod-name> -- protonmail-bridge --cli
        #   3. At the bridge> prompt, type 'login' and follow the prompts
        #   4. Type 'quit'; only the separate CLI exits
        #
        # EMAIL CLIENT SETUP (after login):
        #   IMAP: <any-r-vm-lan-ip>:30143, STARTTLS, accept self-signed cert
        #   SMTP: <any-r-vm-lan-ip>:30025, STARTTLS, accept self-signed cert
        #   Username: your ProtonMail address
        #   Password: bridge-generated password (from 'info' in the CLI above)
        image: shenxn/protonmail-bridge:latest
        command:
        - /bin/bash
        - -c
        - |
          export GNUPGHOME=/bridge-data/.gnupg
          export PASSWORD_STORE_DIR=/bridge-data/.password-store
          apt-get update -qq
          apt-get install -y -qq --no-install-recommends libfido2-1
          socat TCP-LISTEN:25,fork TCP:127.0.0.1:1025 &
          socat TCP-LISTEN:143,fork TCP:127.0.0.1:1143 &
          exec protonmail-bridge --noninteractive
        env:
        - name: GNUPGHOME
          value: /bridge-data/.gnupg
        - name: PASSWORD_STORE_DIR
          value: /bridge-data/.password-store
        ports:
        - name: imap
          containerPort: 143
          protocol: TCP
        - name: smtp
          containerPort: 25
          protocol: TCP
        volumeMounts:
        - name: protonbridge-data
          mountPath: /bridge-data
        - name: protonbridge-data
          # Bridge writes its config (login tokens, account data) to ~/.config/protonmail.
          # The container runs as root so HOME=/root; mount a subpath for the bridge config.
          mountPath: /root/.config
          subPath: dot-config
        - name: protonbridge-data
          # Persist Bridge's self-updated binary across pod restarts.
          mountPath: /root/.local
          subPath: dot-local
        readinessProbe:
          exec:
            command:
            - /bin/bash
            - -c
            - "</dev/tcp/127.0.0.1/1143"
          initialDelaySeconds: 30
          periodSeconds: 15
        startupProbe:
          exec:
            command:
            - /bin/bash
            - -c
            - "</dev/tcp/127.0.0.1/1143"
          periodSeconds: 10
          failureThreshold: 30
        livenessProbe:
          exec:
            command:
            - /bin/bash
            - -c
            - "</dev/tcp/127.0.0.1/1143"
          initialDelaySeconds: 60
          periodSeconds: 30
      volumes:
      - name: protonbridge-data
        persistentVolumeClaim:
          claimName: protonbridge-data-pvc