yiisoft / yii2-app-advanced

Yii 2.0 Advanced Application Template
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
1.66k stars 1.28k forks source link

Docs: add a webserver configuration example for shared hosting #331

Open hujuice opened 6 years ago

hujuice commented 6 years ago

This is related to #316. Two proposals below. The proposals are not strongly tested and are for Apache only (I'm not expert in nginx). If you are interested, I can test them better, fork and propose formally. Apache only.

Regards, HUjuice

If you have per directory permissions only (.htaccess):

# use mod_rewrite for pretty URL support
RewriteEngine On

# Backend requests
RewriteCond %{REQUEST_URI} ^/admin$ [OR]
RewriteCond %{REQUEST_URI} ^/admin/
# If a directory or a file exists, use the request directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Otherwise forward the request to admin/index.php
RewriteRule . admin/index.php

# Frontend requests
RewriteCond %{REQUEST_URI} !^/admin$
RewriteCond %{REQUEST_URI} !^/admin/
# If a directory or a file exists, use the request directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Otherwise forward the request to index.php
RewriteRule . index.php

# if $showScriptName is false in UrlManager, do not allow accessing URLs with script name
RewriteRule ^(admin/)?index.php/ - [L,R=404]

# ...other settings...
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted

If you can write a complete VirtualHost configuration and want to keep separate web directory:

<VirtualHost *:80>
    ServerName app.example.com

    # Frontend
    # ==============================
    DocumentRoot /path/to/yii2-advanced/frontend/web
    <Directory /path/to/yii2-advanced/frontend/web>
        # Use mod_rewrite for pretty URL support
        RewriteEngine On
        # If a directory or a file exists, use the request directly
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        # Otherwise forward the request to index.php
        RewriteRule . index.php

        # If $showScriptName is false in UrlManager, do not allow accessing URLs with script name
        RewriteRule ^index.php/ - [L,R=404]

        # ...other settings...
        Options -Indexes +FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>

    # Backend
    # ==============================
    Alias /admin /path/to/yii2-advanced/backend/web
    <Directory /path/to/yii2-advanced/backend/web>
        # Use mod_rewrite for pretty URL support
        RewriteEngine On
        # If a directory or a file exists, use the request directly
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        # Otherwise forward the request to index.php
        RewriteRule . index.php

        # If $showScriptName is false in UrlManager, do not allow accessing URLs with script name
        RewriteRule ^index.php/ - [L,R=404]

        # ...other settings...
        Options -Indexes +FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>

Note: sorry, but the external configuration linked at the end of the document is an overkill and in contrast with the Apache recommendations. I filed a bug to Oleg about: https://github.com/mickgeek/yii2-advanced-one-domain-config/issues/16

mickgeek commented 6 years ago

Of cource, if you have a highload project, you have good skills and should to optimize the web server configuration anyway. The one-domain-config repo proposes the base and universal solution without bugs. The speed implications of using mod_alias instead mod_rewrite in most cases is negligible.

About your second config. If we set the alias, the request to /admin will always force redirect to /admin/. And I don't think that we should restrict the access to /index.php/*, because Yii allow us to change the visibility behavior. Also, your configs have some slight flaws.

hujuice commented 6 years ago

@mickgeek , in the application that I'm developing, my running configuration simply starts with:

RewriteEngine On
# If $showScriptName is false in UrlManager, do not allow accessing URLs with script name
RewriteRule ^(/backend)?/index.php/ - [L,R=404]
# Protect against access to special files
RewriteRule \.(htaccess|htpasswd|svn|git) - [L,R=404]

# Frontend
# ==============================
DocumentRoot /path/to/yii2-advanced/frontend/web
<Directory /path/to/yii2-advanced/frontend/web>
...

I think that it's unrelated.

mickgeek commented 6 years ago

It does not really make much sense to restrict index.php/*, if a direct path to the entry script anyway is available. But using of it is more than acceptable.

When we use the document root as the path to the frontend app, we need use the alias. When we use the alias, we can't manipulate the trailing slash.

mickgeek commented 6 years ago

Anyway, if we talk about a shared hosting, usually we only have access to the .htaccess files.

mickgeek commented 6 years ago

I got the next .htaccess and vhosts, mod_alias is used now.

hujuice commented 6 years ago

I think that these ideas are better. Firstly, because a typical "shared hosting" scenario doesn't have a VirtualHost context, so a pure .htaccess solution is necessary. But also because the typical "shared hosting" scenario is not the unique: one can prefer to stay in one domain enjoying the Alias recommendation by Apache.

I've a couple of hints (I'm in hurry now, I cannot explore better).

The $showScriptName also should be managed with some trick, depending on the context.

I've found also 'AllowNoSlash' in the RewriteOptions section http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriteoptions

Have a nice day, HUjuice

mickgeek commented 6 years ago

We can also use FallbackResource (since 2.2.16), FilesMatch and RedirectMatch instead RewriteRule, restrict the /assets/*.php files or use new features from 2.4. It is optional, but maybe I add something to the repo later.