Kuantum Dirençli E-posta: E-postanızı Güvende Tutmak İçin Şifrelenmiş SQLite Posta Kutularını Nasıl Kullanıyoruz
Önsöz
Important
E-posta servisimiz %100 açık kaynak ve güvenli, şifrelenmiş SQLite posta kutuları sayesinde gizlilik odaklıdır.
IMAP desteğini başlatana kadar kalıcı veri depolama ihtiyaçlarımız için MongoDB kullanıyorduk.
Bu teknoloji harika ve hâlâ kullanıyoruz – ancak MongoDB ile verilerin şifrelenmiş olarak saklanabilmesi için Digital Ocean veya Mongo Atlas gibi MongoDB Enterprise sunan bir sağlayıcı kullanmanız gerekiyor – ya da kurumsal lisans için ödeme yapmanız (ve ardından satış ekibiyle gecikmelerle uğraşmanız) gerekiyor.
Forward Email ekibimiz, IMAP posta kutuları için geliştirici dostu, ölçeklenebilir, güvenilir ve şifrelenmiş bir depolama çözümüne ihtiyaç duyuyordu. Açık kaynak geliştiriciler olarak, şifrelenmiş veri saklama özelliği için lisans ücreti ödemeniz gereken bir teknoloji kullanmak prensiplerimize aykırıydı – bu yüzden deneyler yaptık, araştırdık ve bu ihtiyaçları karşılamak için sıfırdan yeni bir çözüm geliştirdik.
Posta kutularınızı depolamak için paylaşılan bir veritabanı kullanmak yerine, posta kutularınızı şifrenizle (sadece sizin bildiğiniz) ayrı ayrı saklıyor ve şifreliyoruz. E-posta servisimiz o kadar güvenlidir ki, şifrenizi unutursanız posta kutunuzu kaybedersiniz (ve çevrimdışı yedeklerle kurtarmanız veya baştan başlamanız gerekir).
Aşağıda e-posta servis sağlayıcı karşılaştırması, servisimizin nasıl çalıştığı, teknoloji yığınımız ve daha fazlası ile derinlemesine incelemeye devam edin.
E-posta servis sağlayıcı karşılaştırması
Bireysel olarak şifrelenmiş SQLite posta kutuları depolayan, sınırsız alan adı, takma ad ve kullanıcı sunan, ayrıca giden SMTP, IMAP ve POP3 desteği olan tek %100 açık kaynak ve gizlilik odaklı e-posta servis sağlayıcısıyız:
Diğer e-posta sağlayıcılarının aksine, Forward Email ile alan adı veya takma ad başına depolama için ödeme yapmanız gerekmez. Depolama tüm hesabınızda paylaşılır – yani birden fazla özel alan adınız ve her birinde birden fazla takma adınız varsa, biz sizin için mükemmel çözümdür. İsterseniz alan adı veya takma ad bazında depolama sınırları koyabilirsiniz.
E-posta Servis Karşılaştırmasını Oku
Nasıl çalışır
-
Apple Mail, Thunderbird, Gmail veya Outlook gibi e-posta istemcinizi kullanarak, kullanıcı adınız ve şifrenizle güvenli IMAP sunucularımıza bağlanırsınız:
- Kullanıcı adınız,
hello@example.comgibi alan adınızla birlikte tam takma adınızdır. - Şifreniz rastgele oluşturulur ve Şifre Oluştur butonuna tıkladığınızda sadece 30 saniye boyunca size gösterilir. Bu buton Hesabım Alan Adları Takma Adlar altında bulunur.
- Kullanıcı adınız,
-
Bağlandıktan sonra, e-posta istemciniz posta kutunuzu senkronize tutmak için IMAP protokol komutları gönderecektir. Bu, taslak e-postaların yazılması ve saklanması ile yapabileceğiniz diğer işlemleri (örneğin bir e-postayı Önemli olarak etiketlemek veya bir e-postayı Spam/İstenmeyen Posta olarak işaretlemek) içerir.
-
Posta değişim sunucuları (genellikle "MX" sunucuları olarak bilinir) yeni gelen e-postaları alır ve posta kutunuza kaydeder. Bu olduğunda, e-posta istemciniz bilgilendirilir ve posta kutunuzu senkronize eder. Posta değişim sunucularımız e-postanızı bir veya daha fazla alıcıya (dahil olmak üzere webhooklar) iletebilir, e-postanızı bizimle şifrelenmiş IMAP depolamanızda saklayabilir, veya her ikisini de yapabilir!
Tip
Daha fazlasını öğrenmek ister misiniz? E-posta yönlendirmeyi nasıl kuracağınızı, posta değişim hizmetimizin nasıl çalıştığını okuyun veya rehberlerimize göz atın.
-
Sahne arkasında, güvenli e-posta depolama tasarımımız posta kutularınızı şifreli tutmak ve yalnızca sizin erişebilmeniz için iki şekilde çalışır:
-
Gönderen tarafından size yeni posta alındığında, posta değişim sunucularımız sizin için bireysel, geçici ve şifrelenmiş bir posta kutusuna yazar.
-
E-posta istemcinizle IMAP sunucumuza bağlandığınızda, şifreniz bellekte şifrelenir ve posta kutunuzu okumak ve yazmak için kullanılır. Posta kutunuz yalnızca bu şifre ile okunabilir ve yazılabilir. Bu şifreye yalnızca sizin sahip olduğunuzu unutmayın, bu nedenle posta kutunuza erişirken sadece siz okuyabilir ve yazabilirsiniz. E-posta istemciniz bir sonraki sefer posta kontrolü veya senkronizasyon yapmaya çalıştığında, yeni mesajlar bu geçici posta kutusundan alınır ve sağladığınız şifre kullanılarak gerçek posta kutusu dosyanıza kaydedilir. Bu geçici posta kutusunun daha sonra temizlenip silindiğini ve böylece yalnızca şifre korumalı posta kutunuzun mesajları içerdiğini unutmayın.
-
Eğer IMAP'e bağlıysanız (örneğin Apple Mail veya Thunderbird gibi bir e-posta istemcisi kullanıyorsanız), geçici disk depolamaya yazmamıza gerek yoktur. Bunun yerine, bellekte şifrelenmiş IMAP şifreniz alınır ve kullanılır. Gerçek zamanlı olarak, size bir mesaj teslim edilmeye çalışıldığında, tüm IMAP sunucularına aktif bir oturumunuz olup olmadığını soran bir WebSocket isteği göndeririz (bu alma kısmıdır) ve ardından şifrelenmiş bellekteki şifreyi iletiriz – böylece geçici posta kutusuna yazmamıza gerek kalmaz, şifrelenmiş şifrenizle gerçek şifrelenmiş posta kutunuza yazabiliriz.
-
-
Şifrelenmiş posta kutularınızın yedekleri günlük olarak alınır. Ayrıca istediğiniz zaman yeni bir yedek talep edebilir veya en son yedeği Hesabım Alan Adları Takma Adlar bölümünden indirebilirsiniz. Başka bir e-posta hizmetine geçmeye karar verirseniz, posta kutularınızı ve yedeklerinizi istediğiniz zaman kolayca taşıyabilir, indirebilir, dışa aktarabilir ve temizleyebilirsiniz.
Teknolojiler
Veritabanları
Başka olası veritabanı depolama katmanlarını araştırdık, ancak hiçbiri SQLite kadar gereksinimlerimizi karşılamadı:
| Veritabanı | Dinlenme Halinde Şifreleme | Sandboxed Posta Kutuları | Lisans | Her Yerde Kullanılıyor |
|---|---|---|---|---|
| SQLite ⭐ | ✅ SQLite3MultipleCiphers ile Evet | ✅ | ✅ Kamu Malı | ✅ |
| MongoDB | ❌ "Sadece MongoDB Enterprise'da Mevcut" | ❌ İlişkisel veritabanı | ❌ AGPL ve SSPL-1.0 |
❌ |
| rqlite | ❌ Sadece Ağ | ❌ İlişkisel veritabanı | ✅ MIT |
❌ |
| dqlite | ❌ Test edilmemiş ve henüz desteklenmiyor? | ❌ Test edilmemiş ve henüz desteklenmiyor? | ✅ LGPL-3.0-only |
❌ |
| PostgreSQL | ✅ Evet | ❌ İlişkisel veritabanı | ✅ PostgreSQL ( BSD veya MIT benzeri) |
❌ |
| MariaDB | ✅ Sadece InnoDB için | ❌ İlişkisel veritabanı | ✅ GPLv2 ve BUSL-1.1 |
❌ |
| CockroachDB | ❌ Sadece Enterprise özelliği | ❌ İlişkisel veritabanı | ❌ BUSL-1.1 ve diğerleri |
❌ |
Yukarıdaki tabloda birkaç SQLite veritabanı depolama seçeneğini karşılaştıran bir blog yazısı bulunmaktadır.
Güvenlik
Her zaman dinlenme halindeki şifreleme (AES-256), iletim halindeki şifreleme (TLS), 🍊 Tangerine kullanarak HTTPS üzerinden DNS ("DoH") ve posta kutularında sqleet (ChaCha20-Poly1305) şifrelemesi kullanıyoruz. Ayrıca, SMS'in araya girme saldırılarına açık olması nedeniyle token tabanlı iki faktörlü kimlik doğrulama, root erişimi devre dışı bırakılmış dönen SSH anahtarları, kısıtlı IP adresleri üzerinden sunuculara özel erişim ve daha fazlasını kullanıyoruz. Bir kötü hizmetçi saldırısı veya üçüncü taraf bir satıcıdan kötü niyetli bir çalışan durumunda, posta kutunuz yalnızca sizin oluşturduğunuz şifre ile açılabilir. İçiniz rahat olsun, Cloudflare, DataPacket, Digital Ocean, GitHub ve Vultr gibi SOC Tip 2 uyumlu sunucu sağlayıcılarımız dışında herhangi bir üçüncü taraf satıcıya güvenmiyoruz.
Amacımız mümkün olduğunca az tek hata noktası olmaktır.
Posta Kutuları
özet; IMAP sunucularımız her posta kutunuz için ayrı ayrı şifrelenmiş SQLite veritabanları kullanır.
SQLite son derece popüler bir gömülü veritabanıdır – şu anda telefonunuzda ve bilgisayarınızda çalışmaktadır – ve neredeyse tüm büyük teknolojiler tarafından kullanılmaktadır.
Örneğin, şifrelenmiş sunucularımızda linux@example.com, info@example.com, hello@example.com gibi her biri için bir SQLite veritabanı posta kutusu vardır – her biri .sqlite veritabanı dosyası olarak. Veritabanı dosyalarını e-posta adresi ile isimlendirmiyoruz – bunun yerine posta kutusunun kime ait olduğunu veya hangi e-posta adresine bağlı olduğunu paylaşmayan BSON ObjectID ve benzersiz UUID'ler kullanıyoruz (örneğin 353a03f21e534321f5d6e267.sqlite).
Bu veritabanlarının her biri, yalnızca sizin sahip olduğunuz şifreniz kullanılarak sqleet (ChaCha20-Poly1305) ile şifrelenmiştir. Bu, posta kutularınızın ayrı ayrı şifrelendiği, kendi içinde bağımsız, sandboxlanmış ve taşınabilir olduğu anlamına gelir.
SQLite'ı aşağıdaki PRAGMA ile ince ayar yaptık:
PRAGMA |
Amaç |
|---|---|
cipher=chacha20 |
ChaCha20-Poly1305 SQLite veritabanı şifrelemesi. Daha fazla bilgi için Projeler altında better-sqlite3-multiple-ciphers referansına bakınız. |
key="****************" |
Bu, e-posta istemcinizin IMAP bağlantısı aracılığıyla sunucumuza iletilen, yalnızca bellekte çözülen şifrenizdir. Her okuma ve yazma oturumu için yeni veritabanı örnekleri oluşturulur ve kapatılır (sandboxlama ve izolasyonu sağlamak için). |
journal_mode=WAL |
Yazmadan önce günlük ("WAL") performansı artırır ve eşzamanlı okuma erişimine izin verir. |
busy_timeout=5000 |
Yazma kilidi hatalarını diğer yazmalar devam ederken önler. |
synchronous=NORMAL |
İşlemlerin dayanıklılığını veri bozulması riski olmadan artırır. |
foreign_keys=ON |
Yabancı anahtar referanslarının (örneğin bir tablodan diğerine ilişki) uygulanmasını sağlar. SQLite'da varsayılan olarak kapalıdır, ancak doğrulama ve veri bütünlüğü için etkinleştirilmelidir. |
encoding='UTF-8' |
Geliştirici sağduyusunu sağlamak için kullanılacak varsayılan kodlama. |
Diğer tüm varsayılanlar, resmi PRAGMA dokümantasyonunda belirtildiği gibi SQLite'tandır.
Eşzamanlılık
kısaca; Şifrelenmiş SQLite posta kutularınıza eşzamanlı okuma ve yazma işlemleri için
WebSocketkullanıyoruz.
Okumalar
Telefonunuzdaki e-posta istemcisi imap.forwardemail.net adresini Digital Ocean IP adreslerimizden birine çözümleyebilir – ve masaüstü istemciniz tamamen farklı bir sağlayıcıdan ayrı bir IP adresi çözümleyebilir.
E-posta istemcinizin hangi IMAP sunucusuna bağlandığına bakılmaksızın, bağlantının veritabanınızı gerçek zamanlı ve %100 doğrulukla okumasını istiyoruz. Bu, WebSocket'ler aracılığıyla yapılır.
Yazmalar
Veritabanınıza yazmak biraz farklıdır – çünkü SQLite gömülü bir veritabanıdır ve posta kutunuz varsayılan olarak tek bir dosyada bulunur.
Aşağıda litestream, rqlite ve dqlite gibi seçenekleri araştırdık – ancak hiçbiri gereksinimlerimizi karşılamadı.
Write-ahead-logging ("WAL") etkinleştirilmiş yazmaları gerçekleştirmek için – yalnızca bir sunucunun ("Birincil") bu işlemi yapmasından emin olmamız gerekir. WAL eşzamanlılığı büyük ölçüde hızlandırır ve bir yazıcı ile birden fazla okuyucuya izin verir.
Birincil, şifrelenmiş posta kutularını içeren bağlanmış hacimlere sahip veri sunucularında çalışır. Dağıtım açısından, imap.forwardemail.net arkasındaki tüm bireysel IMAP sunucularını ikincil sunucular ("İkincil") olarak düşünebilirsiniz.
İki yönlü iletişimi WebSocket'ler ile sağlıyoruz:
- Birincil sunucular, ws'nin
WebSocketServersunucu örneğini kullanır. - İkincil sunucular, ws'nin
WebSocketistemci örneğini kullanır ve bu istemci websocket-as-promised ve reconnecting-websocket ile sarılır. Bu iki sarmalayıcı,WebSocket'in yeniden bağlanmasını ve belirli veritabanı yazmaları için veri gönderip almasını sağlar.
Yedekler
kısaca; Şifrelenmiş posta kutularınızın yedekleri günlük olarak alınır. Ayrıca istediğiniz zaman Hesabım Alan Adları Takma Adlar sayfasından yeni bir yedek talep edebilir veya en son yedeği indirebilirsiniz.
Yedekler için, IMAP komut işleme sırasında her gün SQLite VACUUM INTO komutunu çalıştırıyoruz; bu komut, bellekteki IMAP bağlantısından şifrelenmiş parolanızı kullanır. Yedekler, mevcut bir yedek algılanmazsa veya dosyanın SHA-256 karması en son yedekle karşılaştırıldığında değişmişse saklanır.
backup komutu yerine VACUUM INTO komutunu kullanmamızın nedeni, backup komutu sırasında bir sayfa değiştirilirse işlemin baştan başlaması gerekmesidir. VACUUM INTO komutu ise bir anlık görüntü alır. Daha fazla bilgi için bu GitHub ve Hacker News yorumlarına bakabilirsiniz.
Ayrıca backup komutu, rekey çağrılana kadar veritabanını kısa bir süre şifresiz bırakacağından VACUUM INTO komutunu tercih ediyoruz (detaylar için bu GitHub yorumu incelenebilir).
İkincil, Birincil'e WebSocket bağlantısı üzerinden yedekleme komutunu verir – Birincil bu komutu alır ve ardından:
- Şifrelenmiş posta kutunuza bağlanır.
- Yazma kilidi alır.
wal_checkpoint(PASSIVE)ile WAL kontrol noktası çalıştırır.VACUUM INTOSQLite komutunu çalıştırır.- Kopyalanan dosyanın şifrelenmiş parola ile açılabildiğinden emin olur (güvenlik/koruma).
- Dosyayı depolama için Cloudflare R2'ye (veya belirtilmişse kendi sağlayıcınıza) yükler.
Posta kutularınızın şifreli olduğunu unutmayın – ve WebSocket iletişimi için IP kısıtlamaları ve diğer kimlik doğrulama önlemleri uygulamış olsak da – kötü niyetli bir durumda, WebSocket yükü IMAP şifrenizi içermediği sürece veritabanınızı açamaz.
Şu anda her posta kutusu için yalnızca bir yedek saklanmaktadır, ancak gelecekte nokta-zaman-kurtarma ("PITR") sunabiliriz.
Arama
IMAP sunucularımız karmaşık sorgular, düzenli ifadeler ve daha fazlasını destekleyen SEARCH komutunu destekler.
Hızlı arama performansı, FTS5 ve sqlite-regex sayesinde mümkündür.
Date değerlerini SQLite posta kutularında ISO 8601 dizeleri olarak saklıyoruz; bu, Date.prototype.toISOString (UTC zaman dilimi ile, eşitlik karşılaştırmalarının doğru çalışması için) kullanılarak yapılır.
Arama sorgularında yer alan tüm özellikler için dizinler de saklanır.
Projeler
Kaynak kodumuzda ve geliştirme sürecimizde kullandığımız projeleri (alfabetik olarak sıralanmış) gösteren tablo:
| Proje | Amaç |
|---|---|
| Ansible | Tüm sunucu filomuzu kolayca yönetmek, ölçeklendirmek ve sürdürmek için DevOps otomasyon platformu. |
| Bree | Node.js ve JavaScript için cron, tarihler, ms, later ve insan dostu destekle iş zamanlayıcı. |
| Cabin | Güvenlik ve gizlilik odaklı geliştirici dostu JavaScript ve Node.js günlükleme kütüphanesi. |
| Lad | MVC ve daha fazlası ile tüm mimari ve mühendislik tasarımımızı güçlendiren Node.js çerçevesi. |
| MongoDB | Posta kutuları dışındaki tüm diğer verileri (ör. hesap, ayarlar, alan adları ve takma ad yapılandırmaları) saklamak için kullandığımız NoSQL veritabanı çözümü. |
| Mongoose | Tüm yığınımızda kullandığımız MongoDB nesne belge modelleme ("ODM"). Mongoose'u SQLite ile kullanmaya devam etmemizi sağlayan özel yardımcılar yazdık 🎉 |
| Node.js | Tüm sunucu süreçlerimizi çalıştıran açık kaynak, çapraz platform JavaScript çalışma zamanı ortamı. |
| Nodemailer | E-posta gönderme, bağlantılar oluşturma ve daha fazlası için Node.js paketi. Bu projenin resmi sponsoru biziz. |
| Redis | Önbellekleme, yayın/abonelik kanalları ve DNS üzerinden HTTPS istekleri için bellek içi veritabanı. |
| SQLite3MultipleCiphers | Tüm veritabanı dosyalarının (yazma öncesi günlük ("WAL"), günlük, geri alma vb. dahil) şifrelenmesine izin veren SQLite şifreleme eklentisi. |
| SQLiteStudio | Geliştirme posta kutularını test etmek, indirmek ve görüntülemek için kullanabileceğiniz görsel SQLite düzenleyici. |
| SQLite | Ölçeklenebilir, kendi kendine yeten, hızlı ve dayanıklı IMAP depolama için gömülü veritabanı katmanı. |
| Spam Scanner | Node.js anti-spam, e-posta filtreleme ve kimlik avı önleme aracı (bizim Spam Assassin ve rspamd alternatifimiz). |
| Tangerine | Node.js ile DNS üzerinden HTTPS istekleri ve Redis kullanarak önbellekleme – küresel tutarlılık ve çok daha fazlasını sağlar. |
| Thunderbird | Geliştirme ekibimiz tarafından kullanılan ve Forward Email ile kullanılması önerilen tercih edilen e-posta istemcisi. |
| UTM | Geliştirme ekibimiz, IMAP ve SMTP sunucularımızla farklı e-posta istemcilerini (paralel olarak) test etmek için iOS ve macOS üzerinde sanal makineler oluşturmak için bunu kullanır. |
| Ubuntu | Tüm altyapımızı güçlendiren modern açık kaynak Linux tabanlı sunucu işletim sistemi. |
| WildDuck | IMAP sunucu kütüphanesi – ek açıklamalarını ve IMAP protokol desteğini inceleyin. |
| better-sqlite3-multiple-ciphers | SQLite3 ile programatik olarak etkileşim için Node.js'e hızlı ve basit API kütüphanesi. |
| email-templates | Geliştirici dostu e-posta çerçevesi; özel e-postalar (ör. hesap bildirimleri ve daha fazlası) oluşturmak, önizlemek ve göndermek için. |
| json-sql-enhanced | Mongo tarzı sözdizimi kullanan SQL sorgu oluşturucu. Bu, geliştirme ekibimizin tüm yığın boyunca Mongo tarzında yazmaya devam etmesini sağlar ve veritabanı bağımsız bir yaklaşım sunar. Ayrıca sorgu parametreleri kullanarak SQL enjeksiyon saldırılarını önlemeye yardımcı olur. |
| knex-schema-inspector | Mevcut veritabanı şeması hakkında bilgi çıkarmak için SQL aracı. Bu, tüm dizinlerin, tabloların, sütunların, kısıtlamaların ve daha fazlasının geçerli ve olması gerektiği gibi 1:1 olduğunu kolayca doğrulamamızı sağlar. Veritabanı şemalarında değişiklik yapılırsa yeni sütunlar ve dizinler eklemek için otomatik yardımcılar bile yazdık (çok ayrıntılı hata uyarılarıyla). |
| knex | Yalnızca veritabanı geçişleri ve knex-schema-inspector ile şema doğrulama için kullandığımız SQL sorgu oluşturucu. |
| mandarin | Markdown desteği ile otomatik i18n ifade çevirisi için Google Cloud Translation API kullanımı. |
| mx-connect | MX sunucularıyla bağlantı kurmak ve hataları yönetmek için Node.js paketi. |
| pm2 | Yerleşik yük dengeleyici ile Node.js üretim süreç yöneticisi (performans için ince ayarlı). |
| smtp-server | SMTP sunucu kütüphanesi – posta değişimi ("MX") ve giden SMTP sunucularımız için kullanıyoruz. |
| ImapTest | IMAP sunucularını kıyaslamalar ve RFC spesifikasyonu IMAP protokol uyumluluğu açısından test etmek için faydalı araç. Bu proje, Dovecot ekibi tarafından oluşturuldu (Temmuz 2002'den beri aktif açık kaynak IMAP ve POP3 sunucusu). IMAP sunucumuzu bu araçla kapsamlı şekilde test ettik. |
Diğer kullandığımız projeleri GitHub üzerindeki kaynak kodumuzda bulabilirsiniz.
Sağlayıcılar
| Sağlayıcı | Amaç |
|---|---|
| Cloudflare | DNS sağlayıcısı, sağlık kontrolleri, yük dengeleyiciler ve Cloudflare R2 kullanarak yedek depolama. |
| GitHub | Kaynak kodu barındırma, CI/CD ve proje yönetimi. |
| Digital Ocean | Özel sunucu barındırma ve yönetilen veritabanları. |
| Vultr | Özel sunucu barındırma. |
| DataPacket | Özel sunucu barındırma. |
Düşünceler
İlkeler
Forward Email şu ilkeler doğrultusunda tasarlanmıştır:
- Her zaman geliştirici dostu, güvenlik ve gizlilik odaklı ve şeffaf olmak.
- MVC, Unix, KISS, DRY, YAGNI, Twelve Factor, Occam's razor ve dogfooding prensiplerine bağlı kalmak.
- Mütevazı, kendi kendine yeten ve ramen-kârlı geliştiriciyi hedeflemek.
Deneyler
kısaca; Sonuç olarak S3 uyumlu nesne depolama ve/veya Sanal Tabloların performans nedenleriyle teknik olarak uygulanabilir olmadığı ve bellek sınırlamaları nedeniyle hata yapmaya eğilimli olduğu görülmüştür.
Yukarıda tartışıldığı gibi nihai SQLite çözümümüze ulaşana kadar birkaç deney yaptık.
Bunlardan biri, rclone ve SQLite'ı S3 uyumlu bir depolama katmanı ile birlikte kullanmayı denemekti.
Bu deney, rclone, SQLite ve VFS kullanımıyla ilgili kenar durumları daha iyi anlamamıza ve keşfetmemize yol açtı:
- rclone ile
--vfs-cache-mode writesbayrağını etkinleştirirseniz, okuma işlemleri iyi çalışır ancak yazmalar önbelleğe alınır.- Birden fazla IMAP sunucunuz küresel olarak dağıtılmışsa, önbellek bunlar arasında kapalı olur; ancak tek bir yazıcı ve birden fazla dinleyici (örneğin bir pub/sub yaklaşımı) varsa bu sorun olmaz.
- Bu inanılmaz derecede karmaşıktır ve buna benzer ek karmaşıklıklar daha fazla tek hata noktası yaratır.
- S3 uyumlu depolama sağlayıcıları kısmi dosya değişikliklerini desteklemez – bu,
.sqlitedosyasındaki herhangi bir değişikliğin veritabanının tamamen değişmesi ve yeniden yüklenmesi anlamına gelir. rsyncgibi diğer çözümler vardır, ancak bunlar yazma öncesi günlük ("WAL") desteğine odaklanmaz – bu yüzden Litestream'i inceledik. Neyse ki şifreleme kullanımız zaten WAL dosyalarını bizim için şifreliyor, bu yüzden Litestream'e bu konuda güvenmemize gerek yok. Ancak Litestream'in üretim kullanımı için henüz tam güvenimiz yok ve aşağıda bununla ilgili birkaç notumuz var.--vfs-cache-mode writesseçeneğini kullanmak (yazmalar içinrcloneüzerinden SQLite kullanmanın tek yolu) tüm veritabanını sıfırdan belleğe kopyalamaya çalışır – 10 GB'lık bir posta kutusunu yönetmek sorun değil, ancak çok yüksek depolama gerektiren birden fazla posta kutusunu yönetmek IMAP sunucularının bellek sınırlarına,ENOMEMhatalarına, segmentasyon hatalarına ve veri bozulmasına yol açar.
- SQLite Sanal Tabloları (örneğin s3db kullanarak) S3 uyumlu depolama katmanında veri tutmak için kullanmaya çalışırsanız, birkaç başka sorunla karşılaşırsınız:
- Okuma ve yazma işlemleri çok yavaş olur çünkü S3 API uç noktalarına HTTP
GET,PUT,HEADvePOSTyöntemleriyle erişilmesi gerekir. - Geliştirme testleri, fiber internet üzerinde 500K-1M+ kayıt aşımının bile S3 uyumlu sağlayıcılara yazma ve okuma hızlarıyla sınırlı olduğunu gösterdi. Örneğin geliştiricilerimiz hem ardışık SQL
INSERTifadeleri hem de büyük miktarda veriyi toplu yazanfordöngüleri çalıştırdı. Her iki durumda da performans şaşırtıcı derecede yavaştı. - Sanal tablolar indekslere,
ALTER TABLEifadelerine ve diğer kısıtlamalara sahip olamaz – bu da veri miktarına bağlı olarak 1-2 dakika veya daha fazla gecikmeye yol açar. - Nesneler şifrelenmemiş olarak depolanır ve yerel şifreleme desteği mevcut değildir.
- Okuma ve yazma işlemleri çok yavaş olur çünkü S3 API uç noktalarına HTTP
- Ayrıca sqlite-s3vfs kullanmayı araştırdık; bu kavramsal ve teknik olarak önceki maddeye benzer (dolayısıyla aynı sorunlara sahip). Bir olasılık, yukarıdaki çözümümüzde kullandığımız gibi şifreleme ile sarılmış özel bir
sqlite3derlemesi kullanmak olabilir; örneğin wxSQLite3 aracılığıyla kurulum dosyasını düzenleyerek. - Başka bir potansiyel yaklaşım multiplex eklentisi kullanmaktı, ancak bunun 32 GB sınırı var ve karmaşık derleme ve geliştirme zorlukları gerektirir.
ALTER TABLEifadeleri gereklidir (bu nedenle Sanal Tablolar tamamen elenir).knex-schema-inspectorile kancamızın düzgün çalışması içinALTER TABLEifadelerine ihtiyacımız var – bu, verilerin bozulmamasını ve alınan satırlarınmongooseşema tanımlarımıza göre geçerli belgelere dönüştürülebilmesini sağlar (bu tanımlar kısıtlamalar, değişken türleri ve keyfi veri doğrulamasını içerir).- Açık kaynak topluluğunda SQLite ile ilgili S3 uyumlu projelerin neredeyse tamamı Python'dadır (ve bizim kullandığımız %100 JavaScript değildir).
- sqlite-zstd gibi sıkıştırma kütüphaneleri (bkz. yorumlar) umut verici görünmekle birlikte henüz üretim kullanımı için hazır olmayabilir. Bunun yerine
String,Object,Map,Array,SetveBuffergibi veri türlerinde uygulama tarafı sıkıştırma daha temiz ve kolay bir yaklaşım olacaktır (ve geçişi de daha kolaydır, çünkü birBooleanbayrak veya sütun saklayabiliriz – ya da veritabanı meta verisi olarak sıkıştırma içinPRAGMA user_version=1veya sıkıştırmasız içinuser_version=0kullanabiliriz).- Neyse ki IMAP sunucu depolamamızda ek dosya çoğaltma önleme zaten uygulanmıştır – bu nedenle aynı eki içeren her mesaj eki kopyalamaz – bunun yerine bir posta kutusundaki birden fazla mesaj ve konu için tek bir ek saklanır ve yabancı bir referans kullanılır.
- SQLite çoğaltma ve yedekleme çözümü olan Litestream projesi çok umut verici ve muhtemelen gelecekte kullanacağız.
- Yazarı/yazarları küçümsemek istemeyiz – çünkü onlar açık kaynak için on yılı aşkın süredir yaptıkları çalışmalar ve katkılarla çok seviyoruz – ancak gerçek dünya kullanımı, birçok sorun ve kullanımdan kaynaklanan potansiyel veri kaybı olabileceğini gösteriyor.
- Yedek geri yükleme sürtünmesiz ve basit olmalıdır.
mongodumpvemongoexportkullanan MongoDB gibi çözümler sadece zahmetli değil, aynı zamanda zaman alıcı ve yapılandırma karmaşıklığına sahiptir.- SQLite veritabanları bunu basitleştirir (tek bir dosyadır).
- Kullanıcıların posta kutularını istedikleri anda alıp ayrılabilecekleri bir çözüm tasarlamak istedik.
- Basit Node.js komutlarıyla
fs.unlink('mailbox.sqlite')yaparak dosya kalıcı olarak diskten silinir. - Benzer şekilde S3 uyumlu API ile HTTP
DELETEkullanarak kullanıcılar için anlık görüntüleri ve yedekleri kolayca kaldırabiliriz.
- Basit Node.js komutlarıyla
- SQLite en basit, en hızlı ve en maliyet etkin çözümdü.
Alternatif Eksikliği
Bildiklerimize göre, başka hiçbir e-posta servisi bu şekilde tasarlanmamıştır ve açık kaynak değildir.
Bunun sebebinin, mevcut e-posta servislerinin üretimde spagetti kod 🍝 içeren eski teknolojiye sahip olmaları olduğunu düşünüyoruz.
Mevcut e-posta servis sağlayıcılarının çoğu ya kapalı kaynaklıdır ya da açık kaynak olarak reklam yapar, ancak gerçekte sadece ön yüzleri açık kaynaktır.
E-postanın en hassas kısmı (gerçek depolama/IMAP/SMTP etkileşimi) tamamen arka uçta (sunucu) yapılır, ön uçta (istemci) değil.
Forward Email'i Deneyin
Bugün https://forwardemail.net adresinden kaydolun! 🚀