]> Untitled Git - lemmy.git/blob - docker/prod/nginx.conf
3e0bc3491f4b9f86a44f5b735a074fe01d1c48a6
[lemmy.git] / docker / prod / nginx.conf
1 # nginx example config
2 # replace {{yourdomain}} and review the certbot/letsencrypt config
3 worker_processes 1;
4 events {
5     worker_connections 1024;
6 }
7 http {
8     limit_req_zone $binary_remote_addr zone={{yourdomain}}_ratelimit:10m rate=1r/s;
9
10     upstream lemmy {
11         # this needs to map to the lemmy (server) docker service hostname
12         server "lemmy:8536";
13     }
14     upstream lemmy-ui {
15         # this needs to map to the lemmy-ui docker service hostname
16         server "lemmy-ui:1234";
17     }
18
19     server {
20         # allow letsencrypt challenge
21         # redirect everything else to 443
22         listen 80;
23         listen [::]:80;
24         server_name {{yourdomain}};
25         location /.well-known/acme-challenge/ {
26             root /var/www/certbot;
27         }
28         location / {
29             return 301 https://$host$request_uri;
30         }
31     }
32
33     server {
34         listen 443 ssl http2;
35         listen [::]:443 ssl http2;
36         server_name {{yourdomain}};
37
38         ssl_certificate /etc/letsencrypt/live/{{yourdomain}}/fullchain.pem;
39         ssl_certificate_key /etc/letsencrypt/live/{{yourdomain}}/privkey.pem;
40
41         # Various TLS hardening settings
42         # https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
43         ssl_protocols TLSv1.2 TLSv1.3;
44         ssl_prefer_server_ciphers on;
45         ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
46         ssl_session_timeout  10m;
47         ssl_session_cache shared:SSL:10m;
48         ssl_session_tickets on;
49         ssl_stapling on;
50         ssl_stapling_verify on;
51
52         # Hide nginx version
53         server_tokens off;
54
55         # Enable compression for JS/CSS/HTML bundle, for improved client load times.
56         # It might be nice to compress JSON, but leaving that out to protect against potential
57         # compression+encryption information leak attacks like BREACH.
58         gzip on;
59         gzip_types text/css application/javascript image/svg+xml;
60         gzip_vary on;
61
62         # Only connect to this site via HTTPS for the two years
63         add_header Strict-Transport-Security "max-age=63072000";
64
65         # Various content security headers
66         add_header Referrer-Policy "same-origin";
67         add_header X-Content-Type-Options "nosniff";
68         add_header X-Frame-Options "DENY";
69         add_header X-XSS-Protection "1; mode=block";
70
71         # Upload limit for pictrs
72         client_max_body_size 20M;
73
74         # frontend
75         location / {
76             # distinguish between ui requests and backend
77             # don't change lemmy-ui or lemmy here, they refer to the upstream definitions on top
78             set $proxpass "http://lemmy-ui";
79
80             if ($http_accept = "application/activity+json") {
81                 set $proxpass "http://lemmy";
82             }
83             if ($http_accept = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") {
84                 set $proxpass "http://lemmy";
85             }
86             if ($request_method = POST) {
87                 set $proxpass "http://lemmy";
88             }
89             proxy_pass $proxpass;
90
91             rewrite ^(.+)/+$ $1 permanent;
92
93             # Send actual client IP upstream
94             proxy_set_header X-Real-IP $remote_addr;
95             proxy_set_header Host $host;
96             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
97         }
98
99         # backend
100         location ~ ^/(api|feeds|nodeinfo|.well-known) {
101             proxy_pass "http://lemmy";
102             proxy_http_version 1.1;
103             proxy_set_header Upgrade $http_upgrade;
104             proxy_set_header Connection "upgrade";
105
106             # Rate limit
107             limit_req zone={{yourdomain}}_ratelimit burst=30 nodelay;
108
109             # Add IP forwarding headers
110             proxy_set_header X-Real-IP $remote_addr;
111             proxy_set_header Host $host;
112             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
113         }
114
115         # pictrs only - for adding browser cache control.
116         location ~ ^/(pictrs) {
117             # allow browser cache, images never update, we can apply long term cache
118             expires 120d;
119             add_header Pragma "public";
120             add_header Cache-Control "public";
121
122             proxy_pass "http://lemmy";
123             proxy_http_version 1.1;
124             proxy_set_header Upgrade $http_upgrade;
125             proxy_set_header Connection "upgrade";
126
127             # Rate limit
128             limit_req zone={{yourdomain}}_ratelimit burst=30 nodelay;
129
130             # Add IP forwarding headers
131             proxy_set_header X-Real-IP $remote_addr;
132             proxy_set_header Host $host;
133             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
134         }
135
136         # Redirect pictshare images to pictrs
137         location ~ /pictshare/(.*)$ {
138             return 301 /pictrs/image/$1;
139         }
140     }
141
142     # Anonymize IP addresses
143     # https://www.supertechcrew.com/anonymizing-logs-nginx-apache/
144     map $remote_addr $remote_addr_anon {
145         ~(?P<ip>\d+\.\d+\.\d+)\.    $ip.0;
146         ~(?P<ip>[^:]+:[^:]+):       $ip::;
147         127.0.0.1                   $remote_addr;
148         ::1                         $remote_addr;
149         default                     0.0.0.0;
150     }
151     access_log /var/log/nginx/access.log combined;
152 }