caddyserver / caddy

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
https://caddyserver.com
Apache License 2.0
57.33k stars 4k forks source link

Examples of converted htaccess files? #472

Closed pwFoo closed 8 years ago

pwFoo commented 8 years ago

Hello,

I found caddy a short time ago and really like it. So I would be interested into converted htaccess files to get applications (cms, ...) working with caddy (+php-fpm).

Maybe (working and tested) examples could be added to the documentation?

abiosoft commented 8 years ago

Yeah. Rewrite is getting some notable updates that will roll out with the next patch release in about a week. However, the current version supports it to some extent. But if you're willing to build from source, you should be covered.

Can you provide the htaccess contents you'd like to replicate with Caddy? I'll gladly help with that.

The plan is to get examples here https://github.com/caddyserver/examples. We are accepting PRs for more examples for any Caddy feature.

pwFoo commented 8 years ago

At the moment I play and test ProcessWire CMS and Flarum forum software

ProcessWire CMS / CMF https://github.com/ryancramerdesign/ProcessWire/blob/master/htaccess.txt

Flarum https://github.com/flarum/flarum/blob/master/.htaccess

Here are Flarum nginx and lighttpd examples too: http://flarum.org/docs/installation/

There are many other interesting apps like Wordpress, Drupal, SMF or phpBB to make Caddy more interesting for people (which I not need / use yet g).

So Flarum and ProcessWire would be very interesting for me. Also to do some tests running both on Caddy :)

abiosoft commented 8 years ago

Converting Flarum's Apache rewrite.

rewrite {
    r ^vendor/(.*)?$
    to /forbidden.html #or any error path/page.
}
rewrite {
    r ^storage/(.*)?$
    to /forbidden.html #or any error path/page.
}
rewrite {
    r ^config.php$
    to /forbidden.html #or any error path/page.
}
rewrite {
    r  ^api(.*)$
    to /api.php
}
rewrite {
    r  ^admin(.*)$
    to /admin.php
}

# not available until next patch release
rewrite {
    to {uri} {uri}/ /index.php
}

Converting Flarum's nginx rewrite installation instruction.

# not available until next patch release
rewrite /api {
    to {uri} {uri}/ /api.php
}
rewrite /admin {
    to {uri} {uri}/ /admin.php
}
rewrite /flanium {
    to /404.html #or any error path/page.
}
rewrite {
    to {uri} {uri}/ /index.php
}
abiosoft commented 8 years ago

ProcessWire looks too dependent on Apache mod_rewrite as there's no official support for nginx and any other server. But I've been able to extract some rewrite conditions.

RewriteCond %{REQUEST_URI} "[^-_.a-zA-Z0-9/~]"
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?it=/http404/ [L,QSA]

Translates to

# not available until next patch release
rewrite {
    r [^-_.a-zA-Z0-9/~]
    to {uri} {uri}/ /index.php?it=/http404&{query}
}

And this

RewriteCond %{REQUEST_URI} "^/~?[-_.a-zA-Z0-9/]*$"
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !(favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ index.php?it=$1 [L,QSA]

Translates to

# not available until next patch release
rewrite {
    r ^/~?[-_.a-zA-Z0-9/]*$
    {file} not favicon.ico
    {file} not robots.txt
    to {uri} {uri}/ /index.php?it={path_escaped}&{query}
}
abiosoft commented 8 years ago

I'll be closing this issue.

The documentation will be updated as required when the features are ready and anyone is welcomed to contribute to https://github.com/caddyserver/examples.

Thanks.

pwFoo commented 8 years ago

Wow, great! Thank you to spend your time for that!!!

pwFoo commented 8 years ago

Sorry for posting to a closed topic, but someone converted ProcessWire (older version, but should be the same content...) htaccess to nginx. Maybe that would help?

server {
       listen 80;
       server_name www.example.com example.com;
       root /var/www/www.example.com/web;

       if ($http_host != "www.example.com") {
                 rewrite ^ http://www.example.com$request_uri permanent;
       }

       index index.php index.html;

       location = /favicon.ico {
                log_not_found off;
                access_log off;
       }

       location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
       }

       # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
       location ~ /\. {
                deny all;
                access_log off;
                log_not_found off;
       }

       client_max_body_size 100M;

       location ~ /(COPYRIGHT|LICENSE|README|htaccess)\.txt {
                deny  all;
       }
       location ~ ^/site(-[^/]+)?/assets/(.*\.php|backups|cache|config|install|logs|sessions) {
                deny  all;
       }
       location ~ ^/site(-[^/]+)?/install {
                deny  all;
       }
       location ~ ^/(site(-[^/]+)?|wire)/(config(-dev)?|index\.config)\.php {
                deny  all;
       }
       location ~ ^/((site(-[^/]+)?|wire)/modules|wire/core)/.*\.(inc|module|php|tpl) {
                deny  all;
       }
       location ~ ^/(site(-[^/]+)?|wire)/templates(-admin)?/.*\.(inc|html?|php|tpl) {
                deny  all;
       }

       ### GLOBAL REWRITE
       location / {
                try_files  $uri  $uri/  /index.php?it=$uri&$args;
       }

       location ~ \.php$ {
                try_files $uri =404;
                include /etc/nginx/fastcgi_params;
                fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_intercept_errors on;
       }
}

Here is a filtered PW htaccess file without comments.

//-- Apache config should be ported to caddyfile (remove indexes, will caddy follow symlinks?, default error page) --//
Options -Indexes
Options +FollowSymLinks
ErrorDocument 404 /index.php
//-- Apache config should be ported to caddyfile (remove indexes, will caddy follow symlinks?, default error page) --//

//-- 404 error instead of PW internal error page / handling? --//
<Files favicon.ico>
  ErrorDocument 404 "The requested file favicon.ico was not found.
</Files>
<Files robots.txt>
  ErrorDocument 404 "The requested file robots.txt was not found.
</Files>
//-- 404 error instead of PW internal error page / handling? --//

<IfModule mod_headers.c>
  Header always append X-Frame-Options SAMEORIGIN 
  Header set X-XSS-Protection "1; mode=block"
</IfModule>

//-- ??? --//
<FilesMatch "\.(inc|info|info\.json|module|sh|sql)$|^(\..*)$">
  Order allow,deny
</FilesMatch>
//-- ??? --//

//-- Ignore because htaccess file related --//
<Files .htaccess>
  order allow,deny
  deny from all
</Files>
//-- Ignore because htaccess file related --//

//-- php config move to php-fpm config --//
<IfModule mod_php5.c>
  php_flag magic_quotes_gpc     off
  php_flag magic_quotes_sybase      off
  php_flag register_globals     off
</IfModule>
//-- php config move to php-fpm config --//

// Directory index setting -> caddyfile --//
DirectoryIndex index.php index.html index.htm
// Directory index setting -> caddyfile --//

<IfModule mod_rewrite.c>
  RewriteEngine On
  AddDefaultCharset UTF-8
  <IfModule mod_env.c>
    SetEnv HTTP_MOD_REWRITE On
  </IfModule>
  RewriteRule "(^|/)\." - [F]
  RewriteCond %{REQUEST_URI} "[^-_.a-zA-Z0-9/~]"
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?it=/http404/ [L,QSA]

  RewriteCond %{REQUEST_URI} !(^|/)site-[^/]+/install/[^/]+\.(jpg|jpeg|png|gif)$
  RewriteCond %{REQUEST_URI} (^|/)\.htaccess$ [NC,OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets/(cache|logs|backups|sessions|config|install|tmp)($|/.*$) [OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/install($|/.*$) [OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets.*/-.+/.* [OR]
  RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/(config|index\.config|config-dev)\.php$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets($|/|/.*\.php)$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)wire/(core|modules)/.*\.(php|inc|tpl|module|info\.json)$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/modules/.*\.(php|inc|tpl|module|info\.json)$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)(COPYRIGHT|INSTALL|README|htaccess)\.(txt|md|textile)$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)site-default/
  RewriteRule ^.*$ - [F,L]

  RewriteCond %{REQUEST_URI} "^/~?[-_.a-zA-Z0-9/]*$"
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !(favicon\.ico|robots\.txt)
  RewriteRule ^(.*)$ index.php?it=$1 [L,QSA]

This section should be converted as caddy internal? Just block direct access, but to along list of directories / files...

RewriteCond %{REQUEST_URI} !(^|/)site-[^/]+/install/[^/]+\.(jpg|jpeg|png|gif)$
  RewriteCond %{REQUEST_URI} (^|/)\.htaccess$ [NC,OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets/(cache|logs|backups|sessions|config|install|tmp)($|/.*$) [OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/install($|/.*$) [OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets.*/-.+/.* [OR]
  RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/(config|index\.config|config-dev)\.php$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets($|/|/.*\.php)$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)wire/(core|modules)/.*\.(php|inc|tpl|module|info\.json)$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/modules/.*\.(php|inc|tpl|module|info\.json)$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)(COPYRIGHT|INSTALL|README|htaccess)\.(txt|md|textile)$ [OR]
  RewriteCond %{REQUEST_URI} (^|/)site-default/
  RewriteRule ^.*$ - [F,L]

So it should be possible to convert all the content I think with caddy "internal", your posted snippets above and some entries moved to php config?

abiosoft commented 8 years ago

The only place regexp is supported in Caddy is rewrite but internal can still be used, not just directly.

It is easier to translate nginx to Caddy so I'll be doing that only. :wink:

Once again, note that this is not yet available. It is coming in next patch release or if you build from source.

example.com, www.example.com {

    root /var/www/www.example.com/web

    fastcgi / unix:/var/run/php5-fpm.sock php

    internal /forbidden

    rewrite {
        r /\.
        to /forbidden
    }
    rewrite {
        r /(COPYRIGHT|LICENSE|README|htaccess)\.txt
        to /forbidden
    }
    rewrite {
        r ^/site(-[^/]+)?/assets/(.*\.php|backups|cache|config|install|logs|sessions)
        to /forbidden
    }
    rewrite {
        r ^/site(-[^/]+)?/install
        to /forbidden
    }
    rewrite {
        r ^/(site(-[^/]+)?|wire)/(config(-dev)?|index\.config)\.php
        to /forbidden
    }
    rewrite {
        r ^/((site(-[^/]+)?|wire)/modules|wire/core)/.*\.(inc|module|php|tpl)
        to /forbidden
    }
    rewrite {
        r ^/(site(-[^/]+)?|wire)/templates(-admin)?/.*\.(inc|html?|php|tpl)
        to /forbidden
    }

    # GLOBAL
    rewrite {
        to {uri} {uri}/ /index.php?it={uri}&{query}
    }

}

Regarding posting to a closed issue, that's fine as long as the message is relevant.

mestaritonttu commented 8 years ago

I tried the above example and I get Access denied when trying to access my site. Yet, pwFoo and another PW user in the PW forums say that works for them. Serving PHP in a simple way works, static files work, but that PW config file does not work with PW.

The error log below has me accessing the site root and then accessing index.php.

10/Mar/2016:20:36:04 +0200 [ERROR 403 /] Access to the script '/var/www/user/pw' has been denied (see security.limit_extensions) 10/Mar/2016:20:36:13 +0200 [ERROR 200 /index.php] PHP message: PHP Fatal error: Uncaught Error: Call to a member function ready() on null in /var/www/user/pw/wire/core/ProcessWire.php:351 Stack trace:

0 /var/www/user/pw/wire/core/Wire.php(398): ProcessWire->___ready()

1 /var/www/user/pw/wire/core/Wire.php(333): Wire->runHooks('ready', Array)

2 /var/www/user/pw/wire/core/ProcessWire.php(404): Wire->__call('ready', Array)

3 /var/www/user/pw/wire/core/ProcessWire.php(324): ProcessWire->__call('ready', Array)

4 /var/www/user/pw/wire/modules/Process/ProcessPageView.module(227): ProcessWire->setStatus(4)

5 /var/www/user/pw/wire/core/Wire.php(398): ProcessPageView->___ready()

6 /var/www/user/pw/wire/core/Wire.php(333): Wire->runHooks('ready', Array)

7 /var/www/user/pw/wire/modules/Process/ProcessPageView.module(152): Wire->__call('ready', Array)

8 /var/www/user/pw/wire/core/Wire.php(398): ProcessPageView->___execute(true)

9 /var/www/user/pw/wire/core/Wire.php(333): Wire->runHooks('execute', Array)

10 /var/...

PHP message: PHP Fatal error: Class 'ProcessPageType' not found in /var/www/user/pw/wire/modules/LanguageSupport/ProcessLanguage.module on line 18

How could I troubleshoot this? I did try temporarily setting security.limit_extensions to FALSE in php-fpm's www.conf, but it was not the cause of the PHP fatal error. However, it made the Access denied go away and it changed to "No input file specified". This was in the log:

10/Mar/2016:20:42:56 +0200 [ERROR 404 /] PHP message: PHP Warning: Unknown: failed to open stream: Success in Unknown on line 0 Unable to open primary script: /var/www/user/pw (Success)

It is, of course, likely to be something in my system setup. I am getting assistance next week.

Edit: I discovered something had gone wrong with transferring my old site via wget. I transferred it with a different route and now the site works (at least in Nginx for now).

Edit 2: abiosoft helped me and now PW works with caddy. Note that this is the correct GLOBAL rewrite: to {path} {path}/ /index.php?it={path}&{query}

jottr commented 8 years ago

I have another .htaccess file from sendy.co, which I would love to get some input on how to convert it properly:

ErrorDocument 404 "[404 error] If you're seeing this error after install, check this FAQ for the fix: https://sendy.co/troubleshooting#404-error"

Options +FollowSymLinks
Options -Multiviews

RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^([a-zA-Z0-9-]+)$ $1.php [L]

# Link tracker
RewriteRule ^l/([a-zA-Z0-9/]+)$ l.php?i=$1 [L]

# Open tracker
RewriteRule ^t/([a-zA-Z0-9/]+)$ t.php?i=$1 [L]

# Web version
RewriteRule ^w/([a-zA-Z0-9/]+)$ w.php?i=$1 [L]

# unsubscribe
RewriteRule ^unsubscribe/(.*)$ unsubscribe.php?i=$1 [L]

# subscribe
RewriteRule ^subscribe/(.*)$ subscribe.php?i=$1 [L]

What about the options lines, i.e.: Options +FollowSymLinks, what does this convert to in caddy?

@abiosoft if you find the time, your help would be very much appreciated.

kokizzu commented 8 years ago

googling "is caddy follow symlink" and no answer here.. :3

mark-kubacki commented 8 years ago

@kokizzu On questions please join us on https://forum.caddyserver.com

(Edited to update link to forum)