דואר אלקטרוני עמיד לקוונטים: איך אנחנו משתמשים בתיבות דואר SQLite מוצפנות כדי לשמור על הדואר האלקטרוני שלך בטוח

איור שירות דואר אלקטרוני מוצפן בטוח לקוונטים

הקדמה

Important

שירות הדואר האלקטרוני שלנו הוא קוד פתוח במאה אחוז וממוקד בפרטיות באמצעות תיבות דואר SQLite מאובטחות ומוצפנות.

עד שהשקנו את תמיכת IMAP, השתמשנו ב-MongoDB לצרכי אחסון הנתונים המתמידים שלנו.

הטכנולוגיה הזו מדהימה ואנחנו עדיין משתמשים בה היום – אך כדי לקבל הצפנה במצב מנוחה עם MongoDB, יש צורך להשתמש בספק שמציע MongoDB Enterprise, כמו Digital Ocean או Mongo Atlas – או לשלם עבור רישיון ארגוני (ולעבוד עם עיכובים מצד צוות המכירות).

הצוות שלנו ב-Forward Email היה זקוק לפתרון אחסון ידידותי למפתחים, סקלאבילי, אמין ומוצפן עבור תיבות דואר IMAP. כמפתחים בקוד פתוח, השימוש בטכנולוגיה שדורשת תשלום עבור רישיון כדי לקבל את תכונת ההצפנה במצב מנוחה היה מנוגד ל-העקרונות שלנו – ולכן ניסינו, חקרנו ופיתחנו פתרון חדש מאפס כדי לענות על הצרכים הללו.

במקום להשתמש במסד נתונים משותף לאחסון תיבות הדואר שלך, אנחנו מאחסנים ומצפינים כל תיבת דואר בנפרד עם הסיסמה שלך (שיש רק לך). שירות הדואר האלקטרוני שלנו כל כך מאובטח שאם תשכח את הסיסמה שלך, תאבד את תיבת הדואר שלך (ותצטרך לשחזר מגיבויים לא מקוונים או להתחיל מחדש).

המשך לקרוא כשאנחנו נכנסים לעומק עם השוואת ספקי שירות דואר אלקטרוני, איך השירות שלנו עובד, ערימת הטכנולוגיה שלנו ועוד.

השוואת ספקי שירות דואר אלקטרוני

אנחנו ספק שירות הדואר האלקטרוני היחיד שהוא 100% קוד פתוח וממוקד פרטיות, שמאחסן תיבות דואר SQLite מוצפנות בנפרד, מציע דומיינים, כינויים ומשתמשים ללא הגבלה, ותומך ב-SMTP יוצא, IMAP ו-POP3:

בניגוד לספקי דואר אחרים, אינך צריך לשלם עבור אחסון על בסיס דומיין או כינוי עם Forward Email. האחסון משותף לכל החשבון שלך – אז אם יש לך מספר שמות דומיין מותאמים אישית וכינויים מרובים על כל אחד מהם, אנחנו הפתרון המושלם עבורך. שים לב שניתן עדיין לאכוף מגבלות אחסון אם תרצה על בסיס דומיין או כינוי.

קרא השוואת שירותי דואר אלקטרוני

איך זה עובד

  1. באמצעות לקוח הדואר האלקטרוני שלך כגון Apple Mail, Thunderbird, Gmail או Outlook – אתה מתחבר לשרתי IMAP המאובטחים שלנו באמצעות שם המשתמש והסיסמה שלך:

    • שם המשתמש שלך הוא הכינוי המלא עם הדומיין שלך כמו hello@example.com.
    • הסיסמה שלך נוצרת באקראי ומוצגת רק לך למשך 30 שניות כשאתה לוחץ על צור סיסמה מתוך החשבון שלי דומיינים כינויים.
  2. ברגע שמתחברים, לקוח הדואר האלקטרוני שלך ישלח פקודות פרוטוקול IMAP לשרת ה-IMAP שלנו כדי לשמור על סינכרון תיבת הדואר שלך. זה כולל כתיבה ואחסון של מיילים טיוטה ופעולות נוספות שאתה עשוי לבצע (למשל לסמן מייל כחשוב או לסמן מייל כספאם/דואר זבל).

  3. שרתי החלפת הדואר (המכונים בדרך כלל "MX") מקבלים מיילים נכנסים חדשים ואוחסנים אותם בתיבת הדואר שלך. כאשר זה קורה, לקוח הדואר שלך יקבל התראה ויסנכרן את תיבת הדואר. שרתי החלפת הדואר שלנו יכולים להעביר את המייל שלך לנמען אחד או יותר (כולל webhooks), לאחסן את המייל שלך עבורך באחסון ה-IMAP המוצפן שלנו, או את שניהם!

  4. מאחורי הקלעים, עיצוב אחסון הדואר המאובטח שלנו פועל בשתי דרכים כדי לשמור על תיבות הדואר מוצפנות ונגישות רק עבורך:

    • כאשר מתקבל דואר חדש עבורך מהשולח, שרתי החלפת הדואר שלנו כותבים לתיבת דואר אישית, זמנית ומוצפנת עבורך.

    • כאשר אתה מתחבר לשרת ה-IMAP שלנו עם לקוח הדואר שלך, הסיסמה שלך מוצפנת בזיכרון ומשמשת לקריאה וכתיבה בתיבת הדואר שלך. ניתן לקרוא ולכתוב לתיבת הדואר רק עם סיסמה זו. זכור כי מאחר ואתה היחיד שיש לו סיסמה זו, רק אתה יכול לקרוא ולכתוב לתיבת הדואר שלך כאשר אתה ניגש אליה. בפעם הבאה שלקוח הדואר שלך ינסה לבדוק דואר או לסנכרן, ההודעות החדשות יועברו מתיבת הדואר הזמנית הזו ויאוחסנו בקובץ תיבת הדואר האמיתי שלך באמצעות הסיסמה שסיפקת. שים לב שתיבת הדואר הזמנית הזו נמחקת לאחר מכן כך שרק תיבת הדואר המוגנת בסיסמה שלך מכילה את ההודעות.

    • אם אתה מחובר ל-IMAP (למשל באמצעות לקוח דואר כמו Apple Mail או Thunderbird), אז אין צורך לכתוב לאחסון זמני בדיסק. הסיסמה המוצפנת בזיכרון של IMAP שלך נשלפת ומשמשת במקום זאת. בזמן אמת, כאשר מייל מנסה להימסר אליך, אנו שולחים בקשת WebSocket לכל שרתי ה-IMAP ושואלים אם יש להם סשן פעיל עבורך (זהו שלב השליפה), ולאחר מכן מעבירים את הסיסמה המוצפנת בזיכרון – כך שאין צורך לכתוב לתיבת דואר זמנית, ניתן לכתוב לתיבת הדואר המוצפנת האמיתית שלך באמצעות הסיסמה המוצפנת שלך.

  5. גיבויים של תיבות הדואר המוצפנות שלך מתבצעים מדי יום. ניתן גם לבקש גיבוי חדש בכל עת או להוריד את הגיבוי האחרון מ-החשבון שלי דומיינים כינויים. אם תחליט לעבור לשירות דואר אחר, תוכל בקלות להגר, להוריד, לייצא ולמחוק את תיבות הדואר והגיבויים שלך בכל עת.

טכנולוגיות

מסדי נתונים

בדקנו שכבות אחסון מסד נתונים אחרות, אך אף אחת מהן לא ענתה על דרישותינו כמו SQLite:

Database Encryption-at-rest תיבות דואר מבודדות רישיון משמש בכל מקום
SQLite ✅ כן עם SQLite3MultipleCiphers ✅ דומיין ציבורי
MongoDB "זמין רק ב-MongoDB Enterprise" ❌ מסד נתונים רלציוני ❌ AGPL ו-SSPL-1.0
rqlite רק ברשת ❌ מסד נתונים רלציוני MIT
dqlite לא נבדק ועדיין לא נתמך? לא נבדק ועדיין לא נתמך? LGPL-3.0-only
PostgreSQL כן ❌ מסד נתונים רלציוני PostgreSQL (דומה ל-BSD או MIT)
MariaDB רק עבור InnoDB ❌ מסד נתונים רלציוני GPLv2 ו-BUSL-1.1
CockroachDB תכונה רק לארגונים ❌ מסד נתונים רלציוני BUSL-1.1 ואחרים

הנה פוסט בלוג שמשווה מספר אפשרויות אחסון מסד נתונים SQLite בטבלה למעלה.

אבטחה

בכל עת אנו משתמשים ב-הצפנה במנוחה (AES-256), הצפנה בהעברה (TLS), DNS מעל HTTPS ("DoH") באמצעות 🍊 Tangerine, ובהצפנת sqleet (ChaCha20-Poly1305) על תיבות הדואר. בנוסף, אנו משתמשים באימות דו-שלבי מבוסס טוקן (בניגוד ל-SMS הרגיש ל-התקפות אדם בתווך), מפתחות SSH מסתובבים עם גישת root מושבתת, גישה בלעדית לשרתים דרך כתובות IP מוגבלות, ועוד. במקרה של התקפת משרתת רעה או עובד מרושע מספק צד שלישי, תיבת הדואר שלך עדיין יכולה להיפתח רק עם הסיסמה שיצרת. תהיה בטוח, אנחנו לא מסתמכים על ספקי צד שלישי אחרים מלבד ספקי השרתים שלנו התואמים ל-SOC Type 2 של Cloudflare, DataPacket, Digital Ocean, GitHub, ו-Vultr.

המטרה שלנו היא שיהיו כמה שפחות נקודות כשל יחידות ככל האפשר.

תיבות דואר

תקציר; שרתי ה-IMAP שלנו משתמשים במסדי נתונים SQLite מוצפנים בנפרד עבור כל אחת מתיבות הדואר שלך.

SQLite הוא מסד נתונים משובץ פופולרי מאוד – הוא פועל כרגע בטלפון ובמחשב שלך – ומשמש כמעט את כל הטכנולוגיות הגדולות.

לדוגמה, בשרתים המוצפנים שלנו יש מסד נתונים SQLite עבור תיבת הדואר של linux@example.com, info@example.com, hello@example.com וכן הלאה – אחד לכל תיבה כקובץ מסד נתונים .sqlite. אנחנו לא קוראים לקבצי מסד הנתונים על פי כתובת האימייל – במקום זאת אנחנו משתמשים ב-BSON ObjectID ו-UUID ייחודיים שנוצרים שאינם חושפים למי שייכת תיבת הדואר או איזו כתובת אימייל היא (למשל 353a03f21e534321f5d6e267.sqlite).

כל אחד ממסדי הנתונים האלה מוצפן בעצמו באמצעות הסיסמה שלך (שיש רק לך) באמצעות sqleet (ChaCha20-Poly1305). משמעות הדבר היא שתיבות הדואר שלך מוצפנות בנפרד, עצמאיות, מבודדות, וניידות.

כיווננו את SQLite עם ה-PRAGMA הבאים:

PRAGMA מטרה
cipher=chacha20 הצפנת מסד נתונים SQLite ChaCha20-Poly1305. עיין ב-better-sqlite3-multiple-ciphers תחת Projects לקבלת תובנות נוספות.
key="****************" זוהי הסיסמה שלך מפוענחת בזיכרון בלבד שמועברת דרך חיבור ה-IMAP של לקוח האימייל שלך לשרת שלנו. מופעלות מופעי מסד נתונים חדשים וננעלים עבור כל סשן קריאה וכתיבה (כדי להבטיח בידוד ומבודדות).
journal_model=WAL יומן כתיבה מקדימה ("WAL") שמשפר ביצועים ומאפשר גישה לקריאה במקביל.
busy_timeout=5000 מונע שגיאות נעילת כתיבה בזמן שכתיבות אחרות מתבצעות.
synchronous=NORMAL מגדיל את עמידות העסקאות בלי סיכון לשחיתות נתונים.
foreign_keys=ON מחייב הפניות מפתח זר (למשל קשר מטבלה אחת לאחרת). ברירת המחדל ב-SQLite היא לא להפעיל זאת, אך לצורך אימות ושלמות הנתונים יש להפעיל זאת.
encoding='UTF-8' קידוד ברירת מחדל לשימוש להבטחת שפיות המפתח.

כל ברירות המחדל האחרות הן מ-SQLite כפי שמפורט ב-התיעוד הרשמי של PRAGMA.

תחרותיות

תקציר; אנו משתמשים ב-WebSocket לקריאות וכתיבות מקבילות לתיבות הדואר המוצפנות שלך ב-SQLite.

קריאות

לקוח הדואר האלקטרוני שלך בטלפון עשוי לפתור את imap.forwardemail.net לאחד מכתובות ה-IP של Digital Ocean שלנו – ולקוח שולחן העבודה שלך עשוי לפתור כתובת IP נפרדת מספק שונה לחלוטין.

ללא קשר לאיזה שרת IMAP לקוח הדואר שלך מתחבר, אנו רוצים שהחיבור יקרא מהמסד נתונים שלך בזמן אמת עם דיוק של 100%. זה נעשה באמצעות WebSockets.

כתיבות

הכתיבה למסד הנתונים שלך שונה במקצת – מכיוון ש-SQLite הוא מסד נתונים מוטמע ותיבת הדואר שלך נמצאת בקובץ יחיד כברירת מחדל.

בדקנו אפשרויות כמו litestream, rqlite, ו-dqlite למטה – אך אף אחת מהן לא ענתה על הדרישות שלנו.

כדי לבצע כתיבות עם רישום מראש לכתיבה ("WAL") מופעל – עלינו לוודא שרק שרת אחד ("ראשי") אחראי על כך. WAL מזרז משמעותית את התחרותיות ומאפשר כותב אחד ורבים קוראים.

הראשי פועל על שרתי הנתונים עם הכוננים המותקנים המכילים את תיבות הדואר המוצפנות. מבחינת הפצה, ניתן לראות את כל שרתי ה-IMAP הפרטניים מאחורי imap.forwardemail.net כשרתים משניים ("משני").

אנו משיגים תקשורת דו-כיוונית עם WebSockets:

  • שרתי הראשי משתמשים במופע של שרת WebSocketServer מ-ws.
  • שרתי המשני משתמשים במופע של לקוח WebSocket מ-ws שעוטף עם websocket-as-promised ו-reconnecting-websocket. שני העוטפים הללו מבטיחים שה-WebSocket יתחבר מחדש ויוכל לשלוח ולקבל נתונים עבור כתיבות מסד נתונים ספציפיות.

גיבויים

תקציר; גיבויים של תיבות הדואר המוצפנות שלך נעשים מדי יום. אתה יכול גם לבקש מיידית גיבוי חדש או להוריד את הגיבוי האחרון בכל עת מ-החשבון שלי דומיינים כינויים.

לגיבויים, אנו פשוט מריצים את פקודת SQLite VACUUM INTO כל יום במהלך עיבוד פקודות IMAP, שמשתמשת בסיסמת ההצפנה שלך מחיבור IMAP בזיכרון. הגיבויים נשמרים אם לא זוהה גיבוי קיים או אם ערך ה-SHA-256 השתנה בקובץ לעומת הגיבוי האחרון.

שים לב שאנו משתמשים בפקודת VACUUM INTO במקום בפקודת backup המובנית כי אם דף משתנה במהלך פעולת פקודת backup, אז יש להתחיל מחדש. פקודת VACUUM INTO תיצור צילום מצב. ראה את ההערות האלה ב-GitHub וב-Hacker News לקבלת תובנות נוספות.

בנוסף, אנו משתמשים ב-VACUUM INTO במקום ב-backup, כי פקודת backup תשאיר את מסד הנתונים לא מוצפן לפרק זמן קצר עד ש-rekey יופעל (ראה את ההערה הזו ב-GitHub comment לקבלת תובנה).

המשני ינחה את הראשי דרך חיבור ה-WebSocket לבצע את הגיבוי – והראשי יקבל את הפקודה לעשות זאת ולאחר מכן:

  1. יתחבר לתיבת הדואר המוצפנת שלך.
  2. ירכוש נעילת כתיבה.
  3. יריץ נקודת ביקורת WAL באמצעות wal_checkpoint(PASSIVE).
  4. יריץ את פקודת SQLite VACUUM INTO.
  5. יוודא שהקובץ שהועתק ניתן לפתיחה עם הסיסמה המוצפנת (אבטחה/הגנה מפני טעויות).
  6. יעלה אותו ל-Cloudflare R2 לאחסון (או לספק שלך אם צוין).

זכור שתיבות הדואר שלך מוצפנות – ובזמן שיש לנו הגבלות IP ואמצעי אימות נוספים לתקשורת WebSocket – במקרה של שחקן זדוני, תוכל להיות בטוח שאם מטען ה-WebSocket אינו מכיל את סיסמת ה-IMAP שלך, הוא לא יוכל לפתוח את מסד הנתונים שלך.

נשמר גיבוי אחד בלבד לכל תיבת דואר כרגע, אך בעתיד ייתכן ונציע שחזור נקודתי בזמן ("PITR").

שרת ה-IMAP שלנו תומך בפקודת SEARCH עם שאילתות מורכבות, ביטויים רגולריים ועוד.

ביצועי חיפוש מהירים הודות ל-FTS5 ו-sqlite-regex.

אנו מאחסנים ערכי Date בתיבות הדואר של SQLite כמחרוזות ISO 8601 דרך Date.prototype.toISOString (עם אזור זמן UTC כדי שהשוואות שוויון יעבדו כראוי).

אינדקסים נשמרים גם עבור כל התכונות שנמצאות בשאילתות החיפוש.

פרויקטים

להלן טבלה המתארת פרויקטים שאנו משתמשים בהם בקוד המקור ובתהליך הפיתוח שלנו (ממוינים אלפביתית):

פרויקט מטרה
Ansible פלטפורמת אוטומציה DevOps לתחזוקה, סקיילינג וניהול כל צי השרתים שלנו בקלות.
Bree מתזמן משימות ל-Node.js ו-JavaScript עם תמיכה ב-cron, תאריכים, ms, later ותמיכה ידידותית למשתמש.
Cabin ספריית לוגים ידידותית למפתחים ב-JavaScript ו-Node.js עם דגש על אבטחה ופרטיות.
Lad מסגרת Node.js שמפעילה את כל הארכיטקטורה ועיצוב ההנדסה שלנו עם MVC ועוד.
MongoDB פתרון מסד נתונים NoSQL שאנו משתמשים בו לאחסון כל שאר הנתונים מחוץ לתיבות הדואר (למשל החשבון שלך, הגדרות, דומיינים וקונפיגורציות כינויים).
Mongoose מודל מסמכים אובייקטיבי ל-MongoDB ("ODM") שאנו משתמשים בו בכל הסטאק שלנו. כתבנו עזרים מיוחדים שמאפשרים לנו להמשיך להשתמש בMongoose עם SQLite 🎉
Node.js Node.js היא סביבת ריצה חוצה פלטפורמות וקוד פתוח ל-JavaScript שמריצה את כל תהליכי השרת שלנו.
Nodemailer חבילת Node.js לשליחת מיילים, יצירת חיבורים ועוד. אנו ספונסרים רשמיים של הפרויקט הזה.
Redis מסד נתונים בזיכרון לאחסון מטמון, ערוצי פרסום/מנוי, ובקשות DNS דרך HTTPS.
SQLite3MultipleCiphers תוסף הצפנה ל-SQLite שמאפשר הצפנת קבצי מסד נתונים שלמים (כולל write-ahead-log ("WAL"), יומן, rollback ועוד).
SQLiteStudio עורך SQLite ויזואלי (שגם אתה יכול להשתמש בו) לבדיקת, הורדת וצפייה בתיבות דואר לפיתוח.
SQLite שכבת מסד נתונים מוטמעת לאחסון IMAP סקיילבילי, עצמאי, מהיר ועמיד.
Spam Scanner כלי נגד ספאם, סינון מיילים ומניעת פישינג ב-Node.js (האלטרנטיבה שלנו ל-Spam Assassin ו-rspamd).
Tangerine בקשות DNS דרך HTTPS עם Node.js ואחסון מטמון באמצעות Redis – שמבטיח עקביות גלובלית ועוד.
Thunderbird צוות הפיתוח שלנו משתמש בזה (וממליץ גם) כלקוח המייל המועדף לשימוש עם Forward Email.
UTM צוות הפיתוח שלנו משתמש בזה ליצירת מכונות וירטואליות ל-iOS ו-macOS כדי לבדוק לקוחות מייל שונים (במקביל) עם שרתי ה-IMAP וה-SMTP שלנו.
Ubuntu מערכת הפעלה מודרנית מבוססת לינוקס בקוד פתוח שמפעילה את כל התשתית שלנו.
WildDuck ספריית שרת IMAP – ראה את ההערות שלו על הסרת כפילויות בקבצים מצורפים ו-תמיכה בפרוטוקול IMAP.
better-sqlite3-multiple-ciphers ספריית API מהירה ופשוטה ל-Node.js לאינטראקציה עם SQLite3 בצורה תכנותית.
email-templates מסגרת מייל ידידותית למפתחים ליצירה, תצוגה ושליחה של מיילים מותאמים אישית (למשל התראות חשבון ועוד).
json-sql-enhanced בונה שאילתות SQL עם תחביר בסגנון Mongo. זה חוסך לצוות הפיתוח שלנו זמן כי אנו יכולים להמשיך לכתוב בסגנון Mongo בכל הסטאק בגישה שאינה תלויה במסד נתונים. זה גם עוזר למנוע התקפות SQL injection על ידי שימוש בפרמטרים בשאילתה.
knex-schema-inspector כלי SQL לחילוץ מידע על סכמת מסד נתונים קיימת. זה מאפשר לנו לאמת בקלות שכל האינדקסים, הטבלאות, העמודות, המגבלות ועוד תקינים ותואמים 1:1 למה שהם צריכים להיות. כתבנו אפילו עזרים אוטומטיים להוספת עמודות ואינדקסים חדשים אם נעשות שינויים בסכמות מסד הנתונים (עם התראות שגיאה מפורטות מאוד).
knex בונה שאילתות SQL שאנו משתמשים בו רק למיגרציות מסד נתונים ולאימות סכמות דרך knex-schema-inspector.
mandarin תרגום אוטומטי של ביטויים i18n עם תמיכה ב-Markdown באמצעות Google Cloud Translation API.
mx-connect חבילת Node.js לפתרון והקמת חיבורים עם שרתי MX וטיפול בשגיאות.
pm2 מנהל תהליכים ל-Node.js בסביבת ייצור עם מאזן עומסים מובנה (מכוון היטב לביצועים).
smtp-server ספריית שרת SMTP – אנו משתמשים בזה לשרת החלפת המייל ("MX") ושרת ה-SMTP היוצא שלנו.
ImapTest כלי שימושי לבדיקת שרתי IMAP מול מדדים ותקינות פרוטוקול IMAP לפי RFC. הפרויקט נוצר על ידי צוות Dovecot (שרת IMAP ו-POP3 בקוד פתוח פעיל מאז יולי 2002). בדקנו לעומק את שרת ה-IMAP שלנו עם הכלי הזה.

אתה יכול למצוא פרויקטים נוספים שבהם אנו משתמשים ב-קוד המקור שלנו ב-GitHub.

ספקים

ספק מטרה
Cloudflare ספק DNS, בדיקות בריאות, מאזני עומס ואחסון גיבוי באמצעות Cloudflare R2.
GitHub אחסון קוד מקור, CI/CD וניהול פרויקטים.
Digital Ocean אירוח שרתים ייעודיים ומסדי נתונים מנוהלים.
Vultr אירוח שרתים ייעודיים.
DataPacket אירוח שרתים ייעודיים.

מחשבות

עקרונות

Forward Email מעוצב בהתאם לעקרונות הבאים:

  1. תמיד להיות ידידותי למפתחים, ממוקד אבטחה ופרטיות, ושקוף.
  2. לעמוד ב-MVC, Unix, KISS, DRY, YAGNI, Twelve Factor, Occam's razor, ו-dogfooding
  3. לפנות למפתחים עצמאיים, ממומנים בעצמם, ורווחיים מרמן

ניסויים

תקציר; בסופו של דבר שימוש באחסון אובייקטים תואם S3 ו/או טבלאות וירטואליות אינו ישים טכנית מסיבות ביצועים ורגיש לשגיאות עקב מגבלות זיכרון.

ביצענו כמה ניסויים שהובילו לפתרון SQLite הסופי שלנו כפי שנדון לעיל.

אחד מהם היה ניסיון להשתמש ב-rclone ו-SQLite יחד עם שכבת אחסון תואמת S3.

ניסוי זה הוביל אותנו להבנה נוספת ולגילוי מקרים קצה סביב השימוש ב-rclone, SQLite ו-VFS:

  • אם מפעילים את הדגל --vfs-cache-mode writes עם rclone, אז הקריאות יהיו בסדר, אך הכתיבות יישמרו במטמון.
    • אם יש לך מספר שרתי IMAP המפוזרים ברחבי העולם, אז המטמון יהיה לא סינכרוני ביניהם אלא אם יש כותב יחיד ומספר מאזינים (למשל גישת pub/sub).
    • זה מורכב מאוד והוספת כל מורכבות נוספת כזו תגרום לנקודות כשל בודדות נוספות.
    • ספקי אחסון תואמי S3 אינם תומכים בשינויים חלקיים בקבצים – מה שאומר שכל שינוי בקובץ .sqlite יגרום לשינוי מלא והעלאה מחדש של מסד הנתונים.
    • קיימות פתרונות אחרים כמו rsync, אך הם אינם מתמקדים בתמיכה בכתיבת יומן מקדימה ("WAL") – לכן סקרנו את Litestream. למזלנו השימוש בהצפנה שלנו כבר מצפין את קבצי WAL, כך שאיננו צריכים להסתמך על Litestream לכך. עם זאת, עדיין לא היינו בטוחים בשימוש ב-Litestream לייצור ויש לנו כמה הערות להלן.
    • שימוש באפשרות --vfs-cache-mode writes (הדרך היחידה להשתמש ב-SQLite מעל rclone לכתיבות) ינסה להעתיק את כל מסד הנתונים מההתחלה בזיכרון – טיפול בתיבת דואר של 10 גיגה-בייט הוא בסדר, אך טיפול במספר תיבות דואר עם אחסון גבוה מאוד יגרום לשרתי IMAP להיתקל במגבלות זיכרון ובשגיאות ENOMEM, קריסות זיכרון, ושחיתות נתונים.
  • אם תנסה להשתמש ב-טבלאות וירטואליות של SQLite (למשל באמצעות s3db) כדי לאחסן נתונים בשכבת אחסון תואמת S3, תיתקל בכמה בעיות נוספות:
    • קריאות וכתיבות יהיו איטיות מאוד כי יש לפנות לנקודות קצה של S3 עם שיטות HTTP GET, PUT, HEAD, ו-POST.
    • בדיקות פיתוח הראו כי מעבר ל-500K-1M+ רשומות באינטרנט סיבים אופטיים עדיין מוגבל על ידי קצב הכתיבה והקריאה לספקי אחסון תואמי S3. לדוגמה, המפתחים שלנו הריצו לולאות for לביצוע הצהרות SQL INSERT סדרתיות וכתיבה בכמויות גדולות. בשני המקרים הביצועים היו איטיים להפליא.
    • לטבלאות וירטואליות אין אפשרות לאינדקסים, הצהרות ALTER TABLE, ומגבלות אחרות – מה שמוביל לעיכובים של 1-2 דקות ואף יותר בהתאם לכמות הנתונים.
    • האובייקטים נשמרו ללא הצפנה ואין תמיכה טבעית בהצפנה זמינה.
  • גם בדקנו שימוש ב-sqlite-s3vfs שהוא דומה מבחינה רעיונית וטכנית לנקודה הקודמת (ולכן יש לו את אותן הבעיות). אפשרות תהיה להשתמש בבניית sqlite3 מותאמת עם הצפנה כמו wxSQLite3 (שאנחנו משתמשים בה כיום בפתרון שלנו לעיל) דרך עריכת קובץ ההתקנה.
  • גישה פוטנציאלית נוספת הייתה להשתמש בהרחבת multiplex, אך יש לה מגבלה של 32 גיגה-בייט והיא תדרוש בנייה מורכבת וכאבי ראש בפיתוח.
  • הצהרות ALTER TABLE נדרשות (כך שזה שולל לחלוטין שימוש בטבלאות וירטואליות). אנו זקוקים להצהרות ALTER TABLE כדי שה-hook שלנו עם knex-schema-inspector יעבוד כראוי – מה שמבטיח שהנתונים לא ייפגמו ושהשורות שנשלפות יוכלו להיות מומרות למסמכים תקינים לפי הגדרות הסכימה של mongoose שלנו (שכוללות הגבלות, סוג משתנה, ואימות נתונים שרירותי).
  • כמעט כל הפרויקטים התואמים ל-S3 הקשורים ל-SQLite בקהילה הקוד הפתוח הם בפייתון (ולא ב-JavaScript שאנו משתמשים בו ב-100% מהסטאק שלנו).
  • ספריות דחיסה כמו sqlite-zstd (ראה הערות) נראות מבטיחות, אך ייתכן שעדיין אינן מוכנות לשימוש בייצור. במקום זאת, דחיסה בצד היישום על סוגי נתונים כמו String, Object, Map, Array, Set, ו-Buffer תהיה גישה נקייה וקלה יותר (וגם קלה יותר למיגרציה, שכן נוכל לאחסן דגל Boolean או עמודה – או אפילו להשתמש ב-PRAGMA user_version=1 לדחיסה או user_version=0 ללא דחיסה כמטא-נתוני מסד הנתונים).
    • למזלנו כבר יש לנו יישום של הסרת שכפולים בקבצים מצורפים באחסון שרת ה-IMAP שלנו – לכן כל הודעה עם אותו קובץ מצורף לא תשמור עותק של הקובץ – במקום זאת קובץ מצורף יחיד נשמר עבור הודעות ושרשורים מרובים בתיבת דואר (והפניה זרה משמשת לאחר מכן).
  • פרויקט Litestream, שהוא פתרון שכפול וגיבוי ל-SQLite, מבטיח מאוד ונשתמש בו ככל הנראה בעתיד.
  • שחזור גיבויים צריך להיות ללא חיכוכים וטריוויאלי. שימוש בפתרון כמו MongoDB עם mongodump ו-mongoexport הוא לא רק מייגע, אלא גם גוזל זמן ומורכב בקונפיגורציה.
    • מסדי נתונים של SQLite עושים זאת פשוט (זהו קובץ יחיד).
    • רצינו לעצב פתרון שבו משתמשים יוכלו לקחת את תיבת הדואר שלהם ולעזוב בכל רגע.
      • פקודות Node.js פשוטות כמו fs.unlink('mailbox.sqlite') ומסד הנתונים נמחק לצמיתות מאחסון הדיסק.
      • נוכל באותה צורה להשתמש ב-API תואם S3 עם HTTP DELETE כדי להסיר בקלות צילומי מצב וגיבויים למשתמשים.
    • SQLite היה הפתרון הפשוט, המהיר והחסכוני ביותר.

חוסר באלטרנטיבות

למיטב ידיעתנו, אין שירותי דואר אלקטרוני אחרים שעוצבו בצורה זו ואינם קוד פתוח.

אנחנו חושבים שזה עשוי להיות בגלל ששירותי דואר קיימים משתמשים בטכנולוגיה ישנה בפרודקשן עם קוד ספגטי 🍝.

רוב אם לא כל ספקי שירותי הדואר הקיימים הם או קוד סגור או מפרסמים עצמם כקוד פתוח, אבל במציאות רק החזית שלהם היא קוד פתוח.

החלק הרגיש ביותר בדואר האלקטרוני (האחסון בפועל/IMAP/SMTP) נעשה כולו בצד השרת (back-end), ולא בצד הלקוח (front-end).

נסו את Forward Email

הירשמו היום בכתובת https://forwardemail.net! 🚀