Search code examples
.htaccessshared-hostinginternal-server-errorhttp-status-code-500

500 error for html site on shared hosting, is my .htaccess syntax wrong?


First time here. I'm actually an Industrial & Systems Engineer from Mexico, trying to become a self-taught Web Developer/Graphic Designer. I'M SORRY if my english is flawed & for being such a noob, especially if my question was already asked by someone else, or whatever. (I did search questions, though)

I just finished (out of a bought html template) the 1º stage of the website (& everything design wise) of a new company (which is my client): https://www.starhauss.com/

The site works fine... considering what was requested of me, considering it's the 1º stage, it has minor flaws... I think.

ANYWAY...

I need to do (& tried) several things with .htaccess for my client, ASAP:

  1. Redirect to custom 404
  2. Declare Spanish language (the site will soon have an english version on /en/ directory)
  3. Block sensible Server info
  4. Disable directory listings
  5. Remove www from urls
  6. Remove html file extensions from urls
  7. Block hidden files from appearing
  8. Block "risky" files from appearing
  9. Force https on the urls
  10. Check & correct simple spelling errors on urls

I researched the Apache guides & everything, from different sources & I came up with my own .htaccess file, but I'm not sure if the syntax is wrong, or if I need to contact the respective Hosting Support Guys so they allow my file to be executed, because when it's uploaded (RIGHT NOW IT'S NOT UPLOADED) with CyberDuck to the root directory encoding text via US-ASCII with 755 file permissions, accessing my site results in a 500 Internal Server Error. I don't know what modules are on by default on the server of the shared hosting company, but of what I understand, they do work with the Apache Platform.

My .htaccess code is the next

# redirect not found
ErrorDocument 404 /404.html

# declare language for multilingual sites, adding a .htaccess file for each language subdirectory
DefaultLanguage es

# prevent server from outputing sensible information
ServerSignature Off

# disable directory listings, only when on
Options -Indexes

# requirement to change urls & such
RewriteEngine On

# use in subdirectories if rewrite rules are not working properly
# RewriteBase /

# mod_rewrite.c wrapper works mainly with WordPress & such
# <IfModule mod_rewrite.c>

# remove www from urls
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]

# remove html file extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.html [NC, L]

# block hidden files
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule "(^|/)\." - [F]

# </IfModule>

# block risky files
<FilesMatch "(^#.*#|\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|sw[op])|~)$">
  Order allow,deny
  Deny from all
  Satisfy All
</FilesMatch>

# force https
<IfModule mod_headers.c>
  Header set Strict-Transport-Security max-age=16070400;
</IfModule>

# check & correct url spelling errors, useful for SEO
<IfModule mod_speling.c>
  CheckSeplling On
</IfModule>

So, what do you think guys? Should it work? Is something wrong with the code syntax, the order or whatever? Is something missing Server Side for the file to work & if so, how can I know, if I have no access to the Httpd.Conf? Should I get in contact with the shared hosting support for them to allow my file?


Solution

  • RewriteRule ^([^\.]+)$ $1.html [NC, L]
    

    You have an erroneous space in the RewriteRule flags argument. This will result in a 500 Internal Server Error and if you look at your server's error.log you will see an error reported like "RewriteRule: bad flag delimiters".

    Whenever you get a 500 error (which is just a generic server response), you need to check the server's error log for the details of that error.

    In this case, [NC, L] should be [NC,L]. Although the NC flag is superfluous here, so [L] is sufficient.

    <IfModule mod_speling.c>
      CheckSeplling On
    </IfModule>
    

    You've spelt CheckSpelling wrong. (This would also trigger a 500 error response.)

    1. Force https on the urls

       # remove www from urls
       RewriteCond %{HTTPS} !=on
       RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
       RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
      

    You're not actually "forcing HTTPS" anywhere.

    The above only removes www on HTTP only. Why are you specifically checking that the request is not HTTPS in the above www to non-www redirect and redirecting to HTTP, not HTTPS?

    You could change the above to the following in order to remove www on HTTP and HTTPS (canonicalising HTTPS at the same time):

      # Remove www (redirect to HTTPS)
      RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
      RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
    

    And add an additional rule to force HTTPS (however, see note below about HSTS*1):

      # Force HTTPS
      RewriteCond %{HTTPS} !=on
      RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    
    # force https
    <IfModule mod_headers.c>
      Header set Strict-Transport-Security max-age=16070400;
    </IfModule>
    

    This doesn't strictly "force https".

    This "HSTS header" instructs the browser to always request HTTPS, once the user has visited the site over HTTPS. It does nothing if the user has only visited the site over HTTP (hence the requirement to first redirect/force the user to HTTPS - see above). However, this is not complete - you need to redirect on the same host first (*1ie. reverse the two redirects above) and also set the header on the 301 redirect that removes www over HTTPS (this directive does not). And ideally you should avoid sending the header over plain HTTP (although that does not strictly matter, as the browser will simply ignore it).

    I would avoid setting HSTS initially, until your site is working correctly over HTTPS. You should consider HSTS as a one-way trip, it is problematic to backtrack on this (max-age=16070400 will persist this for 6+ months for anyone who visits over HTTPS).

    See the following related question on the CodeReview stack regarding HSTS implementation: https://codereview.stackexchange.com/questions/250805/hsts-recommendations-in-htaccess

      Order allow,deny
      Deny from all
      Satisfy All
    

    These are Apache 2.2 directives and are formerly deprecated on Apache 2.4. I assume you are using Apache 2.4 (Apache 2.2 was EOL almost 2 years ago). You should use the Apache 2.4 directives instead:

    Require all denied