我们有一个多租户应用程序(dotnet core + Angular),主网站网址为https://example.com,客户 URL 是(http://cust1.example.com,http://cust2.example.com,......)
如果客户需要使用自己的域名,他只需要将他的域名重定向到我们的服务器,例如:客户 1 有自己的域名:customer1.com,因此他将转到域名设置并编辑 DNS 设置以引用我们的服务器 IP 记录 @ = XXXX(我们的服务器 IP)记录 CNAME www = cust1.example.com 然后他可以使用他的域名打开他的应用程序(http://customer1.com),而不是使用(http://cust1.example.com)
不,我们进入下一步并使用 HTTPS,我已经使用 certbot 创建了 LetsEncrypt 通配符证书:sudo certbot --serverhttps://acme-v02.api.letsencrypt.org/directory-d *.example.com --manual --preferred-challenges dns-01 certonly
现在,如果您使用以下方式访问该应用程序,则该应用程序将以 HTTPS 形式运行 (https://cust1.example.com)并且运行良好,
但问题是,如何使用不同的域名提供 HTTPS,假设我想访问https://customer1.com,显然无法提供服务,因为这个域名的服务器中没有证书。
我们需要一种自动化的方法来为新域创建证书,而无需在 nginx 配置文件中创建新的块,因为可能有 100000 个客户,因此不可能手动完成。
这是我现在的 Nginx 配置文件
server {
listen 80 default_server;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl default_server;
server_name example.com *.example.com;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
我尝试过在 Nginx 中使用 Lua,但是没有找到方法。
有人能提出解决这个问题的建议吗?
答案1
我建议使用 Ansible 作为此任务的配置工具,因为它允许您使用模板和变量来设置客户的 SaaS 系统站点。在您的案例中,这可能看起来有点过度和重复,但一旦您开始在同一站点列表上实施其他基础设施任务,它将带来巨大的好处。通常我会期望以下内容:
- SSL/Letsencrypt 续订
- 客户特定的备份脚本
- 任何其他大规模变化
具有角色的最小设置(未测试语法或任何内容)如下所示:
组变量/全部:
sites:
- { name: customer1.yoursaas.com, user: www_customer1, memory_limit: "256M", max_children: 2, port: 5000 }
- { name: yoursaas.customerdomain.com, user: www_customer2, memory_limit: "256M", max_children: 2, port: 5001 }
角色/nginx/任务/main.yml:
---
- name: copy host files
template: src=nginx-host.j2 dest=/etc/nginx/sites-available/{{item.name}} owner=root group=root mode=0644
with_items:
- "{{sites}}"
notify:
- reload nginx
tags:
- nginx
角色/nginx/模板/nginx-host.j2:
server {
listen 80 default_server;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl default_server;
server_name {{item.name}};
access_log /var/log/nginx/{{item.name}}.access.log;
error_log /var/log/nginx/{{item.name}}.error.log;
ssl_certificate /etc/letsencrypt/live/{{item.name}}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{item.name}}/privkey.pem;
location / {
proxy_pass http://localhost:{{item.port}};
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
web服务器.yml:
---
- hosts: tag_group_web_servers
vars_files:
- group_vars/all
- group_vars/vault
roles:
- nginx
我对此进行了过度简化,但在包括 Saas 应用程序在内的所有网络托管基础设施管理中都使用它。
另一个好处是,使用配置工具,您可以拥有非常详细(重复)的配置文件,而无需额外的工作和重复导致错误的风险。这让其他人更容易理解某些东西是如何配置的。
答案2
我希望您可以使用下面提到的 vhost 文件找到解决方案。
server {
server_name *.myapp.io;
}
server {
server_name ~^(?<account>.+)\.myapp\.io$;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_param ACCOUNT $account; # $_SERVER['ACCOUNT']
}
}
server {
server_name ~^(?<account>.+)\.myapp\.io$;
root /var/www/$account;
access_log /var/log/nginx/$account-access.log;
error_log /var/log/nginx/$account-error.log;
}