Compare commits

...

17 Commits

Author SHA1 Message Date
Richard
105bd805a6 xr2000 2025-08-11 21:25:12 +02:00
Richard
1c89ce04d0 typo 2024-01-06 13:07:35 +01:00
Richard
06047b1107 iphone devops part 3 2023-12-30 16:52:46 +01:00
Richard Bronkhorst
3c869902ea Update index.md 2023-07-03 07:04:21 +02:00
Richard Bronkhorst
c9e0246acf Update index.md 2023-07-02 23:31:36 +02:00
Richard Bronkhorst
390420f132 Add index.md, nistasel.gif and one other file 2023-07-02 23:26:45 +02:00
Richard Bronkhorst
1cbfaf57ac Time == priority 2023-04-11 21:18:46 +02:00
Richard Bronkhorst
9fb71ea642 Update config.toml 2023-03-13 21:50:21 +01:00
Richard Bronkhorst
7fd119ee91 Bump 2023-03-13 21:37:24 +01:00
Richard Bronkhorst
5e27674a58 Add double-email.md 2023-02-22 20:10:01 +01:00
Richard Bronkhorst
1f243ac050 Added cname for gh pages 2022-11-20 18:18:42 +01:00
Richard Bronkhorst
e095751bb7 Finish rails post 2022-11-19 22:50:58 +01:00
Richard Bronkhorst
28ec96435d Remove post about coolify 2022-11-19 09:51:31 +01:00
Richard Bronkhorst
a684cf5d37 Removed analytics and new draft 2022-07-31 16:28:41 +02:00
richmans
ce0265c7a2 setup 2022-07-31 12:58:10 +02:00
richmans
8de3c63941 setup 2022-07-31 12:54:54 +02:00
richmans
e6c8a4a1fa setup 2022-07-31 12:52:33 +02:00
15 changed files with 277 additions and 37 deletions

View File

@@ -1,32 +0,0 @@
name: github pages
on:
push:
branches:
- master # Set a branch to deploy
pull_request:
jobs:
deploy:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
# extended: true
- name: Build
run: hugo --minify
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: github.ref == 'refs/heads/main'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public

View File

@@ -3,7 +3,7 @@ name: github pages
on: on:
push: push:
branches: branches:
- main # Set a branch to deploy - master # Set a branch to deploy
pull_request: pull_request:
jobs: jobs:
@@ -26,7 +26,7 @@ jobs:
- name: Deploy - name: Deploy
uses: peaceiris/actions-gh-pages@v3 uses: peaceiris/actions-gh-pages@v3
if: github.ref == 'refs/heads/main' if: github.ref == 'refs/heads/master'
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public publish_dir: ./public

View File

@@ -1,7 +1,7 @@
--- ---
title: "ClearSky == coolify?" title: "ClearSky == coolify?"
date: 2022-04-03 date: 2022-04-03
draft: false draft: true
--- ---
ClearSky started with the idea of getting the "cloud devops experience" without the cloud. Since registering this domain about 4 months ago and writing the first post about ClearSky, I did a lot of development and thinking what that would mean. ClearSky started with the idea of getting the "cloud devops experience" without the cloud. Since registering this domain about 4 months ago and writing the first post about ClearSky, I did a lot of development and thinking what that would mean.
@@ -13,4 +13,4 @@ As always, there are still a lot of features that i would like to have. Maybe th
Another optimalization that i would like to see is shared database servers. I don't need 10 postgres instances to host 10 databases. 1 instance is enough. Databases are more than capable of handling authentication and authorization of different users. Another optimalization that i would like to see is shared database servers. I don't need 10 postgres instances to host 10 databases. 1 instance is enough. Databases are more than capable of handling authentication and authorization of different users.
While there is definitely room for improvement, coolify comes closer to what I envisioned for ClearSky than anything I've seen so far. So I decided to stop working on the ClearSky platform for now, and see what cool things I can build on coolify. This blog is now hosted on coolify as well. While there is definitely room for improvement, coolify comes closer to what I envisioned for ClearSky than anything I've seen so far. So I decided to stop working on the ClearSky platform for now, and see what cool things I can build on coolify. This blog is now hosted on coolify as well

View File

@@ -0,0 +1,50 @@
---
title: ActionMailer renders the email body twice
date: 2023-02-22
draft: false
---
Recently i was happily coding on my rails project. I wanted to add a feature that would send an email to all admin users when a certain event occurred. So i searched "rails email" and discovered [ActionMailer](https://guides.rubyonrails.org/action_mailer_basics.html).
It works simple enough. First you define a "mailer" which is a lot like a controller. I defined a "PublicationMailer". It fetches the necessary data and then renders the email. Step 2 is defining views for the mailer, both html and txt formats. Lastly, you call `PublicationMailer.publication().deliver` and bimbamboom your email is ready. Good! On to the next feature.
Fast forward a couple of weeks. The app is almost ready and i'm deploying it on a VPS to see if everything works as expected. File uploads? Check! Authentication? Check! Email notifications? Che... wait a minute! The email that arrived in my inbox had the right contents, but it had them twice! Sanity check: no this did not occur in my test environment. What was going on?
After some head-scratching, i took another hard look at my mailer object:
```
class PublicationMailer < ApplicationMailer
helper :application
default from: "notifications@mark423.com"
layout "mailer"
def publication(recording)
@recording = recording
User.where(is_admin: true).each do |user|
mail to: user.email, subject: "Podcast published"
end
end
end
```
I immediately understood my mistake. What I would expect this code to do is to send one email to each user that is an admin.
In my test environment, i only had one admin user. In my production environment i had created 2, which triggered the problem.
> It turns out the **mail** function does not really send a mail. It **renders** the mail.
## Solving it
The fix was simple: call mail once with a list of recipients.
```
class PublicationMailer < ApplicationMailer
helper :application
default from: "notifications@mark423.com"
def recording_published(recording)
@recording = recording
emails = User.where(is_admin: true).collect(&:email)
mail to: emails, subject: "Podcast published"
end
end
```
## Hindsight
I think the function 'mail' could have had a better name (maybe 'render' like in controllers?). On the other hand, i could probably have read the [documentation](https://api.rubyonrails.org/classes/ActionMailer/Base.html#method-i-mail) better.

View File

@@ -0,0 +1,57 @@
---
title: "iPhone DevOps - python edition"
date: 2023-07-02T19:25:16+01:00
draft: false
tags: [mobile]
---
I wrote [earlier](https://clearsky.dev/blog/iphone-devops/) about my dream of developing "single-handedly" on an iPhone. That dream has not gone away. In fact, the arrival of another baby in my house has again led to increased iPhone screentime and decreased laptop-screentime. So consider this an update of my iPhone DevOps adventure.
## But why would you want this?
I've been a developer since I was a kid. Writing code is what I love to do. Recently, I became a dad. This new task involves a lot of walking and sitting with your child while it either sleeps or cries. Usually I need only one hand to perform these dad-duties. The other hand and also my brain are free to... write code? My child got a bit older in the mean time but still I find that I rarely have time to sit down behind a laptop, yet have enough time to spend on my phone. So what if instead of trying to scroll through the mountain of garbage called facebook, I use that time to code? This is basically my main reason for wanting to code on the phone.
In the beginning, I was mostly developing scripts (both bash and python) that managed my docker environment. The scripts are pretty small and have limited features. I found that using a good ssh client combined with tmux and vi, this was (sort of) doable.
## New project, new workflow
This year, i discovered [spacetraders](https://spacetraders.io). It's a kind of game where you command ships using a REST api. I decided that this was a worthy project for my next mobile DevOps adventure. So i got to work using my language of choice: python. However, I quickly discovered that my workflow was not working as well for this project. Mainly:
* This project needed more than 1 module, so I was often switching between files in my editor.
* The files were longer, so I was scrolling much more. This is very slow in vi
I needed a new workflow for this project...
## What didn't work: VSCode
I'm a big fan of [VSCode](https://code.visualstudio.com/). It's not the fastest editor but it's very flexible and has a lot of good plugins. I already knew that you could [host it as a webapp and run it in the browser](https://github.com/coder/code-server). What if I had my complete Dev environment in a docker container on my server, and I could just resume my work on my phone where I left off on my laptop? That would be AMAZING!
So I set it up. It was very easy to setup and to get it working. You can even add the site as an icon on your iphone so it kind of feels like a regular 'app'. With some tweaking, the fonts and icons were kind of ok. That's when I found the problem, a real showstopper without a workaround.
> you can't select anything
Wait what? So on other apps or even webapps on my iphone, i long-press and then choose 'select', and then 'copy' to copy something. As with a lot of tasks in my 'mobile development workflow', it's way slower then the desktop experience but it's what there is, and you learn to live with that. But when I long-press in VSCode I get some kind of menu. No way of selecting text. I looked for plugins or other solutions but there is just no way. Desperate, I even tried some [wrapper app](https://apps.apple.com/nl/app/ucow-ultimate-code-wrapper/id1551344923?l=en) **(do not buy this app)**. There is just no way to get this working. Which is so weird because the functionality of selecting text is already in the browser! So VSCode is disabling that somehow. Of course VSCode was never designed to be used on a touch screen. Still, this is crazy. I hope someone fixes this.
## The next best thing: pythonista
Pythonista is an app that lets you edit and run python scripts on the iphone. It seems to focus mostly on game or ui development, but i've found it usable for cli apps as well. Most importantly, it does a couple of things very smoothly: scrolling, switching between files and the running script output. Observe!
![Swipe swipe](pythonista.gif)
But, maybe much more importantly observe the following shocking innovation!
![Movin](nistasel.gif)
**Eat that, VSCode!**
As with most things that run on an iPhone, the UI is pretty great. But it's not all good news:
* The code runs locally in the app, which means it **stops when you leave the app**. Not really usable for longer running processes. I use pythonista only to do quick tests. To do a longer test I have to commit and deploy the code to my server.
* speaking of committing, it had **no git support** I work around that using [Polygit](https://apps.apple.com/nl/app/polygit-git-client/id1508942822?l=en) and adding the polygit dir to pythonista. This works fine.
* It packs a bunch of libraries by default, but it has **no way of installing new packages or upgrading existing ones**. For instance, i found that the yaml lib is broken. This is solved in a newer version, but I have no way to update it. I worked around this by using json...
* The 'play' button **executes the file that is currently open** Larger projects usually have a 'main' file that you want to execute. Executing some submodule is useless. So when i edit a file and I want to test it, I have to go back to the main.py file and then press play. This is cumbersome. One partial workaround is to have main.py open in a separate tab
* There is **no way to pass commandline arguments** to a script. I work around this by making all options available as commands within my script.
* The terminal is **not a real terminal**. You can use `input()` and `print()` but don't expect anything fancy like arrow keys or colors to work
* It **works only for python**.I would love to work more with other languages such as rust, but I'd need a different solution for that.
This may sound like a long list of pretty serious issues. And it is. But at least for this project, pythonista gets the job done... slowly.
## Conclusion: it works...for patient people
Coding on an iPhone is no joke. It takes longer and is more error-prone than a desktop experience. I will keep on searching for alternatives. Especially working on rust projects would be nice.
But if you have no other choice, and you have a large amount of patience, you can actually program spaceships from an iPhone. And to me, that's pretty neat!

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

View File

@@ -0,0 +1,80 @@
---
title: "iPhone DevOps - ultimate edition"
date: 2023-12-28T19:57:34+01:00
draft: false
tags: [mobile]
---
I wrote [earlier](https://clearsky.dev/blog/iphone-devops/) about my dream of developing "single-handedly" on an iPhone. Then, I wrote [some more about it](https://clearsky.dev/blog/iphone-devops-python/). The dream still lives strongly! I am now coding single-handedly in any language on my iPhone SE model 2022. But although i still like [pythonista](http://omz-software.com/pythonista/) I am now using a combination of three great apps that allow me to write code in any language using only one hand, holding my son in the other!
> what happened to pythonista? Wasn't it awesome because it could copy-paste and stuff?
Pythonista still is a great app. An update came out early this year featuring a much-needed python version push to 3.10. I still like to use the app for small scripts such as [Advent of Code](http://adventofcode.com).
## A new quest
So what disturbed the bliss of my little pythonista-powered mobile dev heaven? I blame [protohackers](https://protohackers.com). The day I found this site, I knew i had to go back to the drawingboard for my mobile dev workflow.
The idea for protohackers is this: the site gives you a spec for a client-server protocol. You have to implement the server. You then plug the ip and port of your running server into the website, and it runs a series of tests interacting with your server. You have to make all tests pass. You can implement your server in any language you like. The specs are mostly watertight, although there are some surprises in the tests. The protocols are on top of either TCP or UDP. Overall these challenges are really well designed and a lot of fun to implement. My solutions are [here](https://git.clearsky.dev/richard/Proto)
So i wanted to do these challenges, but my workflow could not support it:
* I cant just open up a port on my iPhone. It sits behind a router at home, or some kind of [NAT](https://en.m.wikipedia.org/wiki/Carrier-grade_NAT) outside. Even if I could, I don't know if it would be a good idea security-wise.
* I don't want to do this one in python. I want to use this challenge to gain some more experience in [golang](https://go.dev)
## The search is on (again)
After revisiting all the options from my earlier searches, and looking at a bunch of code editors/ide's, I was just ready to start vim in a terminal and start working completely on my server.
I was using [termius](https://termius.com/) which is a pretty nice terminal app even when you use the free version. But i decided to do a quick search for terminal apps and see if anything popped out that would work even better. And that's when it happened.
I found [secure shellfish](https://secureshellfish.app/)
## Secure shellfish
I wouldn't call it the best terminal app, because the menus are a bit hard to navigate and some design choices are a bit... creative. But in spite of that, I love it! Mostly because this app has 1 killer feature:
✨Offline folders ✨
This is like rsync for your phone. In fact I would not be surprised if this is implemented using rsync. Once you configure an offline folder, it will two-way sync that folder while you use the app. The kicker is: on your phone you can now open that folder in another app (like an editor) and make changes. When you switch back to the shellfish app, the changes are uploaded almost instantly. Also changes that happen on the server come back to the phone.
![Offline folders](offline.png "Offline folders")
For me this is a killer feature because it allows me to switch back and forth between the editor and the shell.
* Make a change
* switch to shellfish
* up arrow enter
* back to the editor
* repeat!
## The place to run code
So now that my code doesn't run on the phone anymore, it needs a place to run.
I already had a vps running, so for me this was not a problem. Any linux based machine will do. I use docker to easily spin up environments for each project. I am on a [contabo](https://contabo.com) vps which has really nice specs for money, but I did have some outages lately. I might switch provider soon.
Ofcourse if you are on a budget, ypu can use any linux machine you have running at home.
## The editor
So now we need to find an editor that can open the "offline folder". I landed on [textastic](https://www.textasticapp.com/) which has its own sftp functionality and even a shell builtin. I didnt get that to work smoothly. The app allows you to open "external folders" which is how you can reach the shellfish folder.
![External folders](external.png "Two synced folders from my vps and one stored locally by working version")
The syncing works really well. I have seen one problem which is that if you type something and then switch the shellfish app, it doesn't seem to sync the file. It looks like textastic didn't save the file. My workaround is to move the cursor, just tap anywhere in the file before switching away from the editor.
Other features that this editor does well is search/replace, search in files and file management (move, rename etc)
Im not sure if other editors can do the "external folders" trick, or if textastic is the best one. So far it works really well. There's room for improvement here, I might test some other editors and write a follow-up some time.
## The version control
I use git mostly as a backup for my code. I have my own git server for private projects and github for public. Now I could use the commandline git and commit that way. That works okay, but I really like the [working copy](https://workingcopy.app) app. It can attach to the same "external folder" and you are off to the races! This app is made by the same developer as shellfish.
## The euros
Good things have a price. Here's the full damage report:
* shellfish life unlock: € 24,99
* textastic € 9,99
* working copy life unlock: € 24,99
* contabo vps: € 7,25 / month
Shellfish and working copy also have subscription-based pricing which is great if you are unsure if mobile dev will work for you. I went for the fixed price and am pretty sure I'm going to enjoy these apps for quite some time.
## The conclusion
The conlusion remains the same as the previous editions: it works, but not for impatient people. It has become my alternative to social media. While it might be a lot less effective than a laptop, it's definitely a lot less mind-numbing than instagram.
With that, let's get back to writing some code!

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View File

@@ -0,0 +1,34 @@
---
title: Rails doesn't save my added attribute
date: 2022-07-09
draft: false
---
A long long time ago in 2014, before I started to work in a place ruled by the evil snake called "python", I worked with a little framework called [Ruby on Rails](https://rubyonrails.org). It was a wonderful time. Rails was hip in those days. All the cool kids were doing it. What I liked most about rails was how little code was needed to achieve something.
There is a bit a learning curve with rails. Rails is magic. You don't need to understand exactly what is happening, but you do need to remember the right spells. The good thing is that once you get into the rails mindset, you start expecting things to work in a certain way. And 9 out of 10 times, it does!
Another philosophy that i like about rails is "**convention over configuration**". For instance: lets say you have a table "posts". What do you call the column that identifies a row? And the column that is the foreign key to the "authors" table? In most cases, it doesn't really matter. So rails decides for you: "id" and "author_id". The rails ORM called ActiveRecord understands these column. Now you can do things like `my_post.author` and boom you've followed that foreign key without ever naming it in your code. Ofcourse, of you really want to, there's a way to [change the name of the foreign key column](https://guides.rubyonrails.org/association_basics.html#options-for-belongs-to-foreign-key)
So rails was great in 2014. I hadn't used it or even looked at it since that time. The hype seems to have passed. The cool kids have all jumped on the nodejs/"single page app"-train. I seem to have missed that train. In fact, i never liked javascript or npm. So, when rails' big boss [posted a blog about a new rails version that steers clear from transpiling and bundling](https://world.hey.com/dhh/modern-web-apps-without-javascript-bundling-or-transpiling-a20f2755), I was paying attention. When rails 7 came out in december 2021, I decided to take it for a spin.
> rails in 2022: less hype, same magic?
It felt like coming home after a long trip: running `rails g scaffold post title:string content:text` and `rails s` and finding your crud functions ready and working. This is where a lot of "rails tutorials" stop. But a scaffold is not a building. It's a starting point. What happens when we want to add an attribute to our blog?
* First, we add a new migration to add a column to the table. Dont forget to `rails db:migrate`
* Next, we edit the \_form partial to define an input field for the attribute
* As i remember it, there was no step 3. Lets give it a whirl!
**Wait, it doesn't error but it also doesn't save the new attribute?**
It turns out that in the last 8 years, someone found out that it isn't the greatest idea to let the user define arbitrary attributes in the controller update/create calls. So now you have to define which model attributes can be updated by the controller. They call it [Strong parameters](https://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html). It looks like this:
```
def blog_params
params.require(:blog).permit(:title, :content)
end
```
So adding an attribute now requires this extra step in the controller. This is a process i do very often when developing apps. I guess it makes sense security wise to have this validation. For me though, it also means rails has lost some of its famous magic.
There's lots of other magic left though, and even some new magic that was added since 2014. I really like [active storage](https://edgeguides.rubyonrails.org/active_storage_overview.html).

View File

@@ -0,0 +1,17 @@
---
title: "Time == Priority"
date: 2023-04-01
---
"I don't have time" is something i hear people saying often. I hear it at work when we're thinking about a new project, or sometimes I hear the words coming out of my own mouth explaining to my wife why I haven't started on some home-improvement-project yet. Everyone is busy. But are we really?
I must have been around 16 when I was at summer camp. I don't remember what the conversation was about, but I clearly remember one of my friends muttering: "time is priority" after someone complained about not having enough time. At the time I thought that was a wise thing to say. It stuck with me and became one of my core values.
Basically the amount of time we have is the same for everyone. Lets say you sleep about 8 hours per day. That leaves 16 hours per day or 5840 hours per year. If you are lucky enough to live a full 80 years, that means a whopping 467200 waking hours that you get to spend on this (mostly) beautiful earth. That sounds like a lot right?
Now the question is: how will you spend these hours? There are so many options to spend your time on. An hour spent scrolling through instagram is an hour not spent doing useful work. And an hour doing useful work is an hour not spent with your loved ones. So how do you make a decision about what you spend your next hour on? I think the answer should be **priority**.
If some activity has a high priority, you should try very hard to spend enough time on it. If health and fitness are a high priority for you, you will probably spend multiple hours per week doing something sporty. If your work is important for you, you might be putting in a bit more than the regular 40 hours.
This does not just go for your "life choices". It is also true for the choices you make at work. No matter how big your team is, you will always have to make choices on what you spend your time on.
So instead of saying: "I don't have time for that" it would be more accurate to say: "I have other things to do that are higher priority for me" But on the other hand, that might sound less friendly to the person asking for your time. So maybe just keep the priority thing to yourself :-)

View File

@@ -0,0 +1,34 @@
---
title: "Challenge: XR2000"
date: 2025-08-10T21:29:12+01:00
draft: false
tags: [challenge]
---
Today Im releasing the **XR2000**: A programming challenge with extensive science fiction backstory. This is a project Ive long wanted to make, and it has slowly come to life in the last few years.
I love a good puzzle or game that involves programming. Over the years I found a couple of these games that were particularly fun. These really inspired me to start the XR2000. Before explaining more about my new challenge, I want to mention (and recommend) these games.
## TIS-100
This is one of the weirdest games ever. [TIS-100](https://store.steampowered.com/app/370360/TIS100/) that lets you write assembly code for a fictional cpu. There is a complete manual documenting the CPU instructions and all peripherals. It really got me hooked on legacy computing and assembly programming.
## Space Traders
In [Space Traders](https://spacetraders.io) you control a spaceship through a REST API. The game is mainly focused on trading (as the name suggests) and involves closely monitoring and analyzing market prices. It's a great challenge for learning a new programming language or programming in general. The simulation has remarkable depth.
## Protohackers
[Protohackers](https://protohackers.com) is not a game but more a programming challenge like [AoC](https://adventofcode.com) but focussed on backend and protocols. It really makes you dive into the depths of tcp, udp and sockets.
## And now something different
I decided to create a challenge that combines a science fiction story with a programming challenge. The programming challenge so far is mostly focussed on binary protocols, and some cryptography.
The story is far from finished. There are lots of ideas on continuing the story, expanding the fictional universe and including more low level / assembly techniques. So let's call this chapter 1. More might follow depending on the success of this first part. So let's get ready to...
## Dive in!
To get started:
```
nc clearsky.dev 29438
```
And dont forget: this is supposed to be fun!
This challenge was fully [developed from an iPhone](https://clearsky.dev/blog/iphone-devops-ssh/)

View File

@@ -1 +0,0 @@
<script async defer data-website-id="1c1c8489-4fb2-4940-af2a-09eca940adb1" src="https://analytics.clearsky.dev/umami.js"></script>

1
static/CNAME Normal file
View File

@@ -0,0 +1 @@
clearsky.dev