getgrav / grav-plugin-admin

Grav Admin Plugin
http://getgrav.org
MIT License
355 stars 223 forks source link

Upgrade problems Win10 IIS #2343

Open dk-ok opened 1 year ago

dk-ok commented 1 year ago

IIS 10.0 on Win 10 machine. PHP latest. New install - evaluating the product, looks promising!: grav-admin unzipped from getgrav.org. After all dependencies resolved/fixed, runs :), default UI, add admin user #1. Prompted to upgrade 1.7.39 -> 1.7.39.1 via "Upgrade Grav Now" button: Squish. Message of success in web UI. Nav to any Url, returns 403.13 (no default doc), including root of site. Observe that index.php is missing in app folder. system/config/system.yml has been overwritten (lost changes to username_regex, pwd_regex).

Copied index.php out of original zip file, and added changes back to system.yml. Restart web server. Seems to work, and am now presented with a new prompt to upgrade to 1.7.39.2. "Grav v1.7.39.2 is now available! (Current v1.7.39.1)" Squish button. Successful update. index.php once again missing, system.yml once again overwritten. Copy again from zip, update yml. Browser reload. Apparent success. Footer says v1.7.39.2 - Admin v1.10.39.

The date on index.php is 1 month as of today (2/20/2023), so I'm sort of assuming no changes since 1.7.39.0.

I also have detailed missing steps for Win 10 virgin install if you want. Numerous things missing from doco. This is a dev machine, but I'm going to want to reproduce/copy to a public Win server.

Is a copy via git clone preferable to install from this zip? Thanks!

rhukster commented 1 year ago

The upgrade procedure via Admin or CLI (bin/gpm) is usually very reliable. At least on Mac/Linux machines. Windows has some 'quirks' and it seems most people that have issues are on Windows. Updating via the "upgrade" package zip is also fine as that's all the built in package manager stuff is doing anyway (unzip they copy recursively).

BTW, only the system/config/system.yaml will get overridden.. You should be making any modifications in the user/config/system.yaml as everything outside of user/ folder is considered system files and can be deleted or updated by Grav itself. Things in user/ folder are for you to mess with.. That's where content goes, configuration, plugins, themes etc.

Cheers!

dk-ok commented 1 year ago

HI Andy!

Thanks for the newbie lesson on system.yaml. Moved to user/config/system.yaml. Works beautifully.

Here are the additional hoops jumped through for Win10 IIS/PHP fresh install. Perhaps someone else will benefit. Do the Windows/IIS config first so that the rest falls into place easier.

PHP - download, install latest to say, "c:\php" folder

Add c:\php to PATH environment vars. I added to both system path and user path just in case.

Make sure the following are enabled in php.ini (or use local ini file - see https://www.php.net/manual/en/configuration.file.per-user.php): Enable extensions: curl, gd, mbstring, openssl, zip

Download and add to path composer.phar from https://getcomposer.org/download/ -- php dependency manager; "Latest Stable"

Check php path & version: C:> php -v

Ran "php composer.phar update" in Grav folder. Don't know if was strictly required. This command seemed to fix all the initial PHP shortcomings by downloading some 56 packages.

Ran "php bin/gpm selfupgrade -f" resulted in:

Grav v1.7.39.1 is now available [release date: Mon Feb 20 18:54:47 2023]. You are currently using v1.7.39. --respond to 2 prompts with no, yes Preparing to upgrade to v1.7.39.1.. |- Downloading upgrade [8.9M]... 100% |- Installing upgrade... error | '- Unknown error '- Installation failed or aborted.

Note: In the end, I upgraded by smashing Upgrade buttons as described above, then recopying index.php to root folder. Missing index.php was the only apparent failure in Grav.

IIS

Enable CGI Module in (advanced) Windows Features (under IIS feature node). Dig to find as it keeps falling deeper into MS retro-land. This installs the "FastCGI" module in IIS. Add Handler for php to Grav app web.config. See example below. Also add default doc definition.

Download/Install IIS Url Rewrite v2.0 module from https://www.iis.net/downloads/microsoft/url-rewrite

Note: Web Platform Installer is obsoleted as of 12/2022. Restart IIS Manager.

Select Grav app in IIS Manager, select Url Rewrite, Right-click list of Rules, select Inbound rules -> Import rules, select .htaccess file from Grav folder. Restart web server.

Note: I did not have any problems with folder/file permissions - a first for me for a Windows machine. Perhaps because it is a dev machine and current user is already authorized to execute code from localhost. On servers, usually need to add IIS_USR or NETWORK_SERVICE as read/execute/write permission on folder.

Nav to site in browser. HTTP Error 500.52 - URL Rewrite Module Error. The expression "({{|}}|{%|%})" contains a repeat expression (one of '*', '?', '+', '{' in most contexts) that is not preceded by an expression.

Soultion (from somewhere on this site): Comment out from "Imported Rule #1" first 2 "adds" (URL + QUERY_STRING).

Final web.config:

<?xml version="1.0" encoding="UTF-8"?>
<configuration> 
    <system.webServer>
        <defaultDocument>
            <files>
                <add value="index.php" />
            </files>
        </defaultDocument>
        <handlers>
            <add name="PHP-FastCGI" path="*.php" verb="*" modules="FastCgiModule" scriptProcessor="C:\php\php-cgi.exe" resourceType="File" />
        </handlers>
        <rewrite>
            <rules>
                <rule name="Imported Rule 1">
                    <match url=".*" ignoreCase="false" />
                    <conditions logicalGrouping="MatchAny">
            <!-- Fails under IIS 10.0 under Win10
                        <add input="{URL}" pattern="({{|}}|{%|%})" ignoreCase="false" />
                        <add input="{QUERY_STRING}" pattern="({{|}}|{%25|%25})" ignoreCase="false" />-->
                        <add input="{QUERY_STRING}" pattern="base64_encode[^(]*\([^)]*\)" ignoreCase="false" />
                        <add input="{QUERY_STRING}" pattern="(&lt;|%3C)([^s]*s)+cript.*(>|%3E)" />
                        <add input="{QUERY_STRING}" pattern="GLOBALS(=|\[|\%[0-9A-Z]{0,2})" ignoreCase="false" />
                        <add input="{QUERY_STRING}" pattern="_REQUEST(=|\[|\%[0-9A-Z]{0,2})" ignoreCase="false" />
                    </conditions>
                    <action type="CustomResponse" url="index.php" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
                </rule>
                <rule name="Imported Rule 2" stopProcessing="true">
                    <match url=".*" ignoreCase="false" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{URL}" pattern="^/index\.php" ignoreCase="false" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="index.php" />
                </rule>
                <rule name="Imported Rule 3">
                    <match url="^(\.git|cache|bin|logs|backup|webserver-configs|tests)/(.*)" ignoreCase="false" />
                    <action type="CustomResponse" url="error" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
                </rule>
                <rule name="Imported Rule 4">
                    <match url="^(system|vendor)/(.*)\.(txt|xml|md|html|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$" ignoreCase="false" />
                    <action type="CustomResponse" url="error" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
                </rule>
                <rule name="Imported Rule 5">
                    <match url="^(user)/(.*)\.(txt|md|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$" ignoreCase="false" />
                    <action type="CustomResponse" url="error" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
                </rule>
                <rule name="Imported Rule 6">
                    <match url="\.md$" ignoreCase="false" />
                    <action type="CustomResponse" url="error" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
                </rule>
                <rule name="Imported Rule 7">
                    <match url="(^|/)\.(?!well-known)" ignoreCase="false" />
                    <action type="CustomResponse" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
                </rule>
                <rule name="Imported Rule 8">
                    <match url="^(LICENSE\.txt|composer\.lock|composer\.json|\.htaccess)$" ignoreCase="false" />
                    <action type="CustomResponse" url="error" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer> 
</configuration>