将多个nginx配置文件合并为一个

3

这是我现在正在使用的配置“模板”:

server {
  server_name {:primaryDomain};
  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/{:primaryDomain}/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/{:primaryDomain}/privkey.pem;
  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
  root {:siteRoot};
  index index.php index.html;

  recursive_error_pages off;
  error_page 403 = /HTTP_ERRORS/403.html;
  error_page 404 = /HTTP_ERRORS/404.html;
  error_page 500 = /HTTP_ERRORS/500.html;
  
  location ^~ /HTTP_ERRORS/ {
    alias {:sharedHtmlRoot}/;
    internal;
  }  
  
  location / {
    try_files $uri $uri/ /index.php?$query_string;
  }

  location /manage {
    root {:siteRoot}/manage;  
    try_files $uri $uri/ /manage/index.php?$query_string;
  }

  location ~* \.php$ {
    fastcgi_pass unix:/run/php/php{:phpVer}-fpm-{:user}.sock;
    include         fastcgi_params;
    fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
  }

  location /assets/ {
    alias /public/assets/;
  }     
}

server {
  server_name {:primaryDomain} www.{:primaryDomain};
  listen 80;
  return 301 https://{:primaryDomain}$request_uri;
}

server {
  server_name www.{:primaryDomain};
  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/{:primaryDomain}/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/{:primaryDomain}/privkey.pem;
  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;  
  return 301 https://{:primaryDomain}$request_uri;
}

注意{:keywords}。这些是我使用生成nginx最终配置的脚本要替换的字符串。 它可以正常工作,但我大约有300个网站,该脚本将使用此模板生成300个这样的配置,因此最终的nginx .conf文件相当大。 我能否以某种方式为所有站点使用单个nginx配置?
1个回答

4

以下是我已经验证过的nginx/1.18.0配置全合一,但仍需要生成一个域名列表文件/etc/nginx/mydomains

/etc/nginx/sites-enabled/default

map $http_host $vhost_config {
    hostnames;
    default "";
    include /etc/nginx/mydomains;
}

map $vhost_config $vhost_root {
    default "";
    ~^([^:]+):([^:]+):([^:]+)$ $1;
}

map $vhost_config $php_version {
    default "";
    ~^([^:]+):([^:]+):([^:]+)$ $2;
}

map $vhost_config $php_user {
    default "";
    ~^([^:]+):([^:]+):([^:]+)$ $3;
}

map $ssl_server_name $my_cert_name {
    default "";
    ~^(www\.)?(.+)$ $2;
}

server {
    listen 80 default_server;
    listen 443 ssl default_server;

    ssl_certificate /etc/letsencrypt/live/$my_cert_name/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/$my_cert_name/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    server_name ~^(?<www>(www\.)?)(?<domain>.+)$;

    recursive_error_pages off;
    error_page 403 = /HTTP_ERRORS/403.html;
    error_page 404 = /HTTP_ERRORS/404.html;
    error_page 500 = /HTTP_ERRORS/500.html;

    location ^~ /HTTP_ERRORS/ {
        alias {:sharedHtmlRoot}/;
        internal;
    }

    # redirect www.abc.com to abc.com
    if ($www != '') {
        return 301 https://$domain$request_uri;
    }

    # redirect http to https
    if ($scheme = 'http') {
        return 301 https://$domain$request_uri;
    }

    # if domain not exist in mydomains, return 404
    if ($vhost_root = '') {
        return 404;
    }

    root $vhost_root;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location /manage {
        root $vhost_root/manage;
        try_files $uri $uri/ /manage/index.php?$query_string;
    }

    location ~* \.php$ {
        fastcgi_pass unix:/run/php/php$php_version-fpm-$php_user.sock;
        include         fastcgi_params;
        fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
    }

    location /assets/ {
        alias /public/assets/;
    }
}

/etc/nginx/mydomains 的内容

# domain.name "<site root>:<php version>:<php user>";
abc.com "/var/www/html/abc:7.4:user1";
efg.com "/var/www/html/efg:7.0:user2";

注意事项

  1. Nginx自1.15.9版本开始支持在ssl_certificate指令中使用变量,同时在nginx/1.70引入了$ssl_server_name。由于http变量$http_host只有在建立https连接后才会初始化,因此在这种情况下无法替换$ssl_server_name
  2. 你可以将server块中的{:sharedHtmlRoot}替换为你实际的路径。
  3. 全能型server块被声明为默认块,如果你的nginx配置中已经有一个默认的server块,则需要覆盖旧的server块。

似乎不起作用。我收到“此网站无法提供安全连接”的消息。我以为你在ssl_server_name上犯了一个错误,所以我用vhost_config替换了它,但仍然出现了这个错误。有没有办法查看nginx在这些变量中看到了什么? - Alex
好的,我找到原因了:https://serverfault.com/questions/972146/nginx-config-using-variable-in-ssl-certificate-path-throws-permissions-error。显然,当使用变量时,nginx没有权限读取证书文件。很奇怪。 - Alex
@Alex 自 nginx 1.15.9 版本开始支持在 ssl_certificate 中使用变量。如果你的 nginx 版本符合要求,可以尝试启用调试日志 error_log /var/logs/nginx/xxx.error.log debug; 并检查 error_log。 - emptyhua
$ssl_server_name 是在 nginx/1.70 中引入的变量,它不能被其他变量替换。 - emptyhua
用户在哪里?组在哪里?工人的数量在哪里?…… - reza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接