我刚刚完成了 nginx+gunicorn+django 网络服务器的设置(之前 apache2+wsgi+django 也遇到了同样的问题),并确认它可以通过 http 完美运行。运行 letsencrypt 的 certbot 后,它会正确地将 http 重定向到 https,但是,我的浏览器随后出现标题中提到的错误。我花了很多时间尝试了所有我能想到的方法,现在终于找到了解决方案。文件中的一些注释掉的行可能会揭示我迄今为止尝试过的一些方法。
PS:我尝试运行 ssllabs 并检查你的网站,但没有返回任何有用的东西/我不知道的东西。
附加信息(其中一些可能不需要,但有些可能会有帮助)
运行 Ubuntu 18.04 LTS
nginx nginx/1.14.0
Django 2.2.5
Python 3.6
gunicorn 19.9.0
域名来自 Google Domains,使用 ddclient 中的 googledomains 协议进行 DDNS
文件
# /etc/nginx/sites-available/mysite
upstream your-gunicorn {
server unix:/tmp/gunicorn.sock fail_timeout=0;
}
server {
client_max_body_size 4G;
server_name mysite.net;
keepalive_timeout 70;
access_log /var/log/nginx/mysite.access_log;
error_log /var/log/nginx/mysite.error_log;
root /home/user/Desktop/Django/mysite;
location /static/ {
autoindex on;
alias /home/user/Desktop/Django/mysite/static/;
expires 1M;
access_log off;
add_header Cache-Control "public";
proxy_ignore_headers "Set-Cookie";
}
location @proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
# proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_pass http://your-gunicorn;
}
location / {
try_files $uri @proxy_to_app;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/nerd-squad.net/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/nerd-squad.net/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = mysite.net) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 default;
server_name mysite.net;
return 404; # managed by Certbot
}
# <Django mysite root>/gunicorn/gunicorn-config.py
import multiprocessing
bind = 'unix:/tmp/gunicorn.sock'
workers = multiprocessing.cpu_count() * 2 + 1
reload = True
daemon = True
accesslog = './access.log'
errorlog = './error.log'
# <Django Site Root>/mysite/settings.py
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = <nope>
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
ALLOWED_HOSTS = [
<nope>
]
# Application definition
INSTALLED_APPS = [
'home.apps.HomeConfig',
'pics.apps.PicsConfig',
'welcome.apps.WelcomeConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'mysite.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'mysite.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3')
}
}
# Password validation
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'America/Chicago'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "staticfiles"),
]
#STATIC_ROOT = os.path.join(BASE_DIR, "static")
STATIC_ROOT = '/home/user/Desktop/Django/static'
#SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# /etc/letsencrypt/options-ssl-nginx.conf
# This file contains important security parameters. If you modify this file
# manually, Certbot will be unable to automatically provide future security
# updates. Instead, Certbot will print and log an error message with a path to
# the up-to-date file that you will need to refer to when manually updating
# this file.
ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_timeout 1440m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers <nope>;
如果需要的话我可以提供更多信息。谢谢!