• Ansible for a single server — overkill or exactly right?

    When I first set up my VPS, I configured everything by hand. SSH’d in, ran commands, tweaked config files, forgot what I did three weeks later. The second time I set up a server I wrote bash scripts. Big bash scripts. Scripts that grew organically until they were unreadable, non-idempotent, and broke in subtle ways if they’d already been partially run. The third time I used Ansible. I haven’t looked back.

  • Deploying with PM2 — why I stopped using Docker for Node.js apps

    Hot take: Docker is overkill for deploying Node.js apps on a single server. I know, I know. Containers are great. Isolation, reproducibility, all that. But when you’re running 4 Express apps on one VPS and your “deployment” is rsync + restart, Docker adds a layer of complexity that earns you almost nothing.

  • Running Prometheus + Grafana on a single VPS

    I run a bunch of services on a single Hetzner VPS. Nothing fancy — a few Node.js apps behind nginx, some cron jobs, the usual. For a long time my “monitoring” was htop over SSH and hoping nothing breaks while I sleep. That’s embarrassing to admit, but I think a lot of solo devs are in the same boat.

  • SSH config tricks I wish I knew years ago

    For years I SSH’d into servers by typing the full command every time. ssh -i ~/.ssh/id_rsa -p 2222 user@192.168.1.100. Sometimes with a jump host in the middle. It worked, but it was tedious and error-prone. Then I actually read the ssh_config man page and felt mildly embarrassed about all the time I’d wasted.

  • Terraform state management — best practices I follow religiously

    State is Terraform’s Achilles heel and nobody really talks about it until something goes wrong. I’ve been using S3 backend with DynamoDB locking from day one — I’ve seen enough horror stories from teams that didn’t. Here’s what I do and why.

  • GitHub Actions replacing Jenkins — what actually got better

    I finally killed my Jenkins server last month. It had been running on a tiny VPS for three years, eating 512MB of RAM just to exist, and breaking every time I forgot to update a plugin. GitHub Actions has been around long enough now that I gave it a real shot — not just for toy projects, but for the stuff Jenkins was actually doing.

  • Mirkotik router backup with SSH and SFTP

    Everybody knows how important it is to backup. I use Mikrotik Routers in my home network and have quite complex configuration which I would not want to write again from scratch. Prior to this day I have used scheduled script on Mikrotik to create backups locally, transferring it out of router itself into another location is great way to increase backup durability.

  • Sentry 9 - fix for PagerDuty legacy integration.

    Recently I’ve been involved in investigating why PagerDuty integration with sentry 9.1.1 doesn’t work. Same thing was happening to 9.1.2 version. The problem was not visible in UI but in logs such error message was repeating:

    19:13:04 [INFO] sentry.plugins.pagerduty: notification-plugin.notify-failed. (plugin=u’pagerduty’ error=u’Error Communicating with PagerDuty (HTTP 400): Event object is invalid’)

    No incoming event on PagerDuty side assured me that this problem is real.

  • Migration to Google Cloud Dns from different provider.

    Decision to pick DNS provider should be, in my opinion, based on currently used cloud environment. If you use AWS then Route53, GCP then Cloud Dns, etc. It’s easier to manage it and audit then. Not the case for multicloud usage but most of the companies I worked for were using single cloud.

    If DNS domain was registered before cloud adoption then your task might be to migrate DNS. Such migration is not uncommon and in this blog post I will write about changing NS records from godaddy to google Cloud Dns.

  • Mass file renaming containing nonASCII characters to ASCII

    Recently I found a problem with playing samba resources with VLC. Polish characters were breaking playback because file could not be found. Strangely enough this happened only for files with lowercase Polish letters like ąśżźćłóęń.
    Removing those letters helped to fix playback on test file but I had more than one file to fix.

    I tried to find a way to do rename all files quickly and easy and get rid of nonASCII characters and in this post I’m providing easiest, quickest and robust way to this.