Custom domains

· team pico

it's as easy as a DNS entry
#feature

It's been a pretty exciting week for us at the pico.sh headquarters.

We made it to the front-page of hackernews!

front-page of hacker news

We were so excited about the launched that we announced in the thread support for custom domains landed.

We figured it would be a good idea to officially announce it on our blog.

# Add your custom domain today!

Don't want to be bored with the details of how custom domains work?

The full usage guide can be found on our help page.

# How it works

We decided to go with a solution that didn't require us to store any information about the custom domain you want to use. Instead, all the user needs to do is add a TXT record and then point the domain with a CNAME to prose.sh.

Under the hood we use Caddy's on-demand tls. On our end, the configuration was very simple using Caddyfile:

{
	on_demand_tls {
		ask http://web:3000/check
		interval 1m
		burst 10
	}
}

:443 {
	reverse_proxy web:3000
	tls hello@prose.sh {
		on_demand
	}
	encode zstd gzip
}

The endpoint referenced in the above Caddyfile points to this golang function:

 1func checkHandler(w http.ResponseWriter, r *http.Request) {
 2	dbpool := GetDB(r)
 3	cfg := GetCfg(r)
 4
 5	if cfg.IsCustomdomains() {
 6		hostDomain := r.URL.Query().Get("domain")
 7		appDomain := strings.Split(cfg.ConfigCms.Domain, ":")[0]
 8
 9		if !strings.Contains(hostDomain, appDomain) {
10			subdomain := GetCustomDomain(hostDomain)
11			if subdomain != "" {
12				u, err := dbpool.FindUserForName(subdomain)
13				if u != nil && err == nil {
14					w.WriteHeader(http.StatusOK)
15					return
16				}
17			}
18		}
19	}
20
21	w.WriteHeader(http.StatusNotFound)
22}

This function does a couple of things. It gets the current domain from the request and then performs a TXT lookup via GetCustomDomain:

 1func GetCustomDomain(host string) string {
 2	records, err := net.LookupTXT(fmt.Sprintf("_prose.%s", host))
 3	if err != nil {
 4		return ""
 5	}
 6
 7	for _, v := range records {
 8		return strings.TrimSpace(v)
 9	}
10
11	return ""
12}

If the username matches then we respond with a success status. That's really all there is to it.

It's amazing how far we've come with TLS, isn't it?

# Wrap up

This is just one of many features we have planned to make prose.sh awesome. We also have a handful of sibling services we are thinking about building.


Join our irc #pico.sh on libera or email us at ~erock/pico.sh@lists.sr.ht.

Be sure to subscribe to our rss feed to get the latest updates at team pico.