귀하의 개인정보 보호를 위해 암호화된 SQLite 메일함
다른 이메일 서비스와 달리 우리는 항상 귀하만이 귀하의 편지함에 접근할 수 있도록 보장합니다.
- 검색 페이지
- 목차
머리말
tldr; 우리의 이메일 서비스는 100% 오픈 소스 안전하고 암호화된 SQLite 메일박스를 통해 개인정보 보호에 중점을 둡니다.
출시하기 전까지 IMAP 지원, 우리는 지속적인 데이터 스토리지 요구 사항을 위해 MongoDB를 사용했습니다.
이 기술은 놀랍고 오늘날에도 여전히 사용됩니다. 하지만 MongoDB로 저장 시 암호화 기능을 사용하려면 Digital Ocean 또는 Mongo Atlas와 같이 MongoDB Enterprise를 제공하는 공급자를 이용하거나 기업 라이선스 비용을 지불해야 합니다(그리고 이후에는 영업팀 대기 시간과 협력해야 합니다).
우리 팀은 이메일 전달 IMAP 사서함을 위한 개발자 친화적이고 확장 가능하며 안정적이며 암호화된 저장소 솔루션이 필요했습니다. 오픈 소스 개발자로서 미사용 암호화 기능을 사용하려면 라이센스 비용을 지불해야 하는 기술을 사용하는 것이 반대였습니다. 우리의 원칙 – 그래서 우리는 이러한 요구 사항을 해결하기 위해 처음부터 새로운 솔루션을 실험, 연구 및 개발했습니다.
귀하의 편지함을 저장하기 위해 공유 데이터베이스를 사용하는 대신, 우리는 귀하의 비밀번호(귀하만이 알고 있는)로 귀하의 편지함을 개별적으로 저장하고 암호화합니다. 우리의 이메일 서비스는 매우 안전하므로 비밀번호를 잊어버리면 사서함도 잃어버릴 수 있습니다 (오프라인 백업으로 복구하거나 다시 시작해야 함)
아래에서 자세히 알아보면서 계속 읽어보세요. 이메일 서비스 제공업체 비교, 우리 서비스가 어떻게 작동하는지, 우리의 기술 스택, 그리고 더.
이메일 서비스 제공업체 비교
우리는 개별적으로 암호화된 SQLite 사서함을 저장하고 무제한 도메인, 별칭 및 사용자를 제공하며 아웃바운드 SMTP, IMAP 및 POP3를 지원하는 유일한 100% 오픈 소스 및 개인 정보 보호 중심 이메일 서비스 제공업체입니다.
다른 이메일 제공업체와 달리 이메일 전달을 사용하면 도메인 또는 별칭 기준으로 저장 비용을 지불할 필요가 없습니다. 스토리지는 전체 계정에서 공유됩니다. 따라서 각각에 여러 개의 맞춤 도메인 이름과 여러 개의 별칭이 있는 경우 당사가 완벽한 솔루션입니다. 원하는 경우 도메인 또는 별칭별로 저장 용량 제한을 적용할 수 있습니다.
어떻게 작동하나요?
-
Apple Mail, Thunderbird, Gmail 또는 Outlook과 같은 이메일 클라이언트를 사용하여 보안에 연결합니다. IMAP 귀하의 사용자 이름과 비밀번호를 사용하는 서버:
- 귀하의 사용자 이름은 다음과 같은 도메인의 전체 별칭입니다.
hello@example.com
. - 귀하의 비밀번호는 무작위로 생성되며 클릭 시 30초 동안만 표시됩니다. 비밀번호 생성 ~에서 내 계정 도메인 별칭.
- 귀하의 사용자 이름은 다음과 같은 도메인의 전체 별칭입니다.
-
연결되면 이메일 클라이언트에서 IMAP 프로토콜 명령 사서함을 동기화 상태로 유지하려면 IMAP 서버에 연결하세요. 여기에는 초안 이메일을 작성하고 저장하는 것과 귀하가 수행할 수 있는 기타 작업(예: 이메일에 중요 라벨을 지정하거나 이메일을 스팸/정크 메일로 표시)이 포함됩니다.
-
메일 교환 서버(일반적으로 "MX" 서버로 알려짐)는 새로운 인바운드 이메일을 수신하여 이를 사용자의 편지함에 저장합니다. 이런 일이 발생하면 이메일 클라이언트가 알림을 받고 사서함을 동기화합니다. 당사의 메일 교환 서버는 귀하의 이메일을 한 명 이상의 수신자(포함)에게 전달할 수 있습니다. 웹훅) 귀하의 이메일을 암호화된 IMAP 저장소에 당사와 함께 저장하세요. 아니면 둘다!
더 자세히 알고 싶으십니까? 읽다 이메일 전달을 설정하는 방법, 메일 교환 서비스 작동 방식, 또는 보기 우리 가이드.
-
우리의 보안 이메일 저장소 설계는 두 가지 방식으로 작동하여 귀하의 사서함을 암호화하고 귀하만 액세스할 수 있도록 합니다.
-
보낸 사람으로부터 새 메일이 수신되면 당사의 메일 교환 서버는 귀하를 위해 개별적이고 임시이며 암호화된 사서함에 기록합니다.
sequenceDiagram autonumber actor Sender Sender->>MX: Inbound message received for your alias (e.g. you@yourdomain.com). MX->>SQLite: Message is stored in a temporary mailbox. Note over MX,SQLite: Forwards to other recipients and webhooks configured. MX->>Sender: Success!
-
이메일 클라이언트로 IMAP 서버에 연결하면 비밀번호가 메모리 내에서 암호화되어 사서함을 읽고 쓰는 데 사용됩니다. 귀하의 사서함은 이 비밀번호로만 읽고 쓸 수 있습니다. 이 비밀번호를 아는 사람은 본인뿐이므로 주의하세요. 오직 너 당신이 그것에 접근할 때 당신의 편지함에 읽고 쓸 수 있습니다. 다음에 이메일 클라이언트가 메일이나 동기화를 폴링하려고 시도하면 새 메시지가 이 임시 편지함에서 전송되고 제공된 비밀번호를 사용하여 실제 편지함 파일에 저장됩니다. 이 임시 사서함은 이후에 제거 및 삭제되므로 비밀번호로 보호된 사서함에만 메시지가 보관됩니다.
-
IMAP에 연결되어 있는 경우(예: Apple Mail 또는 Thunderbird와 같은 이메일 클라이언트 사용) 임시 디스크 저장소에 쓸 필요가 없습니다. 대신 메모리 내 암호화된 IMAP 비밀번호를 가져와 사용합니다. 실시간으로 메시지가 사용자에게 전달되려고 할 때 우리는 모든 IMAP 서버에 WebSocket 요청을 보내 활성 세션이 있는지 묻고(가져오기 부분) 이를 전달합니다. 암호화된 메모리 내 비밀번호 – 임시 메일함에 쓸 필요가 없으므로 암호화된 비밀번호를 사용하여 실제 암호화된 메일함에 쓸 수 있습니다.
sequenceDiagram autonumber actor You You->>IMAP: You connect to IMAP server using an email client. IMAP->>SQLite: Transfer message from temporary mailbox to your alias' mailbox. Note over IMAP,SQLite: Your alias' mailbox is only available in-memory using IMAP password. SQLite->>IMAP: Retrieves messages as requested by email client. IMAP->>You: Success!
-
-
암호화된 사서함 백업 매일 만들어집니다. 언제든지 새 백업을 요청하거나 다음에서 최신 백업을 다운로드할 수도 있습니다. 내 계정 도메인 별칭. 다른 이메일 서비스로 전환하기로 결정한 경우 언제든지 사서함과 백업을 쉽게 마이그레이션, 다운로드, 내보내기 및 제거할 수 있습니다.
기술
데이터베이스
우리는 가능한 다른 데이터베이스 스토리지 레이어를 탐색했지만 SQLite만큼 우리의 요구 사항을 충족하는 레이어는 없었습니다.
데이터 베이스 | 미사용 암호화 | 샌드박스 처리됨 사서함 | 특허 | 어디에서나 사용됨 |
---|---|---|---|---|
SQLite ⭐ | ✅ 예 SQLite3다중 암호 | ✅ | ✅ 공개 도메인 | ✅ |
몽고DB | ❌ "MongoDB Enterprise에서만 사용 가능" | ❌ 관계형 데이터베이스 | ❌ AGPL과 SSPL-1.0 | ❌ |
rqlite | ❌ 네트워크만 | ❌ 관계형 데이터베이스 | ✅ MIT | ❌ |
dqlite | ❌ 테스트되지 않았으며 아직 지원되지 않습니까? | ❌ 테스트되지 않았으며 아직 지원되지 않습니까? | ✅ LGPL-3.0-only | ❌ |
포스트그레SQL | ✅ 예 | ❌ 관계형 데이터베이스 | ✅ PostgreSQL (비슷하다 BSD 또는 MIT ) | ❌ |
마리아DB | ✅ InnoDB에만 해당 | ❌ 관계형 데이터베이스 | ✅ GPLv2 그리고 BUSL-1.1 | ❌ |
바퀴벌레DB | ❌ 기업 전용 기능 | ❌ 관계형 데이터베이스 | ❌ BUSL-1.1 다른 사람 | ❌ |
여기에는 여러 SQLite 데이터베이스 스토리지 옵션을 비교하는 블로그 게시물 위의 표에서.
보안
우리는 항상 사용합니다 미사용 암호화 (AES-256), 전송 중 암호화 (TLS), HTTPS를 통한 DNS ("DoH") 🍊 사용 귤, 그리고 sqleet (차차20-폴리1305) 사서함 암호화. 또한 우리는 토큰 기반의 2단계 인증(SMS와는 반대로)을 사용합니다. 중간자 공격), 루트 액세스가 비활성화된 순환 SSH 키, 제한된 IP 주소를 통한 서버에 대한 독점 액세스 등이 있습니다.
다음과 같은 경우 사악한 하녀 공격 또는 제3자 공급업체의 불량 직원, 귀하의 사서함은 생성된 비밀번호로만 열 수 있습니다. 안심하십시오. Cloudflare, Digital Ocean 및 Vultr의 SOC 유형 2 불만 사항 서버 제공업체 이외의 타사 공급업체에 의존하지 않습니다.
우리의 목표는 적은 수를 갖는 것입니다 단일 실패 지점 가능한 한.
사서함
tldr; 당사의 IMAP 서버는 각 사서함에 대해 개별적으로 암호화된 SQLite 데이터베이스를 사용합니다.
SQLite는 매우 인기가 있습니다. 내장된 데이터베이스 – 현재 휴대폰과 컴퓨터에서 실행 중 – 거의 모든 주요 기술에서 사용됩니다..
예를 들어 암호화된 서버에는 다음을 위한 SQLite 데이터베이스 사서함이 있습니다. linux@example.com
, info@example.com
, hello@example.com
등등 – 각각 하나씩 .sqlite
데이터베이스 파일. 우리는 이메일 주소로 데이터베이스 파일 이름을 지정하지 않습니다. 대신 BSON ObjectID와 고유한 UUID를 사용하여 사서함이 속한 사람이나 해당 이메일 주소를 공유하지 않습니다(예: 353a03f21e534321f5d6e267.sqlite
).
이러한 각 데이터베이스는 다음을 사용하여 귀하의 비밀번호(귀하만 알고 있음)를 사용하여 자체적으로 암호화됩니다. sqleet (차차20-폴리1305). 이는 귀하의 사서함이 개별적으로 암호화되고 자체 포함되어 있음을 의미합니다. 샌드박스 처리된, 휴대 가능합니다.
우리는 다음과 같이 SQLite를 미세 조정했습니다. PRAGMA:
PRAGMA | 목적 |
---|---|
cipher=chacha20 | ChaCha20-Poly1305 SQLite 데이터베이스 암호화. 참조 better-sqlite3-multiple-ciphers 아래에 프로젝트 더 많은 통찰력을 위해. |
key="****************" | 이는 이메일 클라이언트의 IMAP 연결을 통해 서버에 전달되는 해독된 메모리 내 전용 비밀번호입니다. 각 읽기 및 쓰기 세션마다 새 데이터베이스 인스턴스가 생성되고 닫힙니다(샌드박싱 및 격리를 보장하기 위해). |
journal_model=WAL | 미리 쓰기-로그("WAL") 성능을 향상시키고 동시 읽기 액세스를 허용합니다.. |
busy_timeout=5000 | 쓰기 잠금 오류 방지 다른 쓰기가 진행되는 동안. |
synchronous=NORMAL | 거래의 내구성을 높입니다. 데이터 손상 위험 없이. |
foreign_keys=ON | 외래 키 참조(예: 한 테이블에서 다른 테이블로의 관계)가 시행되도록 합니다. 기본적으로 이는 SQLite에서는 켜져 있지 않습니다., 그러나 유효성 검사 및 데이터 무결성을 위해서는 활성화해야 합니다. |
encoding='UTF-8' | 기본 인코딩 개발자의 정신을 보장하는 데 사용됩니다. |
다른 모든 기본값은 SQLite에서 지정한 대로입니다. 공식 PRAGMA 문서.
동시성
tldr; 우리는 사용
WebSocket
암호화된 SQLite 메일박스에 대한 동시 읽기 및 쓰기를 위해.
읽기
휴대폰의 이메일 클라이언트가 문제를 해결할 수 있습니다. imap.forwardemail.net
Digital Ocean IP 주소 중 하나로 연결되며 귀하의 데스크톱 클라이언트는 다른 IP 주소에서 별도의 IP를 확인할 수 있습니다. 공급자 전부.
귀하의 이메일 클라이언트가 어떤 IMAP 서버에 연결되어 있는지에 관계없이 우리는 100% 정확도로 실시간으로 귀하의 데이터베이스에서 연결을 읽기를 원합니다. 이는 WebSocket을 통해 수행됩니다.
쓰기
데이터베이스에 쓰기는 약간 다릅니다. SQLite는 내장형 데이터베이스이고 사서함은 기본적으로 단일 파일에 있기 때문입니다.
우리는 다음과 같은 옵션을 탐색했습니다. litestream
, rqlite
, 그리고 dqlite
아래 – 그러나 이들 중 어느 것도 우리의 요구 사항을 충족하지 못했습니다.
미리 쓰기 로깅("WAL") 활성화 – 단 하나의 서버("기본")만 해당 작업을 담당하도록 해야 합니다. WAL 동시성 속도를 크게 높이고 하나의 작성자와 여러 명의 판독기를 허용합니다.
기본 서버는 암호화된 메일함을 포함하는 마운트된 볼륨이 있는 데이터 서버에서 실행됩니다. 배포 관점에서 보면 뒤에 있는 모든 개별 IMAP 서버를 고려할 수 있습니다. imap.forwardemail.net
보조 서버("보조")가 됩니다.
우리는 양방향 커뮤니케이션을 실현합니다. 웹소켓:
- 기본 서버는 다음 인스턴스를 사용합니다. 와스'에스
WebSocketServer
섬기는 사람. - 보조 서버는 다음 인스턴스를 사용합니다. 와스'에스
WebSocket
래핑된 클라이언트 약속대로 웹소켓 그리고 다시 연결-websocket. 이 두 래퍼는 다음을 보장합니다.WebSocket
특정 데이터베이스 쓰기에 대한 데이터를 다시 연결하고 보내고 받을 수 있습니다.
백업
tldr; 암호화된 사서함의 백업은 매일 이루어집니다. 또한 언제든지 다음 사이트에서 즉시 새 백업을 요청하거나 최신 백업을 다운로드할 수 있습니다. 내 계정 도메인 별칭.
백업의 경우 간단히 SQLite를 실행합니다. VACUUM INTO
IMAP 명령 처리 중에 매일 명령을 실행합니다. 이는 메모리 내 IMAP 연결에서 암호화된 비밀번호를 활용합니다. 기존 백업이 감지되지 않거나 SHA-256 가장 최근 백업과 비교하여 파일의 해시가 변경되었습니다.
우리는 VACUUM INTO
내장 명령과 반대되는 명령 backup
명령을 실행하는 동안 페이지가 수정되면 backup
명령 작업을 수행한 다음 다시 시작해야 합니다. 그만큼 VACUUM INTO
명령은 스냅샷을 찍습니다. 다음 댓글을 참조하세요. 깃허브 그리고 해커 뉴스 더 많은 통찰력을 위해.
추가적으로 우리는 VACUUM INTO
반대로 backup
, 왜냐하면 backup
명령은 다음까지 짧은 기간 동안 데이터베이스를 암호화되지 않은 상태로 둡니다. rekey
호출됩니다(이 GitHub 참조). 논평 통찰력을 위해).
중등은 초등에게 지시할 것입니다. WebSocket
백업을 실행하기 위한 연결 - 기본은 백업을 수행하라는 명령을 수신하고 이후에 다음을 수행합니다.
- 암호화된 사서함에 연결하세요.
- 쓰기 잠금을 획득합니다.
- 다음을 통해 WAL 체크포인트를 실행하세요.
wal_checkpoint(PASSIVE)
. - 실행
VACUUM INTO
SQLite 명령. - 복사된 파일이 암호화된 비밀번호(보호/더미 방지)로 열 수 있는지 확인하세요.
- 저장을 위해 Cloudflare R2(또는 지정된 경우 자체 공급자)에 업로드하세요.
귀하의 사서함은 암호화되어 있으며 WebSocket 통신을 위한 IP 제한 및 기타 인증 조치가 마련되어 있지만 악의적인 행위가 발생하는 경우 WebSocket 페이로드에 IMAP 비밀번호가 없으면 데이터베이스를 열 수 없으므로 안심하셔도 됩니다. .
현재는 사서함당 하나의 백업만 저장되지만 앞으로는 특정 시점 복구("PITR").
찾다
우리의 IMAP 서버는 다음을 지원합니다. SEARCH
복잡한 쿼리, 정규식 등이 포함된 명령입니다.
빠른 검색 성능은 다음과 같습니다. FTS5 그리고 sqlite-정규식.
우리는 저장 Date
SQLite 메일함의 값은 다음과 같습니다. ISO 8601 문자열을 통해 Date.prototype.toISOString (동일성 비교가 제대로 작동하려면 UTC 시간대를 사용하세요.)
검색어에 포함된 모든 속성에 대한 색인도 저장됩니다.
프로젝트
다음은 소스 코드 및 개발 프로세스에서 사용하는 프로젝트를 간략하게 설명하는 표입니다(알파벳순으로 정렬).
프로젝트 | 목적 |
---|---|
앤서블 | 전체 서버 제품군을 쉽게 유지 관리, 확장 및 관리하기 위한 DevOps 자동화 플랫폼입니다. |
브리 | cron, 날짜, ms 이상 및 인간 친화적인 지원을 제공하는 Node.js 및 JavaScript용 작업 스케줄러입니다. |
선실 | 보안과 개인 정보 보호를 염두에 둔 개발자 친화적인 JavaScript 및 Node.js 로깅 라이브러리입니다. |
허락하다 | MVC 등을 통해 전체 아키텍처와 엔지니어링 설계를 강화하는 Node.js 프레임워크입니다. |
몽고DB | 사서함 외부의 다른 모든 데이터(예: 계정, 설정, 도메인 및 별칭 구성)를 저장하는 데 사용하는 NoSQL 데이터베이스 솔루션입니다. |
몽구스 | 전체 스택에서 사용하는 MongoDB 개체 문서 모델링("ODM")입니다. 우리는 단순히 계속해서 사용할 수 있도록 하는 특별한 도우미를 작성했습니다. SQLite를 사용한 몽구스 🎉 |
노드.js | Node.js는 모든 서버 프로세스를 실행하는 오픈 소스 크로스 플랫폼 JavaScript 런타임 환경입니다. |
메모 메일러 | 이메일 전송, 연결 생성 등을 위한 Node.js 패키지입니다. 우리는 이 프로젝트의 공식 후원자입니다. |
레디스 | 캐싱, 게시/구독 채널 및 HTTPS를 통한 DNS 요청을 위한 인메모리 데이터베이스입니다. |
SQLite3다중 암호 | 전체 데이터베이스 파일을 암호화할 수 있도록 하는 SQLite용 암호화 확장(미리 쓰기 로그("WAL"), 저널, 롤백, …). |
SQLite스튜디오 | 개발 메일함을 테스트하고, 다운로드하고, 보는 데 사용할 수 있는 Visual SQLite 편집기. |
SQLite | 확장 가능하고 독립적이며 빠르고 탄력적인 IMAP 저장소를 위한 내장형 데이터베이스 계층입니다. |
스팸 스캐너 | Node.js 스팸 방지, 이메일 필터링, 피싱 방지 도구(대안) 스팸 암살자 그리고 스팸메일). |
귤 | Node.js를 통한 DNS over HTTPS 요청 및 Redis를 사용한 캐싱 – 이는 글로벌 일관성 등을 보장합니다. |
천둥새 | 우리 개발팀은 이것을 다음과 같이 사용하고 권장합니다. 이메일 전달과 함께 사용할 기본 이메일 클라이언트. |
UTM | 우리 개발팀은 IMAP 및 SMTP 서버와 함께 다양한 이메일 클라이언트를 (병렬로) 테스트하기 위해 iOS 및 macOS용 가상 머신 생성을 사용합니다. |
우분투 | 모든 인프라를 지원하는 최신 오픈 소스 Linux 기반 서버 운영 체제입니다. |
와일드덕 | IMAP 서버 라이브러리 - 해당 참고 사항을 참조하세요. 첨부 파일 중복 제거 그리고 IMAP 프로토콜 지원. |
더 나은-sqlite3-다중 암호 | 프로그래밍 방식으로 SQLite3과 상호 작용하는 Node.js용 빠르고 간단한 API 라이브러리입니다. |
이메일 템플릿 | 사용자 정의 이메일(예: 계정 알림 등)을 생성하고, 미리 보고, 보낼 수 있는 개발자 친화적인 이메일 프레임워크입니다. |
json-sql | Mongo 스타일 구문을 사용하는 SQL 쿼리 빌더입니다. 데이터베이스에 구애받지 않는 접근 방식을 사용하여 전체 스택에 걸쳐 Mongo 스타일로 계속 작성할 수 있으므로 개발 팀의 시간이 절약됩니다. 또한 쿼리 매개변수를 사용하여 SQL 주입 공격을 방지하는 데 도움이 됩니다. |
knex-스키마-검사기 | 기존 데이터베이스 스키마에 대한 정보를 추출하는 SQL 유틸리티입니다. 이를 통해 모든 인덱스, 테이블, 열, 제약 조건 등이 유효하고 유효한지 쉽게 확인할 수 있습니다. 1:1 그들이 어떻게 되어야 하는지. 데이터베이스 스키마가 변경되면 새 열과 인덱스를 추가하는 자동화된 도우미도 작성했습니다(매우 상세한 오류 경고도 포함). |
넥스 | 데이터베이스 마이그레이션 및 스키마 검증에만 사용하는 SQL 쿼리 빌더 knex-schema-inspector . |
만다린 오렌지 | 자동적 인 i18n Markdown을 지원하는 구문 번역 Google 클라우드 번역 API. |
mx-연결 | MX 서버와의 연결을 해결 및 설정하고 오류를 처리하는 Node.js 패키지입니다. |
오후 2시 | 로드 밸런서가 내장된 Node.js 생산 프로세스 관리자(조율이 잘되어있는 성능을 위해). |
smtp 서버 | SMTP 서버 라이브러리 – 메일 교환("MX") 및 아웃바운드 SMTP 서버에 이를 사용합니다. |
Imap테스트 | 벤치마크 및 RFC 사양 IMAP 프로토콜 호환성에 대해 IMAP 서버를 테스트하는 데 유용한 도구입니다. 이 프로젝트는 비둘기장 팀(2002년 7월부터 활성화된 오픈 소스 IMAP 및 POP3 서버). 우리는 이 도구를 사용하여 IMAP 서버를 광범위하게 테스트했습니다. |
우리가 사용하는 다른 프로젝트를 찾을 수 있습니다 GitHub의 소스 코드.
공급자
공급자 | 목적 |
---|---|
클라우드플레어 | DNS 공급자, 상태 확인, 로드 밸런서 및 백업 스토리지를 사용하여 클라우드플레어 R2. |
디지털 오션 | 전용 서버 호스팅, SSD 블록 스토리지 및 관리형 데이터베이스. |
불트르 | 전용 서버 호스팅 및 SSD 블록 스토리지. |
생각
원칙
이메일 전달은 다음 원칙에 따라 설계되었습니다.
- 항상 개발자 친화적이고 보안 및 개인 정보 보호에 중점을 두고 투명하게 행동하세요.
- 준수 MVC, 유닉스, KISS, DRY, YAGNI, 12가지 요소, 오캄의 면도날, 그리고 개밥
- 스크랩, 부트스트랩 및 라면수익이 나는 개발자
실험
tldr; 궁극적으로 S3 호환 객체 스토리지 및/또는 가상 테이블을 사용하는 것은 성능상의 이유로 기술적으로 가능하지 않으며 메모리 제한으로 인해 오류가 발생하기 쉽습니다.
우리는 위에서 논의한 최종 SQLite 솔루션에 이르기까지 몇 가지 실험을 수행했습니다.
이 중 하나는 rc클론 S3 호환 스토리지 계층과 함께 SQLite.
그 실험을 통해 우리는 rclone, SQLite 및 VFS 용법:
- 활성화하면
--vfs-cache-mode writes
rclone으로 플래그를 지정하면 읽기는 괜찮지만 쓰기는 캐시됩니다.- 여러 IMAP 서버가 전역적으로 분산되어 있는 경우 단일 작성자와 여러 리스너(예: 게시/구독 접근 방식)가 없으면 캐시가 서버 전체에서 꺼집니다.
- 이는 엄청나게 복잡하며 이와 같은 복잡성을 추가하면 단일 실패 지점이 더 많아지게 됩니다.
- S3 호환 스토리지 공급자는 부분적인 파일 변경을 지원하지 않습니다.
.sqlite
파일을 삭제하면 데이터베이스가 완전히 변경되고 다시 업로드됩니다. - 다음과 같은 다른 솔루션
rsync
존재하지만 미리 쓰기 로그("WAL") 지원 – 그래서 우리는 Litestream을 검토하게 되었습니다. 다행히도 우리의 암호화 사용은 이미 WAL 파일을 제공하므로 이를 위해 Litestream에 의존할 필요가 없습니다. 그러나 우리는 프로덕션 용도로 Litestream에 대해 아직 확신이 없었으며 이에 대한 몇 가지 참고 사항이 아래에 있습니다. - 이 옵션을 사용하면
--vfs-cache-mode writes
(그만큼 오직 SQLite를 사용하는 방법rclone
쓰기의 경우)는 전체 데이터베이스를 메모리 내에서 처음부터 복사하려고 시도합니다. 10GB 사서함 하나를 처리하는 것은 괜찮습니다. 그러나 저장소가 지나치게 높은 여러 사서함을 처리하면 IMAP 서버가 메모리 제한에 직면하게 되고ENOMEM
오류, 분할 오류 및 데이터 손상.
- SQLite를 사용하려고 하면 가상 테이블 (예를 들어 s3db) S3 호환 스토리지 계층에 데이터를 저장하려면 몇 가지 추가 문제에 직면하게 됩니다.
- S3 API 엔드포인트가 HTTP에 도달해야 하므로 읽기 및 쓰기 속도가 매우 느려집니다.
GET
,PUT
,HEAD
, 그리고POST
행동 양식. - 개발 테스트에 따르면 광섬유 인터넷에서 50만~1백만 개 이상의 레코드를 초과하는 것은 S3 호환 공급자에 대한 쓰기 및 읽기 처리량으로 인해 여전히 제한되는 것으로 나타났습니다. 예를 들어, 우리 개발자들은 다음을 실행했습니다.
for
순차 SQL을 모두 수행하는 루프INSERT
명령문과 대량의 데이터를 대량으로 작성한 명령문. 두 경우 모두 성능이 엄청나게 느렸습니다. - 가상 테이블 인덱스를 가질 수 없습니다,
ALTER TABLE
진술 및 다른 한계 – 데이터 양에 따라 1~2분 이상 지연이 발생할 수 있습니다. - 객체는 암호화되지 않은 상태로 저장되었으며 기본 암호화 지원은 쉽게 제공되지 않습니다.
- S3 API 엔드포인트가 HTTP에 도달해야 하므로 읽기 및 쓰기 속도가 매우 느려집니다.
- 우리는 또한 다음을 사용하여 탐색했습니다. sqlite-s3vfs 이는 개념적으로나 기술적으로 이전 글머리 기호와 유사합니다(따라서 동일한 문제가 있음). 가능성은 사용자 정의를 사용하는 것입니다
sqlite3
다음과 같은 암호화로 래핑된 빌드 wxSQLite3 (현재 위의 솔루션에서 사용하고 있음)을 통해 설정 파일 편집. - 또 다른 잠재적 접근 방식은 멀티플렉스 확장그러나 이는 32GB로 제한되며 복잡한 구축 및 개발 문제가 필요합니다.
ALTER TABLE
문이 필요합니다(따라서 가상 테이블 사용이 완전히 배제됩니다). 우리는 필요하다ALTER TABLE
우리의 후크를 위한 진술knex-schema-inspector
제대로 작동하려면 데이터가 손상되지 않고 검색된 행이 당사 규정에 따라 유효한 문서로 변환될 수 있습니다.mongoose
스키마 정의(제약조건, 변수 유형 및 임의 데이터 유효성 검사 포함)- 오픈 소스 커뮤니티의 SQLite와 관련된 거의 모든 S3 호환 프로젝트는 Python으로 되어 있습니다(스택의 100%에 사용하는 JavaScript는 아닙니다).
- 다음과 같은 압축 라이브러리 sqlite-zstd (보다 코멘트) 유망해 보이지만, 아직 프로덕션 용도로 사용할 준비가 되지 않았을 수 있습니다.. 대신 다음과 같은 데이터 유형에 대한 애플리케이션 측 압축
String
,Object
,Map
,Array
,Set
, 그리고Buffer
더 깔끔하고 쉬운 접근 방식이 될 것입니다(그리고 마이그레이션도 더 쉽습니다.Boolean
플래그 또는 열 - 또는 심지어 사용PRAGMA
user_version=1
압축을 위해 또는user_version=0
데이터베이스 메타데이터로 압축하지 않음)- 다행스럽게도 우리는 이미 IMAP 서버 저장소에 첨부 파일 중복 제거 기능을 구현했습니다. 따라서 동일한 첨부 파일이 있는 모든 메시지는 첨부 파일의 복사본을 유지하지 않습니다. 대신 단일 첨부 파일이 사서함의 여러 메시지와 스레드에 대해 저장됩니다(외부 메시지 포함). 나중에 참조가 사용됩니다).
- SQLite 복제 및 백업 솔루션인 Litestream 프로젝트는 매우 유망하며 앞으로도 이를 사용할 가능성이 높습니다.
- 저자의 신용을 떨어뜨리려는 것이 아닙니다. 우리는 현재 10년 넘게 그들의 작업과 오픈 소스에 대한 기여를 사랑하고 있기 때문입니다. 그러나 실제 사용에서 볼 때 머리가 많이 아플 수도 있다 그리고 사용으로 인한 잠재적인 데이터 손실.
- 백업 복원은 원활하고 간단해야 합니다. MongoDB와 같은 솔루션을 사용하여
mongodump
그리고mongoexport
지루할 뿐만 아니라 시간 집약적이며 구성이 복잡합니다.- SQLite 데이터베이스를 사용하면 간단해집니다(단일 파일임).
- 우리는 사용자가 언제든지 사서함을 가지고 나갈 수 있는 솔루션을 디자인하고 싶었습니다.
- 간단한 Node.js 명령을 사용하여
fs.unlink('mailbox.sqlite'))
그리고 디스크 저장소에서 영구적으로 지워집니다. - 마찬가지로 S3 호환 API를 HTTP와 함께 사용할 수 있습니다.
DELETE
사용자를 위해 스냅샷과 백업을 쉽게 제거합니다.
- 간단한 Node.js 명령을 사용하여
- SQLite는 가장 간단하고 빠르며 비용 효율적인 솔루션이었습니다.
대안의 부족
우리가 아는 바로는 다른 어떤 이메일 서비스도 이런 방식으로 설계되지 않았으며 오픈 소스도 아닙니다.
우리 이게 원인일지도 모른다고 생각해 기존 기술을 사용하여 생산 중인 기존 이메일 서비스에 스파게티 코드 🍝.
기존 이메일 서비스 제공업체의 전부는 아니더라도 대부분은 비공개 소스이거나 오픈 소스로 광고합니다. 그러나 실제로는 프런트엔드만 오픈 소스입니다.
이메일에서 가장 민감한 부분 (실제 저장소/IMAP/SMTP 상호 작용) 모든 작업은 백엔드(서버)에서 수행됩니다. ~ 아니다 프런트엔드(클라이언트)에서.
이메일 전달을 사용해 보세요
오늘 등록하세요 https://forwardemail.net! 🚀