Recently I thought it was a good idea to purchase the itshonest.work domain to do the funniest thing ever (maybe), nothing too interesting, but I learned a couple of things I want to write down. I suggest you give the repo a check before moving on tho, if you are too lazy here is a TLDR for the "architecture":
index.html and abiw.png are uploaded to Cloudflare R2/ to /index.html, as R2 doesn't serve a default documentBy default R2 files are not cached, as you can see by consulting the cf-cache-status:
$: curl -s -o /dev/null -D - https://aintmuch.but.itshonest.work/abiw.png | grep "cache"
cf-cache-status: DYNAMIC
DYNAMIC means that abiw.png was requested from the origin web server, but, what's a Cloudflare without a caching? Let's fix that by creating a caching rule:
{
"expression": "(http.host eq \"aintmuch.but.itshonest.work\")",
"description": "cache everything forever",
"action": "set_cache_settings",
"action_parameters": {
"cache": true,
"edge_ttl": {"mode": "override_origin","default":31536000},
"browser_ttl": {"mode":"override_origin","default":31536000}
}
}
So what? HITting cache now? you bet:
$: curl -s -o /dev/null -D - https://aintmuch.but.itshonest.work | grep "cache"
cache-control: max-age=31536000
cf-cache-status: HIT
In order to add a rule, we have to create a ruleset first, check abiw.sh.
Apparently I am doing nix now, and with this comes a nice approach to secret management.
The flake pins two inputs beyond nixpkgs:
filosottile/ageThe devShell provides age, agenix, jq, and liquidprompt (defintely unnecessary, but I like it). The shellHook sources liquidprompt and then runs the agenix-shell installation script, which decrypts three secrets (CLOUDFLARE_API_TOKEN, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY). This is super handy for development as it means i can just copy a command from the script and run it without having to worry about manually setting them.
Decryption uses a private SSH key located at /tmp/rc-ssh-key I extract from my Bitwarden vault with:
bw get item $(bw list items --search "rc-ssh-key" | jq -r '.[].id') | jq -r '.sshKey.privateKey' > /tmp/rc-ssh-key
The matching public key is fetched at eval time from https://git.rcast.dev/rc.keys inside secrets.nix, which declares which public keys can decrypt each secret file.
Each .age file is the encrypted ciphertext of the corresponding secret, this is safe to commit, because they can only be decrypted by whoever holds the matching private key (aka me).
To set or rotate a secret I run, e.g.:
agenix -e CLOUDFLARE_API_TOKEN.age
This is quickly becoming my favourite approach to secret management, if you don't like nix you can use jdx/fnox, perhaps in combination with jdx/mise, to achieve something similar.
Uploading a file to S3 is easy with curl:
curl -X PUT "https://$ACCOUNT_ID.r2.cloudflarestorage.com/$BUCKET_NAME/abiw.png" \
--aws-sigv4 "aws:amz:auto:s3" \
--user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
--upload-file abiw.png \
-H "Content-Type: image/png"
Yup, I hear you, yet another curl W, hard to disagree.
This setup is essentially free to run, as Cloudflare free tier includes:
P.S: I am not a paid shill, I do this for free :P
It ain't much, but it's honest work, someone may say :)