Phoenix in Production on EC2 不使用 AWS Load Balancer 在 HTTPS 中呈现

Phoenix in Production on EC2 not rendering in HTTPS with AWS Load Balancer

我已经按照这个 tutorial 在 EC2 上设置我的 phoenix 应用程序,后来我添加了 SSL 的负载均衡器。

我使用 ACM (Amazon Certificate Manager) 获取了 public 证书并应用到 Amazon Load Balancer (ALB) 上。

我对端口映射仍然有点模糊,所以我想这可能是原因。

# config/prod.exs

host = System.get_env("HOST") || "example.com"

config :app_web, AppWeb.Endpoint,
  force_ssl: [rewrite_on: [:x_forwarded_proto]],
  load_from_system_env: true,
  http: [port: 80],
  url: [host: host, port: 80],
  url: [host: host, port: 443, scheme: "https"],
  server: true,
  secret_key_base: System.get_env("SECRET_KEY_BASE")
# docker-compose.yml
version: '2'
services:
  kroo:
    image: [image url]
    environment:
      - HOST=0.0.0.0
    ports:
      - '443:443'
      - '80:80'
$ docker ps
PORTS
0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp
$ docker logs 
01:56:30.177 [info] Running AppWeb.Endpoint with cowboy 2.7.0 at 0.0.0.0:80 (http)
01:56:30.177 [info] Access AppWeb.Endpoint at https://example.com
Running Release tasks
[]
01:56:31.316 [info] Already up
01:56:33.085 [info] Plug.SSL is redirecting GET / to https://example.com with status 301

当我不包含 force_ssl: [rewrite_on: [:x_forwarded_proto]] 时,我可以让页面在 http 中正常显示,但是当我包含 force_ssl 时,它会重定向工作正常的 https,但是我越来越无法连接错误。

我的困惑是,由于负载平衡器负责 SSL,我没有 SSL 的密钥和证书,这就是为什么我没有 https: [] 选项的原因 prod.exs

有人能指出我做错了什么吗?

谢谢

更新:我终于让它工作了,下面是我的工作配置,以防有人觉得它有用。

# config/prod.exs

# https config is not needed since ALB is handling the SSL
# Phoenix app serving in http is fine
config :app_web, AppWeb.Endpoint,
  load_from_system_env: true,
  http: [port: 8080],
  url: [host: "example.com"],
  server: true,
  secret_key_base: System.get_env("SECRET_KEY_BASE")
# docker-compose.yml
# map phoenix port 8080 to docker 8080
  ports:
    - '8080:8080'

因为我不提供 SSL 证书,但我仍然想强制使用 ssl,就像@jamesvl 在回答中建议的那样,使用您的负载平衡器将 http 流量重定向到 https。

如果您需要帮助在 ALB 上设置 SSL,我遵循了这个 guide

如果您的应用仍然没有出现在您的域下,请确保您有一个 A 记录,其中别名映射到您的负载均衡器的 DNS 名称

我建议将 docker 容器的侦听端口设置为 80 以外的端口,并且根本不要在 443 上侦听。

理由

认为 问题可能在于您的 http: 配置正在侦听端口 80。

启用 force_ssl: 后,您表示希望 http 连接转到端口 443,但是当某些内容到达 443 时(通过负载均衡器),您将其发送到您的(侦听)端口80... 将其重定向回 443?

修复

让 Phoenix 在任意端口(例如... 4010)上侦听 http 连接。 (由于负载均衡器会终止您的 SSL,因此您与负载均衡器的所有通信都将通过 http。)这涉及更改您的 Docker 容器以将连接转发到该端口 - 您不想听您的容器中总共有 80 或 443 个。

您的 url: 配置将只查看 headers,根据需要将 http 请求重定向到 https。

顺便说一句,如果你设置了规则,亚马逊的ALB也可以为你做80 -> 443重定向;这使 Phoenix 甚至不必为端口 80 进行配置 url: 设置