Mục lục

Không có mục lục
Tham gia kênh Telegram của CloudFly để nhận thêm ưu đãi và không bỏ lỡ bất kỳ khuyến mãi nào từ CloudFly

Cách bảo mật ứng dụng Node.js được đóng gói bằng Nginx, Let's Encrypt và Docker Compose

Ngày đăng: 1 tháng 4 năm 2024

Giới thiệu

Có nhiều cách để nâng cao tính linh hoạt và bảo mật cho ứng dụng Node.js của bạn. Sử dụng proxy ngược như Nginx sẽ cung cấp cho bạn các yêu cầu cân bằng tải, lưu trữ nội dung tĩnh và triển khai Transport Layer Security (TLS). Việc bật HTTPS được mã hóa trên máy chủ của bạn sẽ đảm bảo rằng hoạt động liên lạc đến và đi từ ứng dụng của bạn vẫn được an toàn.

Việc triển khai proxy ngược bằng TLS/SSL trên vùng chứa bao gồm một bộ quy trình khác với hoạt động trực tiếp trên hệ điều hành máy chủ. Ví dụ: nếu bạn đang lấy chứng chỉ từ Let's Encrypt cho một ứng dụng chạy trên máy chủ, bạn sẽ cài đặt phần mềm cần thiết trực tiếp trên máy chủ của mình. Vùng chứa cho phép bạn thực hiện một cách tiếp cận khác. Khi sử dụng Docker Compose, bạn có thể tạo các vùng chứa cho ứng dụng, máy chủ web và ứng dụng khách Certbot để cho phép bạn lấy chứng chỉ của mình. Bằng cách làm theo các bước này, bạn có thể tận dụng tính mô-đun và tính di động của quy trình làm việc được đóng gói.

Trong hướng dẫn này, bạn sẽ triển khai ứng dụng Node.js với proxy ngược Nginx bằng Docker Compose. Bạn sẽ nhận được chứng chỉ TLS/SSL cho miền được liên kết với ứng dụng của bạn và đảm bảo rằng nó nhận được xếp hạng bảo mật cao từ SSL Labs. Cuối cùng, bạn sẽ thiết lập một công việc cron để gia hạn chứng chỉ của mình và giúp miền của bạn luôn được bảo mật.

Điều kiện tiên quyết

Để làm theo hướng dẫn này, bạn sẽ cần:

  • Máy chủ Ubuntu 18.04, non-root user có đặc quyền sudo và tường lửa đang hoạt động. Để được hướng dẫn về cách thiết lập những thứ này, vui lòng đọc hướng dẫn Thiết lập máy chủ ban đầu với Ubuntu 18.04.
  • Docker và Docker Compose được cài đặt trên máy chủ của bạn. Để được hướng dẫn cài đặt Docker, hãy làm theo Bước 1 và 2 của Cách cài đặt và sử dụng Docker trên Ubuntu 18.04. Để được hướng dẫn cài đặt Compose, hãy làm theo Bước 1 của Cách cài đặt Docker Compose trên Ubuntu 18.04.
  • Một tên miền đã đăng ký. Hướng dẫn này sẽ sử dụng your_domain xuyên suốt. Bạn có thể đăng ký tên miền tại công ty mà bạn chọn, chẳng hạn như CloudFly.
  • Cả hai bản ghi DNS sau đây đều được thiết lập cho máy chủ của bạn.
    • Bản ghi A có your_domain trỏ đến địa chỉ IP công cộng của máy chủ của bạn.
    • Bản ghi A có www.your_domain trỏ đến địa chỉ IP công cộng của máy chủ của bạn.

Khi bạn đã thiết lập xong mọi thứ, bạn đã sẵn sàng bắt đầu bước đầu tiên.

Bước 1 - Nhân bản và kiểm tra ứng dụng node

Bước đầu tiên, bạn sẽ sao chép kho lưu trữ bằng mã ứng dụng Node, bao gồm Dockerfile để xây dựng hình ảnh ứng dụng của bạn bằng Compose. Sau đó, bạn sẽ kiểm tra ứng dụng bằng cách xây dựng và chạy nó bằng lệnh docker run mà không cần proxy ngược hoặc SSL.

Trong thư mục chính của non-root user của bạn, hãy sao chép kho lưu trữ nodejs-image-demo từ tài khoản GitHub. Kho lưu trữ này bao gồm mã từ quá trình thiết lập được mô tả trong Cách xây dựng ứng dụng Node.js bằng Docker.

Sao chép kho lưu trữ vào một thư mục. Ví dụ này sử dụng node_project làm tên thư mục. Hãy đặt tên thư mục này theo ý thích của bạn:

  1. git clone https://github.com/do-community/nodejs-image-demo.git node_project

Thay đổi vào thư mục node_project:

  1. cd node_project

Trong thư mục này, có một Dockerfile chứa hướng dẫn xây dựng ứng dụng Node bằng cách sử dụng hình ảnh Docker node:10 và nội dung của thư mục dự án hiện tại của bạn. Bạn có thể xem trước nội dung của Dockerfile bằng cách sau:

  1. cat Dockerfile
Output
FROM node:10-alpine RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app WORKDIR /home/node/app COPY package*.json ./ USER node RUN npm install COPY --chown=node:node . . EXPOSE 8080 CMD [ "node", "app.js" ]

Các hướng dẫn này xây dựng hình ảnh Node bằng cách sao chép mã dự án từ thư mục hiện tại vào vùng chứa và cài đặt các phần phụ thuộc bằng npm install. Họ cũng tận dụng bộ nhớ đệm và phân lớp hình ảnh của Docker bằng cách tách bản sao của pack.jsonpackage-lock.json, chứa các phần phụ thuộc được liệt kê của dự án, từ bản sao của phần còn lại của mã ứng dụng. Cuối cùng, hướng dẫn chỉ định rằng vùng chứa sẽ được chạy với tư cách là non-root node user với các quyền thích hợp được đặt trên mã ứng dụng và thư mục node_modules.

Để biết thêm thông tin về các phương pháp hay nhất về Dockerfile và hình ảnh Node này, vui lòng khám phá phần thảo luận đầy đủ trong Bước 3 của Cách xây dựng ứng dụng Node.js bằng Docker.

Để kiểm tra ứng dụng không có SSL, bạn có thể xây dựng và gắn thẻ hình ảnh bằng cách sử dụng docker build và cờ -t. Ví dụ này đặt tên cho hình ảnh node-demo, nhưng bạn có thể tự do đặt tên cho nó bằng tên khác:

  1. docker build -t node-demo .

Khi quá trình xây dựng hoàn tất, bạn có thể liệt kê hình ảnh của mình bằng docker images:

  1. docker images

Đầu ra sau đây xác nhận việc xây dựng hình ảnh ứng dụng:

Output
REPOSITORY TAG IMAGE ID CREATED SIZE node-demo latest 23961524051d 7 seconds ago 73MB node 10-alpine 8a752d5af4ce 3 weeks ago 70.7MB

Tiếp theo, tạo vùng chứa bằng docker run. Ba cờ được bao gồm trong lệnh này:

  • -p: Điều này xuất bản cổng trên vùng chứa và ánh xạ nó tới một cổng trên máy chủ của bạn. Bạn sẽ sử dụng cổng 80 trên máy chủ trong ví dụ này, nhưng vui lòng sửa đổi cổng này nếu cần nếu bạn có một quy trình khác đang chạy trên cổng đó. Để biết thêm thông tin về cách thức hoạt động của tính năng này, hãy xem lại cuộc thảo luận này trong tài liệu Docker về liên kết cổng.
  • -d: Cái này chạy container ở chế độ nền.
  • --name: Điều này cho phép bạn đặt cho vùng chứa một cái tên dễ nhớ.

Chạy lệnh sau để xây dựng vùng chứa:

  1. docker run --name node-demo -p 80:8080 -d node-demo

Kiểm tra các container đang chạy của bạn bằng docker ps:

  1. docker ps

Đầu ra sau đây xác nhận rằng vùng chứa ứng dụng của bạn đang chạy:

Output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4133b72391da node-demo "node app.js" 17 seconds ago Up 16 seconds 0.0.0.0:80->8080/tcp node-demo

Bây giờ bạn có thể truy cập miền của mình để kiểm tra thiết lập của mình: http://your_domain. Hãy nhớ thay thế your_domain bằng tên miền của riêng bạn. Ứng dụng của bạn sẽ hiển thị trang đích sau:

description image

Bây giờ bạn đã kiểm tra ứng dụng, bạn có thể dừng vùng chứa và xóa hình ảnh. Sử dụng docker ps để lấy CONTAINER ID của bạn:

  1. docker ps
Output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4133b72391da node-demo "node app.js" 17 seconds ago Up 16 seconds 0.0.0.0:80->8080/tcp node-demo

Dừng vùng chứa bằng docker stop. Đảm bảo thay thế CONTAINER ID được liệt kê ở đây bằng CONTAINER ID ứng dụng của riêng bạn:

  1. docker stop 4133b72391da

Bây giờ bạn có thể xóa vùng chứa đã dừng và tất cả các hình ảnh, bao gồm cả hình ảnh không được sử dụng và hình ảnh lơ lửng (dangling images), bằng docker system prune và cờ -a:

  1. docker system prune -a

Nhấn y khi được nhắc ở đầu ra để xác nhận rằng bạn muốn xóa vùng chứa và hình ảnh đã dừng. Xin lưu ý rằng thao tác này cũng sẽ xóa bộ nhớ đệm bản dựng của bạn.

Sau khi thử nghiệm hình ảnh ứng dụng, bạn có thể chuyển sang xây dựng phần còn lại của thiết lập bằng Docker Compose.

Bước 2 - Xác định cấu hình máy chủ web

Với ứng dụng Dockerfile của chúng ta đã có sẵn, bạn sẽ tạo một tệp cấu hình để chạy vùng chứa Nginx của mình. Bạn có thể bắt đầu với cấu hình tối thiểu bao gồm tên miền, gốc tài liệu, thông tin proxy và khối vị trí để chuyển các yêu cầu của Certbot tới thư mục .well-known, nơi nó sẽ đặt một tệp tạm thời để xác thực DNS cho của bạn tên miền phân giải đến máy chủ của bạn.

Đầu tiên, tạo một thư mục trong thư mục dự án hiện tại, node_project, cho tệp cấu hình:

  1. mkdir nginx-conf

Tạo và mở tệp bằng nano hoặc trình chỉnh sửa yêu thích của bạn:

  1. nano nginx-conf/nginx.conf

Thêm khối máy chủ sau vào các yêu cầu của proxy user vào vùng chứa ứng dụng Node của bạn và chuyển các yêu cầu của Certbot tới thư mục .well-known. Đảm bảo thay thế your_domain bằng tên miền của riêng bạn:

~/node_project/nginx-conf/nginx.conf
server {
        listen 80;
        listen [::]:80;

        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;

        server_name your_domain www.your_domain;

        location / {
                proxy_pass http://nodejs:8080;
        }

        location ~ /.well-known/acme-challenge {
                allow all;
                root /var/www/html;
        }
}

Khối máy chủ này sẽ cho phép bạn khởi động vùng chứa Nginx làm proxy ngược, nó sẽ chuyển các yêu cầu đến vùng chứa ứng dụng Node của bạn. Nó cũng sẽ cho phép bạn sử dụng plugin webroot của Certbot để lấy chứng chỉ cho miền của bạn. Plugin này phụ thuộc vào phương thức xác thực HTTP-01, sử dụng yêu cầu HTTP để chứng minh rằng Certbot có thể truy cập tài nguyên từ máy chủ phản hồi một tên miền nhất định.

Sau khi chỉnh sửa xong, hãy lưu và đóng tệp. Nếu bạn đã sử dụng nano, bạn có thể thực hiện việc này bằng cách nhấn CTRL + X, sau đó là YENTER. Để tìm hiểu thêm về máy chủ Nginx và thuật toán khối vị trí, vui lòng tham khảo bài viết về Tìm hiểu thuật toán lựa chọn khối vị trí và máy chủ Nginx.

Với các chi tiết cấu hình máy chủ web đã có, bạn có thể chuyển sang tạo tệp docker-compose.yml, tệp này sẽ cho phép bạn tạo các dịch vụ ứng dụng và vùng chứa Certbot mà bạn sẽ sử dụng để lấy chứng chỉ của mình.

Bước 3 - Tạo tệp Docker Compose

Tệp docker-compose.yml sẽ xác định các dịch vụ của bạn, bao gồm ứng dụng Node và máy chủ web. Nó sẽ chỉ định các chi tiết như khối lượng (volumes) được đặt tên, điều này sẽ rất quan trọng để chia sẻ thông tin xác thực SSL giữa các vùng chứa, cũng như thông tin mạng và cổng. Nó cũng sẽ cho phép bạn chỉ định các lệnh sẽ chạy khi vùng chứa của bạn được tạo. Tệp này là tài nguyên trung tâm sẽ xác định cách các dịch vụ của bạn sẽ hoạt động cùng nhau.

Tạo và mở tệp trong thư mục hiện tại của bạn:

  1. nano docker-compose.yml

Đầu tiên, xác định dịch vụ ứng dụng:

~/node_project/docker-compose.yml
version: '3'

services:
  nodejs:
    build:
      context: .
      dockerfile: Dockerfile
    image: nodejs
    container_name: nodejs
    restart: unless-stopped

Định nghĩa dịch vụ của nodejs bao gồm:

  • build: Phần này xác định các tùy chọn cấu hình, bao gồm contextdockerfile, sẽ được áp dụng khi Compose xây dựng hình ảnh ứng dụng. Nếu muốn sử dụng hình ảnh hiện có từ sổ đăng ký như Docker Hub, bạn có thể sử dụng hướng dẫn image thay thế, kèm theo thông tin về tên người dùng, kho lưu trữ và thẻ hình ảnh của bạn.
  • context: Điều này xác định bối cảnh xây dựng cho hình ảnh ứng dụng build. Trong trường hợp này, đó là thư mục dự án hiện tại được biểu thị bằng phần mở rộng ..
  • dockerfile: Điều này chỉ định Dockerfile mà Compose sẽ sử dụng cho bản dựng - Dockerfile đã được xem xét ở Bước 1.
  • image, container_name: Những tên này áp dụng cho hình ảnh và vùng chứa.
  • restart: Điều này xác định chính sách khởi động lại. Mặc định là no, nhưng trong ví dụ này, vùng chứa được đặt để khởi động lại trừ khi nó bị dừng.

Lưu ý rằng bạn không bao gồm các liên kết gắn kết với dịch vụ này vì thiết lập của bạn tập trung vào việc triển khai hơn là phát triển. Để biết thêm thông tin, vui lòng đọc tài liệu Docker về bind mounts và volumes.

Để cho phép liên lạc giữa ứng dụng và vùng chứa máy chủ web, hãy thêm bridge network có tên là app-network sau định nghĩa khởi động lại:

~/node_project/docker-compose.yml
services:
  nodejs:
...
    networks:
      - app-network

Bridge network do người dùng xác định như thế này cho phép liên lạc giữa các vùng chứa trên cùng một máy chủ Docker daemon. Điều này hợp lý hóa lưu lượng truy cập và liên lạc trong ứng dụng của bạn, vì nó mở tất cả các cổng giữa các vùng chứa trên cùng một bridge network, trong khi không để lộ cổng nào ra thế giới bên ngoài. Do đó, bạn có thể chọn lọc chỉ mở các cổng bạn cần để hiển thị các dịch vụ giao diện người dùng của mình.

Tiếp theo, xác định dịch vụ webserver:

~/node_project/docker-compose.yml
...
 webserver:
    image: nginx:mainline-alpine
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - web-root:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
    depends_on:
      - nodejs
    networks:
      - app-network

Một số cài đặt được xác định ở đây cho dịch vụ nodejs vẫn giữ nguyên, nhưng một số thay đổi sau đã được thực hiện:

  • image: Lệnh này yêu cầu Compose lấy hình ảnh Nginx dựa trên Alpine mới nhất từ Docker Hub. Để biết thêm thông tin về hình ảnh alpine, vui lòng đọc Bước 3 của Cách xây dựng ứng dụng Node.js bằng Docker.
  • ports: Điều này hiển thị cổng 80 để kích hoạt các tùy chọn cấu hình mà bạn đã xác định trong cấu hình Nginx của mình.

Các volumes và bind mounts được đặt tên sau đây cũng được chỉ định:

  • web-root:/var/www/html: Điều này sẽ thêm nội dung tĩnh của trang web của bạn, được sao chép vào một ổ đĩa có tên là web-root, vào thư mục /var/www/html trên vùng chứa.
  • ./nginx-conf:/etc/nginx/conf.d: Điều này sẽ liên kết gắn thư mục cấu hình Nginx trên máy chủ với thư mục có liên quan trên vùng chứa, đảm bảo rằng mọi thay đổi bạn thực hiện đối với các tệp trên máy chủ sẽ được phản ánh trong vùng chứa.
  • certbot-etc:/etc/letsencrypt: Điều này sẽ gắn các chứng chỉ và khóa Let's Encrypt có liên quan cho miền của bạn vào thư mục thích hợp trên vùng chứa.
  • certbot-var:/var/lib/letsencrypt: Điều này gắn kết thư mục làm việc mặc định của Let's Encrypt vào thư mục thích hợp trên vùng chứa.

Tiếp theo, thêm các tùy chọn cấu hình cho vùng chứa certbot. Đảm bảo thay thế thông tin tên miền và email bằng tên miền và email liên hệ của riêng bạn:

~/node_project/docker-compose.yml
...
  certbot:
    image: certbot/certbot
    container_name: certbot
    volumes:
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
      - web-root:/var/www/html
    depends_on:
      - webserver
    command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain  -d www.your_domain

Định nghĩa này yêu cầu Compose lấy hình ảnh certbot/certbot từ Docker Hub. Nó cũng sử dụng các volumes được đặt tên để chia sẻ tài nguyên với bộ chứa Nginx, bao gồm chứng chỉ miền và khóa trong certbot-etc, thư mục làm việc Let's Encrypt trong certbot-var và mã ứng dụng trong web-root.

Một lần nữa, bạn đã sử dụng depends_on để chỉ định rằng vùng chứa certbot sẽ được khởi động sau khi dịch vụ webserver đang chạy.

Tùy chọn command chỉ định lệnh sẽ chạy khi vùng chứa được khởi động. Nó bao gồm lệnh con certonly với các tùy chọn sau:

  • --webroot: Điều này yêu cầu Certbot sử dụng plugin webroot để đặt các tệp vào thư mục webroot để xác thực.
  • --webroot-path: Điều này chỉ định đường dẫn của thư mục webroot.
  • --email: Email ưa thích của bạn để đăng ký và khôi phục.
  • --agree-tos: Điều này xác định rằng bạn đồng ý với Thỏa thuận thuê bao của ACME.
  • --no-eff-email: Điều này cho Certbot biết rằng bạn không muốn chia sẻ email của mình với Electronic Frontier Foundation (EFF). Hãy bỏ qua điều này nếu bạn muốn.
  • --staging: Điều này cho Certbot biết rằng bạn muốn sử dụng môi trường chạy thử của Let's Encrypt để lấy chứng chỉ kiểm tra. Việc sử dụng tùy chọn này cho phép bạn kiểm tra các tùy chọn cấu hình của mình và tránh các giới hạn yêu cầu tên miền có thể có. Để biết thêm thông tin về các giới hạn này, vui lòng đọc tài liệu về giới hạn tốc độ của Let's Encrypt.
  • -d: Điều này cho phép bạn chỉ định tên miền bạn muốn áp dụng cho yêu cầu của mình. Trong trường hợp này, bạn đã bao gồm your_domainwww.your_domain. Hãy chắc chắn thay thế chúng bằng tên miền của riêng bạn.

Bước cuối cùng, thêm định nghĩa volume và network. Hãy nhớ thay thế tên người dùng ở đây bằng non-root user của riêng bạn:

~/node_project/docker-compose.yml
...
volumes:
  certbot-etc:
  certbot-var:
  web-root:
    driver: local
    driver_opts:
      type: none
      device: /home/sammy/node_project/views/
      o: bind

networks:
  app-network:
    driver: bridge

Volumes được đặt tên của bạn bao gồm chứng chỉ Certbot và volumes thư mục làm việc của bạn và volumes cho tài nguyên tĩnh trên trang web của bạn, web-root. Trong hầu hết các trường hợp, trình điều khiển mặc định cho tập Docker là trình điều khiển local, trên Linux chấp nhận các tùy chọn tương tự như lệnh mount. Nhờ điều này, bạn có thể chỉ định danh sách các tùy chọn trình điều khiển với driver_opts, gắn thư mục views trên máy chủ, trong đó chứa các tài nguyên tĩnh ứng dụng của bạn, vào volume khi chạy. Nội dung thư mục sau đó có thể được chia sẻ giữa các vùng chứa. Để biết thêm thông tin về nội dung của thư mục views, vui lòng đọc Bước 2 về cách xây dựng ứng dụng Node.js với Docker.

Sau đây là tệp docker-compose.yml hoàn chỉnh:

~/node_project/docker-compose.yml
version: '3'

services:
  nodejs:
    build:
      context: .
      dockerfile: Dockerfile
    image: nodejs
    container_name: nodejs
    restart: unless-stopped
    networks:
      - app-network

  webserver:
    image: nginx:mainline-alpine
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - web-root:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
    depends_on:
      - nodejs
    networks:
      - app-network

  certbot:
    image: certbot/certbot
    container_name: certbot
    volumes:
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
      - web-root:/var/www/html
    depends_on:
      - webserver
    command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain  -d www.your_domain 

volumes:
  certbot-etc:
  certbot-var:
  web-root:
    driver: local
    driver_opts:
      type: none
      device: /home/sammy/node_project/views/
      o: bind

networks:
  app-network:
    driver: bridge

Với các định nghĩa dịch vụ được áp dụng bạn đã sẵn sàng khởi động vùng chứa và kiểm tra các yêu cầu chứng chỉ của mình.

Bước 4 - Lấy chứng chỉ và thông tin xác thực SSL

Bạn có thể khởi động các vùng chứa bằng docker-compose up. Điều này sẽ tạo và chạy các vùng chứa và dịch vụ của bạn theo thứ tự bạn đã chỉ định. Sau khi yêu cầu miền của bạn thành công, chứng chỉ của bạn sẽ được gắn vào thư mục /etc/letsencrypt/live trên vùng chứa webserver.

Tạo các dịch vụ với docker-compose up bằng cờ -d, cờ này sẽ chạy các vùng chứa nodejswebserver trong nền:

  1. docker-compose up -d

Đầu ra của bạn sẽ xác nhận rằng dịch vụ của bạn đã được tạo:

Output
Creating nodejs ... done Creating webserver ... done Creating certbot ... done

Sử dụng docker-compose ps để kiểm tra trạng thái dịch vụ của bạn:

  1. docker-compose ps

Nếu mọi thứ đều thành công, các dịch vụ nodejswebserver của bạn sẽ Up và vùng chứa certbot sẽ thoát với thông báo trạng thái 0:

Output
Name Command State Ports ------------------------------------------------------------------------ certbot certbot certonly --webroot ... Exit 0 nodejs node app.js Up 8080/tcp webserver nginx -g daemon off; Up 0.0.0.0:80->80/tcp

Nếu bạn nhận thấy bất cứ điều gì khác ngoài Up trong cột State đối với các dịch vụ nodejswebserver hoặc trạng thái thoát khác 0 đối với vùng chứa certbot, hãy nhớ kiểm tra nhật ký dịch vụ bằng lệnh docker-compose logs. Ví dụ: nếu bạn muốn kiểm tra nhật ký Certbot, bạn sẽ chạy:

  1. docker-compose logs certbot

Bây giờ bạn có thể kiểm tra xem thông tin đăng nhập của bạn đã được gắn vào vùng chứa webserver hay chưa bằng docker-compose exec:

  1. docker-compose exec webserver ls -la /etc/letsencrypt/live

Khi yêu cầu của bạn thành công, đầu ra của bạn sẽ hiển thị như sau:

Output
total 16 drwx------ 3 root root 4096 Dec 23 16:48 . drwxr-xr-x 9 root root 4096 Dec 23 16:48 .. -rw-r--r-- 1 root root 740 Dec 23 16:48 README drwxr-xr-x 2 root root 4096 Dec 23 16:48 your_domain

Bây giờ bạn biết yêu cầu của mình sẽ thành công, bạn có thể chỉnh sửa định nghĩa dịch vụ certbot để xóa cờ --staging.

Mở tệp docker-compose.yml:

  1. nano docker-compose.yml

Tìm phần của tệp có định nghĩa dịch vụ certbot và thay thế cờ --staging trong tùy chọn command bằng cờ --force-renewal. Điều này sẽ cho Certbot biết rằng bạn muốn yêu cầu chứng chỉ mới có cùng tên miền với chứng chỉ hiện có. Định nghĩa dịch vụ certbot phải có các định nghĩa sau:

~/node_project/docker-compose.yml
...
  certbot:
    image: certbot/certbot
    container_name: certbot
    volumes:
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
      - web-root:/var/www/html
    depends_on:
      - webserver
    command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
...

Khi bạn chỉnh sửa xong, hãy lưu và thoát tệp. Bây giờ bạn có thể chạy docker-compose up để tạo lại vùng chứa certbot và các volumes liên quan của nó. Bằng cách bao gồm tùy chọn --no-deps, bạn đang thông báo cho Compose rằng Compose có thể bỏ qua việc khởi động dịch vụ webserver vì nó đã chạy:

  1. docker-compose up --force-recreate --no-deps certbot

Kết quả đầu ra sau đây cho biết yêu cầu chứng chỉ của bạn đã thành công:

Output
Recreating certbot ... done Attaching to certbot certbot | Account registered. certbot | Renewing an existing certificate for your_domain and www.your_domain certbot | certbot | Successfully received certificate. certbot | Certificate is saved at: /etc/letsencrypt/live/your_domain/fullchain.pem certbot | Key is saved at: /etc/letsencrypt/live/your_domain phd.com/privkey.pem certbot | This certificate expires on 2022-11-03. certbot | These files will be updated when the certificate renews. certbot | NEXT STEPS: certbot | - The certificate will need to be renewed before it expires. Cert bot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setu p for instructions. certbot | Saving debug log to /var/log/letsencrypt/letsencrypt.log certbot | certbot | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - certbot | If you like Certbot, please consider supporting our work by: certbot | * Donating to ISRG / Let's Encrypt: https://letsencrypt.org/do nate certbot | * Donating to EFF: https://eff.org/donate-le certbot | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - certbot exited with code 0

Với chứng chỉ đã có, bạn có thể chuyển sang sửa đổi cấu hình Nginx của mình để bao gồm SSL.

Bước 5 - Sửa đổi cấu hình máy chủ web và định nghĩa dịch vụ

Việc bật SSL trong cấu hình Nginx của bạn sẽ liên quan đến việc thêm chuyển hướng HTTP vào HTTPS và chỉ định chứng chỉ SSL cũng như các vị trí chính của bạn. Nó cũng sẽ liên quan đến việc chỉ định nhóm Diffie-Hellman mà bạn sẽ sử dụng cho Perfect Forward Secrecy.

Vì bạn sắp tạo lại dịch vụ webserver để bao gồm những phần bổ sung này nên bạn có thể dừng dịch vụ đó ngay bây giờ:

  1. docker-compose stop webserver

Tiếp theo, tạo một thư mục trong thư mục dự án hiện tại của bạn cho khóa Diffie-Hellman:

  1. mkdir dhparam

Tạo khóa của bạn bằng lệnh openssl:

  1. sudo openssl dhparam -out /home/sammy/node_project/dhparam/dhparam-2048.pem 2048

Sẽ mất một chút thời gian để tạo khóa.

Để thêm thông tin Diffie-Hellman và SSL có liên quan vào cấu hình Nginx của bạn, trước tiên hãy xóa tệp cấu hình Nginx bạn đã tạo trước đó:

  1. rm nginx-conf/nginx.conf

Mở phiên bản khác của tệp:

  1. nano nginx-conf/nginx.conf

Thêm mã sau vào tệp để chuyển hướng HTTP sang HTTPS và thêm thông tin xác thực, giao thức và tiêu đề bảo mật SSL. Hãy nhớ thay thế your_domain bằng tên miền của riêng bạn:

~/node_project/nginx-conf/nginx.conf
server {
        listen 80;
        listen [::]:80;
        server_name your_domain www.your_domain;

        location ~ /.well-known/acme-challenge {
          allow all;
          root /var/www/html;
        }

        location / {
                rewrite ^ https://$host$request_uri? permanent;
        }
}

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name your_domain www.your_domain;

        server_tokens off;

        ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;

        ssl_buffer_size 8k;

        ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

        ssl_protocols TLSv1.2;
        ssl_prefer_server_ciphers on;

        ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

        ssl_ecdh_curve secp384r1;
        ssl_session_tickets off;

        ssl_stapling on;
        ssl_stapling_verify on;
        resolver 8.8.8.8;

        location / {
                try_files $uri @nodejs;
        }

        location @nodejs {
                proxy_pass http://nodejs:8080;
                add_header X-Frame-Options "SAMEORIGIN" always;
                add_header X-XSS-Protection "1; mode=block" always;
                add_header X-Content-Type-Options "nosniff" always;
                add_header Referrer-Policy "no-referrer-when-downgrade" always;
                add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
                #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
                # enable strict transport security only if you understand the implications
        }

        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;
}

Khối máy chủ HTTP chỉ định webroot cho các yêu cầu gia hạn Certbot tới thư mục .well-known/acme-challenge. Nó cũng bao gồm một lệnh viết lại hướng các yêu cầu HTTP đến thư mục gốc tới HTTPS.

Khối máy chủ HTTPS cho phép sslhttp2. Để đọc thêm về cách HTTP/2 lặp lại trên các giao thức HTTP và những lợi ích mà nó có thể mang lại cho hiệu suất trang web, vui lòng đọc phần giới thiệu về Cách thiết lập Nginx với hỗ trợ HTTP/2 trên Ubuntu 18.04. Khối này cũng bao gồm một loạt tùy chọn để đảm bảo rằng bạn đang sử dụng các giao thức và mật mã SSL cập nhật nhất cũng như tính năng ghim OSCP được bật. Việc ghim OSCP cho phép bạn đưa ra phản hồi theo thời gian từ cơ quan cấp chứng chỉ của bạn trong quá trình TLS handshake ban đầu, điều này có thể tăng tốc quá trình xác thực.

Khối này cũng chỉ định thông tin xác thực SSL và Diffie-Hellman cũng như các vị trí chính của bạn.

Cuối cùng, bạn đã di chuyển thông tin chuyển proxy sang khối này, bao gồm khối vị trí có lệnh try_files, trỏ yêu cầu tới vùng chứa ứng dụng Node.js bí danh của bạn và khối vị trí cho bí danh đó, bao gồm các tiêu đề bảo mật sẽ cho phép bạn để nhận được xếp hạng A về những thứ như trang web thử nghiệm máy chủ SSL Labs và Security Headers. Các tiêu đề này bao gồm X-Frame-Options, X-Content-Type-Options, Referrer Policy, Content-Security-Policy, và X-XSS-Protection. Tiêu đề HTTP Strict Transport Security (HSTS) đã được nhận xét - chỉ bật tiêu đề này nếu bạn hiểu ý nghĩa và đã đánh giá chức năng "preload" của nó.

Sau khi chỉnh sửa xong, hãy lưu và đóng tệp.

Trước khi tạo lại dịch vụ webserver, bạn cần thêm một số nội dung vào định nghĩa dịch vụ trong tệp docker-compose.yml, bao gồm thông tin cổng có liên quan cho HTTPS và định nghĩa volume Diffie-Hellman.

Mở tập tin:

  1. nano docker-compose.yml

Trong định nghĩa dịch vụ webserver, hãy thêm ánh xạ cổng dưới đây và volume có tên dhparam:

~/node_project/docker-compose.yml
...
 webserver:
    image: nginx:latest
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - web-root:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
      - dhparam:/etc/ssl/certs
    depends_on:
      - nodejs
    networks:
      - app-network

Tiếp theo, thêm volume dhparam vào định nghĩa volumes của bạn. Hãy nhớ thay thế các thư mục sammynode_project để khớp với thư mục của bạn:

~/node_project/docker-compose.yml
...
volumes:
  ...
  webroot:
  ...
  dhparam:
    driver: local
    driver_opts:
      type: none
      device: /home/sammy/node_project/dhparam/
      o: bind

Tương tự như volume web-root, volume dhparam sẽ gắn khóa Diffie-Hellman được lưu trữ trên máy chủ vào vùng chứa webserver.

Lưu và đóng tệp khi bạn chỉnh sửa xong.

Tạo lại dịch vụ webserver:

  1. docker-compose up -d --force-recreate --no-deps webserver

Kiểm tra dịch vụ của bạn với docker-compose ps:

  1. docker-compose ps

Đầu ra sau cho biết rằng các dịch vụ nodejswebserver của bạn đang chạy:

Output
Name Command State Ports ---------------------------------------------------------------------------------------------- certbot certbot certonly --webroot ... Exit 0 nodejs node app.js Up 8080/tcp webserver nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp

Cuối cùng, bạn có thể truy cập miền của mình để đảm bảo rằng mọi thứ đều hoạt động như mong đợi. Điều hướng trình duyệt của bạn tới https://your_domain, đảm bảo thay thế your_domain bằng tên miền của riêng bạn:

description image

Biểu tượng lock sẽ xuất hiện trong chỉ báo bảo mật của trình duyệt của bạn. Nếu muốn, bạn có thể điều hướng đến trang đích SSL Labs Server Test hoặc trang đích Security Headers server test. Các tùy chọn cấu hình được bao gồm sẽ giúp trang web của bạn được xếp hạng A trong SSL Labs Server Test. Để nhận được xếp hạng A trong Security Headers server test, bạn sẽ phải bỏ ghi chú tiêu đề Strict Transport Security (HSTS) trong tệp nginx-conf/nginx.conf của mình:

~/node_project/nginx-conf/nginx.conf
location @nodejs {
                proxy_pass http://nodejs:8080;
                add_header X-Frame-Options "SAMEORIGIN" always;
                add_header X-XSS-Protection "1; mode=block" always;
                add_header X-Content-Type-Options "nosniff" always;
                add_header Referrer-Policy "no-referrer-when-downgrade" always;
                add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
                add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
                # enable strict transport security only if you understand the implications
        }

Một lần nữa, chỉ bật tùy chọn này nếu bạn hiểu ý nghĩa và đã đánh giá chức năng “preload” của nó.

Bước 6 - Gia hạn chứng chỉ

Chứng chỉ Let’s Encrypt có hiệu lực trong 90 ngày. Bạn có thể thiết lập quy trình gia hạn tự động để đảm bảo rằng chúng không bị mất hiệu lực. Một cách để làm điều này là tạo một công việc bằng tiện ích lập lịch trình cron. Bạn có thể lên lịch công việc cron bằng cách sử dụng tập lệnh sẽ gia hạn chứng chỉ và tải lại cấu hình Nginx của bạn.

Mở tập lệnh có tên ssl_renew.sh trong thư mục dự án của bạn:

  1. nano ssl_renew.sh

Thêm mã sau vào tập lệnh để gia hạn chứng chỉ và tải lại cấu hình máy chủ web của bạn:

[label ~/node_project/ssl_renew.sh
]
#!/bin/bash

COMPOSE="/usr/local/bin/docker-compose --ansi never"
DOCKER="/usr/bin/docker"

cd /home/sammy/node_project/
$COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver
$DOCKER system prune -af

Tập lệnh này trước tiên gán tệp nhị phân docker-compose cho một biến có tên COMPOSE và chỉ định tùy chọn --no-ansi, tùy chọn này sẽ chạy các lệnh docker-compose mà không có ký tự điều khiển ANSI. Sau đó nó thực hiện tương tự với docker nhị phân. Cuối cùng, nó thay đổi thư mục ~/node_project và chạy các lệnh docker-compose sau:

  • docker-compose run: Điều này sẽ khởi động vùng chứa certbot và ghi đè command được cung cấp trong định nghĩa dịch vụ certbot. Thay vì sử dụng lệnh con certonly, hãy sử dụng lệnh con renew, lệnh này sẽ gia hạn các chứng chỉ sắp hết hạn. Cũng bao gồm tùy chọn --dry-run để kiểm tra tập lệnh.
  • docker-compose kill: Điều này sẽ gửi tín hiệu SIGHUP đến vùng chứa webserver để tải lại cấu hình Nginx.

Sau đó, nó chạy docker system prune để loại bỏ tất cả các vùng chứa và hình ảnh không sử dụng.

Đóng tệp khi bạn chỉnh sửa xong, sau đó làm cho nó có thể thực thi được:

  1. chmod +x ssl_renew.sh

Tiếp theo, mở tệp crontab root của bạn để chạy tập lệnh gia hạn theo một khoảng thời gian nhất định:

sudo crontab -e 

Nếu đây là lần đầu tiên bạn chỉnh sửa tệp này, bạn sẽ được yêu cầu chọn một trình chỉnh sửa:

crontab
no crontab for root - using an empty one
Select an editor.  To change later, run 'select-editor'.
  1. /bin/ed
  2. /bin/nano        <---- easiest
  3. /usr/bin/vim.basic
  4. /usr/bin/vim.tiny
Choose 1-4 [2]: 
...

Ở cuối tập tin, thêm dòng sau:

crontab
...
*/5 * * * * /home/sammy/node_project/ssl_renew.sh >> /var/log/cron.log 2>&1

Thao tác này sẽ đặt khoảng thời gian thực hiện công việc là 5 phút một lần, do đó bạn có thể kiểm tra xem yêu cầu gia hạn của mình có hoạt động như dự kiến hay không. Bạn cũng đã tạo một tệp nhật ký, cron.log, để ghi lại kết quả đầu ra liên quan từ công việc.

Sau năm phút, hãy kiểm tra cron.log để xác nhận xem yêu cầu gia hạn có thành công hay không:

  1. tail -f /var/log/cron.log

Sau một lúc, đầu ra sau đây báo hiệu việc gia hạn thành công:

Output
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates below have not been saved.) Congratulations, all renewals succeeded. The following certs have been renewed: /etc/letsencrypt/live/your_domain/fullchain.pem (success) ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates above have not been saved.) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Killing webserver ... done
Output
… Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/your_domain/fullchain.pem (success) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Saving debug log to /var/log/letsencrypt/letsencrypt.log Killing webserver ... Killing webserver ... done Deleted Containers: 00cad94050985261e5b377de43e314b30ad0a6a724189753a9a23ec76488fd78 Total reclaimed space: 824.5kB

Thoát ra bằng cách nhập CTRL + C trong thiết bị đầu cuối của bạn.

Bây giờ bạn có thể sửa đổi tệp crontab để đặt khoảng thời gian hàng ngày. Ví dụ: để chạy tập lệnh hàng ngày vào buổi trưa, bạn có thể sửa đổi dòng cuối cùng của tệp như sau:

crontab
...
0 12 * * * /home/sammy/node_project/ssl_renew.sh >> /var/log/cron.log 2>&1

Bạn cũng có thể xóa tùy chọn --dry-run khỏi tập lệnh ssl_renew.sh của mình:

~/node_project/ssl_renew.sh
#!/bin/bash

COMPOSE="/usr/local/bin/docker-compose --no-ansi"
DOCKER="/usr/bin/docker"

cd /home/sammy/node_project/
$COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver
$DOCKER system prune -af

Công việc cron của bạn sẽ đảm bảo rằng chứng chỉ Let's Encrypt của bạn không bị mất hiệu lực khi gia hạn nếu chúng đủ điều kiện. Bạn cũng có thể thiết lập xoay vòng nhật ký bằng tiện ích Logrotate để xoay và nén các tệp nhật ký của mình.

Kết luận

Bạn đã sử dụng vùng chứa để thiết lập và chạy ứng dụng Node với proxy ngược Nginx. Bạn cũng đã bảo mật chứng chỉ SSL cho miền ứng dụng của mình và thiết lập công việc cron để gia hạn các chứng chỉ này khi cần thiết.

Nếu bạn muốn tìm hiểu thêm về plugin Let's Encrypt, vui lòng xem lại bài viết của chúng tôi về cách sử dụng plugin Nginx hoặc plugin độc lập.

Bạn cũng có thể tìm hiểu thêm về Docker Compose bằng các tài nguyên sau:

  • Cách cài đặt Docker Compose trên Ubuntu 18.04.
  • Cách định cấu hình môi trường thử nghiệm tích hợp liên tục với Docker và Docker Compose trên Ubuntu 16.04.
  • Cách thiết lập Laravel, Nginx và MySQL với Docker Compose.
Tham gia kênh Telegram của CloudFly để nhận thêm ưu đãi và không bỏ lỡ bất kỳ khuyến mãi nào từ CloudFly
Chia sẻ

0 câu trả lời