Skip to content

Commit 80189e0

Browse files
authored
Merge pull request #1 from rkaiser0324/develop
doc: reformat and add supported-features section
2 parents 2a987c4 + 36401b4 commit 80189e0

File tree

1 file changed

+278
-61
lines changed

1 file changed

+278
-61
lines changed

README.md

Lines changed: 278 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,315 @@
1-
.htaccess for nginx
2-
===================
1+
# .htaccess for nginx
32

4-
**.htaccess for nginx** enables [nginx](https://nginx.org/en/) high performance webserver to deal with `.htaccess` files.
3+
**.htaccess for nginx** enables the [nginx](https://nginx.org/en/) high performance webserver to deal with `.htaccess` files.
54

6-
`.htaccess` files are mainly used for access control and URL rewrite instructions and are widely known across the web community. Originally designed for [Apache](https://www.apache.org/), there is no native implementation available for nginx.
5+
`.htaccess` files are mainly used for access control and URL rewrite instructions and are widely known across the web community. Originally designed for [Apache](https://www.apache.org/), there is no native implementation available for nginx. While there is a [legitimate reason for this](https://www.nginx.com/resources/wiki/start/topics/examples/likeapache-htaccess/), there would be huge practical benefit if nginx was able to support this.
76

87
**.htaccess for nginx** is efficient and elegant, using micro caching and various performance tweaks right out of the box. It is effortless in its installation and usage. The plugin's deeply integrated approach is ideal for webhosters, who are looking for mixed technology solutions using only nginx and nothing else.
98

10-
Stop Using Apache
11-
-----------------
9+
## Stop using Apache
1210

1311
* Apache is slow.
1412
* Apache is wasting resources.
1513
* Compared to nginx, Apache is poorly and inconsistently designed.
1614
* Apache's monolithic design prevents it from scaling properly, while nginx is capable of handling tens of thousands of simultaneous connections with ease.
1715
* Switching to nginx heavily improves performance, efficiency and security.
1816

19-
* * *
20-
21-
Reasons for .htaccess in nginx
22-
------------------------------
17+
## Reasons for .htaccess in nginx
2318

2419
When using nginx, there are many **legitimate reasons** to support `.htaccess` files.
2520

2621
* **Mixed technology.** Imagine using NodeJS and PHP side by side, running on one stable nginx webserver. When dealing with customer webspace, using Apache and nginx together (one proxying the other) is possible, however this adds unnecessary layers of redundancy and heavily wastes valuable server resources.
27-
* **Ease of use.** Everybody knows how to use `.htaccess` files. [January 2020, more than 24% of all active websites out there are still run by Apache's webserver](https://web.archive.org/web/20200130141042/https://news.netcraft.com/archives/2020/01/21/january-2020-web-server-survey.html), capable of utilizing `.htaccess` files. If nginx had a way to support this feature, this number would be going down significantly, making the web faster.
22+
* **Ease of use.** Everybody knows how to use `.htaccess` files. As pf January 2020, [more than 24% of all active websites](https://web.archive.org/web/20200130141042/https://news.netcraft.com/archives/2020/01/21/january-2020-web-server-survey.html) are still run on Apache and thus capable of utilizing `.htaccess` files. If nginx had a way to support this feature, this number would be going down significantly, making the web faster.
2823
* **Legacy.** Just use your old code, without worrying if someone could access a protected directory inside any library you just forgot to handle in your nginx config.
29-
* **Plug'n'play.** No need to convert `.htaccess` files for nginx and fix all the errors, rant about unsupported or oddly mixed up auto-generated config goo coming from a random online converter.
24+
* **Plug and play.** No need to convert `.htaccess` files for nginx and fix all the errors, rant about unsupported or oddly mixed up auto-generated config goo coming from a random online converter.
3025
* **Justified.** Apache performs multiple file reads anyway, so .htaccess for nginx cannot make it worse than Apache, right? In fact, with our built-in micro caching mechanism both, CPU and I/O load are reduced drastically compared to Apache's implementation.
3126
* **For webhosters.** Today, webhosters still need to provide an interface for their customers to change certain aspects of their webserver's behaviour. The decades long and proven `.htaccess` file does just that.
3227

33-
* * *
3428

35-
Performance
36-
-----------
29+
## Performance
3730

38-
**.htaccess for nginx is incredibly lightweight and fast!** It is writting from ground up with performance optimizations in mind. Even with low-end hardware it **adds less than 1 millisecond to your response time**, also for quite complex rewrite structures with server variables.
31+
**.htaccess for nginx is incredibly lightweight and fast!** It is written from the ground up with performance optimizations in mind. Even with low-end hardware it adds less than 1 millisecond to your response time, despite supporting quite complex rewrite structures with server variables.
3932

40-
Physical **memory usage** of this plugin is insanely low, just **less than 10 KB** for each nginx worker process, and it doesn't increase with more requests.
33+
Physical memory usage of this plugin is insanely low, under 10 KB for each nginx worker process, and it doesn't increase with more requests.
4134

42-
* * *
4335

44-
Requirements
45-
------------
36+
## Requirements
4637

47-
* Unix environment
48-
* `nginx` with Lua module
38+
* Debian or Fedora environment
39+
* `nginx` v1.19+ with Lua module
4940
* `curl` command-line tool
50-
51-
### Optional Dependencies
52-
53-
* `htpasswd` utility (`apache2-utils` package) for .htpasswd hashing functions (required for Basic HTTP Authentication)
54-
* `getent` utility (`libc-bin` package) for hostname lookups (e.g. `Deny from _domainname.tld_`)
55-
56-
* * *
57-
58-
Installation
59-
------------
60-
61-
* Install nginx **with Lua module**: `apt-get install nginx`
62-
* Install [Lua](https://www.lua.org/download.html): `apt-get install lua5.2`
63-
* Save this plugin directory into `/etc/nginx/`, so that you can access `/etc/nginx/htaccess-for-nginx/htaccess.lua`
64-
* Add the following configuration to your `http {}` context: `lua_shared_dict htaccess 16m;`
65-
* Configure your hosts (within the `server {}` context): `rewrite_by_lua_file /etc/nginx/htaccess-for-nginx/htaccess.lua;`
66-
67-
### Hints and Common Practice
68-
69-
* Depending on your operating system, the installation process may vary.
70-
* Make sure to have **Lua version 5.2** installed on your system.
71-
* You can clone this repository to any directory of your choice. Just make sure to adjust the paths accordingly.
72-
* If you don't set the `lua_shared_dict` setting in `http {}`, this plugin will refuse to work. It represents a caching system, used on a short-term per-request basis. Values (`.htaccess` lines) are usually cached less than 100 milliseconds, but kept in memory as long as there are active connections. You can choose to assign any other memory amount to it, although 16 MB should be more than enough.
73-
* ⚠️ Note that global configuration within your `http {}` context is technically possible. However, if you want to keep the good nginx performance for your new, non-legacy projects, you are **highly encouraged** to use this plugin in `server {}` context only.
74-
* To make your life easier, just create a config snipped and write e.g. `include snippets/htaccess.conf` in the `server {}` config.
75-
76-
* * *
77-
78-
Usage — Testing it
79-
------------------
41+
* Optional: `htpasswd` utility (`apache2-utils` package) for `.htpasswd` hashing functions (required for Basic HTTP Authentication)
42+
* Optional: `getent` utility (`libc-bin` package) for hostname lookups (e.g. `Deny from _domainname.tld_`)
43+
44+
45+
## Installation
46+
47+
1. Install nginx (with the [Lua module](https://github.com/openresty/lua-nginx-module) if you don't already have it) and luajit.
48+
1. Debian: `apt-get install nginx luajit`
49+
1. Fedora: `yum install nginx luajit`
50+
1. uild and install the plugin into an appropriate directory accessible by the nginx process, e.g.,
51+
```bash
52+
luajit -b htaccess.lua /etc/nginx/lua/htaccess.lbc
53+
```
54+
1. Add the following configuration to the nginx `http {}` context:
55+
```nginx
56+
http {
57+
...
58+
lua_shared_dict htaccess 16m;
59+
...
60+
}
61+
```
62+
This represents a caching system, used on a short-term per-request basis. `.htaccess` lines are usually cached as values for less than 100 milliseconds, but kept in memory as long as there are active connections. You can choose to assign any other memory amount to it, although 16 MB should be more than enough.
63+
1. Configure the nginx `server {}` context(s) to use the plugin:
64+
```nginx
65+
server {
66+
...
67+
rewrite_by_lua_file /path/to/htaccess.lua;
68+
# or reference the bytecode instead
69+
# rewrite_by_lua_file /path/to/htaccess.lbc;
70+
...
71+
}
72+
```
73+
74+
## Example
8075

8176
Create an `.htaccess` file in a directory of your host with the following content:
8277

83-
`Order deny,allow
84-
Deny from all`
78+
```apache
79+
Order deny,allow
80+
Deny from all
81+
```
8582

8683
When trying to access a file inside this directory through your browser, access should be denied by receiving an `HTTP 403` response.
8784

88-
* * *
89-
90-
Supported Features
91-
------------------
92-
93-
**We compiled a [complete list of implemented `.htaccess` directives and variables](https://htaccess-for-nginx.com/features).**
9485

95-
This plugin tries to make things as secure as possible. **Wherever an unclear situation occurs, access will be denied** to prevent unintended access, e.g. if unsupported, security-critical directives are being used (HTTP 500 response). Unsupported, non-security-related directives will be ignored.
86+
## Supported Syntax
87+
88+
The following tables came from [this page](https://htaccess-for-nginx.com/features).
89+
90+
### Sections
91+
92+
| Module | Section | Supported | Notes |
93+
| ------ | ------- | --------- | ----- |
94+
core | `<Else>` | No |
95+
core | `<ElseIf>` | No |
96+
core | `<Files>` | Yes |
97+
core | `<FilesMatch>` | Yes |
98+
core | `<If>` | No |
99+
core | `<IfDefine>` | Never | Impossible to be implemented. Apache specific
100+
core | `<IfDirective>` | Yes |
101+
core | `<IfFile>` | Yes |
102+
core | `<IfModule>` | Yes | Emulating supported modules according to supported directives
103+
core | `<IfSection>` | Yes |
104+
core | `<Limit>` | Yes |
105+
core | `<LimitExcept>` | Yes |
106+
mod_authz_core | `<RequireAll>` | No |
107+
mod_authz_core | `<RequireAny>` | No |
108+
mod_authz_core | `<RequireNone>` | No |
109+
mod_version | `<IfVersion>` | Yes | The version will be simulated as Apache 2.4.0
110+
111+
### Directives
112+
113+
Directives not listed below are not supported.
114+
115+
| Module | Directive | Supported | Notes |
116+
| ------ | --------- | --------- | ----- |
117+
core | `AcceptPathInfo` | No |
118+
core | `AddDefaultCharset` | No |
119+
core | `CGIMapExtension` | No |
120+
core | `CGIPassAuth` | No |
121+
core | `CGIVar` | No |
122+
core | `ContentDigest` | No |
123+
core | `DefaultType` | No |
124+
core | `EnableMMAP` | No |
125+
core | `EnableSendfile` | No |
126+
core | `ErrorDocument` | No |
127+
core | `FileETag` | No |
128+
core | `ForceType` | No |
129+
core | `LimitRequestBody` | No |
130+
core | `LimitXMLRequestBody` | No |
131+
core | `Options` | No |
132+
core | `QualifyRedirectURL` | No |
133+
core | `RLimitCPU` | Never | Rarely used and not practical for nginx
134+
core | `RLimitMEM` | Never | Rarely used and not practical for nginx
135+
core | `RLimitNPROC` | Never | Rarely used and not practical for nginx
136+
core | `ScriptInterpreterSource` | No |
137+
core | `ServerSignature` | No |
138+
core | `SetHandler` | No |
139+
core | `SetInputFilter` | No |
140+
core | `SetOutputFilter` | No |
141+
mod_access_compat | `Allow` | Yes | `Allow from domainname.tld` requires `getent` command line tool
142+
mod_access_compat | `Deny` | Yes | `Deny from domainname.tld` requires `getent` command line tool
143+
mod_access_compat | `Order` | Yes |
144+
mod_access_compat | `Satisfy` | Never | Security reasons. `Satisfy All` assumed
145+
mod_actions | `Action` | Never | Security reasons. CGI request handling must be in main host config
146+
mod_alias | `Redirect` | Yes |
147+
mod_alias | `RedirectMatch` | Yes |
148+
mod_alias | `RedirectPermanent` | Yes |
149+
mod_alias | `RedirectTemp` | Yes |
150+
mod_auth_basic | `AuthBasicAuthoritative` | No |
151+
mod_auth_basic | `AuthBasicFake` | No |
152+
mod_auth_basic | `AuthBasicProvider` | No |
153+
mod_auth_basic | `AuthBasicUseDigestAlgorithm` | No |
154+
mod_auth_digest | `*` | No |
155+
mod_auth_form | `*` | No |
156+
mod_authn_anon | `*` | No |
157+
mod_authn_core | `AuthName` | Yes |
158+
mod_authn_core | `AuthType` | Partially | Only `AuthType Basic` supported
159+
mod_authn_dbm | `*` | No |
160+
mod_authn_file | `AuthUserFile` | Yes |
161+
mod_authn_socache | `*` | No |
162+
mod_authnz_ldap | `*` | No |
163+
mod_authz_core | `AuthMerging` | No |
164+
mod_authz_core | `Require` | Partially | Require group, host, expr not supported
165+
mod_authz_dbm | `*` | No |
166+
mod_authz_groupfile | `*` | No |
167+
mod_autoindex | `AddAlt` | No |
168+
mod_autoindex | `AddAltByEncoding` | No |
169+
mod_autoindex | `AddAltByType` | No |
170+
mod_autoindex | `AddDescription` | No |
171+
mod_autoindex | `AddIcon` | No |
172+
mod_autoindex | `AddIconByEncoding` | No |
173+
mod_autoindex | `AddIconByType` | No |
174+
mod_autoindex | `DefaultIcon` | No |
175+
mod_autoindex | `HeaderName` | No |
176+
mod_autoindex | `IndexHeadInsert` | No |
177+
mod_autoindex | `IndexIgnore` | No |
178+
mod_autoindex | `IndexIgnoreReset` | No |
179+
mod_autoindex | `IndexOptions` | No |
180+
mod_autoindex | `IndexOrderDefault` | No |
181+
mod_autoindex | `IndexStyleSheet` | No |
182+
mod_autoindex | `ReadmeName` | No |
183+
mod_cern_meta | `*` | No | Rarely used
184+
mod_charset_lite | `CharsetDefault` | No |
185+
mod_charset_lite | `CharsetOptions` | No |
186+
mod_charset_lite | `CharsetSourceEnc` | No |
187+
mod_dir | `DirectoryCheckHandler` | No |
188+
mod_dir | `DirectoryIndex` | No |
189+
mod_dir | `DirectoryIndexRedirect` | No |
190+
mod_dir | `DirectorySlash` | No |
191+
mod_dir | `FallbackResource` | No |
192+
mod_env | `PassEnv` | No |
193+
mod_env | `SetEnv` | No |
194+
mod_env | `UnsetEnv` | No |
195+
mod_expires | `ExpiresActive` | No |
196+
mod_expires | `ExpiresByType` | No |
197+
mod_expires | `ExpiresDefault` | No |
198+
mod_filter | `AddOutputFilterByType` | No |
199+
mod_filter | `FilterChain` | No |
200+
mod_filter | `FilterDeclare` | No |
201+
mod_filter | `FilterProtocol` | No |
202+
mod_filter | `FilterProvider` | No |
203+
mod_headers | `Header` | No |
204+
mod_headers | `RequestHeader` | No |
205+
mod_imagemap | `*` | No |
206+
mod_include | `SSIErrorMsg` | No |
207+
mod_include | `SSITimeFormat` | No |
208+
mod_include | `SSIUndefinedEcho` | No |
209+
mod_include | `XBitHack` | No |
210+
mod_isapi | `*` | No |
211+
mod_ldap | `*` | No |
212+
mod_logio | `*` | No |
213+
mod_lua | `*` | No |
214+
mod_mime | `AddCharset` | No |
215+
mod_mime | `AddEncoding` | No |
216+
mod_mime | `AddHandler` | No |
217+
mod_mime | `AddInputFilter` | No |
218+
mod_mime | `AddLanguage` | No |
219+
mod_mime | `AddOutputFilter` | No |
220+
mod_mime | `AddType` | Yes |
221+
mod_mime | `DefaultLanguage` | No |
222+
mod_mime | `MultiviewsMatch` | No |
223+
mod_mime | `RemoveCharset` | No |
224+
mod_mime | `RemoveEncoding` | No |
225+
mod_mime | `RemoveHandler` | No |
226+
mod_mime | `RemoveInputFilter` | No |
227+
mod_mime | `RemoveLanguage` | No |
228+
mod_mime | `RemoveOutputFilter` | No |
229+
mod_mime | `RemoveType` | No |
230+
mod_negotiation | `ForceLanguagePriority` | No |
231+
mod_negotiation | `LanguagePriority` | No |
232+
mod_reflector | `*` | Never | Security reasons
233+
mod_rewrite | `RewriteBase` | Yes |
234+
mod_rewrite | `RewriteCond` | Yes |
235+
mod_rewrite | `RewriteEngine` | Yes |
236+
mod_rewrite | `RewriteOptions` | No |
237+
mod_rewrite | `RewriteRule` | Yes |
238+
mod_session | `*` | No |
239+
mod_setenvif | `BrowserMatch` | No |
240+
mod_setenvif | `BrowserMatchNoCase` | No |
241+
mod_setenvif | `SetEnvIf` | No |
242+
mod_setenvif | `SetEnvIfExpr` | No |
243+
mod_setenvif | `SetEnvIfNoCase` | No |
244+
mod_speling | `CheckCaseOnly` | No |
245+
mod_speling | `CheckSpelling` | No |
246+
mod_ssl | `SSLCipherSuite` | No |
247+
mod_ssl | `SSLOptions` | No |
248+
mod_ssl | `SSLRenegBufferSize` | No |
249+
mod_ssl | `SSLRequire` | No |
250+
mod_ssl | `SSLRequireSSL` | No |
251+
mod_ssl | `SSLUserName` | No |
252+
mod_ssl | `SSLVerifyClient` | No |
253+
mod_ssl | `SSLVerifyDepth` | No |
254+
mod_substitute | `Substitute` | No |
255+
mod_substitute | `SubstituteInheritBefore` | No |
256+
mod_substitute | `SubstituteMaxLineLength` | No |
257+
mod_usertrack | `CookieDomain` | No |
258+
mod_usertrack | `CookieExpires` | No |
259+
mod_usertrack | `CookieHTTPOnly` | No |
260+
mod_usertrack | `CookieName` | No |
261+
mod_usertrack | `CookieSameSite` | No |
262+
mod_usertrack | `CookieSecure` | No |
263+
mod_usertrack | `CookieStyle` | No |
264+
mod_usertrack | `CookieTracking` | No |
265+
266+
### Variables
267+
268+
Variables not listed below are not supported.
269+
270+
| Variable | Supported | Notes |
271+
| ------ | --------- | --------- | ----- |
272+
`HTTP_*` | Yes | all standard and non-standard HTTP header fields are supported
273+
`HTTPS` | Yes
274+
`DOCUMENT_ROOT` | Yes
275+
`SERVER_ADDR` | Yes
276+
`SERVER_NAME` | Yes
277+
`SERVER_PORT` | Yes
278+
`SERVER_PROTOCOL` | Yes
279+
`REMOTE_ADDR` | Yes
280+
`REMOTE_HOST` | Yes
281+
`REMOTE_USER` | Yes
282+
`REMOTE_PORT` | Yes
283+
`REQUEST_METHOD` | Yes
284+
`REQUEST_FILENAME` | Yes
285+
`REQUEST_URI` | Yes
286+
`QUERY_STRING` | Yes
287+
`SCRIPT_FILENAME` | Yes
288+
`REQUEST_SCHEME` | Yes
289+
`THE_REQUEST` | Yes
290+
`IPV6` | Yes
291+
`TIME` | Yes
292+
`TIME_YEAR` | Yes
293+
`TIME_MON` | Yes
294+
`TIME_DAY` | Yes
295+
`TIME_HOUR` | Yes
296+
`TIME_MIN` | Yes
297+
`TIME_SEC` | Yes
298+
`TIME_WDAY` | Yes
299+
300+
301+
## Tips
302+
303+
* This plugin tries to make things as secure as possible. **Wherever an unclear situation occurs, access will be denied** to prevent unintended access, e.g. if unsupported, security-critical directives are being used (HTTP 500 response). Unsupported, non-security-related directives will be ignored.
304+
* Global configuration within your `http {}` context is technically possible. However, you are encouraged to use this plugin only in the `server {}` contexts that will need it.
305+
* To make your life easier, you can create a config snippet and include it in the `server {}` config:
306+
```nginx
307+
server {
308+
...
309+
include snippets/htaccess.conf
310+
...
311+
}
312+
```
96313

97314
* * *
98315

0 commit comments

Comments
 (0)