Signed-off-by: Marc S. Weidner <cendev@coresecret.eu>
Table of Contents
- CISS.2024.hardened.webstack
CISS.2024.hardened.webstack
Centurion Intelligence Consulting Agency Information Security Standard 2024
Debian Bookworm Hardening Webstack Setup Script
Mainline Version 5.0
V5.08.128.2024.10.14
This is a digitally signed, self-verifying shell script for setting up an all-inclusive LAMP environment that relies on the most secure ciphers and follows the latest best practices in webserver hardening to achieve a quadruple A+ rating at Qualys SSL Labs, Mozilla Observatory, immuniweb, Probely; incl. HSTS Preload preparation and HTTP/3 and QUIC support. Letsencrypt CA has been replaced by the Norwegian CA buypass.no, which supports 180-day free TLS certificates.
Check out more Centurion Net Services | coresecret.eu DNS Resolver | Centurion Net Status | Centurion Meet | Contact me
Please note: All my signing keys are contained in a HSM and the signing environment is air gapped. Next step: move to a room gapped environment ^^
Please read carefully before installation!
Key Words
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14], [RFC2119], [RFC8174] when, and only when, they appear in all capitals, as shown here.
Quick start
- You SHOULD check Prerequisites before installation.
- You MUST be root to run this script.
apt install wget --no-install-recommends -y
mkdir /root/server-scripts
cd /root/server-scripts
curl --proto '=https' --tlsv1.3 -sSf https://cendev.eu/marc.weidner/CISS.2024.hardened.webstack/raw/branch/main/webstack.conf -o webstack.conf
if echo '759e38d810bfe2b97eb6f4b563ef45cfe474aae702eb098c92cbb3b82f606f0aed312879973a261c43007f9caca3b570b4323afcaae801a54db24f03e01585bf webstack.conf' | sha512sum -c; then
chmod 0600 webstack.conf
else
echo "SHA-512 checksum is incorrect! You MUST NOT proceed. You SHOULD contact the author please."
yes | rm -rf webstack.conf
fi
curl --proto '=https' --tlsv1.3 -sSf https://cendev.eu/marc.weidner/CISS.2024.hardened.webstack/raw/branch/main/webstack.sh -o webstack.sh
if echo '3f23ec731084b16179a7c90ce6dd32511c0c98bbd286116e545ba0daf5b38fd404809ecbc0d61f2e9fa271bdb1fd714b321e6b50174b6df9f247e22da2fafdad webstack.sh' | sha512sum -c; then
chmod 0700 webstack.sh
else
echo "SHA-512 checksum is incorrect! You MUST NOT proceed. You SHOULD contact the author please."
yes | rm -rf webstack.sh
fi
You MUST edit webstack.conf before you start the script. Then run:
./webstack.sh --install
or
./webstack.sh --install --debug
for detailed debugging information logged in /root/webstack/log/debug_log_$SCRIPT_START.log.
- Select the NIC, if applicable, and you will be prompted to edit webstack.conf to suit your needs.
- For detailed installation instructions for Contabo, Hetzner, Netcup and Proxmox installations, please see Main Installation
- Check the pre-selected ciphers
ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-ECDSA-CHACHA20-POLY1305,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-RSA-CHACHA20-POLY1305according to your needs: https://ciphersuite.info/
Background of this script
Why I use my special CISS.2024 LAMP webstack configuration?
When it comes to setting up LAMP stacks, I focus on nginx as a standalone webserver or proxy, and secondly on apache, as well as MariaDB, PHP, Redis and PHPMyAdmin for seemless administration. In addition, a full integration of acme.sh and a setup to use only buypass.no as CA for this extended LAMP stack guarantees as little information leakage to non-EEA countries as possible. Finally, this LAMP stack is managed to take advantage of the most secure ciphers available and is hardened by following the latest best practices.
In a world where web applications are increasingly the focus of security threats, it is crucial to have a robust and secure server infrastructure. I have chosen a special LAMP webstack configuration that meets the CISS.2024 security standards. Here are the reasons for my choice.
-
Exclusive use of FOSS: My entire webstack configuration is based exclusively on free and open-source software (FOSS). This means that I do not have to rely on closed software, which not only increases transparency but also improves security, as the source code can be checked by the community.
-
Fully secured according to CISS.2024 security standards: The configuration meets the latest security standards according to CISS.2024 (Cybersecurity International Standard for Secure Systems). This ensures that all components of my infrastructure meet the highest security requirements.
-
Use of the strongest encryption algorithms: Only the strongest encryption algorithms available are used in my LAMP configuration. This ensures that all data transfers are optimally protected.
-
Nginx for superior speed and website management: Nginx is known for its outstanding speed and efficient handling of web requests. It enables fast and reliable delivery of websites and web applications.
-
Hardened Nginx configuration: The Nginx configuration and the service itself are hardened against common and more complex attacks. This includes measures such as special configurations that provide protection against DDoS attacks, SQL injections and other threats.
-
Buypass.no CA for TLS encryption: For TLS encryption, I use certificates from Buypass.no, a certification authority based in the European Economic Area (EEA). This ensures that data transfers are not only secure, but also subject to the strict data protection regulations of the EU.
-
PHPMyAdmin for easy and secure database management: PHPMyAdmin is used for convenient database management. It is not only user-friendly, but also specially hardened and protected by additional authentication methods to prevent unauthorised access.
With these carefully selected and configured components, my custom CISS.2024 LAMP web stack configuration ensures a robust, secure and efficient infrastructure for my web applications. This gives me the assurance that my systems are optimally protected against threats while maintaining the highest levels of performance and usability.
In short, I wanted to automate the installation of a state-of-the-art LAMP stack that could guarantee a quadruple A+ rating from Qualys SSL Labs, Mozilla Observatory, immuniweb, Probely and was also ready for HSTS preloading.
Upcoming Features
tba
Features of the script
-
The script and all modules and assets downloaded by my scripts are cryptographically signed with my private OpenPGP key, see the public key fingerprint here, which resides in an HSM. All signing operations are performed on an air-gapped system. Help me move to the next level of security: a room-gapped signing environment. All cryptographic verification operations can be disabled for easy and convenient script editing. A comprehensive list of all my keys and certificates in use is available here via DANE/TLSA and DNSSEC secured
https onlyandhttps preloadedwebsite. -
If there are any errors in the verification process of cryptographically signed scripts, assets and modules, the script will automatically fail immediately.
-
Advanced error trap function. Returns exit code, line number and module name both on screen and in the error log file.
-
All assets are signed by PGP and via the signed commit on my DNSSEC and TLSA secured Gitea instance.
-
Detailed logs available at
/root/webstack/logs, including logging of user input (without logging of any credentials to be clear) and coloured log file. -
Most backed up files are now moved to the central backup directory (except some php files for better handling context). No files are overwritten: see bash environment settings below.
-
Select the trust level of the signing key I have provided.
-
For security reasons, the bash history is also deleted after the setup routine.
-
Take advantage of the following bash error handling options:
set -o errexit # Exit script when a command exits with non-zero status, same as "set -e".
set -o errtrace # Any trap on ERR are inherited in a subshell environment.
set -o functrace # Any trap on DEBUG and RETURN are inherited in a subshell environment.
set -o nounset # Exit script on use of an undefined variable, same as "set -u".
set -o pipefail # Makes pipeline return the exit status of the last command in the pipe that failed.
set -o noclobber # Prevent overwriting.
set +o history # Temporarily turn off history, to avoid sensitive information leakage.
Features
-
This script will retrieve all RSA-4096 bit leaf certificates for
your-domain.tldandphpmyadmin.your-domain.tldwith a validity of 180 days. -
nginx hardening:
- nginx setup - only the strongest ciphers are selected:
ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-ECDSA-CHACHA20-POLY1305,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-RSA-CHACHA20-POLY1305. - nginx setup - only the strongest elliptic curves are chosen:
X448,secp521r1,secp384r1. - nginx setup - all supported http headers are pre-selected to ensure maximum security against common web attacks.
- nginx is built against the latest version of the OpenSSL library and includes GeoIP2 database support.
- nginx rate limiting will be enabled if you provide dedicated IPv4 and IPv6 addresses for Jump Host, Bastion or VPN exitnode.
- nginx setup - only the strongest ciphers are selected:
-
PHP fpm status page is enabled (https://yourdomain.tld/status) and secured by auth access and rate limiting (if applicable).
-
Hardened fail2ban nginx setup, including configuration of the following jails and preconfigured bantime of 1 day.:
- http-auth
- bad-request
- botsearch
- nginx-directory-listing
- nginx-rate-limit
-
Hardened Wordpress environment, ready to use:
- Auth and rate limit protection wp-login.php
- Auth and rate limit protection xmlrpc.php
- Disallow access to important files (HTTP response status code 444 "Connection Closed Without Response")
- Disable direct access of any *.php files in /wp_includes folder (HTTP response status code 444 "Connection Closed Without Response")
- Disable direct access of any *.php in /wp_content folder (HTTP response status code 444 "Connection Closed Without Response")
- Disable direct access to cache directory (HTTP response status code 444 "Connection Closed Without Response")
-
Pre-configured http-auth setup and default enable when PHPMyAdmin setup is selected.
-
Hardened PHPMyAdmin installation if you choose to install it, incl:
- /libraries/ protection.
- /setup/lib/ protection.
- /setup/frames/ protection.
-
Redis listens only on localhost and REDISPASS is installed by default.
-
The following components will be installed (as of 14.10.2024):
- acme.sh (powered by buypass)
- Docker 27.3.1
- Docker Compose v2.29.7
- Maria DB LTS 11.4.3
- nginx 1.27.2 / mainline
- PHP 8.3.12
- PHPMyAdmin 5.2.1
- Redis (5:7.0.15-1~deb12u1)
Online Audit Results
- Once installed, the web server will receive a quadruple A+ rating from the following online audit tools:
| Online Audit Provider | Online Audit Rating |
|---|---|
| Qualys SSL Labs | ![]() |
| Mozilla Observatory | ![]() |
| immuniweb | ![]() |
| Probely | ![]() |
Please check out Online Audits for more online tests.
Main Installation
Prerequisites
-
Root Server (recommended: netcup Root VPS RS Series G11 | Hetzner shared AMD VPS CPXnn Series | Hetzner dedicated VPS CCXnn Series | own Proxmox installation).
- AMD 7003 and later CPU are strongly RECOMMENDED for their RAM encyrption fatures:
- Secure Memory Encryption (SME): Encrypts the entire physical memory to protect data from attacks such as cold boot attacks.
- Secure Encrypted Virtualisation (SEV): Extends storage encryption to virtual machines so that each VM has its own encryption key.
- SEV-ES (Secure Encrypted Virtualisation - Encrypted State): Additionally encrypts the CPU registers when a VM is paused or hibernated, providing additional protection.
- SEV-SNP (Secure Encrypted Virtualisation - Secure Nested Paging): Adds additional protection against hypervisor-based attacks and provides an even higher level of security for VMs. It protects the integrity of the pages used by the VM and prevents tampering by the hypervisor.
- AMD 7003 and later CPU are strongly RECOMMENDED for their RAM encyrption fatures:
-
Fully hardened Debian Bookworm installation (RECOMMENDED: CISS.2024.vps.bookworm.hardening).
- Incl. Full-Disk-Encryption.
- Incl.
/boot-Encryption. - Incl. Ephemeral-SWAP-Encryption.
-
fail2ban and ufw installation MUST be ensured.
-
Fully configured FQDN MUST already pointing to the IPv4 and IPv6 of the server in question.
-
You MUST ensure sure that
your-domain.tldand if PHPMyAdmin setup is selected the domainphpmyadmin.your-domain.tldis set up properly. -
You MUST (e.g. Hetzner Firewall) open
80/tcp,443/tcpand443/udpin your firewall. Otherwise buypass.no CA could not proof the ownership ofyour-domain.tldand if selectedphpmyadmin.your-domain.tld. -
The port
443/udpis needed for Quic protocol, so keep in mind that you MUST open this protocol in your firewall as well. -
DNSSEC secured domain is strongly RECOMMENDED.
-
A properly rDNS record is strongly RECOMMENDED, you MUST setup a correct rDNS if you want to set up an MTA.
If your DNS is not set up properly, the script will fail because the buypass.no CA, triggered by
acme.shwill not be able to contact the web server in question to validate your domain ownership.
Tested VPS Provider
Latest Tested and recommended VPS Provider
| Tested & Recommended VPS Provider | Date | Version tested | Notes |
|---|---|---|---|
| Hetzner Shared vCPU (AMD64) CPXn | 15.08.2024 | V5.0.768 | E) 1) 4) 6) 7) |
| Netcup Root-Server Generation 11 | 05.08.2024 | V5.0.256 | E) 1) 2) 3) 4) 5) 6) 7) |
History Tested and recommended VPS Provider
| Tested & Recommended VPS Provider | Date | Version tested | Notes |
|---|---|---|---|
| Contabo Cloud VPS | tba | V4.7.128 | |
| Contabo Storage VPS | tba | V4.7.128 | |
| Hetzner Shared vCPU (AMD64) CPXn | 15.08.2024 | V5.0.768 | E) 1) 4) 6) 7) |
| Hetzner Dedicated vCPU | tba | V4.7.128 | |
| Netcup vServer ARM64 Generation 11 | tba | V4.7.128 | |
| Netcup Root-Server Generation 11 | 05.08.2024 | V5.0.256 | E) 1) 2) 3) 4) 5) 6) 7) |
| Netcup Root-Server Generation 11 | 20.06.2024 | V4.7.128 | E) 1) 2) 3) 4) 5) 6) |
| Generic Proxmox 8.2 based VM | tba | V4.7.128 |
Notes
E) Locale `en_US.UTF-8` tested.
G) Locale `de_DE.UTF-8` tested.
1) acme.sh succesfully retrieved domain.tld buypass.no cert.
2) acme.sh succesfully retrieved phpmyadmin.domain.tld buypass.no cert
3) Docker, Docker Compose installation succesful.
4) nginx auth installation succesful.
5) PHPMyAdmin installation succesful.
6) Updated fail2ban jails: checked.
7) debug mode: checked.
sha512 Hashes
759e38d810bfe2b97eb6f4b563ef45cfe474aae702eb098c92cbb3b82f606f0aed312879973a261c43007f9caca3b570b4323afcaae801a54db24f03e01585bf *webstack.conf
3f23ec731084b16179a7c90ce6dd32511c0c98bbd286116e545ba0daf5b38fd404809ecbc0d61f2e9fa271bdb1fd714b321e6b50174b6df9f247e22da2fafdad *webstack.sh
Server Preparation and Setup
A detailed Tutorial is available at CISS.2024.hardened.webstack Tutorial.
.conf file values
All variables must be entered in double quotes.
#!/bin/bash
###########################################################################################
# Debian Bookworm Hardening Webstack Setup Script Conf File V5.08.128.2024.10.14 #
###########################################################################################
# Copyright (c) 2019 - 2024, Marc Weidner, Centurion Intelligence Consulting Agency #
# https://coresecret.eu/ #
# Licensed under the EUROPEAN UNION PUBLIC LICENCE v. 1.2 https://eupl.eu/1.2/en/ #
###########################################################################################
# https://keys.openpgp.org/vks/v1/by-fingerprint/A6D46A56AE17A185AB0F6DB77095A8A13CBE0FA3 #
# Fingerprint A6D4 6A56 AE17 A185 AB0F 6DB7 7095 A8A1 3CBE 0FA3 ## valid till: 01.01.2031 #
###########################################################################################
# Please change the variables according to your needs #
###########################################################################################
###########################################################################################
# LAMP stack related #
###########################################################################################
ACMEEMAIL="acme.client@domain.tld" # https://github.com/acmesh-official/acme.sh
CURRENTTIMEZONE="Europe/Lisbon" # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
FQDN="fully.qualified.domain.name" # https://en.wikipedia.org/wiki/Fully_qualified_domain_name
IPV4="123.123.123.123"
IPV6="AAAA::FFFF"
JUMPHOST="Yes"
# Only required if JUMPHOST="Yes": For VPN or Bastion Host access to the Web Admin Panel
JUMPHOST_IPV4="123.123.123.123"
JUMPHOST_IPV6="AAAA::FFFF"
#####
MARIADBVERS="11.4" # https://mariadb.org/download/
NGINXAUTHUSER="security" # https://nginx.org/en/linux_packages.html
PHPVERS="8.3" # https://www.php.net/downloads.php
VPSPROVIDER="Netcup"
###########################################################################################
# Docker related #
###########################################################################################
DOCKERINST="Yes"
# Only required if DOCKERINST="Yes":
DOCKERCOMPOSEVERS="v2.29.1" # https://github.com/docker/compose/releases
DOCKERUSER="dockeruser"
###########################################################################################
# Script related #
###########################################################################################
SELFCHECK="Yes"
SELFCHECKDL="Yes"
TRUSTKEY="Yes"
TRUSTLEVEL="5"
###########################################################################################
# PHPMyAdmin related #
###########################################################################################
PHPMAINST="Yes"
# Only required if PHPMAINST="Yes": # https://www.phpmyadmin.net/downloads/
PHPMAUSER="phpmauser"
PHPMAVERS="5.2.1"
###########################################################################################
# ! No changes below this line ! #
###########################################################################################
CONFVERS="V5.08.128.2024.10.14"
MARIADBROOTPASSWORD=$(pwgen -n 32 -B -c -s -1)
NGINXAUTHPASS=$(pwgen -n 32 -B -c -s -1)
PHPMABLOWFISHSECRET=$(pwgen -n 32 -B -c -s -1)
PHPMAPMAPASSWD=$(pwgen -n 32 -B -c -s -1)
PHPMAUSERPASSWD=$(pwgen -n 32 -B -c -s -1)
PHPTIMEZONE=$(sed 's|/|\\/|g' <<< $CURRENTTIMEZONE)
REDISPASS=$(pwgen -n 32 -B -c -s -1)
SLEEPTIMER="1"
ACMEEMAIL
Please specify the email to setup the CA account via acme.sh.
CURRENTTIMEZONE
Allowed values are:
"Europe/Lisbon" or any other specified Timezone (TZ) identifier: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
DOCKERCOMPOSEVERS
Please specify the Docker Compose version to install.
DOCKERINST
Please select if youwant to install Docker and Docker Compose. Allowed values are:
"Yes" or "No"
DOCKERUSER
Please choose the username that should be added to the 'docker' group.
HOSTNAME
Please specify the desired FQDN ot the server. Allowed values are:
any valid FQDN: https://en.wikipedia.org/wiki/Fully_qualified_domain_name
IPV4
Please provide the IPv4 of the server in question.
IPV6
As a good practice, it is recommended that you have entered a PTR record that matches the FQDN that you have set up in the DNS section of your DNS service provider, stating that the following IPv6 convention is used and suggested:
Consider your IPv4 to be: 123.123.123.123
Consider your IPv6 Prefix to be: 2a10:ABCD:1111:FFFF::1/64
Then the server IPv6 is as follows: 2a10:ABCD:1111:FFFF:123:123:123:123/128
For Contabo: Please enter the IPv6 you have entered in the PTR Record section.
For Hetzner: Please enter the IPv6 you have entered in the Networking tab.
For Netcup: Please enter the IPv6 you have specified in the Netcup Server Control Panel.
JUMPHOST
Please specify if you want your new web server to be pre-configured with an additional rate limit for the admin web panel and if you want to whitelist a Bastion / Jump Server / VPN exit node. Allowed values are:
"Yes" or "No"
JUMPHOST_IPV4
In case you are using a Jumphost, VPN-Exitnode, you MUST add here the IPv4 and IPv6 of the respective Jump Server, VPN-Exitnode which will be added to the nginx whitelist.
JUMPHOST_IPV6
In case you are using a Jumphost, VPN-Exitnode, you MUST add here the IPv4 and IPv6 of the respective Jump Server, VPN-Exitnode which will be added to the nginx whitelist.
MARIADBVERS
Please specify the Maria DB version to install.
NGINXAUTHUSER
Please specify the username to set up the nginx web auth module. The password is generated automatically by the script and will be displayed at the end of the script.
PHPVERS
Please specify the PHP version to install.
PHPMAINST
Please select if you want to install PHPMyAdmin.
PHPMAVERS
Please specify the PHPMyAdmin version to install.
PHPMAUSER
Please select the username you will use to login to PHPMyAdmin. The password is generated automatically by the script and will be displayed at the end of the script.
SELFCHECK
Please specify if you want the script to self-verify, or not to self-verify the script and avoid a script verification failure due to an invalid signature or for easy and convenient script editing. Allowed values are:
"Yes" or "No"
TRUSTKEY
Please specify if you want to trust my ed25519 Gitea Signing Key. All my used keys reside in HSM like NitroKey and signing operations are done via an airgapped system. Allowed values are:
"Yes" or "No"
TRUSTLEVEL
Please specify the trust level of the signing key. PGP Trustlevel:
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
Allowed values are:
"5" or "4" or "3"
VPSPROVIDER
Please select the VPS provider you are using. Or use "Generic" for a basic hardening of your generic server or VPS after a freshly installed Debian Bookworm environment including the CISS partition scheme. Allowed values are:
"Contabo" or "Hetzner" or "Netcup" or "Generic"
SLEEPTIMER
This variable is used to set the clear screen routine after each module and is measured in seconds.
Resources
Tutorials
- Work in progress.
Packages related
- https://www.buypass.no/
- https://ciphersuite.info/
- https://www.keylength.com/en/4/
- https://github.com/acmesh-official/acme.sh
- https://github.com/docker
- https://github.com/docker/compose/releases
- https://mariadb.org/download/
- https://mariadb.com/kb/en/documentation/
- https://nginx.org/en/docs/
- https://nginx.org/en/linux_packages.html
- https://www.php.net/downloads
- https://www.php.net/manual/en/intro-whatis.php
- https://www.phpmyadmin.net/
- https://www.phpmyadmin.net/downloads/
- https://www.tenable.com/audits/CIS_NGINX_v2.0.1_Level_1_Proxy
- https://www.tenable.com/audits/CIS_NGINX_v2.0.1_Level_1_Webserver
Bash related
- https://www.gnu.org/software/bash/manual/
- https://www.shellcheck.net/
- https://explainshell.com/
- https://google.github.io/styleguide/shellguide.html
- https://github.com/mvdan/sh
- https://gist.github.com/Potherca/4f4ce1c8d4bcf4cd4aab
Online Audits
- https://www.ssllabs.com/ssltest/
- https://observatory.mozilla.org/
- https://www.immuniweb.com/ssl/
- https://securityheaders.com/
- https://hstspreload.org/
- https://http3check.net/
- https://www.hardenize.com/
- https://cryptcheck.fr/
- https://www.tls-check.de/de
Acknowledgements
I would like to express my sincere gratitude to Mr Who-wants-to-live-forever for his gracious support and insightful and profound criticism.
Changelog
Available at: CHANGELOG.md
Screenshots
Available at: SCREENSHOTS.md
Security Policy
Available at: SECURITY.md
Troubleshooting
Available at: TROUBLESHOOTING.md
no tracking | no logging | no advertising | no profiling | no bullshit



