diff --git a/content-org/posts.org b/content-org/posts.org new file mode 100644 index 0000000..fec5493 --- /dev/null +++ b/content-org/posts.org @@ -0,0 +1,271 @@ +#+HUGO_BASE_DIR: ../ +#+HUGO_SECTION: posts +:PROPERTIES: +:EXPORT_OPTIONS: author:nil +:END: +* Homelab :homelab: +** DONE HTTPS @ Home +:PROPERTIES: +:EXPORT_FILE_NAME: https-at-home +:EXPORT_DATE: 2022-11-08 +:EXPORT_HUGO_MENU: :menu "main" +:EXPORT_AUTHOR: +:END: + +I run a lot of services at home. + +This includes, but isn't limited to + +- [[https://archivebox.io/][ArchiveBox]] +- [[https://github.com/dani-garcia/vaultwarden][VaultWarden]] +- [[https://github.com/navidrome/navidrome][Navidrome]] +- [[https://plex.tv][Plex]] +- [[https://github.com/LibrePhotos/librephotos][LibrePhotos]] +- This blog + +and a lot more. + +Pretty much anything that's served up over HTTP is always nice if not +necessary to have behind TLS. + +[[https://letsencrypt.org/][LetsEncrypt]] long ago brought free certs to +the masses and there are a lot of tools for automating that nowadays. + +My preferred approach for getting all the unnecessary nonsense I +self-host at home behind TLS is [[https://caddyserver.com][Caddy]]. + +I have a super straight forward setup, generally: + +- Run Caddy in a docker container +- Create a wildcard CNAME record in my DNS pointing at my home's + (effectively) static IP +- Add an entry in my Caddyfile for each services I'm running at home on + its own subdomain +- If it's a service then I add it with a =reverse_proxy= block +- If it's a static site (like this) then there's a block for +- If it's something I want only accessible on my home network then I put + a block like + +#+BEGIN_EXAMPLE + @local_network { + path * + remote_ip + } +#+END_EXAMPLE + +in the directive. And voila. + +Then tell Caddy to reload the config and I'm done. + ++++ title = "My multiroom audio setup" date = "2022-11-08" +++ + +I've put my home audio solution together out of the following +components. + +- [[https://github.com/badaix/snapcast][Snapcast]] + +- [[https://www.musicpd.org/][MPD]] + +- [[https://github.com/librespot-org/librespot][Librespot]] + +- [[https://github.com/mikebrady/shairport-sync][Shairport-sync]] + +- A mini-PC in my closet running the above software + +- Two Raspberry Pi 4s + +- Four Raspberry Pi Zero Ws + +- Some desktop speakers and some Bluetooth speakers (wired to the Pis) + +Each of the Raspberry Pis is in a room or porch attached to a speaker. + +Snapcast lets me take an audio source and synchronize it across multiple +clients. Each of the Raspberry Pis are running a =snapclient= instance +and play whatever the =snapserver= instance tells them to. + +Snapcast is setup to send whichever of the streams (MPD, Spotify, +Shairport-sync/AirPlay) is playing audio to each of the clients that are +connected to it. + +This lets me or anyone else on my WiFi network play directly on one or +more of the speakers - each named for the room that they're in using +either Spotify, AirPlay, picking from my own music collection or by +pointing at a URL (like to a podcast episode). + +This works out great and we've used it at home for the past year. + +I'd like to get the podcast experience to a more seamless place but it's +pretty OK right now using AirMusic on my phone to play audio to the +speakers over AirPlay. +** TODO My multiroom audio setup +:PROPERTIES: +:EXPORT_FILE_NAME: snapcast +:EXPORT_DATE: 2022-11-08 +:EXPORT_HUGO_MENU: :menu "main" +:END: + +I've put my home audio solution together out of the following +components. + +- [[https://github.com/badaix/snapcast][Snapcast]] + +- [[https://www.musicpd.org/][MPD]] + +- [[https://github.com/librespot-org/librespot][Librespot]] + +- [[https://github.com/mikebrady/shairport-sync][Shairport-sync]] + +- A mini-PC in my closet running the above software + +- Two Raspberry Pi 4s + +- Four Raspberry Pi Zero Ws + +- Some desktop speakers and some Bluetooth speakers (wired to the Pis) + +Each of the Raspberry Pis is in a room or porch attached to a speaker. + +Snapcast lets me take an audio source and synchronize it across multiple +clients. Each of the Raspberry Pis are running a =snapclient= instance +and play whatever the =snapserver= instance tells them to. + +Snapcast is setup to send whichever of the streams (MPD, Spotify, +Shairport-sync/AirPlay) is playing audio to each of the clients that are +connected to it. + +This lets me or anyone else on my WiFi network play directly on one or +more of the speakers - each named for the room that they're in using +either Spotify, AirPlay, picking from my own music collection or by +pointing at a URL (like to a podcast episode). + +This works out great and we've used it at home for the past year. + +I'd like to get the podcast experience to a more seamless place but it's +pretty OK right now using AirMusic on my phone to play audio to the +speakers over AirPlay. +* Tooling :tooling: +** vi modal editing in most places +:PROPERTIES: +:EXPORT_FILE_NAME: vi-mode-everywhere +:EXPORT_DATE: 2022-11-13 +:EXPORT_HUGO_MENU: :menu "main" +:END: +For my sake, I prefer to have Vim bindings in as many places as +possible. + +Most shells can be configured to use Vim bindings by putting =set -o vi= +somewhere in your shell startup script. + +If you're using ZSH then you'll probably want an additional binding to +restore CTRL-R reverse history search. + +=bindkey '^R' history-incremental-search-backward= + +For CLI tools that use the =readline= library then you can configure its +input mode using a =.inputrc= file in your =$HOME= directory. + +This affects REPLs like =ghci= and tools like =psql=. + +#+begin_src txt +set editing-mode vi +$if mode=vi + +set keymap vi-command +# these are for vi-command mode +Control-l: clear-screen + +set keymap vi-insert +# these are for vi-insert mode +Control-l: clear-screen +$endif +#+end_src + +* AWS :aws: +** Structed and passively collected metrics via AWS CloudWatch +:EXPORT_FILE_NAME: cloudwatch-metric-filters +:EXPORT_DATE: 2022-11-12 +:EXPORT_HUGO_MENU: :menu "main" + +AWS is a vast and sprawling set of services. It can be hard to find the +hidden gems like this one so I wanted to point this one out. + +Structured metrics are very helpful to monitoring the health and +function of an software system. + +- Do you want to know how long a particular transaction typically takes? +- How fast your database queries are? +- How long external APIs take to respond? +- Fire an alert when a particular function on the site happens too many + times? Or too few times? + +...plus a million other things specific to whatever system you're +working on. + +There are a lot of great tools for doing this and one that you might not +know about is AWS CloudWatch Metric Filters. If you're already on AWS +then you should consider these because it requires only that your +application logs to CloudWatch. + +If you're on ECS then the +[[https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_awslogs.html][awslogs]] +log driver for Docker gets you that nearly for free. By "free" I mean +that your application itself can have /zero/ dependencies on AWS +services and not require any AWS credentials or libraries to start +pumping out metrics that you can visualize, alert on and record over +time. + +The +[[https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/MonitoringLogData.html][AWS +docs]] themselves offer the canonical reference for configuring these so +I won't go into detail here. + +However, the gist is that for a log filter you define the following +properties + +- A filter pattern for extracting a discrete metric value out of a log + entry +- A metric name to store the value in +- An optional dimension for sub-classifying the value +- And finally a log group to extract the metric values from + +After that you just run the application and as the logs roll in the +metric values get pumped out. Then you can +[[https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Create-alarm-on-metric-math-expression.html][define +alarms for alerting]] on them, +[[https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Dashboards.html][graph +them]], +[[https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-scaling-simple-step.html#policy-creating-alarm-console][define +autoscaling rules]] from them and more. + +To conclude - AWS is big and hairy. While there are benefits to staying +platform agnostic, some AWS services don't require much or any coupling +of your application code to take advantage of. Cloudwatch Metrics is one +of those services and you can get a lot of value out of it with not much +effort. + +* Musings :musings: +** TODO My job description +** TODO Managing expectations +** TODO Just let people be wrong +:EXPORT_FILE_NAME: trust-through-failure +:EXPORT_DATE: 2024-10-01 +:EXPORT_HUGO_MENU: :menu "main" + +Warning: This, like most things, will involve a fair bit of projection. + +I have some thoughts about collaboration. + +While a lot of this is obvious and well accepted, I think there are some fine points worth elaborating on. + +The obvious part is that people work better together when they believe they are trusted. Trust breeds initiative and independence. Distrust breeds resentment and inaction. + +Consider the flip side of trust, for a moment. + +A common way that people show _distrust_ when collaborating is either micromanaging or just coming in behind someone and redoing their work. + +If that demonstrates distrust then + +It's not enough that you simply _do_ trust someone else to get the benefits, you need to show it. I think this is the part that many people skip or ignore. + +This is, of course, true in general. diff --git a/content/posts/https-at-home.md b/content/posts/https-at-home.md new file mode 100644 index 0000000..30acee6 --- /dev/null +++ b/content/posts/https-at-home.md @@ -0,0 +1,99 @@ ++++ +title = "HTTPS @ Home" +date = 2022-11-08 +tags = ["homelab"] +draft = false +[menu] + [menu.main] + weight = 2001 + identifier = "https-home" ++++ + +I run a lot of services at home. + +This includes, but isn't limited to + +- [ArchiveBox](https://archivebox.io/) +- [VaultWarden](https://github.com/dani-garcia/vaultwarden) +- [Navidrome](https://github.com/navidrome/navidrome) +- [Plex](https://plex.tv) +- [LibrePhotos](https://github.com/LibrePhotos/librephotos) +- This blog + +and a lot more. + +Pretty much anything that's served up over HTTP is always nice if not +necessary to have behind TLS. + +[LetsEncrypt](https://letsencrypt.org/) long ago brought free certs to +the masses and there are a lot of tools for automating that nowadays. + +My preferred approach for getting all the unnecessary nonsense I +self-host at home behind TLS is [Caddy](https://caddyserver.com). + +I have a super straight forward setup, generally: + +- Run Caddy in a docker container +- Create a wildcard CNAME record in my DNS pointing at my home's + (effectively) static IP +- Add an entry in my Caddyfile for each services I'm running at home on + its own subdomain +- If it's a service then I add it with a `reverse_proxy` block +- If it's a static site (like this) then there's a block for +- If it's something I want only accessible on my home network then I put + a block like + + + +```text +@local_network { + path * + remote_ip +} +``` + +in the directive. And voila. + +Then tell Caddy to reload the config and I'm done. + +~~+~~ title = "My multiroom audio setup" date = "2022-11-08" ~~+~~ + +I've put my home audio solution together out of the following +components. + +- [Snapcast](https://github.com/badaix/snapcast) + +- [MPD](https://www.musicpd.org/) + +- [Librespot](https://github.com/librespot-org/librespot) + +- [Shairport-sync](https://github.com/mikebrady/shairport-sync) + +- A mini-PC in my closet running the above software + +- Two Raspberry Pi 4s + +- Four Raspberry Pi Zero Ws + +- Some desktop speakers and some Bluetooth speakers (wired to the Pis) + +Each of the Raspberry Pis is in a room or porch attached to a speaker. + +Snapcast lets me take an audio source and synchronize it across multiple +clients. Each of the Raspberry Pis are running a `snapclient` instance +and play whatever the `snapserver` instance tells them to. + +Snapcast is setup to send whichever of the streams (MPD, Spotify, +Shairport-sync/AirPlay) is playing audio to each of the clients that are +connected to it. + +This lets me or anyone else on my WiFi network play directly on one or +more of the speakers - each named for the room that they're in using +either Spotify, AirPlay, picking from my own music collection or by +pointing at a URL (like to a podcast episode). + +This works out great and we've used it at home for the past year. + +I'd like to get the podcast experience to a more seamless place but it's +pretty OK right now using AirMusic on my phone to play audio to the +speakers over AirPlay. diff --git a/hugo.toml b/hugo.toml index 03a59c3..0a70d0e 100644 --- a/hugo.toml +++ b/hugo.toml @@ -5,11 +5,14 @@ theme = 'dark-theme-editor' # Support Taxonomies [taxonomies] - autor = "James brechtel" + author = "James brechtel" tag = "tags" category = "categories" _merge = "deep" - + +[markup.goldmark.renderer] + unsafe = true + # Theme parameters [params] diff --git a/posts.org b/posts.org deleted file mode 100644 index b10b693..0000000 --- a/posts.org +++ /dev/null @@ -1,53 +0,0 @@ -#+HUGO_BASE_DIR: . -* Homelab -** HTTPS @ Home -:PROPERTIES: -:EXPORT_FILE_NAME: https-at-home -:EXPORT_DATE: 2022-11-08 -:EXPORT_HUGO_MENU: :menu "main" -:END: - -I run a lot of services at home. - -This includes, but isn't limited to - -- [[https://archivebox.io/][ArchiveBox]] -- [[https://github.com/dani-garcia/vaultwarden][VaultWarden]] -- [[https://github.com/navidrome/navidrome][Navidrome]] -- [[https://plex.tv][Plex]] -- [[https://github.com/LibrePhotos/librephotos][LibrePhotos]] -- This blog - -and a lot more. - -Pretty much anything that's served up over HTTP is always nice if not -necessary to have behind TLS. - -[[https://letsencrypt.org/][LetsEncrypt]] long ago brought free certs to -the masses and there are a lot of tools for automating that nowadays. - -My preferred approach for getting all the unnecessary nonsense I -self-host at home behind TLS is [[https://caddyserver.com][Caddy]]. - -I have a super straight forward setup, generally: - -- Run Caddy in a docker container -- Create a wildcard CNAME record in my DNS pointing at my home's - (effectively) static IP -- Add an entry in my Caddyfile for each services I'm running at home on - its own subdomain -- If it's a service then I add it with a =reverse_proxy= block -- If it's a static site (like this) then there's a block for -- If it's something I want only accessible on my home network then I put - a block like - -#+BEGIN_EXAMPLE - @local_network { - path * - remote_ip - } -#+END_EXAMPLE - -in the directive. And voila. - -Then tell Caddy to reload the config and I'm done.