Category: How-To Guides

Step-by-step instructions for the things I had to figure out the hard way so that you don’t have to Google forever or stuck with hallucinating AI models.

  • Step by Step: How to Fix your server’s DNS Resolver within 5 minutes

    Step by Step: How to Fix your server’s DNS Resolver within 5 minutes

    Emails can be scary. Especially if they’re not coming from @gmail, @hotmail, or whatever, but from a damn government agency—and not just once. But the culprit is not you; it’s your DNS Resolver.

    tl;dr

    Start at Step 1.

    Luckily, I had done my homework when I chose my server and can now enjoy the tears in /r/hosting where people – despite a million warnings – open posts and beg for help to get out of GoDaddy’s contract. GoDaddy, and this must be said once and for all, is the absolutely shittiest, cheapest (I don’t mean the price), and most scammy hosting provider out there!

    E-Mail from Hell

    Alright, since this is clear now, let’s continue with the emails. So, every few weeks, I’d receive an email from Hetzner, immediately scaring the shit out of me.

    Sender: [email protected].
    Subject line: [AbuseID:112F9G4A:1B]: AbuseBSI: [CB-Report#20260218-10003814] Offene DNS-Resolver in AS249401

    Recipient: me 😬

    That doesn’t sound good, I remember thinking, not good at all. Hetzner is a German company. I am a German citizen. And I’ve been busted before for torrenting a shitty German movie I thought nobody, but my then-girlfriend, would care about anyway. Well, as it turned out, one of these law firms that always has one or two partners (“Wehler, Henkel & Secht” or something) did care, and their care had a price tag: €1,000 EUR, please. I paid the same day.

    Federal Office for Information Security

    I immediately thought of this rather forgotten day in my life and hastily skimmed the email. Hetzner’s scary [email protected] handle had only redirected an email they had received (I let my email client translate it into English, only for you!):

    Abuse email notification on a computer screen: DNS Resolver
    Hetzner’s “abuse” email

    The real reason for this was buried in the email history at the end. No translation here, because only the highlighted part meant something:

    Email warning message on computer screen
    Message from the federal office for information security

    So, the Federal Office for Information Security had been asking me for months, if not years, via the CERT Bund to close my open DNS resolver. No problem, if I only knew how. But that’s exactly where Cherry Studio, my desktop AI client, came into play. I have “assistants” for nearly everything, all carefully fed with system instructions to get the best out of each model.

    So it was only natural that I also had a “Server Guy,” whom I fed with all conceivable information about my dedicated server, the websites they host, its technology, and so on. My LLM of choice was GLM-4.7, which costs me nothing, so there’s that. Not even 5 minutes later, I was done.

    A’ight, let’s get our hands dirty and shut this DNS Resolver down!

    Step 1: Login

    Spin up the terminal of your choice and SSH into your server (you must be root, obviously). Here’s mine, for the curious ones:

    Step 2: Identify the Server

    To see what’s running, use one of the two commands:

    systemctl status named
    # OR
    systemctl status bind9
    Bash

    Right at the top of the output, you’ll see named.service, and behind that what’s actually running. In my case BIND Domain Name Server.

    Step 3: Check if it is an open DNS Resolver

    grep -A 10 "allow-recursion" /etc/named.conf
    Bash

    You’ll get some text, but look out for this:

    allow-recursion {
      any;
    };
    Bash

    You can already see what I flagged. It’s the “any” that the Federal Office for Information Security doesn’t like—an open DNS resolver. Because it can be hijacked for DDoS attacks.

    Step 4: Change DNS Resolver

    Open the file (nano /etc/named.conf) and switch the any to localhost, like this:

    allow-recursion {
    	127.0.0.1;
    	::1;
    };
    Bash

    Step 5: Last Steps

    1. Verify

    named-checkconf
    Bash

    No output? That’s how it should be.

    2. Reload BIND

    systemctl reload named
    Bash

    3. Verify it’s running

    systemctl status named
    Bash

    Save, exit, and be happy you’ll never get scary emails again. At least not from Hetzner.

    Checks (optional)

    But since we’re professionals and don’t get our servers at GoDaddy (or anything else for that matter!), we do a quick check.

    From your local machine, swap the the IP to your server’s IP, and run:

    dig @75.31.131.28 google.com # Change IP to your server's IP
    Bash

    This should give you some output with the words REFUSED on SERVFAIL. That means recursion is now blocked.

    Last check, this time on your server (No need to change anything here):

    dig @127.0.0.1 google.com
    Bash

    Here, however, recursion must work. If you see anything from the above, check for missing commas or semicolons in /etc/named.

    What do we learn from this story? How to close the DNS resolver, of course. And that not every email with “abuse” in its name is to be taken literally.

    1. Numbers changed for security reasons ↩︎

  • How to easily Send Automated Push Notifications to your iOS or Android device within minutes

    How to easily Send Automated Push Notifications to your iOS or Android device within minutes

    Today, we’re learning about the latest technological discovery. The concept is straightforward: I want to have automated reminders that pop up on my iPhone. What seems to be an easy task, considering services like IFTTT (“If this then that”) and a lot of similar services have been around for ages, is a pain in the ass once you need customization and try to use apps and scripts to customize them.

    Fortunately, I found ntfy.sh. It is exactly what I was looking for: Run a cron job on my server that triggers a script that delivers a notification to a specific device. But let’s start from the beginning, so you can enjoy my dumb journey until I found the Holy Grail.

    The Problem

    My wife doesn’t drink enough water per day. Using her age, height, and weight, we calculated her daily water intake to be between 2 and 2.7 liters. That’s a fact. However, facts are only as good as the person paying attention to them. Without notifications, my wife “forgets” to drink the required amount.

    Hey, I’m a programmer. I can do this. Super easy! 😎 Well, it wasn’t, at least at first.

    The task is very clear: My wife needs to drink a certain amount of water per day. Program something that reminds her of this: Push notifications. I immediately started playing around with iOS’ Shortcuts, which can be a pretty powerful tool for all kinds of automations and actions. Before I started, I had to set up some guidelines:

    • Drink in 30-minutes intervals
    • Drink like this during her working hours
    • Her working hours are 09:00 to 18:00.

    The (wrong) Solution

    Still sounds easy, right? I fumbled around with Shortcuts, downloaded extensions for the app, and an entirely different app that should take care of this, for free, without bloat, just a simple schedule to show push notifications on her iPhone.

    As you can guess, it didn’t work. Either they were bloated to a full fitness app, or required a subscription from the App Store. All that, just for a regular reminder in the form of simple push notifications. That can not be so difficult!

    Well, it is. And at the same time, it’s not. See, cron jobs on servers are exactly built for purposes like these; repeated execution of a script within a set timeframe. That’s good—but what about the script? How do I send the push notifications to my wife’s device to remind her to drink water every 30 minutes?

    Aside from expensive or bloated software, there was one key element that none of them had: customized intervals throughout the day. I think very highly of iOS’ and macOS’ Shortcuts app, but after hours of tinkering around (a native solution is always the best), I simply couldn’t find an automation that sends out push notifications every 30 minutes from Monday to Friday.

    Apple’s annoying Push Notifications API

    As I already wrote, the schedule and intervals can be easily handled by a single cron job. But what script allows a random user to send notifications to another random user’s device? iOS phones have an integrated so-called Apple Push Notifications API (APNs) for exactly this. It’s remote notification infrastructure connecting your servers to iOS, iPadOS, macOS, watchOS, and tvOS devices. The pipeline is simple as hell:

    Server sends uses APN to contact the device → Device reacts.

    Simple in theory, nightmarish in practice. Because Apples’ API has some architectural design flaws. Here’s a list of what I mean:

    1. Certifications expire and stop the process altogether
    2. Requires two separate environments
    3. APNs demand HTTP/2 but enforce a narrow cipher suite
    4. Background push limitations
    5. 4 KB payload limit (!)
    6. No push history

    This is certainly not the only reason why it’s difficult to manage in a non-public setting. Apple built a system that works beautifully until something goes wrong, at which point you’re left with HTTP status codes and existential questions about why you chose mobile development. And, of course, the notifications, the heart of all this, don’t arrive.

    My first try was a Python script. I created a class with a lot of methods to check everything:

    • Is today a weekend?
    • Is it within the timeframe?
    • Does the timezone play along?

    I ended up with a pretty verbose Python script that only lacked one thing: sending push notifications. Awesome.

    ntfy: An Open-Source Gem

    That’s when I discovered a service that does exactly that, triggering notifications on specific devices as needed. It comes with a mobile app to receive the actual notifications and a web interface that lets you sort of register a “client list,” for lack of a better word. They call it “topics,” so I’ll stick to that name from hereon.

    Workflow:

    1. My wife downloads the app
    2. I subscribe her app to listen to one specific topic for incoming notifications
    3. And then let cron do the job.

    The service is called ntfy, and it’s so simple that once I found out about it, I rm -rf *‘d my entire previous Python project out of sheer frustration after spending hours trying to bend the knee. The new script, also written in Python but can also be programmed in PHP, Go, JavaScript, and other programming languages, is now a single .py file with an offensively few lines:

    import requests
    
    requests.post("https://ntfy.sh/mytopic",
      data="Backup successful 😀".encode(encoding='utf-8'))
    Python

    There, that’s it. Import your requests module, trigger a web-hook on the server, and ntfy does the rest. And that’s not all: it’s entirely open-source, and you can host it yourself if you have a web server, which I, of course, did. But let’s talk about that later.

    Let’s Build a Simple Script

    So, let’s build my wife’s drinking reminder together. It’s so easy: the only thing you need is the minimalist app on your Android or iOS device and a unique name for the topic the device has subscribed to.

    The easiest solution, as I said, is to install the app. It’s called “ntfy” and costs: nothing. No trial period or some other bullshit. You can download it for Android from the Google Play Store and for iOS from the Apple App Store.

    Once the app is installed, it shows: nothing:

    How to easily Send Automated Push Notifications to your iOS or Android device within minutes — 1
    Subscribe to a topic to get push notifications
    How to easily Send Automated Push Notifications to your iOS or Android device within minutes — 2
    Add the name of your topic to subscribe

    In order to receive notifications, you must subscribe to the “topic.” That’s easily done by tapping the + sign in the top-right corner and giving the topic a unique name. For testing purposes, we’ll use wife-water-reminder:

    How to easily Send Automated Push Notifications to your iOS or Android device within minutes — 3
    Subscribed to topic
    Empty push notifications history
    Empty push notifications history

    Now we’re subscribed to a topic. You can tap to see the history of all push notifications, which is currently empty. Regarding the pixelated part of the server URL: I mentioned that I am self-hosting this service, and I’d like to keep that domain private. Sorry!

    Your “Topic” is your Pipeline

    However, this won’t concern you if you use ntfy.sh’s online service. Open the app on its website—you don’t even have to sign up for this—and click “Subscribe to topic,” which, you might’ve witnessed before, is in German, because I am German, and German is the best language on the planet. End of the discussion!

    Sending push notifications through topics
    Sending push notifications through topics

    Then, enter your topic. This must be the same as set on your mobile device.

    Subscribe to topic
    Subscribe to topic

    Once you hit “Subscribe,” the interface displays a narrow input field at the bottom—your message. At this point, it makes sense to simply test our connection by sending a test message. If everything went well, you’ll now, after a few seconds’ delay, receive one of the push notifications that displays on your device like any other notification (ignore the pixelated part before the topic). If you click it, you’ll be taken to the history page, where we now have 1 notification stored.

    The push notification has been sent
    Notification sent and received
    Push notifications
    History of all push notifications

    Well, what can I say—that’s it! You have now successfully used the Apple Push Notification API to send a notification from a remote server directly to your phone. Let that and how easy it was sink in before you start reading part two of this How-To-Guide.

    Pages: 1 2

  • Reading Selected Text out Loud: How to Create a Custom Text-to-Speech Service on macOS

    Reading Selected Text out Loud: How to Create a Custom Text-to-Speech Service on macOS

    On September 15, 2025, Apple released macOS Tahoe. This shiny new OS packs some pretty cool features that most folks probably haven’t spotted yet. One of them is Apple Intelligence—Apple’s AI sidekick, which, ironically, depends on ChatGPT. It provides you with “Writing Tools” to rephrase, summarize, translate, and all that jazz.

    Now, sometimes I want to share a news article with my partner while we’re in the same room. Instead of reading it out loud, I use the built-in text-to-speech feature called “Speak.” Just highlight the text, right-click, and pick “Speak” → “Start Speaking.” macOS 11 Big Sur included it, and after a few tweaks on Apple’s side, it works pretty well.

    However, it has one gigantic flaw: it only works in some apps. Even apps explicitly for writing, like my favorite Typora, don’t have the “Speak” option.

    That’s why I created a custom text-to-speech tool myself. Turns out, it’s surprisingly easy; you might be done and ready in less than 20 minutes. The big advantage: no ChatGPT needed. It uses macOS’ native voice models, so it’s faster and works even when you’re offline.

    Note

    My macOS interface is in German, and so are all apps and their descriptions, buttons, and so on. I tried my best to translate the labels into English, but some translations might not be accurate.

    tl;dr

    1. Click on this link to view the final shortcut
    2. Click “Receive Shortcut” and let it import itself into the Shortcuts app
    3. Right-click on any text and choose “Services” → “Vorlesen”

    Abstract

    So, we’re creating a way to have macOS’ native voices speak any text we highlight. You might think this is a perfect case for the Automator app, but it’s not. The magic app that is more powerful as you might think is called Shortcuts.

    We’re going to create a custom shortcut. It’ll take in the selected text, determine its language, and then read it out aloud in your native language (or any other language you choose). Sounds easy? It’s because it is.

    1. Create a Custom Shortcut

    Use Spotlight (⌘ + space) to open it and enter shortcuts. Once it’s open, it’s important that you switch to the “Quick Actions” library on the left. After that, click on the + icon to create a new shortcut:

    Reading Selected Text out Loud: How to Create a Custom Text-to-Speech Service on macOS — 4
    Add the shortcut to the correct library

    Since we created our shortcut in the “Quick Actions” library, our new shortcut starts with a module that receives whatever we select when we click it. I’d recommend changing the name since this is the one that will be displayed in the “Services” context menu

    Reading Selected Text out Loud: How to Create a Custom Text-to-Speech Service on macOS — 5
    Add a name and change the field types to “text” variants

    As you can see in the “2” marker, it points to the field type(s) from which the shortcut is supposed to receive the content. Click on it, unselect all items, and only keep “Text”, “Formatted Text”, and “Article” selected:

    Reading Selected Text out Loud: How to Create a Custom Text-to-Speech Service on macOS — 6
    Image #1 for “reading selected text out loud: how to create a custom text-to-speech service on macos”

    2. Prepare the Text-to-Speech Logic

    This is the main part. We’re adding the logic—named “Actions” in the Shortcuts app—from the predefined Actions library.

    The exact workflow needs the following Actions in the right order:

    1. “Add to variable”
    2. “Recognize language”
    3. An “If” condition, which creates two more modules:
      • “If”: What happens when the condition we’re going to set in a minute is true.
      • “Else”: What happens when the condition is not true.
      • “End of If”: This will close the conditional logic. No changes needed.

    3. Identify the Language

    Now, we only have to add some “Actions” and change some values. To store the text we highlighted and want to read out, we’ll need to pass it to a variable via “Add to Variable”. Leave the first selection as “Quick Action content” and give the variable the name “Text”.

    Now it’s time to identify the language of the text so our text-to-speech can work. Add the Action called “Recognize language” from the library and put it below the variable. Right-click into the placeholder and select our variable, Text:

    Reading Selected Text out Loud: How to Create a Custom Text-to-Speech Service on macOS — 7
    Image #2 for “reading selected text out loud: how to create a custom text-to-speech service on macos”

    4. Conditions

    Since we want English to be read in English and, in my case, German to be spoken in German, we have to set this as the condition. The order of the input fields is a bit off, but it still makes sense: If Text, which is the identified language, is Englisch1, then is:

    Reading Selected Text out Loud: How to Create a Custom Text-to-Speech Service on macOS — 8
    Image #3 for “reading selected text out loud: how to create a custom text-to-speech service on macos”

    Now we have to define what actually happens if the text is in English. Move the Action “Read variable” inside the “If” condition and let it receive the value in our Text variable. If it doesn’t add this automatically, right-click the field and select it manually.

    The next part is the actual text-to-speech part. Add the action “Speak Text”. Via the dropdown icon, you can select which language should be spoken, the voice, the tempo, and so on. Since this condition is set to Englisch, we select a German voice with the input of our Text variable:

    If English, then get the selected text and read it out loud
    Image #4 for “reading selected text out loud: how to create a custom text-to-speech service on macos”

    The “Else” condition works the same way. If it’s not Englisch, it’ll read it in German. Makes sense, right? Use the variable again so you can add Text into the “Speak text” action, and that’s it.

    5. Save as Service

    Aaaaaand we’re done. No, seriously, it’s that simple. Save your shortcut and make sure it’s in the “Quick Actions” library as shown before. After that, test it.

    Select any text, for example, in your browser or in a writing app, and choose your new shortcut name under “Services”. The text will now be read in the right language and with a great voice model.

    Here’s the entire workflow in one image, although in German:

    Full text-to-speech shortcut workflow
    Image #5 for “reading selected text out loud: how to create a custom text-to-speech service on macos”

    If you want to add more languages, you can, of course, add more conditions, but I personally only need English and German. No API is used, so it runs solely on your macOS, and you’re not limited by OpenAI’s LLM rate limits.

    Footnotes

    1. Since my macOS is set to German, the languages are also Germanized. Instead of English, I need to add Englisch. Keep this in mind. ↩︎
  • macOS: Create a Quick Action to easily verify the md5 or sha1 hash of a file or folder in Finder

    macOS: Create a Quick Action to easily verify the md5 or sha1 hash of a file or folder in Finder

    Let me put it this way: I often work with files whose authenticity is not always guaranteed. If you interpret this as downloaded cracked macOS apps, then that’s on you! Regardless of what files they are, if possible, you want to check their md5 or sha1 hash. It’s an easy way to verify that the file you’ve downloaded is what it’s supposed to be.

    (more…)
  • Fixing “Apple could not verify [some app] is free of malware that may harm your Mac or compromise your privacy.” Move to trash? I don’t think so

    Fixing “Apple could not verify [some app] is free of malware that may harm your Mac or compromise your privacy.” Move to trash? I don’t think so

    Apple doesn’t like software that doesn’t come from the App Store. In fact, Apple doesn’t want any software that has not been vetted by Apple itself. This applies to cracked apps (shame on you 🤐) and open-source apps from, let’s say, GitHub.

    The error message for this is always the same: “Apple could not verify [some app] is free of malware that may harm your Mac or compromise your privacy. ” It actually recommends moving the app to Trash. God, thanks. macOS has a decent command line, which allows us to fix this issue with just one line of code.

    (more…)
  • Login error with GitHub’s Copilot plugin in JetBrains 2024.2 IDEs: Here’s how I fixed it

    Login error with GitHub’s Copilot plugin in JetBrains 2024.2 IDEs: Here’s how I fixed it

    I’m using WebStorm by JetBrains as my go-to IDE for most of my front-end projects. As I was about to start it to continue one of my projects, from one day to the next, I was confronted with multiple errors that, in the end, wouldn’t let me log in to the super helpful GitHub Copilot plugin.

    A thorough Google search didn’t yield any useful results on how to fix this, but it seemed like this is not a new bug. I’ve seen similar reports going back as far as February 2023.

    However, the good news is, after tinkering around a bit, I found a way to fix this issue and use Copilot on every JetBrains product again. The following steps explain how I solved it, step by step. I can’t guarantee that it’ll work on your system, but it’s worth giving it a try.

    (more…)