kopia lustrzana https://0xacab.org/rysiek/fasada
initial import
commit
7fcc22f3c3
|
@ -0,0 +1,61 @@
|
|||
# Fasada - a front-end cache and reverse proxy config
|
||||
|
||||
A front-end cache and reverse proxy config, based on `nginx`, with Tor thrown in for good measure.
|
||||
|
||||
## Idea
|
||||
|
||||
The basic idea is to have a minimal front-end-cache config that can be spun-up (or indeed, that's just running) on a public server and is able to cache and serve a WordPress website effectively.
|
||||
|
||||
This includes strict caching of all content, even dynamic one, in a way that takes the load off of the PHP backend, and that is able to serve cached content for a long period of time in case of the backend not being available (due to maintenance or technical problems).
|
||||
|
||||
## Operation
|
||||
|
||||
Static resources (CSS, JS, images, etc) should be cached for long time (say, 24 hours or more); cookies on such static resources should be ignored.
|
||||
|
||||
Public dynamic resources should be cached for a short time (say, 1 minute), cookies should be ignored/removed.
|
||||
|
||||
Private dynamic content (admin pages, etc) should not be cached, at all. Ideally, they would be served from a dedicated domain (`admin.example.com`), which would not be cached, but would also be accessible only via a VPN or some such.
|
||||
|
||||
## Configuration
|
||||
|
||||
[Upstreams](http://nginx.org/en/docs/http/ngx_http_upstream_module.html) configuration should put in [`services/etc/nginx/conf.d/upstreams.conf`](services/etc/nginx/conf.d/upstreams.conf) file, so that tests can make use of them.
|
||||
|
||||
## Testing
|
||||
|
||||
Automated tests are provided, using [BATS](https://github.com/bats-core/bats-core/) (which is included as a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules)). When deploying Fasada remember to initialized and pull the submodule:
|
||||
|
||||
```
|
||||
git submodule init
|
||||
git submodule update
|
||||
```
|
||||
|
||||
Once that's done, tests are available via the `./tests/runtests.sh` command. Upon running it will:
|
||||
|
||||
1. use `./tests/gentests.sh` to generate upstream-specific tests
|
||||
1. run them on the host server
|
||||
1. run them via `docker-compose exec` in the `nginx` container
|
||||
|
||||
## Things to consider
|
||||
|
||||
**Q: How should we handle apparent `IP:port` clash between the upstream config and `fasada`? There are going to have to be two `nginx` services running on public ports, right?**
|
||||
**A**: Two ways to go around it:
|
||||
- run them on different IPs;
|
||||
- run them on different ports.
|
||||
|
||||
The `fasada` will have to run on public `IP` and ports `80` and `443`, no way around it. We're running `nginx` in a `docker` container, and while there is a way to tell `docker-compose` that a certain port should only be exposed on a certain IP, that would require specific configuration for specific hosts (that is, putting specific `IP` addresses in the `docker-compose.yml` file) - something we want to avoid.
|
||||
Hence the sane solution is to run `nginx` from `fasada` on ports `80` and `443`, and the `server-config` one on other ports (say, `10080` and `10443`).
|
||||
|
||||
**Q: Where should we handle setting cache control headers?**
|
||||
**A**: Apparently the right answer is: ["upstream"](https://serversforhackers.com/nginx-caching/).
|
||||
|
||||
# Wait, why nginx?
|
||||
|
||||
There are software solutions that are hand-crafted to be reverse proxies and front-end-cache solutions, why are we using `nginx`? Well...
|
||||
|
||||
Mainly: no time to play with other solutions and learn them, `nginx` does the job well enough.
|
||||
|
||||
But we did look at `varnish`, and we found [it does not support SSL and has no intention to](https://www.varnish-cache.org/docs/trunk/phk/ssl_again.html). We would have to run `nginx` *in front* of `varnish` that would then be *in front of* our upstream `nginx` servers. This is madness.
|
||||
|
||||
# ToDo
|
||||
|
||||
This needs to be documented better, both using comments in code, and using this README file, and the one in the `services/etc/nginx` subdirectory.
|
|
@ -0,0 +1,25 @@
|
|||
nginx:
|
||||
build: https://github.com/occrp/watchful-nginx.git
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- "./services/etc/nginx/:/etc/nginx/:ro" # config
|
||||
- "./tests/:/opt/tests/:ro" # tests
|
||||
- "/srv/data/secrets/nginx/:/etc/ssl/nginx/" # this is where dhparam goes; maybe we should use a data container for this
|
||||
- "/srv/data/cache/fasada/:/srv/data/cache/nginx" # cache; maybe we should use a data container for this?
|
||||
- "/srv/logs/fasada/:/srv/logs/nginx/" # logs
|
||||
# letsencrypt
|
||||
- "/srv/data/secrets/letsencrypt/archive/:/srv/data/secrets/letsencrypt/archive/:ro" # LetsEncrypt certificate store, containing all the certs ever issued
|
||||
- "/srv/data/secrets/letsencrypt/live/:/srv/data/secrets/letsencrypt/live/:ro" # LetsEncrypt live certificate store, containing symlinks to the most current certificates for a given domain
|
||||
|
||||
tor:
|
||||
image: vpetersson/torrelay
|
||||
user: debian-tor
|
||||
volumes:
|
||||
- "./services/etc/tor/:/etc/tor/:ro"
|
||||
- "/srv/data/secrets/tor/:/var/lib/tor/web/" # apparently tor has to have RW acess to this directory;
|
||||
# TODO make private_key read-only?
|
||||
links:
|
||||
- nginx
|
||||
command: ["/usr/sbin/tor", "-f", "/etc/tor/torrc"]
|
|
@ -0,0 +1,3 @@
|
|||
This is where we're working on building new Nginx config files for everything on this server.
|
||||
|
||||
ToDo: Document it better.
|
|
@ -0,0 +1,109 @@
|
|||
|
||||
# This map is not a full koi8-r <> utf8 map: it does not contain
|
||||
# box-drawing and some other characters. Besides this map contains
|
||||
# several koi8-u and Byelorussian letters which are not in koi8-r.
|
||||
# If you need a full and standard map, use contrib/unicode2nginx/koi-utf
|
||||
# map instead.
|
||||
|
||||
charset_map koi8-r utf-8 {
|
||||
|
||||
80 E282AC ; # euro
|
||||
|
||||
95 E280A2 ; # bullet
|
||||
|
||||
9A C2A0 ; #
|
||||
|
||||
9E C2B7 ; # ·
|
||||
|
||||
A3 D191 ; # small yo
|
||||
A4 D194 ; # small Ukrainian ye
|
||||
|
||||
A6 D196 ; # small Ukrainian i
|
||||
A7 D197 ; # small Ukrainian yi
|
||||
|
||||
AD D291 ; # small Ukrainian soft g
|
||||
AE D19E ; # small Byelorussian short u
|
||||
|
||||
B0 C2B0 ; # °
|
||||
|
||||
B3 D081 ; # capital YO
|
||||
B4 D084 ; # capital Ukrainian YE
|
||||
|
||||
B6 D086 ; # capital Ukrainian I
|
||||
B7 D087 ; # capital Ukrainian YI
|
||||
|
||||
B9 E28496 ; # numero sign
|
||||
|
||||
BD D290 ; # capital Ukrainian soft G
|
||||
BE D18E ; # capital Byelorussian short U
|
||||
|
||||
BF C2A9 ; # (C)
|
||||
|
||||
C0 D18E ; # small yu
|
||||
C1 D0B0 ; # small a
|
||||
C2 D0B1 ; # small b
|
||||
C3 D186 ; # small ts
|
||||
C4 D0B4 ; # small d
|
||||
C5 D0B5 ; # small ye
|
||||
C6 D184 ; # small f
|
||||
C7 D0B3 ; # small g
|
||||
C8 D185 ; # small kh
|
||||
C9 D0B8 ; # small i
|
||||
CA D0B9 ; # small j
|
||||
CB D0BA ; # small k
|
||||
CC D0BB ; # small l
|
||||
CD D0BC ; # small m
|
||||
CE D0BD ; # small n
|
||||
CF D0BE ; # small o
|
||||
|
||||
D0 D0BF ; # small p
|
||||
D1 D18F ; # small ya
|
||||
D2 D180 ; # small r
|
||||
D3 D181 ; # small s
|
||||
D4 D182 ; # small t
|
||||
D5 D183 ; # small u
|
||||
D6 D0B6 ; # small zh
|
||||
D7 D0B2 ; # small v
|
||||
D8 D18C ; # small soft sign
|
||||
D9 D18B ; # small y
|
||||
DA D0B7 ; # small z
|
||||
DB D188 ; # small sh
|
||||
DC D18D ; # small e
|
||||
DD D189 ; # small shch
|
||||
DE D187 ; # small ch
|
||||
DF D18A ; # small hard sign
|
||||
|
||||
E0 D0AE ; # capital YU
|
||||
E1 D090 ; # capital A
|
||||
E2 D091 ; # capital B
|
||||
E3 D0A6 ; # capital TS
|
||||
E4 D094 ; # capital D
|
||||
E5 D095 ; # capital YE
|
||||
E6 D0A4 ; # capital F
|
||||
E7 D093 ; # capital G
|
||||
E8 D0A5 ; # capital KH
|
||||
E9 D098 ; # capital I
|
||||
EA D099 ; # capital J
|
||||
EB D09A ; # capital K
|
||||
EC D09B ; # capital L
|
||||
ED D09C ; # capital M
|
||||
EE D09D ; # capital N
|
||||
EF D09E ; # capital O
|
||||
|
||||
F0 D09F ; # capital P
|
||||
F1 D0AF ; # capital YA
|
||||
F2 D0A0 ; # capital R
|
||||
F3 D0A1 ; # capital S
|
||||
F4 D0A2 ; # capital T
|
||||
F5 D0A3 ; # capital U
|
||||
F6 D096 ; # capital ZH
|
||||
F7 D092 ; # capital V
|
||||
F8 D0AC ; # capital soft sign
|
||||
F9 D0AB ; # capital Y
|
||||
FA D097 ; # capital Z
|
||||
FB D0A8 ; # capital SH
|
||||
FC D0AD ; # capital E
|
||||
FD D0A9 ; # capital SHCH
|
||||
FE D0A7 ; # capital CH
|
||||
FF D0AA ; # capital hard sign
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
|
||||
charset_map koi8-r windows-1251 {
|
||||
|
||||
80 88 ; # euro
|
||||
|
||||
95 95 ; # bullet
|
||||
|
||||
9A A0 ; #
|
||||
|
||||
9E B7 ; # ·
|
||||
|
||||
A3 B8 ; # small yo
|
||||
A4 BA ; # small Ukrainian ye
|
||||
|
||||
A6 B3 ; # small Ukrainian i
|
||||
A7 BF ; # small Ukrainian yi
|
||||
|
||||
AD B4 ; # small Ukrainian soft g
|
||||
AE A2 ; # small Byelorussian short u
|
||||
|
||||
B0 B0 ; # °
|
||||
|
||||
B3 A8 ; # capital YO
|
||||
B4 AA ; # capital Ukrainian YE
|
||||
|
||||
B6 B2 ; # capital Ukrainian I
|
||||
B7 AF ; # capital Ukrainian YI
|
||||
|
||||
B9 B9 ; # numero sign
|
||||
|
||||
BD A5 ; # capital Ukrainian soft G
|
||||
BE A1 ; # capital Byelorussian short U
|
||||
|
||||
BF A9 ; # (C)
|
||||
|
||||
C0 FE ; # small yu
|
||||
C1 E0 ; # small a
|
||||
C2 E1 ; # small b
|
||||
C3 F6 ; # small ts
|
||||
C4 E4 ; # small d
|
||||
C5 E5 ; # small ye
|
||||
C6 F4 ; # small f
|
||||
C7 E3 ; # small g
|
||||
C8 F5 ; # small kh
|
||||
C9 E8 ; # small i
|
||||
CA E9 ; # small j
|
||||
CB EA ; # small k
|
||||
CC EB ; # small l
|
||||
CD EC ; # small m
|
||||
CE ED ; # small n
|
||||
CF EE ; # small o
|
||||
|
||||
D0 EF ; # small p
|
||||
D1 FF ; # small ya
|
||||
D2 F0 ; # small r
|
||||
D3 F1 ; # small s
|
||||
D4 F2 ; # small t
|
||||
D5 F3 ; # small u
|
||||
D6 E6 ; # small zh
|
||||
D7 E2 ; # small v
|
||||
D8 FC ; # small soft sign
|
||||
D9 FB ; # small y
|
||||
DA E7 ; # small z
|
||||
DB F8 ; # small sh
|
||||
DC FD ; # small e
|
||||
DD F9 ; # small shch
|
||||
DE F7 ; # small ch
|
||||
DF FA ; # small hard sign
|
||||
|
||||
E0 DE ; # capital YU
|
||||
E1 C0 ; # capital A
|
||||
E2 C1 ; # capital B
|
||||
E3 D6 ; # capital TS
|
||||
E4 C4 ; # capital D
|
||||
E5 C5 ; # capital YE
|
||||
E6 D4 ; # capital F
|
||||
E7 C3 ; # capital G
|
||||
E8 D5 ; # capital KH
|
||||
E9 C8 ; # capital I
|
||||
EA C9 ; # capital J
|
||||
EB CA ; # capital K
|
||||
EC CB ; # capital L
|
||||
ED CC ; # capital M
|
||||
EE CD ; # capital N
|
||||
EF CE ; # capital O
|
||||
|
||||
F0 CF ; # capital P
|
||||
F1 DF ; # capital YA
|
||||
F2 D0 ; # capital R
|
||||
F3 D1 ; # capital S
|
||||
F4 D2 ; # capital T
|
||||
F5 D3 ; # capital U
|
||||
F6 C6 ; # capital ZH
|
||||
F7 C2 ; # capital V
|
||||
F8 DC ; # capital soft sign
|
||||
F9 DB ; # capital Y
|
||||
FA C7 ; # capital Z
|
||||
FB D8 ; # capital SH
|
||||
FC DD ; # capital E
|
||||
FD D9 ; # capital SHCH
|
||||
FE D7 ; # capital CH
|
||||
FF DA ; # capital hard sign
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
types {
|
||||
text/html html htm shtml;
|
||||
text/css css;
|
||||
text/xml xml;
|
||||
image/gif gif;
|
||||
image/jpeg jpeg jpg;
|
||||
application/javascript js;
|
||||
application/atom+xml atom;
|
||||
application/rss+xml rss;
|
||||
|
||||
text/mathml mml;
|
||||
text/plain txt;
|
||||
text/vnd.sun.j2me.app-descriptor jad;
|
||||
text/vnd.wap.wml wml;
|
||||
text/x-component htc;
|
||||
|
||||
image/png png;
|
||||
image/tiff tif tiff;
|
||||
image/vnd.wap.wbmp wbmp;
|
||||
image/x-icon ico;
|
||||
image/x-jng jng;
|
||||
image/x-ms-bmp bmp;
|
||||
image/svg+xml svg svgz;
|
||||
image/webp webp;
|
||||
|
||||
application/font-woff woff;
|
||||
application/java-archive jar war ear;
|
||||
application/json json;
|
||||
application/mac-binhex40 hqx;
|
||||
application/msword doc;
|
||||
application/pdf pdf;
|
||||
application/postscript ps eps ai;
|
||||
application/rtf rtf;
|
||||
application/vnd.apple.mpegurl m3u8;
|
||||
application/vnd.ms-excel xls;
|
||||
application/vnd.ms-fontobject eot;
|
||||
application/vnd.ms-powerpoint ppt;
|
||||
application/vnd.wap.wmlc wmlc;
|
||||
application/vnd.google-earth.kml+xml kml;
|
||||
application/vnd.google-earth.kmz kmz;
|
||||
application/x-7z-compressed 7z;
|
||||
application/x-cocoa cco;
|
||||
application/x-java-archive-diff jardiff;
|
||||
application/x-java-jnlp-file jnlp;
|
||||
application/x-makeself run;
|
||||
application/x-perl pl pm;
|
||||
application/x-pilot prc pdb;
|
||||
application/x-rar-compressed rar;
|
||||
application/x-redhat-package-manager rpm;
|
||||
application/x-sea sea;
|
||||
application/x-shockwave-flash swf;
|
||||
application/x-stuffit sit;
|
||||
application/x-tcl tcl tk;
|
||||
application/x-x509-ca-cert der pem crt;
|
||||
application/x-xpinstall xpi;
|
||||
application/xhtml+xml xhtml;
|
||||
application/xspf+xml xspf;
|
||||
application/zip zip;
|
||||
|
||||
application/octet-stream bin exe dll;
|
||||
application/octet-stream deb;
|
||||
application/octet-stream dmg;
|
||||
application/octet-stream iso img;
|
||||
application/octet-stream msi msp msm;
|
||||
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx;
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx;
|
||||
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx;
|
||||
|
||||
audio/midi mid midi kar;
|
||||
audio/mpeg mp3;
|
||||
audio/ogg ogg;
|
||||
audio/x-m4a m4a;
|
||||
audio/x-realaudio ra;
|
||||
|
||||
video/3gpp 3gpp 3gp;
|
||||
video/mp2t ts;
|
||||
video/mp4 mp4;
|
||||
video/mpeg mpeg mpg;
|
||||
video/quicktime mov;
|
||||
video/webm webm;
|
||||
video/x-flv flv;
|
||||
video/x-m4v m4v;
|
||||
video/x-mng mng;
|
||||
video/x-ms-asf asx asf;
|
||||
video/x-ms-wmv wmv;
|
||||
video/x-msvideo avi;
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
|
||||
user www-data www-data;
|
||||
|
||||
worker_processes 8;
|
||||
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 768;
|
||||
multi_accept on;
|
||||
use epoll;
|
||||
}
|
||||
|
||||
http {
|
||||
##
|
||||
# Basic Settings
|
||||
##
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
types_hash_max_size 2048;
|
||||
server_tokens off;
|
||||
|
||||
server_names_hash_max_size 2048;
|
||||
server_names_hash_bucket_size 64;
|
||||
# server_name_in_redirect off;
|
||||
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# default charset
|
||||
charset utf-8;
|
||||
|
||||
##
|
||||
# Some of SSL settings are in snippets/ssl.conf
|
||||
# included in all ssl-enabled hosts
|
||||
##
|
||||
|
||||
# Mozilla SSL Intermediate profile
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
# cache SSL sessions for 10m (this is about 40,000 sessions), timing them out
|
||||
# after 24 hours.
|
||||
# https://sethvargo.com/getting-an-a-plus-on-qualys-ssl-labs-tester/
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 24h;
|
||||
|
||||
# set the buffer size to 1400 bytes (that way it fits into a single MTU).
|
||||
ssl_buffer_size 1400;
|
||||
|
||||
# this is generated in docker/nginx/run.sh
|
||||
ssl_dhparam '/etc/ssl/nginx/dhparam.pem';
|
||||
|
||||
##
|
||||
# Default Logging Settings
|
||||
##
|
||||
|
||||
access_log /srv/logs/nginx/access.log combined;
|
||||
error_log /srv/logs/nginx/error.log;
|
||||
|
||||
######################################################################
|
||||
## Various configuration sections: ##
|
||||
######################################################################
|
||||
|
||||
##
|
||||
# Gzip Settings
|
||||
##
|
||||
|
||||
gzip on;
|
||||
gzip_disable "msie6";
|
||||
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;
|
||||
|
||||
|
||||
##
|
||||
# Size Limits & Buffer Overflows
|
||||
##
|
||||
|
||||
#client_header_buffer_size 1k;
|
||||
client_max_body_size 20m;
|
||||
client_body_buffer_size 1m;
|
||||
#large_client_header_buffers 2 1k;
|
||||
|
||||
##
|
||||
# Start: Timeouts
|
||||
##
|
||||
client_body_timeout 10;
|
||||
client_header_timeout 10;
|
||||
keepalive_timeout 5 5;
|
||||
send_timeout 10;
|
||||
|
||||
# Directive describes the zone, in which the session states are stored i.e. store in slimits.
|
||||
# 1m can handle 32000 sessions with 32 bytes/session, set to 5m x 32000 session
|
||||
# limit_conn_zone $binary_remote_addr zone=slimits:5m;
|
||||
|
||||
# Control maximum number of simultaneous connections for one session i.e.
|
||||
# restricts the amount of connections from a single ip address
|
||||
# limit_conn slimits 5;
|
||||
|
||||
|
||||
#
|
||||
# rate limiting
|
||||
# https://www.nginx.com/blog/rate-limiting-nginx/
|
||||
# https://nginx.org/en/docs/http/ngx_http_limit_req_module.html
|
||||
#
|
||||
# just add "limit_req zone=ddosed burst=100;" in any location
|
||||
# that is supposed to be rate-limited
|
||||
limit_req_zone $binary_remote_addr zone=ddosed:20m rate=10r/s;
|
||||
|
||||
##
|
||||
# Proxy cache settings
|
||||
##
|
||||
|
||||
# keys_zone=fasada:10m - how long the cache is considered fresh
|
||||
# max_size=3G - we're fine with large cache size on disk
|
||||
# inactive=12h - stale cached content is retained in cache for 12h at least
|
||||
# this is necessary if we want to be able to serve stale content
|
||||
# in case of errors longer than the time the cache is considered "fresh"
|
||||
# which we do -- this gives us the ability to survive a backend crash
|
||||
# with most users not noticing
|
||||
proxy_cache_path /srv/data/cache/nginx/proxy/ levels=1:2 keys_zone=fasada:10m max_size=3G inactive=12h;
|
||||
|
||||
#
|
||||
# A cached response is first written to a temporary file, and then the file is renamed.
|
||||
# Starting from version 0.8.9, temporary files and the cache can be put on different file systems.
|
||||
# However, be aware that in this case a file is copied across two file systems instead of
|
||||
# the cheap renaming operation. It is thus recommended that for any given location both
|
||||
# cache and a directory holding temporary files are put on the same file system. The directory
|
||||
# for temporary files is set based on the use_temp_path parameter (1.7.10).
|
||||
#
|
||||
proxy_temp_path /srv/data/cache/nginx/tmp/ 1 2;
|
||||
|
||||
# no fastcgi around
|
||||
#fastcgi_cache_path /srv/data/cache/nginx/fastcgi/ levels=1:2 keys_zone=fastcgicache:100m max_size=5G;
|
||||
|
||||
proxy_cache_key $scheme:$request_method:$host/$uri$is_args$args;
|
||||
# no fastcgi around
|
||||
#fastcgi_cache_key "$proxy_host|$request_method|$scheme|$host|$request_uri|$is_args|$args|$cookie_user|$cookie_phpsessid";
|
||||
|
||||
# by default, bypass the cache when:
|
||||
# - Pragma: no-cache is present
|
||||
# - any cookie is present
|
||||
proxy_cache_bypass $http_pragma $http_cookie;
|
||||
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
proxy_intercept_errors on;
|
||||
proxy_buffering on;
|
||||
proxy_buffer_size 128k;
|
||||
proxy_buffers 256 16k;
|
||||
proxy_busy_buffers_size 256k;
|
||||
proxy_temp_file_write_size 256k;
|
||||
proxy_max_temp_file_size 0;
|
||||
|
||||
# Defines a timeout for establishing a connection with a proxied server.
|
||||
# It should be noted that this timeout cannot usually exceed 75 seconds.
|
||||
proxy_connect_timeout 2;
|
||||
|
||||
# Sets a timeout for transmitting a request to the proxied server.
|
||||
# The timeout is set only between two successive write operations,
|
||||
# not for the transmission of the whole request.
|
||||
# If the proxied server does not receive anything within this time,
|
||||
# the connection is closed.
|
||||
proxy_send_timeout 120;
|
||||
|
||||
# Defines a timeout for reading a response from the proxied server.
|
||||
# The timeout is set only between two successive read operations,
|
||||
# not for the transmission of the whole response.
|
||||
# If the proxied server does not transmit anything within this time,
|
||||
# the connection is closed.
|
||||
proxy_read_timeout 5;
|
||||
|
||||
|
||||
##
|
||||
# Virtual Host Configs
|
||||
##
|
||||
|
||||
include sites/*.conf;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
# require TLS, redirect to https://www.example.com/
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen 443 ssl default_server;
|
||||
server_name _;
|
||||
|
||||
# tls letsencrypt stateless acme config
|
||||
# no need for webroot and stuff
|
||||
#
|
||||
# this is described for acme.sh,
|
||||
# but should work with any LE client
|
||||
# https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode
|
||||
location ~ "^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)$" {
|
||||
default_type text/plain;
|
||||
return 200 "$1.<ACME_THUMBPRINT>";
|
||||
}
|
||||
|
||||
|
||||
# ssl keycert
|
||||
ssl_certificate /srv/data/ssl/sites/www.example.com.cert;
|
||||
ssl_certificate_key /srv/data/ssl/sites/www.example.com.key;
|
||||
|
||||
location / {
|
||||
return 301 https://www.example.com/;
|
||||
}
|
||||
access_log /srv/logs/nginx/catchall.access.log combined;
|
||||
error_log /srv/logs/nginx/catchall.error.log error;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
# www.example.com website
|
||||
server {
|
||||
listen 80;
|
||||
listen 443 ssl;
|
||||
server_name admin.example.com;
|
||||
|
||||
# general vhost settings
|
||||
access_log /srv/logs/nginx/admin.example.com.access.log combined;
|
||||
error_log /srv/logs/nginx/admin.example.com.error.log error;
|
||||
|
||||
# ssl keycert
|
||||
ssl_certificate /srv/data/secrets/letsencrypt/live/admin.example.com/fullchain.pem;
|
||||
ssl_certificate_key /srv/data/secrets/letsencrypt/live/admin.example.com/privkey.pem;
|
||||
|
||||
# TLS settings
|
||||
# can't set headers in an if that is *not* in a location,
|
||||
# so we need to work around this
|
||||
add_header Strict-Transport-Security "max-age=31536000";
|
||||
|
||||
# proxy params, mainly for properly tracking visitors
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# needed for keepalive to work
|
||||
proxy_set_header Connection "";
|
||||
proxy_http_version 1.1;
|
||||
|
||||
# tls letsencrypt stateless acme config
|
||||
# no need for webroot and stuff
|
||||
#
|
||||
# this is described for acme.sh,
|
||||
# but should work with any LE client
|
||||
# https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode
|
||||
location ~ "^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)$" {
|
||||
default_type text/plain;
|
||||
return 200 "$1.<ACME_THUMBPRINT>";
|
||||
}
|
||||
|
||||
# set proxy zone
|
||||
proxy_cache off;
|
||||
|
||||
# reverse proxy to upstream
|
||||
location / {
|
||||
# debugging
|
||||
add_header X-Proxy-Cache $upstream_cache_status;
|
||||
#include snippets/security.conf;
|
||||
proxy_pass http://127.0.0.1:10080;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
# www.example.com website
|
||||
server {
|
||||
listen 80;
|
||||
listen 443 ssl;
|
||||
server_name www.example.com example.com;
|
||||
|
||||
# general vhost settings
|
||||
access_log /srv/logs/nginx/example.com.access.log combined;
|
||||
error_log /srv/logs/nginx/example.com.error.log error;
|
||||
|
||||
# ssl keycert
|
||||
ssl_certificate /srv/data/secrets/letsencrypt/live/example.com/fullchain.pem;
|
||||
ssl_certificate_key /srv/data/secrets/letsencrypt/live/example.com/privkey.pem;
|
||||
|
||||
# TLS settings
|
||||
# can't set headers in an if that is *not* in a location,
|
||||
# so we need to work around this
|
||||
add_header Strict-Transport-Security "max-age=31536000";
|
||||
|
||||
# TLS letsencrypt stateless acme config
|
||||
# no need for webroot and stuff
|
||||
#
|
||||
# this is described for acme.sh,
|
||||
# but should work with any LE client
|
||||
# https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode
|
||||
location ~ "^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)$" {
|
||||
default_type text/plain;
|
||||
return 200 "$1.<ACME_THUMBPRINT>";
|
||||
}
|
||||
|
||||
# proxy params, mainly for properly tracking visitors
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# needed for keepalive to work
|
||||
proxy_set_header Connection "";
|
||||
proxy_http_version 1.1;
|
||||
|
||||
# proxy zone
|
||||
proxy_cache fasada;
|
||||
# use stale cached resources in case upstream is not available for some reason
|
||||
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
|
||||
proxy_cache_background_update on;
|
||||
proxy_cache_revalidate on;
|
||||
proxy_cache_valid 200 1h;
|
||||
proxy_cache_lock on;
|
||||
|
||||
|
||||
# admin area *have to* be uncached; blocking here
|
||||
# should be made available on admin.domain.tld
|
||||
location ~* ^/(wp-admin|admin|login|wp-login|signin).* {
|
||||
add_header X-Proxy-Cache $upstream_cache_status;
|
||||
return 403;
|
||||
}
|
||||
|
||||
# WordPress themes
|
||||
location ~* ^/wp-content/themes/.* {
|
||||
|
||||
# forced cache
|
||||
proxy_cache_bypass 0;
|
||||
proxy_hide_header Set-Cookie;
|
||||
proxy_hide_header Expires;
|
||||
proxy_hide_header Cache-Control;
|
||||
proxy_hide_header Pragma;
|
||||
proxy_ignore_headers Set-Cookie Expires Cache-Control;
|
||||
add_header Cache-Control "public";
|
||||
expires 30m;
|
||||
add_header X-Proxy-Cache-WP themes;
|
||||
|
||||
# debugging
|
||||
add_header X-Proxy-Cache $upstream_cache_status;
|
||||
|
||||
# no need for access log for these
|
||||
access_log off;
|
||||
proxy_pass http://127.0.0.1:10080;
|
||||
|
||||
}
|
||||
|
||||
# robots.txt, favicons, apple icons, etc
|
||||
location ~* .*/(robots\.txt|favicon\.ico|apple-touch-icon\.png|apple-touch-icon-precomposed\.png)$ {
|
||||
|
||||
# forced cache
|
||||
proxy_cache_bypass 0;
|
||||
add_header Cache-Control "public";
|
||||
proxy_cache_valid 200 301 302 303 307 308 5h;
|
||||
expires 5h;
|
||||
|
||||
# debugging
|
||||
add_header X-Proxy-Cache $upstream_cache_status;
|
||||
|
||||
# no need for access log for these
|
||||
access_log off;
|
||||
proxy_pass http://127.0.0.1:10080;
|
||||
}
|
||||
|
||||
# images and other static resources
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|json|woff|woff2|ttf|otf|bmp|cur|gz|svgz|mp4|ogg|ogv|webm|htc|mp4|mpeg|mp3|txt|pdf)$ {
|
||||
|
||||
# forced cache
|
||||
proxy_cache_bypass 0;
|
||||
add_header Cache-Control "public";
|
||||
proxy_cache_valid 200 301 302 303 307 308 1h;
|
||||
expires 1h;
|
||||
|
||||
add_header X-Proxy-Cache $upstream_cache_status;
|
||||
|
||||
proxy_pass http://127.0.0.1:10080;
|
||||
}
|
||||
|
||||
# reverse proxy to upstream, for *everything else*
|
||||
# caching for 1 minute
|
||||
location / {
|
||||
# forced cache
|
||||
proxy_cache_bypass 0;
|
||||
proxy_hide_header Set-Cookie;
|
||||
proxy_hide_header Expires;
|
||||
proxy_hide_header Cache-Control;
|
||||
proxy_hide_header Pragma;
|
||||
proxy_ignore_headers Set-Cookie Expires Cache-Control X-Accel-Expires;
|
||||
add_header Cache-Control "no-store";
|
||||
proxy_cache_valid 200 301 302 303 307 308 20s;
|
||||
add_header X-Proxy-Cache $upstream_cache_status;
|
||||
add_header Content-Security-Policy "frame-ancestors 'self'";
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
proxy_pass http://127.0.0.1:10080;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
# This map is not a full windows-1251 <> utf8 map: it does not
|
||||
# contain Serbian and Macedonian letters. If you need a full map,
|
||||
# use contrib/unicode2nginx/win-utf map instead.
|
||||
|
||||
charset_map windows-1251 utf-8 {
|
||||
|
||||
82 E2809A; # single low-9 quotation mark
|
||||
|
||||
84 E2809E; # double low-9 quotation mark
|
||||
85 E280A6; # ellipsis
|
||||
86 E280A0; # dagger
|
||||
87 E280A1; # double dagger
|
||||
88 E282AC; # euro
|
||||
89 E280B0; # per mille
|
||||
|
||||
91 E28098; # left single quotation mark
|
||||
92 E28099; # right single quotation mark
|
||||
93 E2809C; # left double quotation mark
|
||||
94 E2809D; # right double quotation mark
|
||||
95 E280A2; # bullet
|
||||
96 E28093; # en dash
|
||||
97 E28094; # em dash
|
||||
|
||||
99 E284A2; # trade mark sign
|
||||
|
||||
A0 C2A0; #
|
||||
A1 D18E; # capital Byelorussian short U
|
||||
A2 D19E; # small Byelorussian short u
|
||||
|
||||
A4 C2A4; # currency sign
|
||||
A5 D290; # capital Ukrainian soft G
|
||||
A6 C2A6; # borken bar
|
||||
A7 C2A7; # section sign
|
||||
A8 D081; # capital YO
|
||||
A9 C2A9; # (C)
|
||||
AA D084; # capital Ukrainian YE
|
||||
AB C2AB; # left-pointing double angle quotation mark
|
||||
AC C2AC; # not sign
|
||||
AD C2AD; # soft hypen
|
||||
AE C2AE; # (R)
|
||||
AF D087; # capital Ukrainian YI
|
||||
|
||||
B0 C2B0; # °
|
||||
B1 C2B1; # plus-minus sign
|
||||
B2 D086; # capital Ukrainian I
|
||||
B3 D196; # small Ukrainian i
|
||||
B4 D291; # small Ukrainian soft g
|
||||
B5 C2B5; # micro sign
|
||||
B6 C2B6; # pilcrow sign
|
||||
B7 C2B7; # ·
|
||||
B8 D191; # small yo
|
||||
B9 E28496; # numero sign
|
||||
BA D194; # small Ukrainian ye
|
||||
BB C2BB; # right-pointing double angle quotation mark
|
||||
|
||||
BF D197; # small Ukrainian yi
|
||||
|
||||
C0 D090; # capital A
|
||||
C1 D091; # capital B
|
||||
C2 D092; # capital V
|
||||
C3 D093; # capital G
|
||||
C4 D094; # capital D
|
||||
C5 D095; # capital YE
|
||||
C6 D096; # capital ZH
|
||||
C7 D097; # capital Z
|
||||
C8 D098; # capital I
|
||||
C9 D099; # capital J
|
||||
CA D09A; # capital K
|
||||
CB D09B; # capital L
|
||||
CC D09C; # capital M
|
||||
CD D09D; # capital N
|
||||
CE D09E; # capital O
|
||||
CF D09F; # capital P
|
||||
|
||||
D0 D0A0; # capital R
|
||||
D1 D0A1; # capital S
|
||||
D2 D0A2; # capital T
|
||||
D3 D0A3; # capital U
|
||||
D4 D0A4; # capital F
|
||||
D5 D0A5; # capital KH
|
||||
D6 D0A6; # capital TS
|
||||
D7 D0A7; # capital CH
|
||||
D8 D0A8; # capital SH
|
||||
D9 D0A9; # capital SHCH
|
||||
DA D0AA; # capital hard sign
|
||||
DB D0AB; # capital Y
|
||||
DC D0AC; # capital soft sign
|
||||
DD D0AD; # capital E
|
||||
DE D0AE; # capital YU
|
||||
DF D0AF; # capital YA
|
||||
|
||||
E0 D0B0; # small a
|
||||
E1 D0B1; # small b
|
||||
E2 D0B2; # small v
|
||||
E3 D0B3; # small g
|
||||
E4 D0B4; # small d
|
||||
E5 D0B5; # small ye
|
||||
E6 D0B6; # small zh
|
||||
E7 D0B7; # small z
|
||||
E8 D0B8; # small i
|
||||
E9 D0B9; # small j
|
||||
EA D0BA; # small k
|
||||
EB D0BB; # small l
|
||||
EC D0BC; # small m
|
||||
ED D0BD; # small n
|
||||
EE D0BE; # small o
|
||||
EF D0BF; # small p
|
||||
|
||||
F0 D180; # small r
|
||||
F1 D181; # small s
|
||||
F2 D182; # small t
|
||||
F3 D183; # small u
|
||||
F4 D184; # small f
|
||||
F5 D185; # small kh
|
||||
F6 D186; # small ts
|
||||
F7 D187; # small ch
|
||||
F8 D188; # small sh
|
||||
F9 D189; # small shch
|
||||
FA D18A; # small hard sign
|
||||
FB D18B; # small y
|
||||
FC D18C; # small soft sign
|
||||
FD D18D; # small e
|
||||
FE D18E; # small yu
|
||||
FF D18F; # small ya
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
ORPort 0
|
||||
SocksPort 0
|
||||
SocksPolicy reject *
|
||||
RunAsDaemon 0
|
||||
DataDirectory /var/lib/tor/
|
||||
Exitpolicy reject *:*
|
||||
Nickname ExampleName
|
||||
ContactInfo The Webmaster <webmaster@example.com>
|
||||
|
||||
HiddenServiceDir /var/lib/tor/web/
|
||||
HiddenServicePort 80 nginx:80
|
|
@ -0,0 +1 @@
|
|||
001-upstreams.bats
|
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# basic networking tests
|
||||
# a reality check, of sorts
|
||||
#
|
||||
|
||||
@test "[$HOSTNAME][general] networking: is the outside world accessible via IPv4?" {
|
||||
run ping -c 2 -w 3 8.8.8.8
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "[$HOSTNAME][general] networking: is the outside world accessible via IPv6?" {
|
||||
run ping6 -c 2 -w 3 ipv6.google.com
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
#!/bin/bash
|
||||
|
||||
#
|
||||
# generating relevant tests
|
||||
#
|
||||
# $1 -- path of the upstreams.conf file to use
|
||||
|
||||
#
|
||||
# first, upstream-related tests
|
||||
#
|
||||
|
||||
FASADA_TESTS_DIR="$( dirname "$BASH_SOURCE" )"
|
||||
FASADA_TESTS_UPSTREAMS_FILE="$FASADA_TESTS_DIR/001-upstreams.bats"
|
||||
|
||||
# clear the playing field
|
||||
echo > "$FASADA_TESTS_UPSTREAMS_FILE"
|
||||
|
||||
# do we have *any* upstreams configured?
|
||||
cat <<EOF >> "$FASADA_TESTS_UPSTREAMS_FILE"
|
||||
@test "[\$HOSTNAME][upstreams] any upstreams configured?" {
|
||||
[ $( awk '/^upstream/,/^}/' "$1" | egrep '^\s+server' | sed -r -e 's/^\s*server\s([][a-f0-9\.\:]+)(;|\s+.+)/\1/g' | wc -l ) != 0 ]
|
||||
}
|
||||
EOF
|
||||
|
||||
# ok, let's go through hte upstreams
|
||||
# and generate tests per-upstream
|
||||
for upstream in $( awk '/^upstream/,/^}/' "$1" | egrep '^\s+server' | sed -r -e 's/^\s*server\s([][a-f0-9\.\:]+)(;|\s+.+)/\1/g' ); do
|
||||
|
||||
# NOTICE: this will also handle regular domain names... not sure if that's what we want
|
||||
if [[ "$upstream" = *'.'* ]]; then
|
||||
# IPv4
|
||||
BATS_RUN="run ping -c 2 -w 3 '${upstream%:*}'"
|
||||
else
|
||||
# IPv6
|
||||
BATS_RUN="run ping6 -c 2 -w 3 '$( echo -n ${upstream%]*} | tr -d '[]' )'"
|
||||
fi
|
||||
|
||||
cat <<EOF >> "$FASADA_TESTS_UPSTREAMS_FILE"
|
||||
# pinging the upstream but *without* the port, obviously
|
||||
@test "[\$HOSTNAME][upstreams] testing upstream: $upstream - accessible via ping?" {
|
||||
$BATS_RUN
|
||||
[ "\$status" -eq 0 ]
|
||||
}
|
||||
EOF
|
||||
|
||||
# checking TCP connectivity
|
||||
# yes we're using bash built-in /dev/tcp for this to not rely on things like curl or wget
|
||||
# relevant: https://www.linuxjournal.com/content/more-using-bashs-built-devtcp-file-tcpip
|
||||
#
|
||||
# no need to get *too* fancy here, if a HTTP request is sent to a HTTPS port
|
||||
# we will still get a HTTP/1.1 Bad Request plain text response
|
||||
#
|
||||
# if no port is specified, default to 80
|
||||
# using example.com for all requests, we just want to check if a webserver is listening
|
||||
# are we doing IPv4 or IPv6?
|
||||
if [[ $upstream = *'.'* ]]; then
|
||||
# IPv4 (or a domain name), we can assume there's max. a single ':'
|
||||
UPSTREAM_IP="${upstream%:*}"
|
||||
UPSTREAM_PORT="${upstream#*:}"
|
||||
if [ "$UPSTREAM_IP" == "$UPSTREAM_PORT" ]; then
|
||||
UPSTREAM_PORT="80"
|
||||
fi
|
||||
else
|
||||
# IPv6, square brackets are obligatory, otherwise nginx complains about invalid port
|
||||
# so we can use that to drop the port if any
|
||||
UPSTREAM_IP="$( echo -n ${upstream%]*} | tr -d '[]' )"
|
||||
UPSTREAM_PORT="${upstream#*]:}"
|
||||
if [ "$UPSTREAM_PORT" == "" ]; then
|
||||
UPSTREAM_PORT="80"
|
||||
fi
|
||||
fi
|
||||
|
||||
cat <<EOF >> "$FASADA_TESTS_UPSTREAMS_FILE"
|
||||
@test "[\$HOSTNAME][upstreams] testing upstream: $upstream - accessible via HTTP/HTTPS?" {
|
||||
exec 8<>/dev/tcp/$UPSTREAM_IP/$UPSTREAM_PORT
|
||||
echo -e "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n" >&8
|
||||
run timeout 3 cat <&8
|
||||
exec 8<&-
|
||||
[[ "\${lines[0]}" == "HTTP/1.1 "* ]]
|
||||
}
|
||||
|
||||
EOF
|
||||
done
|
|
@ -0,0 +1,35 @@
|
|||
#!/bin/bash
|
||||
|
||||
#
|
||||
# running the tests
|
||||
#
|
||||
# this should be ran directly on the bare metal
|
||||
# *not* in the docker container
|
||||
#
|
||||
# it will generate the tests and then run them,
|
||||
# first on bare metal, and then in the nginx container
|
||||
#
|
||||
|
||||
# get the source directory
|
||||
FASADA_TESTS_DIR="$( dirname "$BASH_SOURCE" )"
|
||||
|
||||
# generate the tests
|
||||
#
|
||||
# ...but only if we're not currently running the tests inside the container
|
||||
if [ "$1" != '--running-in-container' ]; then
|
||||
"$FASADA_TESTS_DIR"/gentests.sh "$FASADA_TESTS_DIR/../services/etc/nginx/conf.d/upstreams.conf"
|
||||
fi
|
||||
|
||||
# make sure PATH is set to what we need
|
||||
export PATH="$FASADA_TESTS_DIR/bats-core/bin:$PATH"
|
||||
|
||||
# do the bagic
|
||||
bats "$FASADA_TESTS_DIR"/*.bats
|
||||
|
||||
# do the magic in the container
|
||||
#
|
||||
# ...unless we are already running in the container
|
||||
if [ "$1" != '--running-in-container' ]; then
|
||||
cd "$FASADA_TESTS_DIR/../"
|
||||
docker-compose exec nginx /opt/tests/runtests.sh --running-in-container
|
||||
fi
|
Ładowanie…
Reference in New Issue