Stop inserting "index.php" with Apache + fastcgi?

Hi everybody,

I am using Nextcloud 11.0.2 on Webfaction, and everything seem to work well. Now I would like to remove “index.php” from the URLs. I followed the instructions here and added 'htaccess.RewriteBase' => '/' to my config, however then I read:

Furthermore these instructions are only working when using Apache together with the mod_php Apache module for PHP. Other modules like php-fpm or mod_fastcgi are unsupported.

As far as I can see, Webfaction uses Apache with fastcgi and PHP 7. Nevertheless, the url rewriting seems to work. I can use either https://example.com/apps/files or https://example.com/index.php/apps/files. However, often, but not always, I get a 303 redirect to the long url (with index.php). Also, some links (such as in the dropdown menu in the top left) have the long urls, and some others don’t.

Is there any way to suppress these redirects? It seems some part of the code is thinking the URL rewriting does not work, while it does. Any ideas?

found a solution? same problem here.

Have you also done a regeneration of the .htaccess file with the occ command:

sudo -u www-data php occ maintenance:update:htaccess

No I haven’t found a solution yet.

@X4LD1M0 Yes, the .htaccess file is generated properly. Redirects from short to long addresses work fine. The problem is that Nextcloud (unnecessarily) writes the long URLs into the HTML output.

You have the possibility to connect via SSH to your Webfaction server. Can you check which PHP packages are installed but running:

dpkg -l | grep php

And show the list of active Apache modules with:

ls /etc/apache/mods-enabled

As it states the mod_fastcgi is not supported, so the incoming requests (if you remove the index.php part) will work since the rewrite code will process it, but the outgoing HTML code won’t be changed since it can’t process it as per the documentation.

same problem here. jessie, php5.6, fpm. everything works except removing index.php from the url. even the urls without index.php work fluently, but nextlcoud constantly adds/redirects it to the links with index.php…

dpkg -l|grep php
ii  php-pear                       5.6.30+dfsg-0+deb8u1               all          PEAR - PHP Extension and Application Repository
ii  php5                           5.6.30+dfsg-0+deb8u1               all          server-side, HTML-embedded scripting language (metapackage)
ii  php5-cgi                       5.6.30+dfsg-0+deb8u1               amd64        server-side, HTML-embedded scripting language (CGI binary)
ii  php5-cli                       5.6.30+dfsg-0+deb8u1               amd64        command-line interpreter for the php5 scripting language
ii  php5-common                    5.6.30+dfsg-0+deb8u1               amd64        Common files for packages built from the php5 source
ii  php5-curl                      5.6.30+dfsg-0+deb8u1               amd64        CURL module for php5
ii  php5-dev                       5.6.30+dfsg-0+deb8u1               amd64        Files for PHP5 module development
ii  php5-fpm                       5.6.30+dfsg-0+deb8u1               amd64        server-side, HTML-embedded scripting language (FPM-CGI binary)
ii  php5-gd                        5.6.30+dfsg-0+deb8u1               amd64        GD module for php5
ii  php5-imagick                   3.2.0~rc1-1                        amd64        Provides a wrapper to the ImageMagick library
ii  php5-imap                      5.6.30+dfsg-0+deb8u1               amd64        IMAP module for php5
ii  php5-intl                      5.6.30+dfsg-0+deb8u1               amd64        internationalisation module for php5
ii  php5-json                      1.3.6-1                            amd64        JSON module for php5
ii  php5-mcrypt                    5.6.30+dfsg-0+deb8u1               amd64        MCrypt module for php5
ii  php5-mysql                     5.6.30+dfsg-0+deb8u1               amd64        MySQL module for php5
ii  php5-sqlite                    5.6.30+dfsg-0+deb8u1               amd64        SQLite module for php5
ii  php5-xsl                       5.6.30+dfsg-0+deb8u1               amd64        XSL module for php5

apachectl -M

Loaded Modules:
 core_module (static)
 so_module (static)
 watchdog_module (static)
 http_module (static)
 log_config_module (static)
 logio_module (static)
 version_module (static)
 unixd_module (static)
 access_compat_module (shared)
 actions_module (shared)
 alias_module (shared)
 auth_basic_module (shared)
 authn_core_module (shared)
 authn_file_module (shared)
 authz_core_module (shared)
 authz_groupfile_module (shared)
 authz_host_module (shared)
 authz_user_module (shared)
 autoindex_module (shared)
 deflate_module (shared)
 dir_module (shared)
 env_module (shared)
 fastcgi_module (shared)
 filter_module (shared)
 headers_module (shared)
 mime_module (shared)
 mpm_worker_module (shared)
 negotiation_module (shared)
 reqtimeout_module (shared)
 rewrite_module (shared)
 rpaf_module (shared)
 setenvif_module (shared)
 status_module (shared)

apache virtual host like this

<VirtualHost *:80>
  ServerName foo.com

  DocumentRoot /var/www/nextcloud/foo
  <Directory /var/www/nextcloud/foo>
    Options +FollowSymlinks
    AllowOverride All
    Require all granted
    Satisfy Any
   <IfModule mod_dav.c>
    Dav off
   </IfModule>
   SetEnv HOME /var/www/nextcloud/foo
   SetEnv HTTP_HOME /var/www/nextcloud/foo
  </Directory>

  #we have our own fpm-user/pool:
  <IfModule mod_fastcgi.c>
      AddType application/x-httpd-fastphp5 .php
      Action application/x-httpd-fastphp5 /php5-fcgi
      Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi-foo
      FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi-foo -socket /var/run/php5-fpm-foo.sock -pass-header Authorization
  </IfModule>
`</VirtualHost>`

php fpm pool like this

[www-foo]
user = www-foo
group = www-foo
listen = /var/run/php5-fpm-foo.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 3
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.status_path = /status
ping.path = /ping
slowlog = /dev/null
request_slowlog_timeout = 30s
chdir = /
catch_workers_output = yes
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
security.limit_extensions =

nextcloud 11.0.2 with config

...
  'overwrite.cli.url' => 'http://foo.com',
  'htaccess.RewriteBase' => '/',
...

generated .htaccess

...
<IfModule mod_rewrite.c>
  Options -MultiViews
  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]
  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]
  RewriteCond %{REQUEST_FILENAME} !\.(css|js|svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$
  RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$
  RewriteCond %{REQUEST_FILENAME} !/remote.php
  RewriteCond %{REQUEST_FILENAME} !/public.php
  RewriteCond %{REQUEST_FILENAME} !/cron.php
  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php
  RewriteCond %{REQUEST_FILENAME} !/status.php
  RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php
  RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php
  RewriteCond %{REQUEST_FILENAME} !/updater/
  RewriteCond %{REQUEST_FILENAME} !/ocs-provider/
  RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*
  RewriteRule . index.php [PT,E=PATH_INFO:$1]
  RewriteBase /
  <IfModule mod_env.c>
    SetEnv front_controller_active true
    <IfModule mod_dir.c>
      DirectorySlash off
    </IfModule>
  </IfModule>
</IfModule>

As can be seen in your output it shows it is using FastCGI, which is not supported for pretty URLs. The rewrite section in the .htaccess file will rewrite any ‘pretty’ incoming URLs to include index.php but the outgoing HTML code back to the browser won’t get rewritten to remove the index.php due to the restrictions of fastcgi and fpm. So unfortunately it won’t be possible unless you are able to switch over to the mod_php structure.

This isn’t a problem with NextCloud but a limitation of the interaction of Apache and PHP (for which only the mod_php can rewrite it).

Hi, my hoster uses CentOS and not Debian, but here are the packages:

$ rpm -qa | grep php70 | sort
php70-7.0.17-1.el7.webfaction.x86_64
php70-cli-7.0.17-1.el7.webfaction.x86_64
php70-memcached-2.2.0-1.el7.webfaction.x86_64
php70-pear-1.10.1-0.webfaction.noarch
php70-pear-HTTP_Request2-2.2.1-0.webfaction.noarch
php70-pear-Mail-1.3.0-1.webfaction.noarch
php70-pear-Mail_Mime-1.10.0-1.webfaction.noarch
php70-pear-Net_SMTP-1.7.2-1.webfaction.noarch
php70-pear-Net_Socket-1.0.14-0.webfaction.noarch
php70-pear-Net_URL2-2.1.2-1.webfaction.noarch
php70-pecl-imagick-3.4.1-1.el7.webfaction.x86_64
php70-pecl-mailparse-3.0.0-0.el7.webfaction.x86_64

$ ls /etc/apache/mods-enabled
ls: cannot access /etc/apache/mods-enabled: No such file or directory

$ ls /etc/httpd/modules
mod_access_compat.so    mod_dialup.so               mod_proxy_express.so
mod_actions.so          mod_dir.so                  mod_proxy_fcgi.so
mod_alias.so            mod_dontdothat.so           mod_proxy_fdpass.so
mod_allowmethods.so     mod_dumpio.so               mod_proxy_ftp.so
mod_asis.so             mod_echo.so                 mod_proxy_http.so
mod_auth_basic.so       mod_env.so                  mod_proxy_scgi.so
mod_auth_digest.so      mod_expires.so              mod_proxy.so
mod_authn_anon.so       mod_ext_filter.so           mod_proxy_wstunnel.so
mod_authn_core.so       mod_file_cache.so           mod_ratelimit.so
mod_authn_dbd.so        mod_filter.so               mod_reflector.so
mod_authn_dbm.so        mod_headers.so              mod_remoteip.so
mod_authn_file.so       mod_heartbeat.so            mod_reqtimeout.so
mod_authn_socache.so    mod_heartmonitor.so         mod_request.so
mod_authz_core.so       mod_include.so              mod_rewrite.so
mod_authz_dbd.so        mod_info.so                 mod_security2.so
mod_authz_dbm.so        mod_lbmethod_bybusyness.so  mod_sed.so
mod_authz_groupfile.so  mod_lbmethod_byrequests.so  mod_setenvif.so
mod_authz_host.so       mod_lbmethod_bytraffic.so   mod_slotmem_plain.so
mod_authz_owner.so      mod_lbmethod_heartbeat.so   mod_slotmem_shm.so
mod_authz_svn.so        mod_log_config.so           mod_socache_dbm.so
mod_authz_user.so       mod_log_debug.so            mod_socache_memcache.so
mod_autoindex.so        mod_log_forensic.so         mod_socache_shmcb.so
mod_buffer.so           mod_logio.so                mod_speling.so
mod_cache_disk.so       mod_lua.so                  mod_status.so
mod_cache.so            mod_macro.so                mod_substitute.so
mod_cache_socache.so    mod_mime_magic.so           mod_suexec.so
mod_cgid.so             mod_mime.so                 mod_systemd.so
mod_cgi.so              mod_mpm_event.so            mod_unique_id.so
mod_charset_lite.so     mod_mpm_prefork.so          mod_unixd.so
mod_data.so             mod_mpm_worker.so           mod_userdir.so
mod_dav_fs.so           mod_negotiation.so          mod_usertrack.so
mod_dav_lock.so         mod_pagespeed_ap24.so       mod_version.so
mod_dav.so              mod_pagespeed.so            mod_vhost_alias.so
mod_dav_svn.so          mod_proxy_ajp.so            mod_watchdog.so
mod_dbd.so              mod_proxy_balancer.so
mod_deflate.so          mod_proxy_connect.so

Here is a phpinfo, redirected to in the same way as index.php (which I will take down after a while):
https://cloud.hidpi.info/information/test?foo=bar
https://cloud.hidpi.info/information
https://cloud.hidpi.info/phpinfo.php

The mod_rewrite part works absolutely fine. The problem is that nextcloud constructs URLs using SCRIPT_NAME (/phpinfo.php or /index.php), instead of SCRIPT_URL (/information/test or /apps/files). I wasn’t able to find the place in the source where that happens, as it goes through many layers of indirection.

I have to add that some links are correct (like the left-hand sidebar, All Files, Recent, …). Some links are not supposed to be shortened (remote.php). But most links that could be shortened are not. And I find that I sometimes, but not always, get redirected to the long URL. The redirect seems to get issued from PHP, not Apache.

Thanks for helping!

Hi StephanW,
I heard that before, could you please elaborate a bit? PHP code can write any URL it likes into HTML, I don’t understand how this can be a restriction from fastcgi. I thought maybe the issue was fastcgi not reporting the correct “clean” URL to PHP, but in my tests all the clean path, the original path, and the query parameters were available.

It seems to be rather a problem with the routing code or Symfony not detecting that short URLs are available. Somewhere in these files maybe?

lib/private/URLGenerator.php
lib/private/Route/Router.php
3rdparty/symfony/routing/Generator/UrlGenerator.php

My last experience with PHP is a long time ago so this is not so easy :slight_smile: but I think maybe I can at least create a config option to force short URLs.

You are correct in regards to the URLGenerator.php file, this does check if it can generate pretty URLs.

The line of code that checks for it is:

$frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');

But am not sure exactly where the FrontController values come from, but if you follow that script you can see it uses an if/else to use the index.php or pretty URL.

hm. not sure if i’m right: isn’t that a bug in the if? IgnoreFrontController===true means $frontControllerActive = true. as far as i understand $frontControllerActive should be false, if IgnoreFrontController===true… (if we keep out the ENV-var)… the default for this option is false … i don’t know if this matters at all on the whole discussion.

i found a solution (need to test further)… adding
'htaccess.IgnoreFrontController' => true,
to the config file works. as far as i see there is no change to the .htaccess when ./occ maintenance:update:htaccess is called…

but not sure what other consequences this option has…

1 Like

Thanks StefanW, toastbrotch, that is really interesting! I think this should be investigated further though to see that nothing breaks (e.g. infinite redirect loops). If it works, then it is just a matter of fixing the detection and I might be able to write a patch!

Edit: it seems front_controller_active is set in .htaccess by mod_env, which doesn’t work with fastcgi (I think because it reuses the same process, it cannot inject environment variables between calls). So this is just a matter of not detecting mod_rewrite. I have to think about it a bit more, probably this could be done in a different way.

About IgnoreFronController, this seems to be fairly benign, and is documented here: https://docs.nextcloud.com/server/11/admin_manual/configuration_server/config_sample_php_parameters.html#proxy-configurations

cheers,
Jason

1 Like

Yes you are correct. By default it will check if there is a front controller, but if (for example described in your link reference) it isn’t possible to confirm it, you can overwrite it by setting that value, as long as you can confirm yourself that mod_rewrite is working as expected.

So steps would be:

  1. Confirm rewrite is active and working
  2. Disable FrontController in config.php
  3. Confirm pretty URLs are working

yep on my setup:

  1. mod_rewrite is active and working
  2. setting: ‘htaccess.IgnoreFrontController’ => true in the config.php gives pretty urls

in the documentation is also ‘overwritewebroot’ => ‘’ mentioned, but this has no effect (i dont know if it should in our setups)

I would say if it works without setting ‘overwritewebroot’ then it won’t effect it and will be obsolete to use.

Only if there are problems (behind a proxy) you would want to set that value.

jup. i’m behind a proxy (nginx with ssl-offloading)… now everything works perfect. thanx!!

I am now myself hitting this issue.

I checked the lib/private/URLGenerator.php file (by checking the variables and outputting $urlLinkTo variable) and found that the URL is correct ‘/’ only. But the end HTML still includes the index.php part. So now puzzled where this is being added.

Are you using a Self Signed Certificate? I also followed this instructions Remove /index.php/ from the url until I realized I was using the SSL website so I just add the code to the apache virtual host, in my case nextcloud-ssl.conf

config.php file:

<?php $CONFIG = array ( 'htaccess.RewriteBase' => '/', Apache for both virtual hosts: Options +FollowSymlinks AllowOverride All Dav off SetEnv HOME /var/www/nextcloud SetEnv HTTP_HOME /var/www/nexcloud Satisfy Any

I don’t use self-signed certifcates. I have those lines already in my vhost config, as per the installation procedure.

I did notice that the only place the ‘index.php’ is showing is in the files section. Any other app or menu item is using pretty URL.