【问题标题】:Mapping subdomains to URLs with nginx使用 nginx 将子域映射到 URL
【发布时间】:2013-01-20 14:58:24
【问题描述】:

我对 nginx 很陌生,如果我的解释不对,请原谅我。我会尽力解释我想要达到的目标。

使用 WordPress 和 nginx,我希望将用户帐户映射到主域的子域。例如,如果用户创建了一个名为“sample”的帐户,则该用户的子域将是 sample.example.com

当用户访问sample.example.com时,子域应该映射到example.com/sample/。同样,如果用户访问sample.example.com/account/,它应该映射到example.com/sample/account/,以此类推。需要注意的是,example.com/sample/ URL 是对这种结构的重写:example.com/index.php?user=sample

还有一些保留的子域不应重定向,例如 cdn 和 admin。如果需要,这些规则应忽略它们。

当用户创建帐户时,如何自动实现这一点?这里的目标是自动化——正确设置一次,不用担心。由于几天前我才刚刚开始使用 nginx,所以我完全不知道从哪里开始。任何能让我朝着正确方向前进的建议都会非常有帮助。这是我当前的域配置文件:

server {
    listen          80;
    server_name     www.example.com;
    rewrite     ^(.*) $scheme://example.com$1 permanent;
}

server {
    listen          443 ssl;
    server_name     www.example.com;
    rewrite         ^(.*) $scheme://example.com$1 permanent;
}

server {
    listen      80;
    server_name example.com;

    access_log  /var/www/example.com/logs/access.log;
    error_log   /var/www/example.com/logs/error.log;

    root        /var/www/example.com/public;
    index       index.php;

    location / {
        try_files $uri $uri/ @wordpress /index.php?q=$request_uri;
    }

    location @wordpress {
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_param SCRIPT_FILENAME /var/www/example.com/public/index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_NAME /index.php;
    }

    # Pass the PHP scripts to FastCGI server listening on UNIX sockets.
    #
    location ~ \.php$ {
        try_files $uri @wordpress;
        fastcgi_pass   unix:/var/run/php5-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/example.com/public$fastcgi_script_name;
        include        fastcgi_params;
    }
}

server {
    listen                      443 ssl;
    ssl                         on;
    keepalive_timeout           70;
    server_name                 example.com;
    ssl_certificate             ssl/example.com.chained.crt;
    ssl_certificate_key         ssl/example.key;
    ssl_protocols               SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers                 HIGH:!aNULL:!MD5;
    ssl_session_cache           shared:SSL:10m;
    ssl_session_timeout         10m;
    ssl_prefer_server_ciphers   on;

    root        /var/www/example.com/public;
    index       index.php;

    location / {
        try_files $uri $uri/ @wordpress /index.php?q=$request_uri;
    }

    location @wordpress {
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_param SCRIPT_FILENAME /var/www/example.com/public/index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_NAME /index.php;
    }

    # Pass the PHP scripts to FastCGI server listening on UNIX sockets.
    #
    location ~ \.php$ {
        try_files $uri @wordpress;
        fastcgi_pass   unix:/var/run/php5-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/example.com/public$fastcgi_script_name;
        include        fastcgi_params;
    }
}

我了解,如果我希望实现自动化,我想要实现的目标可能需要进入 /etc/nginx/nginx.conf 文件,并且我正在积极尝试学习如何实现这一目标。我只是被困在现在的位置,正在寻找任何可以为我指明正确方向的建议/帮助。我渴望学习!

【问题讨论】:

  • 为什么需要两个php相关的位置块?除了 wordpress 之外,您还有其他 php 页面吗?两者都指向同一个 php-fpm 套接字。

标签: wordpress nginx rewrite subdomain


【解决方案1】:

以下应该这样做:

server {
  listen 80; listen 443;
  server_name *.example.com;

  if ($host ~ "^(.*)\.example\.com$" ) { set $subdomain $1;}
  rewrite ^ $scheme://example.com/$subdomain/$request_uri permanent;
}

(顺便说一句:正则表达式 ^ 匹配所有 url 的效率最高,标准 nginx 变量 $request_uri 包含包含参数的 uri,因此您不需要 (.*) 组在重写中)

另外为您不希望重定向的域添加第二个服务器块:

server {
  listen 80; listen 443;
  server_name cdn.example.com admin.example.com;
  # do whatever with the requests of the reserved subdomains;
}

【讨论】:

  • 我得到了这个错误:[emerg] invalid condition "then" in
  • 另外,这不会重定向用户吗?我不希望它们被重定向,而是映射到 URL,以便子域 URL 仍然存在于浏览器窗口中。
  • 哎呀,删除了 then(我脑海中的红宝石:D)。是的,它会重定向用户,我认为这就是你想要的?我误会了什么?
  • 我发现在我的事业中非常有用的一件事是在再次测试之前清除我的浏览器cahce。
【解决方案2】:

回答

经过数天的搜索、调整和配置,我已经获得了将子域映射到 URL 所需的代码,就像在我的示例中一样。这是 example.com 的我的虚拟主机:https://gist.github.com/thomasgriffin/4733283

server {
    listen      80;
    listen      443 ssl;
    server_name ~^(?<user>[a-zA-Z0-9-]+)\.example\.com$;

    location / {
        resolver            8.8.8.8;
        rewrite             ^([^.]*[^/])$ $1/ permanent;
        proxy_pass_header   Set-Cookie;
        proxy_pass          $scheme://example.com/user/$user$request_uri;
    }
}

server {
    listen          80;
    listen          443 ssl;
    server_name     www.example.com;
    return          301 $scheme://example.com$request_uri;
}

server {
    listen      80;
    server_name example.com;

    access_log  /var/www/example.com/logs/access.log;
    error_log   /var/www/example.com/logs/error.log;

    root        /var/www/example.com/public;
    index       index.php;

    location / {
        try_files $uri $uri/ @wordpress /index.php?q=$request_uri;
    }

    location @wordpress {
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_NAME /index.php;
    }

    # Pass the PHP scripts to FastCGI server listening on UNIX sockets.
    #
    location ~ \.php$ {
        try_files $uri @wordpress;
        fastcgi_pass   unix:/var/run/php5-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

server {
    listen                      443 ssl;
    ssl                         on;
    keepalive_timeout           70;
    server_name                 example.com;
    ssl_certificate             ssl/example.com.chained.crt;
    ssl_certificate_key         ssl/example.key;
    ssl_protocols               SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers                 HIGH:!aNULL:!MD5;
    ssl_session_cache           shared:SSL:10m;
    ssl_session_timeout         10m;
    ssl_prefer_server_ciphers   on;

    root        /var/www/example.com/public;
    index       index.php;

    location / {
        try_files $uri $uri/ @wordpress /index.php?q=$request_uri;
    }

    location @wordpress {
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_NAME /index.php;
    }

    # Pass the PHP scripts to FastCGI server listening on UNIX sockets.
    #
    location ~ \.php$ {
        try_files $uri @wordpress;
        fastcgi_pass   unix:/var/run/php5-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

映射的主要块在第一个服务器块中完成。我的目标是任何子域(我已经用其他不相关的代码清除了受限制的子域)并重写它以确保它有一个尾部斜杠,以避免 WordPress 对没有尾部斜杠的 URL 进行任何内部重定向。从那里开始,需要resolver 指令来解析proxy_pass 中定义的URL,所以我使用Google 的DNS 进行解析。我还使用 proxy_pass_header 指令通过 cookie 发送,以保持 WordPress 登录身份验证的完整性。 proxy_pass 定义要映射到的 URL。

还应注意,如果您想对子域也使用登录身份验证,则需要在 wp-config.php 中定义您的自定义 cookie 域,如下所示:

define('COOKIE_DOMAIN', '.example.com');

应该就是这样。您现在可以享受像 subdomain.example.com 这样映射到 example.com/user/subdomain/ 或任何您想要的 URL。从那里,您可以利用 WordPress 的 Rewrite API 将映射的 URL 映射到特定的查询参数,这些参数可以发送到 $wp_query 以加载自定义模板等。

【讨论】:

  • 这很好。但是,依赖外部 dns 服务器(甚至是 google 的服务器)对性能不利。使用代理也会增加开销。
  • 另外,不要认为您需要 resolver 指令,它仅在您的 proxy_pass 指令的域部分中有变量时才有用。
【解决方案3】:

我认为 .htaccess 不适用于 nginx。 我使用 Nginx 作为反向代理服务器端口 80 和 Apache 作为 Web 服务器 HERE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多