EST. 2026 — บันทึกงานเซิร์ฟเวอร์จริง SYSADMIN · SECURITY · AI · DIRECTADMIN เล่มที่ 01
THE SYSADMIN ALMANAC
หน้าหลัก / Security / ย้าย DA ตอนจบ — security fixes + hardening หลังเครื่องนิ่ง
Security — ซีรีส์ ย้าย DA CentOS7 -> Debian12 [5]

ย้าย DA ตอนจบ — security fixes + hardening หลังเครื่องนิ่ง

โดย Ton-Or ·20 พ.ค. 2026·อ่าน 12 นาที
ย้าย DA ตอนจบ — security fixes + hardening หลังเครื่องนิ่ง

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

ตอนที่ 1 ถึง 4 ของซีรีส์เล่าตั้งแต่วางแผนย้าย CentOS 7 ไป Debian 12, การ restore DirectAdmin ข้ามดิสโทร, แก้ stack ที่เปลี่ยนไป (pure-ftpd ไป proftpd, spamassassin ไป rspamd) ยันเครื่องขึ้นนิ่ง ใครยังไม่ได้อ่านย้อนไปดูจาก index ของซีรีส์ได้

ตอนนี้คือตอนที่ผมตั้งใจเก็บไว้ปิดท้าย เพราะมันไม่ใช่งาน migration ตรงๆ แต่เป็นงาน security fixes กับ hardening ที่ผมทำหลังจากเครื่องนิ่งหมดแล้ว ของบางตัวเป็นช่องโหว่จริงที่หลายคนเขียน config ผิดมาตลอดโดยไม่รู้ตัว ผมว่าตรงนี้แชร์ออกมาน่าจะมีประโยชน์ที่สุดในซีรีส์

ลำดับงาน hardening หลังเครื่องนิ่งsudoerswildcard CVE->OpenSSLSECLEVEL 0→2->ModSecexclusion before CRS->CSFcsfpost drop-in->DA-survival5 ชั้น

sudoers wildcard path traversal — อันที่อยากเตือนที่สุด

อันนี้ถ้าใครยังใช้ sudoers entry ที่มี wildcard * อยู่ ผมแนะนำให้ตรวจด่วน เพราะตอนแรกของผมเองก็เขียนแบบนี้หลายบรรทัด

ลองดู entry ตัวอย่าง — เผินๆ มันดูปลอดภัยมาก เพราะจำกัดให้รัน cat ได้เฉพาะไฟล์ใน directory เดียว

user ALL=(root) NOPASSWD: /usr/bin/cat /var/spool/cron/crontabs/*

ผมเข้าใจมาตลอดว่า * ตรงนี้คือ "ไฟล์ไหนก็ได้ในโฟลเดอร์นี้" แต่พอเอา bot user ที่ได้สิทธิ์นี้ไปลองยิงดู ผลที่ออกมาทำผมหนาว

sudo -u bot_user sudo -n cat /var/spool/cron/crontabs/../../../../etc/passwd
# RESULT: เนื้อหา /etc/passwd ออกมาเฉยเลย

มันอ่าน /etc/passwd ออกมาได้ ทั้งที่ entry บอกชัดว่าให้อ่านได้แค่ใน crontabs/ เท่านั้น

สาเหตุคือ glob ของ sudoers ไม่เหมือน glob ของ shell ใน shell ดอกจัน * จะ ไม่ match เครื่องหมาย / แต่ใน sudoers ดอกจัน match / ด้วย ดังนั้น crontabs/* ใน sudoers จึงครอบคลุม crontabs/../../../../etc/passwd ไปด้วย กลายเป็น path traversal ที่ traverse ../ ออกไปอ่านไฟล์อะไรก็ได้บนเครื่อง ในนามของ root

แบบเดิม: ดอกจันลอยcrontabs/*crontabs/../../../../etc/passwdผ่านอ่านไฟล์ทั้งระบบเป็น rootแบบแก้: character class[a-z][a-z0-9_-]*crontabs/../../../../etc/passwdไม่ matchclass ไม่มี / และ . ให้ traverseใน sudoers ดอกจัน match เครื่องหมาย / ด้วย ต่างจาก shell globที่เขียนใน sudoerspath ที่ยิงเข้ามาผล
ดอกจันใน sudoers ครอบเครื่องหมาย / ไปด้วย path ที่มี ../ หลุดออกนอกโฟลเดอร์ได้ ส่วน class ที่ไม่มี / กับ . ปิดทางนั้นสนิท
ช่องโหว่จริง

sudoers wildcard * match เครื่องหมาย / ต่างจาก shell glob ทำให้ entry ที่ดูจำกัดวงแค่โฟลเดอร์เดียว ถูก traverse ด้วย ../ ออกไปอ่านไฟล์ทั้งระบบได้ ใครให้ bot/script รัน sudo NOPASSWD ผ่าน wildcard ควรไปตรวจทุก entry

วิธีแก้คือเลิกใช้ดอกจันลอยๆ แล้วเปลี่ยนเป็น character class ที่กันตัว / กับ . ออกไปเลย

- user ALL=(root) NOPASSWD: /usr/bin/cat /var/spool/cron/crontabs/*
+ user ALL=(root) NOPASSWD: /usr/bin/cat /var/spool/cron/crontabs/[a-z][a-z0-9_-]*

[a-z][a-z0-9_-]* แปลว่า ตัวแรกต้องเป็นพิมพ์เล็ก a-z แล้วตามด้วย alphanumeric หรือ underscore หรือ dash เท่านั้น ไม่มี / ไม่มี . อยู่ในชุดอักขระที่อนุญาตเลย เมื่อ pattern ไม่มี / ก็ traverse ../ ไม่ได้ ปิดช่องนี้ได้สนิท

พอเจอแบบนี้ผมก็ไล่ apply pattern เดียวกันกับทุก entry ที่มี wildcard ในระบบ ที่ใช้บ่อยๆ ก็พวกอ่าน usage ของ user, ดูขนาดโฮม, เช็ควันหมดอายุ cert

/usr/bin/cat /usr/local/directadmin/data/users/[a-z][a-z0-9_-]*/user.usage
/usr/bin/du -sh /home/[a-z][a-z0-9_-]*/
/usr/bin/openssl x509 -enddate -noout -in /etc/letsencrypt/live/[a-z0-9][a-z0-9._-]*/cert.pem

ตรงบรรทัด cert ผมยอมให้มี . กับ _ ใน class ได้ ([a-z0-9._-]) เพราะชื่อโฟลเดอร์ของ Let's Encrypt เป็นโดเมนซึ่งมีจุดอยู่แล้ว แต่ตัวแรกบังคับเป็น [a-z0-9] เพื่อไม่ให้เริ่มด้วยจุด — กัน . นำหน้าที่จะกลายเป็น ../ ได้ ของผมตอนแรกมี wildcard * ลอยๆ หลายตัว เพิ่งมา refactor ทิ้งหมดหลังรู้เรื่องนี้

OpenSSL SECLEVEL — แผนรัดเข็มขัดระยะยาว

ตอนที่ 4 ผมเปิด SECLEVEL=0 ไว้ตอนแรกเพื่อให้ web stack boot ขึ้นมาได้ เพราะ Debian 12 ตั้ง default crypto policy เข้มกว่า CentOS 7 มาก cert เก่าที่ยังมี SHA1 ในห่วงโซ่ certificate เลยถูกปฏิเสธ เว็บ user หลายรายขึ้นไม่ได้ ผมเลยกด SECLEVEL ลงเป็น 0 ชั่วคราวให้ทุกอย่างกลับมาทำงานก่อน

แต่ SECLEVEL=0 คือ insecure mode มันยอมรับ crypto อ่อนๆ หมด อยู่แบบนี้ระยะยาวไม่ได้ ต้องมีแผนไล่ขยับกลับขึ้นไป ผมวางเป็นขั้นๆ ไว้แบบนี้

ชั่วคราว

SECLEVEL=0

  • ยอมรับ crypto อ่อนหมด รวม SHA1
  • ใช้แค่ให้ stack boot ขึ้น
  • ห้ามอยู่ถาวร
เป้าหมาย

SECLEVEL=2

  • default ของ Debian 12
  • ปฏิเสธ SHA1 ทั้ง end-entity และ CA
  • ปลายทางที่อยากไปให้ถึง

ขั้นตอนที่ผมวางไว้คือ

  • ใช้ Let's Encrypt renewal hook ให้ reissue cert ของทุก user ใหม่ ทุก 60 ถึง 90 วัน cert ที่ออกใหม่จะใช้ SHA256 ทั้งสาย ไม่มี SHA1 หลงเหลือ
  • track ว่า cert ไหนยังมี SHA1 ใน chain อยู่ ใช้ openssl x509 ไล่ verify ทีละใบ จะได้รู้ว่าเหลือ legacy อีกกี่ใบ
  • พอ cert SHA1 หมดแล้ว ค่อยขยับเป็น SECLEVEL=1 ซึ่งยังอนุญาต SHA1 ที่ตัว end-entity cert ได้ แต่ไม่ยอมให้ CA cert เป็น SHA1
  • เป้าหมายระยะยาวคือ SECLEVEL=2 ตาม default ของ Debian 12 ซึ่งปฏิเสธ SHA1 หมดทั้งสาย

ของผมตอนนี้อยู่ที่ SECLEVEL=0 มาสามเดือนแล้ว เหลือ legacy cert อีกแค่ใบเดียวที่ยังไม่ได้ reissue ใกล้เคลียร์หมด พอใบนั้นหมดอายุแล้วผมจะขยับเป็น SECLEVEL=1 ทันที แล้วค่อยไต่ขึ้น 2 ต่อ จุดสำคัญคืออย่าลืมว่าตัวเองเปิด insecure mode ไว้ ต้องมี checklist หรือ reminder ไม่งั้นเปิดทิ้งยาวเป็นปีโดยไม่รู้ตัว

ModSecurity exclusion — ต้องโหลดก่อน CRS ถึงจะทัน

อันนี้เป็นกับดักที่ทำผมงงอยู่พักหนึ่ง DirectAdmin มีที่เก็บ custom ModSec rules ของ admin อยู่ที่ /usr/local/directadmin/data/admin/modsecurity_rules ซึ่งดูเหมือนเป็นที่ที่ควรใส่ exclusion แต่ปัญหาคือไฟล์ตรงนี้มันถูกโหลด หลัง OWASP CRS

พอ CRS โหลดก่อน rule ของมันก็ fire ไปแล้ว request โดน block ไปก่อนที่ exclusion ของเราจะมีโอกาสทำงาน ใส่ยังไงก็ไม่ติด เพราะมันสายเกินไป

ลำดับการโหลดของ ModSecurity บนลงล่าง1 exclusion ของเราREQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf2 OWASP CRS3 modsecurity_rules ของ admin DA/usr/local/directadmin/data/admin/modsecurity_rulesปิด CRS rule ได้ทันrule fire แล้ว request โดน blockโหลดหลัง CRS ใส่ยังไงก็ไม่ติดเลข 900 ตามคอนเวนชันของ CRS ทำให้มาก่อนชุด rule หลัก
exclusion ต้องอยู่ในไฟล์ที่โหลดก่อน CRS ถ้าวางที่ไฟล์ของ admin DA ซึ่งโหลดหลัง CRS rule จะ fire ไปแล้ว exclusion เลยไม่มีผล
ลำดับการโหลดสำคัญ

exclusion ที่จะปิด CRS rule ตัวไหน ต้องถูกโหลด ก่อน CRS ถ้าวางไว้ในที่ที่โหลดทีหลัง CRS rule จะ fire ไปแล้ว exclusion ไม่มีผล ต้องไปวางในไฟล์ที่ stack โหลดก่อน CRS

วิธีแก้คือเอา exclusion ไปวางในไฟล์ที่ถูกโหลดก่อน CRS โดยตรง ใช้ชื่อ REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf ตามคอนเวนชันของ CRS เอง เลข 900 ทำให้มันมาก่อนชุด rule หลักที่เลขสูงกว่า

cat > /etc/modsecurity.d/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf <<'EOF'
SecRule REMOTE_ADDR "@ipMatch 203.0.113.99" \
    "id:99001,phase:1,pass,nolog,ctl:ruleRemoveById=920350"

SecAction "id:99002,phase:1,pass,nolog,ctl:ruleRemoveById=920450"

SecRule REQUEST_URI "@beginsWith /phpMyAdmin/" \
    "id:99003,phase:1,pass,nolog,ctl:ruleRemoveById=932380"
EOF

nginx -t && systemctl reload nginx

แต่ละบรรทัดคือ exclusion ที่ต่างกัน — ตัวแรกยกเว้น CRS rule 920350 ให้ IP ที่เชื่อถือได้ (placeholder 203.0.113.99 แทน IP จริง), ตัวที่สองปิด rule 920450 แบบ unconditional, ตัวที่สามปิด rule 932380 เฉพาะ request ที่เข้า phpMyAdmin จำไว้ว่า id ของ rule เราต้องไม่ชน CRS อย่าใช้เลขในช่วงที่ CRS จองไว้ ผมเลือกใช้ช่วง 99xxx ซึ่งว่างชัวร์ ปิดท้ายด้วย nginx -t ทุกครั้งก่อน reload กัน syntax พังแล้วเว็บล่มทั้งเครื่อง

Self-heal — ให้มันรอด DA update เอง

ปัญหาต่อมาคือ DA update หรือ CustomBuild rebuild อาจ wipe /etc/modsecurity.d/ ทั้งโฟลเดอร์ exclusion ที่เราอุตส่าห์วางไว้หายเกลี้ยง แล้วเราก็ไม่รู้ตัวจนกว่าจะมี request ดีๆ โดน block ผมเลยทำ cron daily ไว้คอยเช็คแล้ว restore กลับให้อัตโนมัติ

cat > /usr/local/directadmin/scripts/custom/check_modsec_exclusions.sh <<'EOF'
#!/bin/bash
set -e
TARGET=/etc/modsecurity.d/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
if [ -f "$TARGET" ] && grep -q 'id:99001' "$TARGET" && \
   grep -q 'id:99002' "$TARGET" && grep -q 'id:99003' "$TARGET"; then
    exit 0
fi
# ถ้าไฟล์หายหรือ rule ไม่ครบ → เขียน exclusion กลับลงไปใหม่ตรงนี้
EOF
chmod 755 /usr/local/directadmin/scripts/custom/check_modsec_exclusions.sh

echo '20 4 * * * root /usr/local/directadmin/scripts/custom/check_modsec_exclusions.sh' \
    > /etc/cron.d/modsec-exclusions-check

logic ง่ายๆ คือ ถ้าไฟล์ยังอยู่และมี id ครบทั้งสาม ก็ exit 0 ไม่ทำอะไร ถ้าไฟล์หายหรือ rule ไม่ครบ ค่อยเขียนกลับลงไปใหม่ ตั้ง cron รันทุกวันตอนตีสี่ยี่สิบ DA จะ wipe ตอนไหนก็ได้ ไฟล์ก็จะกลับมาภายในไม่เกินหนึ่งวัน

csfpost.sh drop-in — เลี่ยงกับดัก path ที่ตายเงียบ

ตอนที่ 4 ผมเจอปัญหาข้อ 16 ของซีรีส์เรื่อง CSF กับ csfpost.sh เรื่องคือ CSF มันเช็คสอง path คือ /usr/local/csf/bin/csfpost.sh กับ /etc/csf/csfpost.sh แต่จะรันแค่ตัวเดียว ถ้าใครเผลอใส่ rule ไว้ทั้งสองที่ ตัวที่อยู่ /etc/csf/csfpost.sh จะตายเงียบ ไม่มี warning ไม่มี error อะไรเลย rule ที่เขียนไว้ก็ไม่ทำงาน กว่าจะรู้ว่าทำไม firewall rule ไม่ติดก็เสียเวลาไล่อยู่นาน

ผมแก้ถาวรด้วย drop-in pattern แทนที่จะยัด rule ลงไปในไฟล์เดียวยาวๆ ก็ทำไฟล์หลักให้ทำหน้าที่แค่ loop เรียกไฟล์ย่อยในโฟลเดอร์ drop-in

cat > /usr/local/csf/bin/csfpost.sh <<'EOF'
#!/bin/bash
set -u
DROPIN=/etc/csf/csfpost.d
[ -d "$DROPIN" ] || exit 0
for f in "$DROPIN"/*.sh; do
    [ -r "$f" ] || continue
    . "$f" || logger -t csfpost "FAIL: $f exited $?"
done
EOF
chmod 700 /usr/local/csf/bin/csfpost.sh

mkdir -p /etc/csf/csfpost.d
cat > /etc/csf/csfpost.d/10-allowout-da-users.sh <<'EOF'
for uid in 65534 1002 999; do
    iptables -C ALLOWOUT -p tcp -m owner --uid-owner $uid \
        -m conntrack --ctstate NEW -j ACCEPT 2>/dev/null \
        || iptables -I ALLOWOUT 1 -p tcp -m owner --uid-owner $uid \
           -m conntrack --ctstate NEW -j ACCEPT
done
EOF
chmod 755 /etc/csf/csfpost.d/*.sh

[ -f /etc/csf/csfpost.sh ] && mv /etc/csf/csfpost.sh /root/csfpost.sh.dead-bak

ตัว csfpost.sh หลักจะวนอ่านทุกไฟล์ .sh ใน /etc/csf/csfpost.d/ แล้ว source เข้ามาทีละตัว ถ้าตัวไหนพังก็ log ผ่าน logger ไว้ ไม่ทำให้ทั้งชุดตาย ส่วนไฟล์ย่อยตัวอย่างคือ allowout ให้ uid บางตัว และสังเกตว่าผมใช้ iptables -C เช็คก่อนว่ามี rule นี้อยู่แล้วไหม ถ้ายังไม่มีค่อย insert เป็น idempotent รันซ้ำกี่รอบก็ไม่เพิ่มซ้ำ ขั้นสุดท้ายย้ายไฟล์ /etc/csf/csfpost.sh ตัวเก่าออกไปเป็น backup กัน shadow ที่ทำให้สับสน

ประโยชน์ของ pattern นี้คือ พอจะเพิ่ม rule ใหม่ก็แค่ drop ไฟล์ใหม่ลงใน csfpost.d/ ไม่ต้องไปแก้ไฟล์เก่า ไม่มีความเสี่ยงเรื่อง shadow ระหว่างสอง path อีก จัดระเบียบ rule เป็นไฟล์ๆ ตามหน้าที่ได้ด้วย

5 ชั้นรอด DA update — แยก config ตามที่ DA แตะ/ไม่แตะ

หลังเจอ DA wipe ของหลายครั้ง ผมเลยนั่งจัดระเบียบ custom config ของตัวเองทั้งหมด แบ่งเป็น 5 ชั้นตามว่า DA จะ preserve หรือ overwrite มันยังไง ถ้าวาง config ถูกชั้น DA update หรือ CustomBuild rebuild จะไม่ทำลายอะไรเลย

5 ชั้น config ที่รอด DA updatescripts/customDA ไม่แตะ->templates/customvhost override->99-custom iniPHP override->cron.dself-heal->post hooksหลัง build
  • DA-preserved — /usr/local/directadmin/scripts/custom/ คือที่เก็บ custom hook ที่ DA สัญญาว่าจะไม่แตะเลย ของที่อยากให้คงอยู่แน่ๆ วางที่นี่
  • Template overrides — /usr/local/directadmin/data/templates/custom/ ใช้ override template ของ nginx/Apache vhost พอ DA rewrite config มันจะอ่าน template ในนี้แทนของ default
  • Numbered ini — ไฟล์ตั้งชื่อ 99-custom-*.ini สำหรับ override ค่า PHP เลข 99 นำหน้าทำให้โหลดทีหลังสุด ค่าจึงชนะ default และรอด ./build php_*
  • Self-healing cron — ไฟล์ใน /etc/cron.d/* ที่เรียก script ใน scripts/custom/ คอย re-apply rule ทุกวัน (แบบเดียวกับ ModSec self-heal ข้างบน) เผื่อ DA wipe อะไรไป
  • Post-build hooks — custombuild/custom/post.<target>.sh รันหลัง CustomBuild build เสร็จ ใช้ทำงานเก็บกวาดอย่าง strip การ listen บน TAB port ออก ฯลฯ

จัดให้ครบ 5 ชั้นนี้แล้ว ความกังวลเรื่อง DA update ลบ config ของเราจะหายไปเกือบหมด เพราะทุกชั้นมีกลไกอยู่รอดของมันเอง

2-Tier Incident Detection — จับเหตุทั้งเร็วและช้า

อีกอย่างที่ผมวางหลังเครื่องนิ่งคือระบบจับเหตุแบบสองชั้น เพราะ failure มีสองแบบ — แบบที่ดังทันที กับแบบที่เงียบๆ ค่อยๆ แย่ ใช้ตัวจับตัวเดียวไม่ครอบทั้งสอง

Tier 1

systemd OnFailure

  • จับเร็ว 1-2 วินาที
  • ผ่าน .service.d/onfailure.conf
  • ดักตอน service ตายทันที
Tier 2

Periodic poll

  • วน poll ทุก 60 วินาที
  • จับ failure แบบช้า/เงียบ
  • ดักเคสที่ไม่ trigger OnFailure

ตัว recovery script ที่ผมเขียน ผมตั้งใจให้มันระวังตัวมาก ไม่ใช่เจอปัญหาแล้ว restart มั่วๆ เพราะ DA build cycle เองก็ทำให้ service ดับๆ ติดๆ เป็นปกติ logic หลักๆ มีสี่ข้อ

  • 5-second debounce — เจอสัญญาณแล้วยังไม่รีบทำ รอ แล้ว re-check อีกที กรอง noise จาก DA build cycle ที่ทำให้เห็น service ดับชั่วคราว
  • CustomBuild detection — เช็คด้วย pgrep -af '/usr/local/directadmin/custombuild/build' ถ้าเจอว่ากำลัง build อยู่ ก็ skip recovery ไปเลย เพราะ service ดับตอนนั้นเป็นเรื่องปกติของการ build
  • Strict pattern matching — playbook จะ return non-zero ถ้า error ไม่ตรง pattern ที่รู้จัก ไม่เดาสุ่มแก้ เจออะไรแปลกใหม่ให้คนดู
  • No generic restart — ไม่มีการ restart แบบ "ลองดูก่อน" เพราะการ touch service โดยไม่รู้ root cause มันเสี่ยง อาจทำให้สถานการณ์แย่กว่าเดิม

บทเรียนสรุปทั้งซีรีส์

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

  • ลำดับสำคัญ — งานแก้ต้องทำตามลำดับที่ถูก ของผมคือ SECLEVEL ก่อน แล้วค่อย TAB-listen แล้วค่อย per-domain test แล้วค่อยแจ้ง user ห้ามรัน ./build rewrite_confs ซ้ำหลายรอบโดยหวังว่ามันจะแก้ปัญหาให้เอง ต้องไล่ fix root cause ก่อน
  • cross-distro migration เจอปัญหาเป็นชั้นๆ แน่นอน — คาดไว้เลยว่าจะเจอ 10 กว่าจุด เพราะ default value ของ OS เปลี่ยน, DA backward compat ไม่ 100%, stack ก็ต่างกัน (pure-ftpd ไป proftpd, spamassassin ไป rspamd) ไม่มีทางย้ายเรียบทุกอย่าง
  • customer comms — แจ้ง user ล่วงหน้าอย่างน้อย 3 วัน, ส่ง status update ทุก 30 นาทีระหว่าง cutover, และช่วง 24 ถึง 48 ชั่วโมงแรกต้อง response เร็ว อย่ารับปาก promise ว่า "ใช้ได้ทันที" เพราะมันไม่เคยทันทีจริง
  • document ทุกอย่าง — backup config ก่อนเปลี่ยนทุกครั้ง, จดคำสั่งจริงที่รันไว้, diff สถานะระบบก่อนกับหลัง จะได้รู้ว่าอะไรเปลี่ยนไปบ้าง
  • ระวัง secret หลุดโดยไม่ตั้งใจ — credential ใส่ .gitignore, search-replace IP/โดเมน/username ก่อน publish ทุกครั้ง, token ของ bot ส่งผ่าน config บน tmpfs อย่า hardcode ลงไฟล์
สภาพแวดล้อมที่ทดสอบ

ของพวกนี้ผมทำกับ DA 1.700/1.701 + Debian 12.7 + PVE 8.4 ใครใช้ DA Modern license แบบ subscription อาจไม่เจอบาง issue เพราะ DA support distro ใหม่ตรงๆ อยู่แล้ว

ถ้าใครจะข้ามดิสโทรแบบนี้ ผมแนะนำให้ทำ snapshot/backup ทุกชั้นก่อนเริ่ม อย่างน้อยสามชั้น — PVE snapshot, vzdump, แล้วก็ DA backup เผื่อพลาดตรงไหนจะได้ rollback กลับมาได้ทุกระดับ

ซีรีส์นี้ผมเล่าให้ฟังเป็นภาพรวมเป็นหลัก ของย่อยลึกๆ อย่าง pigz wrapper benchmark กับ safety analysis, DA dataskq architecture, csf-trusted-sweep ฉบับเต็ม, ZFS scrub กับงาน maintenance ระยะยาว, PHP 6-slot strategy หรือ ModSec3 + OWASP CRS tuning สำหรับร้านไทย ตรงไหนอยากเห็นลึกขึ้นบอกได้ ผมจะแยกเขียนเพิ่มเป็นเรื่องๆ

ครบซีรีส์แล้วครับ ตรงไหนตกหล่นหรือผิดเดี๋ยวผมมาแก้ ใครจะเอาไปปรับใช้ตามสภาพเครื่องตัวเองได้ตามสะดวก หลักการมันเหมือนกันหมด

อยากให้เราทำให้ไหม?

ให้เราช่วยติดตั้ง ตั้งค่า ย้ายระบบ หรือแก้ปัญหาเซิร์ฟเวอร์ เพื่อให้คุณมีเวลาไปทำงานที่สำคัญกว่า

คุยเรื่องงานกับเรา

เคยเจองานแบบนี้ไหม? ติดตรงไหน?

มาแลกวิธีกันต่อในบอร์ด LinuxThai

→ คุยต่อในบอร์ด

ความคิดเห็น 0

ยังไม่มีความคิดเห็น — เป็นคนแรกเลย