กลับไปที่บล็อก

SSH Permission Denied (publickey): วิธีแก้ที่แท้จริง

18 กันยายน 2569

ตีสองสิบ การ deploy หนึ่งตายลงบนบรรทัดที่ผมพิมพ์มานับพันครั้ง: ssh deploy@stagingPermission denied (publickey) key ไม่มีปัญหา แต่การยื่นเสนอต่างหากที่มี

TL;DR: Permission denied (publickey) หมายความว่าทุก key ที่ client ยื่นไปถูก server ปฏิเสธ — เป็นคำตัดสินของการเจรจา ไม่ใช่พิมพ์รหัสผ่านผิด วินิจฉัยด้วย ssh -vvv (key ไหนถูกยื่น) และ log ฝั่งเซิร์ฟเวอร์ journalctl -u ssh (key ไหนถูกปฏิเสธและเพราะอะไร) แล้วแก้หนึ่งในสี่สาเหตุ: user ผิด, key ไม่อยู่ใน authorized_keys, สิทธิ์เปิดกว้างเกิน, หรือ key ssh-rsa ที่ OpenSSH 8.8+ ปฏิเสธ ssh-copy-id กันการกลับมาซ้ำได้เกือบทั้งหมด

$ ssh -T [email protected]
[email protected]: Permission denied (publickey).

error นี้คือคำตัดสิน ไม่ใช่คำใบ้: ทุกอย่างในการยื่นเสนอถูกปฏิเสธ

ทำไม SSH ถึงบอกว่า “Permission denied (publickey)“?

การยืนยันด้วย public key คือการเจรจาแบบยื่นเสนอและปฏิเสธ client ยื่นทุก key ที่หาเจอ — identity จาก agent, จาก ~/.ssh/config, ชื่อไฟล์ดีฟอลต์ (id_ed25519, id_rsa) และทุกอย่างที่ส่งผ่าน -i เซิร์ฟเวอร์เทียบแต่ละคำเสนอกับ ~/.ssh/authorized_keys ของบัญชีปลายทาง เมื่อไม่มีตัวไหนตรง และการยืนยันด้วยรหัสผ่านถูกปิดหรือหมดทาง client จะพิมพ์บรรทัดเดียวที่วิศวกร devops ทุกคนจำขึ้นใจ

สองข้อเท็จจริงสำคัญกับการ debug หนึ่ง ข้อความไม่บอกว่าคุณชน user ตัวไหน — ครึ่งหนึ่งของทุกกรณีคือ key ที่สมบูรณ์แบบนั่งอยู่ใน authorized_keys ของบัญชีอื่น สอง เซิร์ฟเวอร์บอกสาเหตุไปแล้ว: sshd บันทึกคำตัดสินของทุกคำเสนอที่ถูกปฏิเสธ stack trace ฝั่ง client ที่ไม่มีใครขอแต่ทุกคนต้องมีคือ -vvv

รู้ได้อย่างไรว่า SSH ยื่น key ตัวไหนจริง ๆ?

ssh -vvv deploy@staging 2>&1 | grep -iE "offering|identity|denied|authentications"
# debug1: Offering public key: /home/you/.ssh/id_ed25519 RSA-SHA256 (explicit)
# debug1: Authentications that can continue: publickey
# deploy@staging: Permission denied (publickey).

อ่านสามบรรทัด: Offering public key (client เสนออะไร), Authentications that can continue (เซิร์ฟเวอร์ยังรับอะไร — ถ้า password ไม่อยู่ในรายการ prompt รหัสผ่านจะไม่มีวันมาถึง) และคำตัดสินสุดท้าย ถ้า key ที่คุณตั้งใจใช้ไม่เคยโผล่ในรายการยื่นเสนอ ปัญหาอยู่ฝั่ง client: path ของ -i ผิด, มี IdentityFile ใน ~/.ssh/config ที่คุณลืมไป, หรือ agent (ssh-add -l) ถือ identity เก่าที่ตอบแทนก่อน

สาเหตุจริงสี่ข้อคืออะไร?

สาเหตุสัญญาณวิธีแก้
user ผิดkey ทำงานกับ root@host แต่ล้มกับ deploy@hostkey ต้องอยู่ใน ~/.ssh/authorized_keys ของuser นั้นจริง
key ยังไม่ติดตั้งlog เซิร์ฟเวอร์โชว์ Failed publickey กับทุกคำเสนอssh-copy-id user@host
สิทธิ์เปิดกว้างเกินclient: WARNING: UNPROTECTED PRIVATE KEY FILE — key ถูกข้าม ไม่ถูกยื่นchmod 700 ~/.ssh; chmod 600 ~/.ssh/*
key ssh-rsa ยุคเก่าเซิร์ฟเวอร์รัน OpenSSH 8.8+; key RSA เก่าไม่เคยถูกรับสร้างใหม่เป็น ed25519 หรืออัปเกรด key

สาเหตุเรื่องสิทธิ์สมควรได้โน้ตพิเศษ เพราะ OpenSSH บังคับใช้แบบหนักหน่วง: private key ที่ group หรือ world อ่านได้จะถูก client ปฏิเสธเองแล้วหลุดจากรายการยื่นแบบเงียบ ๆ วิธีแก้คือสองคำสั่ง:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 ~/.ssh/authorized_keys

สาเหตุ ssh-rsa ตะกุย CI image เก่า ๆ กับ Raspberry Pi: OpenSSH 8.8 (ปล่อย 2021-10-01, openssh.com/txt/release-8.8) ปิดลายเซ็น ssh-rsa — ตัวที่พึ่ง SHA-1 — เป็นค่าเริ่มต้น ตาม release notes: “the ssh-rsa signature scheme is … disabled by default” key RSA ที่สร้างปี 2018 ไม่ได้พัง รูปแบบลายเซ็นของมันแค่ไม่มีใครพูดภาษาเดียวกันอีกแล้ว การสร้าง key แบบ ed25519 (ssh-keygen -t ed25519) คือคำตอบที่ยั่งยืน และคอนโซลของผู้ให้บริการคลาวด์ให้ serial console แก่คุณในกรณีที่คุณกุญแจตัวเองกลางการแก้

มองเห็นได้อย่างไรว่าเซิร์ฟเวอร์ปฏิเสธ key เพราะอะไร?

log ฝั่งเซิร์ฟเวอร์คือพยานที่ซื่อสัตย์ บน Ubuntu (systemd) sshd บันทึกคำตัดสินรายคำเสนอ:

journalctl -u ssh -n 50 --no-pager | grep -iE "publickey|denied|accepted"
# sshd[4421]: Failed publickey for deploy from 203.0.113.7 port 51422 ssh2: RSA SHA256:...
# sshd[4421]: Accepted publickey for deploy from 203.0.113.7 port 51422 ssh2: ED25519 SHA256:...

Failed publickey พร้อม fingerprint ที่คุณไม่คาดคิดแปลว่า client ยื่น key ต่างจากที่คุณคิด — กลับไปที่ -vvv Failed publickey พร้อมfingerprint ของคุณแปลว่า key ถูกต้องแต่ยังไม่ได้ติดตั้งกับบัญชีนั้น หรือสิทธิ์ home directory ฝั่งเซิร์ฟเวอร์ผิด (กฎ 700/600 เดิมมีผลกับ ~/.ssh และ ~/.ssh/authorized_keys ของเซิร์ฟเวอร์ด้วย) ถ้า sshd ไม่ยอมสตาร์ตช่วงที่คุณกำลังแก้ config นั่นคือการล่าอีกเรื่องหนึ่ง — ดูsystemd service not starting

ติดตั้ง key อย่างถูกวิธีได้อย่างไร?

ssh-copy-id deploy@staging
# Number of key(s) added: 1
ssh -o BatchMode=yes deploy@staging 'echo ok'   # หลักฐานแบบไม่ต้องโต้ตอบ

ssh-copy-id ต่อท้าย public key ของคุณเข้า authorized_keys ของบัญชีปลายทางและตั้งสิทธิ์ให้เหมาะสม — มันมีอยู่เพราะการก๊อปวางเองลง authorized_keys พังที่การขึ้นบรรทัดใหม่เกินหรือโฟลเดอร์ที่ยังไม่มีบ่อยพอที่จะเสียเวลา การเช็ก BatchMode คือการทดสอบจริง: มันปิดทุก prompt ความสำเร็จจึงแปลว่า key ตัวเดียวพอแบกการล็อกอินได้ เมื่อ key ทำงานแล้ว scp กับ rsync สืบทอดการยืนยันชุดเดิมฟรี ๆ ทางเลือกระหว่างสองตัวคือเรื่อง bandwidth ไม่ใช่ credential (rsync vs scp)

คัดกรองใน 30 วินาที

ssh -vvv user@host 2>&1 | grep -i offering      # 1. key ไหนถูกยื่นไป?
journalctl -u ssh -n 50 | grep -i publickey     # 2. ถูกปฏิเสธเพราะอะไร?
ls -ld ~/.ssh ~/.ssh/authorized_keys            # 3. 700 / 600?
ssh-copy-id user@host                           # 4. ติดตั้ง แล้วยืนยันด้วย BatchMode

Permission denied (publickey) คือผลการเจรจา ไม่ใช่ prompt ถามรหัสผ่าน — เซิร์ฟเวอร์ปฏิเสธทุก key ในการยื่น และ log ของมันรู้สาเหตุมาก่อนแล้ว

รันสี่คำสั่งตามลำดับ ความล้มเหลวจะหยุดเป็นปริศนา: หนึ่งในนั้นจะเรียกชื่อผู้ร้ายทุกครั้ง คดีของผมคือ identity เก่าของ agent ตอบแทนก่อน key ที่ถูกต้อง — ssh-add -d แล้ว deploy เขียวภายใน 02:31

FAQ

ทำไม SSH ถึงบอก Permission denied (publickey)?

หมายความว่าทุก key ที่ client ยื่นไปถูก server ปฏิเสธ และการยืนยันด้วยรหัสผ่านหรือ keyboard-interactive ไม่ได้ถูกลองหรือไม่ได้รับอนุญาต นี่คือคำตัดสินของการเจรจาต่อรองเรื่อง key ที่ยื่นไป — ไม่ใช่การพิมพ์รหัสผ่านผิด

แก้ SSH permission denied (publickey) บน Ubuntu อย่างไร?

ตรวจฝั่งเซิร์ฟเวอร์ด้วย journalctl -u ssh -n 50 ยืนยันว่า public key ของคุณอยู่ใน ~/.ssh/authorized_keys ของ user ปลายทาง และแน่ใจว่าสิทธิ์คือ 700 ที่ ~/.ssh กับ 600 ที่ authorized_keys และ private key

ทำไม ssh -i mykey ถึงยังล้มเหลว?

สามเหตุผลประจำ: สิทธิ์ของ private key เปิดกว้างเกินจน OpenSSH ปฏิเสธการโหลด, เซิร์ฟเวอร์รัน OpenSSH 8.8+ ซึ่งปิดลายเซ็น ssh-rsa (SHA-1), หรือ key ไม่ได้อยู่จริงใน authorized_keys ของ user ปลายทาง

เพิ่ม public key ของผมเข้าเซิร์ฟเวอร์อย่างไร?

รัน ssh-copy-id user@host — มันจะต่อท้าย public key ของคุณเข้า ~/.ssh/authorized_keys พร้อมสิทธิ์ที่ถูกต้อง ถ้าการล็อกอินด้วยรหัสผ่านถูกปิดไปแล้ว ให้ทำจากคอนโซลที่คุณยังเข้าถึงได้

— mrsaynothing

— mrsaynothing

บันทึกหน้างานเรื่อง AI, Linux และ self-hosted

รับวิธีแก้ฉบับถัดไปทางอีเมล

อีเมลหนึ่งฉบับต่อหนึ่งโพสต์ แก้เสร็จแล้วไปต่อ

self-hosted · ไม่มีบุคคลที่สาม · ยกเลิกได้ในคลิกเดียว

นี่คืออะไร?

Gitignore ไม่ทำงาน? นี่คือวิธีแก้ที่แท้จริง

ถ้าอ่านแล้วชอบ — ผมสร้างงานแบบนี้เป็นอาชีพ จ้างผม