Starting from scratch

1. The problem I’m having:

Hello,
I tried to setup a reverse proxy to access a nextcloud, and homeassistant from the internet. For this I have a domain at Ionos and some subdomains. Starting point is the nextcloud, which is accessable from the internet. For this alone no reverse proxy is necessary of course.
By experimenting hours and hours with no real success I went back to the basics: a bare Raspberry Pi 3b with latest Raspbian, all updates and started a Quick-start session according to Reverse proxy quick-start — Caddy Documentation.
When succeeding in this “simple” problem, I’ll go back to my original task. However, first I would like to understand the basics.

At the point ‘static files’ . At this point there is a home directory /var/www/caddypi with a simple index.html, but no Caddyfile nor caddy.json config. The commands ‘caddy file-server --listen :2015’ and ‘curl localhost:2015’ work as expected. Now with Caddyfile:

localhost:2015
file_server browse

This command fails:
uli@caddy:/var/www/caddypi $ caddy run

And of course, the site does not work:
uli@caddy:/var/www/caddypi $ curl localhost:2015

2. Error messages and/or full log output:

caddy run →
2024/11/10 13:30:02.886 INFO using adjacent Caddyfile
2024/11/10 13:30:02.890 INFO adapted config to JSON {“adapter”: “caddyfile”}
2024/11/10 13:30:02.893 INFO admin admin endpoint started {“address”: “localhost:2019”, “enforce_origin”: false, “origins”: [“//localhost:2019”, “//[::1]:2019”, “//127.0.0.1:2019”]}
2024/11/10 13:30:02.894 INFO http.auto_https enabling automatic HTTP->HTTPS redirects {“server_name”: “srv0”}
2024/11/10 13:30:02.894 INFO tls.cache.maintenance started background certificate maintenance {“cache”: “0x40006ad200”}
2024/11/10 13:30:02.896 INFO pki.ca.local root certificate is already trusted by system {“path”: “storage:pki/authorities/local/root.crt”}
2024/11/10 13:30:02.897 INFO tls.cache.maintenance stopped background certificate maintenance {“cache”: “0x40006ad200”}
Error: loading initial config: loading new config: http app module: start: listening on :80: listen tcp :80: bind: permission denied

curl localhost:2015
curl: (7) Failed to connect to localhost port 2015 after 1 ms: Couldn’t connect to server

My question: how to interpret the error message. I have no other web server running.

3. Caddy version:

v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=

4. How I installed and ran Caddy:

Strictly following the Installation process on Welcome — Caddy Documentation.
No Docker.

a. System environment:

Raspberry Pi3b, 64GB Flash, 64Bit RasbianOS,
Linux caddy 6.6.51+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.6.51-1+rpt3 (2024-10-08) aarch64

b. Command:

see above.

c. Service/unit/compose file:

Not relevant for now.

d. My complete Caddy config:

localhost:2015
file_server browse

5. Links to relevant resources:

Howdy @pampasadmin, welcome to the Caddy community.

This means Caddy tried to start up and listen to port 80 (so that it can redirect HTTP requests to HTTPS on the configured port 2015 for your localhost site). It couldn’t, though, because something is already running on port 80.

The difference between caddy file-server --listen :2015 and your Caddyfile is that the command assumes you want HTTP for that address and the Caddyfile assumes you want HTTPS. When you have HTTPS configured, Caddy tries to set up the aforementioned redirect listener.

You can use http://localhost:2015 to tell Caddy to use HTTP in your Caddyfile, or you can try and troubleshoot what else is running on your host that is consuming port 80 and possibly move/stop that other process to make room for Caddy if you prefer.

1 Like

Thanks for the reply.
I’m struggeling with the question, which process is occupying port 80.
A netstat as root shows following:

root@caddy:/var/www/caddypi# netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 654/sshd: /usr/sbin
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 6761/cupsd
tcp6 0 0 :::22 :::* LISTEN 654/sshd: /usr/sbin
tcp6 0 0 ::1:631 :::* LISTEN 6761/cupsd
udp 0 0 0.0.0.0:5353 0.0.0.0:* 462/avahi-daemon: r
udp 0 0 0.0.0.0:52254 0.0.0.0:* 462/avahi-daemon: r
udp6 0 0 fe80::309f:19f5:ff9:546 :::* 542/NetworkManager
udp6 0 0 :::5353 :::* 462/avahi-daemon: r
udp6 0 0 :::53523 :::* 462/avahi-daemon: r

… and therefore no hint to find out. As I mentioned at the very beginning, I started with a blank Rasbian: no Apache etc. .

Cheers Uli

Oh - it might just be that the user you’re running Caddy as doesn’t have bind permission for low-numbered ports.

1 Like

Don’t use caddy run directly. Follow the instructions here to run Caddy as a service:

1 Like

OK, I’ll use caddy start. However, how to overcome the thing with the port bindings?

By running it as a service with the caddy service user, it will be able to bind to low ports (i.e. port 80).

1 Like

I understand, that caddy from the command line is somewhat tricky. Forcing ‘http://localhost:2015’ works - however these are only first steps to get a very little experience with caddy - but not necessarily relevant for real application.

Therefore I assume to go back to my original plan, to run a caddy within a container. The underlying question for this, is following:
I have a Domain and some subdomains. For all of them I have a common set of certificates and keys. The connection to the internet is established by a router with one (external) ipv4 address and updated by the router itself (DynDNS). Is caddy able to proxy from subdomains to individual ip addresses within the LAN?
I try to set this up and in case of questions I’ll come back - with a new topic.

Thanks and cheers
Uli

Why not let Caddy manage TLS certs automatically instead?

FYI you can do DDNS IP updates from Caddy itself with GitHub - mholt/caddy-dynamicdns: Caddy app that keeps your DNS records (A/AAAA) pointed at itself.

Absolutely.

Are your other services also running in containers? If not, then you wouldn’t gain much from running Caddy in a container, you could just run it directly on the host as a systemd service. If yes, then you can proxy to the container service names like reverse_proxy my-app:8080 (assuming you have a service in Docker named my-app).

1 Like

I had my tries with certificates from lets encrypt. As long as the nextcloud was the only application to be reached from ithe internet it worked fine - I opened ports 80/443 of the server on my router and everything worked well. Then I installed caddy within docker on my server (Intel NUC with lots of ram/SSD) and switched to DynDNS and the supplied keys of my DNS provider. The connection to the nextcloud still works. To provide caddy with an own IP address to serve as proxy I had to use macvlan to map the IP into the allowed range of my router. This address I then opened to the internet (instead of the server address directly) - and nothing worked in the way I expected. I found it quite hard to debug caddy - at the end I was not sure whether it worked at all even if Portainer showed it running and whether the ports and IPs were connected correctly.
Now, as an intermediate step, I add a raspi just for caddy- I try both - within docker and as service. I just hope, that this simple configuration is better to understand and debuggable. At the end, everything should be concentrated on the NUC again.

Thanks pampasadmin for your answer. It will be helpful.