TLS Certificates and HTTPS

Level: Intermediate Module: Web Services 9 min read Lesson 24 of 66

Overview

  • What you’ll learn: How TLS/SSL encryption works, certificate types and the chain of trust, how to obtain free certificates with Let’s Encrypt and Certbot, and how to configure HTTPS on both Apache and Nginx.
  • Prerequisites: Lesson 22 — Apache2 Web Server, Lesson 23 — Nginx Web Server
  • Estimated reading time: 18 minutes

Introduction

Transport Layer Security (TLS) is the cryptographic protocol that secures communication between web clients and servers. When you see the padlock icon in your browser’s address bar or a URL beginning with https://, TLS is at work — encrypting data in transit, authenticating the server’s identity, and ensuring data integrity.

TLS is the successor to the Secure Sockets Layer (SSL) protocol. Although the term “SSL” is still commonly used colloquially, all modern implementations use TLS (versions 1.2 and 1.3). As a Linux system administrator, configuring TLS correctly is one of the most critical security tasks you will perform.

In this lesson, you will learn how the TLS handshake works, understand certificate types and the chain of trust, use Let’s Encrypt with Certbot to obtain free certificates, and configure HTTPS on both Apache and Nginx on Ubuntu.

How TLS Works

TLS operates between the transport layer (TCP) and the application layer (HTTP), creating an encrypted tunnel through which HTTP traffic flows. The process begins with a TLS handshake:

  • Client Hello: The client sends supported TLS versions, cipher suites, and a random number.
  • Server Hello: The server selects the TLS version and cipher suite, and sends its certificate.
  • Certificate Verification: The client verifies the server’s certificate against trusted Certificate Authorities (CAs).
  • Key Exchange: Client and server establish a shared session key using asymmetric cryptography.
  • Encrypted Communication: All subsequent data is encrypted using the shared session key (symmetric encryption).
# View the TLS handshake with curl
$ curl -v https://www.example.com/ 2>&1 | grep -E "SSL|TLS|subject|issuer|expire"
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* Server certificate:
*  subject: CN=www.example.com
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  expire date: Apr 15 12:00:00 2025 GMT

# View certificate details with openssl
$ echo | openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null | openssl x509 -noout -text | head -20

TLS 1.2 vs TLS 1.3

TLS 1.3 (standardized in 2018) significantly improves on TLS 1.2:

  • Faster handshake: Reduced from two round trips to one (or zero with 0-RTT resumption).
  • Stronger security: Removed obsolete cipher suites (RC4, DES, 3DES, static RSA key exchange).
  • Forward secrecy: All key exchanges use ephemeral keys, so compromising a server’s private key cannot decrypt past sessions.

Certificate Types and Chain of Trust

TLS certificates are issued by Certificate Authorities (CAs). There are three validation levels:

  • Domain Validation (DV): Verifies domain ownership only. Issued in minutes. Let’s Encrypt provides free DV certificates.
  • Organization Validation (OV): Verifies the organization behind the domain. Requires business documentation.
  • Extended Validation (EV): Highest level of verification. Historically displayed a green bar in browsers.

The chain of trust works as follows: a root CA (trusted by browsers) signs an intermediate CA certificate, which in turn signs your server’s certificate. When a browser connects, it verifies each link in the chain up to a trusted root.

# View the certificate chain
$ echo | openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null | grep -E "^(Certificate chain| [0-9])"
Certificate chain
 0 s:CN = www.example.com
   i:C = US, O = Let's Encrypt, CN = R3
 1 s:C = US, O = Let's Encrypt, CN = R3
   i:C = US, O = Internet Security Research Group, CN = ISRG Root X1

Let’s Encrypt and Certbot

Let’s Encrypt is a free, automated Certificate Authority that provides DV certificates. Certbot is the recommended client tool for obtaining and renewing Let’s Encrypt certificates.

# Install Certbot and the web server plugin
$ sudo apt update
$ sudo apt install certbot

# For Apache
$ sudo apt install python3-certbot-apache

# For Nginx
$ sudo apt install python3-certbot-nginx

Obtaining a Certificate for Apache

# Certbot automatically configures Apache
$ sudo certbot --apache -d example.com -d www.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
...
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/example.com/privkey.pem

# Certbot creates/modifies the Apache SSL virtual host automatically

Obtaining a Certificate for Nginx

# Certbot automatically configures Nginx
$ sudo certbot --nginx -d example.com -d www.example.com

# Or use standalone mode if no web server is running
$ sudo certbot certonly --standalone -d example.com

Automatic Renewal

Let’s Encrypt certificates are valid for 90 days. Certbot installs a systemd timer for automatic renewal:

# Check the renewal timer
$ sudo systemctl status certbot.timer
● certbot.timer - Run certbot twice daily
     Active: active (waiting)

# Test renewal (dry run)
$ sudo certbot renew --dry-run

# View all managed certificates
$ sudo certbot certificates
Certificate Name: example.com
    Domains: example.com www.example.com
    Expiry Date: 2025-04-15 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem

Manual HTTPS Configuration for Apache

If you need manual control over the SSL configuration:

# Enable SSL module
$ sudo a2enmod ssl

# /etc/apache2/sites-available/example.com-ssl.conf
<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com/public_html

    SSLEngine on
    SSLCertificateFile      /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/example.com/privkey.pem

    # Modern TLS configuration
    SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
    SSLHonorCipherOrder     off

    # HSTS header — force HTTPS for 1 year
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

    ErrorLog ${APACHE_LOG_DIR}/example.com-ssl-error.log
    CustomLog ${APACHE_LOG_DIR}/example.com-ssl-access.log combined
</VirtualHost>

# HTTP to HTTPS redirect
<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / https://example.com/
</VirtualHost>
$ sudo a2enmod headers
$ sudo a2ensite example.com-ssl.conf
$ sudo apache2ctl configtest
$ sudo systemctl reload apache2

Manual HTTPS Configuration for Nginx

# /etc/nginx/sites-available/example.com
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    root /var/www/example.com/html;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Modern TLS configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;

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

# HTTP to HTTPS redirect
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}
$ sudo nginx -t
$ sudo systemctl reload nginx

Testing and Verifying TLS Configuration

# Test with curl
$ curl -vI https://example.com/ 2>&1 | grep -E "SSL|TLS|HTTP/"

# Test with openssl
$ openssl s_client -connect example.com:443 -servername example.com -brief
CONNECTION ESTABLISHED
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384

# Check certificate expiration
$ echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
notBefore=Jan 15 00:00:00 2025 GMT
notAfter=Apr 15 23:59:59 2025 GMT

# Online test — SSL Labs (browser)
# https://www.ssllabs.com/ssltest/analyze.html?d=example.com

Key Takeaways

  • TLS encrypts HTTP traffic, authenticates the server, and ensures data integrity via the TLS handshake.
  • TLS 1.3 is faster and more secure than TLS 1.2 — always prefer it when possible.
  • Certificate Authorities issue DV, OV, and EV certificates; Let’s Encrypt provides free DV certificates.
  • Certbot automates certificate issuance and renewal for both Apache and Nginx.
  • Always configure HTTP-to-HTTPS redirects and enable HSTS headers for full security.
  • OCSP Stapling improves TLS performance by eliminating extra round trips for certificate status checks.
  • Test your TLS configuration with openssl s_client and SSL Labs to ensure a strong security grade.

What’s Next

In Lesson 25, you will learn how to deploy PHP applications on Ubuntu, including installing PHP-FPM, connecting it to Apache and Nginx, configuring database connectivity, and deploying a complete web application.

繁體中文

概述

  • 您將學到: TLS/SSL 加密的運作原理、憑證類型和信任鏈、如何使用 Let’s Encrypt 和 Certbot 取得免費憑證,以及如何在 Apache 和 Nginx 上設定 HTTPS。
  • 先決條件: 第 22 課 — Apache2 網頁伺服器、第 23 課 — Nginx 網頁伺服器
  • 預估閱讀時間: 18 分鐘

簡介

傳輸層安全(TLS)是保護網頁客戶端和伺服器之間通訊的加密協定。當您在瀏覽器的網址列中看到鎖頭圖示或 URL 以 https:// 開頭時,TLS 正在運作——加密傳輸中的資料、驗證伺服器身份並確保資料完整性。

TLS 是安全通訊端層(SSL)協定的後繼者。所有現代實作都使用 TLS(版本 1.2 和 1.3)。

TLS 的運作原理

TLS 在傳輸層和應用層之間運作,建立加密通道。過程從 TLS 握手開始:

  • 客戶端 Hello: 客戶端發送支援的 TLS 版本、密碼套件和亂數。
  • 伺服器 Hello: 伺服器選擇 TLS 版本和密碼套件,並發送其憑證。
  • 憑證驗證: 客戶端根據受信任的憑證授權機構(CA)驗證伺服器憑證。
  • 金鑰交換: 使用非對稱加密建立共享會話金鑰。
  • 加密通訊: 所有後續資料使用共享會話金鑰加密。

憑證類型和信任鏈

  • 網域驗證(DV): 僅驗證網域所有權。Let’s Encrypt 提供免費 DV 憑證。
  • 組織驗證(OV): 驗證網域背後的組織。
  • 延伸驗證(EV): 最高等級的驗證。

Let’s Encrypt 和 Certbot

# 安裝 Certbot
$ sudo apt install certbot

# Apache 外掛
$ sudo apt install python3-certbot-apache
$ sudo certbot --apache -d example.com

# Nginx 外掛
$ sudo apt install python3-certbot-nginx
$ sudo certbot --nginx -d example.com

# 測試自動續約
$ sudo certbot renew --dry-run

Apache 的 HTTPS 設定

<VirtualHost *:443>
    ServerName example.com
    DocumentRoot /var/www/example.com/public_html
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    Header always set Strict-Transport-Security "max-age=31536000"
</VirtualHost>

Nginx 的 HTTPS 設定

server {
    listen 443 ssl http2;
    server_name example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    add_header Strict-Transport-Security "max-age=31536000" always;
}

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

重點整理

  • TLS 透過 TLS 握手加密 HTTP 流量、驗證伺服器並確保資料完整性。
  • TLS 1.3 比 TLS 1.2 更快、更安全。
  • Let’s Encrypt 提供免費的 DV 憑證,Certbot 自動化憑證的發行和續約。
  • 始終設定 HTTP 到 HTTPS 的重新導向並啟用 HSTS 標頭。
  • 使用 openssl s_client 和 SSL Labs 測試 TLS 設定。

下一步

在第 25 課中,您將學習如何在 Ubuntu 上部署 PHP 應用程式,包括安裝 PHP-FPM 及與 Apache 和 Nginx 的整合。

日本語

概要

  • 学習内容: TLS/SSL 暗号化の仕組み、証明書の種類と信頼チェーン、Let’s Encrypt と Certbot で無料証明書を取得する方法、Apache と Nginx での HTTPS 設定。
  • 前提条件: レッスン 22 — Apache2 ウェブサーバー、レッスン 23 — Nginx ウェブサーバー
  • 推定読了時間: 18 分

はじめに

トランスポート層セキュリティ(TLS)は、ウェブクライアントとサーバー間の通信を保護する暗号化プロトコルです。ブラウザのアドレスバーに南京錠のアイコンが表示されたり、URL が https:// で始まる場合、TLS が動作しています。

TLS は SSL(Secure Sockets Layer)プロトコルの後継です。現在のすべての実装は TLS(バージョン 1.2 および 1.3)を使用しています。

TLS の仕組み

TLS はトランスポート層とアプリケーション層の間で動作し、暗号化されたトンネルを作成します。TLS ハンドシェイクの手順:

  • クライアント Hello: サポートする TLS バージョン、暗号スイート、乱数を送信。
  • サーバー Hello: TLS バージョンと暗号スイートを選択し、証明書を送信。
  • 証明書検証: 信頼された認証局(CA)に対してサーバー証明書を検証。
  • 鍵交換: 非対称暗号を使用して共有セッション鍵を確立。
  • 暗号化通信: 以降のすべてのデータは共有セッション鍵で暗号化。

証明書の種類と信頼チェーン

  • ドメイン認証(DV): ドメインの所有権のみを確認。Let’s Encrypt が無料 DV 証明書を提供。
  • 組織認証(OV): ドメインの背後にある組織を確認。
  • 拡張認証(EV): 最高レベルの検証。

Let’s Encrypt と Certbot

# Certbot をインストール
$ sudo apt install certbot

# Apache プラグイン
$ sudo apt install python3-certbot-apache
$ sudo certbot --apache -d example.com

# Nginx プラグイン
$ sudo apt install python3-certbot-nginx
$ sudo certbot --nginx -d example.com

# 自動更新のテスト
$ sudo certbot renew --dry-run

Apache の HTTPS 設定

<VirtualHost *:443>
    ServerName example.com
    DocumentRoot /var/www/example.com/public_html
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    Header always set Strict-Transport-Security "max-age=31536000"
</VirtualHost>

Nginx の HTTPS 設定

server {
    listen 443 ssl http2;
    server_name example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    add_header Strict-Transport-Security "max-age=31536000" always;
}

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

重要ポイント

  • TLS は HTTP トラフィックを暗号化し、サーバーを認証し、データの完全性を保証する。
  • TLS 1.3 は TLS 1.2 より高速で安全。
  • Let’s Encrypt は無料の DV 証明書を提供し、Certbot が発行と更新を自動化。
  • HTTP から HTTPS へのリダイレクトと HSTS ヘッダーを常に設定する。
  • openssl s_client と SSL Labs で TLS 設定をテストする。

次のステップ

レッスン 25 では、Ubuntu に PHP アプリケーションをデプロイする方法を学びます。PHP-FPM のインストールと Apache/Nginx との統合を含みます。

You Missed