Configuring Caddyfile to Prevent Access to "private" folder

So I’ve been using a setup for a few years now with Apache + CrushFTP so that our staff can have a folder created and be web accessible based on their username.

CrushFTP provides the SFTP connectivity and allows them to use their LDAP credentials to authenticate and it automatically will create a folder based on their username on the server.

These folders are getting created in the Apache site root folder so for example, after I login there might be a folder like the following created:

http://spaces.example.com/orware

As an extra feature, I had configured Apache so that if a user created a folder named “private” that folder would not be listed or accessible from the web, so the following wouldn’t work:

http://spaces.example.com/orware/private

And that would allow the users to (in theory) put some files they may not want web accessible inside of the private directory.

This is being done via the following directive in Apache:

<Directory ~ "private">
Order allow,deny
Deny from all
</Directory>

I wanted to ask and find out if there was an equivalent option I could take advantage of from within a Caddyfile?

So far, the one that seems closest to what I might be looking for would be the internal directive:
https://caddyserver.com/docs/internal

But I’m not sure if it would work in the generic sense the way I have it working in Apache currently (where any folder named “private” would be excluded from being served.

Thank you!

OK, actually the rewrite directive can probably do what I need:
https://caddyserver.com/docs/rewrite

But I’ll need to do some testing/research…if I figure it out before anyone replies I’ll post what I figure out back on here!

If you specify a 403 or 404 for a path with the status directive you can effectively exclude locations from being served.

You can’t wildcard a status directive, but you can for a rewrite, so something like this would work fairly universally for any path like /*/private:

status 403 /forbidden
#status 404 /notfound
rewrite / {
  r ^/.*/private/?$
  to /forbidden
  #to /notfound
}

https://caddyserver.com/docs/status

1 Like

So I finally got to try out your suggestion and it doesn’t seem to be doing what we expected and allows for the private folder to still be browsable.

https://spaces-test.example.com {  
	tls C:/Caddy/ssl/example.com_cert.pem C:/Caddy/ssl/example.com_key.pem
	
	# Site Root:
	root C:/Caddy/sites/spaces
    
	# Enable Directory Browsing:
	browse
	
	status 403 /forbidden
	#status 404 /notfound
	rewrite / {
	  r ^/.*/private/?$
	  to /forbidden
	  #to /notfound
	}
	
	# Enable templates:
	templates
	
	# Error Logging:
	errors {
		log logs/spaces-test_example.com_error.log {
			size 50 # Rotate after 50 MB
			age  30 # Keep rotated files for 30 days
			keep 5  # Keep at most 5 log files
		}
	}

	# Access Logging:
	log logs/spaces-test_example.com_access.log {
		rotate {
			size 100 # Rotate after 100 MB
			age  14  # Keep log files for 14 days
			keep 10  # Keep at most 10 log files
		}
	}
	
	#gzip
}

In the spaces folder I copied over a small folder containing some images and that was browsable and then made a copy and renamed the folder to “private” but it remained browsable too, rather than being redirected to the forbidden folder as expected. The server it’s being tested on is running a fairly recent build (0.9.5) but I can try a newer version too (though I’m not sure if a newer version would fix it).

It would be nice to have this sort of capability added into the browse feature as an “excluded paths” sort of option that would help prevent certain directories from being web accessible automatically :-).

I’ve thought of creating a hide directive which adds files to the FileServer’s Hide list. That would probably do what you want, since the browse directive honors that.

Was the resulting folder in C:\Caddy\sites\spaces\private?

I ask because the request for that, based on the root in your Caddyfile, would be GET /private/ - which wouldn’t match the rewrite.

The regex is written to catch /somefolder/private, so if you create a directory C:\Caddy\sites\spaces\foo\private, then make a request GET /foo/private/, that should be rewritten correctly and be forbidden.

@Whitestrake,

Yes, the “private” folder that was created was placed inside of an example user’s directory (which would be equivalent to the “foo” folder you mentioned) so it should have worked but didn’t seem to redirect as expected.

@matt,

Thanks for responding! The hide directive sounds like it might be what would be needed in this case, if it were available to use.

I thought maybe it was a bad regex, so I tested it out real quick.

Matt at hermes in ~/Projects
→ caddy -version
Caddy 0.10.4

Matt at hermes in ~/Projects
→ cat Caddyfile
:2015
status 403 /forbidden
rewrite / {
  r ^/.*/private/?$
  to /forbidden
}
log / stdout "{common} -- {rewrite_uri}"

Matt at hermes in ~/Projects
→ caddy
Activating privacy features... done.
http://:2015
::1 - - [25/Jul/2017:09:56:23 +1000] "GET /stuff/private HTTP/1.1" 403 14 -- /forbidden
::1 - - [25/Jul/2017:09:56:28 +1000] "GET /stuff/private/ HTTP/1.1" 403 14 -- /forbidden
::1 - - [25/Jul/2017:09:56:33 +1000] "GET /foo/private/ HTTP/1.1" 403 14 -- /forbidden
::1 - - [25/Jul/2017:09:56:38 +1000] "GET /bar/private HTTP/1.1" 403 14 -- /forbidden
^C%

From the client’s side:

Matt at hermes in ~/Projects
→ curl localhost:2015/stuff/private
403 Forbidden

Matt at hermes in ~/Projects
→ curl localhost:2015/stuff/private/
403 Forbidden

Matt at hermes in ~/Projects
→ curl localhost:2015/foo/private/
403 Forbidden

Matt at hermes in ~/Projects
→ curl localhost:2015/bar/private
403 Forbidden

So I’m not sure why the rewrite would be failing in your case.

You might have some luck setting a log format similar to mine (log / stdout "{common} -- {rewrite_uri}") and review the logs to determine why the requests don’t seem to be matching.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.