Unable to get caddy to work

1. Output of caddy version:


2. How I run Caddy:

a. System environment:

Ubuntu 20.04, Duck DDns with my router,Port forwarding to 4443, cause the ISP’s modem got port 80 and 443 blocked

b. Command:

sudo ~/go/caddy run --config /etc/caddy/Caddyfile

c. Service/unit/compose file:

d. My complete Caddy config:

****.duckdns.org:4443 {

tls {
    dns duckdns {my token} {
            override_domain ****.duckdns.org

root * /var/www/html/index.html

reverse_proxy /rss
encode zstd gzip
handle_errors {
        rewrite * /{err.status_code}.html

3. The problem I’m having:

Hey Guys,
I’m new to Caddy, since nginx is just to complicated for me…
So I’m trying to build a homeserver with a RSS and a homeassistant on it.
Now I’m also stuggling to get Caddy to work.
No matter what I’ve changed, the browser always tells me “Connection Failure”,
except http://****.duckdns.org:4443, which gives this error"Client sent an HTTP request to an HTTPS server." (curl the same)
I have checked that port 4443 is open.
the tls was using DNS challenge to get from.

Could someone gimme a hand here?
Thnaks in advance!

4. Error messages and/or full log output:

H720@H720:/etc/caddy$ sudo ~/go/caddy start --config /etc/caddy/Caddyfile
2022/11/27 00:46:29.868 INFO    using provided configuration    {"config_file": "/etc/caddy/Caddyfile", "config_adapter": ""}
2022/11/27 00:46:29.870 WARN    Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies    {"adapter": "caddyfile", "file": "/etc/caddy/Caddyfile", "line": 11}
2022/11/27 00:46:29.871 INFO    admin   admin endpoint started  {"address": "localhost:2019", "enforce_origin": false, "origins": ["//[::1]:2019", "//", "//localhost:2019"]}
2022/11/27 00:46:29.872 INFO    tls.cache.maintenance   started background certificate maintenance      {"cache": "0xc0006f6bd0"}
2022/11/27 00:46:29.872 INFO    http    enabling automatic HTTP->HTTPS redirects        {"server_name": "srv0"}
2022/11/27 00:46:29.872 INFO    http    enabling HTTP/3 listener        {"addr": ":4443"}
2022/11/27 00:46:29.872 INFO    tls     cleaning storage unit   {"description": "FileStorage:/root/.local/share/caddy"}
2022/11/27 00:46:29.873 INFO    failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size for details.
2022/11/27 00:46:29.873 INFO    http.log        server running  {"name": "srv0", "protocols": ["h1", "h2", "h3"]}
2022/11/27 00:46:29.873 INFO    http.log        server running  {"name": "remaining_auto_https_redirects", "protocols": ["h1", "h2", "h3"]}
2022/11/27 00:46:29.873 INFO    http    enabling automatic TLS certificate management   {"domains": ["****.duckdns.org"]}
2022/11/27 00:46:29.873 INFO    tls     finished cleaning storage units
2022/11/27 00:46:29.874 INFO    autosaved config (load with --resume flag)      {"file": "/root/.config/caddy/autosave.json"}
2022/11/27 00:46:29.874 INFO    serving initial configuration

5. What I already tried:

curl ****.duckdns.org:4443 -v
*   Trying ip.ip.ip.ip4443...
* Connected to ****.duckdns.org (ip.ip.ip.ip) port 4443 (#0)
> GET / HTTP/1.1
> Host: ****.duckdns.org:4443
> User-Agent: curl/7.83.1
> Accept: */*
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
< HTTP/1.0 400 Bad Request
Client sent an HTTP request to an HTTPS server.
* Closing connection 0

6. Links to relevant resources:

Can you share the output of curl https://****.duckdns.org:4443 -v?
(https:// instead of http://)

1 Like

You don’t need this – only use this if the domain you want to serve on is different than the one you use to issue certificates. That’s not true in your case.

This doesn’t make sense – the root should be the path to a directory, not a path to a file. For example, root * /var/www/html would make sense. The file_server directive will check for an index.html file if the path / is requested.

Keep in mind that /rss will only match requests to exactly /rss and nothing else. If you need requests like /rss/foo to work, then use /rss* instead.

As @emilylange implied, that’s because you made a request with http:// to an HTTPS server. The error message is pretty clear. Try with https:// instead.

Please do this – your config is very hard to read because of inconsistent indentation. Specifically, you can run sudo caddy fmt --overwrite /etc/caddy/Caddyfile.

It would be best if you run Caddy as a systemd service instead. See the docs.


Hey James,
yes, the https curl out put is below, after I tweaked as francis said, it could work now, thou theres is another problem…

H720@H720:/etc/caddy$ curl https://rss.****.duckdns.org:4443/ -v
*   Trying ***.***.***.***:4443...
* Connected to rss.****.duckdns.org (***.***.***.***) port 4443 (#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_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=rss.****.duckdns.org
*  start date: Nov 27 13:29:19 2022 GMT
*  expire date: Feb 25 13:29:18 2023 GMT
*  subjectAltName: host "rss.****.duckdns.org" matched cert's "rss.****.duckdns.org"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* Using Stream ID: 1 (easy handle 0x55b50bddee80)
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET / HTTP/2
> Host: rss.****.duckdns.org:4443
> 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):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 200
< alt-svc: h3=":4443"; ma=2592000
< cache-control: public
< content-security-policy: default-src 'self'; style-src 'self'; script-src 'self'; font-src 'self'; img-src 'self'; form-action 'self'; connect-src 'self'; frame-ancestors 'none';
< content-type: text/html; charset=UTF-8
< date: Sun, 27 Nov 2022 22:30:43 GMT
< permissions-policy: interest-cohort=()
< referrer-policy: no-referrer-when-downgrade
< server: Caddy
< server: nginx/1.22.1
< strict-transport-security: max-age=31536000;
< x-content-type-options: nosniff
< x-frame-options: DENY
< x-powered-by: PHP/8.0.25
* TLSv1.2 (IN), TLS header, Supplemental data (23):
<!DOCTYPE html>
        <title>Tiny Tiny RSS : Login</title>
        <link rel="shortcut icon" type="image/png" href="images/favicon.png">
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <script src="lib/dojo/dojo.js?1668217531" type="text/javascript" charset="utf-8"></script>
<script src="lib/dojo/tt-rss-layer.js?1668217531" type="text/javascript" charset="utf-8"></script>
<script src="js/common.js?1668217530" type="text/javascript" charset="utf-8"></script>
<script src="js/utility.js?1668217530" type="text/javascript" charset="utf-8"></script>

        <script src="themes.local/local-overrides.js?1668217492" type="text/javascript" charset="utf-8"></script>

        <style type="text/css">
                @media (prefers-color-scheme: dark) {
                        body {
                                background : #303030;

                body.css_loading * {
                        display : none;

        <script type="text/javascript">

        <script type="text/javascript">
        /* exported Plugins */
        const Plugins = {};


Hi Francis,
thanks for your reply, I have tweaked the Caddyfile after your suggestion and it works now, partially…
I could access my rss.####.duckdns.org:4443 now, which is my ttrss server, and also the main site ####.duckdns.org:4443.
However, the site “rss.####.duckdns.org:4443” does not load correctly. It takes a minute to get the login page and looks really weird.

Although there are some other content types in the curl output, (like “text/css” and “text/javascript”), the headers only allow “text/html”.
I dont know if thats the problem but in the console of the developer mode in Firefox, it said “script loading error”

Loading failed for the with source “https://rss.####.duckdns.org:4443/lib/dojo/dojo.js?1668217531”

I have also browsed the forum, tunrs out you have also anwsered another thread about fail loading css etc.

Caddy not loading CSS because of MIME type - #2 by francislavoie

However, I tried to ass Content-type headers, But they did not work, well no changes were in curl’s output.

anyway, here is my recent Caddyfile

****.duckdns.org:4443 {
        tls {
                dns duckdns {token}

        root * /var/www/html

        encode zstd gzip

        handle_errors {
                rewrite * /{err.status_code}.html

rss.****.duckdns.org:4443 {
        tls {
                dns duckdns {token}

        root * /var/www/html

        encode zstd gzip

#        @css path *.css
#        @java path *.js

        header {
                  Content-Type text/css
                  Content-Type application/javascript

        handle_errors {
                rewrite * /{err.status_code}.html

well later I managed to add a content header correctly, but the page was still broken, so it might not be the MIME problem

Hi Guys @emilylange @francislavoie
Well after some research, I figuered the problem is that the TTRSS Docker Container ""as upstream cannot pass correct infotmation to “rss.****.duckdns.org:4443”.

Cause the “” looks pretty good in the browser.
I have also switched the Docker image of the ttrss, but it still doesnt work, so I think it’s due to incomplete Caddyfile configurations.
Could you guys pls help me out (◔‸◔)

Caddyfile now look like this

****.duckdns.org:4443 {
        tls {
                dns duckdns {token}

        root * /var/www/html

        encode zstd gzip

        handle_errors {
                rewrite * /{err.status_code}.html

rss.****.duckdns.org:4443 {
        tls {
                dns duckdns {token}

        root * /var/www/html

        encode zstd gzip

        handle_errors {
                rewrite * /{err.status_code}.html

I dont know if docker-compose file matters, but here it is

version: "3"
    image: postgres:alpine
    container_name: postgres
      - POSTGRES_PASSWORD=1 # please change the password
      - ~/postgres/data/:/var/lib/postgresql/data # persist postgres data to ~/postgres/data/ on the host
    restart: always

    image: wangqiru/ttrss:latest
    container_name: ttrss
      - 181:80
      - SELF_URL_PATH=https://rss.****.duckdns.org # please change to your own domain
      - DB_HOST=database.postgres
      - DB_PORT=5432
      - DB_NAME=ttrss
      - DB_USER=postgres
      - DB_PASS=1 # please change the password
      - ENABLE_PLUGINS=auth_internal,fever # auth_internal is required. Plugins enabled here will be enabled for all users as system plugins
      - FEED_LOG_QUIET=true
    stdin_open: true
    tty: true
    restart: always
    command: sh -c 'sh /wait-for.sh $$DB_HOST:$$DB_PORT -- php /configure-db.php && exec s6-svscan /etc/s6/'

I bet your browser cached some broken assets or whatever.

Try curl https://rss.####.duckdns.org:4443/lib/dojo/dojo.js --head instead. That should work just fine (status code 200).

Test your page website in an incognito tab and see if that changes something for you.

Also, the following should be enough for your rss.####.duckdns.org:4443 block:

rss.****.duckdns.org:4443 {
	tls {
		dns duckdns {token}

	encode zstd gzip

Hello @emilylange ,
well when I curl dodo.js, it indeedthrow back a HTTP 200 .
Though I ve noticed there are 2 server headers in the ouput

sudo curl https://rss.****.duckdns.org:4443/lib/dojo/dojo.js --head
HTTP/2 200
accept-ranges: bytes
alt-svc: h3=":4443"; ma=2592000
content-type: application/javascript
date: Tue, 29 Nov 2022 13:29:12 GMT
etag: "62efca4c-23aca"
last-modified: Sun, 07 Aug 2022 14:21:00 GMT
server: Caddy
server: nginx/1.22.0
content-length: 146122

when I changed the SELF_URL_PATH in the docker-compose to, curl gave me an output with only one server nginx

sudo curl  --head
HTTP/1.1 200 OK
Server: nginx/1.22.0
Date: Tue, 29 Nov 2022 13:32:08 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/8.0.22
Cache-Control: public

would that be the problem?
ps: I have already removed nginx

Hmm, so I have tried to use a docker image I’m certain it works( from the image I have built last year)
unfortunately it’s still broken.
Kinda devastated… :smiling_face_with_tear:
So it’s either Ubuntu 22.04’s problem or Caddy’s

That is working as intended. It means your request is going through two servers! :slight_smile:

there are so many things to learn in the server world :grinning:

1 Like

I figured out the problem, well partially.
After switching back to nginx today, the problem is still the same(well not displaying anything at all but eroors are same)
Somehow my ISP’s modem is blocking this traffic. (Or not routing it correctly)
As long as I use mobile network or a VPN on my devices its all good.
I m gonna figure it out and switching back to Caddy to have another try.

1 Like

After a bit research, I think it’s due to lack of ability of my ISP modem
which does not support NAT loopback, so I cant access my ddns domain locally.
I’m gonna buy a new one :melting_face:

IIRC some people overcome this with split-horizon DNS (but then you have 3 problems)

My own router doesn’t support hairpin NAT either, kind of annoying.

Thanks for your info Matt,

I gave Caddy another go, it works perfectly, its just my modem lol


This topic was automatically closed after 30 days. New replies are no longer allowed.