WIUNIX ACADEMY
آموزش HAProxy و Let’s Encrypt با تمدید امن گواهی
دو بکاند HTTP را پشت HAProxy و TLS قرار دهید؛ مسیر HTTP-01، هدرهای قابلاعتماد، سلامت بکاند و تعویض اتمیک گواهی را بررسی کنید.
محیطت را انتخاب کنآموزش متناسب با محیط تو
کجا اجرا میکنی؟
سیستمعامل و نسخه را انتخاب کن تا مراحل، دستورها و راهحلها برای همان محیط نمایش داده شوند.
آموزش متناسب با مقادیر تو
تنظیمات این آموزش
مقادیر نمونه را برای محیط خودت تنظیم کن؛ متن و دستورهای مرتبط با هم تغییر میکنند. رمز، کلید خصوصی و توکن وارد نکن. مقادیر فقط در همین زبانه نگهداری میشوند و به سرور یا لینک اشتراکگذاری فرستاده نمیشوند. پیش از اجرا، DNS، گواهیها و سیاست شبکهٔ واقعی را بررسی کن.
آیپی، دامنه یا پورت مثالها با محیط تو فرق دارد؟ دکمهٔ زیر را باز کن، مقادیر را تغییر بده و «اعمال در آموزش» را بزن؛ سپس دستورهای بهروزشده را کپی کن.
تنظیم مقادیر برای محیط من7 مقدار قابلتغییر
از اینجا شروع کن
در پایان چه چیزی خواهی داشت؟
ورودی HTTPS برای app.example.com با دو بکاند و تعویض قابلبازیابی گواهی
سیستمعاملها و نسخههای پوششدادهشده
مسیر سیستمعاملها مستند است؛ آزمون ایزوله و محدودیت آن در پایان آمده است.
قبل از شروع
- VM تازه با sudo و کنسول مستقل؛ مالکیت دامنه و دسترسی مدیریت DNS و فایروال.
- دو بکاند خصوصی آماده با health/ready؛ مسیر /srv/academy-haproxy-tls و پورتهای listener بدون تداخل.
- فرم را باز کنید، مقدارها را ویرایش و Apply کنید، سپس کپی بگیرید. مقدارها عمومیاند و فقط در همین تب/زبان/محیط ذخیره میشوند؛ کلید، گذرواژه یا توکن وارد نکنید.
توزیع بار HTTPS با مسیر بازیابی گواهی
در این تمرین، app.example.com ورودی HTTPS دو بکاند 10.77.0.21 و 10.77.0.22 روی پورت 8080 میشود. مسیر HTTP-01 هنگام ریدایرکت HTTP باز میماند و گواهی تازه پیش از reload از نظر نام، زنجیره، کلید و پیکربندی بررسی میشود.
برای مدیر لینوکس با تجربهٔ مقدماتی TLS، حدود ۶۵ دقیقه بهعلاوهٔ انتظار DNS و ACME زمان در نظر بگیرید. این معماری یک فرانتاند دارد؛ HA، تکثیر داده و ماندگاری نشست فراهم نمیکند. HTTP بکاند فقط در شبکهٔ خصوصی قابلاعتماد مناسب است؛ برای مسیر نامطمئن از TLS با اعتبارسنجی بکاند استفاده کنید.
مسیر challenge را از اپلیکیشن جدا کنید
کاربر از پورتهای عمومی ۸۰ و ۴۴۳ به آدرس محلی 192.0.2.10 میرسد؛ اگر NAT دارید، نگاشت آن باید از قبل مشخص باشد. DNS به آدرس عمومی واقعی اشاره میکند و لزوماً با این IP محلی یکی نیست. دامنه و IP نمونه قابل صدور نیستند؛ ابتدا مقدارهای خودتان را وارد کنید. پورت 8888 فقط روی loopback است و جای پورت عمومی ۸۰ را نمیگیرد.
فقط پیشوند challenge به وبروت میرود. HAProxy درخواستهای HTTPS را با health check بین دو بکاند تقسیم میکند و هدرهای پراکسی دریافتی را بازنویسی میکند. اپلیکیشن باید فقط همین فرانتاند را پراکسی قابلاعتماد بداند و دسترسی مستقیم عمومی به بکاند بسته باشد. وجود CDN یا پراکسی دیگر نیازمند طراحی جداگانهٔ مرز اعتماد است.
قدم بعدی
مالکیت مسیرها و listenerها را بررسی کنید
این مراحل برای VM تازه و اختصاصی است. IP محلی باید از قبل روی آن تنظیم شده باشد و پورتهای ۸۰، ۴۴۳ و 8888 آزاد باشند. اگر HAProxy، وضعیت Certbot، unitهای همنام یا /srv/academy-haproxy-tls وجود دارد، ادامه ندهید. کنسول SSH و مدیریت فعلی فایروال را حفظ کنید؛ فقط قواعد لازم ورودی و ارتباط بکاند را از همان مسیر مدیریتی بازبینی کنید.
Bash روی VM اختصاصی؛ مورد بیرونی در متن مشخص است
set -eu
case '/srv/academy-haproxy-tls' in /*) ;; *) printf '%s\n' 'Use a new absolute path'; exit 1;; esac
cat /etc/os-release
ps -p 1 -o comm=
test "$(ps -p 1 -o comm=)" = systemd
ip -br address
sudo ss -lntup
test ! -e '/srv/academy-haproxy-tls'
test ! -L '/srv/academy-haproxy-tls'
test ! -e /etc/haproxy
test ! -e /etc/letsencrypt
for name in academy-haproxy academy-acme-webroot academy-certbot; do
test ! -e "/etc/systemd/system/$name.service"
done
test ! -e /etc/systemd/system/academy-certbot.timer
VM تازه است، فایل و سرویس همنام ندارد و IP محلی و مسیر شبکهٔ آن مشخص است.
قدم بعدی
بستههای امضاشدهٔ توزیع را نصب کنید
Certbot جاری، وبروت و deploy hook را مستند کرده است. پیشنهاد عمومی upstream در بسیاری از سیستمها Snap است؛ این تمرین عمداً بستهٔ نگهداریشدهٔ توزیع و کانال امنیتی apt را انتخاب میکند و اسکریپت دانلودی یکخطی ندارد. نسخهٔ نصبشده را ثبت کنید. دستورهای این متن با خانوادههای HAProxy 2.6، 2.8 و 3.x سازگارند؛ نصب تازهترین باینری upstream شرط نیست. توقف سرویس فقط برای بستهٔ خالی همین VM تازه است.
Bash روی VM اختصاصی؛ مورد بیرونی در متن مشخص است
set -eu
. /etc/os-release
test "$VERSION_CODENAME" = 'noble'
sudo apt-get update
apt-cache policy haproxy certbot python3
sudo apt-get install --no-install-recommends haproxy certbot python3 openssl ca-certificates curl dnsutils nano
sudo systemctl disable --now haproxy.service certbot.timer
haproxy -vv
certbot --version
python3 --version
کدنام درست است، نسخهٔ بستهها ثبت شده و سرویس خالی نصبشده متوقف است.
قدم بعدی
مسیر عمومی و خصوصی را جدا بسازید
/srv/academy-haproxy-tls باید مسیر مطلق تازه، بدون فاصله و symlink باشد. وبروت برای responder خواندنی است، اما کلیدها، PEM و نسخهٔ قبلی دسترسی root دارند. master این نمونه chroot ندارد؛ گواهی را با root میخواند و worker با کاربر haproxy اجرا میشود. به www-data دسترسی کلید ندهید.
Bash روی VM اختصاصی؛ مورد بیرونی در متن مشخص است
set -eu
case '/srv/academy-haproxy-tls' in /*) ;; *) printf '%s\n' 'Use a new absolute path'; exit 1;; esac
test ! -e '/srv/academy-haproxy-tls'
test ! -L '/srv/academy-haproxy-tls'
sudo install -d -m 0755 '/srv/academy-haproxy-tls'
sudo install -d -m 0755 '/srv/academy-haproxy-tls/webroot/.well-known/acme-challenge'
sudo install -d -m 0700 '/srv/academy-haproxy-tls/certs' '/srv/academy-haproxy-tls/acme'
for dir in config work logs staging-config staging-work staging-logs; do
sudo install -d -m 0700 "/srv/academy-haproxy-tls/acme/$dir"
done
responder وبروت را میخواند؛ مسیر گواهی و ACME با مجوز ۰۷۰۰ محفوظ است.
قدم بعدی
فایلهای شروع HTTP را باز کنید
هر پنل بعدی محتوای یک فایل است؛ آن را در فایل همنام وارد کنید و بهعنوان shell اجرا نکنید. در مرحلهٔ bootstrap هنوز HTTPS اپلیکیشن فعال نیست. این فاصلهٔ راهاندازی باید در بازهٔ برنامهریزیشده انجام شود.
Bash روی VM اختصاصی؛ مورد بیرونی در متن مشخص است
set -eu
test ! -e '/srv/academy-haproxy-tls/haproxy.cfg'
test ! -L '/srv/academy-haproxy-tls/haproxy.cfg'
sudo install -m 0644 /dev/null '/srv/academy-haproxy-tls/haproxy.cfg'
test ! -e /etc/systemd/system/academy-haproxy.service
test ! -L /etc/systemd/system/academy-haproxy.service
sudo install -m 0644 /dev/null /etc/systemd/system/academy-haproxy.service
test ! -e /etc/systemd/system/academy-acme-webroot.service
test ! -L /etc/systemd/system/academy-acme-webroot.service
sudo install -m 0644 /dev/null /etc/systemd/system/academy-acme-webroot.service
sudo nano '/srv/academy-haproxy-tls/haproxy.cfg' /etc/systemd/system/academy-haproxy.service /etc/systemd/system/academy-acme-webroot.service
سه فایل تازه آمادهاند؛ محتوای کامل سه پنل بعدی در آنها قرار میگیرد.
قدم بعدی
پیکربندی آغازین HTTP
محتوای فایل را در مسیر نمایشدادهشده ذخیره کنید.
فایل روی VM اختصاصی
global
log stdout format raw local0
user haproxy
group haproxy
ssl-default-bind-options ssl-min-ver TLSv1.2
defaults
log global
mode http
option httplog
timeout connect 5s
timeout client 30s
timeout server 30s
timeout http-request 10s
frontend public_http
bind 192.0.2.10:80
acl known_host hdr(host) -i app.example.com app.example.com:80
http-request deny deny_status 421 unless known_host
acl acme_path path_beg /.well-known/acme-challenge/
http-request redirect prefix https://app.example.com code 308 unless acme_path
use_backend acme_webroot if acme_path
backend acme_webroot
server challenge 127.0.0.1:8888 check
فایل ذخیرهشده با پنل یکسان است و کلید خصوصی ندارد.
قدم بعدی
سرویس master-worker HAProxy
محتوای فایل را در مسیر نمایشدادهشده ذخیره کنید.
فایل روی VM اختصاصی
[Unit]
Description=Academy isolated HAProxy listener
After=network-online.target academy-acme-webroot.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/sbin/haproxy -Ws -f /srv/academy-haproxy-tls/haproxy.cfg -p /srv/academy-haproxy-tls/haproxy.pid
ExecReload=/usr/sbin/haproxy -c -f /srv/academy-haproxy-tls/haproxy.cfg
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
Restart=on-failure
[Install]
WantedBy=multi-user.target
فایل ذخیرهشده با پنل یکسان است و کلید خصوصی ندارد.
قدم بعدی
پاسخگوی استاتیک روی loopback
محتوای فایل را در مسیر نمایشدادهشده ذخیره کنید.
فایل روی VM اختصاصی
[Unit]
Description=Academy HTTP-01 static webroot
After=network.target
[Service]
User=www-data
Group=www-data
ExecStart=/usr/bin/python3 -m http.server 8888 --bind 127.0.0.1 --directory /srv/academy-haproxy-tls/webroot
Restart=on-failure
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
[Install]
WantedBy=multi-user.target
فایل ذخیرهشده با پنل یکسان است و کلید خصوصی ندارد.