Starting work on making nginx easy to configure (for standard installations) reference #352

jschan
Thomas Lynch 3 years ago
parent 9125ec6807
commit e787c7892d
  1. 45
      INSTALLATION.md
  2. 10
      configs/nginx/README.md
  3. 180
      configs/nginx/nginx.sh
  4. 179
      configs/nginx/nginx_config.sh
  5. 55
      configs/nginx/sites-available.example

@ -52,49 +52,10 @@ You may install Node.js yourself without nvm if you prefer.
**6. Configure nginx**
NOTE: The sample configs assume you use the apex domain and a www. subdomain.
For standard installations, run configs/nginx/nginx.sh for easy installation. This will prompt you for installation directory, domains, onion/lokinet, whether
to enable geoip and more. Then, use [certbot](https://certbot.eff.org/) to get a free https certificate.
- Copy the nginx example config and snippets, and create a symlink from sites-available -> sites-enabled
```bash
$ sudo cp configs/nginx/nginx.example /etc/nginx/sites-available/EXAMPLE.COM
$ sudo ln -s /etc/nginx/sites-available/EXAMPLE.COM /etc/nginx/sites-enabled/EXAMPLE.COM
$ sudo cp configs/nginx/snippets/* /etc/nginx/snippets
```
If you have a .onion or .loki address:
- Uncomment the block in /etc/nginx/sites-available/EXAMPLE.COM
Edit/replace the following in your nginx config:
- "/path/to/jschan" with the path of your jschan root folder
- "example.com" with your domain name
- "example.onion" or "example.loki" with your tor or lokinet address
`sed` can be used to automate this process, for example:
```bash
$ sudo sed -i 's|/path/to/jschan|/path/to/your/install|g' /etc/nginx/sites-available/EXAMPLE.COM
$ sudo sed -i 's|/path/to/jschan|/path/to/your/install|g' /etc/nginx/snippets/*
$ sudo sed -i 's/example.com/your.example.com/g' /etc/nginx/sites-available/EXAMPLE.COM
$ sudo sed -i 's/example.com/your.example.com/g' /etc/nginx/snippets/*
# repeat the same for "example.onion" and "example.loki" with your addresses
```
If you don't use .onion or .loki address, remove the example domains from the content-security-policy snippet:
```bash
$ sudo sed -i 's/ wss:\/\/www.example.onion\/ wss:\/\/example.onion\///g' /etc/nginx/snippets/security_headers*
$ sudo sed -i 's/ wss:\/\/www.example.loki\/ wss:\/\/example.loki\///g' /etc/nginx/snippets/security_headers*
```
- Make sure the sites enabled folder is included by `/etc/nginx/nginx.conf` (in debian nginx package this is already done)
- Use [certbot](https://certbot.eff.org/) to get a free https certificate.
- For post flags to work, [follow this guide](http://archive.is/2SMOb) to setup the [legacy GeoIP database](https://www.miyuru.lk/geoiplegacy), then add this directive inside the http block of `/etc/nginx/nginx.conf`:
```
geoip_country /usr/share/GeoIP/GeoIP.dat;
```
If you plan on using hcaptcha or google recaptcha, you will need to modify the content-security-policy header (CSP) in your nginx config. (documentation: [google recaptcha](https://developers.google.com/recaptcha/docs/faq#im-using-content-security-policy-csp-on-my-website.-how-can-i-configure-it-to-work-with-recaptcha), [hcaptcha](https://docs.hcaptcha.com/#content-security-policy-settings))
If you use cloudflare, please read [these](https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs-Logging-visitor-IP-addresses-with-mod-cloudflare-) [articles](https://support.cloudflare.com/hc/en-us/articles/200168236-Configuring-Cloudflare-IP-Geolocation) to setup proper IP forwarding and geolocation headers. Similar steps would apply to other CDNs/reverse proxies.
For non-standard installations like using a CDN, see [configs/nginx/README.md](configs/nginx/README.md) and DIY.
**7. Get the backend setup & running**

@ -1,2 +1,8 @@
`nginx.example` is your /etc/nginx/sites-available/example.com file
`snippets/*` goes in /etc/nginx/snippets/
`sites-available.example` is a sample /etc/nginx/sites-available/example.com file
`snippets/*` are sample snippets for /etc/nginx/snippets/
For standard installs, run nginx.sh for easy configuration with prompts.
For non-standard installations, DIY.
If you use cloudflare, please read [these](https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs-Logging-visitor-IP-addresses-with-mod-cloudflare-) [articles](https://support.cloudflare.com/hc/en-us/articles/200168236-Configuring-Cloudflare-IP-Geolocation) to setup proper IP forwarding and geolocation headers. Similar steps would apply to other CDNs/reverse proxies.

@ -0,0 +1,180 @@
#!/bin/bash
#sets up nginx config
#are you root?
[[ "$EUID" -ne 0 ]] && echo "Please run as root" && exit;
echo "[jschan nginx configuration helper]"
read -p "Enter the directory you cloned jschan (blank=$(pwd)): " JSCHAN_DIRECTORY
JSCHAN_DIRECTORY=${JSCHAN_DIRECTORY:-$(pwd)}
read -p "Enter your clearnet domain name e.g. example.com (blank=no clearnet domain): " CLEARNET_DOMAIN
SITES_AVAILABLE_NAME=${CLEARNET_DOMAIN:-jschan} #not sure on a good default, used for sites-available config name
read -p "Enter tor .onion address (blank=no .onion address): " ONION_DOMAIN
read -p "Enter lokinet .loki address (blank=no .loki address): " LOKI_DOMAIN
read -p "Allow google captcha in content-security policy? (y/n): " GOOGLE_CAPTCHA
read -p "Allow Hcaptcha in content-security policy? (y/n): " H_CAPTCHA
read -p "Try to download and setup geoip for post flags? (y/n): " GEOIP
#looks good?
read -p "Is this correct?
jschan directory: $JSCHAN_DIRECTORY
clearnet domain: $CLEARNET_DOMAIN
.onion address: $ONION_DOMAIN
.loki address: $LOKI_DOMAIN
google captcha: $GOOGLE_CAPTCHA
hcaptcha: $H_CAPTCHA
geoip: $GEOIP
(y/n): " CORRECT
#not saying no = yes, just like real life
[[ "$CORRECT" == "n" ]] && echo "Exiting..." && exit;
#copy the snippets and replace install path, they aren't templated
sudo cp $JSCHAN_DIRECTORY/configs/nginx/snippets/* /etc/nginx/snippets
sudo sed -i "s|/path/to/jschan|$JSCHAN_DIRECTORY|g" /etc/nginx/snippets/*
#declare teplate start
JSCHAN_CONFIG="upstream chan {
server 127.0.0.1:7000;
}"
if [ "$CLEARNET_DOMAIN" != "" ]; then
#onion_location rediret header
ONION_LOCATION=""
if [ "$ONION_DOMAIN" != "" ]; then
ONION_LOCATION="add_header onion-location 'http://$ONION_DOMAIN\$request_uri';"
fi
#concat clearnet server{} block
JSCHAN_CONFIG="${JSCHAN_CONFIG}
server {
server_name www.$CLEARNET_DOMAIN $CLEARNET_DOMAIN;
client_max_body_size 0;
$ONION_LOCATION
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/$CLEARNET_DOMAIN/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/$CLEARNET_DOMAIN/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
include /etc/nginx/snippets/security_headers.conf;
include /etc/nginx/snippets/error_pages.conf;
include /etc/nginx/snippets/jschan_clearnet_routes.conf;
include /etc/nginx/snippets/jschan_common_routes.conf;
}
server {
if (\$host = www.$CLEARNET_DOMAIN) {
return 301 https://\$host\$request_uri;
} # managed by Certbot
if (\$host = $CLEARNET_DOMAIN) {
return 301 https://$host\$request_uri;
} # managed by Certbot
server_name www.$CLEARNET_DOMAIN $CLEARNET_DOMAIN;
listen 80;
listen [::]:80;
return 444; # managed by Certbot
}"
#replace clearnet domain in snippets
sudo sed -i "s/example.com/$CLEARNET_DOMAIN/g" /etc/nginx/snippets/*
fi
if [ "$ONION_DOMAIN" != "" ]; then
#concat onion server{} block
JSCHAN_CONFIG="${JSCHAN_CONFIG}
server {
server_name www.example.onion example.onion;
client_max_body_size 0;
listen unix:/var/run/nginx-tor.sock;
allow 'unix:';
deny all;
include /etc/nginx/snippets/security_headers.conf;
include /etc/nginx/snippets/error_pages.conf;
include /etc/nginx/snippets/jschan_common_routes.conf;
include /etc/nginx/snippets/jschan_tor_routes.conf;
}"
#replace onion domain in snippets
sudo sed -i "s/example.onion/$ONION_DOMAIN/g" /etc/nginx/snippets/*
else
#no onion, remove it from CSP
sudo sed -i 's/ wss:\/\/www.example.onion\/ wss:\/\/example.onion\///g' /etc/nginx/snippets/security_headers*
fi
if [ "$LOKI_DOMAIN" != "" ]; then
#concat lokinet server{} block
JSCHAN_CONFIG="${JSCHAN_CONFIG}
server {
server_name www.$LOKI_DOMAIN $LOKI_DOMAIN;
client_max_body_size 0;
#address may vary if this address is already used by something other than lokinet
listen 172.16.0.1:80;
include /etc/nginx/snippets/security_headers.conf;
include /etc/nginx/snippets/error_pages.conf;
include /etc/nginx/snippets/jschan_common_routes.conf;
include /etc/nginx/snippets/jschan_loki_routes.conf;
}"
#replace lokinet domain in snippets
sudo sed -i "s/example.loki/$LOKI_DOMAIN/g" /etc/nginx/snippets/*
else
#no lokinet, remove it from csp
sudo sed -i 's/ wss:\/\/www.example.loki\/ wss:\/\/example.loki\///g' /etc/nginx/snippets/security_headers*
fi
#debug
#printf "$JSCHAN_CONFIG"
#write the config to file and syymlink to sites-available
echo $JSCHAN_CONFIG >> /etc/nginx/sites-available/$SITES_AVAILABLE_NAME.conf
sudo ln -s /etc/nginx/sites-available/$SITES_AVAILABLE_NAME.conf /etc/nginx/sites-enabled/$SITES_AVAILABLE_NAME.conf
if [ "$GOOGLE_CAPTCHA" == "y" ]; then
#add google captcha CSP exceptions
sudo sed -i "s|script-src|script-src https://www.google.com/recaptcha/, https://www.gstatic.com/recaptcha/ |g" /etc/nginx/snippets/*
sudo sed -i "s|frame-src|frame-src https://www.google.com/recaptcha/, https://recaptcha.google.com/recaptcha/ |g" /etc/nginx/snippets/*
fi
if [ "$H_CAPTCHA" == "y" ]; then
#add hcaptcha CSP exceptions
sudo sed -i "s|script-src|script-src https://hcaptcha.com, https://*.hcaptcha.com |g" /etc/nginx/snippets/*
sudo sed -i "s|frame-src|frame-src https://hcaptcha.com, https://*.hcaptcha.com |g" /etc/nginx/snippets/*
sudo sed -i "s|style-src|style-src https://hcaptcha.com, https://*.hcaptcha.com |g" /etc/nginx/snippets/*
sudo sed -i "s|connect-src|connect-src https://hcaptcha.com, https://*.hcaptcha.com |g" /etc/nginx/snippets/*
fi
if [ "$GEOIP" == "y" ]; then
#download geoip data
cd /usr/share/GeoIP
mv GeoIP.dat GeoIP.dat.bak
wget --retry-connrefused https://dl.miyuru.lk/geoip/dbip/country/dbip.dat.gz
gunzip dbip.dat.gz
mv dbip.dat GeoIP.dat
chown www-data:www-data /usr/share/GeoIP/GeoIP.dat
#add config statement to /etc/nginx/nginx.conf
sudo sed -i '/http {/a \
geoip_country /usr/share/GeoIP/GeoIP.dat;' /etc/nginx/nginx.conf
fi

@ -0,0 +1,179 @@
#!/bin/bash
#sets up nginx config
#are you root?
[[ "$EUID" -ne 0 ]] && echo "Please run as root" && exit;
echo "[jschan nginx configuration helper]"
read -p "Enter the directory you cloned jschan (blank=$(pwd)): " JSCHAN_DIRECTORY
JSCHAN_DIRECTORY=${JSCHAN_DIRECTORY:-$(pwd)}
read -p "Enter your clearnet domain name e.g. example.com (blank=no clearnet domain): " CLEARNET_DOMAIN
SITES_AVAILABLE_NAME=${CLEARNET_DOMAIN:-jschan} #not sure on a good default, used for sites-available config name
read -p "Enter tor .onion address (blank=no .onion address) " ONION_DOMAIN
read -p "Enter lokinet .loki address (blank=no .loki address) " LOKI_DOMAIN
read -p "Allow google captcha in content-security policy? (y/n)" GOOGLE_CAPTCHA
read -p "Allow Hcaptcha in content-security policy? (y/n)" H_CAPTCHA
read -p "Try to download and setup geoip for post flags? (y/n)" GEOIP
#looks good?
read -p "Is this correct?
jschan directory: $JSCHAN_DIRECTORY
clearnet domain: $CLEARNET_DOMAIN
.onion address: $ONION_DOMAIN
.loki address: $LOKI_DOMAIN
google captcha: $GOOGLE_CAPTCHA
hcaptcha: $H_CAPTCHA
geoip: $GEOIP
(y/n): " CORRECT
#not saying no = yes, just like real life
[[ "$CORRECT" == "n" ]] && echo "Exiting..." && exit;
#copy the snippets and replace install path, they aren't templated
#sudo cp $JSCHAN_DIRECTORY/configs/nginx/snippets/* /etc/nginx/snippets
#sudo sed -i "s|/path/to/jschan|$JSCHAN_DIRECTORY|g" /etc/nginx/snippets/*
#declare teplate start
JSCHAN_CONFIG="upstream chan {
server 127.0.0.1:7000;
}"
if [ "$CLEARNET_DOMAIN" != "" ]; then
#onion_location rediret header
ONION_LOCATION=""
if [ "$ONION_DOMAIN" != "" ]; then
ONION_LOCATION="add_header onion-location 'http://$ONION_DOMAIN\$request_uri';"
fi
#concat clearnet server{} block
JSCHAN_CONFIG="${JSCHAN_CONFIG}
server {
server_name www.$CLEARNET_DOMAIN $CLEARNET_DOMAIN;
client_max_body_size 0;
$ONION_LOCATION
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/$CLEARNET_DOMAIN/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/$CLEARNET_DOMAIN/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
include /etc/nginx/snippets/security_headers.conf;
include /etc/nginx/snippets/error_pages.conf;
include /etc/nginx/snippets/jschan_clearnet_routes.conf;
include /etc/nginx/snippets/jschan_common_routes.conf;
}
server {
if (\$host = www.$CLEARNET_DOMAIN) {
return 301 https://\$host\$request_uri;
} # managed by Certbot
if (\$host = $CLEARNET_DOMAIN) {
return 301 https://$host\$request_uri;
} # managed by Certbot
server_name www.$CLEARNET_DOMAIN $CLEARNET_DOMAIN;
listen 80;
listen [::]:80;
return 444; # managed by Certbot
}"
#replace clearnet domain in snippets
#sudo sed -i "s/example.com/$CLEARNET_DOMAIN/g" /etc/nginx/snippets/*
fi
if [ "$ONION_DOMAIN" != "" ]; then
#concat onion server{} block
JSCHAN_CONFIG="${JSCHAN_CONFIG}
server {
server_name www.example.onion example.onion;
client_max_body_size 0;
listen unix:/var/run/nginx-tor.sock;
allow 'unix:';
deny all;
include /etc/nginx/snippets/security_headers.conf;
include /etc/nginx/snippets/error_pages.conf;
include /etc/nginx/snippets/jschan_common_routes.conf;
include /etc/nginx/snippets/jschan_tor_routes.conf;
}"
#replace onion domain in snippets
#sudo sed -i "s/example.onion/$ONION_DOMAIN/g" /etc/nginx/snippets/*
else
#no onion, remove it from CSP
#sudo sed -i 's/ wss:\/\/www.example.onion\/ wss:\/\/example.onion\///g' /etc/nginx/snippets/security_headers*
fi
if [ "$LOKI_DOMAIN" != "" ]; then
#concat lokinet server{} block
JSCHAN_CONFIG="${JSCHAN_CONFIG}
server {
server_name www.$LOKI_DOMAIN $LOKI_DOMAIN;
client_max_body_size 0;
#address may vary if this address is already used by something other than lokinet
listen 172.16.0.1:80;
include /etc/nginx/snippets/security_headers.conf;
include /etc/nginx/snippets/error_pages.conf;
include /etc/nginx/snippets/jschan_common_routes.conf;
include /etc/nginx/snippets/jschan_loki_routes.conf;
}"
#replace lokinet domain in snippets
#sudo sed -i "s/example.loki/$LOKI_DOMAIN/g" /etc/nginx/snippets/*
else
#no lokinet, remove it from csp
#sudo sed -i 's/ wss:\/\/www.example.loki\/ wss:\/\/example.loki\///g' /etc/nginx/snippets/security_headers*
fi
echo "$JSCHAN_CONFIG"
#write the config to file and syymlink to sites-available
#echo $JSCHAN_CONFIG >> /etc/nginx/sites-available/$SITES_AVAILABLE_NAME.conf
#sudo ln -s /etc/nginx/sites-available/$SITES_AVAILABLE_NAME.conf /etc/nginx/sites-enabled/$SITES_AVAILABLE_NAME.conf
if [ "$GOOGLE_CAPTCHA" == "y" ]; then
#add google captcha CSP exceptions
#sudo sed -i "s|script-src|script-src https://www.google.com/recaptcha/, https://www.gstatic.com/recaptcha/ |g" /etc/nginx/snippets/*
#sudo sed -i "s|frame-src|frame-src https://www.google.com/recaptcha/, https://recaptcha.google.com/recaptcha/ |g" /etc/nginx/snippets/*
fi
if [ "$H_CAPTCHA" == "y" ]; then
#add hcaptcha CSP exceptions
#sudo sed -i "s|script-src|script-src https://hcaptcha.com, https://*.hcaptcha.com |g" /etc/nginx/snippets/*
#sudo sed -i "s|frame-src|frame-src https://hcaptcha.com, https://*.hcaptcha.com |g" /etc/nginx/snippets/*
#sudo sed -i "s|style-src|style-src https://hcaptcha.com, https://*.hcaptcha.com |g" /etc/nginx/snippets/*
#sudo sed -i "s|connect-src|connect-src https://hcaptcha.com, https://*.hcaptcha.com |g" /etc/nginx/snippets/*
fi
if [ "$GEOIP" == "y" ]; then
#download geoip data
cd /usr/share/GeoIP
mv GeoIP.dat GeoIP.dat.bak
wget --retry-connrefused https://dl.miyuru.lk/geoip/dbip/country/dbip.dat.gz
gunzip dbip.dat.gz
mv dbip.dat GeoIP.dat
chown www-data:www-data /usr/share/GeoIP/GeoIP.dat
#add config statement to /etc/nginx/nginx.conf
#sudo sed -i '/http {/a \
#geoip_country /usr/share/GeoIP/GeoIP.dat;' /etc/nginx/nginx.conf
fi

@ -2,40 +2,37 @@ upstream chan {
server 127.0.0.1:7000;
}
# uncomment for lokinet snapp
#server {
# server_name www.example.loki example.loki;
# client_max_body_size 0;
#
# #address may vary if this address is already used by something other than lokinet
# listen 172.16.0.1:80;
#
# include /etc/nginx/snippets/security_headers.conf;
# include /etc/nginx/snippets/error_pages.conf;
# include /etc/nginx/snippets/jschan_common_routes.conf;
# include /etc/nginx/snippets/jschan_loki_routes.conf;
#}
server {
server_name www.example.loki example.loki;
client_max_body_size 0;
# uncomment for .onion tor hidden service
#server {
# server_name www.example.onion example.onion;
# client_max_body_size 0;
#
# listen unix:/var/run/nginx-tor.sock;
# allow "unix:";
# deny all;
#
# include /etc/nginx/snippets/security_headers.conf;
# include /etc/nginx/snippets/error_pages.conf;
# include /etc/nginx/snippets/jschan_common_routes.conf;
# include /etc/nginx/snippets/jschan_tor_routes.conf;
#}
listen 172.16.0.1:80;
include /etc/nginx/snippets/security_headers.conf;
include /etc/nginx/snippets/error_pages.conf;
include /etc/nginx/snippets/jschan_common_routes.conf;
include /etc/nginx/snippets/jschan_loki_routes.conf;
}
server {
server_name www.example.onion example.onion;
client_max_body_size 0;
listen unix:/var/run/nginx-tor.sock;
allow "unix:";
deny all;
include /etc/nginx/snippets/security_headers.conf;
include /etc/nginx/snippets/error_pages.conf;
include /etc/nginx/snippets/jschan_common_routes.conf;
include /etc/nginx/snippets/jschan_tor_routes.conf;
}
server {
server_name www.example.com example.com;
client_max_body_size 0;
#uncomment if you have a .onion
#add_header onion-location 'http://example.onion$request_uri';
add_header onion-location 'http://example.onion$request_uri';
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
Loading…
Cancel
Save