SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor

Ubuntu 24.04-এ Nginx-এর জন্য Certbot ইনস্টল করার নিয়ম

Ubuntu 24.04-এ sudo apt install certbot python3-certbot-nginx কমান্ড দিয়ে Certbot সেটআপ করুন। snap বনাম apt ব্যবহারের পার্থক্য এবং পোর্ট 80 রিনিউয়াল টাইমআউট সমস্যা এড়ানোর উপায় জানুন।

Certbot ইনস্টল করুন: apt অথবা snap

Ubuntu 24.04-এ sudo apt install certbot python3-certbot-nginx ব্যবহার করলে কার্যকর Certbot পাওয়া যায়, যা বাস্তবে ব্যবহারযোগ্য এবং সর্বজনস্বীকৃত Let's Encrypt certificate ইস্যু করে। Certbot-এর upstream documentation পরিবর্তে snap ব্যবহারের নির্দেশ দেয়। পার্থক্য সীমিত: snap upstream release অনুসরণ করে, আর archive package LTS-এর সঙ্গে যে সংস্করণ প্রকাশিত হয়েছিল সেটিই অনুসরণ করে এবং security fix পায়।

একটি বেছে নিন। Certbot-এর দুটি copy থাকলে একই /etc/letsencrypt tree-এর জন্য দুটি renewal timer তৈরি হয়। আপনি যে copy-টির কথা ভুলে গেছেন, সেটিই পরে অপ্রত্যাশিত সমস্যা তৈরি করবে।

apt পদ্ধতি:

sudo apt update
sudo apt install certbot python3-certbot-nginx

এটি /usr/bin/certbot, nginx plugin, একটি certbot.service + certbot.timer জোড়া এবং একটি /etc/cron.d/certbot entry ইনস্টল করে, যা systemd-এর অধীনে কোনো কাজ করে না।

snap পদ্ধতি:

sudo apt remove certbot python3-certbot-nginx
sudo snap install core && sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

snap নিজস্ব timer, snap.certbot.renew.timer, নিয়ে আসে। snap ইনস্টল করার আগে apt package সরিয়ে ফেলুন।

এরপর দুটি installation একইভাবে কাজ করে। শুধু renewal কখন চালাবে, সেই সময়ের পার্থক্য থাকে, যা নিচের Renewal অংশে ব্যাখ্যা করা হয়েছে। Certbot 2.x ডিফল্টভাবে ECDSA (P-256) key ব্যবহার করে। ECDSA সমর্থন করে না এমন client-এর জন্যই কেবল --key-type rsa দিন। Certbot-এর সব state /etc/letsencrypt-এর অধীনে থাকে: archive/-এ আসল key ও certificate file থাকে, live/ বর্তমান file-গুলোর দিকে symlink করে, renewal/-এ প্রতিটি certificate-এর জন্য একটি configuration file থাকে, আর accounts/-এ আপনার ACME account key থাকে।

HTTP-01 আসলে কী করে এবং port 80 কেন ঐচ্ছিক নয়

HTTP-01 challenge একটি callback। আপনি example.com কভার করে এমন certificate-এর জন্য Let's Encrypt-এর কাছে অনুরোধ করেন। এটি public DNS-এ নামটির resolution করে, সেখানে পাওয়া address-এ port 80-এ connection খোলে এবং http://example.com/.well-known/acme-challenge/<token>-এর জন্য অনুরোধ পাঠায়। আপনার server Certbot যে exact token content disk-এ লিখেছে, সেটিই ফেরত দেয়। পুরো প্রক্রিয়াটি এতটুকুই। এর তিনটি পরিণতি আছে। বেশিরভাগ issuance ব্যর্থতার কারণ এগুলোই।

  • Public Internet থেকে port 80-এ পৌঁছানো আবশ্যক, শুধু আপনার laptop থেকে পৌঁছানো যথেষ্ট নয়। একটি ufw rule, cloud provider-এর security group অথবা VPS console-এর firewall যদি শুধু 443 খোলে, তাহলে issuance এবং পরবর্তী প্রতিটি renewal ব্যর্থ হবে।
  • DNS-কে আগে থেকেই এই box-এর দিকে নির্দেশ করতে হবে। Validation server বাইরে থেকে নিজেই lookup করে। আপনার /etc/hosts entry এবং browser cache তার কাছে কোনো কাজে আসে না।
  • আপনি যদি AAAA record প্রকাশ করেন, তাহলে IPv6 আগে চেষ্টা করা হয়। IPv6 connection timeout হলেই Let's Encrypt IPv4 দিয়ে আবার চেষ্টা করে। IPv6 connection refused হলে আবার চেষ্টা করা হয় না। এমন কোনো stale AAAA যদি এমন host-এর দিকে নির্দেশ করে, যা connection গ্রহণ করে কিন্তু অন্য কিছু serve করে, তাহলে validation সরাসরি ব্যর্থ হবে।

Redirect অনুমোদিত। Validation HTTP redirect অনুসরণ করে HTTPS-এ যেতে পারে। অপর প্রান্তের certificate অনুপস্থিত, expired অথবা self-signed হলেও এতে সমস্যা হয় না। তবে এটি port 80 ছাড়া অন্য কোনো port থেকে শুরু করবে না। Certbot-এ TLS-ALPN-01 implementation নেই। তাই "শুধু 443 ব্যবহার করুন" কোনো সমাধান নয়।

একটি অথেন্টিকেটর নির্বাচন: --nginx, --webroot, --standalone

--nginx হলো সঠিক ডিফল্ট অপশন যখন Nginx আগে থেকেই চলছে এবং ডোমেইনটি সার্ভ করছে। Certbot আপনার কনফিগারেশন পার্স করে, একটি সাময়িক চ্যালেঞ্জ লোকেশন ইনজেক্ট করে, Nginx রিলোড করে, ভ্যালিডেশন সম্পন্ন করে এবং তারপর TLS ডিরেক্টিভগুলো আপনার সার্ভার ব্লকে লিখে দেয়। এতে কোনো ডাউনটাইম হয় না।

sudo certbot --nginx -d example.com -d www.example.com

নতুন সার্ভারের জন্য স্ক্রিপ্টেড পদ্ধতি:

sudo certbot --nginx \
  -d example.com -d www.example.com \
  --agree-tos -m ops@example.com --no-eff-email \
  --redirect --non-interactive

--webroot তখন সঠিক যখন আপনি চান না যে Certbot আপনার Nginx কনফিগারেশনের আশেপাশে থাকুক। এটি এমন ক্ষেত্রে কার্যকর যখন আপনি টেমপ্লেট থেকে কনফিগারেশন তৈরি করেন, git-এ রাখেন অথবা Ansible দিয়ে পুশ করেন। Certbot শুধুমাত্র চ্যালেঞ্জ ফাইলটি আপনার সার্ভ করা একটি ডিরেক্টরিতে লিখে দেয়।

sudo certbot certonly --webroot -w /var/www/example.com \
  -d example.com -d www.example.com \
  --deploy-hook "systemctl reload nginx"

--standalone তখন সঠিক যখন পোর্ট 80-এ কোনো কিছু লিসেন করছে না: যেমন একটি মেইল সার্ভার, এমন একটি API যা শুধুমাত্র 443 পোর্টে কথা বলে, অথবা Nginx ইনস্টল হওয়ার আগে চালানো প্রথম বুট স্ক্রিপ্ট। Certbot নিজেই কয়েক সেকেন্ডের জন্য পোর্ট 80 বাইন্ড করে। যদি Nginx আগে থেকেই চলতে থাকে, তবে এটি ব্যর্থ হবে; তাই রান করার সময় সেটি বন্ধ রাখুন:

sudo certbot certonly --standalone -d mail.example.com \
  --pre-hook "systemctl stop nginx" \
  --post-hook "systemctl start nginx"

এই হুকগুলো সার্টিফিকেটের রিনিউয়াল কনফিগারেশনে রেকর্ড করা থাকে, তাই রিনিউয়ালের সময় একই স্টপ/স্টার্ট প্রক্রিয়া স্বয়ংক্রিয়ভাবে সম্পন্ন হয়।

Certificate বিদ্যমান থাকার আগে ও পরে কাজ করে এমন একটি server block

এখানে chicken-and-egg সমস্যা আছে: অস্তিত্বহীন ফাইলের দিকে নির্দেশ করা ssl_certificate থাকলে nginx চালু হতে অস্বীকার করে, আবার nginx বন্ধ থাকলে Certbot validation করতে পারে না। প্রথমে port 80-এ site চালু করুন।

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/example.com;
    index index.html;

    location ^~ /.well-known/acme-challenge/ {
        root /var/www/example.com;
        default_type "text/plain";
        try_files $uri =404;
    }

    location / {
        try_files $uri $uri/ =404;
    }
}

sudo nginx -t && sudo systemctl reload nginx চালান। বক্সের বাইরে থেকে curl -I http://example.com/ উত্তর দিচ্ছে কি না নিশ্চিত করুন। এরপর certificate issue করুন।

এরপর:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    location ^~ /.well-known/acme-challenge/ {
        root /var/www/example.com;
        default_type "text/plain";
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com www.example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    root /var/www/example.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

দীর্ঘ ACME prefix ইতিমধ্যেই location /-এর আগে match করে। তাই challenge request কখনো return 301-এ পৌঁছায় না। ^~ modifier-এর উপকার অন্য ক্ষেত্রে পাওয়া যায়: ওই prefix match হলে nginx regex location-গুলো সম্পূর্ণ এড়িয়ে যায়। ফলে পরে যোগ করা location ~ /\. { deny all; }-এর মতো কোনো rule challenge-কে block করতে পারে না। ওই location port 80-এ রাখলে site-এর বাকি অংশ HTTPS-only হওয়ার পরও renewal কাজ করতে থাকে।

উপরের উভয় block disk থেকে file serve করে। nginx যদি application-এর সামনে থাকে, তাহলে location / একটি proxy_pass block হয়ে যাবে। reverse proxy server block, প্রতিটি line-এর ব্যাখ্যা-তে applicationটির প্রয়োজনীয় header-গুলো দেখানো হয়েছে। ACME location এবং TLS directive-গুলো অপরিবর্তিত থাকবে।

HTTP/2 syntax আপনার nginx version-এর ওপর নির্ভর করে। Ubuntu 24.04-এ nginx 1.24 থাকে। এই version-এ directive-টি inline দিতে হয়, listen 443 ssl http2;। আলাদা http2 on; directive দিলে nginx চালু হতে ব্যর্থ হয়। Debian 13-এ nginx 1.26 থাকে। এই version-এ http2 on; ব্যবহার করতে হয় এবং inline form-টিকে শুধু deprecated হিসেবে warning দেওয়া হয়। আগে nginx -v পরীক্ষা করুন।

nginx-কে live/-এর দিকে নির্দেশ করুন। কখনো archive/-এর দিকে নির্দেশ করবেন না। প্রতিটি renewal-এর সময় live/ symlink পুনর্নির্দেশ করা হয়। archive/-এর ভেতরের কোনো নির্দিষ্ট path ব্যবহার করলে এমন certificate-এ আটকে যাবেন, যেটি আপনার অজান্তে expire হয়ে যাবে।

Wildcard মানেই DNS-01, আর DNS-01 মানেই একটি plugin

একটি wildcard certificate (*.example.com) HTTP-01 এর মাধ্যমে যাচাই করা সম্ভব নয়, কারণ ফাইলটি সংগ্রহ করার জন্য কোনো নির্দিষ্ট একটি hostname নেই। DNS-01 ই একমাত্র উপায়: আপনি একটি _acme-challenge.example.com TXT record প্রকাশ করার মাধ্যমে আপনার নিয়ন্ত্রণ প্রমাণ করবেন। Certbot-এর স্বয়ংক্রিয়ভাবে এটি করার জন্য আপনার DNS provider-এর API credentials প্রয়োজন, আর এই কারণেই provider plugin-গুলোর অস্তিত্ব রয়েছে। সম্পূর্ণ wildcard certificate নির্দেশিকা-তে TXT record-এর কার্যপদ্ধতি এবং manual mode-এ renewal-এর ঝুঁকিগুলো আলোচনা করা হয়েছে; নিচে Cloudflare-এর সংক্ষিপ্ত সংস্করণ দেওয়া হলো।

sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflare

apt পাথের ক্ষেত্রে এটি sudo apt install python3-certbot-dns-cloudflare হবে। Credentials-গুলো শুধুমাত্র root ব্যবহারকারীর জন্য সংরক্ষিত একটি ফাইলে রাখতে হবে:

# /root/.secrets/cloudflare.ini
# then: sudo chmod 600 /root/.secrets/cloudflare.ini
dns_cloudflare_api_token = your_scoped_token_here

Token-টিকে শুধুমাত্র নির্দিষ্ট zone-এর DNS-edit অধিকারের মধ্যে সীমাবদ্ধ রাখুন। এটি আপনার DNS-এর একটি চাবিকাঠি; তাই এটিকে সেই গুরুত্ব দিন।

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
  -d example.com -d '*.example.com'

Wildcard-টিকে উদ্ধৃতি চিহ্নের (quote) মধ্যে রাখুন যাতে আপনার shell সেটিকে glob না করে। DNS-01 এমন সমস্যারও সমাধান করে যা HTTP-01 পারে না: যেসব host-এর কোনো public port 80 নেই, কোনো internal service, শুধুমাত্র VPS-এ self-hosted WireGuard VPN-এর মাধ্যমে পৌঁছানো যায় এমন কোনো সার্ভার, অথবা private interface-এ থাকা কোনো admin panel-এর জন্য certificate তৈরি করা।

নবায়ন: 90 দিন, timer এবং deploy hook

Let's Encrypt certificate 90 দিনের জন্য বৈধ থাকে। apt package (Certbot 2.9.0) মেয়াদ শেষ হতে 30 দিনের কম সময় বাকি থাকলে renewal করে। snap সর্বশেষ Certbot version অনুসরণ করে। version 4.1 থেকে এটি ACME Renewal Info (ARI)-এর মাধ্যমে Let's Encrypt-এর কাছে প্রস্তাবিত renewal সময়ও জানতে চায় এবং আরও আগে renewal করতে পারে। Let's Encrypt certificate-এর ক্ষেত্রে এর অর্থ সাধারণত certificate-এর মেয়াদের প্রায় দুই-তৃতীয়াংশ অতিক্রান্ত হলে renewal করা।

দুই ক্ষেত্রেই আপনি প্রায় 30 দিনের একটি সময়সীমা পান। এই সময়ে renewal ব্যর্থ হলে তা outage না হয়ে সমাধানযোগ্য সমস্যা হিসেবে থাকে। আগামী বছর থেকে renewal আরও ঘন ঘন হবে বলে ধরে নিন। Let's Encrypt-এর default profile 2027 সালের February 10 তারিখে 64 দিনের certificate এবং 2028 সালের February 16 তারিখে 45 দিনের certificate ব্যবহার শুরু করবে।

Let's Encrypt এখন আর expiry-warning email পাঠায় না। কেউ আপনাকে আলাদা করে সতর্ক করবে না। তাই এখন monitoring-এর দায়িত্ব আপনার।

আপনার ইনস্টলের সঙ্গে আসা timer পরীক্ষা করুন:

systemctl list-timers 'certbot*' 'snap.certbot*'
sudo certbot certificates

certbot renew /etc/letsencrypt/renewal/-এর প্রতিটি configuration পরীক্ষা করে, যেগুলোর renewal এখনও বাকি নেই সেগুলো বাদ দেয়, এবং বাকি configuration-গুলোতে সংরক্ষিত option ব্যবহার করে renewal সম্পন্ন করে। আপনি পরে certbot reconfigure দিয়ে option পরিবর্তন না করলে, এগুলো মূল run-এর flag। তাই প্রথম run গুরুত্বপূর্ণ: সেটিই record করা হয়।

ডিস্কের certificate ফাইল renew করলেই নিজে থেকে কোনো পরিবর্তন হয় না। nginx reload করার নির্দেশ না পাওয়া পর্যন্ত memory থেকে পুরোনো certificate পরিবেশন করতে থাকে। একবার deploy hook কনফিগার করুন:

sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh >/dev/null <<'EOF'
#!/bin/sh
set -e
nginx -t && systemctl reload nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

renewal-hooks/deploy/-এ executable যেকোনো কিছু প্রতিটি সফল renewal-এর পরে চালানো হয়। --deploy-hook flag একই কাজ একটি certificate-এর জন্য করে এবং renew_hook = ...-কে তার renewal config-এ সংরক্ষণ করে। certbot --nginx নিজে reload করে; --webroot এবং --standalone setup তা করে না। Hook না থাকাই এর কারণ যে একটি site expired certificate পরিবেশন করে, যদিও certbot certificates নতুন certificate পাওয়া গেছে বলে দেখায়। Startup-এর সময় certificate পড়ে এমন অন্য যেকোনো কিছুতেও একই hook প্রয়োজন। Docker, TLS ও backup-সহ Nextcloud VPS install-এর মতো containerised app-এর জন্যও এখানে নিজস্ব restart বা reload ধাপ যুক্ত করতে হবে।

রিনিউয়াল কার্যকরভাবে পরীক্ষা করা

sudo certbot renew --dry-run

এটি Let's Encrypt-এর staging environment-এর বিরুদ্ধে সম্পূর্ণ challenge চালায়: একই code path, একই firewall, একই DNS ব্যবহার করে। কোনো কিছুই আপনার production rate limit-এ গণনা হয় না; staging-এর নিজস্ব rate limit অনেক বেশি। কোনো certificate disk-এ সংরক্ষণ করা হয় না। আজ পরীক্ষা সফল হলে 60 দিন পরের unattended renewal-ও সফল হবে, যদি এর মধ্যে সার্ভারের অন্য কোনো পরিবর্তন না হয়।

Dry run আপনার reload hook কার্যকর হয় কি না তা প্রমাণ করে না। Certbot version অনুযায়ী এর আচরণ ভিন্ন হতে পারে। এই অংশটি হাতে পরীক্ষা করুন: hook script সরাসরি চালান, systemctl reload nginx সফল হয় কি না নিশ্চিত করুন, এবং sudo grep renew_hook /etc/letsencrypt/renewal/example.com.conf পরীক্ষা করুন।

যে ত্রুটিগুলোর মুখোমুখি আপনি বাস্তবে হবেন

Could not bind to IPv4 or IPv6., --standalone যখন nginx ইতিমধ্যে port 80 দখল করে রেখেছে। --nginx বা --webroot ব্যবহার করুন, অথবা run চালানোর সময় nginx বন্ধ রাখুন। sudo ss -lntp | grep ':80' দিয়ে কোন process portটি ব্যবহার করছে তা নিশ্চিত করুন।

Timeout during connect (likely firewall problem), Let's Encrypt port 80-এ পৌঁছাতে পারেনি। ধাপে ধাপে বাইরের দিক পরীক্ষা করুন: sudo ufw status (sudo ufw allow 'Nginx Full' দিয়ে এটি খুলুন), তারপর VPS provider-এর নিজস্ব firewall, এবং শেষে DNS। আপনার server নয়, এমন কোনো স্থান থেকে পরীক্ষা করুন: curl -sSv http://example.com/.well-known/acme-challenge/test। পুরোনো AAAA record থেকেও একই message দেখা যায়।

unauthorized :: Invalid response from http://example.com/.well-known/acme-challenge/xyz: 404, port 80-এ সংযোগ করা যাচ্ছে, কিন্তু token পরিবেশিত হচ্ছে না। অনুরোধটি অন্য একটি server block-এ গেছে (default_server কোন block-এর অধীনে আছে তা পরীক্ষা করুন), অথবা -w-এ দেওয়া directory-টি nginx যে directory পরিবেশন করে সেটি নয়। /var/www/example.com/.well-known/acme-challenge/test-এ একটি file রাখুন এবং বাইরে থেকে সেটি fetch করুন; সেটিতেও 404 হলে certificate কখনোই সমস্যার কারণ ছিল না।

DNS problem: NXDOMAIN looking up A for example.com, নামটি public DNS-এ resolve হচ্ছে না। নতুন record এখনও propagate হয়নি, অথবা এমন একটি zone-এ record রয়েছে যা আপনার registrar serve করছে না।

too many certificates (5) already issued ..., একটি rate limit, এবং debugging করার সময় loop-এর মধ্যে মানুষ যে সীমায় আটকে যায়। বার্তায় সীমাটির নাম থাকে এবং শেষে একটি retry after সময় থাকে। Let's Encrypt একই নামের exact set-এর duplicate certificate প্রতি সপ্তাহে পাঁচটিতে সীমাবদ্ধ রাখে। এই সীমার জন্য কোনো override নেই। তাই সময় পার হলেই কেবল এটি unblocked হয়। আলাদাভাবে, প্রতি registered domain-এ প্রতি সপ্তাহে 50টি নতুন certificate অনুমোদিত। override চেয়ে এই সীমা বাড়ানো যায়। বিদ্যমান certificate-এর একই exact set of names-এর জন্য request করলে সেটি renewal হিসেবে গণ্য হয় এবং এই সীমার আওতামুক্ত থাকে। ARI-এর মাধ্যমে সমন্বিত renewals সব limit-এর আওতামুক্ত। --dry-run ব্যবহার করে staging environment-এ debugging করুন।

nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/example.com/fullchain.pem": No such file or directory, nginx এমন একটি certificate-এর জন্য configured আছে যা কখনো issue করা হয়নি, অথবা `certbot delete` দিয়ে সরিয়ে ফেলা হয়েছে। TLS server block-টি comment out করুন, nginx চালু করুন, certificate issue করুন, তারপর block-টি পুনরুদ্ধার করুন।

open() "/etc/letsencrypt/options-ssl-nginx.conf" failed, nginx plugin package-এর সঙ্গে ওই file-টি সরবরাহ করা হয়। python3-certbot-nginx ছাড়া certonly box-এ plugin যোগ করুন, অথবা include line-টি নিজের ssl_protocols ও ssl_ciphers settings দিয়ে প্রতিস্থাপন করুন।

বড় পরিসরে এটি পরিচালনা

একটি certificate-এ সর্বোচ্চ 100টি name থাকতে পারে। একটি একক certbot --nginx -d a.example.com -d b.example.com ... ব্যবহার করা আকর্ষণীয় মনে হতে পারে। কিন্তু একটি পুরোনো DNS record validation ব্যর্থ করলেই ওই certificate-এর অন্য সব name-ও অকার্যকর হয়ে যায়। প্রতিটি site-এর জন্য আলাদা certificate ব্যবহার করলে সেগুলো স্বাধীনভাবে ব্যর্থ হয়। একাধিক service host করা server-এ এটিই কাঙ্ক্ষিত আচরণ। কয়েকটি site-এর বেশি হলে একটি ACME-aware front door ব্যবহার করা যুক্তিযুক্ত। একটি Docker Compose-এর অধীনে একাধিক app চালানো Traefik reverse proxy নিজেই certificate request ও renewal করে। ফলে Certbot সম্পূর্ণভাবে বাদ দেওয়া যায়। এই front door-এ কোন proxy থাকবে, সেটি আলাদা সিদ্ধান্ত। Nginx, Caddy এবং Traefik-এর তুলনা মূলত নির্ভর করে certificate এবং প্রতিটি app-এর configuration-এর কতটা কাজ আপনি proxy-কে করতে দিতে চান তার ওপর।

/etc/letsencrypt সম্পূর্ণ tree-এর backup নিন। sudo tar -czf letsencrypt-$(date +%F).tar.gz -C /etc letsencrypt এবং symlink অক্ষত রাখুন। ওই tree-তে accounts/ রয়েছে। এটি আপনার ACME account key, যা একইভাবে পুনরায় তৈরি করা যায় না। নতুন VPS-এ স্থানান্তরের কাজ তখন দাঁড়ায়: -a ব্যবহার করে tree-টি rsync করা, Certbot install করা, DNS পুনর্নির্দেশ করা এবং cutover-এর আগে certbot renew --dry-run চালানো।

Server পুনর্নির্মাণ করলে বা নতুন LTS-এ গেলে renewal timer আপনার সঙ্গে স্থানান্তরিত হয় না। যেকোনো migration, snapshot restore বা distro upgrade-এর পরে systemctl list-timers 'certbot*' চালান এবং একটি --dry-run সম্পন্ন করুন। এটি বাদ দিলে 89 দিন পরে রাত 3টায় site বন্ধ হয়ে যেতে পারে। সবাই ধরে নিয়েছিল certificate নিজে থেকেই renew হচ্ছে।

উপরের HTTP-01 route-গুলো এমন একটি machine ধরে নেয়, যেটি আপনি নিয়ন্ত্রণ করেন, যার public IP আছে এবং port 80 সবার জন্য খোলা। অর্থাৎ একটি VPS। DNS-01-এর ক্ষেত্রে এগুলোর কোনোটিই প্রয়োজন হয় না। এই দুই ক্ষেত্রেই উপরের প্রক্রিয়া একই।

একই certificate-এর ধাপগুলো nginx-এর পরিবর্তে Apache-এও প্রযোজ্য। Public certificate ব্যবহার করা সম্ভব না হলে Ubuntu-তে self-signed certificate internal service-এর জন্য যথেষ্ট।

FAQ

আমার site যদি শুধু HTTPS সেবা দেয়, তাহলে কি port 80 খোলা রাখতে হবে?

হ্যাঁ, HTTP-01 challenge-এর জন্য। Let's Encrypt সবসময় port 80-এ validation request শুরু করে। Certbot-এ TLS-ALPN-01 implementation নেই। তাই শুধু 443 খোলা firewall প্রথম certificate issuance এবং পরবর্তী প্রতিটি unattended renewal—দুটিই আটকে দেয়। port 80 থেকে HTTPS-এ redirect করা ঠিক আছে; validation সেই redirect অনুসরণ করে। port 80 পুরোপুরি এড়ানোর একমাত্র উপায় DNS-01। এটি provider plugin দিয়ে করা যায়, অথবা Certbot-এর --manual --preferred-challenges dns ব্যবহার করে করা যায়। এই পদ্ধতিতে TXT record আপনাকেই যোগ করতে হবে। --manual-auth-hook script না দিলে renewal আর automatic থাকবে না।

Ubuntu 24.04-এ nginx-এর জন্য apt নাকি snap—কোন Certbot install করব?

apt ব্যবহার করুন। sudo apt install certbot python3-certbot-nginx Ubuntu 24.04-এ Certbot 2.9.0 দেয়। এই সংস্করণটি এই guide-এর সব কাজের জন্য যথেষ্ট নতুন। এটি unattended-upgrades-এর মাধ্যমে security patch পায় এবং snapd প্রয়োজন হয় না। সর্বশেষ release অবিলম্বে প্রয়োজন হলে, অথবা শুধু snap হিসেবে বিতরণ করা কোনো DNS plugin দরকার হলে snap বেছে নিন। যেকোনো ক্ষেত্রে ঠিক একটি পদ্ধতি বেছে নিন। দুটি install একই /etc/letsencrypt tree-এর জন্য দুটি renewal timer চালায়। পরে ভুলে যাওয়া install-টিই সমস্যা তৈরি করে।

Certbot কি nginx-এর জন্য wildcard certificate issue করতে পারে?

শুধু DNS-01-এর মাধ্যমে। *.example.com-এর মতো wildcard-এর challenge file সংগ্রহ করার জন্য কোনো একক hostname নেই। তাই --nginx, --webroot এবং --standalone—কোনোটিই ব্যবহার করা যাবে না। আপনার DNS provider-এর plugin install করুন। root-only credentials file-এ সীমিত scope-এর API token রাখুন। তারপর certbot certonly --dns-cloudflare -d example.com -d '*.example.com' চালান। wildcard-টি quote করুন, যাতে shell এটিকে glob হিসেবে বিবেচনা না করে।

সফল renewal-এর পরেও nginx কেন পুরোনো certificate সেবা দেয়?

nginx certificate memory-তে রাখে। disk-এর নতুন file তৈরি হওয়ার পর reload না হওয়া পর্যন্ত nginx সেটি জানতে পারে না। certbot --nginx নিজে reload করে। কিন্তু --webroot এবং --standalone run তা করে না। ফলে renewal সফল হলেও browser-এ মেয়াদ শেষ হতে থাকা certificate দেখা যেতে পারে। /etc/letsencrypt/renewal-hooks/deploy/-এ একটি executable script রাখুন, যা nginx -t && systemctl reload nginx চালায়। প্রতিটি সফল renewal-এর পরে script-টি চালু হবে।

certbot renew --dry-run কি প্রমাণ করে যে renewal কাজ করবে?

বেশিরভাগ ক্ষেত্রে। এটি staging environment-এর বিরুদ্ধে প্রকৃত challenge চালায়। এতে একই firewall, একই DNS এবং একই code path ব্যবহার হয়। পাশাপাশি production rate limit প্রভাবিত হয় না এবং কোনো certificate disk-এ সংরক্ষণ করা হয় না। তাই pass হলে network অংশটি সঠিক আছে বলে ধরে নেওয়া যায়। তবে deploy hook চালু হবে কি না, এটি নির্ভরযোগ্যভাবে প্রমাণ করে না। সেটি আলাদাভাবে পরীক্ষা করুন। হাতে hook script চালান এবং sudo grep renew_hook /etc/letsencrypt/renewal/example.com.conf পরীক্ষা করুন।