A blog about tech & coding

Use Caddy as a reverse proxy (+ local CA!)

By Marco on Thu May 28 20202 min readself-hosting

Self-hosting enthusiasts often run their own services such as NextCloud, Jellyfin, Home Assistant, Pihole and many others. When you start self-hosting you quickly accumulate a lot of services. Soon you will find out that accessing services by an IP address and port number is not very user-friendly, and if this sounds familiar, you've probably heard about something called a reverse proxy:

Reverse proxy flow (source: Cloudflare)

A reverse proxy is a service that sits in fronts of web services and handles all traffic towards those web services. A reverse proxy will forward access to web services based on host names: you can point the DNS records of a.mydomain.com and b.mydomain.com to the same reverse proxy and the reverse proxy will figure out which service you actually want to connect with. A reverse proxy will also allow you to configure SSL certificates so you can configure your encryption in one place.

This functionality is also extremely useful when self-hosting. Although the above image explains the situation where a reverse proxy is used for web services accessed over the internet, the same concept also applies for your local network. So let's add a reverse proxy to our own server at home!

Nginx has been widely in use as a reverse proxy for years: it's fast, mature and battle-tested. However, configuring nginx can be quite cumbersome and it wasn't necessarily designed for a world where you quickly want to be able to host new web services. Recently I came across a new modern reverse proxy (which also has many more features) that is very easy to use, Caddy. Caddy also offers automatic HTTPS which a huge benefit for hobbyists who don't want to be bothered with renewing certificates and having their services flagged as insecure.

You can easily run Caddy using Docker, below an example for running Caddy with docker-compose:

version: "3.7"
services:
  caddy:
    image: caddy/caddy
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./data/caddy/data:/data
      - ./data/caddy/config:/config
    restart: unless-stopped
    container_name: caddy

Configuring Caddy is dead simple using something called a Caddyfile, just look at this example for a reverse proxy with automatic HTTPS enabled:

mydomain.tld {
  reverse_proxy http://<SERVICE_IP>:8080
}

If you point your DNS records for mydomain.tld towards your server running Caddy it will serve whatever is running on <SERVICE_IP>:8080. If you have a service running in docker-compose, you can directly connect to the service using the service name defined in docker-compose.yml.

Adding more websites is as simple as you would hope it would be:

mydomain.tld {
  reverse_proxy http://<SERVICE_IP>:8080
}
subdomain.mydomain.tld {
  reverse_proxy http://<SERVICE_IP>:3000
}

Relaunch Caddy and that 's it, no other steps or configuration required! Both websites are now served using the same reverse proxy with automatic HTTPS.

You can even go as far as enabling HTTPS using a local certificate authority for locally hosted websites. This can be useful if you run your own DNS server and have some services internally available using hostnames such a <myservice>.lan or some other non-public TLD.

myservice.lan {
  tls internal
  reverse_proxy http://<SERVICE_IP>:8080
}

Now Caddy will generate a certificate for this website using a local certificate authority. You can fetch the root certificate from /data/caddy/pki/authorities/local/root.crt and install it on your machine so that your browser will trust your local services hosted on an internal domain. You can also install the root certificate on your iPhone if needed.

If you still have some questions, post a comment and I will try to help you. Thanks for reading!

Using pyenv for Python version management

Python is currently the 2nd most used programming language in the world. Development tools are increasing in quality as well, making life as a Python developer much easier (shoutout to Visual Studio Code, poetry, black and flake8). Most of the time you use only the Python version installed in your operating system. However, projects can require different Python versions, sometimes even made explicit thanks to poetry. pyenv is a cli-utility that solves this problem by making it easy to manage Py

Mon Nov 16 2020

Use Poetry for Python dependency management with Visual Studio Code

Python has been the most popular programming language for years, but despite this dependency management has been a weak spot for a long time as well. Pipenv was (and is) a good attempt to fix this, but in late 2019 Poetry 1.0 was released and it is very good. Seriously, give it a try. There is a small problem though: Poetry uses venv for installing dependencies: when you add dependencies to a Poetry Python project, a new virtual environment is created where the dependencies are installed. Howev

Mon May 11 2020