บล็อกของฉัน // คลังเก็บข้อมูลดิจิทัล

ความคิด โปรเจกต์ และบันทึกทางเทคนิค

เดิมทีการตั้งค่าบล็อกของผมถูกวางแผนให้เป็น โปรเจกต์ IPv6 ล้วนผ่าน WireGuard เนื่องจากรันอยู่บนโฮมเซิร์ฟเวอร์ (คุณสามารถขอที่อยู่ IPv6 ได้ฟรีที่ route64.org) เพื่อเพิ่มความสามารถในการเข้าถึง ตอนนี้ผมได้เพิ่ม IPv4 Proxy ภายนอกเข้ามาแล้ว (ขอบคุณ @Larvitz)

อย่างไรก็ตาม มีปัญหาเรื่อง SSL เกิดขึ้นทันที: เนื่องจากในตอนแรกทั้งเรคคอร์ด A และ AAAA วิ่งผ่าน Proxy ทำให้การตรวจสอบความถูกต้อง (Validation) ของ Let's Encrypt บนเซิร์ฟเวอร์ของผมล้มเหลว

วิธีแก้ปัญหา: "IPv6-Hack"

วิธีแก้คือการกำหนดให้ AAAA-Record ชี้ไปยัง IP ของ WireGuard บนเซิร์ฟเวอร์ของผมโดยตรง แทนที่จะส่งผ่าน Proxy เหมือนเดิม

  • โดเมน: blog.burningboard.org
  • A-Record (Proxy): 194.28.98.217
  • AAAA-Record (Server): 2a11:6c7:f05:a8::2 (WireGuard)

ด้วยการชี้ AAAA-Record ไปยัง IP ของ WireGuard โดยตรง Let’s Encrypt จะยังคงเข้าถึงเซิร์ฟเวอร์ของผมได้โดยตรงผ่าน IPv6 (เนื่องจากปกติแล้ว AAAA-Record จะได้รับความสำคัญก่อน) และออกใบรับรอง SSL ให้ ส่วนทราฟฟิก IPv4 จะถูกส่งต่อจาก Proxy มายังผมในรูปแบบที่เข้ารหัสไว้

การกำหนดค่าขั้นสุดท้าย

เพื่อให้การสื่อสารทำงานได้อย่างราบรื่น เราจำเป็นต้องปรับแต่งเซิร์ฟเวอร์ Caddy:

1. บนเซิร์ฟเวอร์ของผม (NixOS, blog.nix)

เพื่อให้ IP จริงของผู้เข้าชมส่งมาถึงอย่างถูกต้องและไม่ถูกเขียนทับด้วย IP ของ Proxy เราต้องกำหนดให้ Proxy นั้นเป็นที่น่าเชื่อถือ (trusted):

services.caddy.globalConfig = ''
  servers {
      trusted_proxies static 2a06:9801:1c:1000::10
  }
'';

2. บน Proxy ภายนอก (Caddy)

เพื่อให้ Proxy ติดต่อกับเซิร์ฟเวอร์ของผมผ่าน HTTPS ได้อย่างถูกต้อง จะต้องส่งชื่อโฮสต์ (SNI) ไปด้วย:

reverse_proxy [https://[2a11:6c7:f05:a8::2]:443](https://[2a11:6c7:f05:a8::2]:443) {
    header_up Host {host}
    transport http {
        tls_server_name blog.burningboard.org
    }
}

ตอนนี้บล็อกสามารถเข้าถึงได้ทั้งผ่าน IPv4 และ IPv6 มีการเข้ารหัสที่ปลอดภัย และ IP ที่บ้านของผมก็ยังคงเป็นส่วนตัวอยู่! 🚀

สิ่งสำคัญที่สุดก่อนอื่นเลย: ไฟล์ Markdown ที่คุ้นเคยยังคงเป็นพื้นฐานเหมือนเดิม – ผมเป็นแฟนตัวยงของโซลูชันที่เรียบง่ายแบบนี้ แต่เบื้องหลังมีการเปลี่ยนแปลงไปเยอะมาก:

ผมได้ปรับแต่งการตั้งค่าไปหลายอย่าง:

📂 ไฟล์ MD: โครงสร้างบล็อกยังคงเรียบง่ายบนพื้นฐานของ Markdown

🌍 เป็นสากลยิ่งกว่าที่เคย: ตอนนี้บล็อกของผมรองรับการแปลถึง 43 ภาษา ใช่แล้ว รวมภาษาคลิงออนด้วย! 🖖 (Qapla'!)

เดิมทีผมวางแผนจะให้มีการแปลแบบเรียลไทม์อัตโนมัติทั้งหมดโดยอิงจากการตรวจจับภาษาของเบราว์เซอร์ สปอยล์เลยครับ: มันทำงานได้แค่บางส่วนเท่านั้น จะเห็นได้ว่า: AI นั้นน่าทึ่งมาก แต่ก็ยังไม่ถึงจุดที่เราต้องการให้เป็นเสียทีเดียว

วิธีแก้ปัญหา: ตอนนี้ผมใช้วิธีแปลทุกบทความล่วงหน้าเป็น ทุก ภาษาที่กำหนดไว้ ซึ่งส่งผลดีต่อการทำอันดับในเครื่องมือค้นหา (SEO) มากกว่าด้วย หากการตรวจจับอัตโนมัติไม่ทำงาน คุณสามารถเลือกภาษาที่ต้องการได้ด้วยตนเองผ่านไอคอนรูปโลก ซึ่งจะถูกบันทึกไว้ผ่านคุกกี้อย่างง่ายดาย

ตอนนี้การแปลดำเนินการด้วย Gemini 3 Flash ซึ่งให้ผลลัพธ์ที่ดีอย่างน่าประหลาดใจ อย่างไรก็ตาม เรายังต้องคอยตรวจสอบการทำงานของ AI อย่างใกล้ชิด: ในการรันแบบกลุ่ม (Bulk) ครั้งแรก แท็กต่างๆ ถูกแปลไปด้วยโดยผิดพลาด ซึ่งแน่นอนว่าไม่ได้วางแผนไว้แบบนั้น

โค้ดยังคงมีให้ใช้งาน (ถ้าสนใจก็ส่งข้อความมาหาผมได้เลย) 👍 แต่โปรดทราบว่าตอนนี้ระบบจำเป็นต้องใช้ Gemini API Key 🔑 ของตัวเองแล้ว

ฉันตัดสินใจเปลี่ยนบล็อกของฉันจาก WriteFreely มาเป็นระบบที่พัฒนาขึ้นเองอย่างรวดเร็ว: MD-Blog (แน่นอนว่า MD ย่อมาจาก Markdown) จุดเริ่มต้นเกิดจากการอัปเดตระบบเก่าที่ล้มเหลว แต่สุดท้ายมันกลับเป็นแรงผลักดันที่สมบูรณ์แบบในการทำให้ทุกอย่างง่ายขึ้นอย่างสิ้นเชิง และทำให้ฉันสามารถ ควบคุมการออกแบบ ได้อย่างเต็มที่

หัวใจสำคัญคือไฟล์ Markdown ง่ายๆ ในโฟลเดอร์ data/ ซึ่งจะถูกแปลงเป็น HTML ที่ทันสมัยในขณะประมวลผล ผลลัพธ์ที่ได้นั้นรวดเร็วมาก ไม่ต้องใช้ฐานข้อมูล และด้วยระบบการออกแบบของตัวเอง (รวมถึง Dark Mode) ตอนนี้มันจึงดูตรงตามที่ฉันจินตนาการไว้ทุกประการ แถมยังมี ปุ่มแชร์ไปยัง Mastodon ที่ทันสมัยติดตั้งมาให้ในตัวเลยด้วย

หากใครสนใจโค้ดหรือการตั้งค่าที่เรียบง่ายนี้ สามารถติดต่อฉันผ่าน Mastodon ได้เลย!

อันที่จริงแนวคิดเบื้องหลัง #Winboat นั้นยอดเยี่ยมมาก แต่การนำไปใช้งานจริงในปัจจุบันดูเหมือนจะยังไม่ค่อยเสถียรนัก ตั้งแต่ติดตั้งเมื่อต้นปีที่ผ่านมา ระบบก็ทำงานได้ดีมาตลอด แต่ทว่าวันนี้ซอฟต์แวร์กลับหยุดทำงานไปโดยสิ้นเชิง

จู่ๆ อิมเมจก็แจ้งเตือนว่าหน่วยความจำ (RAM) ไม่เพียงพอ ผมพยายามแก้ไขปัญหาด้วยตัวเองแล้ว แต่นั่นกลับทำให้ระบบใช้งานไม่ได้อย่างถาวร แทนที่จะเสียเวลาไปกับการหาสาเหตุของปัญหา ผมจึงตัดสินใจเปลี่ยนมาใช้ Dockurr Windows-Image โดยตรง ซึ่งจริงๆ แล้วมันคือพื้นฐานทางเทคนิคของ Winboat นั่นเอง

Fehlermeldung

1. การเตรียมการ

เนื่องจากผมใช้ Podman ผมจึงเริ่มจากการสร้างไดเรกทอรีที่จำเป็นบนระบบโฮสต์ของผมก่อน เพื่อให้ข้อมูลยังคงอยู่ครบถ้วนในกรณีที่ต้องสร้างคอนเทนเนอร์ใหม่:

mkdir -p $HOME/Windows/System
mkdir -p $HOME/Windows/Shared

2. คำสั่งเริ่มต้น

ข้อควรระวัง: ให้แทนที่ตัวยึดตำแหน่ง (placeholder) ในตัวแปร -e USERNAME และ -e PASSWORD ด้วยข้อมูลการเข้าสู่ระบบส่วนตัวของคุณ

podman run -d \
  --name windows \
  -p 8006:8006 \
  --device=/dev/kvm \
  --cap-add NET_ADMIN \
  -e RAM_SIZE="8G" \
  -e USERNAME="Carsten" \
  -e PASSWORD="1234" \
  -e LANGUAGE="German" \
  -v $HOME/Windows/System:/storage:Z \
  -v $HOME/Windows/Shared:/shared:Z \
  --stop-timeout 120 \
  dockurr/windows

ทันทีที่คอนเทนเนอร์ทำงาน คุณสามารถเข้าถึงอินสแตนซ์ Windows ได้โดยตรงผ่านเบราว์เซอร์ของคุณ:

http://127.0.0.1:8006

Laufender Container

3. สรุป

ผมต้องรันคำสั่งข้างต้นเพียงครั้งเดียวเท่านั้น ในการใช้งานประจำวัน ตอนนี้คุณสามารถควบคุมสภาพแวดล้อม Windows ได้อย่างสะดวกสบายผ่านคำสั่งลัดเหล่านี้:

  • เริ่มทำงาน: podman start windows
  • หยุดทำงาน: podman stop windows (หรือสั่งปิดเครื่องจากภายใน Windows โดยตรง)
  • ตรวจสอบสถานะ: podman ps -a

ลิงก์เพิ่มเติม:

ผมได้ติดตั้งบล็อกส่วนตัวของตัวเองขึ้นมา — โดยมีจุดประสงค์หลักคือเพื่อทำความรู้จักกับ #NixOS ให้มากขึ้น ซึ่งก็น่าประหลาดใจที่ทุกอย่างดำเนินไปอย่างราบรื่นและไม่ซับซ้อนเลย

WriteFreely ตอบโจทย์นี้ได้ดีมาก ทั้งความเรียบง่าย ติดตั้งได้รวดเร็ว และไม่มีฟีเจอร์ที่เกินความจำเป็น เหมาะอย่างยิ่งสำหรับการเริ่มต้นเขียนและเรียนรู้สิ่งใหม่ๆ ไปพร้อมกัน การตั้งค่าก็ดูสะอาดตาและเข้าใจง่าย เพียงแค่กำหนดตัวเลือกไม่กี่อย่าง เตรียมไดเรกทอรี ตั้งค่า Reverse Proxy ไว้ข้างหน้า เท่านี้ก็เรียบร้อย

นี่คือการตั้งค่า NixOS ปัจจุบันของผมสำหรับโปรเจกต์นี้:

{ config, pkgs, ... }:

{
  services.writefreely = {
    enable = true;
    host = "blog.burningboard.org"; 
    settings = {
      server = {
        port = 8080;
        min_log_level = "debug";
      };
      app = {
        host = "https://blog.burningboard.org";
        single_user = true;
        landing = "/read";
        wf_modesty = true;
        federation = true;
        public_stats = true;
        theme = "write";
      };
    };
    stateDir = "/opt/writefreely";
  };

  # แก้ไขสำหรับการสร้างคีย์ ActivityPub: Federation จำเป็นต้องใช้ openssl
  systemd.services.writefreely.path = [ pkgs.openssl ];

  # สร้างไดเรกทอรีข้อมูลโดยอัตโนมัติพร้อมกำหนดสิทธิ์ที่ถูกต้อง
  systemd.tmpfiles.rules = [
    "d /opt/writefreely 0700 writefreely writefreely -"
  ];

  services.caddy.virtualHosts."blog.burningboard.org".extraConfig = ''
    reverse_proxy 127.0.0.1:8080 {
      header_up Host {host}
      header_up X-Real-IP {remote_host}
      header_up X-Forwarded-For {remote_host}
      header_up X-Forwarded-Proto {scheme}
    }
  '';
}

หลักๆ ก็มีเพียงเท่านี้ NixOS ช่วยให้การตั้งค่าบริการต่างๆ เป็นไปอย่างเป็นระเบียบและสามารถทำซ้ำได้ง่ายจริงๆ