Caddy your Serverless Functions
(image from Ryan De Hamer)
Use Caddy to bring your serverless functions under one "custom domain" roof, with automatic HTTPS.
Why host your own API gateway?
First a public service announcement:
Each of the major cloud providers have an API management service that works well with their functions-as-a-service product. You may prefer to use that instead of hosting your own server.
For my personal project I wanted to:
- bring together my cloud functions under a custom domain, rather than expose cloud function endpoints separately
- roll my own gateway on a Digital Ocean droplet, using Docker, Docker Compose and Caddy. I enjoy the engineering journey and flexibility this combination offers
- have automatic HTTPS support
- keep it simple since I'm hosting it myself
Configuring Caddy v2
Caddy is an open source web server that offers a streamlined configuration for automatic HTTPS (by handling the certificate renewal for you) and reverse proxying.
This configuration example shows how to hide https://us-central1-abc123.cloudfunctions.net/myCloudFunction
beyond a custom domain and expose the function at https://myfunction.mydomain.com/add
https://myfunction.mydomain.com {
tls myemail@gmail.com
handle_path /add* {
rewrite * /myCloudFunction{uri}
reverse_proxy {
header_up Host "us-central1-abc123.cloudfunctions.net"
to https://us-central1-abc123.cloudfunctions.net
}
}
log {
output file /logs/myfunction.mydomain.com.log
}
}
Here are the highlights:
tls
configures automatic HTTPS forhttps://myfunction.mydomain.com
handle_path
handles the "/add" route and then rewrites the url by stripping the incoming "/add" and thenrewrite
add the cloud function namereverse-proxy
forwards the request to the newly formed URL and returns the results- the
Host
header is required so the cloud provider (Google Cloud in this case) knows where to find the function. It avoids "The requested URL /myCloudFunction/ was not found on this server" error.
If you're currently using an older version of Caddy (v1)
Caddy v2 was released in May 2020 and I recently went through the exercise of upgrading my Caddy v1 configuration and ran into a couple of challenges:
-
There weren't easy-to-find examples for the scenario I was interested in, so after playing for awhile I reached out to the Caddy team to help me convert the one-line
proxy
directive in v1 to a combination ofreverse-proxy
,handle_path
andrewrite
in v2. -
That got me closer, though Google Cloud was still returning a 404 for
myCloudFunction
. After researching SNI and hints around the internet, the key was addingheader_up Host "us-central1-abc123.cloudfunctions.net"
to avoid "The requested URL /myCloudFunction/ was not found on this server" error.
For reference, here was my original configuration from Caddy v1's:
https://myfunction.mydomain.com {
tls myemail@gmail.com
proxy /add https://us-central1-abc123.cloudfunctions.net/myCloudFunction
errors /log/myfunction.mydomain.com.errors.log
log / /log/myfunction.mydomain.com.log "{combined}" {
rotate_size 100
rotate_keep 10
}
}
Wrapping up
As an engineer, hosting your own server with open source technology is a great way to stay sharp and learn about what's happening behind-the-scenes.