We are going to serve a Quarto site behind an OAuth proxy to make it private, as described here.
-
You have taken the first tutorial.
-
A custom domain that you don't mind experimenting with. If you don't have one, you can buy one here. In this example, I'm using the custom domain
hamel.rsvp
.
Render is a hosting service that provides a generous free tier. We just have to learn a little bit about their YAML, but if you did the first tutorial, it will be approachable.
Render also has Oauth2 Proxy tutorial which is pretty close to what we want. We are going to simplify that example considerably, while also getting rid of things that aren't free.
-
Optional: Change the content of your site by editing one of the
.qmd
files, then runquarto render
to re-generate the content into the_site/
folder. Make sure you check-in any changes, including the_site
folder into your repo. -
Click this link to deploy the app, and grant Render access to the repo you just forked. Next, fill in values for the
OAUTH2_PROXY_CLIENT_ID
andOAUTH2_PROXY_CLIENT_SECRET
:
- Create another OAuth application and save the
Client ID
andClient Secret
as you did in the minimal example. You can fill it out like this:
Homepage URL can also be a subdomain of a custom domain you own (e.g. private.hamel.rsvp
). If using Netlify, just type in whatever you want the subdomain to be for now, and then add a CNAME
DNS record once you've deployed your site on Render.
- Set up your custom domain on Render by navigating to your dashboard and clicking on this project, which is named
oauth2-proxy-render
(unless you changed it). On the left-hand side clickSettings
. UnderSettings
, scroll down to the section namedCustom Domains
. Add your domain there and follow the instructions. Render will take care of provisioning an SSL certificate to enablehttps
on your domain for you.
Anytime your push a change to your repo, your site will rebuild. Try misspelling your email in the email_list.txt
file and see what happens, then try changing it back. Warning: if you revoke/grant access, it takes 2-3 minutes for it to take effect, and you may have to clear your cache - be patient!
See the repo's README.
These are some alternatives to Render that work similarly.
You might not like serverless solutions. They can often be harder to debug. However, you can host a blog on a VM as well. Here are some tips if you are hosting things on a VM.
-
You might want to use Caddy or Nginx as your web server. Caddy is easier to use and just as powerful. Both of these servers facilitate automatically provisioning SSL certificates for
https
(but it requires some setup). Even though OAuth2 Proxy can be a web server itself, it is convenient to put one of these in front of the proxy for the automatic SSL functionality. Furthermore, this setup gives you the flexibility to host a mix of private and public sites from the same VM. -
If you have a web server that handles SSL for you that forwards traffic to the OAuth2 Proxy, your OAuth2 proxy will likely receive
http
traffic from the web server. Therefore, you might want to configure yourdocker run
command accordingly:
The below command assumes:
- There is an
app/emails
andapp/site
directory in the current directory. - You have set the
OAUTH2_PROXY_COOKIE_SECRET
,OAUTH2_PROXY_CLIENT_ID
, andOAUTH2_PROXY_CLIENT_SECRET
environment variables.
docker run -v $(pwd)/app/site:/app \
-v $(pwd)/app/emails:/site_config \
-p 4180:4180 \
quay.io/oauth2-proxy/oauth2-proxy \
--provider github \
--upstream "file:///app/#/" \
--http-address=":4180" \
--authenticated-emails-file "/site_config/email_list.txt" \
--scope user:email \
--cookie-expire 0h0m30s \
--session-cookie-minimal true \
--skip-provider-button true \
--cookie-secret $OAUTH2_PROXY_COOKIE_SECRET \
--client-id $OAUTH2_PROXY_CLIENT_ID \
--client-secret $OAUTH2_PROXY_CLIENT_SECRET \
--cookie-csrf-per-request=true
In the above example, you would have your webserver forward traffic to localhost:4180
.
- Use rsync to update your static site or email white list when necessary. For example, this is how I would sync my local files with my VM in this case:
rsync -a email_list.txt myvm:/home/ubuntu/app/emails/
rsync -a _site/* myvm:/home/ubuntu/app/site
I recommend updating your ~/.ssh/config
file so that you can reference your VM with a name like myvm
, as shown above. For example, this is the relevant part of my ~/.ssh/config
, which has the IP, username, and location of the private key I need to access my VM.
Host myvm
HostName 111.22.333.44 # your VM's Public IP Address
User ubuntu # The username you need to login
IdentityFile /Users/hamelsmu/.ssh/vm_private_key.rsa
As an advanced exercise, I show how to do this same thing on Kubernetes. That example:
- Deploys a website on Kubernetes behind a load balancer with the OAuth proxy.
- Sets up automated SSL for
https
with Google Managed Certificates - Deploys a separate webserver for the website to make the pattern more generalizable.
Deploying this on Kubernetes is much more complicated, but is something I wanted to play with.