diff --git a/install/apache.sh b/install/apache.sh
new file mode 100644
index 0000000..bb68b63
--- /dev/null
+++ b/install/apache.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/bash
+
+mkdir /srv/servnest/ht
+cp -r /install/http-messages /srv/servnest/ht/http-messages
+chown -R root:root /srv/servnest/ht
+chmod -R u=rX,g=rX,o=rX /srv/servnest/ht
+
+mkdir /srv/servnest/ht/fs
+chown -R $apache:$sftpgo /srv/servnest/ht/fs
+chmod -R u=rX,g=rwX,o= /srv/servnest/ht/fs
+
+mkdir /srv/servnest/ht/uri
+mkdir /srv/servnest/ht/uri/ht.servnest.test
+chown -R $servnest:$apache /srv/servnest/ht/uri
+chmod -R u=rwX,g=rX,o= /srv/servnest/ht/uri
+
+if [[ $OS = "arch" ]]; then
+ rm -r /etc/httpd/*
+ mkdir /etc/httpd/conf/
+ cp -r /install/apache/* /etc/httpd/
+ mv /etc/httpd/httpd.conf /etc/httpd/conf/httpd.conf
+
+ mkdir -p /srv/servnest/ht/usr/lib
+ ln /usr/lib/libc.so.6 /srv/servnest/ht/usr/lib/libc.so.6
+
+ systemctl enable httpd
+fi
+
+if [[ $OS = "debian" ]]; then
+ rm -r /etc/apache2/*
+ cp -r /install/apache/* /etc/apache2/
+ mv /etc/apache2/httpd.conf /etc/apache2/apache2.conf
+ sed -i 's#/usr/lib/httpd/modules/#/usr/lib/apache2/modules/#g' /etc/apache2/apache2.conf
+ sed -i 's#ServerRoot "/etc/httpd"#ServerRoot "/etc/apache2"#' /etc/apache2/apache2.conf
+ sed -i 's/LoadModule unixd_module/#LoadModule unixd_module/' /etc/apache2/apache2.conf
+ sed -i 's/LoadModule mpm_event_module/#LoadModule mpm_event_module/' /etc/apache2/apache2.conf
+ sed -i 's/LoadModule log_config_module/#LoadModule log_config_module/' /etc/apache2/apache2.conf
+ sed -i 's#/var/log/httpd/#/var/log/apache2/#g' /etc/apache2/apache2.conf
+
+ mkdir -p /srv/servnest/ht/lib/x86_64-linux-gnu
+ ln /lib/x86_64-linux-gnu/libgcc_s.so.1 /srv/servnest/ht/lib/x86_64-linux-gnu/libgcc_s.so.1
+ ln /lib/x86_64-linux-gnu/libc.so.6 /srv/servnest/ht/lib/x86_64-linux-gnu/libc.so.6
+fi
+
diff --git a/install/apache/errors.conf b/install/apache/errors.conf
new file mode 100644
index 0000000..d456bbc
--- /dev/null
+++ b/install/apache/errors.conf
@@ -0,0 +1,43 @@
+Alias /http-messages/ "/http-messages/"
+
+
+ The request is malformed. +
+ HTTP400
+
+
diff --git a/install/http-messages/403.html b/install/http-messages/403.html
new file mode 100644
index 0000000..1c2fa6e
--- /dev/null
+++ b/install/http-messages/403.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ + The server refused to process the request for security reasons. +
+ HTTP403
+
+
diff --git a/install/http-messages/404.en.html b/install/http-messages/404.en.html
new file mode 100644
index 0000000..d09c1d5
--- /dev/null
+++ b/install/http-messages/404.en.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ + The server did not find anything at the requested address. +
+404
+
+
diff --git a/install/http-messages/404.fr.html b/install/http-messages/404.fr.html
new file mode 100644
index 0000000..b9748e7
--- /dev/null
+++ b/install/http-messages/404.fr.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ + Le serveur n'a rien trouvé à l'adresse demandée. +
+404
+
+
diff --git a/install/http-messages/405.html b/install/http-messages/405.html
new file mode 100644
index 0000000..c99d58a
--- /dev/null
+++ b/install/http-messages/405.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ + The request method is not supported for this resource. +
+ HTTP405
+
+
diff --git a/install/http-messages/410.html b/install/http-messages/410.html
new file mode 100644
index 0000000..7b44cd6
--- /dev/null
+++ b/install/http-messages/410.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ + The requested resource is not available anymore. +
+ HTTP410
+
+
diff --git a/install/http-messages/418.html b/install/http-messages/418.html
new file mode 100644
index 0000000..fcf0bf9
--- /dev/null
+++ b/install/http-messages/418.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ + Your coffee cannot be brewed because this server is a teapot. +
+ HTTP418
+
+
diff --git a/install/http-messages/500.en.html b/install/http-messages/500.en.html
new file mode 100644
index 0000000..88a41d5
--- /dev/null
+++ b/install/http-messages/500.en.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ + The server encountered an error and is unable to satisfy your request. +
+500
+
+
diff --git a/install/http-messages/500.fr.html b/install/http-messages/500.fr.html
new file mode 100644
index 0000000..25926e4
--- /dev/null
+++ b/install/http-messages/500.fr.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ + Le serveur a rencontré une erreur et ne peut pas répondre à cette requête. +
+500
+
+
diff --git a/install/http-messages/502.html b/install/http-messages/502.html
new file mode 100644
index 0000000..7e55459
--- /dev/null
+++ b/install/http-messages/502.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ + The backend server encountered an error and is unable to satisfy your request. +
+502
+
+
diff --git a/install/http-messages/503.en.html b/install/http-messages/503.en.html
new file mode 100644
index 0000000..7e84963
--- /dev/null
+++ b/install/http-messages/503.en.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ + The server cannot handle the request, because it is overloaded or down for maintenance. +
+503
+
+
diff --git a/install/http-messages/503.fr.html b/install/http-messages/503.fr.html
new file mode 100644
index 0000000..c947e50
--- /dev/null
+++ b/install/http-messages/503.fr.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ + Le serveur ne peut pas répondre à cette requête, car il est surchargé ou en cours de maintenance. +
+503
+
+
diff --git a/install/http-messages/504.html b/install/http-messages/504.html
new file mode 100644
index 0000000..3a3b928
--- /dev/null
+++ b/install/http-messages/504.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ + The backend server did not send a timely response. +
+504
+
+
diff --git a/install/http-messages/unsecure.en.html b/install/http-messages/unsecure.en.html
new file mode 100644
index 0000000..3aca026
--- /dev/null
+++ b/install/http-messages/unsecure.en.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+ + This site does not accept HTTP requests without TLS. +
++ You made a request using HTTP without TLS to the server, which refused this for privacy and security reasons, as unsecure HTTP connections can be watched and modified by any device on the way. +
+
+ You can replace the URI scheme http
by https
to tell your client to make the request using TLS.
+
HTTP 403
+
+
diff --git a/install/http-messages/unsecure.fr.html b/install/http-messages/unsecure.fr.html
new file mode 100644
index 0000000..655cb2b
--- /dev/null
+++ b/install/http-messages/unsecure.fr.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+ + Ce site n'accepte pas les connexions HTTP sans TLS. +
++ Vous avez envoyé une requête HTTP sans TLS au serveur, qui l'a refusée pour des raisons de sécurité et de confidentialité. +
+
+ Vous pouvez remplacer le schéma d'URI http
par https
pour indiquer à votre client de faire la requête avec TLS.
+
HTTP 403
+
+
diff --git a/install/install.sh b/install/install.sh
index 2ef7a8e..b46854a 100644
--- a/install/install.sh
+++ b/install/install.sh
@@ -3,6 +3,7 @@ export sftpgo='sftpgo'
export servnest='servnest'
export knot='knot'
export nginx='nginx'
+export apache='apache'
export tor='tor'
if [[ $OS = "debian" ]]; then
export tor='debian-tor'
@@ -12,6 +13,7 @@ fi
useradd -U -r -s $(which nologin) $nginx
useradd -U -r -s $(which nologin) $servnest
useradd -U -r -s $(which nologin) $sftpgo
+useradd -U -r -s $(which nologin) $apache
# Execute installation steps
source /install/sudo.sh
@@ -20,5 +22,6 @@ source /install/knot.sh
source /install/servnest.sh
source /install/php.sh
source /install/nginx.sh
+source /install/apache.sh
source /install/sftpgo.sh
source /install/certbot.sh
diff --git a/install/nginx.sh b/install/nginx.sh
index 2cb2748..c210cf8 100644
--- a/install/nginx.sh
+++ b/install/nginx.sh
@@ -3,9 +3,7 @@
# Generate default self-signed TLS key pair
openssl req -subj '/' -new -newkey RSA:3072 -days 3650 -nodes -x509 -keyout /etc/ssl/private/servnest.key -out /etc/ssl/certs/servnest.crt
+openssl req -subj '/' -new -newkey RSA:3072 -days 3650 -nodes -x509 -keyout /etc/ssl/private/ht.servnest.test.key -out /etc/ssl/certs/ht.servnest.test.crt
+
rm -r /etc/nginx/*
cp -r /install/nginx/* /etc/nginx/
-
-mkdir /srv/servnest/nginx /srv/servnest/subpath /srv/servnest/subdomain
-chown $servnest:$nginx /srv/servnest/nginx /srv/servnest/subpath /srv/servnest/subdomain
-chmod u=rwX,g=rX,o= /srv/servnest/nginx /srv/servnest/subpath /srv/servnest/subdomain
diff --git a/install/nginx/inc/errors.conf b/install/nginx/inc/errors.conf
index ffc77ff..787b7f5 100644
--- a/install/nginx/inc/errors.conf
+++ b/install/nginx/inc/errors.conf
@@ -1,82 +1,20 @@
recursive_error_pages on;
-# 403 Forbidden
-error_page 403 @403;
-location @403 {
- root /srv/servnest/core/http-errors;
- try_files /403.html =500;
+location /http-messages {
+ proxy_pass http://[::1]:42999;
+ proxy_ignore_client_abort on;
+ proxy_http_version 1.1;
+ proxy_set_header Host $host;
+ proxy_redirect http://$host:42999/ /;
}
-# 404 Not Found
-error_page 404 @local404;
-location @local404 {
- try_files /404.html /404.md /404.gmi @servnest404;
-}
-location @servnest404 {
- root /srv/servnest/core/http-errors;
- try_files /404.php =500;
- index /404.php;
- fastcgi_split_path_info ^(.+\.php)(/.+)$;
- fastcgi_pass unix:/run/php-fpm/servnest.sock;
- include inc/fastcgi.conf;
- fastcgi_index /404.php;
-}
-
-# 405 Method Not Allowed
-error_page 405 @405;
-location @405 {
- root /srv/servnest/core/http-errors;
- try_files /405.html =500;
-}
-
-# 410 Gone
-error_page 410 @410;
-location @410 {
- root /srv/servnest/core/http-errors;
- try_files /410.html =500;
-}
-
-# 418 I'm a teapot
-error_page 418 @418;
-location @418 {
- root /srv/servnest/core/http-errors;
- try_files /418.html =500;
-}
-
-# 500 Internal Server Error
-error_page 500 @500;
-location @500 {
- root /srv/servnest/core/http-errors;
- try_files /500.php /500.en.html =500;
- index /500.php;
- fastcgi_split_path_info ^(.+\.php)(/.+)$;
- fastcgi_pass unix:/run/php-fpm/servnest.sock;
- include inc/fastcgi.conf;
- fastcgi_index /500.php;
-}
-
-# 502 Bad Gateway
-error_page 502 @502;
-location @502 {
- root /srv/servnest/core/http-errors;
- try_files /502.html =500;
-}
-
-# 503 Service Unavailable
-error_page 503 @503;
-location @503 {
- root /srv/servnest/core/http-errors;
- try_files /503.php =500;
- index /503.php;
- fastcgi_split_path_info ^(.+\.php)(/.+)$;
- fastcgi_pass unix:/run/php-fpm/servnest.sock;
- include inc/fastcgi.conf;
- fastcgi_index /503.php;
-}
-
-# 504 Gateway Timeout
-error_page 504 @504;
-location @504 {
- root /srv/servnest/core/http-errors;
- try_files /504.html =500;
-}
+error_page 400 /http-messages/400;
+error_page 403 /http-messages/403;
+error_page 404 /http-messages/404;
+error_page 405 /http-messages/405;
+error_page 410 /http-messages/410;
+error_page 418 /http-messages/418;
+error_page 500 /http-messages/500;
+error_page 502 /http-messages/502;
+error_page 503 /http-messages/503;
+error_page 504 /http-messages/504;
diff --git a/install/nginx/inc/ht-onion.conf b/install/nginx/inc/ht-onion.conf
deleted file mode 100644
index 3855972..0000000
--- a/install/nginx/inc/ht-onion.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-# This configuration file is included by dedicated Onion sites created by ServNest
-
-include inc/ht.conf;
diff --git a/install/nginx/inc/ht-tls.conf b/install/nginx/inc/ht-tls.conf
deleted file mode 100644
index f2591fb..0000000
--- a/install/nginx/inc/ht-tls.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-# This configuration file is included by dedicated DNS and TLS sites created by ServNest
-
-include inc/ht.conf;
-include inc/tls.conf;
diff --git a/install/nginx/inc/ht.conf b/install/nginx/inc/proxy.conf
similarity index 53%
rename from install/nginx/inc/ht.conf
rename to install/nginx/inc/proxy.conf
index 946c3d0..bc8ba2e 100644
--- a/install/nginx/inc/ht.conf
+++ b/install/nginx/inc/proxy.conf
@@ -1,7 +1,14 @@
+include inc/errors.conf;
+
+more_clear_headers "Set-Cookie";
+more_clear_input_headers "Cookie";
+
more_set_headers "Content-Security-Policy : default-src 'none'; style-src 'self' 'unsafe-inline' data:; img-src 'self' data:; font-src 'self' data:; media-src 'self' data:; frame-ancestors 'none'; form-action 'none';";
location / {
- try_files $uri $uri/index.html $uri/index.md $uri/index.gmi =404;
+ proxy_pass http://[::1]:42999/;
+ proxy_ignore_client_abort on;
+ proxy_http_version 1.1;
+ proxy_set_header Host $host;
+ proxy_redirect http://$host:42999/ /;
}
-
-include inc/errors.conf;
diff --git a/install/nginx/inc/tls.conf b/install/nginx/inc/tls.conf
deleted file mode 100644
index b18bb6d..0000000
--- a/install/nginx/inc/tls.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-ssl_protocols TLSv1.3;
-ssl_ecdh_curve X25519:X448;
diff --git a/install/nginx/inc/types.conf b/install/nginx/inc/types.conf
index a1342c5..50bfe56 100644
--- a/install/nginx/inc/types.conf
+++ b/install/nginx/inc/types.conf
@@ -43,7 +43,7 @@ types {
application/vnd.oasis.opendocument.chart-template otc;
application/vnd.oasis.opendocument.database odb;
application/vnd.oasis.opendocument.formula odf;
- application/vnd.oasis.opendocument.formula-template otf;
+ application/vnd.oasis.opendocument.formula-template odft;
application/vnd.oasis.opendocument.graphics odg;
application/vnd.oasis.opendocument.graphics-template otg;
application/vnd.oasis.opendocument.image odi;
@@ -58,27 +58,30 @@ types {
application/vnd.oasis.opendocument.text-web oth;
# Font
+ font/ttf ttf;
+ font/otf otf;
font/woff woff;
font/woff2 woff2;
# Image
+ image/svg+xml svg svgz;
image/png png;
image/gif gif;
image/jpeg jpeg jpg;
- image/svg+xml svg svgz;
image/webp webp;
image/avif avif;
+ image/jxl jxl;
image/openraster ora;
# Audio
- audio/opus opus;
- audio/ogg ogg oga spx;
- audio/mpeg mp3;
- audio/webm weba;
- audio/flac flac;
+ audio/opus opus;
+ audio/ogg ogg oga spx;
+ audio/mpeg mp3;
+ audio/webm weba;
+ audio/flac flac;
# Video
- video/ogg ogv;
- video/webm webm;
- video/mp4 mp4;
+ video/ogg ogv;
+ video/webm webm;
+ video/mp4 mp4;
}
diff --git a/install/nginx/nginx.conf b/install/nginx/nginx.conf
index 4b85a78..0291288 100644
--- a/install/nginx/nginx.conf
+++ b/install/nginx/nginx.conf
@@ -27,29 +27,29 @@ http {
gzip_static on;
# Logging
- map $http_cookie $loggable {
- "" 0;
- default 1;
- }
- log_format servnest '|$time_local| [$remote_addr]@$server_name {$ssl_protocol $ssl_cipher} $status $body_bytes_sent "$request" "$http_user_agent"';
error_log /var/log/nginx/error.log notice;
- access_log /var/log/nginx/access.log servnest if=$loggable;
+ access_log off;
# Disable useless/dangerous features
etag off;
server_tokens off;
- more_clear_headers Server;
+ more_clear_headers "Server";
+
+ # Delete unused request headers
+ more_clear_input_headers "User-Agent";
+ more_clear_input_headers "Referer";
+ more_clear_input_headers "From";
+ more_clear_input_headers "DNT";
# Basic security headers
more_set_headers "Referrer-Policy : no-referrer";
- more_set_headers "Strict-Transport-Security : max-age=94608000; includeSubDomains; preload";
+ more_set_headers "Strict-Transport-Security : max-age=31536000";
more_set_headers "X-Content-Type-Options : nosniff";
- #more_set_headers "X-XSS-Protection : 1; mode=block";
- #more_set_headers "X-Download-Options : noopen";
- #more_set_headers "X-Permitted-Cross-Domain-Policies : none";
- #more_set_headers "X-Frame-Options : DENY";
- # Basic TLS settings
+ # TLS
+ ssl_protocols TLSv1.3 TLSv1.2;
+ ssl_ciphers ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384;
+ ssl_ecdh_curve X25519:X448:prime256v1;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
diff --git a/install/nginx/sites/default-server.conf b/install/nginx/sites/default-server.conf
deleted file mode 100644
index 769b8a4..0000000
--- a/install/nginx/sites/default-server.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-# This server block is reached only if no other server block can match, and displays some explanations
-
-server {
- listen [::1]:42443 ssl http2 default_server;
- listen 127.0.0.1:42443 ssl http2 default_server;
-
- ssl_certificate /etc/ssl/certs/servnest.crt;
- ssl_certificate_key /etc/ssl/private/servnest.key;
-
- ssl_stapling off;
-
- location / {
- root /srv/servnest/core/http-errors;
- try_files /index.php =500;
- index index.php;
- fastcgi_split_path_info ^(.+\.php)(/.+)$;
- fastcgi_pass unix:/run/php-fpm/servnest.sock;
- include /etc/nginx/inc/fastcgi.conf;
- }
-
- include /etc/nginx/inc/tls.conf;
- include /etc/nginx/inc/errors.conf;
-
- more_set_headers "Content-Security-Policy : default-src 'none'; frame-ancestors 'none';";
-}
diff --git a/install/nginx/sites/dns.conf b/install/nginx/sites/dns.conf
new file mode 100644
index 0000000..ff0be45
--- /dev/null
+++ b/install/nginx/sites/dns.conf
@@ -0,0 +1,10 @@
+# DNS+TLS site access
+server {
+ listen [::1]:42443 ssl http2 default_server;
+ listen 127.0.0.1:42443 ssl http2 default_server;
+
+ ssl_certificate /etc/ssl/certs/${ssl_server_name}.crt;
+ ssl_certificate_key /etc/ssl/private/${ssl_server_name}.key;
+
+ include inc/proxy.conf;
+}
diff --git a/install/nginx/sites/http.conf b/install/nginx/sites/http.conf
index 6b2a58f..8711d83 100644
--- a/install/nginx/sites/http.conf
+++ b/install/nginx/sites/http.conf
@@ -4,20 +4,13 @@ server {
listen [::1]:42080 default_server;
listen 127.0.0.1:42080 default_server;
+ include inc/errors.conf;
+
location / {
return 403; # Don't allow unsecure HTTP requests
}
- # Display an explanation page
- error_page 403 @http403;
- location @http403 {
- root /srv/servnest/core/http-errors;
- try_files /unsecure.php =500;
- index unsecure.php;
- fastcgi_split_path_info ^(.+\.php)(/.+)$;
- fastcgi_pass unix:/run/php-fpm/servnest.sock;
- include inc/fastcgi.conf;
- }
+ error_page 403 /http-messages/unsecure;
location /.well-known/acme-challenge {
root /srv/servnest/acme/;
diff --git a/install/nginx/sites/interface.conf b/install/nginx/sites/interface.conf
index 8964e72..917e66d 100644
--- a/install/nginx/sites/interface.conf
+++ b/install/nginx/sites/interface.conf
@@ -1,5 +1,6 @@
# This server block is the publicly exposed ServNest control interface
+log_format servnest '|$time_local| [$ip_start]@$server_name $status $body_bytes_sent "$request"';
server {
listen [::1]:42443 ssl http2;
listen 127.0.0.1:42443 ssl http2;
@@ -7,7 +8,6 @@ server {
root /srv/servnest/core;
- include inc/tls.conf;
include inc/errors.conf;
more_set_headers "Content-Security-Policy : default-src 'none'; style-src 'self'; frame-ancestors 'none'; form-action 'self';";
@@ -29,7 +29,18 @@ server {
alias /srv/servnest/docs;
}
+ access_log /var/log/nginx/servnest-access.log servnest if=$loggable;
+
# For a public server, these should point to a Let's Encrypt-trusted key pair
ssl_certificate /etc/ssl/certs/servnest.crt;
ssl_certificate_key /etc/ssl/private/servnest.key;
}
+map $request_method $loggable { # Log only POST requests
+ "POST" 1;
+ default 0;
+}
+map $remote_addr $ip_start {
+ "~^(?P