使用FastAPI uvicorn Nginx(SSL / HTTPS)显示网页


0.简介

  • 使用docker-compose构建FastAPI uvicorn nginx
  • 显示带有FastAPI uvicorn Nginx的网页(Jinja2的模板功能)

作为

的续集,编辑或添加Nginx设置,然后尝试SSL(HTTPS)和BASIC身份验证

*前提:从"使用FastAPI uvicorn Nginx显示网页(Jinja2的模板功能)"状态开始

1. SSL

目录结构(节选)

1
2
3
4
5
6
7
8
9
10
$ tree
.
├── app
├── docker-compose.yml
└── web
    ├── conf.d
    │   └── app.conf
    └── ssl
        ├── server.crt
        └── server.key
  • 修复docker-compose.yml

  • 修改或添加web目录中的文件

    • 修复conf.d/app.conf

    • 证书和密钥准备(ssl/目录)

每个

是必需的

详细信息如下:

docker-compose.yml

固定如下:

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
version: '3'

services:
  web:
    container_name: web
    image: nginx:alpine
    depends_on:
      - app
    ports:
      # - "80:80"
      - "${PORT:-8443:443}"
    volumes:
      - ./web/conf.d:/etc/nginx/conf.d
      - ./web/ssl:/etc/nginx/ssl
    networks:
      - nginx_network

  app:
    container_name: app
    image: test_fastapi_app
    build:
      context: ./app
      dockerfile: Dockerfile
    expose:
      - 8000
    networks:
      - nginx_network
    # volumes:
    #   - ./app/app:/app/app
    # command: "uvicorn app.main:app --host 0.0.0.0 --proxy-headers --forwarded-allow-ips * --reload"

networks:
  nginx_network:
    driver: bridge

如果仅提取存在差异的部分,则

docker-compose.yml(节选)

1
2
3
4
5
6
7
8
services:
  web:
    ports:
      # - "80:80"
      - "${PORT:-8443:443}"
    volumes:
      - ./web/conf.d:/etc/nginx/conf.d
      - ./web/ssl:/etc/nginx/ssl

  • 更改SSL的端口映射

    • 主机OS 8443端口(默认,由环境变量设置)和容器(Nginx)443端口
    • 请注意,出于个人原因,使用环境变量设置8443并不具有深层含义,因此请根据需要进行更改。

      • 请参阅docker-compose文档等。

  • 包含证书密钥的web/ssl目录安装在Nginx容器的/etc/nginx/ssl上。

    • 此处的路径和文件名还将在以后的Nginx配置中使用

web/ssl(密钥?证书)

1
2
3
4
web
└── ssl
    ├── server.crt
    └── server.key

↑预先准备与server.crtserver.key对应的那些,并将它们放置在web/ssl目录

在此示例中,将按原样放置自动生成oleore证书的脚本(单行代码):

make_key.sh

1
2
3
4
5
6
#!/usr/bin/env sh

openssl req -batch -new -x509 -newkey rsa:4096 -nodes -sha256 \
  -subj /CN=example.com/O=example -days 3650 \
  -keyout ./server.key \
  -out ./server.crt

web/conf.d/app.conf

重写Nginx配置文件。

conf.d / app.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
upstream backend {
    server app:8000;
}

server {
    listen 443 ssl;
    ssl_certificate     /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_protocols        TLSv1.2 TLSv1.3;

    # server_name  _;
    index index.html index.htm;

    location / {
        proxy_set_header    Host    $http_host;
        proxy_set_header    X-Real-IP    $remote_addr;
        proxy_set_header    X-Forwarded-Host      $http_host;
        proxy_set_header    X-Forwarded-Server    $http_host;
        proxy_set_header    X-Forwarded-Server    $host;
        proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto  $scheme;
        proxy_redirect      http:// https://;

        proxy_pass http://backend;
    }

    # log
    # access_log /var/log/nginx/access.log;
    # error_log /var/log/nginx/error.log;
}

server_tokens off;

关键更改:

  • 通过如下重写listen 80的部分,可以指定通过卷安装在容器中放置的密钥证书,并使其成为HTTPS。

  • 顺便说一句,我也限制了TLS的版本
1
2
3
4
    listen 443 ssl;
    ssl_certificate     /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_protocols        TLSv1.2 TLSv1.3;
  • 已更正或添加了location /中的proxy_***

    • 我对细节一无所知,因为我做了很多事情,并且反复试验。 .. ..
    • 因此,它可能与不必要的设置混合在一起。 .. ..
1
2
3
4
5
6
7
8
        proxy_set_header    Host    $http_host;
        proxy_set_header    X-Real-IP    $remote_addr;
        proxy_set_header    X-Forwarded-Host      $http_host;
        proxy_set_header    X-Forwarded-Server    $http_host;
        proxy_set_header    X-Forwarded-Server    $host;
        proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto  $scheme;
        proxy_redirect      http:// https://;

暂时
docker-compose up -d
如果访问https://本地主机:8443(端口由您自己设置)等,则可以确认https通信已启用

2.(奖励)使用Nginx进行BASIC身份验证

顺便说一下,让我们应用BASIC身份验证

  • 预先生成.htpasswd

    • 例如,感觉像echo "user:"$(openssl passwd password) >> /path/to/.htpasswd
    • .htpasswd本身的内容与Apache httpd等相同。
  • 这个地方在某种程度上是任意的,但是这次我将其放在web/conf.d中:
1
2
3
4
5
6
7
8
.
├── app
├── docker-compose.yml
└── web
    ├── conf.d
    |   ├── .htpasswd
    │   └── app.conf
    └── ssl
  • 已添加到web/conf.d/app.conf

conf.d / app.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
upstream backend {
    server app:8000;
}

server {
    listen 443 ssl;
    ssl_certificate     /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_protocols        TLSv1.2 TLSv1.3;

    # basic-auth
    auth_basic "BASIC AUTH";
    auth_basic_user_file /etc/nginx/conf.d/.htpasswd;

    # server_name  _;
    index index.html index.htm;

    location / {
        proxy_set_header    Host    $http_host;
        proxy_set_header    X-Real-IP    $remote_addr;
        proxy_set_header    X-Forwarded-Host      $http_host;
        proxy_set_header    X-Forwarded-Server    $http_host;
        proxy_set_header    X-Forwarded-Server    $host;
        proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto  $scheme;
        proxy_redirect      http:// https://;

        proxy_pass http://backend;
    }

    # log
    # access_log /var/log/nginx/access.log;
    # error_log /var/log/nginx/error.log;
}

server_tokens off;

↑我添加了以下内容:

app.conf(其他部分)

1
2
3
    # basic-auth
    auth_basic "BASIC AUTH";
    auth_basic_user_file /etc/nginx/conf.d/.htpasswd;

  • auth_basic的内容在需要身份验证时可能显示为字符串(可能取决于浏览器),因此请适当地重写它。

  • 通过指定批量安装在容器中的.htpasswd的路径来加载auth_basic_user_file

现在,您可以使用以下内容进行身份验证:

スクリーンショット 2020-08-16 14-50-02.png

(*这是我的证书,所以会发出警告)

参考

  • Nginx反向代理设置

    • https://qiita.com/uezo/items/847e1911ac486f5a89c4
    • https://qiita.com/imoimo2009/items/515ceaeea5aeb1bade3a
    • https://qiita.com/tnoce/items/ded6d3d298da5972ab63
    • https://ja.nuxtjs.org/faq/nginx-proxy/
    • https://blog.akagi.jp/archives/3883.html
    • https://www.busterworks.co.jp/archives/64
    • nginx上的https://threetreeslight.com/posts/2014/03/14/ ssl-reverse-proxy设置/
    • https://tech-lab.sios.jp/archives/9922
  • 使用Nginx从http重定向到https

    • https://qiita.com/fisherman08/items/e39e67e85ef07a1ef3db
  • Nginx中的BASIC身份验证

    • http://vdeep.net/nginx-basic-authentication
    • https://www.yoheim.net/blog.php?q=20170804
    • https://qiita.com/kotarella1110/items/be76b17cdbe61ff7b5ca
    • https://qiita.com/STSynthe/items/5387bc33e7be315ae338
    • https://qiita.com/ekzemplaro/items/0385c34c4325da2f2af6
    • https://note.com/club_cloud/n/n581d1995139f
  • .htpasswd生成

    • https://asakawajunya.hatenablog.com/entry/20130706/1373046305
    • https://qiita.com/shell/items/5606d37a802e39479036
    • https://www.junk-works.science/generate-htpasswd-with-openssl/
    • https://www.luft.co.jp/cgi/htpasswd.php
  • 我的证书的单行

    • https://qiita.com/ngyuki/items/27e56196fbf2d68a9f7f
    • https://qiita.com/marcy-terui/items/2f63d7f170ff82531245
    • https://nekonenene.hatenablog.com/entry/2019/08/10/153430