วิธีที่ผมดูแลเซิร์ฟเวอร์ของตัวเอง (2022)
(blog.wesleyac.com)- บริการส่วนตัวรันเองบน DigitalOcean VM เดือนละ $5 กับ Debian 10 และสำหรับบริการขนาดเล็ก วิธีติดตั้งซอฟต์แวร์เซิร์ฟเวอร์ลงบน VM ก็ยังเรียบง่ายและสมเหตุสมผลเพียงพอ
- แอปเซิร์ฟเวอร์สร้างเป็น ไบนารีแบบ static ของ Rust และรวม HTML, CSS, การตั้งค่า ไปจนถึงค่าลับไว้ด้วย ทำให้ artifact สำหรับ deploy คงอยู่เป็นไฟล์เดียว
- การจัดการการรันใช้ systemd ส่วน HTTPS ให้ nginx reverse proxy กับ Let’s Encrypt/certbot จัดการ เพื่อไม่ให้แอปต้องแตะ TLS โดยตรง
- บริการที่ต้องใช้ข้อมูลใช้ SQLite ไฟล์เดียว และใช้ทั้งการสำรองข้อมูลรายวันด้วย Tarsnap กับการสำรองแบบสตรีมไปยัง DigitalOcean Spaces ของ Litestream
- เมื่อต้องวางหลายบริการบน VM เดียวกัน จะแยกด้วย Unix user แยกตามบริการ และถ้าต้องการความปลอดภัยที่แข็งแรงขึ้นก็เลือกใช้ VM แยก, systemd-nspawn หรือ firejail
โครงสร้างพื้นฐานของเซิร์ฟเวอร์และการ deploy
- บริการหลายตัว เช่น thoughts.page, hanabi.site, cgmserver, phonebridge ถูกดูแลด้วยโครงสร้างที่ใกล้เคียงกับแบบนี้
- แอปรันบน DigitalOcean VM โดยใช้แพ็กเกจระดับ $5/เดือน และระบบปฏิบัติการเป็น Debian 10
- บางบริการแชร์ VM เดียวกัน และบางบริการถูกแยกไปอยู่ VM อื่น
- ซอฟต์แวร์เซิร์ฟเวอร์เขียนด้วย Rust
- ลิงก์แบบ static
- HTML, CSS, การตั้งค่า, ค่าลับ ฯลฯ ถูกคอมไพล์เข้าไปในไบนารี
- ใช้ rust-musl-builder และ rust-embed
- วิธีนี้ทำให้การ deploy ง่ายขึ้นเหลือแค่การคัดลอก ไฟล์เดียว ไปยังเซิร์ฟเวอร์
- มองว่าสามารถใช้วิธีคล้ายกันได้กับ Go, C++ เป็นต้น
- สำหรับภาษาที่ deploy เป็นไบนารีไฟล์เดียวได้ไม่ง่าย ทางเลือกคือใช้ Docker container เป็น artifact จากการ build
การรัน พร็อกซี และการเก็บรักษาข้อมูล
- การจัดการการเริ่มบริการให้ systemd รับผิดชอบ
- ทำให้ไบนารีถูกรันพร้อมกันเมื่อเซิร์ฟเวอร์เริ่มทำงาน
- ไฟล์ systemd unit ส่วนใหญ่เป็น ไฟล์เรียบง่าย 9 บรรทัด
- ตัว systemd เองซับซ้อน แต่ในการใช้งานเพื่อเริ่มเซิร์ฟเวอร์ตอนบูต แทบไม่ต้องเจอความซับซ้อนนั้นส่วนใหญ่
- การ deploy จัดการด้วย simple deploy script
- คัดลอกไบนารีไปยังเซิร์ฟเวอร์และรีสตาร์ตเซิร์ฟเวอร์
- สามารถ rollback ได้ และทำให้มีเวอร์ชันที่ใช้งานได้รันอยู่เสมอ แม้การเชื่อมต่อจะหลุดระหว่าง deploy
- โปรแกรมที่ต้องใช้ฐานข้อมูลใช้ SQLite
- สถานะทั้งหมดของแอปอยู่ใน ไฟล์เดียว
- สร้าง backup ทุกวันด้วย คำสั่ง SQLite
.backupและเก็บไว้ใน Tarsnap - สคริปต์ backup รันด้วย cron
- ใช้ Litestream สตรีมสำเนาฐานข้อมูลไปยังสตอเรจ DigitalOcean Spaces ในระดับวินาที และสร้าง snapshot ทุก 6 ชั่วโมง
- เซิร์ฟเวอร์ทั้งหมดรันอยู่หลัง nginx reverse proxy
- nginx จัดการ TLS termination ดังนั้นแอปไม่ต้องสนใจ HTTPS
- ใบรับรอง HTTPS ออกโดย Let’s Encrypt และ certbot พร้อมต่ออายุอัตโนมัติ
- ตัวอย่างการตั้งค่า nginx ของ hanabi.site อยู่ใน gist แยกต่างหาก
- ไฟล์ static สามารถให้ nginx serve ได้ และคัดลอกไปยังเซิร์ฟเวอร์ด้วย
scpหรือrsync
การบำรุงรักษาและการแยกบริการ
- โครงสร้างนี้มุ่งไปที่เส้นทางการดำเนินงานที่เรียบง่ายและ ทนทาน
- ซอฟต์แวร์ในเส้นทางการให้บริการ นอกเหนือจากตัวแอปเอง เป็นองค์ประกอบที่พิสูจน์แล้วจากการใช้งานมาหลายสิบปี
- ตราบใดที่ยังจ่ายค่า DigitalOcean ต่อไป การดูแลไซต์แทบไม่มีงานบำรุงรักษาโดยพื้นฐาน
- ปัญหาที่ monitoring ตรวจพบมีเพียงปัญหาเครือข่าย DigitalOcean ชั่วคราวเท่านั้น
- ระบบปฏิบัติการและอัปเดตความปลอดภัยยังจำเป็นเป็นครั้งคราว
- Debian release ให้การสนับสนุน 5 ปี ดังนั้นจะต้องอัปเกรดเป็น Debian 11 ในอีกราว 2 ปีครึ่ง
- หากเกิดเหตุการณ์แบบ Heartbleed อีก ก็ต้อง patch
- เหตุการณ์แบบนี้ค่อนข้างพบได้ไม่บ่อย
- ค่าใช้จ่าย VM เดือนละ $5 ต่อบริการอาจเป็นภาระได้ แต่สามารถรันหลายบริการบน VM เดียวกันได้
- การแยกกันทำโดยสร้าง บัญชี Unix user แยกต่างหาก ให้แต่ละบริการ
- วิธีแยกแบบนี้มีมาตั้งแต่ยุคแรกของ Unix จึงดูแข็งแรง
- ถ้าต้องการการแยกที่แข็งแรงขึ้น สามารถใช้ systemd-nspawn หรือ firejail ได้
- ถ้าสำคัญด้านความปลอดภัยจริง ๆ ก็จ่ายเพิ่มอีก $5/เดือน แล้วรันบน VM แยก
- ขั้นตอนตั้งค่าโปรเจกต์ใหม่สั้นมาก
- สร้าง user ใหม่
- เพิ่ม nginx virtual host และออกใบรับรอง HTTPS ด้วย certbot
- เพิ่ม systemd unit
- commit deploy script ลงใน repository แล้วรัน
- ตอนแรกมีหลายอย่างที่ต้องเรียนรู้ แต่ infrastructure แบบนี้ เปลี่ยนช้ากว่า cloud infrastructure มาก
- รูปแบบการตั้งค่า nginx แทบไม่เปลี่ยนในสาระสำคัญตลอด 10 ปีที่ผ่านมา
- การเปลี่ยนแปลงใหญ่ครั้งล่าสุดของการดูแลระบบ Debian คือการย้ายไปใช้ systemd เมื่อเกือบ 10 ปีก่อน
- เผชิญกับสถานการณ์ที่ผู้ให้บริการ cloud ยกเลิกบริการหรือแอบเปลี่ยนพฤติกรรมน้อยกว่า
- dependency มีเพียงผู้ให้บริการ VPS และเซิร์ฟเวอร์เป็นสินค้าทั่วไป จึงสามารถย้ายไปผู้ให้บริการรายอื่นได้
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
หากรันแต่ละบริการด้วยผู้ใช้ Unix แยกกันเพื่อการแยกส่วน ฟีเจอร์ DynamicUser ของ systemd สามารถช่วยประหยัดเวลาได้
มันจะจัดสรร UID และสร้างไดเรกทอรีสำหรับล็อก/สถานะด้วยสิทธิ์ที่ถูกต้องให้
https://0pointer.net/blog/dynamic-users-with-systemd.html
เพียงใส่ไฟล์ข้อความขนาดเล็กที่มีข้อมูลอย่างชื่อผู้ใช้และโฮมไดเรกทอรีไว้ใน
/etc/sysusers.d/แล้วรันคำสั่งหรือบริการsysusersช่วงนี้ชอบ HTTP-triggered cloud functions มากที่สุด
ถ้าระวังหลีกเลี่ยงกับดักเฉพาะของแต่ละผู้ให้บริการได้ มันช่วยลดความซับซ้อนได้มาก และเป็น abstraction แบบ cloud-native อย่างเดียวที่ให้ความรู้สึกเหมือนเป็น “รูปแบบสุดท้าย”
ในแอปเดียวมีการ deploy ไปแล้วมากกว่า 2000 ครั้ง และไม่เคยมีสักครั้งที่ environment พังจนต้องติดต่อซัพพอร์ตหรือพิมพ์คำสั่งคอนโซลประหลาด ๆ
ประสิทธิภาพบน Azure แบบ isolated App Service plan ก็ยอดเยี่ยม และความรู้สึกต่อต้านเชิงอุดมการณ์ต่อการคิดเงินตามจำนวนคำขอก็หายไปแล้ว
ถ้าถึงขั้นเป็นเจ้าของอสังหาริมทรัพย์ที่มีเซิร์ฟเวอร์ของตัวเองอยู่จริง ๆ ก็อาจทำให้ถูกกว่าได้ แต่ถ้าจะสร้างคุณสมบัติอย่าง compliance และ audit ที่ HTTP function แบบง่าย ๆ ให้มาเองด้วยมือตัวเอง ในทางปฏิบัติก็คงต้องตั้งบริษัทระดับยักษ์และจ้างคนจำนวนมาก
เหตุผลเรื่อง vendor lock-in ก็ไม่ได้รู้สึกหนักแน่นอีกต่อไป อินเทอร์เฟซที่รับ HTTP request แล้วส่ง HTTP response กลับนั้นเป็นธรรมชาติมาก และความต่างของแต่ละผู้ให้บริการก็มีแค่บริบทเสริมอย่าง method signature ของ trigger หรือ claims ของ OIDC/SAML ดังนั้นถ้าจะทำให้มัน refactor ไปผู้ให้บริการอื่นภายในหนึ่งสัปดาห์ไม่ได้ ก็คงต้องพยายามทำให้ผูกติดเองมากกว่า
ถ้าเป็นบล็อกส่วนตัวก็เข้าใจได้ว่าการซื้อ VM จาก Hetzner มาขัดเกลาแบบงานคราฟต์จะสนุกกว่า ถ้าอยู่ในอุตสาหกรรมที่ไม่มีข้อกำกับเลย ก็พอจะโต้แย้งได้หนักแน่นกว่าว่าควรคิดเรื่องมาร์จินและความซับซ้อนอย่างละเอียดแทนการเอาเซิร์ฟเวอร์ไป outsource ทั้งหมด
ไม่แน่ใจว่าคิดว่าก่อน การย้ายขึ้นคลาวด์ คนเขาทำกันอย่างไร
ตอนนี้ผมดูแลหลายทีมในบริษัทอุตสาหกรรมขนาดใหญ่และกำลังขยาย/ปล่อยแอปนวัตกรรมบน Azure ซึ่งค่าใช้จ่ายคลาวด์มหาศาลเกินเหตุเมื่อเทียบกับจำนวนผู้ใช้
เมื่อก่อนเราเคยรันแอปที่มีผู้ใช้มากกว่านี้ 10 เท่า ด้วยค่าใช้จ่ายเพียง 1/100 และยังซับซ้อนน้อยกว่าอีก
ค่าใช้จ่ายนี้ถูกโยนไปให้แผนกอื่นที่เลือกแนวทางน่าสงสัยแบบนี้อยู่แล้ว ดังนั้นส่วนตัวผมไม่ได้เดือดร้อน แต่ก็เข้าใจยากว่าทำไมถึงเชื่อคลาวด์แบบไร้ข้อกังขา
สำหรับเรา การดูแลฮาร์ดแวร์เอง คือทางเลือกที่ดีที่สุด และเราอยู่ในระดับที่แม้แต่ถ่ายรูปในออฟฟิศก็ไม่ได้ ดังนั้นโอกาสที่จะฝากอะไรไว้กับผู้ให้บริการคลาวด์จึงเป็น 0%
แต่ถ้าแอปจะมีประโยชน์จริงก็ยังต้องมีองค์ประกอบอื่นอย่างฐานข้อมูลด้วย และตรงนั้นค่าใช้จ่ายก็ไม่ได้เพิ่มขึ้นหรือ?
สับสนว่าหมายถึง request handler ของ HTTP server, cloud computing แบบ function-as-a-service หรือแค่ RPC แบบเก่า
ถ้ามี script kiddie คนไหนเริ่มยิง request 10 ครั้งต่อนาที ต้องใช้เวลานานแค่ไหนกว่าค่าใช้จ่ายของฟังก์ชันจะแพงกว่า VPS?
ผมใช้สแตกคล้ายกันกับทั้งเว็บไซต์ส่วนตัวและเว็บไซต์โปรเจกต์
ใช้ Linode VM ราคา 5 ดอลลาร์ต่อเดือน, ใช้ Debian GNU/Linux และเขียนซอฟต์แวร์ด้วย Common Lisp
เว็บไซต์ส่วนตัวหรือบล็อกจะสร้างเป็น static site ด้วยโปรแกรม Common Lisp ส่วนบริการออนไลน์หรือเว็บแอปก็ทำเป็นโปรแกรม Common Lisp ที่รับและตอบ HTTP request ด้วย Hunchentoot
ใช้ไฟล์ยูนิต systemd เพื่อให้เว็บไซต์/บริการเริ่มทำงานอัตโนมัติเมื่อ VM บูตหรือรีสตาร์ต โดยส่วนใหญ่ยาวแค่ราว 10~15 บรรทัด
การตั้งค่าเริ่มต้นของ VM ถูกทำเป็นโค้ดไว้ในเชลล์สคริปต์: https://github.com/susam/dotfiles/blob/main/linode.sh
การตั้งค่าแยกตามโปรเจกต์และบริการจัดการด้วย Makefile ของแต่ละตัว: https://github.com/susam/susam.net/blob/main/Makefile, https://github.com/susam/mathb/blob/main/Makefile
ไม่ใช้คอนเทนเนอร์ เว็บไซต์เหล่านี้รันมากันหลายปีตั้งแต่ก่อนคอนเทนเนอร์จะฮิต และจนถึงตอนนี้แค่มีสคริปต์เริ่มต้นกับ Makefile ก็เพียงพอแล้ว
ใช้ Nginx ด้วยเช่นกัน มันใช้เสิร์ฟไฟล์แบบ static และเมื่อมี backend service ก็ทำหน้าที่เป็น reverse proxy นอกจาก terminate TLS แล้ว ยังมีข้อดีอย่างการจำกัดอัตราคำขอและการตั้ง allowlist ของ HTTP header เพื่อปกป้อง backend
ในเพลย์บุ๊กส่วนตัวขนาดเล็กมีคำสั่งไม่กี่ตัวอย่าง
curl LINK -o linode.sh && sh linode.sh,git clone LINK && cd PROJECT && sudo make setup httpstarget ของ
makeจะจัดการงานที่จำเป็นต่อการเปิดเว็บไซต์ เช่น ติดตั้งเครื่องมืออย่าง Nginx, certbot, sbcl, ตั้งค่า Nginx, ตั้งค่าใบรับรอง และเมื่อคำสั่งจบ เว็บไซต์ก็จะออนไลน์ทันทีดูจาก Makefile เหมือนจะใช้ SBCL เลยสงสัยว่าเคยมีปัญหาเรื่องการใช้หน่วยความจำหรือไม่
ผมใช้ VPS ที่มี RAM 512MB และ SBCL instance หนึ่งกินประมาณ 100MB เลยรันหลายบริการพร้อมกันได้ไม่กี่ตัว
เคยคิดจะย้ายบริการที่มีทราฟฟิกต่ำที่สุดไป CLISP แต่ฟีเจอร์หนึ่งที่ใช้อยู่คือ package-local aliases ไม่มีให้ใช้
หลังจากขัดเกลาการตั้งค่ามาเรื่อย ๆ หลายปี ตอนนี้ลงตัวกับการรันทุกอย่างด้วย Docker containers
ตัว orchestrator ใช้ docker-compose แทน systemd และ proxy ใช้ Caddy แทน nginx
เหมือนกับบทความต้นฉบับ ผมเขียน deployment script แยกสำหรับแต่ละโปรเจกต์ที่ต้องรัน เลยถือว่าภาพรวมค่อนข้างคล้ายกัน
ข้อดีอย่างหนึ่งจากหลาย ๆ ข้อของ Docker คือสามารถรันซอฟต์แวร์ third-party ด้วยการตั้งค่าแบบเดียวกันได้
ใช้การตั้งค่านี้มาหลายปีแล้วและมันดีมาก ทั้งแข็งแรงเหมือนบทความต้นฉบับ และก็ยืดหยุ่นพอจะปรับตามต้องการเมื่อจำเป็น
ตอนนี้จุดที่เจ็บปวดอยู่เรื่องเดียวคือ rolling deployment พอซอฟต์แวร์ใหญ่ขึ้น การที่มี downtime หลายวินาทีทุกครั้งที่ deploy ก็เริ่มเป็นปัญหา และแม้จะยังไม่มีวิธีแก้ที่ง่าย แต่ docker swarm อาจเป็นทางที่ใช่
ถ้าอยากลด downtime ลองใช้
health_uri /health,lb_try_duration 30sได้ตัวอย่างเช่นถ้าตั้งค่าเป็น
reverse_proxy api:8089 { health_uri /health lb_try_duration 30s }ระหว่าง deploy เวอร์ชันใหม่ Caddy จะบัฟเฟอร์คำขอไว้และให้เวลา 30 วินาทีจนกว่าบริการใหม่จะขึ้นมาตามอุดมคติแล้ว Caddy ควรเริ่มส่งทราฟฟิกไปยังเวอร์ชันใหม่หลังจากมันพร้อมใช้งาน แล้วค่อยหยุดคอนเทนเนอร์เดิม
ผมดู https://github.com/Wowu/docker-rollout กับ https://github.com/lucaslorentz/caddy-docker-proxy ไว้แล้ว แต่ยังหาเวลาให้มันเป็นลำดับความสำคัญไม่ได้
มันไม่สมบูรณ์แบบ แต่แทนที่เบราว์เซอร์จะเจอ connection error ผู้ใช้ก็จะเห็นแค่โหลดค้างอยู่ไม่กี่วินาที
https://mrsk.dev/ ก็ใช้เทคนิคเดียวกัน
ฝั่งโปรดักชันเริ่มจาก compose แล้วภายหลังก็พัฒนาเป็น continuous deployment pipeline ที่อัปเกรดสแตกอัตโนมัติ
พอบริษัทและฐานผู้ใช้โตขึ้น ปัญหา downtime ตอนรีสตาร์ตหรือ deploy ก็เริ่มโผล่มา และทุกครั้งที่อยากรันแอปเพิ่มก็ต้องเตรียมสภาพแวดล้อม deploy ใหม่
ผมกลัวว่าวันหนึ่งจะต้องใช้ Kubernetes เพราะเคยเห็นความซับซ้อนของมันมากับตา และไม่อยากใช้เวลาส่วนใหญ่ของวันไปกับการกล่อมคลัสเตอร์
เลยเลือกใช้ Swarm mode ซึ่งเป็นการเดินทางแบบบางทีก็ Jekyll บางทีก็ Hyde
มีทั้งบั๊กที่ไม่มีใครคิดจะแก้ ส่วนของ Docker spec ที่ไม่ได้ implement แต่ก็ไม่บอกกันตรง ๆ การตัดสินใจด้าน implementation ที่ชวนดึงผมตัวเอง และความรู้สึกเหมือนพนักงาน Docker Inc คุยกันไม่รู้เรื่องหรือโฟกัสไม่จบ
ถึงอย่างนั้นมันก็มีด้านที่สวยงามมาก compose stack เดิมยังใช้ต่อได้และค่อย ๆ ขยายเมื่อถึงจุดจำเป็น และถ้าตั้งค่าดี ๆ ก็ทำ zero-downtime deploy, upgrade, load balancing และ rollback ได้ดี
Raft ก็เชื่อถือได้สำหรับการดูแลคลัสเตอร์เหมือนในที่อื่น ๆ และถ้าลงแรงอีกนิด คุณก็สร้างแพลตฟอร์ม self-service ที่ยืดหยุ่น ปลอดภัย และกระจายงานอัตโนมัติได้ โดยใช้งบเพียงเศษเสี้ยวของค่าบำรุงรักษา K8s
แต่ก็ต้องพร้อมจะทำ deployment script ให้ดี ผมใช้เวลาไปเยอะพอสมควรกับการทำเครื่องมือ Python สำหรับแปลง compose file ที่เป็น Docker spec ถูกต้องให้เป็น Swarm spec, รีเฟรชและเก็บกวาด secret, และขยาย environment variables
และขึ้นอยู่กับผู้ให้บริการ VPS คุณต้องตั้งค่า network MTU ให้ถูกต้องด้วย เรื่องนี้น่าจะทำให้อายุผมสั้นลงไปพอสมควร
อย่างน้อยก็จนกว่าจะมีลูกค้าหรือผู้ใช้มากพอจนปัญหาเรื่องการขยายระบบเกิดขึ้นจริง
docker saveกับdocker importเพื่อดันอิมเมจผ่าน SSHเลยสงสัยว่าคุณรัน registry เองหรือเปล่า
บนเซิร์ฟเวอร์จริง ผมใส่ฐานข้อมูล PostgreSQL กับแอปไว้ใน Podman Pod แล้วรันทุกอย่างบนพอร์ต localhost ที่มากกว่า 5000 โดยให้ Caddy ทำหน้าที่เป็น reverse proxy ที่พอร์ต 443
ใช้ systemd Timer ดัมพ์ฐานข้อมูลทั้งหมดไปไว้ในไดเรกทอรีเดียวทุกวันเวลา 16:55
จากนั้น DejaDup [1] จะสำรองข้อมูล
$HOMEไปยัง HDD ภายนอกอัตโนมัติทุกวันเวลา 17:00 โดยไม่รวมไฟล์แคช แต่รวม database dumpOS คือ Debian พร้อม GNOME Core [2] และกฎของ firewalld อนุญาตเฉพาะ 80, 443 และพอร์ต SSH แบบกำหนดเอง
SSH ใช้ key-based และปิด password authentication
มันเป็นวิธีที่น่าเบื่อที่สุด แต่ก็ใช้งานได้ดีเฉย ๆ
1 - https://flathub.org/apps/org.gnome.DejaDup
2 - https://packages.debian.org/bookworm/gnome-core
ช่วงนี้ผมใช้ Dokku ลงบนเซิร์ฟเวอร์เครื่องเดียว
จัดการง่าย นักพัฒนาสามารถ deploy ได้แบบ Heroku-style แค่
git pushและมีปลั๊กอินเยอะมากจนเพิ่มฐานข้อมูลหรือตั้งค่า HTTPS ได้ภายในไม่เกิน 10 วินาทีgit pushทั้งการเพิ่มแอป เพิ่มฐานข้อมูล จัดการ environment variables และจัดการโดเมน ล้วนตรงไปตรงมาและเข้าใจง่ายมาก
ชอบโครงสร้างที่เรียบง่าย เลยรู้สึกว่าวิธีแบบนี้น่าจะทำงานด้วยได้อย่างเพลิดเพลิน
มีโอกาสสูงว่าน่าจะเพียงพอสำหรับ 99% ของบริการ
สำหรับการตั้งค่าเซิร์ฟเวอร์และสคริปต์ deploy น่าจะใช้ Ansible
แบบนั้นก็อาจช่วยให้ตัวเซิร์ฟเวอร์ถูกจัดทำเป็นเอกสารไปด้วย และสคริปต์ deploy ก็เรียบง่ายขึ้น
แต่ก็คงไม่ได้หลีกเลี่ยงการเข้าไปที่เซิร์ฟเวอร์โดยตรงเพื่อดีบักหรือตรวจสอบ
สคริปต์ของฉันแทบไม่เปลี่ยนเลยตลอด 7 ปีที่ผ่านมา แต่ Ansible ช้าและมีแนวโน้มต้องคอยดูแลหลายไฟล์อยู่เรื่อย ๆ
ในแง่ของการดีบัก อาจเปิดเผย app log ผ่าน endpoint ที่ป้องกันด้วยรหัสผ่าน บน nginx ก็ได้
บางทีก็ดูเหมือนเราจะลืมไปว่า แม้ก่อนย้ายขึ้นคลาวด์ CI/CD และการจัดการเซิร์ฟเวอร์อย่างมีประสิทธิภาพก็เป็นแนวปฏิบัติที่พบได้ทั่วไปอยู่แล้ว
เกี่ยวกับแนวทางการเขียนซอฟต์แวร์เซิร์ฟเวอร์ด้วย Rust แล้วทำ static link จากนั้นคอมไพล์ทุกอย่างอย่าง HTML, CSS, config, secret ฯลฯ ใส่เข้าไปในไบนารีทั้งหมด ช่วงนี้ฉันก็ทำแบบนี้ใน Go อยู่ และชอบมากเพราะมันทำให้ทั้งการเขียนและ deploy ซอฟต์แวร์ที่พึ่งพา static file ง่ายขึ้นมาก
การใช้ environment variable หรือ config สำหรับ secret น่าจะใกล้เคียงกับมาตรฐานมากกว่า และแม้จะเพิ่มขั้นตอนก่อนรันมาอีกหนึ่งอย่าง แต่ก็ช่วยเลี่ยงสถานการณ์ที่แชร์ไบนารีไปแล้วลืมว่ามี secret อยู่ข้างใน
การแตกไบนารีแล้วค้นหาสตริงทำได้ค่อนข้างง่าย
แต่การใส่ static frontend asset และค่า config เริ่มต้นเข้าไปด้วยกันถือเป็นข้อดีมาก
การ cross-compile ไปเป็น Rust โดยเฉพาะจาก Mac ไป Linux ค่อนข้างเจ็บปวด ในขณะที่ Go เป็นเรื่องเล็กน้อยและมีมาให้ในเครื่องมือ
goอยู่แล้วมันช่วยลดแรงเสียดทานเวลาจะปิดงาน side project แล้วเอาไป deploy ได้ง่ายมาก
แต่มีคำถามอยู่อย่างหนึ่ง ในบทความบอกว่า “รับใบรับรอง Let’s Encrypt ด้วย certbot และมีการต่ออายุอัตโนมัติด้วย” แต่ฉันใช้ โครงสร้างข้ามรีเจียน ที่มีเซิร์ฟเวอร์สองเครื่องและ geo-DNS ทำให้ certbot ทำงานได้แค่บนเซิร์ฟเวอร์ในสหรัฐฯ และต้องคัดลอกใบรับรองไปยังเซิร์ฟเวอร์ยุโรปด้วยตนเอง
มีวิธีแก้เรื่องนี้ไหม?
คำอธิบายของ ClickHouse Playground อยู่ที่นี่: https://ghe.clickhouse.tech/
ให้บริการเว็บแอปจากบริการที่คอมไพล์แบบ static ตัวเดียวกันกับที่ให้ backend API
หลังจากรัน
npm buildใน CI แล้วฝังผลลัพธ์เข้าไป ก็ทำให้การทดสอบบนเครื่องหรือเปิด demo instance ทำได้ง่ายมาก