I like DevOps. More specifically, I like good DevOps. For example, I love Heroku host a few dozen free apps there. Salesforce must be raking in boatloads of cash from every business that also loves Heroku, but I can’t justify spending $7 per app per month.

Heroku apps I have 21 apps. It would cost nearly 150$ per month to run them on the hobby tier.

I tried to recreate something similar to Heroku for years, and I was pretty happy with where it got me. I had a folder full of bash scripts that would generate NGINX configurations, configure port-forwarding, manage SSL certificates, scaffold Systemd services around my apps, and other goodies in the same vein.

An advantage of my setup was how Unix-y permission management was. Each app had its user, making its permissions easy to manage. It allowed me to do cute things like adding a set of apps to the same group and sharing a folder:

# These are made-up apps
# App that can rotate logs
adduser app-log-manager logger
# App that reads logs
adduser app-analytics logger
chown -R app-log-manager:logger /var/logs/mylogs
# app-log-manager and read and write
# app-analytics can read but not write
chmod -R 640 /var/logs/mylogs

I’m not sure how you would do something similar in Docker. Does Docker even have a concept of app groups?

I would’ve happily continued down this road if I had unlimited time, but life does as life does and even patching my servers became a neglected chore.

Where Are These Scripts?

Great question. The answer is that they’re scattered, and most of them depend on many quirks I had configured on my server and never took the time to document. The less quirky ones are on my GitHub. If you’re thinking of doing something similar, consider using Sigil as an alternative to hard-coding templates.

My small collection is rather unimpressive. Truth is, I’ve never really learned bash; largely because every resource I come across is referred to as outdated. Bash is a surprisingly fast-moving target.

These days my bash scripting mostly revolves around passing data to jq or awk. I find them easier to work with.


In principle, the DevOps practice of a folder full of bash scripts is infinitely extendable. In practice, some important features were simply infeasible.

For example, tracking down all the scaffolded configuration files causing issues with a deployment was akin to detective work.

Another major defect is how tightly coupled the apps became with the server. Two applications depending on different versions of a library have essentially no workaround.

Moral of the story: Containers win.

New Architecture

There isn’t much to be said about my new architecture: It’s Dokku! My apps are hosted on GitHub and are automatically pushed to Dokku using Github Actions. I couldn’t be happier with it. I’ll occasionally make a post talking about this-or-that aspect of my personal process.