How to set up Apache2 to let Let's Encrypt certbot find HA VM?

'm running Debian 13 (stable) on an AMD64 system.

I’m using wildcard Let’s Encrypt certificates on my server for some services I’m running on it (e.g. nextcloud). This part works. However, I also have a Home Assistant VW running it. Currently I’m using my router to redirect a specific port to that VM’s IP address but this only works for http and not https.

I can’t get a certificate from Let’s Encrypt certbot because it wants port 80 to go to the host. I could, I suppose, temporarily redirect all port 80 traffic to the VM to get the certificate then continue use the specific port to access the VM. However, that’s clumsy and also probably means I have to keep doing it every time I want to renew the certificate.

I found an answer to a similar problem HTTP & HTTPS Apache redirect to internal IP Virtual Machine but it’s 10 years old. While it looks like it would allow me to use the wildcard certificates, I can’t get it to work on my server. When I try to access the VM through port 80, I get a 503 error. If I add the port that I use to access the VM to the config, I get a 400: bad request error.

Here’s the virtual host config I am trying (the port # would be added to the proxypass: IP addresses)

<VirtualHost *:80>
    ServerAdmin <my email>
    ServerName ha.<my domain>
    redirect permanent / https://ha.<my domain>/
</VirtualHost>

<VirtualHost *:443>
    # SSL
    SSLEngine on
    SSLProxyEngine on
    SSLCertificateFile /etc/letsencrypt/live/<my domain>/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/<my domain>/privkey.pem
    # Basics
    ServerName ha.<my domain>
    # Proxy
    ProxyPreserveHost On
    ProxyRequests off
    SSLProxyEngine On
    ProxyPass / http://192.168.1.38/
    ProxyPassReverse / http://192.168.1.38/
</VirtualHost>

And yes, I have enabled the site and restarted the Apache2 server.

Any ideas on what is going wrong? Thanks.

Internally (LAN) I use caddy. I have domain specifically for LAN

Caddy uses certbot to get my letsencrypt cert.
Caddy has dns module that verifies with domain without port 80 file verification process so in this case I have no open port to caddy

I could have caddy do same to get domain for my external domain and just share with my nginx proxy but currently have chosen not to do this

If you already have a wildcard certificate, then use that.

You’ve missed the point a little. This setup is supposed to let me use the wildcard certificates by handling the https with the Apache2 server. However, that means that Apache2 has to be able to redirect the incoming http request to a server only known by its (local) IP address.

Virtual Hosts in Apache2 normally specify a document root for their site, not an IP address. Despite it being something I would think would be fairly common, I can’t find much in the way of documentation on how to do this - mostly the decade-old post I referred to,

The question’s title is from an early attempt to resolve this, which is why it refers to the certbot.

I think you complicate things a lot.
A certificate is bound to the domain name, not a server, so you can just use the Apache server to get it and copy it to where else you need it.
Even better would be to use DNS challenge instead of HTTP challenge, then all the issues are solved.
I use Cloudflares DNS service, which is free for this.

1 Like

Methinks you don’t understand the complexity of the issue. :wink: I have used the Apache server to get the wildcard cert. That is the easy part. Apache also handles the switch from http to https, which allows traffic to come to ha. without the need for opening port 8123 on my router.

Copying the certs to HA would need to be done regularly so a better option would be to export the cert folder and mount it in HA. However HA doesn’t use /etc/fstab to mount shares. The file is just a stub that gets overwritten when HA starts

If there is a simple way to copy files to or from HA, it escapes me. And doing so in an automated fashion is even trickier. I did get the certificates copied to HA at one point and put them in the folder the LetsEncrypt add-on creates (/mnt/data/supervisor/addons/data/cor_letsencrypt/letsencrypt/ but that didn’t work. And the process to do the copy is not easily automated.

Asking the HA addon to get a certificate stopped working for me when I stopped using individual certs for each service and went to a wildcard. As you note, it will get the cert if I use a qualified DNS server to get the wildcard cert, but that simply reverses the problem while adding an extra entity. Wilhem of Ockham would not approve. :wink:

I’m wondering if the issue is using port 8123? I’m going to try to get HA to listen on ports 80 and/or 443. Apparently this can be done in configuration.yaml.

If you have the certificate, then it needs to o go into the ssl folder in HA.
Let’s encrypt in HA is not even used then.

OK, so I’ve removed Let’s Encrypt and copied the wildcard certificates to the /ssl folder (which appears to be a mapping of the /mnt/data/supervisor/ssl folder I see in the VM interface). I restarted the HA server just to be safe and the certificates are still there.

However I can’t connect to the server using https, just http. Trying to connect to https://[server’]or https://[server]:443 gives me an “unable to connect” error while trying https://[server]:80 gives me "


Secure Connection Failed

An error occurred during a connection to homeassistant:80. SSL received a record that exceeded the maximum permissible length.

Error code: SSL_ERROR_RX_RECORD_TOO_LONG

    The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.
    Please contact the website owners to inform them of this problem."

Because I am going directly to the HA server, this avoids the Apache server redirects but still doesn’t get me an encrypted connection. BTW: as per my previous reply, I do have HA using ports 80 and 443, but that didn’t help either.

The files I copied are the fullchain.pem and privkey.pem plus the cert.pem and chain.pem.

If you can connect to the server using http, then the server is not configured for https, because HA can only run in one of the modes at any one time.

Both the certificate and the key needs to be copied and set up in the configuration.

If you set up your router to match your domain.name, you can do everything with a hairpin NAT and using Apache as reverse proxy forwarder (which is basically the same as what NGinx does)

Then there is no need to copy certificates and certbot is only used on Apache :wink:

You could also use NGINX Proxy Manager addon and add Proxy Hosts incl. certificates that auto-refresh.

Thanks WallyR. The link to the HTTP configuration was very helpful. However, the situation still not ideal. I need to use the router to direct a port to the VM, which means I need to include the port in the URL. It also means I need to set up a cron job sync the certs between the Apache2 server and the VM.

I noticed a setting “trusted_proxies” which looks interesting but when I added it with my Apache2 server’s IP, it broke the configuration.yaml. Do you have any ideas on this? It looks like it may explain why Apache2 proxy wasn’t working but I’m not sure how to alter the configuration.yaml to work.

Thanks Aceindy. That’s what I’ve been trying to do. My router is already set up and it works with nextcloud and other services running on the Apache2 server. However I’ve had no luck getting it to work with HA. I’m thinking it requires the “trusted_proxies” setting to be used in HA, but I haven’t been able to get the configuration.yaml to take it.

Yes, required
post the http section from HA config

You need to specify what you want to achieve.

Setting the ssl entries in HA will make HA a SSL-only service, which some integrations and devices do not like.
Using a reverse proxy like Apache or NGinX makes it possible to run http on HA and then run https on the reverse proxy which pass it through to HA over http.

Whatever you choose for your https setup the client devices need access to a DNS that can resolve the hostname and domain name for the connections that need https.
Https is not possible over IPs nor domain names that are not public resolvable.

If you need https to just make HA public available, then both NGinX and Apache will work and you should follow Aceindys link.
Just beware that HA is not hardened for public internet facing ports.

Here’s the relevant section

http:
#  server_port: 80
#  ssl_certificate: /ssl/fullchain.pem
#  ssl_key: /ssl/privkey.pem
  use_x_forwarded_for: true
  trusted_proxies:
    - 192.168.1.38    # your nginx-server
    - 192.168.1.0/24  # The whole subnet

I’ve disabled the port 8123 forwarding on my router. When I try to connect to https://ha.[mydomain]/, I get " Service Unavailable". When I add port 8123 to the https request, I get the logos but the connection never completes.

If I set the port to 80 (uncomment the server_port line), I get to the login screen but then I get an “unable to connect to Home Assistant” message.

Here is the part from my configuration.yaml:

# Uncomment this if you are using SSL/TLS, running in Docker container, etc.
# Commented out as SSL certificate is now running on Apache (Linux)
http:
#  ssl_certificate: /ssl/fullchain.pem
#  ssl_key: /ssl/privkey.pem
  use_x_forwarded_for: true
  trusted_proxies:
    - 192.168.101.9 #This is my Apache box/Webmin/Virtualmin

And the issue you’re describing sounds as a mis-configuration on Apache side.
(you can check this with chrome debugger or something)

I’m not using Apache anymore (as I took my Apache offline and run only HAOS now), but,
if I remember, websocket is missing…something like this:
So besides this:

    # Home Assistant HTTP
    ProxyPass / https://192.168.101.10:443/
    ProxyPassReverse / https://192.168.101.10:443/

You also need:

    # Home Assistant WebSockets
    ProxyPass /api/websocket wss://192.168.101.10:443/api/websocket
    ProxyPassReverse /api/websocket wss://192.168.101.10:443/api/websocket

I added the extra configs to my Apache2 HA conf file and also found it necessary to add server_port: 443 to configuration.yaml. After doing that, I am back at the same point. I can log in but then get the “unable to connect” message.

HA stays on 8123, it is apache which takes care of the port 443.

So your internal dns should point towards apache, and when you contact https://ha.domain.mine (apache) it will forward (proxy) everything to http://192.168.110.10:8123 (reverse-proxy)

If I have time I’ll try to power up my old apache server and look up my exact configuration :wink:

That’s not how your sample Apache2 conf was set up. It was using port 443 to communicate with HA, unless I have completely misunderstood what those lines were trying to do.

I don’t have an “internal DNS”. All port 80 and 443 traffic goes to Apache2 which uses virtual hosts to send traffic to the correct service. This part is working, as I can log in to HA now.

However, the Apache2 error log has a lot of errors relating to the reverse proxy:

[Sat Jan 24 12:11:57.094005 2026] [mpm_prefork:notice] [pid 619751:tid 619751] AH00163: Apache/2.4.66 (Debian) OpenSSL/3.5.4 configured -- resuming normal operations
[Sat Jan 24 12:12:04.038730 2026] [proxy:error] [pid 782097:tid 782097] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:04.038790 2026] [proxy_http:error] [pid 782097:tid 782097] [client 104.36.180.91:39556] AH01114: HTTP: failed to make connection to backend: 192.168.1.38, referer: https://ha.[my domain]/
[Sat Jan 24 12:12:05.101168 2026] [proxy:error] [pid 782098:tid 782098] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:05.101218 2026] [proxy_http:error] [pid 782098:tid 782098] [client 104.36.180.91:39572] AH01114: HTTP: failed to make connection to backend: 192.168.1.38
[Sat Jan 24 12:12:05.356187 2026] [proxy:error] [pid 782099:tid 782099] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:05.356246 2026] [proxy_http:error] [pid 782099:tid 782099] [client 104.36.180.91:39576] AH01114: HTTP: failed to make connection to backend: 192.168.1.38, referer: https://ha.[my domain]/
[Sat Jan 24 12:12:06.412092 2026] [proxy:error] [pid 782100:tid 782100] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:06.412154 2026] [proxy_http:error] [pid 782100:tid 782100] [client 104.36.180.91:39578] AH01114: HTTP: failed to make connection to backend: 192.168.1.38
[Sat Jan 24 12:12:13.571876 2026] [proxy:error] [pid 782097:tid 782097] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:13.571929 2026] [proxy_http:error] [pid 782097:tid 782097] [client 104.36.180.91:50684] AH01114: HTTP: failed to make connection to backend: 192.168.1.38
[Sat Jan 24 12:12:13.655364 2026] [proxy:error] [pid 782098:tid 782098] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:13.655396 2026] [proxy_http:error] [pid 782098:tid 782098] [client 104.36.180.91:50708] AH01114: HTTP: failed to make connection to backend: 192.168.1.38, referer: https://ha.[my domain]/?auth_callback=1&code=9c2c8f1877304f8eb9010afeafce92f7&state=eyJoYXNzVXJsIjoiaHR0cHM6Ly9oYS5yYWhpbS1kYWxlLm9yZyIsImNsaWVudElkIjoiaHR0cHM6Ly9oYS5yYWhpbS1kYWxlLm9yZy8ifQ%3D%3D
[Sat Jan 24 12:12:13.655466 2026] [proxy:error] [pid 782101:tid 782101] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:13.655514 2026] [proxy_http:error] [pid 782101:tid 782101] [client 104.36.180.91:50692] AH01114: HTTP: failed to make connection to backend: 192.168.1.38, referer: https://ha.[my domain]/?auth_callback=1&code=9c2c8f1877304f8eb9010afeafce92f7&state=eyJoYXNzVXJsIjoiaHR0cHM6Ly9oYS5yYWhpbS1kYWxlLm9yZyIsImNsaWVudElkIjoiaHR0cHM6Ly9oYS5yYWhpbS1kYWxlLm9yZy8ifQ%3D%3D
[Sat Jan 24 12:12:14.525387 2026] [proxy:error] [pid 782099:tid 782099] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:14.525417 2026] [proxy_http:error] [pid 782099:tid 782099] [client 104.36.180.91:50714] AH01114: HTTP: failed to make connection to backend: 192.168.1.38
[Sat Jan 24 12:12:23.563984 2026] [proxy:error] [pid 782100:tid 782100] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:23.564020 2026] [proxy_http:error] [pid 782100:tid 782100] [client 104.36.180.91:33164] AH01114: HTTP: failed to make connection to backend: 192.168.1.38
[Sat Jan 24 12:12:23.646046 2026] [proxy:error] [pid 782096:tid 782096] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:23.646091 2026] [proxy_http:error] [pid 782096:tid 782096] [client 104.36.180.91:33166] AH01114: HTTP: failed to make connection to backend: 192.168.1.38, referer: https://ha.[my domain]/
[Sat Jan 24 12:12:23.664182 2026] [proxy:error] [pid 782095:tid 782095] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:23.664215 2026] [proxy_http:error] [pid 782095:tid 782095] [client 104.36.180.91:33172] AH01114: HTTP: failed to make connection to backend: 192.168.1.38, referer: https://ha.[my domain]/
[Sat Jan 24 12:12:24.500430 2026] [proxy:error] [pid 782097:tid 782097] (111)Connection refused: AH00957: http: attempt to connect to 192.168.1.38:443 (192.168.1.38:443) failed
[Sat Jan 24 12:12:24.500464 2026] [proxy_http:error] [pid 782097:tid 782097] [client 104.36.180.91:33184] AH01114: HTTP: failed to make connection to backend: 192.168.1.38

Anyway, after removing the server_port line and restarting HA, then changing the proxypass lines from 443 to 8123, and reloading (and even restarting), I’m not getting the Apache2 error messages but the other symptoms remain the same. I can login to HA but then the connection fails.