diff --git a/docker-compose.yml b/docker-compose.yml index 854b8012..38d75eaf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -131,8 +131,8 @@ services: - dashboard.internal - api.internal ports: - - "80:80" - - "443:443" + - "${NGINX_PORT:-80}:80" + - "${NGINX_SSL_PORT:-443}:443" depends_on: - dashboard - api diff --git a/docs/user/settings.rst b/docs/user/settings.rst index 13bdd7fb..5bc46d9c 100644 --- a/docs/user/settings.rst +++ b/docs/user/settings.rst @@ -83,13 +83,13 @@ properly on your system. ``SSL_CERT_MODE`` ~~~~~~~~~~~~~~~~~ -- **Explanation:** Flag to enable or disable HTTPs. If it is set to +- **Explanation:** Flag to enable or disable HTTPS. If it is set to ``Yes``, letsencrypt certificates are automatically fetched with the help of certbot and a cronjob to ensure they stay updated is added. If - it is set to ``SelfSigned``, self-signed certificates are used and - cronjob for the certificates is set. If set to ``No``, site is - accessible via HTTP, if set if ``EXTERNAL``, it tells HTTPs is used but - managed by external tool like loadbalancer / provider. Setting this + it is set to ``SelfSigned``, self-signed certificates are used and a + cronjob for the certificates is set. If set to ``No``, the site is + accessible via HTTP. If set to ``External``, it tells HTTPS is used but + managed by an external tool like a loadbalancer/provider. Setting this option as ``No`` is not recommended and might break some features, only do it when you know what you are doing. - **Valid Values:** ``External``, ``Yes``, ``SelfSigned``, ``No``. @@ -869,6 +869,26 @@ Nginx - **Example:** ``index index.html index.htm;``. - **Default:** ``""`` (empty string). +``NGINX_SSL_PORT`` +~~~~~~~~~~~~~~~~~~ + +- **Explanation:** Nginx container external HTTPS port. Change if, for + example, OpenWISP runs behind a reverse proxy listening on port 443 on + the same host. Non-default ports are incompatible with + ``SSL_CERT_MODE=Yes``. +- **Valid Values:** ``INTEGER``. +- **Default:** ``443``. + +``NGINX_PORT`` +~~~~~~~~~~~~~~ + +- **Explanation:** Nginx container external HTTP port. Change if, for + example, OpenWISP runs behind a reverse proxy listening on port 80 on + the same host. Non-default ports are incompatible with + ``SSL_CERT_MODE=Yes``. +- **Valid Values:** ``INTEGER``. +- **Default:** ``80``. + ``NGINX_GZIP_SWITCH`` ~~~~~~~~~~~~~~~~~~~~~ diff --git a/images/common/openwisp/settings.py b/images/common/openwisp/settings.py index cb3cd21b..bdf16b78 100644 --- a/images/common/openwisp/settings.py +++ b/images/common/openwisp/settings.py @@ -50,11 +50,25 @@ ACCOUNT_LOGOUT_REDIRECT_URL = LOGIN_REDIRECT_URL ROOT_URLCONF = "openwisp.urls" HTTP_SCHEME = request_scheme() +HTTP_PORT = ( + os.getenv("NGINX_SSL_PORT", "443") + if HTTP_SCHEME == "https" + else os.getenv("NGINX_PORT", "80") +) +if ( + HTTP_SCHEME == "http" + and HTTP_PORT == "80" + or HTTP_SCHEME == "https" + and (HTTP_PORT == "443" or os.environ["SSL_CERT_MODE"].lower() == "external") +): + HTTP_PORT = "" +else: + HTTP_PORT = f":{HTTP_PORT}" # CORS CORS_ALLOWED_ORIGINS = [ - f'{HTTP_SCHEME}://{os.environ["DASHBOARD_DOMAIN"]}', - f'{HTTP_SCHEME}://{os.environ["API_DOMAIN"]}', + f'{HTTP_SCHEME}://{os.environ["DASHBOARD_DOMAIN"]}{HTTP_PORT}', + f'{HTTP_SCHEME}://{os.environ["API_DOMAIN"]}{HTTP_PORT}', ] + os.environ["DJANGO_CORS_HOSTS"].split(",") CORS_ALLOW_CREDENTIALS = True diff --git a/images/openwisp_dashboard/module_settings.py b/images/openwisp_dashboard/module_settings.py index 1cc66797..6c092abf 100644 --- a/images/openwisp_dashboard/module_settings.py +++ b/images/openwisp_dashboard/module_settings.py @@ -89,7 +89,18 @@ # pregenerate static gzip files to save CPU GZIP_STATIC_COMPRESSION = True -API_BASEURL = f'{request_scheme()}://{os.environ["API_DOMAIN"]}' +HTTP_SCHEME = request_scheme() +HTTP_PORT = ( + os.getenv("NGINX_SSL_PORT", "443") + if HTTP_SCHEME == "https" + else os.getenv("NGINX_PORT", "80") +) +HTTP_PORT = ( + "" + if HTTP_SCHEME == "https" and os.environ["SSL_CERT_MODE"].lower() == "external" + else f":{HTTP_PORT}" +) +API_BASEURL = f'{HTTP_SCHEME}://{os.environ["API_DOMAIN"]}{HTTP_PORT}' OPENWISP_NETWORK_TOPOLOGY_API_URLCONF = "openwisp_network_topology.urls" OPENWISP_MONITORING_API_URLCONF = "openwisp_monitoring.urls" diff --git a/images/openwisp_nginx/Dockerfile b/images/openwisp_nginx/Dockerfile index b37e9ffe..b6c3184a 100644 --- a/images/openwisp_nginx/Dockerfile +++ b/images/openwisp_nginx/Dockerfile @@ -44,6 +44,7 @@ ENV MODULE_NAME=nginx \ NGINX_GZIP_TYPES='text/plain image/svg+xml application/json application/javascript text/xml text/css application/xml application/x-font-ttf font/opentype' \ NGINX_CUSTOM_FILE=False \ NINGX_REAL_REMOTE_ADDR='$real_ip' \ + NGINX_SSL_PORT=443 \ # USWGI pass_port DASHBOARD_APP_PORT=8000 \ API_APP_PORT=8001 \ diff --git a/images/openwisp_nginx/openwisp.ssl.80.template.conf b/images/openwisp_nginx/openwisp.ssl.80.template.conf index 5cf05519..13790e96 100644 --- a/images/openwisp_nginx/openwisp.ssl.80.template.conf +++ b/images/openwisp_nginx/openwisp.ssl.80.template.conf @@ -9,5 +9,5 @@ server { location /.well-known/ { try_files ${DOLLAR}uri /dev/null =404; } - return 301 https://${DOLLAR}host${DOLLAR}request_uri; + return 301 https://${DOLLAR}host:${NGINX_SSL_PORT}${DOLLAR}request_uri; } diff --git a/images/openwisp_nginx/openwisp.ssl.template.conf b/images/openwisp_nginx/openwisp.ssl.template.conf index 441c8b96..502a2ad4 100644 --- a/images/openwisp_nginx/openwisp.ssl.template.conf +++ b/images/openwisp_nginx/openwisp.ssl.template.conf @@ -24,7 +24,7 @@ server { add_header Referrer-Policy "same-site" always; add_header Permissions-Policy "interest-cohort=()" always; add_header Strict-Transport-Security "max-age=31536000" always; - add_header Content-Security-Policy "default-src http: https: data: blob: 'unsafe-inline'; script-src 'unsafe-eval' https: 'unsafe-inline' 'self'; frame-ancestors 'self'; connect-src *.${ROOT_DOMAIN} wss: 'self'; worker-src https://${DOMAIN} blob: 'self';" always; + add_header Content-Security-Policy "default-src http: https: data: blob: 'unsafe-inline'; script-src 'unsafe-eval' https: 'unsafe-inline' 'self'; frame-ancestors 'self'; connect-src *.${ROOT_DOMAIN}:${NGINX_SSL_PORT} wss: 'self'; worker-src https://${DOMAIN} blob: 'self';" always; # GZIP Configurations gzip ${NGINX_GZIP_SWITCH};