Year: 2023

  • Proxmox on Hetzner Setup Notes

    Installation

    Basic installation over plain debian https://pve.proxmox.com/wiki/Install_Proxmox_VE_on_Debian_12_Bookworm

    Network config

    Network configs derived from: https://community.hetzner.com/tutorials/install-and-configure-proxmox_ve

    sysctl -w net.ipv4.ip_forward=1
    sysctl -w net.ipv6.conf.all.forwarding=1

    Proxmox host /etc/network/interfaces

    This example is for the main IPv4 of 157.90.92.151 with two subnets of 157.90.196.48/28 and 162.55.142.192/28. The IPv4 gateway is derived from the existing Hetzner configs given on install.

    source /etc/network/interfaces.d/*

    auto lo
    iface lo inet loopback
    iface lo inet6 loopback

    auto enp8s0
    iface enp8s0 inet static
    address 157.90.92.151
    netmask 255.255.255.255
    pointopoint 157.90.92.129
    gateway 157.90.92.129

    iface enp8s0 inet6 static
    address 2a01:4f8:252:3e22::2
    netmask 128
    gateway fe80::1

    auto vmbr0
    iface vmbr0 inet static
    address 157.90.92.151
    netmask 255.255.255.255
    bridge_ports none
    bridge_stp off
    bridge_fd 0
    pre-up brctl addbr vmbr0
    up ip route add 157.90.196.48/28 dev vmbr0
    up ip route add 162.55.142.192/28 dev vmbr0
    down ip route del 157.90.196.48/28 dev vmbr0
    down ip route del 162.55.142.192/28 dev vmbr0
    post-down brctl delbr vmbr0

    iface vmbr0 inet6 static
    address 2a01:4f8:252:3e22::2
    netmask 64

    The important bits here are sysctl forwarding and routing our guest subnet to vmbr0.

    Also need to systemctl disable --now rpcbind.socket per Hetzner rules.

    Debian guest config

    Subnet: 157.90.196.48/28

    auto ens18
    iface ens18 inet static
    address 157.90.196.48/32
    # or address 157.90.196.X/32
    gateway 157.90.92.151

    iface ens18 inet6 static
    # in this case i'm using the same ending as ipv4
    address 2a01:4f8:252:3e22::48/64
    gateway 2a01:4f8:252:3e22::2

    /etc/apt/sources.list

    deb http://mirror.hetzner.de/debian/packages bookworm main
    deb http://mirror.hetzner.de/debian/packages bookworm-updates main
    deb http://mirror.hetzner.de/debian/packages bookworm-backports main
    deb http://mirror.hetzner.de/debian/security bookworm-security main

    deb http://security.debian.org bookworm-security main

    /etc/resolv.conf

    These are specifically Hetzner’s internal resolvers.

    nameserver 213.133.100.100
    nameserver 213.133.98.98
    nameserver 213.133.99.99
    nameserver 2a01:4f8:0:1::add:1010
    nameserver 2a01:4f8:0:1::add:9999
    nameserver 2a01:4f8:0:1::add:9898
  • We saw Vulfpeck in Brooklyn

    Great show, so much talent!

    Unfortunately, they didn’t do an encore because we went to the early show.

  • Mastodon Admin Notes

    This is the cron job that runs daily to do media and federation data cleanup:

    #!/bin/sh
    
    printf "%s: running cleanup tasks\n" "$(date)"
    RAILS_ENV=production /home/mastodon/.rbenv/shims/ruby /home/mastodon/live/bin/tootctl media remove --days=7
    RAILS_ENV=production /home/mastodon/.rbenv/shims/ruby /home/mastodon/live/bin/tootctl media remove --days=7 --remove-headers
    RAILS_ENV=production /home/mastodon/.rbenv/shims/ruby /home/mastodon/live/bin/tootctl media remove --days=7 --prune-profiles
    RAILS_ENV=production /home/mastodon/.rbenv/shims/ruby /home/mastodon/live/bin/tootctl media remove-orphans
    RAILS_ENV=production /home/mastodon/.rbenv/shims/ruby /home/mastodon/live/bin/tootctl preview_cards remove --days=30
    
    printf "%s: dumping db\n" "$(date)"
    pg_dump -Fc mastodon_production | ssh rsync "dd of=mastodon/db.dump"
    
    date
    

    This is the wrapper script I use to make sure I restart all necessary processes after updates.

    root@mastodon:~# cat /usr/local/bin/masto
    #!/bin/sh
    
    case $1 in
            start|restart|stop|status)
                    printf "%sing mastodon services\n" "$1"
                    ;;
    
            logs)
                    exec journalctl -fu mastodon-\*
                    ;;
            *)
                    printf "%s: invalid action. try logs, status, start, stop, restart.\n" "$1"
                    exit 1
                    ;;
    esac
    
    exec systemctl $1 mastodon-web \
            mastodon-streaming \
            mastodon-sidekiq@default \
            mastodon-sidekiq@pull \
            mastodon-sidekiq@push \
            mastodon-sidekiq@mailers \
            mastodon-sidekiq@scheduler \
            mastodon-sidekiq@ingress
    

    The mastodon-sidekiq@.service units were added to address queues backing up and is essentially the same as the default unit file but with the -q queue name parameter added.

  • Some good podcasts

    These are some of my favorite podcasts. Check them out if you’re so inclined.

    NameBlurbStatus
    1619examining the propaganda of american historyEnded
    20k hertzstories behind the world’s most recognizable and interesting sounds
    99% Invisiblehow design shapes our lives
    A Way With Wordsinteresting discussions on language
    The Anthropocene Reviewed2 topics rated on a 5-star scale
    Ask Me AnotherNPR trivia showEnded
    Benjamen Walker’s Theory of Everythingsome fiction and wild stories – i originally found tilde.club from this episode
    Broken Recordliner notes for the digital age with malcolm gladwell and rick rubin
    Ear Hustletales from prison shared by those inside
    Endless Threadstories from cool things found on reddit
    Everything is Aliveian chillag interviews inanimate objects
    Hello Internettwo youtubers (brady haran and cgp grey) discuss internet thingsEnded
    Invisibiliascience and stories about the invisible forces that affect and steer our livesEnded
    LeVar Burton Readslevar burton hand picks short fiction and reads it to you
    Lingthusiasma podcast that explores the hidden linguistic patterns and features of languages around the world
    On the Mediaa weekly investigation into how the media shapes our worldview
    Radiolaban exploration of science
    Reply Alla podcast about the internet that explores modern life and how to survive it: start hereEnded
    Rough Translationstories about language and interactions across the worldEnded
    The Allusionista language podcast by helen zaltzman
    The Bugleaudio newspaper for a visual world
    The Truthmovies for your ears – short audio fiction stories
    The Unmade Podcasttim and brady discuss podcast ideas that they probably won’t make
    This American Lifestories compiled for radio and podcast by wbez chicago
    Wait Wait Don’t Tell Menpr’s weekly news quiz show
  • Keep it Simple

    I run two weekly pinball tournaments here in Traverse City (https://tcpinball.org/) which we submit to the IFPA for global rankings.

    The IFPA charges a $1 per player fee to be “sanctioned”. This fee is generously sponsored by each location that we run tournaments at. Thinking it’d be easy enough to pull back the player counts later on, I put the fee payments on my credit card and figured I’d get reimbursed later on.

    This is what the stats page shows on IFPA, which is not useful to me, but it shows I’ve paid $568 as of this date in fees. I need to know how much each location owes me.

    I spent probably 4 hours yesterday digging through the API docs for matchplay and the IFPA directly trying to get a count of players by location.

    I ended up writing some code which didn’t quite solve it either. The list of tournaments that it gives back doesn’t include the player count, meaning I have to make another API call to get the player details for each tournament. I got rate-limited almost immediately just testing it.

    While the data I need might not be accessible via the APIs, it’s right here on my TD page in a nice little table. Queue another hour of trying to parse the HTML with several different tools.

    The brain blast came as I was eating dinner. Stop trying to parse it and just paste it into a spreadsheet. Works immediately. Save as a CSV and import to a sqlite db.

    sqlite> .mode csv
    sqlite> .import ifpa.csv ifpa
    sqlite> select sum(players) from ifpa where tournament like '%coin slot%';
    436
    sqlite> select sum(players) from ifpa where tournament like '%right brain%';
    148
    

    I could’ve figured out how to match this up with a calculated column in the spreadsheet but the important feature there was just parsing the HTML from my clipboard.

    Major props to spreadsheets and sqlite yet again!

  • Pinball Expo Day Three

    Got to play Elton John right away in the morning when the line was the shortest. Shoots wonderfully. Steve Ritchie is back, baby! I put up over 200M and got on the board. Four multiballs started and Joe Katz started calling shots for me. What a blast!

    Played some more Pulp Fiction. Also shoots nice and the single-level layout is very cool. Excited to have this on location soon.

    Also got to play Big Lebowski. Gorgeous pin with great theme integration. Also played a game of the bowling-only mode in the sub-playfield.

  • Pinball Expo Day Two

    Played all the Atari pins I could find. Five of them (including Hercules but I didn’t play the one they had there because we have one at right brain).

    Galactic Tank Force is cool. I really love the theme and was fully convinced it was a real show at some point. We went to the panel with the cast and got some more stories of how it was made.

    Star Wars home pin is silly. The screen is so small.

  • Pinball Expo Day One

    Some photos and notes from day 1 of expo:

    Started out with the Stern factory tour. They recently moved into a new, bigger factory building. It’s Huge.

    I liked seeing the process from individual parts to a finished pin, but the vibes were off. I don’t think a single factory worker was white. I don’t recall seeing a designer/programmer/etc that wasn’t white. Let alone the crowds being led through the building gawking at the whole process.

    The Jersey Jack tour last year wasn’t much better for this dynamic, but the scale was quite a big smaller.

    Got to play Pulp Fiction and even met Mark Ritchie in the line to play it. Played Labyrinth after chatting with Bowen Kerins. I learned that pinball isn’t even his full-time job!

    Tons of cool homebrews on the floor and even a transparent cabinet build for an EM.

    Saw a couple talks including a panel of some folks that built Pulp Fiction. It’s been in the works for over a decade. Quentin Tarantino is as strange as suspected.

    There was a screening of the Pinball film including a lovely intro by Roger Sharpe and Michael Gottlieb. If you haven’t seen it, I highly recommend it!

  • Pinball Expo Day 1 (zero?)

    Drove down to pinball expo today. Disappointed with the communication on the pre-expo tournament. I ended up on the waitlist and didn’t know it started at 4pm!

    Played some silly arcade games and a round or two on galactic tank force.

    Also signed up for the mains tournament and played my first couple qualifying games. Terrible scores but I have plenty of submissions left.

  • tilde.team subdomains as bluesky handles

    This is a quick tutorial on using your tilde.team subdomain as a handle on bluesky. Domain verification on bluesky can be done with a DNS challenge or by serving a text file from .well-known in your webroot.

    Since adjusting the Content-Type for plaintext files with no extension isn’t possible without changing global nginx configs, the quickest way is to use a tiny php script.

    <?php header("Content-Type: text/plain");
    echo "did:plc:v7tbr6qxk6xanxzn6hjmbk7o";

    Make sure that the following directory exists ~/public_html/.well-known/atproto-did and put the above script in there as index.php, replacing the did with your own.

    Then go to Settings > Change Handle on bsky.app, pick “I have my own domain”, then pick the No DNS Panel tab. Enter your subdomain and hit Verify Text File.

    You can use any of the domains that are hooked up to your ~/public_html. See the list on the tilde.team wiki.

    Here’s the source for mine on tildegit.