Deploy a Jekyll site
Jekyll is a static site generator developed in Ruby.
Information and requirements
These elements are to be taken into consideration to follow this article:
- The manipulations are carried out on Rocky Linux 8.
- Throughout this post, we will access the server via its domain name
blog.local
which is related to its local IP address. - In some snippets of code, the domain name
blog.domain.fr
must be replaced by the one you assigned to your public server.
Preliminary steps
Build your site
Once you’re ready to deploy your site, build it.
[operator@blog ~]$ bundler exec jekyll build
Install required utilities
[operator@blog ~]$ sudo dnf -y install tar
Tar your static files
[adrien@laptop blog]$ tar cfJ site.tar.xz _site/
Send it to your server
[adrien@laptop blog]$ scp site.tar.xz blog.local:
Update the system
[operator@blog ~]$ sudo dnf -y update
Install required utilities
[operator@blog ~]$ sudo dnf -y install vim httpd mod_ssl epel-release firewalld
Unzip your files
[operator@blog ~]$ sudo mkdir -p /var/www/blog
[operator@blog ~]$ sudo tar -xJf site.tar.xz --strip-components=1 -C /var/www/blog
Set correct permissions
[operator@blog ~]$ sudo chown -R apache: /var/www/blog
[operator@blog ~]$ sudo find /var/www/blog -type d -exec chmod 0755 {} \;
[operator@blog ~]$ sudo find /var/www/blog -type f -exec chmod 0640 {} \;
HTTPD configurations
General TLS configurations
By adding ServerTokens Prod
directive, you remove the Apache2 version from HTTP headers, it’s a good practice for security reasons.
[operator@blog ~]$ sudo sed -i "352i ServerTokens Prod" /etc/httpd/conf/httpd.conf
Add these headers and the cache configuration for OCSP stapling just after #SSLCryptoDevice ubsec
into /etc/httpd/conf.d/ssl.conf
. Also, set the Diffie-Hellman parameters’ path and the temporary curve used for ephemeral ECDH modes.
# Headers
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
Header always set Referrer-Policy no-referrer
# OCSP stapling
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
# Key exchange
SSLOpenSSLConfCmd DHParameters "/etc/pki/tls/private/dhparam.pem"
SSLOpenSSLConfCmd Curves secp384r1
Next, you must generate the Diffie-Hellman’s parameters. Here, the size of the generated parameters set will be 4096 bits.
[operator@gitea ~]$ sudo openssl dhparam -check -out /etc/pki/tls/private/dhparam.pem -rand /dev/urandom 4096
DH parameters appear to be ok.
Set correct permissions.
[operator@blog ~]$ sudo chmod 440 /etc/pki/tls/private/dhparam.pem
Disable TLS session tickets and enable the addition of OCSP responses to TLS negociation.
[operator@blog ~]$ sudo sed -i "214i SSLSessionTickets Off" /etc/httpd/conf.d/ssl.conf
[operator@blog ~]$ sudo sed -i "215i SSLUseStapling On" /etc/httpd/conf.d/ssl.conf
Accept all protocols except those before TLSv1.2
.
[operator@blog ~]$ sudo sed -i "s/#SSLProtocol.*/SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1/" /etc/httpd/conf.d/ssl.conf
Generate TLS certificate (local server only)
Generate the CA private key
Generate a private key for a curve. Here, I use the curve secp521r1
but you can use another one by executing openssl ecparam -list_curves
.
[operator@blog ~]$ sudo openssl ecparam -check -name secp521r1 -genkey -noout -out /etc/pki/tls/private/CAkey.pem -rand /dev/urandom
checking elliptic curve parameters: ok
Generate the CA certificate
The CA root certificate will have 3650 days (10 years lifetime).
[operator@blog ~]$ sudo openssl req -utf8 -new -x509 -days 3650 -key /etc/pki/tls/private/CAkey.pem -out /etc/pki/tls/certs/CAcert.pem -rand /dev/urandom -subj "/CN=Blog root CA/"
Generate blog private key
Generate a private key for a curve. Here, I use the curve secp384r1
but you can use another one by executing openssl ecparam -list_curves
.
[operator@blog ~]$ sudo openssl ecparam -check -name secp384r1 -genkey -noout -out /etc/pki/tls/private/privkey.pem -rand /dev/urandom
checking elliptic curve parameters: ok
Create a dedicated OpenSSL configuration file
Copy the following content in a file called openssl.cnf
. In CN =
and DNS.1 =
, be sure to put the Gitea domain name, heere blog.local
.
[req]
distinguished_name = req_distinguished_name
req_extensions = req_ext
prompt = no
[req_distinguished_name]
CN = blog.local
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = blog.local
Generate CSR based on the OpenSSL configuration file
[operator@blog ~]$ sudo openssl req -new -key /etc/pki/tls/private/privkey.pem -out /tmp/blog.local.csr -rand /dev/urandom -config openssl.cnf
Generate the X.509 certificate with SAN
Certificate will have 365 days (1 year lifetime).
[operator@blog ~]$ sudo openssl x509 -req -days 365 -in /tmp/blog.local.csr -CA /etc/pki/tls/certs/CAcert.pem -CAkey /etc/pki/tls/private/CAkey.pem -CAcreateserial -out /etc/pki/tls/certs/blog.local.pem -rand /dev/urandom -extensions req_ext -extfile openssl.cnf
Signature ok
subject=CN = blog.local
Getting CA Private Key
Check the SAN extension
[operator@blog ~]$ openssl x509 -in /etc/pki/tls/certs/blog.local.pem -noout -ext subjectAltName
X509v3 Subject Alternative Name:
DNS:blog.local
Don’t forget to add the CA root certificate to your certificate store so that the certificate l inked to the blog.local
domain name is validateur without error. You can retrieve it via this command.
[operator@blog ~]$ cat /etc/pki/tls/certs/CAcert.pem
This command should return something like this.
-----BEGIN CERTIFICATE-----
MIICCjCCAWygAwIBAgIUQPwaBG0VfiHXwaSUwf/5H6ShFjowCgYIKoZIzj0EAwIw
FzEVMBMGA1UEAwwMQmxvZyByb290IENBMB4XDTIyMDgxODEyNTMwMFoXDTMyMDgx
NTEyNTMwMFowFzEVMBMGA1UEAwwMQmxvZyByb290IENBMIGbMBAGByqGSM49AgEG
BSuBBAAjA4GGAAQBDANN8uF+UAhKEQkoG+0O5b9EIVeDTkEZur6nEXnEShP5YDQ6
6OxZKMrcWMGYWsQh/eODPse6on9cr9NjBnDTwl0A8zF5i1+WON4phf0TZP+wU3WZ
eKsYhIqqJuEonPnEmQppdXcvCvxC4sC5yJztb1Qs8Rb8ywAo0zRY+MXV9MlI5qij
UzBRMB0GA1UdDgQWBBTtI4HMf/RnkPuCkWc3k1b4tLzzRDAfBgNVHSMEGDAWgBTt
I4HMf/RnkPuCkWc3k1b4tLzzRDAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMC
A4GLADCBhwJBDN/7VyYSehVdLBU89Z7n9CmDkfxHYG6qNDyUdJ12d/Yz9vH2nsv2
TEz2KWqw/3ZkifowilcMZOEcD4yKdWzGizsCQgGGyiPu8dJfZVR0/iKHhzBU1Wpo
ngHSYUGz511BMwCwCnFUQu7O3OHvkYkePgHvXiAwqDCduJcQV0d68zaLO7Jbmw==
-----END CERTIFICATE-----
Copy this text and paste it in a file named CAcert.pem
, this is the file you have to import in your trust store.
Set correct permissions
[operator@blog ~]$ sudo chmod 440 /etc/pki/tls/private/CAkey.pem
[operator@blog ~]$ sudo chmod 644 /etc/pki/tls/certs/CAcert.pem
[operator@blog ~]$ sudo chmod 440 /etc/pki/tls/private/privkey.pem
[operator@blog ~]$ sudo chmod 644 /etc/pki/tls/certs/blog.local.pem
Virtual host configuration
Create the reverse proxy configuration into /etc/httpd/conf.d/vhost.conf
.
<VirtualHost *:80>
ServerName 192.168.2.143
Redirect permanent / https://blog.local
</VirtualHost>
<VirtualHost *:443>
ServerName 192.168.2.143
Redirect permanent / https://blog.local
</VirtualHost>
<VirtualHost *:443>
DocumentRoot /var/www/blog
ServerName blog.local:443
ServerAlias blog.local
ServerAdmin contact@blog.local
SSLCertificateFile /etc/pki/tls/certs/blog.local.pem
SSLCertificateKeyFile /etc/pki/tls/private/privkey.pem
SSLCACertificateFile /etc/pki/tls/certs/CAcert.pem
Protocols h2 http/1.1
ErrorDocument 404 /404.html
ErrorLog /var/log/blog/error_log
CustomLog /var/log/blog/access_log combined
</VirtualHost>
Request a Let’s Encrypt certificate (public server only)
In case you wish to obtain free certificates (via Let’s Encrypt), two methods are available to you. Luck is on your side, you will find here the method to obtain a certificate from Let’s Encrypt, and here a slightly more advanced method that allows you to obtain a certificate based on elliptic curve cryptography (still via Let’s Encrypt).
The reverse proxy configuration is the exact same. Things you have to modify are the location of the certificate, private key and the chain of trust, but it is documented in the article previously mentionned.
Create the logs directory
[operator@blog ~]$ sudo mkdir -p /var/log/blog
Modify the security context
[operator@blog ~]$ sudo chcon -R -t httpd_sys_content_t /var/www/blog
Modify authorized ports
[operator@blog ~]$ sudo firewall-cmd --add-port={80/tcp,443/tcp} --permanent
[operator@blog ~]$ sudo firewall-cmd --reload
Enable gzip compression
The HTTP server’s module mod_deflate
allows to compress HTML
, CSS
and JS
files into gzip
. Thus you can reduce the load of the transmitted data by up to 70%. It will reduce your website’s loading time.
Copy the following snippet into /etc/httpd/conf.d/mod_deflate.conf
.
<FilesMatch "\.(js|html|css)$">
SetOutputFilter DEFLATE
</FilesMatch>
Enable and start HTTPD service
[operator@blog ~]$ sudo systemctl enable --now httpd