2022-05-20 15:06:41 +00:00
#!/bin/bash
2023-02-01 19:44:05 +00:00
set -ex
2022-05-20 15:06:41 +00:00
cd " $( dirname " $0 " ) "
# here's the NGINX config. We support ghost and nextcloud.
2022-08-24 14:09:09 +00:00
NGINX_CONF_PATH = " $PROJECT_PATH /nginx.conf "
2022-09-09 18:00:07 +00:00
# clear the existing nginx config.
2022-05-20 15:06:41 +00:00
echo "" > " $NGINX_CONF_PATH "
2022-09-09 18:00:07 +00:00
# iterate over all our domains and create the nginx config file.
iteration = 0
for DOMAIN_NAME in ${ DOMAIN_LIST //,/ } ; do
export DOMAIN_NAME = " $DOMAIN_NAME "
export SITE_PATH = " $SITES_PATH / $DOMAIN_NAME "
export CONTAINER_TLS_PATH = " /etc/letsencrypt/ ${ DOMAIN_NAME } /live/ ${ DOMAIN_NAME } "
# source the site path so we know what features it has.
2023-02-01 19:44:05 +00:00
echo "BEFORE"
source ../../../defaults.sh
2022-09-09 18:00:07 +00:00
source " $SITE_PATH /site_definition "
2023-02-01 19:44:05 +00:00
source ../../domain_env.sh
echo "after"
2022-09-09 18:00:07 +00:00
if [ $iteration = 0 ] ; then
cat >>" $NGINX_CONF_PATH " <<EOL
2022-05-20 15:06:41 +00:00
events {
worker_connections 1024;
}
http {
client_max_body_size 100m;
server_tokens off;
2022-08-20 21:44:37 +00:00
# next two sets commands and connection_upgrade block come from https://docs.btcpayserver.org/FAQ/Deployment/#can-i-use-an-existing-nginx-server-as-a-reverse-proxy-with-ssl-termination
# Needed to allow very long URLs to prevent issues while signing PSBTs
2022-09-09 18:00:07 +00:00
server_names_hash_bucket_size 128;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
client_header_buffer_size 500k;
large_client_header_buffers 4 500k;
2022-08-20 21:44:37 +00:00
# Needed websocket support (used by Ledger hardware wallets)
map \$ http_upgrade \$ connection_upgrade {
default upgrade;
'' close;
}
2022-08-24 14:09:09 +00:00
# return 403 for all non-explicit hostnames
server {
listen 80 default_server;
2022-09-09 18:00:07 +00:00
return 301 https://${ WWW_FQDN } \$ request_uri;
2022-08-24 14:09:09 +00:00
}
2022-05-20 15:06:41 +00:00
EOL
2022-09-09 18:00:07 +00:00
fi
2022-05-20 15:06:41 +00:00
2022-09-09 18:00:07 +00:00
# ghost http to https redirects.
cat >>" $NGINX_CONF_PATH " <<EOL
2022-08-24 14:11:50 +00:00
# http://${DOMAIN_NAME} redirect to https://${WWW_FQDN}
2022-05-20 15:06:41 +00:00
server {
listen 80;
server_name ${ DOMAIN_NAME } ;
location / {
# request MAY get another redirect at https://domain.tld for www.
return 301 https://${ DOMAIN_NAME } \$ request_uri;
}
}
2022-08-24 14:11:50 +00:00
2022-05-20 15:06:41 +00:00
EOL
2022-09-09 18:00:07 +00:00
cat >>" $NGINX_CONF_PATH " <<EOL
2022-08-24 14:11:50 +00:00
# http://${WWW_FQDN} redirect to https://${WWW_FQDN}
2022-05-20 15:06:41 +00:00
server {
listen 80;
2022-08-24 14:11:50 +00:00
server_name ${ WWW_FQDN } ;
return 301 https://${ WWW_FQDN } \$ request_uri;
2022-05-20 15:06:41 +00:00
}
EOL
2022-09-09 18:00:07 +00:00
# nextcloud http-to-https redirect
if [ " $DEPLOY_NEXTCLOUD " = true ] ; then
cat >>" $NGINX_CONF_PATH " <<EOL
2022-05-20 15:06:41 +00:00
# http://${NEXTCLOUD_FQDN} redirect to https://${NEXTCLOUD_FQDN}
server {
listen 80;
server_name ${ NEXTCLOUD_FQDN } ;
return 301 https://${ NEXTCLOUD_FQDN } \$ request_uri;
}
EOL
2022-09-09 18:00:07 +00:00
fi
2022-05-20 15:06:41 +00:00
2022-09-09 18:00:07 +00:00
# gitea http to https redirect.
if [ " $DEPLOY_GITEA " = true ] ; then
cat >>" $NGINX_CONF_PATH " <<EOL
2022-05-20 15:06:41 +00:00
# http://${GITEA_FQDN} redirect to https://${GITEA_FQDN}
server {
listen 80;
server_name ${ GITEA_FQDN } ;
return 301 https://${ GITEA_FQDN } \$ request_uri;
}
EOL
2022-09-09 18:00:07 +00:00
fi
2022-05-20 15:06:41 +00:00
2022-11-05 23:49:24 +00:00
# let's iterate over BTCPAY_ALT_NAMES and generate our SERVER_NAMES for btcpay server.
BTCPAY_SERVER_NAMES = " $BTCPAY_USER_FQDN "
if [ -n " $BTCPAY_ALT_NAMES " ] ; then
# let's stub out the rest of our site definitions, if any.
for ALT_NAME in ${ BTCPAY_ALT_NAMES //,/ } ; do
BTCPAY_SERVER_NAMES = " $BTCPAY_SERVER_NAMES $ALT_NAME . $DOMAIN_NAME "
done
fi
2022-10-26 23:33:43 +00:00
# BTCPAY server http->https redirect
cat >>" $NGINX_CONF_PATH " <<EOL
2022-08-20 21:44:37 +00:00
# http://${BTCPAY_USER_FQDN} redirect to https://${BTCPAY_USER_FQDN}
server {
listen 80;
2022-11-05 23:49:24 +00:00
server_name ${ BTCPAY_SERVER_NAMES } ;
2023-02-01 19:44:05 +00:00
return 301 https://\$ host\$ request_uri;
2022-08-20 21:44:37 +00:00
}
EOL
2023-02-01 19:44:05 +00:00
if [ $iteration = 0 ] ; then
2022-09-09 18:00:07 +00:00
# TLS config for ghost.
cat >>" $NGINX_CONF_PATH " <<EOL
2022-05-20 15:06:41 +00:00
# global TLS settings
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.3;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=63072000" always;
ssl_stapling on;
ssl_stapling_verify on;
# default server if hostname not specified.
2022-08-24 14:11:50 +00:00
server {
listen 443 default_server;
2022-09-09 18:00:07 +00:00
ssl_certificate $CONTAINER_TLS_PATH /fullchain.pem;
ssl_certificate_key $CONTAINER_TLS_PATH /privkey.pem;
ssl_trusted_certificate $CONTAINER_TLS_PATH /fullchain.pem;
2022-05-20 15:06:41 +00:00
2022-08-24 14:11:50 +00:00
return 403;
}
# maybe helps with Twitter cards.
2022-09-09 18:00:07 +00:00
#map \$http_user_agent \$og_prefix {
# ~*(googlebot|twitterbot)/ /open-graph;
#}
2022-09-28 17:59:01 +00:00
# this map allows us to route the clients request to the correct Ghost instance
# based on the clients browser language setting.
map \$ http_accept_language \$ lang {
2022-10-08 16:44:46 +00:00
default "" ;
2022-09-28 17:59:01 +00:00
~es es;
}
2022-09-09 18:00:07 +00:00
EOL
fi
2022-05-20 15:06:41 +00:00
2022-09-09 18:00:07 +00:00
cat >>" $NGINX_CONF_PATH " <<EOL
# https://${DOMAIN_NAME} redirect to https://${WWW_FQDN}
2022-05-20 15:06:41 +00:00
server {
listen 443 ssl http2;
2022-08-24 14:11:50 +00:00
2022-09-09 18:00:07 +00:00
ssl_certificate $CONTAINER_TLS_PATH /fullchain.pem;
ssl_certificate_key $CONTAINER_TLS_PATH /privkey.pem;
ssl_trusted_certificate $CONTAINER_TLS_PATH /fullchain.pem;
2022-05-20 15:06:41 +00:00
server_name ${ DOMAIN_NAME } ;
2022-11-05 23:49:24 +00:00
2022-05-20 15:06:41 +00:00
EOL
2023-01-07 14:37:55 +00:00
if [ -n " $NOSTR_ACCOUNT_PUBKEY " ] ; then
2022-09-09 18:00:07 +00:00
cat >>" $NGINX_CONF_PATH " <<EOL
2022-05-20 15:06:41 +00:00
# We return a JSON object with name/pubkey mapping per NIP05.
# https://www.reddit.com/r/nostr/comments/rrzk76/nip05_mapping_usernames_to_dns_domains_by_fiatjaf/sssss
# TODO I'm not sure about the security of this Access-Control-Allow-Origin. Read up and restrict it if possible.
location = /.well-known/nostr.json {
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
2023-01-07 14:37:55 +00:00
return 200 '{ "names": { "_": "${NOSTR_ACCOUNT_PUBKEY}" }, "relays": { "${NOSTR_ACCOUNT_PUBKEY}": [ "wss://${NOSTR_FQDN}" ] } }' ;
2022-05-20 15:06:41 +00:00
}
EOL
2022-09-09 18:00:07 +00:00
fi
2022-05-20 15:06:41 +00:00
2022-09-09 18:00:07 +00:00
cat >>" $NGINX_CONF_PATH " <<EOL
2022-11-05 23:49:24 +00:00
# catch all; send request to ${WWW_FQDN}
location / {
return 301 https://${ WWW_FQDN } \$ request_uri;
}
2022-05-20 15:06:41 +00:00
}
#access_log /var/log/nginx/ghost-access.log;
#error_log /var/log/nginx/ghost-error.log;
EOL
2022-08-20 21:44:37 +00:00
2023-01-07 14:37:55 +00:00
if [ -n " $NOSTR_ACCOUNT_PUBKEY " ] ; then
2022-11-14 01:23:48 +00:00
cat >>" $NGINX_CONF_PATH " <<EOL
# wss://$NOSTR_FQDN server block
server {
listen 443 ssl;
server_name ${ NOSTR_FQDN } ;
ssl_certificate $CONTAINER_TLS_PATH /fullchain.pem;
ssl_certificate_key $CONTAINER_TLS_PATH /privkey.pem;
ssl_trusted_certificate $CONTAINER_TLS_PATH /fullchain.pem;
keepalive_timeout 70;
location / {
# redirect all HTTP traffic to btcpay server
proxy_pass http://nostr-${ DOMAIN_IDENTIFIER } :8080;
proxy_http_version 1.1;
proxy_set_header Upgrade \$ http_upgrade;
proxy_set_header Connection "Upgrade" ;
proxy_set_header Host \$ host;
}
}
EOL
fi
2022-10-26 23:33:43 +00:00
cat >>" $NGINX_CONF_PATH " <<EOL
2022-11-05 23:49:24 +00:00
# https server block for https://${BTCPAY_SERVER_NAMES}
2022-08-20 21:44:37 +00:00
server {
listen 443 ssl http2;
2022-08-24 14:11:50 +00:00
2022-09-09 18:00:07 +00:00
ssl_certificate $CONTAINER_TLS_PATH /fullchain.pem;
ssl_certificate_key $CONTAINER_TLS_PATH /privkey.pem;
ssl_trusted_certificate $CONTAINER_TLS_PATH /fullchain.pem;
2022-08-24 14:11:50 +00:00
2022-11-05 23:49:24 +00:00
server_name ${ BTCPAY_SERVER_NAMES } ;
2022-09-28 17:59:01 +00:00
2022-08-20 21:44:37 +00:00
# Route everything to the real BTCPay server
location / {
# URL of BTCPay Server
proxy_pass http://10.139.144.10:80;
proxy_set_header Host \$ http_host;
proxy_set_header X-Forwarded-Proto \$ scheme;
proxy_set_header X-Real-IP \$ remote_addr;
proxy_set_header X-Forwarded-For \$ proxy_add_x_forwarded_for;
# For websockets (used by Ledger hardware wallets)
proxy_set_header Upgrade \$ http_upgrade;
}
}
EOL
2023-02-01 19:44:05 +00:00
# Clams server entry
# cat >>"$NGINX_CONF_PATH" <<EOL
# # https server block for https://${CLAMS_FQDN}
# server {
# listen 443 ssl http2;
# ssl_certificate $CONTAINER_TLS_PATH/fullchain.pem;
# ssl_certificate_key $CONTAINER_TLS_PATH/privkey.pem;
# ssl_trusted_certificate $CONTAINER_TLS_PATH/fullchain.pem;
# server_name ${CLAMS_FQDN};
# index index.js;
# root /apps/clams;
# index 200.htm;
# location / {
# try_files \$uri \$uri/ /200.htm;
# }
# location ~* \.(?:css|js|jpg|svg)$ {
# expires 30d;
# add_header Cache-Control "public";
# }
# }
# EOL
2022-09-28 17:59:01 +00:00
echo " # set up cache paths for nginx caching" >>" $NGINX_CONF_PATH "
for LANGUAGE_CODE in ${ SITE_LANGUAGE_CODES //,/ } ; do
2022-10-19 17:15:38 +00:00
STACK_NAME = " $DOMAIN_IDENTIFIER - $LANGUAGE_CODE "
2022-09-28 17:59:01 +00:00
cat >>" $NGINX_CONF_PATH " <<EOL
proxy_cache_path /tmp/${ STACK_NAME } levels = 1:2 keys_zone = ${ STACK_NAME } :600m max_size = 100m inactive = 24h;
EOL
done
2022-08-20 21:44:37 +00:00
2022-09-28 17:59:01 +00:00
# the open server block for the HTTPS listener for ghost
2022-09-09 18:00:07 +00:00
cat >>" $NGINX_CONF_PATH " <<EOL
2022-09-28 17:59:01 +00:00
# Main HTTPS listener for https://${WWW_FQDN}
2022-05-20 15:06:41 +00:00
server {
listen 443 ssl http2;
2022-09-09 18:00:07 +00:00
ssl_certificate $CONTAINER_TLS_PATH /fullchain.pem;
ssl_certificate_key $CONTAINER_TLS_PATH /privkey.pem;
ssl_trusted_certificate $CONTAINER_TLS_PATH /fullchain.pem;
2022-08-24 14:11:50 +00:00
server_name ${ WWW_FQDN } ;
2022-05-20 15:06:41 +00:00
2022-09-28 17:59:01 +00:00
# Set the crawler policy.
location = /robots.txt {
add_header Content-Type text/plain;
return 200 "User-Agent: *\\nAllow: /\\n" ;
}
2022-05-20 15:06:41 +00:00
EOL
2022-09-28 17:59:01 +00:00
# # add the Onion-Location header if specifed.
# if [ "$DEPLOY_ONION_SITE" = true ]; then
# cat >>"$NGINX_CONF_PATH" <<EOL
# add_header Onion-Location https://${ONION_ADDRESS}\$request_uri;
# EOL
# fi
2022-10-08 16:44:46 +00:00
for LANGUAGE_CODE in ${ SITE_LANGUAGE_CODES //,/ } ; do
2022-10-19 17:15:38 +00:00
STACK_NAME = " $DOMAIN_IDENTIFIER - $LANGUAGE_CODE "
2022-09-28 17:59:01 +00:00
2022-10-08 16:44:46 +00:00
if [ " $LANGUAGE_CODE " = en ] ; then
cat >>" $NGINX_CONF_PATH " <<EOL
location ~ ^/( ghost/| p/| private/) {
EOL
else
cat >>" $NGINX_CONF_PATH " <<EOL
location ~ ^/${ LANGUAGE_CODE } /( ghost/| p/| private/) {
2022-09-28 17:59:01 +00:00
EOL
2022-10-08 16:44:46 +00:00
fi
2022-05-20 15:06:41 +00:00
2022-09-28 17:59:01 +00:00
cat >>" $NGINX_CONF_PATH " <<EOL
2022-05-20 15:06:41 +00:00
proxy_set_header X-Real-IP \$ remote_addr;
2023-02-01 19:44:05 +00:00
proxy_set_header Host \$ host;
2022-05-20 15:06:41 +00:00
proxy_set_header X-Forwarded-For \$ proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$ scheme;
proxy_intercept_errors on;
2022-09-28 17:59:01 +00:00
proxy_pass http://ghost-${ STACK_NAME } :2368;
2022-05-20 15:06:41 +00:00
}
2022-10-08 16:44:46 +00:00
2022-05-20 15:06:41 +00:00
EOL
2022-09-28 17:59:01 +00:00
done
2022-05-20 15:06:41 +00:00
2022-10-08 16:44:46 +00:00
ROOT_SITE_LANGUAGE_CODES = " $SITE_LANGUAGE_CODES "
for LANGUAGE_CODE in ${ ROOT_SITE_LANGUAGE_CODES //,/ } ; do
2022-09-28 17:59:01 +00:00
cat >>" $NGINX_CONF_PATH " <<EOL
2022-10-08 16:44:46 +00:00
# Location block to back https://${WWW_FQDN}/${LANGUAGE_CODE} or https://${WWW_FQDN}/ if english.
EOL
if [ " $LANGUAGE_CODE " = en ] ; then
cat >>" $NGINX_CONF_PATH " <<EOL
location / {
EOL
if ( ( " $LANGUAGE_CODE_COUNT " > 1 ) ) ; then
# we only need this clause if we know there is more than once lanuage being rendered.
cat >>" $NGINX_CONF_PATH " <<EOL
# Redirect the user to the correct language using the map above.
if ( \$ http_accept_language !~* '^en(.*)\$' ) {
#rewrite (.*) \$1/\$lang;
return 302 https://${ WWW_FQDN } /\$ lang;
}
EOL
fi
else
cat >>" $NGINX_CONF_PATH " <<EOL
2022-09-28 17:59:01 +00:00
location /${ LANGUAGE_CODE } {
2022-10-08 16:44:46 +00:00
EOL
fi
cat >>" $NGINX_CONF_PATH " <<EOL
2022-05-20 15:06:41 +00:00
proxy_set_header X-Real-IP \$ remote_addr;
2023-02-01 19:44:05 +00:00
proxy_set_header Host \$ host;
2022-05-20 15:06:41 +00:00
proxy_set_header X-Forwarded-For \$ proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$ scheme;
proxy_intercept_errors on;
2022-10-19 17:15:38 +00:00
proxy_pass http://ghost-${ DOMAIN_IDENTIFIER } -${ LANGUAGE_CODE } :2368;
2022-05-20 15:06:41 +00:00
# https://stanislas.blog/2019/08/ghost-nginx-cache/ for nginx caching instructions
# Remove cookies which are useless for anonymous visitor and prevent caching
proxy_ignore_headers Set-Cookie Cache-Control;
proxy_hide_header Set-Cookie;
# Add header for cache status (miss or hit)
add_header X-Cache-Status \$ upstream_cache_status;
2022-10-19 17:15:38 +00:00
proxy_cache ${ DOMAIN_IDENTIFIER } -${ LANGUAGE_CODE } ;
2022-05-20 15:06:41 +00:00
# Default TTL: 1 day
proxy_cache_valid 5s;
# Cache 404 pages for 1h
proxy_cache_valid 404 1h;
# use conditional GET requests to refresh the content from origin servers
proxy_cache_revalidate on;
proxy_buffering on;
# Allows starting a background subrequest to update an expired cache item,
# while a stale cached response is returned to the client.
proxy_cache_background_update on;
# Bypass cache for errors
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
}
2022-09-28 22:20:17 +00:00
EOL
2022-10-08 16:44:46 +00:00
done
2022-09-29 17:14:51 +00:00
# this is the closing server block for the ghost HTTPS segment
cat >>" $NGINX_CONF_PATH " <<EOL
}
2022-09-28 22:20:17 +00:00
2022-09-29 17:14:51 +00:00
EOL
2022-10-08 16:44:46 +00:00
2022-10-22 00:04:03 +00:00
if [ " $DEPLOY_NEXTCLOUD " = true ] ; then
cat >>" $NGINX_CONF_PATH " <<EOL
# TLS listener for ${NEXTCLOUD_FQDN}
server {
listen 443 ssl http2;
ssl_certificate $CONTAINER_TLS_PATH /fullchain.pem;
ssl_certificate_key $CONTAINER_TLS_PATH /privkey.pem;
ssl_trusted_certificate $CONTAINER_TLS_PATH /fullchain.pem;
server_name ${ NEXTCLOUD_FQDN } ;
location / {
proxy_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 64;
proxy_set_header X-Real-IP \$ remote_addr;
proxy_set_header Host \$ host;
proxy_set_header X-Forwarded-For \$ proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$ scheme;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://${ NEXTCLOUD_STACK_TAG } :80;
}
# https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/reverse_proxy_configuration.html
location /.well-known/carddav {
return 301 \$ scheme://\$ host/remote.php/dav;
}
location /.well-known/caldav {
return 301 \$ scheme://\$ host/remote.php/dav;
}
}
EOL
fi
2022-10-08 16:44:46 +00:00
# TODO this MIGHT be part of the solution for Twitter Cards.
# location /contents {
# resolver 127.0.0.11 ipv6=off valid=5m;
# proxy_set_header X-Real-IP \$remote_addr;
# proxy_set_header Host \$http_host;
# proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto \$scheme;
# proxy_intercept_errors on;
2022-10-19 17:15:38 +00:00
# proxy_pass http://ghost-${DOMAIN_IDENTIFIER}-${SITE_LANGUAGE_CODES}::2368\$og_prefix\$request_uri;
2022-10-08 16:44:46 +00:00
# }
2022-09-29 17:14:51 +00:00
# this piece is for GITEA.
2022-10-08 16:44:46 +00:00
if [ " $DEPLOY_GITEA " = true ] ; then
2022-09-28 22:20:17 +00:00
cat >>" $NGINX_CONF_PATH " <<EOL
# TLS listener for ${GITEA_FQDN}
server {
listen 443 ssl http2;
2022-10-08 16:44:46 +00:00
ssl_certificate $CONTAINER_TLS_PATH /fullchain.pem;
ssl_certificate_key $CONTAINER_TLS_PATH /privkey.pem;
ssl_trusted_certificate $CONTAINER_TLS_PATH /fullchain.pem;
2022-09-28 22:20:17 +00:00
server_name ${ GITEA_FQDN } ;
location / {
proxy_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 64;
proxy_set_header X-Real-IP \$ remote_addr;
proxy_set_header Host \$ host;
proxy_set_header X-Forwarded-For \$ proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$ scheme;
proxy_set_header X-NginX-Proxy true;
2022-10-19 17:15:38 +00:00
proxy_pass http://gitea-${ DOMAIN_IDENTIFIER } -en:3000;
2022-09-28 22:20:17 +00:00
}
2022-09-29 17:14:51 +00:00
}
2022-05-20 15:06:41 +00:00
EOL
2022-10-08 16:44:46 +00:00
fi
2022-05-20 15:06:41 +00:00
2023-03-05 16:49:06 +00:00
# deploy Clams browser app under the primary domain.
if [ $iteration = 0 ] ; then
cat >> " $NGINX_CONF_PATH " <<EOF
# server block for the clams browser-app; just a static website
server {
listen 443 ssl;
server_name ${ CLAMS_FQDN } ;
autoindex off;
server_tokens off;
gzip_static on;
root /browser-app;
index 200.html;
}
EOF
fi
2022-09-09 18:00:07 +00:00
iteration = $(( iteration+1))
done
2022-05-20 15:06:41 +00:00
# add the closing brace.
cat >>" $NGINX_CONF_PATH " <<EOL
}
2022-09-09 18:00:07 +00:00
EOL