OS Apps: Timezone, Swiish and VaultWarden

Time, Cards and Secrets

Posted by Isaac on Thursday, October 8, 2026

I have a few apps on my todo list today. The first of which is this timezone app in Linux. I’ll try a few ways to install.

The next is Swiish which is an excellent containerized business card app.

Lastly, we’ll look at Bitwarden and Vaultwarden as I try to restore my OS secrets engine on the cluster.

But let’s start with a simple timezone app…

Timezone

I found this timezone app some time back and really wanted to get it a try.

Trying with make didn’t work, but the flatpak install works

Add flakpak remote if needed

$ sudo flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo

We need some flakpak dependencies

$ flatpak install flathub org.gnome.Platform//51
$ flatpak install flathub org.gnome.Sdk//51

I’ll add Platform and SDK

(base) builder@LuiGi:~/Workspaces/timezones$ flatpak install flathub org.gnome.Platform//51
Looking for matches…
Remote ‘flathub’ found in multiple installations:

   1) system
   2) user

Which do you want to use (0 to abort)? [0-2]: 1


        ID                                                Branch                 Op            Remote             Download
 1. [✓] org.freedesktop.Platform.GL.default               26.08                  i             flathub            149.4 MB / 150.5 MB
 2. [✓] org.freedesktop.Platform.GL.default               26.08-extra            i             flathub             28.9 MB / 150.5 MB
 3. [✓] org.freedesktop.Platform.VAAPI.Intel              26.08                  i             flathub             14.8 MB / 15.0 MB
 4. [✓] org.freedesktop.Platform.codecs-extra             26.08-extra            i             flathub             15.6 MB / 15.7 MB
 5. [✓] org.gnome.Platform.Locale                         51                     i             flathub             18.7 kB / 391.3 MB
 6. [✓] org.gtk.Gtk3theme.Yaru                            3.22                   i             flathub            139.3 kB / 191.5 kB
 7. [✓] org.gnome.Platform                                51                     i             flathub            372.0 MB / 432.2 MB

Installation complete.
(base) builder@LuiGi:~/Workspaces/timezones$ flatpak install flathub org.gnome.Platform//51
Looking for matches…
Remote ‘flathub’ found in multiple installations:

   1) system
   2) user

Which do you want to use (0 to abort)? [0-2]: 1
Skipping: org.gnome.Platform/x86_64/51 is already installed
(base) builder@LuiGi:~/Workspaces/timezones$ flatpak install flathub org.gnome.Sdk//51
Looking for matches…
Remote ‘flathub’ found in multiple installations:

   1) system
   2) user

Which do you want to use (0 to abort)? [0-2]: 1


        ID                            Branch          Op         Remote          Download
 1. [✓] org.gnome.Sdk.Locale          51              i          flathub          18.8 kB / 408.5 MB
 2. [✓] org.gnome.Sdk                 51              i          flathub         507.8 MB / 873.7 MB

Installation complete.
(base) builder@LuiGi:~/Workspaces/timezones$

Now we can add

$ flatpak-builder --user --install --force-clean build-flatpak packaging/flatpak/io.github.hernantz.timezones.json
ownloading sources
Downloading https://download.gnome.org/sources/gweather-locations/2026/gweather-locations-2026.2.tar.xz
  % Total    % Received % Xferd  Average Speed  Time    Time    Time   Current
                                 Dload  Upload  Total   Spent   Left   Speed
100  2.47M 100  2.47M   0      0  3.81M      0                              0
Downloading https://download.gnome.org/sources/geocode-glib/3.26/geocode-glib-3.26.4.tar.xz
100  75352 100  75352   0      0  1.25M      0                              0
Downloading https://download.gnome.org/sources/libgweather/4.6/libgweather-4.6.0.tar.xz
100 339.4k 100 339.4k   0      0  3.32M      0                              0
Initializing build dir
Committing stage init to cache
Starting build of io.github.hernantz.timezones
========================================================================
Building module gweather-locations in /home/builder/Workspaces/timezones/.flatpak-builder/build/gweather-locations-1
========================================================================
The Meson build system
Version: 1.12.0
Source dir: /run/build/gweather-locations
Build dir: /run/build/gweather-locations/_flatpak_build
Build type: native build
Project name: gweather-locations
Project version: 2026.2
Host machine cpu family: x86_64
Host machine cpu: x86_64
Program python3 (gi) found: YES (/usr/bin/python3) modules: gi
Program build-aux/gen_locations_variant.py found: YES (/run/build/gweather-locations/build-aux/gen_locations_variant.py)
Program xmllint found: YES (/usr/bin/xmllint)
Program pylint-3 pylint3 pylint found: NO
Program msgfmt found: YES (/usr/bin/msgfmt)
Program msginit found: YES (/usr/bin/msginit)
... snip ...

Content Total: 45
Content Written: 0
Content Bytes Written: 0 (0 bytes)
Installing runtime/io.github.hernantz.timezones.Debug/x86_64/master
Installing runtime/io.github.hernantz.timezones.Locale/x86_64/master
Installing app/io.github.hernantz.timezones/x86_64/master
Pruning cache

And

$ flatpak run io.github.hernantz.timezones
$ flatpak run io.github.hernantz.timezones
/app/share/timezones/src/app.py:34: PyGIWarning: Adw was imported without specifying a version first. Use gi.require_version('Adw', '1') before import to ensure that the right version gets loaded.
  from gi.repository import Adw, Gdk, GLib, Gtk  # noqa: E402

(io.github.hernantz.timezones:2): Gtk-WARNING **: 18:18:36.342: Theme parser error: style.css:2:29-33: Expected a valid color.

(io.github.hernantz.timezones:2): Gtk-WARNING **: 18:18:36.343: Theme parser error: style.css:2:29-33: Expected a valid color.
MESA-EGL: warning: failed to get driver name for fd -1
MESA-EGL: warning: MESA-LOADER: failed to retrieve device information
MESA-EGL: warning: failed to get driver name for fd -1
MESA: error: ZINK: failed to choose pdev
MESA-EGL: warning: egl: failed to create dri2 screen

which launches

/img/2026-10-timezones.png

It’s pretty easy to check timezones for people

/img/2026-10-timezones.png

I could see it useful for disparate teams or global work projects.

Swiish

I found Swish from this Marius post which came up on my feed.

It is pretty to install by using the Github repo

(base) builder@LuiGi:~/Workspaces$ git clone https://github.com/MrCrin/swiish.git
Cloning into 'swiish'...
remote: Enumerating objects: 720, done.
remote: Counting objects: 100% (352/352), done.
remote: Compressing objects: 100% (107/107), done.
remote: Total 720 (delta 281), reused 251 (delta 245), pack-reused 368 (from 2)
Receiving objects: 100% (720/720), 2.06 MiB | 5.54 MiB/s, done.
Resolving deltas: 100% (383/383), done.
(base) builder@LuiGi:~/Workspaces$ cd swiish/
(base) builder@LuiGi:~/Workspaces/swiish$ nvm use lts/jod
Now using node v22.22.0 (npm v10.9.4)
(base) builder@LuiGi:~/Workspaces/swiish$ npm install
npm warn deprecated @npmcli/move-file@1.1.2: This functionality has been moved to @npmcli/fs
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated npmlog@6.0.2: This package is no longer supported.
... snip ...

I then copied the sample .env file from the sample

(base) builder@LuiGi:~/Workspaces/swiish$ cp .env.example .env

I then fired up a dev server

Compiled successfully!

You can now view swiish in the browser.

  Local:            http://localhost:3000
  On Your Network:  http://192.168.1.38:3000

Note that the development build is not optimized.
To create a production build, use npm run build.

webpack compiled successfully

The setup page launched into Firefox

/img/2026-10-osapps-01.png

Once setup we can setup our card

/img/2026-10-osapps-02.png

We can see a sample

/img/2026-10-osapps-03.png

and that would make a good card

/img/2026-10-osapps-04.png

K8s

Let’s expose this via Kubernetes. I’ll want an A record.

$ az account set --subscription "Pay-As-You-Go" && az network dns record-set a add-record -g idjdnsrg -z tpk.pw -a 76.156.69.232 -n me
{
  "ARecords": [
    {
      "ipv4Address": "76.156.69.232"
    }
  ],
  "TTL": 3600,
  "etag": "888c1672-e0ae-41f6-9337-44a6a9f058b7",
  "fqdn": "me.tpk.pw.",
  "id": "/subscriptions/d955c0ba-13dc-44cf-a29a-8fed74cbb22d/resourceGroups/idjdnsrg/providers/Microsoft.Network/dnszones/tpk.pw/A/me",
  "name": "me",
  "provisioningState": "Succeeded",
  "resourceGroup": "idjdnsrg",
  "targetResource": {},
  "trafficManagementProfile": {},
  "type": "Microsoft.Network/dnszones/A"
}

I think I’ll just expose this in Kubernetes, but run it in docker on my Rz9 host.

builder@bosgamerz9:~/swiish$ docker compose up -d
WARN[0000] The "JWT_SECRET" variable is not set. Defaulting to a blank string.
[+] up 19/19
 ✔ Image ghcr.io/mrcrin/swiish:latest Pulled                                                                                                                                                                                                       8.0s
 ✔ Network swiish_default             Created                                                                                                                                                                                                      0.0s
 ✔ Container swiish                   Started
 $ docker ps | grep swiish
 dea4a5ebba6d   ghcr.io/mrcrin/swiish:latest                              "docker-entrypoint.s…"   44 seconds ago   Restarting (1) 14 seconds ago                                                            swiish

Now I just need an endpoint, service and ingress created in k3s

$ cat swiish.ingress.yaml
---
apiVersion: v1
kind: Endpoints
metadata:
  name: swiish-external-ip
subsets:
- addresses:
  - ip: 192.168.1.143
  ports:
  - name: swiishint
    port: 8095
    protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: swiish-external-ip
spec:
  clusterIP: None
  clusterIPs:
  - None
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  - IPv6
  ipFamilyPolicy: RequireDualStack
  ports:
  - name: swiish
    port: 80
    protocol: TCP
    targetPort: 8095
  sessionAffinity: None
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: azuredns-tpkpw
    ingress.kubernetes.io/ssl-redirect: "true"
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.org/client-max-body-size: "0"
  name: swiish
spec:
  rules:
  - host: me.tpk.pw
    http:
      paths:
      - backend:
          service:
            name: swiish-external-ip
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - me.tpk.pw
    secretName: swiish-tls

I apply

$ kubectl apply -f ./swiish.ingress.yaml
endpoints/swiish-external-ip created
service/swiish-external-ip created
Warning: annotation "kubernetes.io/ingress.class" is deprecated, please use 'spec.ingressClassName' instead
ingress.networking.k8s.io/swiish created

And watch for the cert to get created

$ kubectl get cert swiish-tls
NAME         READY   SECRET       AGE
swiish-tls   False   swiish-tls   56s
$ kubectl get cert swiish-tls
NAME         READY   SECRET       AGE
swiish-tls   True    swiish-tls   94s

I am now ready with setup

/img/2026-10-swiish-01.png

I can now add my card

/img/2026-10-swiish-02.png

I can now create a card https://me.tpk.pw/EJEMipE

/img/2026-10-swiish-03.png

The share button creates a QR code i could just show someone at a conference or tech talk

/img/2026-10-swiish-04.png

Bitwarden

I noticed all my Bitwarden instances were down. I really don’t use it but it came up recently when preparing some slides for a presentation.

/img/2026-10-bitwarden-01.png

Everything was a mess when i looked in the namespace

/img/2026-10-bitwarden-02.png

The ImagePullBackoffs came because they yanked the old 2024 container images from Dockerhub (or Dockerhub did it). They MySQL was in a death spiral over a bad file

2026-10-08 02:10:18.15 Server      Logging SQL Server messages in file '/var/opt/mssql/log/errorlog'.
2026-10-08 02:10:18.16 Server      Registry startup parameters:
         -d /var/opt/mssql/data/master.mdf
         -l /var/opt/mssql/data/mastlog.ldf
         -e /var/opt/mssql/log/errorlog
2026-10-08 02:10:18.16 Server      Error: 17113, Severity: 16, State: 1.
2026-10-08 02:10:18.16 Server      Error 5(Access is denied.) occurred while opening file '/var/opt/mssql/data/master.mdf' to obtain configuration information at startup. An invalid startup option might have caused the error. Verify your startup options, and correct or remove them if necessary.

But it was running on some odd Microsoft 2022 Ubuntu forked image.

The more I looked, the less I wanted to fix this.

I’ll (try) and uninstall it properly first:

$ helm delete bitwarden -n bitwarden
^C

It timed out so I then deleted the namespace

$ kubectl delete ns bitwarden

This should cleanup the PVCs and other left-over bits

The new guide for installing with helm is here

I’ll recreate the namespace

$ kubectl create namespace bitwarden
namespace/bitwarden created

Then add and update the helm chart repo

$ helm repo add bitwarden https://charts.bitwarden.com/
helm repo update
"bitwarden" has been added to your repositories
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "bitwarden" chart repository
...Successfully got an update from the "openbao" chart repository
...Successfully got an update from the "authelia" chart repository
...Successfully got an update from the "authentik" chart repository
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈

However, as I reviewed the values, it seems to want to do a lot more connecting to the cloud and registration than I feel comfortable with

/img/2026-10-bitwarden-03.png

I was reminded that I moved on to Vaultwarden

Now, that too is an old image from 2024 (version 2024.1.2)

/img/2026-10-bitwarden-04.png

I can use Tugtainer to check the pod and see the SHA is not the latest

/img/2026-10-bitwarden-05.png

Even though the image tag was set to “latest”

/img/2026-10-bitwarden-06.png

I was getting stumped on the right way to update.

Tugtainer update was not working

/img/2026-10-bitwarden-07.png

And Containery didn’t have an option

/img/2026-10-bitwarden-08.png

Dockpeek was taking it’s sweet time

/img/2026-10-bitwarden-09.png

But eventually let me click update

/img/2026-10-bitwarden-10.png

I then ran the update

/img/2026-10-bitwarden-11.png

/img/2026-10-bitwarden-12.png

And it claimed it was successful

/img/2026-10-bitwarden-13.png

Back on the host i see it restarted

/img/2026-10-bitwarden-14.png

And the SHA in Tugtainer seems updated

/img/2026-10-bitwarden-15.png

The WebUI is definitely updated

/img/2026-10-bitwarden-16.png

There are some nice generators

/img/2026-10-bitwarden-17.png

I’m not going to share the keys, but all the secrets I had stored there were saved.

I tried some Firefox and Chrome extensions for Bitwarden and Vaultwarden but they seemed stuck wanting to login to the bitwarden site.

I plan to circle back on that.