<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Aigarius Blog</title><link>http://aigarius.com/</link><description>Mindblogging the world to itself</description><atom:link href="http://aigarius.com/feeds/rss/rss.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 &lt;a href="mailto:aigarius@gmail.com"&gt;Aigars Mahinovs&lt;/a&gt; </copyright><lastBuildDate>Tue, 24 Mar 2026 16:10:17 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Value of outreach and diversity to Debian</title><link>http://aigarius.com/blog/2026/03/23/value-of-outreach/</link><dc:creator>Aigars Mahinovs</dc:creator><description>&lt;p&gt;A question came up in private conversations, but the answer IMHO is useful
generally, so this is a repost. The question was generally on the topic of
divercity and outreach - if it does really help underpriviledged people to give
them some handout and hope that that somehow turns them into priviledged people?
IMHO this is an important question in current world environment in general and
to Debian in particular.&lt;/p&gt;
&lt;p&gt;IMHO It's not about making unprivileged people more privileged than current
contributors or about giving some kind of handouts.&lt;/p&gt;
&lt;p&gt;Just talking from my personal perspective, it is more about analysing where past
decisions (even perfectly reasonable ones) inadvertently created biases and
trying to figure out ways to balance them out over time so that we don't end up
missing good contributors just because they were, for example, unlucky with the
country of their birth.&lt;/p&gt;
&lt;p&gt;A simple example - think back a couple decades - where was the best place in the
world to learn how to develop free software in general and Debian in particular?
Where you had the largest chances of meeting an experienced developer in person
with enough free time who could show you the ropes and explain to you things
that are hard to put into documentation? I'd say those would be the campuses of
a bunch of technical universities in the USA, UK and the rest of Western Europe.&lt;/p&gt;
&lt;p&gt;If you were not attending a university, you were out of luck. If you were rural
in a smaller campus, you were out of luck. If you were on a different
continent - guess what? Still out of luck. Even Eastern Europe - so close, and
yet - out of luck.&lt;/p&gt;
&lt;p&gt;This made perfect sense and was a perfectly reasonable way to operate back
then - Western universities had the highest density of people who had both the
skill and the free time to contribute to free software. It was a no-brainer to
start there. It was not a mistake to do so. But it had side-effects.&lt;/p&gt;
&lt;p&gt;I was very lucky and persistent to overcome this out-of-luck situation, despite
the closest developers being 500-600 km away and across a sea and me operating
on actual dial-up Internet with barely enough money for a bus ticket, never mind
a sea ferry or a plane ticket. Or a laptop to take on such a plane. Thousands of
others around me, including many very competent software developers, did not
have that kind of luck and persistence and thus are not contributing to free
software or Debian at all.&lt;/p&gt;
&lt;p&gt;If we look back at the past, we can recognise that past decisions left whole
continents and also whole classes of people that were not given the opportunity
to learn how and why to contribute to free software and Debian. That is in the
end a realisation that there are many fine future developers out there who we
have not reached out to yet. At this point &lt;em&gt;that&lt;/em&gt; is a great untapped source of
new developers for the project. Opportunities in western universities will still
be there, noone wants to or can tear them down, but they also do not really need
investment of attention, time and money to keep being effective. But other
places do need that investment to start being effective. To start adding new
developers to the community.&lt;/p&gt;
&lt;p&gt;Outreach to diverse communities is in &lt;em&gt;our&lt;/em&gt;, selfish interests. Naturally we
still need to figure out how much effort is actually spent on that and evaluate
efficiency of different approaches. But in principle it &lt;em&gt;is&lt;/em&gt; what we want to do.&lt;/p&gt;
&lt;p&gt;(And also our knowledge might make their lives better, but that's a minor side
effect. /s)&lt;/p&gt;
&lt;p&gt;Questions? Feedback? Just ask
&lt;a href="https://bsky.app/profile/aigarius.com/post/3mhpsppg4fs2s"&gt;here&lt;/a&gt; or
&lt;a href="https://www.threads.com/@aigarius/post/DWORNr8iB9Y?xmt=AQF0y_tx8bqRwnwSm0BcMihG6z4TD-CNXgpYTRDkD73g1g"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><category>blog</category><category>car</category><category>Debian-planet</category><category>hardware</category><category>Ubuntu.lv-planet</category><category>work</category><guid>http://aigarius.com/blog/2026/03/23/value-of-outreach/</guid><pubDate>Mon, 23 Mar 2026 10:00:00 GMT</pubDate></item><item><title>Sedan experience (BMW i5)</title><link>http://aigarius.com/blog/2026/01/07/sedan-experience/</link><dc:creator>Aigars Mahinovs</dc:creator><description>&lt;div&gt;&lt;h2&gt;Two years of midsize electric sedan experience&lt;/h2&gt;
&lt;p&gt;This February (2026) marks a full 10 years since I started working for BMW, and
a key employment bonus is the ability to drive a company car on special two-year
leasing terms. Just before the new year 2026 started, I said goodbye to my
latest company car. After driving the
&lt;a href="https://aigarius.com/blog/2022/06/29/long-travel-in-an-electric-car/"&gt;BMW i4&lt;/a&gt;,
I switched to the
&lt;a href="https://www.bmw.de/de/neufahrzeuge/bmw-i/i5/bmw-i5-ueberblick.html"&gt;BMW i5&lt;/a&gt;. In
terms of power, it was a downgrade as I switched from the maximum power i4 M50
xDrive (all-wheel drive, 600 hp) to the i5 eDrive40 (rear-wheel drive, 340 hp).
Did I regret that? Not for a single second! After driving 60,000 km in the last
two years with the BMW i5, I was really sad to let it go -- it was the best car
I have ever driven. Simple as that.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://aigarius.com/blog/2026/01/07/sedan-experience/"&gt;Read more…&lt;/a&gt; (16 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>blog</category><category>car</category><category>Debian-planet</category><category>hardware</category><category>Ubuntu.lv-planet</category><category>work</category><guid>http://aigarius.com/blog/2026/01/07/sedan-experience/</guid><pubDate>Tue, 13 Jan 2026 10:00:00 GMT</pubDate></item><item><title>Snapshot mirroring in Debian (and Ubuntu)</title><link>http://aigarius.com/blog/2025/08/04/snapshot-mirrors/</link><dc:creator>Aigars Mahinovs</dc:creator><description>&lt;h2&gt;Snapshot mirroring in Debian (and Ubuntu)&lt;/h2&gt;
&lt;p&gt;The use of snapshots has been routine in both
&lt;a href="http://snapshot.debian.org"&gt;Debian&lt;/a&gt; and &lt;a href="http://snapshot.ubuntu.com"&gt;Ubuntu&lt;/a&gt;
for several years now—or more than 15 years for Debian, to be precise. Snapshots
have become not only very reliable, but also an increasingly important part of
the Debian package archive.&lt;/p&gt;
&lt;p&gt;This week, I encountered a problem at work that could be perfectly solved by
correctly using the Snapshot service. However, while trying to figure it out, I
ran into some shortcomings in the documentation. Until the docs are updated, I
am publishing this blog post to make this information easier to find.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Problem 1:&lt;/strong&gt; Ensure fully reproducible creation of Docker containers with the
&lt;em&gt;exact&lt;/em&gt; same packages installed, even &lt;em&gt;years&lt;/em&gt; after the original images were
generated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution 1:&lt;/strong&gt; Pin &lt;em&gt;everything&lt;/em&gt;! Use a pinned source image in the &lt;code&gt;FROM&lt;/code&gt;
statement, such as &lt;code&gt;debian:trixie-20250721-slim&lt;/code&gt;, and also pin the APT package
sources to the "same" date - "20250722".&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Hint:&lt;/em&gt; The APT packages need to be &lt;em&gt;newer&lt;/em&gt; than the Docker image base. If the
APT packages are a bit newer, that's not a problem, as APT can upgrade packages
without issues. However, if your Docker image has a newer package than your APT
package sources, you will have a &lt;em&gt;big&lt;/em&gt; problem. For example, if you have
"libbearssl0" version 0.6-2 installed in the Docker image, but your package
sources only have the older version 0.6-1, you will fail when trying to install
the "libbearssl-dev" package. This is because you only have version 0.6-1 of the
"-dev" package available, which hard-depends on &lt;em&gt;exactly&lt;/em&gt; version 0.6-1 of
"libbearssl0", and APT will refuse to downgrade an already installed package to
satisfy that dependency.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Problem 2:&lt;/strong&gt; You are using a &lt;em&gt;lot&lt;/em&gt; of images in a &lt;em&gt;lot&lt;/em&gt; of executions and
building tens of thousands of images per day. It would be a bad idea to put all
this load on public Debian servers. Using local sources is also faster and adds
extra security.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution 2:&lt;/strong&gt; Use local (transparently caching) mirrors for both the Docker
Hub repository and the APT package source.&lt;/p&gt;
&lt;p&gt;At this point, I ran into another issue—I could not easily figure out how to
specify a local mirror for the &lt;em&gt;snapshot&lt;/em&gt; part of the archive service.&lt;/p&gt;
&lt;p&gt;First of all, snapshot support in both Ubuntu and Debian accepts both syntaxes
described in the Debian and Ubuntu documentation above. The documentation on
both sites presents different approaches and syntax examples, but both work.&lt;/p&gt;
&lt;p&gt;The best approach nowadays is to use the "deb822" sources syntax. Remove
/etc/apt/sources.list (if it still exists), delete all contents of the
/etc/apt/sources.list.d directory, and instead create this file at
/etc/apt/sources.list.d/debian.sources:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;Types: deb
URIs: https://common.mirror-proxy.local/ftp.debian.org/debian/
Suites: trixie
Components: main non-free-firmware non-free contrib
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Snapshot: 20250722
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Hint: This assumes you have a mirror service running at
common.mirror-proxy.local that proxies requests (with caching) to whitelisted
domains, based on the name of the first folder in the path.&lt;/p&gt;
&lt;p&gt;If you now run &lt;code&gt;sudo apt update --print-uris&lt;/code&gt;, you will see that your
configuration accesses your mirror, but does not actually use the snapshot.&lt;/p&gt;
&lt;p&gt;Next, add the following to /etc/apt/apt.conf.d/80snapshots:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;APT::Snapshot "20250722";
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That should work, right? Let's try &lt;code&gt;sudo apt update --print-uris&lt;/code&gt; again. I've
got good news and bad news! The good news is that we are now actually using the
snapshot we specified (twice). The bad news is that we are completely ignoring
the mirror and going directly to snapshots.debian.org instead.&lt;/p&gt;
&lt;p&gt;Finding the right information was a bit of a challenge, but after a few tries,
this worked: to specify a custom local mirror of the Debian (or Ubuntu) snapshot
service, simply add the following line to the same file,
/etc/apt/apt.conf.d/80snapshots:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;Acquire::Snapshots::URI::Override::Origin::debian "https://common.mirror-proxy.local/snapshot.debian.org/archive/debian/@SNAPSHOTID@/";
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, if you check again with &lt;code&gt;sudo apt update --print-uris&lt;/code&gt;, you will see that
the requests go to your mirror &lt;em&gt;and&lt;/em&gt; include the specified snapshot identifier.
Success!&lt;/p&gt;
&lt;p&gt;Now you can install any packages you want, and everything will be completely
local and fully reproducible, even years later!&lt;/p&gt;</description><category>blog</category><category>debian</category><category>Debian-planet</category><category>photo</category><category>travel</category><category>Ubuntu.lv-planet</category><guid>http://aigarius.com/blog/2025/08/04/snapshot-mirrors/</guid><pubDate>Mon, 04 Aug 2025 18:00:00 GMT</pubDate></item><item><title>Debconf 25 photos</title><link>http://aigarius.com/blog/2025/08/03/debconf25-photos/</link><dc:creator>Aigars Mahinovs</dc:creator><description>&lt;h2&gt;Debconf 25 photos&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://debconf25.debconf.org/"&gt;Debconf 25&lt;/a&gt; came to the end in Brest, France
this year a couple weeks ago.&lt;/p&gt;
&lt;p&gt;This has been a very different and unusually interesting Debconf. For me it was
for two, related reasons: for one the conference was close enough in Western
Europe that I could simply drive there with a car (which reminds me that I
should make a blog post about the BMW i5, before I am done with it at the end of
this year) and for the other - the conference is close enough to Western Europe
that many other Debian developers could join this year who have not been seen at
the event for many years. Being able to arrive early, decompress and spend extra
time looking around the place made the event itself even more enjoyable than
usual.&lt;/p&gt;
&lt;p&gt;The French cuisine, especially in its Breton expression, has been a very welcome
treat. Even if there were some rough patches with the food selection, amount, or
waiting, it was still a great experience.&lt;/p&gt;
&lt;p&gt;I specifically want to say a big thank you to the organisers for everything, but
&lt;em&gt;very explicitly&lt;/em&gt; for planning all the talk/BOF rooms in the same building and
almost on the same floor. It saved me a lot of footwork, but also for other
participants the short walks between the talks made it possible to always have a
few minutes to talk to people or grab a croissant before running to the next
talk.&lt;/p&gt;
&lt;p&gt;IMHO we should come back to a tradition of organising Debconf in Europe every
2-3 years. This maximises one of the main goals of Debconf - bringing as many
Debian Developers as possible together in one physical location. This works best
when the location is actually close to large concentrations of existing
developers. In other years, the other goal of Debconf can then take priority -
recruiting new developers in new locations. However, these goals &lt;em&gt;could&lt;/em&gt; both be
achieved at the same time - there are plenty of locations in Europe and even in
Western Europe that still have good potential for attracting new developers.
Especially if we focus on organising the event on the campuses of some larger
technically-oriented universities.&lt;/p&gt;
&lt;p&gt;This year was also very productive for me—a lot of conversations with various
people about all kinds of topics, especially technical packaging questions. It
has been a long time since the very basic foundations of Debian packaging work
have been so fundamentally refactored and modernized as in the past year.
Tag2upload has become a catalyst for git-based packaging and for automated
workflows via Salsa, and all of that feeds back into focusing on a few
best-supported packaging workflows. There is still a bit of a documentation gap
of a new contributor getting to these modern packaging workflows from the point
where the New Maintainers Guide stops.&lt;/p&gt;
&lt;p&gt;In any case, next year Debconf will be happening in Santa Fe, Argentina. And the
year after that it is all still open and in a close
&lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-203-debconf-27-in-your-city.av1.webm"&gt;competition&lt;/a&gt;
between Japan, Spain, Portugal, Brazil and .. El Salvador? Personally, I would
love to travel to Japan (again), but Spain or Portugal would also be great
locations to meet more European developers again.&lt;/p&gt;
&lt;p&gt;As for Santa Fe ... it is quite likely that I will not be able to make it there
next year, for (planned) health reasons. I guess I should also write a new blog
post about what it means to be a Debconf Photographer, so that someone else
could do this as well, and also reduce the "bus factor" along the way.&lt;/p&gt;
&lt;p&gt;But before that - here is the main group photo from this year:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://salsa.debian.org/debconf-team/public/share/debconf25/-/blob/main/photos/aigarius/group/debconf25_group.jpg?ref_type=heads"&gt;&lt;img alt="DebConf 25 Group photo" src="https://salsa.debian.org/debconf-team/public/share/debconf25/-/raw/main/photos/aigarius/group/debconf25_group_tiny.jpg?inline=false"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can also see it on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://photos.app.goo.gl/iV2JAGcWT2pzePqP7"&gt;Google Photos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also enjoy the rest of the photos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/debconf-team/public/share/debconf25/-/tree/main/photos/aigarius/sel?ref_type=heads"&gt;on git-lfs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://photos.app.goo.gl/zF1romToBgXpHKr77"&gt;on Google Photos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, check out photos from other people on GIT LFS and consider adding
your own photos there as well.&lt;/p&gt;
&lt;p&gt;Other places I have updated with up-to-date information are these wiki pages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.debian.org/DebConf/GroupPhotoAll"&gt;All Debconf Group Photos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.debian.org/DebConf/25/Photos"&gt;All photos from Debconf25&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you took part in the
&lt;a href="https://wiki.debian.org/AndySimpkins/DC_PlayingCards2025"&gt;playing cards event&lt;/a&gt;,
then check your photo in
&lt;a href="https://salsa.debian.org/debconf-team/public/share/debconf25/-/tree/main/photos/aigarius/cards?ref_type=heads"&gt;this folder&lt;/a&gt;
and link to your favourite from your line in the playing card wiki&lt;/p&gt;</description><category>blog</category><category>debian</category><category>Debian-planet</category><category>photo</category><category>travel</category><category>Ubuntu.lv-planet</category><guid>http://aigarius.com/blog/2025/08/03/debconf25-photos/</guid><pubDate>Sun, 03 Aug 2025 15:00:00 GMT</pubDate></item><item><title>Debconf 24 photos</title><link>http://aigarius.com/blog/2024/08/02/debconf24-photos/</link><dc:creator>Aigars Mahinovs</dc:creator><description>&lt;p&gt;&lt;a href="https://debconf24.debconf.org/"&gt;Debconf 24&lt;/a&gt; is coming to a close in Busan,
South Korea this year.&lt;/p&gt;
&lt;p&gt;I thought that last year in India was hot. This year somehow managed to beat
that. With 35C and high humidity the 55 km that I managed to walk between the
two conference buildings have really put the pressure on. Thankfully the air
conditioning in the talk rooms has been great and fresh water has been
plentiful. And the korean food has been excellent and very energetic.&lt;/p&gt;
&lt;p&gt;Today I will share with you the main group photo:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://salsa.debian.org/debconf-team/public/share/debconf24/-/raw/main/photos/aigarius/group/debconf24_group.jpg?inline=false" alt="DebConf 24 Group photo" width="1064" height="734"&gt;&lt;/p&gt;
&lt;p&gt;You can also see it in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://photos.google.com/share/AF1QipNWCTYCaSDyKioIJR1eolSpSF1RnPg55P61-ue_BV6A3ZGjitqXn2lQAhMEnsFrdQ/photo/AF1QipP7ljh6rqfuiaMY8_RCtecY1oQFaE_TMUIkNNE3?key=a3BNZG5OaW82Q2tKSzVCY3R5ZHlWTFlOUTczN2dR"&gt;on Google Photos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/debconf-team/public/share/debconf24/-/blob/main/photos/aigarius/group/debconf24_group.jpg"&gt;on git-lfs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The rest of my photos from the event will be published next week. That will give
me a bit more time to process them correctly and also give all of you a chance
to see these pictures with fresh eyes and stir up new memories from the event.&lt;/p&gt;</description><category>blog</category><category>debian</category><category>Debian-planet</category><category>photo</category><category>travel</category><category>Ubuntu.lv-planet</category><guid>http://aigarius.com/blog/2024/08/02/debconf24-photos/</guid><pubDate>Fri, 02 Aug 2024 09:00:00 GMT</pubDate></item><item><title>Figuring out finances part 5</title><link>http://aigarius.com/blog/2024/01/04/figuring-out-finances-part-5/</link><dc:creator>Aigars Mahinovs</dc:creator><description>&lt;p&gt;At the end of the
&lt;a href="https://aigarius.com/blog/2023/10/29/finance-project-four/"&gt;last part&lt;/a&gt; of this,
we got a Home Assistant OS installation that contains in itself a Firefly III
instance and that contains all the current financial information. They are
communicating and calculating predictions for me.&lt;/p&gt;
&lt;p&gt;The only part that I was not 100% happy with was accounting of cash
transactions. You see payments in cash are mostly made away from computer and
sometimes even in areas without a mobile Internet connection. And all Firefly
III apps that I tried failed at the task of creating a new transaction when
offline. Even the one recommended Telegram bot from Firefly III page used a
dialog-based approach for creating even a simplest transaction. Issue asking for
a one-shot transaction creation option stands as unresolved.&lt;/p&gt;
&lt;p&gt;Theoretically it would have been best if I could simply contribute that feature
to that particular Telegram bot ... but it's written in Javascript. By mapping
the API onto tasks somehow. After about 4 hours I still could not figure out
where in the code anything actually happens. It all looked like just sugar or
spagetty. Connectors on connectors on mappers.&lt;/p&gt;
&lt;p&gt;So I did the real open-source thing and just wrote my own tool.
&lt;a href="https://github.com/aigarius/firefly3_telegram_oneshot"&gt;firefly3_telegram_oneshot&lt;/a&gt;
is a maximally simple Telegram bot based on
&lt;a href="https://python-telegram-bot.org/"&gt;python-telegram-bot&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;So what does it do? The primary usage for me is to simply send a message to the
bot at any time with text like "23.2 coffee and cake" and when the message
eventually reaches the bot, it then should create a new transaction from my
"cash" account to "Unknown" account in amount of 23.20€ and description "coffee
and cake".&lt;/p&gt;
&lt;p&gt;That is the key. Everything else in the bot is comfort.&lt;/p&gt;
&lt;p&gt;For example "/undo" command deletes the last transaction in cash account
(presumably added by error) and "/last" shows which transaction the "/undo"
would delete.&lt;/p&gt;
&lt;p&gt;And to help with expense categorisation one can also do a message like "6.1
beer, dest=Edeka, cat=alcohol" that would search for a destination account that
would fuzzy match to "Edeka" (a supermarket in Germany) and add the transation
to the category fuzzy matched to "alcohol", like "Shopping - alcoholic drinks".&lt;/p&gt;
&lt;p&gt;And to make that fuzzy matching more reliable I also added "/cat something" and
"/dest something" commands that would show which category or destination account
would be matched with a given string.&lt;/p&gt;
&lt;p&gt;All of that in around 250 lines of Python code and executed by a 17 line
Dockerfile (via the Portainer on my Home Assistant OS). One remaining function
that could be nice is creating a category or destination account on request (for
example when the first character of the supplied string is "+").&lt;/p&gt;
&lt;p&gt;I am really plesantly surprised about how much can be done with how little code
using the above Python library. And you never need to have any open incoming
ports anywhere to runs such bots, so the attack surface for such bot-based
service is much tighter.&lt;/p&gt;
&lt;p&gt;All in all the system works and works well. The only exception is that for my
particual bank there is still no automatic way of extracting data about credit
card transactions. For those I still have to manually log into the Internet
bank, export a CSV file and then feed that into the Firefly III importer.
Annoying. And I am not really motivated to try to hack my bank :D&lt;/p&gt;
&lt;p&gt;Has this been useful to any of you? Any ideas to expand or improve what I have?
Just find me as "aigarius" on any social media and speak up :)&lt;/p&gt;</description><category>blog</category><category>Debian-planet</category><category>finances</category><category>Ubuntu.lv-planet</category><guid>http://aigarius.com/blog/2024/01/04/figuring-out-finances-part-5/</guid><pubDate>Thu, 04 Jan 2024 20:46:14 GMT</pubDate></item><item><title>Figuring out finances part 4</title><link>http://aigarius.com/blog/2023/10/29/finance-project-four/</link><dc:creator>Aigars Mahinovs</dc:creator><description>&lt;p&gt;At the end of the
&lt;a href="https://aigarius.com/blog/2023/10/22/finance-project-three/"&gt;last part&lt;/a&gt; of
this, we got a Home Assistant OS installation that contains in itself a Firefly
III instance and that contains all the current financial information. Now I will
try to connect the two.&lt;/p&gt;
&lt;p&gt;While it could be nice to create a fully-featured integration for Firefly III to
Home Assistant to communicate all interesting values and events, I have an
interest on programming a more advanced data point calculation for my budget
needs, so a less generic, but more flexible approch is a better one for me. So I
was quite interested when among the addons in the Home Assistant Addon Store I
saw &lt;a href="https://appdaemon.readthedocs.io/en/latest/index.html"&gt;AppDaemon&lt;/a&gt; - a way
to simply integrate arbitrary Python processing with Home Assistant. Let's see
if that can do what I want.&lt;/p&gt;
&lt;p&gt;For start, after reading
&lt;a href="https://appdaemon.readthedocs.io/en/latest/HASS_TUTORIAL.html"&gt;the tutorial&lt;/a&gt; ,
I wanted to create a simple script that would use
&lt;a href="https://docs.firefly-iii.org/firefly-iii/api/"&gt;Firefly III REST API&lt;/a&gt; to read
the current balance of my main account and then send that to Home Assistant as a
sensor value, which then can be displayed on a dashboard.&lt;/p&gt;
&lt;p&gt;As a quick try I modified the provided hello_world.py that is included in the
default AppDaemon installation:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;appdaemon.plugins.hass.hassapi&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;hass&lt;/span&gt;
&lt;span class="n"&gt;app_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;FIREFLY_PERSONAL_ACCESS_TOKEN&amp;gt;"&lt;/span&gt;
&lt;span class="n"&gt;firefly_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;FIREFLY_URL&amp;gt;"&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HelloWorld&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hass&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_asset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"now"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;ent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_entity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"sensor.firefly3_asset_sparkasse_main"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;ent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;ent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s2"&gt;"native_value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"native_unit_of_measurement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"EUR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"state_class"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"measurement"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"device_class"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"monetary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"current_balance_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;firefly_url&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"/api/v1/accounts?type=asset"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Bearer "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;app_token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"application/vnd.api+json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="s2"&gt;"attributes"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"Sparkasse giro"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Account :"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
            &lt;span class="n"&gt;ent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"current_balance"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s2"&gt;"native_value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"current_balance"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="s2"&gt;"current_balance_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"current_balance_date"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Entity updated"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It uses a URL and personal access token to access Firefly III API, gets the
asset accounts information, then extracts info about current balance and balance
date of my main account and then creates and/or updates a "sensor" value into
Home Assistant. This sensor is with
&lt;a href="https://developers.home-assistant.io/docs/core/entity/sensor/"&gt;metadata&lt;/a&gt; marked
as a monetary value and as a measurement. This makes Home Assistant track this
value in the database as a graphable changing value.&lt;/p&gt;
&lt;p&gt;I modified the file using the File Editor addon to edit the
&lt;code&gt;/config/appdaemon/apps/hello.py&lt;/code&gt; file. Each time the file is saved it is
reloaded and logs can be seen in the AppDaemon Logs section - main_log for
logging messages or error_log if there is a crash. Useful to know that
&lt;a href="https://requests.readthedocs.io/en/latest/"&gt;requests&lt;/a&gt; library is included, but
it hard to see in the docks what else is included or if there is an easy way to
install extra Python packages.&lt;/p&gt;
&lt;p&gt;This is already a very nice basis for custom value insertion into Home
Assistant - whatever you can with a Python script extract or calculate, you can
also inject into Home Assistant. With even this simple approach you can monitor
balances, budgets, piggy-banks, bill payment status and even sum of transactions
in particular catories in a particular time window. Especially interesting data
can be found in the insight section of the Firefly III API.&lt;/p&gt;
&lt;p&gt;The script above uses a trigger like
&lt;code&gt;self.run_every(self.set_asset, "now", 60 * 60)&lt;/code&gt; to simply run once per hour.
The data in Firefly will not be updated too often anyway, at least not until we
figure out how to make bank connection run automatically without user
interaction and not screw up already existing transactions along the way. In
theory a
&lt;a href="https://docs.firefly-iii.org/firefly-iii/features/webhooks/"&gt;webhook API&lt;/a&gt; of
the Firefly III could be used to trigger the data update instantly when any
transaction is created or updated. Possibly even using Home Assistant
&lt;a href="https://www.home-assistant.io/docs/automation/trigger/#webhook-trigger"&gt;webhook integration&lt;/a&gt;.
Hmmm. Maybe.&lt;/p&gt;
&lt;p&gt;Who am I kiddind? I am &lt;em&gt;going&lt;/em&gt; to make that work, for sure! :D But first - how
about figuring out the future?&lt;/p&gt;
&lt;p&gt;So what I want to do? In short, I want to predict what will be the balance on my
main account just &lt;em&gt;before&lt;/em&gt; the next months salary comes in. To do this I would:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;take the current balance of the main account&lt;/li&gt;
&lt;li&gt;if this months salary is not paid out yet, then add that into the balance&lt;/li&gt;
&lt;li&gt;deduct all still unpaid bills that are due between now and the target date&lt;/li&gt;
&lt;li&gt;if the credit card account has not yet been reset to the main account, deduct
  current amount on the cards&lt;/li&gt;
&lt;li&gt;if credit card account has been reset, but not from main account deducted yet,
  deduct the reset amount&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To do that I need to use the Firefly API to read: current account info, status
of all bills including next due date and amount, transfer transactions between
credit cards and main account and something that would store the expected salary
date and amount. Ideally I'd use a recurring transaction or a income bill for
this, but Firefly is not really cooperating with that. The easiest would be just
to hardcode that in the script itself.&lt;/p&gt;
&lt;p&gt;And &lt;a href="https://github.com/aigarius/firefly3_ha_oracle"&gt;this&lt;/a&gt; is what I have come
up with so far.&lt;/p&gt;
&lt;p&gt;To make the development process easier, I separated put the params for the API
key and salary info and app params for the month to predict for, and predict
both this and next months balances at the same time. I edited the script locally
with Neovim and also ran it locally with a few mocks, uploading to Home
Assistant via the SSH addon when the local executions looked good.&lt;/p&gt;
&lt;p&gt;So what's next? Well, need to somewhat automate the sync with the bank (if at
all possible). And for sure take a regular database and config backup :D&lt;/p&gt;</description><category>blog</category><category>Debian-planet</category><category>finances</category><category>Ubuntu.lv-planet</category><guid>http://aigarius.com/blog/2023/10/29/finance-project-four/</guid><pubDate>Sun, 29 Oct 2023 17:00:00 GMT</pubDate></item><item><title>Figuring out finances part 3</title><link>http://aigarius.com/blog/2023/10/22/finance-project-three/</link><dc:creator>Aigars Mahinovs</dc:creator><description>&lt;p&gt;So now that I have something that looks very much like a budgeting setup going,
I am going to .. delete it! Why? Well, at the end of the
&lt;a href="https://aigarius.com/blog/2023/10/15/finance-project-two/"&gt;last part&lt;/a&gt; of this,
the &lt;a href="https://www.firefly-iii.org/"&gt;Firefly III&lt;/a&gt; instance was running on a tiny
Debian server in a Docker container right next to another Docker container that
is running the main user of this server - a
&lt;a href="https://www.home-assistant.io/"&gt;Home Assistant&lt;/a&gt; instance that has been managing
my home for several years already. So why change that?&lt;/p&gt;
&lt;p&gt;See, there is one bit of knowledge that is very crucial to your Home Assistant
experience, which is not really emphasised enough in the Home Assistant
documentation. In fact back when I was getting into the Home Assistant both the
main documentation and basically all the guides around were just coming off the
hype of Docker disrupting everything and that is a big reason why everyone
suggested to install and use
&lt;a href="https://www.home-assistant.io/installation/generic-x86-64#install-home-assistant-container"&gt;Home Assistant as a Docker&lt;/a&gt;
container on top of any kind of stable OS. In fact I used to run it for years on
my &lt;a href="https://www.terra-master.com/uk/f2-221.html"&gt;TerraMaster NAS&lt;/a&gt;, just so that
I don't have a separate home server running 24/7 at home and just have
everything inside the very compact NAS case.&lt;/p&gt;
&lt;p&gt;So here is the thing you &lt;strong&gt;&lt;em&gt;NEED&lt;/em&gt;&lt;/strong&gt; to know - Home Assistant Container is
&lt;strong&gt;&lt;em&gt;DEMO&lt;/em&gt;&lt;/strong&gt; version of Home Assistant! If you want to have a full Home Assistant
experience and use the knowledge of the huge community around the HA space, you
&lt;strong&gt;&lt;em&gt;have to&lt;/em&gt;&lt;/strong&gt; use the
&lt;a href="https://www.home-assistant.io/installation/generic-x86-64#install-home-assistant-operating-system"&gt;Home Assistant OS&lt;/a&gt;.
Ideally on dedicated hardware. Ideally on
&lt;a href="https://www.home-assistant.io/green"&gt;HA Green&lt;/a&gt; box, but any
&lt;a href="https://www.csl-computer.com/en/pc-systems/mini-pcs/csl-narrow-box-compact-v5/mini-pc-csl-narrow-box-ultra-hd-compact-v5-windows-11-home.html"&gt;tiny PC&lt;/a&gt;
would also work great.
&lt;a href="https://www.raspberrypi.com/products/raspberry-pi-5/"&gt;Raspberry Pi 4+&lt;/a&gt; is
common, but quite weak as the network size grows and especially the SD card for
storage gets old &lt;em&gt;very&lt;/em&gt; fast. Get a real small x86 PC with at least 4Gb RAM and
a NVME SSD (eMMC is fine too). You want to have an Ethernet port and a few free
USB ports. I would also suggest immediately getting
&lt;a href="https://www.home-assistant.io/skyconnect"&gt;HA SkyConnect adapter&lt;/a&gt; that can do
Zigbee networking and will do Matter soon (tm). I am making do with a
&lt;a href="https://itead.cc/product/sonoff-zbbridge/"&gt;SonOff Zigbee&lt;/a&gt; gateway, but it is
&lt;a href="https://digiblur.com/2020/07/25/how-to-use-the-sonoff-zigbee-bridge-with-home-assistant-tasmota/"&gt;quite hacky&lt;/a&gt;
to get working and your whole Zigbee communication breaks down if the WiFi goes
down - suboptimal.&lt;/p&gt;
&lt;p&gt;So I took a backup of the Home Assistant instance using it's build-in tools. I
took an export of my fully configured Firefly III instance and proceeded to wipe
the drive of the NUC. That was not a smart idea. :D&lt;/p&gt;
&lt;p&gt;On the Home Assitant side I was really frustrated by
&lt;a href="https://www.home-assistant.io/installation/generic-x86-64#write-the-image-to-your-boot-medium"&gt;the documentation&lt;/a&gt;
that was really focused on users that are (likely) using Windows and are using
an SD card in something like Raspberry Pi to get Home Assistant OS running. It
recommended downloading &lt;a href="https://www.balena.io/etcher"&gt;Etcher&lt;/a&gt; to write the
image to the boot medium. That is a really weird piece of software that managed
to actually crash consistently when I was trying to run it from Debian Live or
Ubuntu Live on my NUC. It took me way too long to give up and try something much
simpler - dd.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xzcat haos_generic-x86-64-11.0.img.xz | dd of=/dev/mmcblk0 bs=1M&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That just worked, prefectly and really fast. If you want to use a GUI in a live
environment, then just using the gnome-disk-utility ("Disks" in Gnome menu) and
using the "Restore Disk Image ..." on a partition would work just as well. It
even supports decompressing the XZ images directly while writing.&lt;/p&gt;
&lt;p&gt;But that image is small, will it not have a ton of unused disk space behind the
fixed install partition? Yes, it will ... until first boot. The HA OS takes over
the empty space after its install partition on the first boot-up and just grows
its main partition to take up all the remaining space. Smart. After first boot
is completed, the first boot wizard can be accessed via your web browser and one
of the prominent buttons there is restoring from backup. So you just give it the
backup file and wait. Sadly the restore does not actually give any kind of
progress, so your only way to figure out when it is done is opening the same web
adress in another browser tab and refresh periodically - after restoring from
backup it just boots into the same config at it had before - all the settings,
all the devices, all the history is preserved. Even authentification tokens are
preserved so if yu had a
&lt;a href="https://companion.home-assistant.io/"&gt;Home Assitant Mobile&lt;/a&gt; installed on your
phone (both for remote access and to send location info and phone state, like
charging, to HA to trigger automations) then it will just suddenly start working
again without further actions needed from your side. That is an almost perfect
backup/restore experience.&lt;/p&gt;
&lt;p&gt;The first thing you get for using the OS version of HA is easy automatic update
that also automatically takes a backup before upgrade, so if anything breaks you
can roll back with one click. There is also a command-line tool that allows to
upgrade, but also
&lt;a href="https://community.home-assistant.io/t/downgrading/414612/2"&gt;downgrade ha-core&lt;/a&gt;
and other modules. I had to use it today as HA version 23.10.4 actually broke
support for the Sonoff bridge that I am using to control Zigbee devices, which
are like 90% of all smart devices in my home. Really helpful stuff, but not a
must have.&lt;/p&gt;
&lt;p&gt;What &lt;em&gt;is&lt;/em&gt; a must have and that you can (really) only get with Home Assistant
Operating System are &lt;a href="https://www.home-assistant.io/addons/"&gt;Addons&lt;/a&gt;. Some
addons are just normal servers you can run alongside HA on the same HA OS
server, like MariaDB or Plex or a file server. That is not the most important
bit, but even there the software comes pre-configured to use in a home server
configuration and has a very simple config UI to pre-configure key settings,
like users, passwords and database accesses for MariaDB - you can litereally in
a few clicks and few strings make serveral users each with its own access to its
own database. Couple more clicks and the DB is running and will be kept
restarted in case of failures.&lt;/p&gt;
&lt;p&gt;But the &lt;em&gt;real&lt;/em&gt; gems in the Home Assistant Addon Store are modules that extend
Home Assitant core functionality in way that would be &lt;em&gt;really&lt;/em&gt; hard or near
impossible to configure in Home Assitant Container manually, especially because
no documentation has ever existed for such manual config - everyone just tells
you to install the addon from HA Addon store or from HACS. Or you can read the
addon metadata in various repos and figure out what containers it actually runs
with what settings and configs and what hooks it puts into the HA Core to make
them cooperate. And then do it all over again when a new version breaks
everything 6 months later when you have already forgotten everything. In the
Addons that show up immediately after installation are addons to install the new
&lt;a href="https://www.home-assistant.io/blog/2023/02/08/state-of-matter-and-thread/"&gt;Matter&lt;/a&gt;
server, a MariaDB and &lt;a href="https://www.home-assistant.io/integrations/mqtt/"&gt;MQTT&lt;/a&gt;
server (that other addons can use for data storage and message exchange), Z-Wave
support and ESPHome integration and very handy File manager that includes
editors to edit Home Assitant configs directly in brower and SSH/Terminal addon
that boht allows SSH connection and also a web based terminal that gives access
to the OS itself and also to a comand line interface, for example, to do package
downgrades if needed or see detailed logs. And also there is where you can get
the features that are the focus this year for HA developers -
&lt;a href="https://www.home-assistant.io/blog/2023/10/12/year-of-the-voice-chapter-4-wakewords/"&gt;voice enablers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However that is only a beginning. Like in Debian you can add additional
repositories to expand your list of available addons. Unlike Debian
&lt;a href="https://community.home-assistant.io/tag/hassio-repository"&gt;most of the amazing software&lt;/a&gt;
that is available for Home Assistant is outside the main, official addon store.
For now I have added the most popular addon repository -
&lt;a href="https://hacs.xyz/"&gt;HACS&lt;/a&gt; (Home Assistant Community Store) and repository
maintained by &lt;a href="https://github.com/alexbelgium/hassio-addons"&gt;Alexbelgium&lt;/a&gt;. The
first includes things like NodeRED (a workflow based automation programming UI),
Tailscale/Wirescale for VPN servers, motionEye for CCTV control, Plex for home
streaming. HACS also includes a &lt;em&gt;lot&lt;/em&gt; of HA UI enhacement modules, like themes,
custom UI control panels like Mushroom or mini-graph-card and integrations that
provide more advanced functions, but also require more knowledge to use, like
Local Tuya - that is harder to set up, but allows fully local control of
(normally) cloud-based devices. And it has
&lt;a href="https://appdaemon.readthedocs.io/"&gt;AppDaemon&lt;/a&gt; - basically a Python based
automation framework where you put in Python scrips that get run in a special
environment where they get fed events from Home Assistant and can trigger back
events that can control everything HA can and also do anything Python can do.
This I will need to explore later.&lt;/p&gt;
&lt;p&gt;And the repository by Alex includes the thing that is actually &lt;em&gt;the&lt;/em&gt; focus of
this blog post (I know :D) - Firefly III addon and Firefly Importer addon that
you can then add to your Home Assistant OS with a few clicks. It also has all
kinds of addons for NAS management, photo/video server, book servers and
&lt;a href="https://community.home-assistant.io/t/home-assistant-community-add-on-portainer/68836"&gt;Portainer&lt;/a&gt;
that lets us setup and run &lt;em&gt;any&lt;/em&gt; Docker container inside the HA OS structure. HA
OS &lt;em&gt;will&lt;/em&gt; detect this and warn you about unsupported processes running on your
HA OS instance (nice security feature!), but you can just dismiss that. This
will be very helpful very soon.&lt;/p&gt;
&lt;p&gt;This whole environment of OS and containers and apps really made me think - what
was missing in Debian that made the talented developers behind all of that to
spend the immense time and effor to setup a completely new OS and app
infrastructure and develop a completel paraller developer community for Home
Assistant apps, interfaces and configurations. Is there &lt;em&gt;anything&lt;/em&gt; that can
still be done to make HA community and the general open source and Debian
community closer together? HA devs are not doing anything &lt;em&gt;wrong&lt;/em&gt;: they are
using the best open source can provide, they bring it to people whould could not
install and use it otherwise, they are contributing fixes and improvements as
well. But there must be some way to do this better, together.&lt;/p&gt;
&lt;p&gt;So I installed MariaDB, create a user and database for Firefly. I installed
Firefly III and configured it to use the MariaDB with the web config UI. When I
went into the Firefly III web UI I was confronted with the normal wizard to
setup a new instance. And no reference to any backup restore. Hmm, ok. Maybe
that goes via the Importer? So I make an access token again, configured the
Importer to use that, configured the Nordlinger bank connection settings. Then I
tried to import the export that I downloaded from Firefly III before. The
importer did not auto-recognose the format. Turns out it is just a list of
transactions ... It can only be barely useful if you first manually create all
the asset accounts with the same names as before and even then you'll again have
to deal with resolving the problem of transfers showing up twice. And all of
your categories (that have not been used yet) are gone, your automation rules
and bills are gone, your budgets and piggy banks are gone. Boooo. It will be
easier for me to recreate my account data from bank exports again than to
resolve data in that transaction export.&lt;/p&gt;
&lt;p&gt;Turns out that Firefly III documenation
&lt;a href="https://docs.firefly-iii.org/firefly-iii/advanced-installation/backup/"&gt;explicitly&lt;/a&gt;
recommends making a mysqldump of your own and not rely on anything in the app
itself for backup purposes. Kind of sad this was not mentioned in the export
page that sure looked a lot like a backup :D&lt;/p&gt;
&lt;p&gt;After doing all that work all over again I needed to make &lt;em&gt;something&lt;/em&gt; new not to
feel like I wasted days of work for no real gain. So I started solving a problem
I had for a while already - how do I add cash transations to the system when I
am out of the house with just my phone in the hand? So far my workaround has
been just sending myself messages in WhatsApp with the amount and description of
any cash expenses. Two solutions are possible: app and bot.&lt;/p&gt;
&lt;p&gt;There are actually &lt;em&gt;multiple&lt;/em&gt;
&lt;a href="https://docs.firefly-iii.org/firefly-iii/more-information/3rdparty/#mobile-applications"&gt;Android-based phone apps that work with Firefly III API&lt;/a&gt;
to do full financial management from the phone. However, after trying it out,
that is not what I will be using most of the time. First of all this requires
your Firefly III instance to be accessible from the Internet. Either via direct
API access using some port forwarding and secured with HTTPS and good access
tokens, or via a VPN server redirect that is installed on both HA and your
phone. Tailscale was really easy to get working. But the power has its
drawbacks - adding a new cash transaction requires opening the app, choosing new
transaction view, entering descriptio, amount, choosing "Cash" as source account
and optionally choosing destination expense account, choosing category and
budget and then submitting the form to the server. Sadly none of that really
works if you have no Internet or bad Internet at the place where you are using
cash. And it's just too many steps. Annoying.&lt;/p&gt;
&lt;p&gt;An easier alternative is setting up a
&lt;a href="https://github.com/cyxou/firefly-iii-telegram-bot"&gt;Telegram bot&lt;/a&gt; - it is
running in a custom Docker container right next to your Firefly (via Portainer)
and you talk to it via a
&lt;a href="https://core.telegram.org/bots/tutorial#obtain-your-bot-token"&gt;custom Telegram chat channel&lt;/a&gt;
that you create very easily and quickly. And then you can just tell it "Coffee
5" and it will create a transaction from the (default) cash account in 5€ amount
with description "Coffee". This part also works if you are offline at the
moment - the bot will receive the message once you get back online. You can use
Telegram bot menu system to edit the transaction to add categories or expense
accounts, but this part only work if you are online. And the Firefly instance
does not have to be online at all. Really nifty.&lt;/p&gt;
&lt;p&gt;So next week I will need to write up all the regular payments as bills in
Firefly (again) and then I can start writing a Python script to predict my
(financial) future!&lt;/p&gt;</description><category>blog</category><category>Debian-planet</category><category>finances</category><category>Ubuntu.lv-planet</category><guid>http://aigarius.com/blog/2023/10/22/finance-project-three/</guid><pubDate>Sun, 22 Oct 2023 17:00:00 GMT</pubDate></item><item><title>Figuring out finances part 2</title><link>http://aigarius.com/blog/2023/10/15/finance-project-two/</link><dc:creator>Aigars Mahinovs</dc:creator><description>&lt;p&gt;A &lt;a href="http://aigarius.com/blog/2023/10/09/finance-project-start/"&gt;week ago&lt;/a&gt; I started to migrate my
financial planning from a closed source system to a new system based on an open
source, self-hosted solution. Main candidate is
&lt;a href="https://www.firefly-iii.org/"&gt;Firefly III&lt;/a&gt; - a relatively simple financial
planner with a rather rich feature set and a solid user base and developer
support.&lt;/p&gt;
&lt;p&gt;Starting it up with a Docker-Compose file was quite easy, following the official
documentation. The same Compose file also managed the MySQL database, the
importer app and a cron container for regular imports. The separate importer app
allows both imports from CSV files and also from external bank account
connection services. For whatever weird reason both of those services support
exporting data from my regular bank accounts, but &lt;strong&gt;not&lt;/strong&gt; from my credit cards
for exactly the same bank. So for those cards I would need to periodically
download CVS transaction exports and feed them into the importer.&lt;/p&gt;
&lt;p&gt;The combination of the cron container and the importer app allows for both of
these functions. To do this you first do the import via the Web UI first and
configure all the mappings - configure file and date formats, map account names
in the bank output to account names that you added in Firefly, configure what
otehr columns mean and what is the mapping of other values, like expense and
income accounts. At the end of the process you can download a json file
representing all the settings of the import you just did. Putting such a json
config file in the input folder of the cron container and telling it to do an
import (weekly, for example) would do such import periodically. Putting a credit
card CSV file along with a config file for credit card import would also
auto-import that.&lt;/p&gt;
&lt;p&gt;So far so good. However, when I tried importing exports from MoneyWiz or even
when I tried re-creating account history directly from the bank data, I hit a
very annoying problem. Transfers. Thing is detecting transfers between the real
(asset) accounts that you are managing is really essential. For one those are
not real expenses and incomes, so failing to mark them as transfers would show
weird income/expense numbers. But if you &lt;em&gt;do&lt;/em&gt; detect them as transfers &lt;em&gt;and&lt;/em&gt;
correctly map the destination account, but &lt;em&gt;fail&lt;/em&gt; to match the transations
between another you get a double-transaction. This becomes really hard when
transactions happen on different dates and have different descriptions. So you
get &lt;em&gt;both&lt;/em&gt; a +1000€ transaction "Credit card reset" on 14.09.2023 in the credit
card account &lt;em&gt;and&lt;/em&gt; a -1000$ transaction "Repayment of own credit card" on
24.09.2023 in the main account of the bank. Matching them to recognise that it
is just &lt;em&gt;one&lt;/em&gt; transfer and not two is ... non-trivial. The best solution I could
come up with so far is to always map the "Opposing account name" for such
transfers to a virtual "Transfers" asset account. That has the benefit of being
actually able to correctly represent transfers that take several days to move
between accounts and showing you how much money is still in transit at any point
in time.&lt;/p&gt;
&lt;p&gt;So after I figured this out, finally the account balances started matching up
with reality.&lt;/p&gt;
&lt;p&gt;Setting up spending categories required another change - the author of the
Firefly III does not like complexity so it does not support nesting categories.
Categories can only be in a single, flat list. It is suggested that if you do
need to track multiple categories and also their combination, then category
groups might help you. I will survive for now by simplifying the categories that
I do actually use. Might actually make the reports more usable.&lt;/p&gt;
&lt;p&gt;A new feature for me will be the ability to use automation rules to assign
transactions to categories based on their contents, like expense accounts of
keywords in descriptions.&lt;/p&gt;
&lt;p&gt;Setting up regular bills (with matching rules to assign incoming transactions to
those bills) is another feature that is very important to me. The feature itself
works just fine in Firefly III, but it has two restrictions that the author of
the software does not actually want to be changed. For one it can not be used to
track prodictable &lt;strong&gt;incomes&lt;/strong&gt; (like salary), presumably because it is only there
for bills (subscriptions in v3 UI). And for other, there is nothing in the base
software that actually uses the data from bills to look forward. The author does
not like to try to predict the future. Which for me is basically the one of two
reasons to use this kind of software at all. I want to know - given all manually
entered regular and 100% predictable expenses and incomes, what will be the
state of my accounts at particular date? It seems that to get at that I will
need to write my own oracle script using the rich Firefly III API.&lt;/p&gt;
&lt;p&gt;The last question I had for this week was - how will I enter a new cash puchace
of potatoes on a farmers market into the system that sits in a private server in
my home network? Turns out there are actually multiple Android apps for Firefly
III that can be easily used for this using a robust OAuth or shared token
authentification. Except the web UI needs to be exposed online for this to work
(and ideally protected by HTTPS). Other users have also created Telegram bots
that allow using chat messages to create transaction entries. This is a bit
harder to use and more narrow scope, but should be easier to setup. Will have to
try both apporaches.&lt;/p&gt;
&lt;p&gt;But before I really get going on this, I need to fix another thing that I have
been postponing for a while: I will need to migrate my Home Assistant
installation from a Docker container installation to a Home Assistant OS
installation so that I can install Addons, including Firefly III, MySQL and
Portainer to have a bit more organised and less hand-knitted home server setup.
Let's see how that goes next week :D&lt;/p&gt;</description><category>blog</category><category>Debian-planet</category><category>finances</category><category>Ubuntu.lv-planet</category><guid>http://aigarius.com/blog/2023/10/15/finance-project-two/</guid><pubDate>Sun, 15 Oct 2023 17:00:00 GMT</pubDate></item><item><title>Figuring out finances part 1</title><link>http://aigarius.com/blog/2023/10/09/finance-project-start/</link><dc:creator>Aigars Mahinovs</dc:creator><description>&lt;p&gt;I have been managing my finances and getting an overview of where I am
financially and where I am going month-to-month for a few years already. That
means that I already have &lt;em&gt;a&lt;/em&gt; method of doing my finances and a method of
thinking about them. So far this has been supported by a commerical tool called
MoneyWiz. I was happy to pay them for the ability to have a solid product and be
able to easily access my finances from my phone (to enter cash transactions
directly in the field) and sync data across multiple devices with their cloud
offering. However, MoneyWiz development stalled. So much so that they stopped
updating their Android app and cancelled web version plans to just focus on a
iPhone and MacOS clients. And even there the development did not seem very
successful over the last year. So I am cancelling their subscription, extracting
all my data (as CSV) and looking for alternatives.&lt;/p&gt;
&lt;p&gt;So let's start with the basics - what I want from finace software?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open source and self-hosted&lt;/li&gt;
&lt;li&gt;Accounts to represent real accounts in my bank, credit cards, cash account&lt;/li&gt;
&lt;li&gt;Transactions to represent money moving in/out/between accounts&lt;/li&gt;
&lt;li&gt;Tree of categories for transactions to categorise spending&lt;/li&gt;
&lt;li&gt;Category reports on arbitrary time periods&lt;/li&gt;
&lt;li&gt;Ability to see the expected balance on each account at any historic point in
  time from given transactions&lt;/li&gt;
&lt;li&gt;Ability to do a corrective transaction - hmm, I don't know what happened, but
  right now I have X€ in cash&lt;/li&gt;
&lt;li&gt;Adding past transactions before a corrective transaction should not change
  balance &lt;em&gt;after&lt;/em&gt; correction&lt;/li&gt;
&lt;li&gt;Ability to automatically import transactions from my bank&lt;/li&gt;
&lt;li&gt;Ability to plan future, recurring transactions&lt;/li&gt;
&lt;li&gt;Incoming transactions from bank import should be auto-matched with planned
  recuring transactions&lt;/li&gt;
&lt;li&gt;Ability to see missed planned recurring transactions&lt;/li&gt;
&lt;li&gt;Ability to see value deviations in planned recuring transactions&lt;/li&gt;
&lt;li&gt;Ability to manually match a transaction with a planned recurring transaction
  for that month or skip a month&lt;/li&gt;
&lt;li&gt;Ability to see a &lt;em&gt;projected&lt;/em&gt; balance on my accounts at any future date given
  planned transactions&lt;/li&gt;
&lt;li&gt;Credit card fully refilling its current (negative) balance to zero (from a
  given account) should be a plannable transaction&lt;/li&gt;
&lt;li&gt;Accessible from multiple devices, like Linux, Android, iPhone, MacOS. Most
  likely that means web-based&lt;/li&gt;
&lt;li&gt;Achiving accounts without loosing their past transactions with active accounts&lt;/li&gt;
&lt;li&gt;API to access data, so that I could wire that up to a Home Assistant dashboard&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I don't care about currencies (thanks Euro!), localization, taxes and
double-entry bookkeeping. I don't have much use for tags, budgets or savings
targets.&lt;/p&gt;
&lt;p&gt;It could be useful to be able to track stock investment values (but I do have a
pretty good from the bank that does that anyway). And tracking loans (incoming
and outgoing) could be a worthwhile thing as well, but that can also be
simulated with separate accounts for each loan. Tracking refundable expenses
(like medical expenses that insurances should refund later on) would also be
nice. Could also be simulated by having a separate expense category (Medical -
refundable) and putting the refund as a negative expense into that category.&lt;/p&gt;
&lt;p&gt;One weird feature that I really like is having transfer transactions that have
arbitrary incoming and outgoing dates. For some transactions it is a simple
transfer delay - money leaves the account A on Friday and only appears in the
destination account B on Monday morning. However, this can also happen the other
way around - a few credit cards I have seen work in a way that on 14th of each
month the balance of the credit card gets reset to zero and then a week later
the negative balance that was on that credit card gets taken from the base
account that the card is bound to. So the money leaves the base account a week
&lt;em&gt;later&lt;/em&gt; than it arrives in the credit card account. Financial systems really are
magic sometimes :D&lt;/p&gt;
&lt;p&gt;Ideally that should be represented by a single transaction with two dates - one
date when money leaves one account and another date when it arrives in a
different account, so that balances on both accounts in the days between would
be correct (as in matching what the bank says they were on those dates). &lt;em&gt;And&lt;/em&gt;
it should automatch such transaction from bank data imports. And predict its
value from the negative balance of the credit card. And a pony! But in worst
case this could be simulated using a separate "In transfer" account.&lt;/p&gt;
&lt;p&gt;When I am thinking about my finances, the &lt;em&gt;key&lt;/em&gt; metric for me is - how much will
I spend this month - both in fixed spending (rent, Internet and phone bills,
health insurance, subscriptions, ...) and in variable spending (groceries,
eating out, clothing, ...). In theory that &lt;em&gt;should&lt;/em&gt; be trivial, but in practice
a simple calendar month view will fail because a bunch of fixed expenses occur
at the month end/start boundary and can happen &lt;em&gt;either&lt;/em&gt; at the end of previous
month or at start on next month, depending on how the weekends happen to fall
and how the systems of various providers decided to do direct debits this month.
So 1st of month is not a good snapshoting time. Any date between 6th (last
possible days for monthly bills) and 20th (earliest possible salary day) would
be a better cut off point. Looking at the balance of my main account at that
time point lets me know what was the difference between income and expenses for
the past month. And that is the number I want the financial app to be able to
predict as soon as possible.&lt;/p&gt;
&lt;p&gt;And additional complication is the way credit cards work here. The expenses
booked to a credit card after 14th of September will only appear in the main
account on 20th of October and thus will actually only count towards the
expenses of month of October. That makes it very confusing to see a larger
overspend in the main account on 6th of October and then use the categories to
try to figure out where the money went, because all the spending that happened
on the credit card after the 14th of September should not really be looked at in
that context, but spending on the main account or cash account &lt;em&gt;should&lt;/em&gt; be
counted all the way to 6th of October. :D&lt;/p&gt;
&lt;p&gt;I am not optimistic that &lt;em&gt;any&lt;/em&gt; finance software would able to doea with this
mess correctly.&lt;/p&gt;
&lt;p&gt;So far I am tending to consider
&lt;a href="https://docs.firefly-iii.org/firefly-iii/"&gt;Firefly III&lt;/a&gt; which has &lt;em&gt;most&lt;/em&gt; of
what I need and looks great and well maintained, but has the tiny drawback of
being written in PHP, so that basically excludes me from ability to contribute
anything beyond ideas and feedback. :D&lt;/p&gt;
&lt;p&gt;I already did a quick test of Firefly via local Docker containers, so the next
step would be to try to set it up as a production instance (using the same
always-on mini PC that is running my Home Assistant instance), get the database
up and working, get the Firefly III itself up and running, get account importer
working for bank connection, import historical transactions from there, setup my
categories and recurring transactions, import past data dumped out of MoneyWiz
and see if this works well and gives me the insights I need.&lt;/p&gt;
&lt;p&gt;If you know a better solution, please let me know on any social or email
channel!&lt;/p&gt;</description><category>blog</category><category>Debian-planet</category><category>finances</category><category>Ubuntu.lv-planet</category><guid>http://aigarius.com/blog/2023/10/09/finance-project-start/</guid><pubDate>Mon, 09 Oct 2023 17:00:00 GMT</pubDate></item></channel></rss>