To avoid certificate errors, you need the pi to send a certificate which matches the domain used. There are two approaches to this:
- Use one certificate for both domains, installed on both the pi and main server. It doesn't matter which domain the client used in its query, the certificate will match.
- Choose a certificate the client expects and send that.
Option 1 is easier and common practice. Look at the certificate for google.com! Both the pi and the main server will have the same certificate (for both domains) installed. In order to get such a certificate from Let's Encrypt, you will need the main server to run a website for the pi's dynamic domain also and use one certbot command to verify control of both domains at once. The main server's site for the dyndns name need not host the content from the pi - it's just there so Let's Encrypt can verify you have control of that site (you can even turn off that site between renewals).
Sample Certbot command for this (run on the main web server):
letsencrypt certonly --webroot --csr request.csr -w /http/pisite/www -d mypi.spdyn.de
-w /http/mainwebsite/www -d maindomain.de
Where request.csr uses either domain as the CN and has both domains in the SANs field, /http/pisite/www refers to a local directory you would create for another website on the current server bound to the pi's dynamic name, and /http/mainwebsite/www is the existing directory of your main website.
Option 2 is more involved but produces a 'cleaner' result: the client gets a certificate which matches the domain they typed. On the raspberry pi, run nginx with the stream module (or equivalent) which, when a TLS connection is opened: examines the SNI field (without accepting the TLS connection), and based on the domain included there, chooses which upstream to forward the connection to. This lets you choose how you want to handle requests made of the main domain on the external port forwarded to the raspberry pi. You can send them to the main web server just as if they were made on the correct port, you can send them to some other port on the pi (ie Nextcloud, or anything else), you can terminate them with the same nginx instance and show whatever page you like, or simply close the connection. The choice is yours.
Here is a sample configuration for this method:
stream/sni-switch.conf
# Listen on 443, and on new connection:
# if the SNI is mapped herein, handle it on this Nginx
# else, forward the whole session to 192.168.1.80:443 (TCP passthrough, no decryption)
upstream mainwebserver {
server 192.168.1.80:443;
}
upstream local_https {
server 127.0.0.1:1443;
}
map $ssl_preread_server_name $name {
default mainwebserver;
pisite.spdyn.de local_https;
}
server {
listen 443;
ssl_preread on;
proxy_pass $name;
}
And in nginx.conf
load_module /usr/lib/nginx/modules/ngx_stream_module.so;
stream {
include /etc/nginx/stream/sni-switch.conf;
}
...
To do this with Apache, see this. A sample configuration from which might look like this:
<VirtualHost *:*>
ProxyPreserveHost On
ProxyPass "/" "http://192.168.1.80/"
ProxyPassReverse "/" "http://192.168.1.80/"
ServerName maindomain.de
</VirtualHost>