ย้าย Blog จาก GitHub Pages มาที่ DigitalOcean ตอน 1

Published on 8th November, 2016
  • #blog
  • #jekyll
  • #github
  • #letsencrypt

ตั้งแต่เปลี่ยนมาใช้ Jekyll แทน WordPress blog นี้ก็ถูกโฮสต์อยู่บน GitHub Pages มาตลอด โดยที่ใช้ custom domain armno.in.th แทน armno.github.io

มีประเด็นที่อยากจะปรับปรุงคือ

  1. Static resources อย่างไฟล์ CSS/JS รวมไปถึงรูปภาพต่างๆ มี expiration time (ใน HTTP headers) อยู่ที่ 10 นาที ซึ่งถือว่าสั้นมาก และเปลี่ยนค่าไม่ได้เพราะอยู่บน server ของ GitHub
  2. ไม่สามารถใช้ HTTPS กับ custom domain บน GitHub Pages ได้ ถ้าอยากใช้ต้องใช้ร่วมกับ Universal SSL ของ CloudFlare

เลยมีอยู่ช่วงนึงที่ผมปิด custom domain และเปลี่ยน URL จาก armno.in.th กลับไปเป็น armno.github.io เพียงเพื่อจุดประสงค์เดียว คือให้ใช้งานผ่าน HTTPS ได้ (แก้ปัญหาข้อ 2.) แต่ ณ ตอนนั้น GitHub Pages ยังไม่มี option Enforce HTTPS ทำให้เวลาเปิดเว็บจะสลับไปมาระหว่าง http กับ https ซึ่งดูแล้วก็แปลกๆ

option enforce https ใน repo settings

อีกอย่างก็ยังแก้ปัญหาข้อ 1. ไม่ได้ ก็เลยคิดว่าอยากจะลองย้าย blog จาก GitHub Pages ไปอยู่บน server ที่เช่าเองที่ DigitalOcean ดู โดยหวังผลคือ

  1. ใช้งานผ่าน HTTPS ได้ 100% บน domain armno.in.th (ด้วย Let’s Encrypt)
  2. สามารถควบคุมปัจจัยต่างๆ ที่เกี่ยวกับ performance ได้มากที่สุด ซึ่งบางอย่างนั้นจำเป็นต้องตั้งค่าที่ server (อย่างน้อยก็เซ็ต expire headers ของ static resource ได้เพื่อแก้ปัญหาข้อ 1. ข้างบน)
  3. Workflow ของการเขียน blog ต้องเหมือนเดิม คือต้องมีการ deploy อัตโนมัติทุกครั้งที่ push code ไปที่ master branch เหมือนตอนใช้ GitHub Pages

เอาล่ะ เริ่มเลย

สร้าง Droplet ใหม่บน DigitalOcean

Droplet ที่สร้างใหม่บน DigitalOcean เลือกเป็น Ubuntu 16.04 LTS ส่วน datacenter ก็เลือกที่สิงคโปร์

เนื่องจากผมเคยใช้ web server เพียงตัวเดียวคือ Apache ในครั้งนี้เลยถือโอกาสลองหาประสบการณ์ใหม่ ด้วยการเลือก nginx เป็น web server แทน ส่วน guide ก็หาเอาในเว็บ DigitalOcean มีเยอะ ทำตามง่าย ผมก็ตาม guide ทั้งสองด้านล่างเพื่อเซ็ต server + firewall รวมไปถึง nginx ด้วย

ส่วน DNS ก็เซ็ตให้ชี้ไปที่ IP address ของ server ใหม่นี้ ก็เหมือนกับการเซ็ต DNS ทั่วๆ ไป

Let’s Encrypt

Let’s Encrypt เป็น certificate authority (CA) จาก Linux Foundation และมี sponsor เป็นบริษัท IT ชั้นนำของโลก มีจุดประสงค์คือให้บริการ HTTPS ที่ฟรี ใช้งานง่าย และมีความปลอดภัยสูง

การเซ็ต certificate ของ Let’s Encrypt นั้น ถ้าเทียบกับ CA เจ้าอื่นแล้วถือว่าง่ายกว่ามาก และใช้เวลาเพียงนิดเดียว ขั้นตอนทั้งหมดสามารถทำได้ผ่าน command line interface วิธีการก็ดูได้จาก link ข้างล่างเลยครับ

หน้า home page ของ letsencrypt

auto-renew

Cert ของ Let’s Encrypt นั้นมีอายุแค่ 90 วันนับจากวันที่เริ่มใช้งาน ใน guide แนะนำว่าควรจะ renew cert ทุกๆ 60 วัน ซึ่งสามารถเซ็ต cronjob ให้รันทุกๆ 60 วันเพื่อรัน command letsencrypt ได้ หลังจากรัน renew แล้วก็ต้อง restart nginx เพื่อให้ webserver ใช้ cert ตัวใหม่ที่เพิ่ง renew ไป

$ crontab -e
30 2 * * 1 /usr/bin/letsencrypt renew >> /var/log/le-renew.log
35 2 * * 1 /bin/systemctl reload nginx

พอมาถึงตรงนี้ก็จะมีโดเมน armno.in.th ที่ใช้งานผ่าน HTTPS ได้ไปยาวๆ เลย ไม่ต้องกังวลว่าจะลืมต่ออายุ SSL ของ Let’s Encrypt ครับ

valid SSL ของ domain armno.in.th

เมื่อโดเมนพร้อมแล้ว ขั้นตอนต่อไปก็คือต้องทำ auto-deploy ของ Jekyll แบบของ GitHub Pages

Jekyll-hook

หลักการทำงานของ webhooks ใน GitHub คือ ทุกครั้งที่เรา push code ขึ้นไปที่ repo GitHub ก็จะส่ง HTTP POST request ไปยัง URL ที่เรากำหนดไว้ พร้อมกับข้อมูลต่างๆ ของ commit นั้นๆ นั่นหมายความว่า ก่อนอื่นเราต้องมี URL ที่ว่านี้ก่อน หน้าที่ของ URL นี้ก็คือเป็นตัวรับข้อมูลผ่านทาง POST request นั่นเอง

tool ที่ผมใช้คือ jekyll-hook เป็น web server ที่ทำจาก Express ร่วมกับ pm2 เป็นตัวจัดการ process ของ jekyll-hook อีกทีครับ

หน้าที่ของ jekyll-hook ก็คือ

Note - jekyll-hook ตอนนี้อยู่ในสถานะ no longer maintained ก็คือผู้พัฒนาหยุดทำต่อแล้ว เพราะมีวิธีอื่นที่ง่ายกว่า สามารถดูในจาก Deployment methods บนเว็บของ Jekyll ได้ ส่วนตัว tool เองยังใช้งานได้อยู่ครับ

หลังจากติดตั้งและเริ่มใช้งาน jekyll-hook บน server แล้ว จึงไปตั้งค่า webhook ใน settings ของ repo

Webhooks settings ของ repo

ทุกครั้งที่ผม push code ไปที่ master branch บน github repo รอเพียงไม่กี่วินาที blog ก็ update เหมือนตอนใช้ GitHub Pages ทุกประการ

Custom Domain กลับคืนมา

สร้างไฟล์ชื่อ CNAME ไว้ที่ root level ของ repo เพื่อให้ armno.github.io redirect ไปที่ armno.in.th ทำให้หน้าเพจเดิมๆ ที่ถูก google index ไว้ สามารถ redirect ไปที่ armno.in.th ได้อย่างถูกต้องครับ

Custom domain settings ของ repo

ถึงตอนนี้ ก็ได้ระบบ blog เดิม ที่เพิ่มเติมคืออยู่บน server DigitalOcean แบบที่ต้องการแล้ว

ต่อไป ตอนที่ 2 เป็นการ optimize performance หลังจากย้ายบ้านครับ