Suranyami

Polyglot developer, geometric tessellation fan, ambient DJ.

My current Homelab server rack:

  • Turing Pi 2 cluster, now with 4 x RK1 3588 8-core arm_64 CPUs with 32GB RAM each (not shown in pictures below), 6 TOPS NPU, in a 2U Silverstone rack-mount case, fans, 8-bay hot-swappable SSDs, 4TB SSDs x 4
  • a bunch or Raspberry Pi 4s (4GB x 2, 8GB x 1, 1TB NVMe SSDs in Argon One cases)
  • Radxa Rockchip 5B 16GB RAM, 4TB NVMe. 8-core arm_64, 6 TOPS NPU + case
  • Argon Eon, RasPi 4, 4GB RAM 4 x 4TB SSD
  • Radxa Penta NAS kit with RockChip 4 4GB + 4 x 4TB SATA SSDs
  • UPS + surge protection, because we had a power surge during a storm here a few months ago that destroyed one of the RasPi CM4s I had in the Turing Pi 2, a power supply, and a 15” portable LCD monitor… expensive power surge! It’s the 21st century… you’d think these things wouldn’t happen any more, but they do.

This is all instrumented by a Portainer/Docker Swarm setup running:

  • Nginx-Proxy-Manager (Simple reverse proxy manager)
  • DuckDNS (Dynamic DNS)
  • Minecraft Server (suranyami.duckdns.org:25565)
  • Awwesome Self-Hosted Browser link (no login required)
  • Excalidraw (FOSS collaborative drawing webapp, no login required)
  • Homarr (Home page for all my services)
  • Home Assistant (IoT control for smart devices)
  • Jackett
  • Joplin Server (Knowledge Base)
  • Netdata monitoring on most nodes
  • Ollama + Ollama WebUI (really slow ATM… installing NPU drivers this weekend, coz the RockChip 3588s have 6 TOPS of neural processing)
  • Overseer
  • Plex Media Server
  • Radarr
  • Sonarr
  • Tautulli
  • Tdarr
  • IT-Tools (No login needed). Check it out! It’s very useful!
  • Transmission (Torrents)
  • Uptime-Kuma (Uptime monitoring)
  • WG-Easy Wireguard VPN management
  • GlusterFS distributed File System with 2 x redundancy, 1 unified storage volume of 18TB in total

Discuss...

Today I needed to different layouts for public-facing and authorised pages in a LiveView app.

After an annoying amount of digging in documentation and forums, the following was the most elegant solution I found.

Assume we have these layouts in myapp/lib/myapp_web/components/layouts/:

authenticated.html.heex
public.html.heex

And, also assuming that there is something different in each layout: stuff you can't use unless signed in.

In lib/myapp_web/router.ex modify these authentication routes to add a layout: in the live_session statements:


  scope "/", MyappWeb do
    pipe_through [:browser, :redirect_if_user_is_authenticated]

    live_session :redirect_if_user_is_authenticated,
      on_mount: [{MyappWeb.UserAuth, :redirect_if_user_is_authenticated}],
      layout: {MyappWeb.Layouts, :public} do
      live "/users/register", UserRegistrationLive, :new
      live "/users/log_in", UserLoginLive, :new
      live "/users/reset_password", UserForgotPasswordLive, :new
      live "/users/reset_password/:token", UserResetPasswordLive, :edit
    end

    post "/users/log_in", UserSessionController, :create
  end

  scope "/", ReflectalWeb do
    pipe_through [:browser, :require_authenticated_user]

    live_session :require_authenticated_user,
      on_mount: [{MyappWeb.UserAuth, :ensure_authenticated}],
      layout: {MyappWeb.Layouts, :authenticated} do
      live "/dashboard", DashboardLive.Show, :show
      live "/users/settings", UserSettingsLive, :edit
      live "/users/settings/confirm_email/:token", UserSettingsLive, :confirm_email
    end
  end

The important lines here are:

      layout: {MyappWeb.Layouts, :public} do

and

      layout: {MyappWeb.Layouts, :authenticated} do

Simple!

Discuss...

Here's a top tip to avoid:

Ironbark smoke is abso-fucking-lutely vile. Do not use a couple of ironbark logs in your smoker unless they have completely burnt down to embers and can be used to ignite something that doesn’t make everything taste like sadness and other people’s headaches.

I just managed to ruin an entire barbecue this way. Learn from my stupidity: just never do this.

Discuss...

Countries

Language

(ni) ほん (hon)(go) Japanese (language)


えい (ei)(go) English (language)

Nationality

(ni) ほん (hon) じん ( jin) Japanese (person)
えい (ei)(go)
English (language)

Nationality

(ni) ほん (hon) じん ( jin)
Japanese (person)

Discuss...

I had a bit of a mystery that was bugging me for ages. After enabling automatic formatting for Elixir files in VSCode, I was getting ugly highlighting that looked like this:

Ugly highlighting

It turns out this is a feature of the RainbowIndents extension to show you where you have inconsistent indenting (e.g. 3 spaces, when everything else is 2).

The problem with this is mix format has unchangeable opinions about indenting, such as in a with statement, where it cares more about alignment than even/odd indent boundaries.

The fix is to exclude indentation errors for Elixir. In your settings.json add this:

This was the fix.

With that in place, we now get plain ol' rainbow indenting:

Fixed!

Discuss...

This first appeared in a forum post on community.fly.io

I've updated it a bit with some clarifications and a fix for a version-clash issue I had.

Setup the project

$ mix phx.new hello  --umbrella --no-ecto --install
$ cd hello_umbrella

Enable server in config/runtime.exs:

config :hello_web, HelloWeb.Endpoint, server: true

Add elixir_buildpack.config with the preferred Erlang and Elixir versions:

$ cat <<EOF>./elixir_buildpack.config
elixir_version=1.14
erlang_version=24.3
EOF

I had problems with too-specific versions in the above, so just use major versions, e.g. elixir_version=1.14 versus elixir_version=1.14.3-otp-24

Deploy the assets from within the web app directory:

$ cd apps/hello_web
$ MIX_ENV=prod mix assets.deploy
$ cd ../../

Setup the Fly stuff

$ fly launch

Answer “no” to deploy request and leave fly launch, then set up the secret:

$ export SECRET_KEY_BASE=$(mix phx.gen.secret)
$ fly secrets set SECRET_KEY_BASE=$SECRET_KEY_BASE

Deploy:

$ fly deploy

Enjoy your app!

$ fly open

and the umbrella application is finally happily up and running!

Summary

Besides the steps above, here are the summary of the current differences in how Fly handles deployment between plain and umbrella.

to deploy an Umbrella via Fly:

  • you have to explicitly set server: true in config/runtime.exs
  • you have to add the required elixir_buildpack.config file to the project
  • you have to build the application assets
  • you have to set the SECRET_KEY_BASE executing fly secrets after fly launch and before fly deploy (you can’t just export it to an environment variable)
  • the Fly builder will not generate a Docker file as is the case with plain apps (but if you supply one, the builder will use it)

Discuss...

Install iperf

on MacOS:

brew install iperf

on Linux:

sudo apt install iperf -y

Start iperf on the server:

iperf -s

This waits for incoming connections from clients. Designate another machine as a client and run this command, substituting the IP address of your server machine for the sample one here:

iperf -c 192.168.1.2

Results

Setup was:

LAN config

Results were:

> iperf -c 192.168.1.238
------------------------------------------------------------
Client connecting to 192.168.1.238, TCP port 5001
TCP window size:  128 KByte (default)
------------------------------------------------------------
[  1] local 192.168.1.91 port 58359 connected with 192.168.1.238 port 5001 (icwnd/mss/irtt=11/1448/12000)
[ ID] Interval       Transfer     Bandwidth
[  1] 0.00-10.28 sec  63.9 MBytes  52.1 Mbits/sec

Discuss...

When setting up profiles for AWS locally, start with your own credentials as default, then add profile entries for the different environments. e.g.

# ~/.aws/config

[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

[profile staging]
role_arn = arn:aws:iam::0987654321:role/staging
source_profile = default
region = ap-southeast-2
output = json

[profile prod]
role_arn = arn:aws:iam::5678901234:role/prod
source_profile = default
region = ap-southeast-2
output = json

Discuss...

Well, of course Snoop Dogg has a cookbook with an introduction by Martha Stewart, and yes, I did buy it, thanks for asking.

Quick review: this cookbook is ideally something you give to a stoner teen that’s about to move out of home for the first time. The recipes are super-basic, with some nice twists, but require no complicated ingredients and the processes will not stretch anyone’s brain.

The layout and text are a lot of good, clean fun and nothing is taken too seriously. From that point of view, he’s done a great job at making cooking for yourself more accessible.

I’d keep this to give to my daughter when/if she moves out, but she’s already awesome at making schnitzel, bake cakes and muffins, etc. and she’s only 12, so I think she’ll be fine by the time she’s in her late teens…

Discuss...

date "+%Y-%m-%d"

Mucked around trying to get this right before realising I'd left out the + symbol in the format string. Derp.

Discuss...

Enter your email to subscribe to updates.