Skip to content

Commit

Permalink
Merge pull request #251 from clue-labs/configs
Browse files Browse the repository at this point in the history
Update nginx + Apache configuration files to prevent access to internal files
  • Loading branch information
SimonFrings authored Mar 5, 2024
2 parents 544ef66 + 99d43a5 commit 4fbe9fe
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 14 deletions.
29 changes: 28 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,34 @@ jobs:
- run: docker logs $(docker ps -qn1)
if: ${{ always() }}

nginx-webserver:
nginx-reverse-proxy:
name: nginx (${{ matrix.config.name }})
runs-on: ubuntu-22.04
strategy:
matrix:
config:
- name: reverse proxy with files
path: nginx-reverse-proxy-public.conf
- name: minimal reverse proxy
path: nginx-reverse-proxy-minimal.conf
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: 8.3
- run: composer install -d tests/integration/
- run: docker build -f tests/integration/Dockerfile-basics tests/integration/
- run: docker run -d -p 8080:8080 -v "$PWD/composer.json":/app/composer.json $(docker images -q | head -n1)
- run: docker run -d --net=host -v "$PWD/tests/integration/":/home/framework-x/ -v "$PWD"/tests/integration/${{ matrix.config.path }}:/etc/nginx/conf.d/default.conf nginx:stable-alpine
- run: bash tests/await.sh http://localhost
- run: bash tests/integration.bash http://localhost
- run: docker stop $(docker ps -qn2)
- run: docker logs $(docker ps -qn1)
if: ${{ always() }}
- run: docker logs $(docker ps -qn2 | tail -n1)
if: ${{ always() }}

nginx-fpm:
name: nginx + PHP-FPM (PHP ${{ matrix.php }})
runs-on: ubuntu-22.04
strategy:
Expand Down
53 changes: 43 additions & 10 deletions docs/best-practices/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ server {
try_files $uri $uri/ /index.php$is_args$args;
}
# Optional: handle Apache config with Framework X if it exists in `public/`
error_page 403 = /index.php;
location ~ \.htaccess$ {
deny all;
}
location ~ \.php$ {
fastcgi_pass localhost:9000;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
Expand Down Expand Up @@ -186,6 +192,9 @@ RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php
# Optional: handle `.htaccess` with Framework X instead of `403 Forbidden`
ErrorDocument 403 /%{REQUEST_URI}/../index.php
# This adds support for authorization header
SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0
```
Expand Down Expand Up @@ -412,20 +421,44 @@ all you need to do is to point the nginx' [`root`](http://nginx.org/en/docs/http
to instruct nginx to process any dynamic requests through X. This can be
achieved by using an nginx configuration with the following contents:

```
server {
root /home/alice/projects/acme/public;
index index.php index.html;
=== "nginx.conf (reverse proxy with static files)"

location / {
try_files $uri $uri/ @x;
```
server {
# Serve static files from `public/`, proxy dynamic requests to Framework X
location / {
location ~* \.php$ {
try_files /dev/null @x;
}
root /home/alice/projects/acme/public;
try_files $uri @x;
}

location @x {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header Connection "";
}

# Optional: handle Apache config with Framework X if it exists in `public/`
location ~ \.htaccess$ {
try_files /dev/null @x;
}
}
```

location @x {
proxy_pass http://localhost:8080;
=== "nginx.conf (minimal reverse proxy)"

```
server {
# Proxy all requests to Framework X
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header Connection "";
}
}
}
```
```

> ℹ️ **New to nginx?**
>
Expand Down
10 changes: 7 additions & 3 deletions tests/integration.bash
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@ skipifnot() {
}

out=$(curl -v $base/ 2>&1); match "HTTP/.* 200" && match -iP "Content-Type: text/plain; charset=utf-8[\r\n]"
out=$(curl -v $base/invalid 2>&1); match "HTTP/.* 404" && match -iP "Content-Type: text/html; charset=utf-8[\r\n]"
out=$(curl -v $base// 2>&1); match "HTTP/.* 404"
out=$(curl -v $base/ 2>&1 -X POST); match "HTTP/.* 405"
out=$(curl -v $base/ 2>&1 -X POST); match "HTTP/.* 405" && match -iP "Content-Type: text/html; charset=utf-8[\r\n]"

out=$(curl -v $base/unknown 2>&1); match "HTTP/.* 404" && match -iP "Content-Type: text/html; charset=utf-8[\r\n]"
out=$(curl -v $base/index.php 2>&1); match "HTTP/.* 404" && match -iP "Content-Type: text/html; charset=utf-8[\r\n]"
out=$(curl -v $base/.htaccess 2>&1); match "HTTP/.* 404" && match -iP "Content-Type: text/html; charset=utf-8[\r\n]"
out=$(curl -v $base// 2>&1); match "HTTP/.* 404" && match -iP "Content-Type: text/html; charset=utf-8[\r\n]"

out=$(curl -v $base/error 2>&1); match "HTTP/.* 500" && match -iP "Content-Type: text/html; charset=utf-8[\r\n]" && match "<code>Unable to load error</code>"
out=$(curl -v $base/error/null 2>&1); match "HTTP/.* 500" && match -iP "Content-Type: text/html; charset=utf-8[\r\n]"

Expand Down
6 changes: 6 additions & 0 deletions tests/integration/nginx-fpm.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ server {
try_files $uri $uri/ /index.php$is_args$args;
}

# Optional: handle Apache config with Framework X if it exists in `public/`
error_page 403 = /index.php;
location ~ \.htaccess$ {
deny all;
}

location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
Expand Down
8 changes: 8 additions & 0 deletions tests/integration/nginx-reverse-proxy-minimal.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
server {
# Proxy all requests to Framework X
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header Connection "";
}
}
21 changes: 21 additions & 0 deletions tests/integration/nginx-reverse-proxy-public.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
server {
# Serve static files from `public/`, proxy dynamic requests to Framework X
location / {
location ~* \.php$ {
try_files /dev/null @x;
}
root /home/framework-x/public;
try_files $uri @x;
}

location @x {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header Connection "";
}

# Optional: handle Apache config with Framework X if it exists in `public/`
location ~ \.htaccess$ {
try_files /dev/null @x;
}
}
3 changes: 3 additions & 0 deletions tests/integration/public/.htaccess
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php

# Optional: handle `.htaccess` with Framework X instead of `403 Forbidden`
ErrorDocument 403 /%{REQUEST_URI}/../index.php

# This adds support for authorization header
SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0

0 comments on commit 4fbe9fe

Please sign in to comment.