- Wrote automated API and UI regression tests for QAD's main ERP product using Python, Selenium and JMeter.
- Found and reported bugs and worked with the devs in an agile team to check the fixes.
About
I'm Ilias, a final year Computer Systems student at the University of Limerick. I like building things that actually get used. Right now that's a flight bag app for pilots and the servers I host it on at home. For my FYP I'm building an LLM agent that finds and fixes faults on those same servers.
Before this I spent eight months at QAD automating regression tests, and a summer in UL's UPSTaRT programme building a data pipeline for cancer research. I also do electronics for UL's Formula Student car.
Contents
- DiamondEFB
- Homelab
- Final year project
- Other work
- Student dating platform
- Formula Student UL
- Experience and education
1. DiamondEFB
| Type | Electronic Flight Bag (SaaS) |
|---|---|
| Status | Active development |
| Started | May 2026 |
| Platforms | Web, Android |
| Frontend | React 19, Vite, MapLibre GL |
| Mobile | Expo / React Native |
| Backend | Fastify, better-auth, Stripe |
| Data | PostgreSQL 17, Drizzle ORM |
| Hosting | Docker on my homelab, via Cloudflare Tunnel |
| Size | ~800 commits, ~98k lines of TypeScript |
| Site | diamondefb.com |
DiamondEFB is an electronic flight bag for GA pilots. Map, flight planning, weather and NOTAMs all in one app. ForeFlight does this really well in the US but in Europe there isn't much and what there is costs a lot. I want to get close to what the big EFBs offer using free or cheap data. Ireland first, then the UK, then the rest of Europe.
I build all of it myself. Web app, Android app, API, data ingest, billing and the servers it runs on.
What it does
- Moving map with airspace, airports, navaids, METARs, NOTAMs, SIGMETs, rain radar and your own waypoints.
- Flight planning from an ICAO route string. If a token could mean more than one thing (like a navaid and a waypoint with the same name) it asks you instead of guessing. You get a vertical profile, leg table, fuel and performance, plus a PDF brief package you can print.
- METAR, TAF and SIGMET for every airfield. NOTAMs come from the FAA NOTAM system and refresh every hour.
- Approach charts for Ireland, pulled from the AirNav eAIP each AIRAC cycle.
- Logbook and an aircraft list by tail number.
- Works offline on Android. You download a flight before you go and it grabs the map tiles along your route.
How it fits together
+--------------+
| web (react) |--+
+--------------+ | +-----------------+ +--------------+
+---- https ----->| api (fastify) |----->| postgres 17 |
+--------------+ | | auth + billing | | drizzle orm |
| android |--+ +-----------------+ +--------------+
| (expo) | ^
+--------------+ | loads it on startup + every hour
|
+-----------------+
| .cache/ |
| gzipped geojson |
+-----------------+
^
| writes every hour
|
+-----------------+
| ingest worker |<---- FAA NOTAMs, SIGMETs
+-----------------+The ingest worker and the API don't talk to each other. The worker writes to a cache on disk and the API reads it into memory. If the FAA is slow or down, nobody using the app notices.
Some things I had to figure out
Billing was harder than expected. Subscriptions are only sold on the website through Stripe. The Android app can unlock a subscription you bought on the web, but Google Play only allows that if the app has no price, no buy button and no link to one anywhere. So the app just says a feature needs a Fly subscription and that's it. Access is checked on the backend, not in the app, and there's an offline grace period so you don't lose features mid-flight because you have no signal.
Moving a waypoint in flight was another one. Dragging things on a native map is awkward because converting between screen and map coordinates is async. What I ended up doing is converting the waypoint and its neighbours once, moving the handle in plain JS while you drag, and converting back once when you let go. The change is saved so it survives the app getting killed, and it never touches your saved plan.
Back in July I did a performance audit and found ten things I'd shipped that were wasteful. Since then every feature has to pass a checklist before I call it done. Things like no huge payloads, reuse caches, parse big JSON off the main thread and don't run timers when a screen isn't visible.
I test it on real flights and anything that goes wrong goes straight into the task list.
2. Homelab
| Started | August 2026 |
|---|---|
| Hosts | Ubuntu Docker host, TrueNAS SCALE |
| Services | ~10 Dockerised |
| Deploys | Komodo, GitOps from Forgejo |
| Ingress | Cloudflare Tunnel, Nginx Proxy Manager, split-horizon DNS |
| Auth | Authentik (OIDC), group-based access |
| Monitoring | Prometheus, Alertmanager, Grafana, Blackbox |
| Backups | Nightly to Backblaze B2 |
I wanted to get off Google Drive and Google Photos so I started self hosting. It began as an old 2 core box with 8GB of RAM and it's slowly turning into a small rack. DiamondEFB runs on it too now.
I try to run it properly. Everything is in git, one login for all services, nothing exposed that doesn't need to be, backups I actually check and alerts when something breaks.
Layout
internet
|
v
+-------------------------+
| cloudflare dns + tunnel | no ports open on the router
+-------------------------+
|
v
+----------------------------+ +-------------------------------+
| homeserver (ubuntu) | lan | truenas scale (6700k, 32gb) |
| |---------->| |
| cloudflared | | immich, nextcloud, firefly |
| authentik (sso) | | ssd pool - dbs, configs |
| nginx proxy manager | | hdd pool - zfs, bulk data |
| komodo <-- forgejo hook | | pg_dump every night |
| prometheus + grafana | +-------------------------------+
| pi-hole, dashy, etc. | |
+----------------------------+ v
backblaze b2 (offsite)How it's set up
Every stack is a compose.yaml in a Forgejo repo. When I push, a webhook tells Komodo and it redeploys the stack. Secrets stay in Komodo and only .env.example files go in git.
Nothing is port forwarded. Public services go out through a Cloudflare Tunnel. At home, split-horizon DNS points the same domains at local IPs so the traffic never leaves the house.
Authentik handles login for everything over OIDC, and access is decided by group.
Photos and files live on a redundant ZFS pool of HDDs. Databases and app config live on SSD. Every night a script dumps the Postgres databases (kept for 14 days) and everything gets synced to Backblaze B2. The dump script also writes a metric, so if the backup stops running I get an alert instead of finding out when I need it.
Monitoring
Prometheus scrapes every host every 30 seconds. Blackbox checks the public sites through Cloudflare. Grafana is the only thing that's public and it's behind Authentik. Alerts come to my email, and I test the alert rules with promtool before deploying them.
| Alert | Fires when |
|---|---|
TargetDown | a host or exporter stops responding |
PublicUrlDown | a public site is down, checked through Cloudflare the same way a user gets to it |
TlsCertExpiring | a cert is about to expire |
DiskAlmostFull / MemoryLow | running out of disk or RAM |
ZfsPoolNotOnline | a pool is degraded or offline |
PgBackupStale | last night's database dump didn't happen |
Watchdog | always firing. If it stops pinging Healthchecks.io, the monitoring itself is dead |
What's next
- Two Proxmox nodes, and moving monitoring onto its own VM.
- 2.5GbE switch for the rack plus a second SSD to mirror the NAS app pool.
- It's also the test bed for my final year project.
3. Final year project
| Degree | BSc Computer Systems, UL |
|---|---|
| Supervisor | Dr. Jacek Dabrowski |
| Timeline | Sep 2026 – May 2027 |
| Status | Early stage |
An LLM agent for fault diagnosis and human-gated remediation on self-hosted servers.
When something breaks on a self-hosted server you usually find out late and then spend ages going through logs. I want to build an agent that does that part for you. It looks into the problem, writes up what went wrong with the evidence, and suggests a fix. The fix only runs if you say yes.
How it should work
logs, metrics, container state, config changes
|
v
+----------------------+
| rule-based detector | something looks off
+----------------------+
|
v
+----------------------+
| llm agent | digs around with read-only tools
+----------------------+
|
v
+----------------------+
| incident report | root cause + evidence + a fix
+----------------------+
|
v
human approves?
| |
yes no
| |
v v
apply fix nothing happensWhile it's investigating the agent can only read, it can't change anything. Anything it says in the report has to point to the log line or metric it got it from. Fixes have to be reversible.
How I'll test it
I'm putting together a list of faults to break my servers with on purpose, each one labelled with the real cause and fix. Then I run the agent and a normal chatbot against them and compare. Did it find the right cause, did it suggest the right fix, and does the evidence it quotes actually back that up.
Progress log
Newest first. I update this as I go.
- Project confirmeddone
Got the project agreed with Dr. Jacek Dabrowski.
I'm using my own homelab as the test bed, so the agent will be working on real Docker hosts and not a toy setup.
- Literature review and fault listplanned
Read up on what's already out there for LLM incident diagnosis and AIOps.
Start the list of faults to inject. Crashed containers, full disks, bad config pushes, expired certs, running out of DB connections.
4. Other work
4.1 Student dating platform
April 2026 · team of four · SvelteKit, PostgreSQL, Drizzle, Tailwind, Docker
A dating site for students that we built as a team of four. It has matching, messaging, events and admin moderation. I did the matching algorithm. It ranks people by shared interests and how well you fit each other's preferences, and if you're new and haven't added interests yet it falls back to matching by university.
I also put it in Docker with persistent storage for uploads, wrote the build and push scripts to Docker Hub, and got it live on HTTPS.
4.2 Formula Student UL
October 2025 – present · Electronics & Systems Engineer
I'm on the electronics side of UL's Formula Student team. Right now I'm designing the schematics for a paddle shift system controlled in software, and building a Raspberry Pi dash that shows live data from the car's DTA S60 Pro ECU.
5. Experience and education
Experience
- Got picked for UL's first year research programme with the Faculty of Science and Engineering.
- Built a Python pipeline that scraped cancer research from PubMed into a knowledge graph for an AI diagnosis model.
Education
QCA 3.52 / 4.0 to date (First Class Honours).
Also
- Google Ireland Algorithms Workshop in Dublin, October 2025. One of forty people picked to go.
Skills
| Languages | TypeScript, JavaScript, Python, Java, C, C++, SQL, HTML/CSS |
| Web | React, Next.js, SvelteKit, Fastify, Vite, Drizzle ORM |
| Mobile | Expo, React Native |
| Infrastructure | Linux, Docker, Compose, GitOps, TrueNAS / ZFS, Cloudflare, Prometheus, Grafana |
| Data | PostgreSQL |
| Testing | Selenium, JMeter |