Thứ sáu, 04/01/2019 | 00:00 GMT+7

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

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 reverse-proxy như Nginx cung cấp cho bạn khả năng tải các yêu cầu cân bằng, lưu nội dung tĩnh vào bộ nhớ cache và triển khai Bảo mật lớp truyền tải (TLS). Việc bật HTTPS được mã hóa trên server của bạn đảm bảo liên lạc đến và đi từ ứng dụng của bạn vẫn an toàn.

Việc triển khai Reverse Proxy với TLS / SSL trên các containers bao gồm một loạt các quy trình khác với việc làm việc trực tiếp trên hệ điều hành server . Ví dụ: nếu bạn đang nhận certificate từ Let's Encrypt cho một ứng dụng chạy trên server , bạn sẽ cài đặt phần mềm cần thiết trực tiếp trên server của bạn . Vùng chứa cho phép bạn thực hiện một cách tiếp cận khác. Sử dụng Docker Compose , bạn có thể tạo containers cho ứng dụng, web server của bạn và ứng dụng client Certbot để cho phép bạn lấy certificate của bạn . Theo các bước này, bạn có thể tận dụng tính module 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 Reverse Proxy Nginx bằng Docker Compose. Bạn sẽ nhận được certificate TLS / SSL cho domain được liên kết với ứng dụng của bạn và đảm bảo domain đó nhận được xếp hạng bảo mật cao từ SSL Labs . Cuối cùng, bạn sẽ cài đặt một cron việc cron để gia hạn certificate của bạn để domain của bạn vẫn an toàn.

Yêu cầu

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

  • Server Ubuntu 18.04, user không phải root có quyền sudo và firewall đang hoạt động. Để được hướng dẫn về cách cài đặt những điều này, vui lòng xem hướng dẫn Cài đặt Server Ban đầu này.
  • Docker và Docker Compose được cài đặt trên server 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 Soạn thư, hãy làm theo Bước 1 của Cách cài đặt Docker Compose trên Ubuntu 18.04 .
  • Tên domain đã đăng ký. Hướng dẫn này sẽ sử dụng example.com xuyên suốt. Bạn có thể nhận một miễn phí tại Freenom hoặc sử dụng công ty đăng ký domain mà bạn chọn.
  • Cả hai bản ghi DNS sau được cài đặt cho server của bạn. Bạn có thể theo dõi phần giới thiệu này về DigitalOcean DNS để biết chi tiết về cách thêm chúng vào account DigitalOcean, nếu đó là những gì bạn đang sử dụng:

    • Bản ghi A với example.com trỏ đến địa chỉ IP công cộng của server của bạn.
    • Một bản ghi A với www. example.com trỏ đến địa chỉ IP công cộng của server của bạn.

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

Bước đầu tiên, ta sẽ sao chép repository với mã ứng dụng Node, bao gồm Dockerfile mà ta sẽ sử dụng để xây dựng hình ảnh ứng dụng của bạn bằng Compose. Trước tiên, ta có thể 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 Reverse Proxy hoặc SSL.

Trong folder chính của user không phải root của bạn, sao chép kho lưu trữ nodejs-image-demo từ tài khoản GitHub Cộng đồng DigitalOcean . Kho lưu trữ này bao gồm mã từ cài đặt được mô tả trong Cách tạo ứng dụng Node.js với Docker .

Sao node_project repository vào một folder có tên là node_project :

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

Thay đổi thành folder node_project :

  • cd node_project

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

  • 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ừ folder hiện tại vào containers và cài đặt các phần phụ thuộc với 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 package.jsonpackage-lock.json , chứa các phụ thuộc được liệt kê của dự án, khỏi bản sao của phần còn lại của mã ứng dụng. Cuối cùng, các hướng dẫn chỉ định rằng containers sẽ được chạy với quyền là user không phải nút root với các quyền thích hợp được đặt trên mã ứng dụng và các folder 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 xem thảo luận đầy đủ trong Bước 3 của Cách tạo ứng dụng Node.js với 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 bản docker build và cờ -t . Ta sẽ gọi hình ảnh là node-demo , nhưng bạn có thể đặt tên khác cho nó:

  • 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 bạn với docker images :

  • docker images

Bạn sẽ thấy kết quả sau, 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 containers bằng docker run . Ta sẽ bao gồm ba cờ với lệnh này:

  • -p : Điều này xuất bản cổng trên containers và ánh xạ nó tới một cổng trên server của ta . Ta sẽ sử dụng cổng 80 trên server lưu trữ, nhưng bạn nên sửa đổi điều 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, hãy xem thảo luận này trong tài liệu Docker về cổng kết nối .
  • -d : Thao tác này chạy containers trong nền.
  • --name : Điều này cho phép ta đặt cho containers một cái tên dễ nhớ.

Chạy lệnh sau để tạo containers :

  • docker run --name node-demo -p 80:8080 -d node-demo

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

  • docker ps

Bạn sẽ thấy kết quả xác nhận containers ứ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 domain của bạn để kiểm tra cài đặt của bạn : http:// example.com . Hãy nhớ thay thế example.com bằng domain của bạn . Ứng dụng của bạn sẽ hiển thị trang đích sau:

Trang đích ứng dụng

Đến đây bạn đã thử nghiệm ứng dụng, bạn có thể dừng containers và xóa hình ảnh. Sử dụng lại docker ps để lấy CONTAINER ID của bạn:

  • 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 container 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 bạn :

  • docker stop 4133b72391da

Như vậy, bạn có thể xóa containers đã dừng và tất cả hình ảnh, bao gồm cả những hình ảnh không sử dụng và treo lơ lửng, bằng cách docker system prune và cờ -a :

  • docker system prune -a

Nhập y khi được yêu cầu trong kết quả để xác nhận bạn muốn xóa containers và hình ảnh đã dừng. Lưu ý điều này cũng sẽ xóa bộ nhớ cache bản dựng của bạn.

Với hình ảnh ứng dụng của bạn đã được kiểm tra, bạn có thể chuyển sang xây dựng phần còn lại của cài đặt với Docker Compose.

Bước 2 - Xác cấu hình web server

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

Đầu tiên, tạo một folder trong folder dự án hiện tại cho file cấu hình:

  • mkdir nginx-conf

Mở file bằng nano hoặc editor bạn quen dùng :

  • nano nginx-conf/nginx.conf

Thêm khối server sau vào các yêu cầu của user proxy vào containers ứng dụng Node của bạn và để hướng các yêu cầu của Certbot đến folder .well .well-known . Đảm bảo thay thế example.com bằng domain của 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 example.com www.example.com;          location / {                 proxy_pass http://nodejs:8080;         }          location ~ /.well-known/acme-challenge {                 allow all;                 root /var/www/html;         } } 

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

Khi bạn đã chỉnh sửa xong, hãy lưu file . Để tìm hiểu thêm về server Nginx và các thuật toán khối vị trí, vui lòng tham khảo bài viết này về Tìm hiểu Server Nginx và các thuật toán lựa chọn khối vị trí .

Với các trang web thông tin chi tiết cấu hình server tại chỗ, ta có thể chuyển sang tạo của ta docker-compose.yml file , mà sẽ cho phép ta tạo ra dịch vụ ứng dụng của ta và container Certbot ta sẽ sử dụng để có được giấy chứng nhận của ta .

Bước 3 - Tạo file docker composer

Tệp docker-compose.yml sẽ xác định các dịch vụ của ta , bao gồm ứng dụng Node và web server . Nó sẽ chỉ định các chi tiết như dung lượng đượ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 containers , cũng như thông tin mạng và cổng. Nó cũng sẽ cho phép ta chỉ định các lệnh cụ thể để chạy khi các containers của ta đượ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 ta sẽ hoạt động cùng nhau.

Mở file trong folder hiện tại của bạn:

  • nano docker-compose.yml

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

~ / node_project / docker-compo.yml
version: '3'  services:   nodejs:     build:       context: .       dockerfile: Dockerfile     image: nodejs     container_name: nodejs     restart: unless-stopped 

Định nghĩa dịch vụ nodejs bao gồm những điều sau:

  • build : Tùy chọ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 bạn muốn sử dụng hình ảnh hiện có từ một nơi đăng ký như Docker Hub , bạn có thể sử dụng hướng dẫn image thay thế, với thông tin về tên user , repository 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 việc xây dựng hình ảnh ứng dụng. Trong trường hợp này, đó là folder dự án hiện tại.
  • dockerfile : Điều này chỉ định Dockerfile mà Compose sẽ sử dụng cho bản dựng - Dockerfile mà bạn đã xem ở Bước 1 .
  • image , container_name : Các tên này áp dụng cho hình ảnh và containers .
  • restart : Điều này xác định policy khởi động lại. Mặc định là no , nhưng ta đã đặt containers khởi động lại trừ khi nó bị dừng.

Lưu ý ta không bao gồm mount ràng buộc với dịch vụ này, vì cài đặt của ta tập trung vào triển khai hơn là phát triển. Để biết thêm thông tin, vui lòng xem tài liệu Docker về mount dung lượng .

Để bật giao tiếp giữa các containers ứng dụng và web server , ta cũng sẽ thêm một mạng cầu nối có tên là app-network bên dưới định nghĩa khởi động lại:

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

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

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

~ / node_project / docker-compo.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 ta đã xác định cho dịch vụ nodejs vẫn giữ nguyên, nhưng ta cũng đã áp dụng các thay đổi sau:

Ta cũng đã chỉ định các ổ đĩa và mount ràng buộc được đặt tên sau:

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

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

~ / node_project / docker-compo.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@example.com --agree-tos --no-eff-email --staging -d example.com  -d www.example.com  

Định nghĩa này yêu cầu Soạn thảo kéo hình ảnh certbot / certbot từ Docker Hub. Nó cũng sử dụng dung lượng được đặt tên để chia sẻ tài nguyên với containers Nginx, bao gồm certificate domain và khóa trong certbot-etc , folder làm việc Let's Encrypt trong certbot-var và mã ứng dụng trong web-root .

, ta đã sử dụng depends_on để chỉ định rằng containers certbot sẽ được khởi động khi dịch vụ webserver đang chạy.

Ta cũng đã bao gồm một tùy chọn command định lệnh chạy khi containers được khởi động. Nó bao gồm lệnh 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 file trong folder webroot để xác thực.
  • --webroot-path : Điều này chỉ định đường dẫn của folder webroot.
  • --email : Email bạn muốn để đăng ký và khôi phục.
  • --agree-tos : Điều này chỉ rõ rằng bạn đồng ý với Thỏa thuận người đăng ký 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 bạn 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 staging của Let's Encrypt để lấy certificate thử nghiệm. 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 bạn và tránh các giới hạn yêu cầu domain có thể xảy ra. Để biết thêm thông tin về các giới hạn này, vui lòng xem tài liệu giới hạn tỷ lệ của Let's Encrypt.
  • -d : Điều này cho phép bạn chỉ định domain mà bạn muốn áp dụng cho yêu cầu của bạn . Trong trường hợp này, ta đã bao gồm example.comwww. example.com . Đảm bảo thay thế những điều này bằng các tùy chọn domain của bạn .

Bước cuối cùng, hãy thêm định nghĩa dung lượng và mạng. Đảm bảo thay thế tên user ở đây bằng user không phải root của bạn :

~ / node_project / docker-compo.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 

Dung lượng được đặt tên của ta bao gồm certificate Certbot và dung lượng folder làm việc cũng như dung lượng cho nội dung tĩnh của trang web của ta , web-root . Trong hầu hết các trường hợp, trình điều khiển mặc định cho dung lượng 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ờ đó, ta 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 folder views trên server lưu trữ, chứa nội dung tĩnh của ứng dụng của ta , vào ổ đĩa trong thời gian chạy. Nội dung folder sau đó có thể được chia sẻ giữa các containers . Để biết thêm thông tin về nội dung của folder views , vui lòng xem Bước 2 của Cách tạo ứng dụng Node.js với Docker .

Tệp docker-compose.yml sẽ trông như thế này khi hoàn tất:

~ / node_project / docker-compo.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@example.com --agree-tos --no-eff-email --staging -d example.com  -d www.example.com   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ó, bạn đã sẵn sàng khởi động các containers và kiểm tra các certificate request của bạn .

Bước 4 - Lấy certificate SSL và thông tin đăng nhập

Ta có thể bắt đầu các containers của bạn với docker-compose up , sẽ tạo và chạy các containers và dịch vụ của ta theo thứ tự ta đã chỉ định. Nếu yêu cầu domain của ta thành công, ta sẽ thấy trạng thái thoát chính xác trong kết quả của ta và các certificate phù hợp được gắn trong folder /etc/letsencrypt/live trên containers webserver .

Tạo các dịch vụ với docker-compose up và cờ -d , sẽ chạy các containers nodejswebserver trong nền:

  • docker-compose up -d

Bạn sẽ thấy kết quả xác nhận các 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:

  • docker-compose ps

Nếu mọi thứ đều thành công, các dịch vụ nodejswebserver của bạn sẽ được Up và containers 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 thấy bất kỳ điều gì khác ngoài cột Up trong trạng State cho các dịch vụ nodejswebserver hoặc trạng thái thoát khác 0 cho containers certbot , hãy đảm bảo kiểm tra log dịch vụ bằng lệnh certbot docker-compose logs :

  • docker-compose logs service_name

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 containers webserver với trình thực thi docker-compose exec :

  • docker-compose exec webserver ls -la /etc/letsencrypt/live

Nếu yêu cầu của bạn thành công, bạn sẽ thấy kết quả 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 example.com

Đến đây bạn biết rằng yêu cầu của bạn 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ở docker-compose.yml :

  • nano docker-compose.yml

Tìm phần của file có định nghĩa dịch vụ certbot và thay thế cờ --staging trong tùy chọn command bằng cờ --force-renewal , cờ này sẽ cho Certbot biết rằng bạn muốn certificate request mới với các domain giống như một certificate hiện có. Định nghĩa dịch vụ certbot bây giờ sẽ giống như sau:

~ / node_project / docker-compo.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@example.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com ... 

Như vậy, bạn có thể chạy docker-compose up để tạo lại containers certbot và các dung lượng có liên quan của nó. Ta cũng sẽ bao gồm tùy chọn --no-deps để cho Soạn biết rằng nó có thể bỏ qua việc khởi động dịch vụ webserver , vì nó đã chạy:

  • docker-compose up --force-recreate --no-deps certbot

Bạn sẽ thấy kết quả cho biết rằng certificate request của bạn đã thành công:

Output
certbot | IMPORTANT NOTES: certbot | - Congratulations! Your certificate and chain have been saved at: certbot | /etc/letsencrypt/live/example.com/fullchain.pem certbot | Your key file has been saved at: certbot | /etc/letsencrypt/live/example.com/privkey.pem certbot | Your cert will expire on 2019-03-26. To obtain a new or tweaked certbot | version of this certificate in the future, simply run certbot certbot | again. To non-interactively renew *all* of your certificates, run certbot | "certbot renew" certbot | - Your account credentials have been saved in your Certbot certbot | configuration directory at /etc/letsencrypt. You should make a certbot | secure backup of this folder now. This configuration directory will certbot | also contain certificates and private keys obtained by Certbot so certbot | making regular backups of this folder is ideal. certbot | - If you like Certbot, please consider supporting our work by: certbot | certbot | Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate certbot | Donating to EFF: https://eff.org/donate-le certbot | certbot exited with code 0

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

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

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

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

  • docker-compose stop webserver

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

  • mkdir dhparam

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

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

Sẽ mất một vài phút để 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 file cấu hình Nginx mà bạn đã tạo trước đó:

  • rm nginx-conf/nginx.conf

Mở một version khác của file :

  • nano nginx-conf/nginx.conf

Thêm mã sau vào file để chuyển hướng HTTP sang HTTPS và thêm thông tin đăng nhập SSL, giao thức và tiêu đề bảo mật. Hãy nhớ thay thế example.com bằng domain của bạn :

~ / node_project / nginx-conf / nginx.conf
 server {         listen 80;         listen [::]:80;         server_name example.com www.example.com;          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 example.com www.example.com;          server_tokens off;          ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;         ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;          ssl_buffer_size 8k;          ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;          ssl_protocols TLSv1.2 TLSv1.1 TLSv1;         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 server HTTP chỉ định webroot cho các yêu cầu gia hạn Certbot tới folder .well .well-known/acme-challenge . Nó cũng bao gồm một chỉ thị viết lại hướng các yêu cầu HTTP đến folder root tới HTTPS.

Khối server 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ể có đối với hiệu suất trang web, vui lòng xem phần giới thiệu về Cách Cài đặt 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 các 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 và ghim OSCP được bật. Ghim OSCP cho phép bạn cung cấp phản hồi được đóng dấu thời gian từ tổ chức phát hành certificate của bạn trong quá trình bắt tay TLS ban đầu, điều này có thể tăng tốc quá trình xác thực.

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

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

Khi bạn đã chỉnh sửa xong, hãy lưu file .

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

Mở tập tin:

  • nano docker-compose.yml

Trong định nghĩa dịch vụ webserver , thêm ánh xạ cổng sau và dhparam có tên dhparam :

~ / node_project / docker-compo.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:

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

Tương tự như ổ đĩa web-root của web-root , dhparam sẽ gắn khóa Diffie-Hellman được lưu trữ trên server vào containers webserver .

Lưu file khi bạn hoàn tất chỉnh sửa.

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

  • docker-compose up -d --force-recreate --no-deps webserver

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

  • docker-compose ps

Bạn sẽ thấy kết quả 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 domain của bạn đảm bảo rằng mọi thứ đang hoạt động như mong đợi. Điều hướng trình duyệt của bạn đến https:// example.com , đảm bảo thay thế example.com bằng domain của bạn . Bạn sẽ thấy trang đích sau:

Trang đích ứng dụng

Bạn cũng sẽ thấy biểu tượng ổ khóa trong chỉ báo bảo mật của trình duyệt. Nếu muốn, bạn có thể chuyển đến trang đích Kiểm tra server SSL Labs hoặc trang đích kiểm tra server Tiêu đề bảo mật . Các tùy chọn cấu hình mà ta đã đưa vào sẽ giúp trang web được xếp hạng A trên cả hai.

Bước 6 - Gia hạn certificate

Chứng chỉ Let's Encrypt có giá trị trong 90 ngày, vì vậy bạn cần cài đặt quy trình gia hạn tự động đảm bảo rằng chúng không 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 với tiện ích lập lịch cron . Trong trường hợp này, ta sẽ lên lịch một cron việc cron bằng cách sử dụng tập lệnh sẽ gia hạn certificate của ta và reload cấu hình Nginx của ta .

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

  • nano ssl_renew.sh

Thêm mã sau vào tập lệnh để gia hạn certificate và reload cấu hình web server của bạn:

~ / 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 --dry-run && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af 

Đầu tiên, tập lệnh này sẽ gán mã binary docker-compose cho một biến có tên là 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 mã binary docker . Cuối cùng, nó thay đổi thành folder ~/node_project và chạy các lệnh ~/node_project docker-compose sau:

  • certbot docker-compose run : Thao tác này sẽ khởi động certbot chứa certbot và overrides command được cung cấp trong định nghĩa dịch vụ certbot của ta . Thay vì sử dụng lệnh certonly , ta đang sử dụng lệnh con renew ở đây, lệnh này sẽ gia hạn các certificate sắp hết hạn. Ta đã bao gồm tùy chọn --dry-run ở đây để kiểm tra tập lệnh của ta .
  • docker-compose kill : Thao tác này sẽ gửi SIGHUP hiệu SIGHUP tới containers webserver để reload cấu hình Nginx. Để biết thêm thông tin về cách sử dụng quy trình này để reload cấu hình Nginx của bạn, vui lòng xem bài đăng trên blog Docker này về việc triển khai hình ảnh Nginx chính thức với Docker .

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

Đóng file khi bạn hoàn tất chỉnh sửa. Làm cho nó có thể thực thi:

  • chmod +x ssl_renew.sh

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

  • sudo crontab -e

Nếu đây là lần đầu tiên bạn chỉnh sửa file này, bạn cần chọn một editor :

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 file , thêm dòng sau:

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

Điều này sẽ đặt khoảng thời gian công việc thành năm phút một lần, vì vậy bạn có thể kiểm tra xem yêu cầu gia hạn của bạn có hoạt động như dự định hay không. Ta cũng đã tạo một file log , cron.log , để ghi lại kết quả có liên quan từ công việc.

Sau năm phút, hãy kiểm tra cron.log để xem liệu yêu cầu gia hạn đã thành công hay chưa:

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

Bạn sẽ thấy kết quả xác nhận 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/example.com/fullchain.pem (success) ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates above have not been saved.) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Killing webserver ... done

Đến đây bạn có thể sửa đổi file 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 sẽ sửa đổi dòng cuối cùng của file để trông giống như sau:

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

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

~ / 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 các certificate Let's Encrypt của bạn không mất hiệu lực bằng cách gia hạn chúng khi chúng đủ điều kiện. Bạn cũng có thể cài đặt xoay log với tiện ích Logrotate để xoay và nén các file log của bạn .

Kết luận

Bạn đã sử dụng containers để cài đặt và chạy ứng dụng Node với Reverse Proxy Nginx. Bạn cũng đã bảo đảm certificate SSL cho domain ứng dụng của bạn và cài đặt cron việc cron để gia hạn các certificate 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 các bài viết của ta 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ách xem các tài nguyên sau:

Tài liệu Soạn thư cũng là một nguồn tài liệu tuyệt vời để tìm hiểu thêm về các ứng dụng đa containers .


Tags:

Các tin trước

Cách cài đặt Nginx trên FreeBSD 11.2 2018-11-15
Cách bảo mật Nginx bằng NAXSI trên Ubuntu 16.04 2018-11-09
Cách tạo chứng chỉ SSL tự ký cho Nginx trên Debian 9 2018-09-07
Cách thiết lập Django với Postgres, Nginx và Gunicorn trên Debian 9 2018-09-06
Cách bảo mật Nginx bằng Let's Encrypt trên Debian 9 2018-09-05
Cách cài đặt Nginx trên Debian 9 2018-09-04
Cách cài đặt Nginx trên Ubuntu 18.04 [Quickstart] 2018-07-23
Cách cung cấp các ứng dụng Flask với Gunicorn và Nginx trên Ubuntu 18.04 2018-07-13
Cách di chuyển web root Nginx đến vị trí mới trên Ubuntu 18.04 2018-07-12
Cách cấu hình Jenkins với SSL bằng Nginx Reverse Proxy trên Ubuntu 18.04 2018-07-10