Custom domain setup with AWS Route53 and Cloudfront

I’m trying to set up a custom domain. I use AWS Route53 hosted zones to manage DNS.

At the moment, I have a CNAME for “plastic.flyinggrizzly.net” pointed at “publish-main.obsidian.md”, and the custom domain setting in Obsidian set to “plastic.flyinggrizzly.net

The DNS is working, but I’m getting caught out by SSL cert mismatches (which makes sense).

I don’t have access to a web server that I can use to proxy or rewrite URLs, and I cannot move away from Route53.

Am I missing some obvious step, or is this a “wait for Route53 support” kind of situation?

https://help.obsidian.md/Licenses+%26+add-on+services/Obsidian+Publish#Custom+domain

I’ve already been through the docs a few times. I was hoping someone might have a workaround…

I have an idea, but did not test it.

You could create a CloudFront Web-Distribution with your domain hosted in AWS Route 53 and a free certificate from Certificates Manager and you set the Origin to the obsidian publish domain.

I was also looking in a way to use my custom domain hosted on AWS before subscribing to the publish addon.

For more option on AWS see also

1 Like

Or you could setup a small VM
on Oracle Cloud Free Tier, which includes 1TB traffic per month, setup nginx and follow the obsidian guide to setup this as reverse proxy. In Route 53 you can create an A record instead of CNAME pointing to the IP of the VM.

Thank you! I had already tried the Cloudfront approach, but was getting origin errors out of it once I hooked it up to Route53. I also don’t think it was going to cleanly handle the change from publish.obsidian.md/plamo-flyinggrizzly-net to plastic.flyinggrizzly.net, but I’ll check out the other options in the AWS doc.

Though I had not considered the Lambda@Edge option for rewriting requests… I’ll look at that too!

I had considered setting up an EC2 instance to run a reverse proxy, but I don’t really want to have to run a web server just for this… (or use yet another PaaS provider…)

Thank you!

This turned out to be easier than expected, but took some hunting. This solution assumes 2 things:

  • your custom Obsidian domain is a subdomain that you can define in Route53
  • your custom Obsidian domain does not include subdirectories (e.g. plamo.flyinggrizzly.net, not flyinggrizzly.net/plamo or hobbies.flyinggrizzly.net/plamo)

This approach uses the custom HTTP X-Header to indicate to Publish what site it’s serving.

Steps

  1. Choose your custom domain, like notes.example.com
  2. Create a Cloudfront distribution in AWS, with these settings:
    • Set the origin to publish.obsidian.md
    • Give it an alternate domain value that’s the same as your custom domain, so that it won’t error when we start routing to it from our DNS
    • Assign an SSL cert (this might be one you already have, if you have a wildcard cert for subdomains like *.example.com)
    • Set a custom header, with a name of X-Obsidian-Custom-Domain and a value of notes.example.com (/replace with your custom domain)
  3. In Route53, add a DNS CNAME entry for your subdomain, pointing at your Cloudfront distro’s URL (be sure to remove the https:// if you used the “Copy” button on the distribution page)
  4. Set your custom domain in the Obsidian Publish config settings

Give the DNS and CDN a minute to propagate, and you should now be able to access your published notes at your custom domain.

Other configurations

Obviously, the above is assuming you are using a subdomain without subdirectories.

I suspect this would work for a sub-folder, either by including that in the X-Header’s value, or firing a Lambda@Edge function on Viewer Request events.

The lambda could be used to rewrite your request URIs and get finer-grained control over the path patterns if there’s a mismatch between your filepaths in Obsidian and the request URLs being handled by Cloudfront. Something like this (not tested!):

// Running on Node 14.x runtime

exports.handler = (event, context, callback) => {
    const OBSIDIAN_CUSTOM_BASE_DOMAIN = 'example.com'
    
    const request = event.Records[0].cf.request
    
    // Identify the requested note resource path
    const path = request.uri

    // Update the request URI to hit Publish's serve endpoint
    request.uri = '/serve'
    
    request.querystring = `url=${OBSIDIAN_CUSTOM_BASE_DOMAIN}${path}`
    
    return callback(null, request)
};

2 Likes

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