Setting HTTPS for .onion

1. Output of caddy version:

2-alpine

2. How I run Caddy:

I run Caddy by the command docker compose up -d under the /usr/local/searxng-docker folder.

a. System environment:

Ubuntu 20.04

b. Command:

docker compose up -d

c. Service/unit/compose file:

Paste full file contents here.
Make sure backticks stay on their own lines,
and the post looks nice in the preview pane. -->

d. My complete Caddy config:

{
  admin off
}

{$SEARXNG_HOSTNAME} {
  log {
        output discard
  }

  tls {$SEARXNG_TLS}

  @api {
        path /config
        path /healthz
        path /stats/errors
        path /stats/checker
  }

  @static {
        path /static/*
  }

  @notstatic {
        not path /static/*
  }

  @imageproxy {
        path /image_proxy
  }

  @notimageproxy {
        not path /image_proxy
  }

header Onion-Location http://zpqi3eorbszyks36k6jsicg64wm6el7fom4o2ds3hqqcqcapfin3qfid.onion{path}


  header {
        # Enable HTTP Strict Transport Security (HSTS) to force clients to always connect via HTTPS
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

        # Enable cross-site filter (XSS) and tell browser to block detected attacks
        X-XSS-Protection "1; mode=block"

        # Prevent some browsers from MIME-sniffing a response away from the declared Content-Type
        X-Content-Type-Options "nosniff"

        # Disable some features
        Permissions-Policy "accelerometer=(),ambient-light-sensor=(),autoplay=(),camera=(),encrypted-media=(),focus-without-user-activation=(),geolocation=(),gyroscope=(),magnetometer=(),microphone=(),midi=(),payment=(),picture-in-picture=(),speaker=(),sync-xhr=(),usb=(),vr=()"

        # Disable some features (legacy)
        Feature-Policy "accelerometer 'none';ambient-light-sensor 'none'; autoplay 'none';camera 'none';encrypted-media 'none';focus-without-user-activation 'none'; geolocation 'none';gyroscope 'none';magnetometer 'none';microphone 'none';midi 'none';payment 'none';picture-in-picture 'none'; speaker 'none';sync-xhr 'none';usb 'none';vr 'none'"

        # Referer
        Referrer-Policy "no-referrer"

        # X-Robots-Tag
        X-Robots-Tag "noindex, noarchive, nofollow"

        # Remove Server header
        -Server
  }

  header @api {
        Access-Control-Allow-Methods "GET, OPTIONS"
        Access-Control-Allow-Origin  "*"
  }

  # Cache
  header @static {
        # Cache
        Cache-Control "public, max-age=31536000"
        defer
  }

  header @notstatic {
        # No Cache
        Cache-Control "no-cache, no-store"
        Pragma "no-cache"
  }

  # CSP (see http://content-security-policy.com/ )
  header @imageproxy {
        Content-Security-Policy "default-src 'none'; img-src 'self' data:"
  }

  header @notimageproxy {
        Content-Security-Policy "upgrade-insecure-requests; default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; form-action 'self' https://github.com/searxng/searxng/issues/new; font-src 'self'; frame-ancestors 'self'; base-uri 'self'; connect-src 'self' https://overpass-api.de; img-src 'self' data: https://*.tile.openstreetmap.org; frame-src https://www.youtube-nocookie.com https://player.vimeo.com https://www.dailymotion.com https://www.deezer.com https://www.mixcloud.com https://w.soundcloud.com https://embed.spotify.com"
  }

  # SearXNG
  handle {
        encode zstd gzip

        reverse_proxy localhost:8080 {
               header_up X-Forwarded-Port {http.request.port}
               header_up X-Forwarded-Proto {http.request.scheme}
        }

  }

}

3. The problem I’m having:

In the .env file I set SEARXNG_HOSTNAME=searxng.nicfab.it
Now it works fine via HTTPS.
I add in the Caddyfile the line header Onion-Location http://zpqi3eorbszyks36k6jsicg64wm6el7fom4o2ds3hqqcqcapfin3qfid.onion{path}, and it works fine.

I want to redirect the mentioned onion address to HTTPS having an SSL certificate.
To have the onion address in HTTPS, I want to know the correct configuration for Caddy, being dockerized, and especially in which folder of the server I have to save the certificates. Currently, I saved the certificates in /etc/ssl.

4. Error messages and/or full log output:

No errors at the moment.

5. What I already tried:

6. Links to relevant resources:

My concerns:
I want to redirect the mentioned onion address to HTTPS having an SSL certificate.
To have the onion address in HTTPS, I want to know the correct configuration for Caddy, being dockerized, and especially in which folder of the server I have to save the certificates. Currently, I saved the certificates in /etc/ssl.

I’m not entirely sure whether Caddy can manage .onion certificates with Automatic HTTPS, but if you’ve got your own, you can specify them with the tls directive in your Caddyfile.

Given that you’ve got Caddy in a Docker container, you can place the certificates wherever is convenient, and volume mount them in.

2 Likes

Thank you.
I tried in several ways but if I add any value Caddy stop working.
I don’t know.

Sorry, without more information on exactly what you tried, and exactly how Caddy ‘stopped working’, there’s not much more information I can give you other than to point you back at the documentation that outlines the correct syntax for the directive.

2 Likes

You are right.

After the row

header Onion-Location http://zpqi3eorbszyks36k6jsicg64wm6el7fom4o2ds3hqqcqcapfin3qfid.onion{path}

I add the following lines

https://zpqi3eorbszyks36k6jsicg64wm6el7fom4o2ds3hqqcqcapfin3qfid.onion {

tls /etc/ssl/36F846B6B0FA2F9B93BFE17D1F83824-2.pem /etc/ssl/privateKey.pem

}

After saving Caddifile, I run docker compose down and then docker compose up -d

Caddy stopped working; the logs are the following

{"level":"info","ts":1662358880.3150988,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
run: adapting config using caddyfile: /etc/caddy/Caddyfile:44: unrecognized directive: https://zpqi3eorbszyks36k6jsicg64wm6el7fom4o2ds3hqqcqcapfin3qfid.onion

I hope to have clarified my intervention.

I don’t have the full context, but this error is typical when you try to put one site inside another site. e.g.:

foo.example {
  # some config

  bar.example {
    # some config
  }

}

This cannot be done because the encapsulated site is treated as a directive, and there is no Caddyfile directive called bar.example (or in your case, https://zpqi3eorbszyks36k6jsicg64wm6el7fom4o2ds3hqqcqcapfin3qfid.onion) and therefore Caddy cannot serve your site because it does not understand your configuration.

Individual sites must be separated, e.g.:

foo.example {
  # some config
}

bar.example {
  # some config
}
1 Like

Yes.
So, I tried to append at the end of Caddyfile, as you can see at the beginning of this post, the following lines

https://zpqi3eorbszyks36k6jsicg64wm6el7fom4o2ds3hqqcqcapfin3qfid.onion {

tls /etc/ssl/36F846B6B0FA2F9B93BFE17D1F83824-2.pem /etc/ssl/privateKey.pem

}

However, Caddy doesn’t work, and I see the following logs

{"level":"info","ts":1662359508.8824756,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
{"level":"warn","ts":1662359508.8863788,"logger":"caddyfile","msg":"Unnecessary header_up X-Forwarded-Proto: the reverse proxy's default behavior is to pass headers to the upstream"}
{"level":"warn","ts":1662359508.8884516,"msg":"Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2}
{"level":"warn","ts":1662359508.8929164,"logger":"admin","msg":"admin endpoint disabled"}
{"level":"info","ts":1662359508.8934257,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc0004bb650"}
{"level":"info","ts":1662359508.8948836,"logger":"tls.cache.maintenance","msg":"stopped background certificate maintenance","cache":"0xc0004bb650"}
run: loading initial config: loading new config: loading http app module: provision http: getting tls app: loading tls app module: provision tls: loading certificates: open /etc/ssl/36F846B6B0FA2F9B93BFE17D1F83824-2.pem: no such file or directory

I see from the latest line that it doesn’t find the certificate, but it’s very strange because they are exactly there.

Have you volume mounted them correctly into the Caddy container?

Check by running a command such as: docker compose exec <Caddy compose service name> stat /etc/ssl/36F846B6B0FA2F9B93BFE17D1F83824-2.pem

1 Like

I see

service "searxng/searxng:latest" is not running container #1

The same is if I run

docker compose exec caddy:2-alpine stat /etc/ssl/36F846B6B0FA2F9B93BFE17D1F83824-2.pem

I see

service "caddy:2-alpine" is not running container #1

You will have to bring the container up first.

Please proceed with standard Docker container troubleshooting; this is likely not a Caddy issue, but rather a Docker volume mounting issue.

The container is up and running.
If I run docker ps, I see

CONTAINER ID   IMAGE                    COMMAND                  CREATED         STATUS         PORTS                      NAMES
4ef08651708d   caddy:2-alpine           "caddy run --config …"   6 minutes ago   Up 6 minutes                              caddy
74520a8f1457   redis:alpine             "docker-entrypoint.s…"   6 minutes ago   Up 6 minutes   6379/tcp                   redis
4e6bb54b5ca9   searxng/searxng:latest   "/sbin/tini -- /usr/…"   6 minutes ago   Up 6 minutes   127.0.0.1:8080->8080/tcp   searxng

I run the command
docker compose exec caddy stat /etc/ssl/36F846B6B0FA2F9B93BFE17D1F83824-2.pem

The response is

stat: can't stat '/etc/ssl/36F846B6B0FA2F9B93BFE17D1F83824-2.pem': No such file or directory

Is there any help you can provide me?

I underline that /etc/ssl/36F846B6B0FA2F9B93BFE17D1F83824-2.pem is on my server and not into the container.

You need to mount the files from your host to the inside of the container.

Here is the Docker documentation on bind mounting: Use bind mounts | Docker Documentation

And here is the relevant Compose specification for mounting volumes: Compose specification | Docker Documentation

3 Likes