As part of berrynews.org, I have been battling for quite some time with certificates. I was so upset at one point that I even blocked port :80
at fw --firewall level and stopped all traffic on http
.
But that is not the way things should be handled, and even though it took me about 3 days to figure it out, now, I can proudly say that I have the recipe for success.
Here is the specific situation the article will tackle:
invalid
for www.berrynews.orgdo not exist
and when you try to access them you get an error
Outcome:
www
and non-www
versions of a domain, as well as for subdomains, see below for detailed steps:Domain and DNS Setup:
Ensure that your domain and subdomains are properly set up in your DNS settings. You should have A
records pointing to both the root domain (@
) and the www
version to your server's IP address.
For subdomains, you should have A
or CNAME
records pointing each subdomain to the server's IP address or the main domain, respectively.
DNS setup example with emphasis on: 2xA → server IP, 2x CNAME
for each subdomain
; Domain: berrynews.org
; Exported (y-m-d hh:mm:ss): 2023-11-08 13:03:00
;
; This file is intended for use for informational and archival
; purposes ONLY and MUST be edited before use on a production
; DNS server.
;
; In particular, you must update the SOA record with the correct
; authoritative name server and contact e-mail address information,
; and add the correct NS records for the name servers which will
; be authoritative for this domain.
;
; For further information, please consult the BIND documentation
; located on the following website:
;
; http://www.isc.org/
;
; And RFC 1035:
;
; http://www.ietf.org/rfc/rfc1035.txt
;
; Please note that we do NOT offer technical support for any use
; of this zone data, the BIND name server, or any other third-
; party DNS software.
;
; Use at your own risk.
$ORIGIN berrynews.org.
; SOA Record
@ 3600 IN SOA ns35.domaincontrol.com. dns.jomax.net. (
2023110806
28800
7200
604800
3600
)
; A Record
@ 600 IN A 94.211.67.63
www 600 IN A 94.211.67.63
; NS Record
@ 3600 IN NS ns35.domaincontrol.com.
@ 3600 IN NS ns36.domaincontrol.com.
; CNAME Record
crypto 3600 IN CNAME @
edu 3600 IN CNAME @
www.crypto 3600 IN CNAME crypto.berrynews.org.
www.edu 3600 IN CNAME edu.berrynews.org.
Web Server Configuration:
Configure your web server (Apache, Nginx, etc.) to serve both the www
and non-www
versions of your domain, as well as any subdomains. This usually involves setting up server blocks or virtual hosts for each.
Here is how /etc/apache2/sites-enabled/000-default.conf
should look like, with emphasis on ServerName
, ServerAlias
and Rewrite*
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
ServerName berrynews.org
ServerAlias www.berrynews.org
DocumentRoot /var/www/html/
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.berrynews\.org [NC,OR]
RewriteCond %{HTTP_HOST} ^berrynews\.org [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>
<VirtualHost *:80>
ServerName edu.berrynews.org
ServerAlias www.edu.berrynews.org
DocumentRoot /var/www/html/edu
<Directory /var/www/html/edu>
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
allow from all
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.edu.log
CustomLog ${APACHE_LOG_DIR}/access.edu.log combined
</VirtualHost>
<VirtualHost *:80>
ServerName crypto.berrynews.org
ServerAlias www.crypto.berrynews.org
DocumentRoot /var/www/html/crypto
<Directory /var/www/html/crypto>
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
allow from all
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.crypto.log
CustomLog ${APACHE_LOG_DIR}/access.crypto.log combined
# Add Rewrite rules here if you want to force HTTPS for the crypto subdomain
RewriteEngine on
RewriteCond %{SERVER_NAME} =crypto.berrynews.org [OR]
RewriteCond %{SERVER_NAME} =www.crypto.berrynews.org
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
Here is how /etc/apache2/sites-enabled/000-default-le-ssl.conf
should look like, with emphasis on ServerName
, ServerAlias
and SSLCert*
Replace berrynews.org with your own domain ++ you can skip the SSLCert; it will automatically be added by certbot.
<IfModule mod_ssl.c>
<VirtualHost *:443>
#Header set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self';"
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
ServerName berrynews.org
ServerAlias www.berrynews.org
DocumentRoot /var/www/html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/berrynews.org/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/berrynews.org/privkey.pem
</VirtualHost>
</IfModule>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName edu.berrynews.org
ServerAlias www.edu.berrynews.org
DocumentRoot /var/www/html/edu
<Directory /var/www/html/edu>
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
allow from all
Require all granted
</Directory>
ErrorLog /var/log/apache2/error.edu.log
CustomLog /var/log/apache2/access.edu.log combined
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/edu.berrynews.org/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/edu.berrynews.org/privkey.pem
</VirtualHost>
</IfModule>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName crypto.berrynews.org
ServerAlias www.crypto.berrynews.org
DocumentRoot /var/www/html/crypto
<Directory /var/www/html/crypto>
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
allow from all
Require all granted
</Directory>
ErrorLog /var/log/apache2/error.crypto.log
CustomLog /var/log/apache2/access.crypto.log combined
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/crypto.berrynews.org/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/crypto.berrynews.org/privkey.pem
</VirtualHost>
</IfModule>
Obtain SSL Certificates:
Use a tool like Let's Encrypt's Certbot to obtain SSL certificates. You can include multiple domains and subdomains in a single certificate by using the -d
flag multiple times, like so:
sudo certbot --apache -d example.com -d www.example.com -d subdomain.example.com
Follow the Certbot prompts to complete the validation process and install the certificates.
Here’s a snippet from my history
in-hash:
1144 sudo certbot --apache -d berrynews.org -d www.berrynews.org
1150 sudo certbot --apache -d berrynews.org -d www.berrynews.org
1176 sudo certbot --apache -d crypto.berrynews.org -d www.crypto.berrynews.org
1190 sudo certbot --apache -d crypto.berrynews.org -d www.crypto.berrynews.org
1197 sudo certbot --apache -d edu.berrynews.org -d www.edu.berrynews.org
1202 sudo certbot --apache -d edu.berrynews.org -d www.edu.berrynews.org
Web Server SSL Configuration:
SSLEngine on
directive for Apache or the equivalent for other web servers.
Include a ServerName
directive for the non-www
version and a ServerAlias
directive for the www
version. For subdomains, set up a separate virtual host or server block with its ServerName
.
This has been tackled at point 2, if point 3 fails remove SSL certificates from ssl.conf
Redirection Rules:
Implement redirection rules in your server configuration to redirect HTTP traffic to HTTPS, and optionally redirect www
to non-www
or vice versa, based on your preference.
This has been tackled at point 2, use the example from .conf file
Test Configuration:
After making changes to your web server configuration, always test to make sure there are no syntax errors. For Apache, you can use:
sudo apachectl configtest
If the syntax is OK, restart your web server to apply the changes.
# example output
root@berrynews:/home/ubuntu# sudo apachectl configtest
Syntax OK
Verification:
Verify that your domains and subdomains are correctly serving content over HTTPS by using curl
or by visiting them in a web browser.
You can also use online tools to test your SSL setup, such as SSL Labs' SSL Test.
curl -Iv https://berrynews.org
curl -Iv https://www.berrynews.org
curl -Iv https://edu.berrynews.org
curl -Iv https://www.edu.berrynews.org
curl -Iv https://crypto.berrynews.org
curl -Iv https://www.crypto.berrynews.org
The curl
response should return 200!
curl -Iv https://www.crypto.berrynews.org
* Trying 94.211.67.63:443...
* Connected to www.crypto.berrynews.org (94.211.67.63) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: CN=crypto.berrynews.org
* start date: Nov 8 18:47:08 2023 GMT
* expire date: Feb 6 18:47:07 2024 GMT
* subjectAltName: host "www.crypto.berrynews.org" matched cert's "www.crypto.berrynews.org"
* issuer: C=US; O=Let's Encrypt; CN=R3
* SSL certificate verify ok.
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> HEAD / HTTP/1.1
> Host: www.crypto.berrynews.org
> User-Agent: curl/7.81.0
> Accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Date: Wed, 08 Nov 2023 20:43:39 GMT
Date: Wed, 08 Nov 2023 20:43:39 GMT
< Server: Apache/2.4.52 (Ubuntu)
Server: Apache/2.4.52 (Ubuntu)
< Last-Modified: Wed, 08 Nov 2023 20:38:01 GMT
Last-Modified: Wed, 08 Nov 2023 20:38:01 GMT
< ETag: "14585-609aa103f57f4"
ETag: "14585-609aa103f57f4"
< Accept-Ranges: bytes
Accept-Ranges: bytes
< Content-Length: 83333
Content-Length: 83333
< Vary: Accept-Encoding
Vary: Accept-Encoding
< Content-Type: text/html
Content-Type: text/html
<
* Connection #0 to host www.crypto.berrynews.org left intact
Renewal Setup:
Ensure that automatic renewal of certificates is set up. Certbot usually does this for you by creating a cron job or systemd timer.
Firewall Configuration:
Make sure your firewall is configured to allow HTTPS traffic on port 443.
Monitor and Maintain:
By point 3 with certificate generation, you should already be done.
Hope this helped, and feel free to reach out if you have any questions.
If you liked the article & would like to support content creators such as myself,
Make sure to:
🔔 Follow me Bogdan Tudorache