New user : can't get darkweb site host working

1. Caddy version (caddy version):


2. How I run Caddy:

Nothing special, I just ran caddy run with a simple Caddyfile with some subdomains, no back-end.

a. System environment:

Debian 10, systemd, linux 4.19, no docker

b. Command:

caddy run

c. My complete Caddyfile or JSON config: {
	# Set this path to your site's directory.
	root * /var/www/html/

	# Enable the static file server.

	encode gzip

	log {
		output file /var/log/caddy/
} {
#	redir{uri}
#} {
	root * /var/www/html/
} {
	root * /var/www/html/

http://hecatxfh3mxrk3hzzivk2satob5n2oe7avdbu5h5xupg62u2lvhmrlad.onion:1717 {
	root * /var/www/html/onion

3. The problem I’m having:

I’m trying to have virtual hosting with my clearweb site and my .onion website but I don’t find any doc about it, except Dark Web Diaries: Detecting Co-Hosted Hidden Services without mod_status Leaks but I can’t get it work. Any idea or links ?
Tor service is enabled and running and this is my 2 uncommented lines in the /etc/tor/torrc file :

HiddenServiceDir /var/lib/tor/heca/
HiddenServicePort 80

In /var/lib/tor/heca there is information like my onion url and other stuff, generated by GitHub - cathugger/mkp224o: vanity address generator for tor onion v3 (ed25519) hidden services

4. Error messages and/or full log output:

No error messages :frowning:
My clearweb sites are perfectly working.

5. What I already tried:

Tried to search a lot some doc, even on this forum but get nothing.

Hoping I correctly wrote this help topic ^^’

… has to also be reachable over 80, 443 by ACME Providers.

Otherwise you need to use the acme-dns plugin. However, I’m unsure if the acme-dns plugin will work for *.onion

Hi :slight_smile:

I believe this has something to do with a Host: header mismatch:

  • Tor browser sends a request with Host: <your_v3>.onion (port :80 omitted, because it is a default port)
  • Your Tor service accepts and proxies the request from port :80 to (Caddy)
  • Caddy listens assumes your Host header for :1717 would look something like
    Host: <your_v3>.onion:1717 instead of
    Host: <your_v3>.onion so your vhost won’t be used.

But I might be totally wrong with that, actually.

I currently don’t have a test setup for with Tor hidden service right now.
So just to confirm my theory, would you mind temporarily changing your torrc config like that:

- HiddenServicePort 80
+ HiddenServicePort 1717

and then access your v3 service via <your_v3>.onion:1717 to see whether that works? :innocent:

Nope, it doesn’t.
Automatic HTTPS — Caddy Documentation is disabled here, because they explicitly specified the protocol (http://).
Also, using https:// for Tor hidden services has barely any benefit at all, considering how Tor does encryption.


Good catch!


Hey !
I tried to put HiddenServicePort 1717 in my torrc file and it actually works thanks you a lot !
I have one last question : I can access to my tor website with specifying the port <my_v3>.onion:1717 but it’s not very practical. Is there any way to have port 80 by default for tor ? I mean I think two services can’t listen to one same port but perhaps there is a way ?
Hoping I’m understood ! :smiley:

1 Like
  1. In your current configuration what’s running on 80?
  2. Yes, you use reverse_proxy
  1. Actually caddy is running on port 80 (I changed that few hours) because CloudFlare manages my ssl certificates so I have to disable it on caddy. Tor is running on 1717
  2. Gonna read some doc thanks !

I think you have two main options here:

  1. You could do the “unsafe” thing and essentially make your hidden service accessible from the clearweb if a client or bot fakes their Host: header, which is trivially easy. The first link in your opening post described that as “Hostname hacking” (lol)
    Essentially you would change your configs like that:

    - HiddenServicePort 80
    + HiddenServicePort 80


    - http://<v3 service>.onion:1717 {
    + http://<v3 service>.onion:80 {
    	root * /var/www/html/onion

    You could also omit either http:// or :80 in your patched Caddyfile, but I prefer to keep it explicit for the sake of visibility here.

  2. Or you could do the “safe” thing and use unix sockets. You won’t be listening to a network port, but instead to a file basically, if that helps to explain it a bit.
    The usual Linux file permissions can be used to tighten or loosen the access per user and group and so on.
    If you have multiple hidden services, you could easily use multiple unix sockets to keep them truly separate.
    And clients faking their Host: header won’t expose anything.
    For that, you would need to:

    - HiddenServicePort 80
    + HiddenServicePort 80 unix:/var/run/caddy-hidden-service.sock


    - http://<v3 service>.onion:1717 {
    + http://<v3 service>.onion:80 {
    +	bind unix//var/run/caddy-hidden-service.sock
    	root * /var/www/html/onion

    Though, you might have to change fix the folders’ permissions to allow read/write for both caddy and tor user (which I am afraid might be a bit rough to figure out if you aren’t too familiar with all that, but this response here is already kinda long, for something that you might decide against using anyway :sweat_smile:)


I think the second option is preferable buuut :
I tried what you said, restart the two services, created group for the caddy and the debian-tor users, and make /var/run/caddy-hidden-service.sock readable and writable by this group.
I have a caddy error which I tried to fix, the only results I found on Internet are related with some admin endpoint (don’t know what it is) :
when I caddy reload in the /etc/caddy directory it says :
reload: sending configuration to instance: performing request: Post "http://localhost:2019/load": dial tcp [::1]:2019: connect: connection refused
I tried to lsof -i -P -n to see what services are running on what ports but nothing in the 2019 port :

prometheu   372   prometheus    3u  IPv6  13180      0t0  TCP *:9100 (LISTEN)
dhclient    408         root    7u  IPv4  13194      0t0  UDP *:68 
ntpd        777          ntp   16u  IPv6  14270      0t0  UDP *:123 
ntpd        777          ntp   17u  IPv4  14273      0t0  UDP *:123 
ntpd        777          ntp   18u  IPv4  14277      0t0  UDP 
ntpd        777          ntp   19u  IPv4  14279      0t0  UDP 
ntpd        777          ntp   20u  IPv6  14281      0t0  UDP [::1]:123 
ntpd        777          ntp   21u  IPv6  14283      0t0  UDP [2a02:e00:ffe8:57::a]:123 
ntpd        777          ntp   22u  IPv6  14285      0t0  UDP [2a02:e00:ffe8:57::9]:123 
ntpd        777          ntp   23u  IPv6  14287      0t0  UDP [2a02:e00:ffe8:57::8]:123 
ntpd        777          ntp   24u  IPv6  14289      0t0  UDP [2a02:e00:ffe8:57::7]:123 
ntpd        777          ntp   25u  IPv6  14291      0t0  UDP [2a02:e00:ffe8:57::6]:123 
ntpd        777          ntp   26u  IPv6  14293      0t0  UDP [2a02:e00:ffe8:57::5]:123 
ntpd        777          ntp   27u  IPv6  14295      0t0  UDP [2a02:e00:ffe8:57::4]:123 
ntpd        777          ntp   28u  IPv6  14297      0t0  UDP [2a02:e00:ffe8:57::3]:123 
ntpd        777          ntp   29u  IPv6  14299      0t0  UDP [2a02:e00:ffe8:57::2]:123 
ntpd        777          ntp   30u  IPv6  14301      0t0  UDP [2a02:e00:ffe8:57::1]:123 
ntpd        777          ntp   31u  IPv6  14303      0t0  UDP [fe80::d061:e1ff:fe6b:a2d9]:123 
ntpd        777          ntp   35u  IPv4  18798      0t0  UDP 
ntpd        777          ntp   36u  IPv4  18800      0t0  UDP 
ntpd        777          ntp   37u  IPv4  18802      0t0  UDP 
ntpd        777          ntp   38u  IPv4  18804      0t0  UDP 
ntpd        777          ntp   39u  IPv6  18818      0t0  UDP [fe80::530:6491:cd84:180e]:123 
ntpd        777          ntp   40u  IPv6  18820      0t0  UDP [fe80::5ec6:6cde:9ba3:62bb]:123 
ntpd        777          ntp   41u  IPv6  18822      0t0  UDP [fe80::59fe:649a:99:4183]:123 
ntpd        777          ntp   42u  IPv6  18824      0t0  UDP [fe80::c4da:64ef:6a19:a7e6]:123 
exim4      1120  Debian-exim    3u  IPv4  15196      0t0  TCP (LISTEN)
exim4      1120  Debian-exim    4u  IPv6  15203      0t0  TCP [::1]:25 (LISTEN)
sshd       1123         root    3u  IPv4  15323      0t0  TCP *:5423 (LISTEN)
sshd       1123         root    4u  IPv6  15325      0t0  TCP *:5423 (LISTEN)
python3    1286   openvpn_as    8u  IPv4  16862      0t0  TCP *:1338 (LISTEN)
python3    1286   openvpn_as    9u  IPv4  16863      0t0  TCP *:943 (LISTEN)
python3    1286   openvpn_as   10u  IPv4  16864      0t0  TCP (LISTEN)
python3    1286   openvpn_as   11u  IPv4  16865      0t0  TCP (LISTEN)
python3    1286   openvpn_as   12u  IPv4  16866      0t0  TCP (LISTEN)
python3    1286   openvpn_as   13u  IPv4  16867      0t0  TCP (LISTEN)
python3    1286   openvpn_as   14u  IPv4  16868      0t0  TCP (LISTEN)
python3    1286   openvpn_as   15u  IPv4  16869      0t0  TCP (LISTEN)
openvpn-o  1308   openvpn_as    5u  IPv4  17032      0t0  TCP *:914 (LISTEN)
openvpn-o  1320   openvpn_as    5u  IPv4  18386      0t0  TCP *:915 (LISTEN)
openvpn-o  1329   openvpn_as    5u  IPv4  18596      0t0  UDP *:916 
openvpn-o  1337   openvpn_as    5u  IPv4  18769      0t0  UDP *:917 
sshd      15108         root    3u  IPv4 117072      0t0  TCP> (ESTABLISHED)
sshd      15126 hecatonchire    3u  IPv4 117072      0t0  TCP> (ESTABLISHED)
tor       15352   debian-tor    6u  IPv4 119345      0t0  TCP (LISTEN)
tor       15352   debian-tor    9u  IPv4 119350      0t0  TCP> (ESTABLISHED)

Sorry to again ask you help :sweat_smile: and thanks you a lot for your efforts !

1 Like

The admin endpoint http://localhost:2019 is what caddy reload uses under the hood to reconfigure (reload) an already running caddy server.

In your shared lsof it looks like caddy isn’t running at all.

You didn’t share how you installed caddy on your system in your original post :thinking:
If you used the official guide (recommended), then you should have a caddy.service systemd service, which you can start via systemctl start caddy.

The systemd service also allows one to use systemctl reload caddy, but caddy reload should work just as well.

The service will default to /etc/caddy/Caddyfile on start, so won’t have to run reload if you just started it :innocent:


I have installed Caddy adding its repo like the official guide says. Tor website still doesn’t work.
The problem was that I’ve edited the Caddyfile so I have to caddy reload after it but it didn’t work.
But now I have another error when I try to reload (I didn’t do anything except comment and uncomment the onion domain in the Caddyfile, while I couldn’t fix the problem) :

reload: sending configuration to instance: caddy responded with error: HTTP 400: {"error":"loading config: loading new config: http app module: start: unix: listening on /var/run/caddy-hidden-service.sock: listen unix /var/run/caddy-hidden-service.sock: bind: address already in use"}

Now Caddy is listening at and at *:80, but the problem is not here, it doesn’t want to listen to the unix sock. lsof /var/run/caddy-hidden-service.sock doesn’t return anything.

Perhaps I can try to reverse_proxy instead of unix sock ? Some friend told me I could be a solution.

Okay, this got a bit bigger than I originally expected:
I did a wrong assumption in

and did not explain it any further, partially, because I was unsure whether you would decide in favor of the unix socket. Glad you did, though! :sweat_smile:

I did assume caddy would take the permissions of whatever parent directory are already set and use those for the new socket.
But it doesn’t. I didn’t test that until now.
Instead, it infers it from the shell file mode mask (usually referred to as umask).

I opened an issue on GitHub which goes a bit more into detail and would allow for a proper fix of your issue: Allow one to specify file permissions for unix sockets · Issue #4675 · caddyserver/caddy · GitHub
Feel free to follow it, if you happen to have a GitHub account.

Also, the actual error you are encountering happens because the path of the unix socket you specified in your Caddyfile can’t be an already existing file.
The error message in v2.5.0-beta.1 improved that error message slightly:

run: loading initial config: loading new config: http app module: start: unix: listening on /var/run/caddy-hidden-service.sock: listen unix /var/run/caddy-hidden-service.sock: bind: address already in use: this can happen if Caddy was forcefully killed

I absolutely get why you thought you could just create an empty file and point caddy to it to use it.
I should have explained that better!

Essentially, what I meant is, you can modify the sockets’ permission to your liking after caddy created it.
Those changes won’t last a restart, though. They are temporarily. The linked issue proposes a simple chmod, but it is unclear whether it should do a chown too.
For your use-case, a chmod would be necessary (allowing o=rw, so any user on the host). But an additional chown would allow the use of your custom created group with g=rw, making it all a bit cleaner.

You could do some hackery and modify the umask (and/or group) of the systemd service and whatnot, but I would advise against it.

Instead, at least for now, you should be good doing the following:

  1. remove your empty socket file again
  2. either reload or restart caddy with the onion vhost enabled, so caddy will create the socket on the specified path
  3. run either of the following variants to fix temporarily fix the sockets’ permissions:
    1. chmod u=rw,g=rw,o=rw $YOUR_SOCKET_PATH (or chmod 666)
    2. chmod u=rw,g=rw $YOUR_SOCKET_PATH (or chmod 660) AND chown caddy:$YOUR_CUSTOM_GROUP_NAME

:information_source: A user only needs rw (read/write) access to a socket to be able to use it. x (execute) is not required.

That workaround could be an incredible inconvenient one though, if you happen to reload caddy or restart your host fairly often :thinking:
You could always just fall back to the “unsafe” way (for now) I mentioned in option 1. (in post #8 in this thread) if it annoys you :woman_shrugging:

Last but not least, I really don’t think you can use reverse_proxy here. That directive has a totally different purpose :upside_down_face:


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