• Home
  • Posts
  • Tags
  • About
    EN ES
    • Home
    • Posts
    • Tags
    • About

      My homelab path.

      The story on how did I land to my current homelab setup.

      16 October 2026 14 min read Available in: Spanish
      Homelab Proxmox Incus Ansible Story

      Among my many hobbies, maintaining my homelab is one that brings me the most satisfaction. A homelab or home server is a computer that, instead of serving as a workstation, is used to provide services locally. The most common use case is NAS (Network Attached Storage), but with a bit of creativity and the right software, it’s entirely possible to set up personal finance tools, media servers, or multiplayer game servers.

      In this post, I share the story of the homelab I’ve built over the past 2 years.

      The beginning and the tipping point #

      I already had most of my tech needs covered two years ago: I either solved them locally on my workstation, or I relied on free services. I also had access to infrastructure that a friend lent me for small projects, so setting up a homelab didn’t make much sense for me at the time.

      However, over time I realized that the effort of maintaining my own infrastructure became a better option than tolerating the enshittification of the services I depended on. Seeing my colleagues’ experiences with their homelabs also sparked my curiosity about the topic. The moment I decided to take the reins was when I finished upgrading my personal PC and ended up with extra hardware that I could put to good use for a proof of concept.

      I dedicated some time to researching the state of the art. Fortunately, the spaces I explored were full of people willing to share their experiences and setups. I watched videos on different ways to build the infrastructure, checked out various repositories, and studied the modern tools used for this purpose, both commercial and open source.

      My first setup #

      I acquired most of the components for this computer back in 2013. Since I knew this would be a temporary setup, I only invested in persistent storage, which I could recycle if I ever built a permanent one.

      For this proof of concept, I decided to use Proxmox as the operating system. It was one of the most recommended options for managing containers and virtual machines, it had a nice web interface, and had plenty of online guides available in case I wanted to customize anything. I also wanted to get familiar with LXC as a system containerization technology.

      I decided to work with containers using Fedora images as a base and provision the open-source applications I’d use directly into them. One downside of this approach is that many applications distributed for local hosting come packaged as Docker images meant to be used with Docker Compose. In those cases, it would require the extra work of adapting or repackaging them to install them directly inside the container. At worst, I could always nest containers, but that was something I wanted to avoid.

      Instead of manually installing the applications into the containers, I chose to use Ansible as my provisioning tool, since I was already familiar with it from my day job. This decision might seem overkill for the project’s initial scale, but shifting the mindset from “maintaining infrastructure” to “building a system” is something that feels much more natural to me as a developer. Plus, it keeps a record of the system’s composition, which is handy for someone who tends to forget things and doesn’t have the patience to document everything manually. I also evaluated other provisioning tools (Kubernetes, OpenTofu, things like that), but they didn’t make sense given that my project wouldn’t scale beyond local use.

      My initial plan was to migrate the Discord bot and the games I was hosting with my friend, and then build upon that foundation.

      ¶ Note: Homelab’s first steps
          flowchart LR
          subgraph Proxmox["Proxmox VE Host"]
              subgraph LXC0["LXC Container: dns"]
                 Cockpit0["Cockpit Web UI"]
                 DNS["<b>DNS</b><br/>BIND9<br/>port 53"]
             end
             subgraph LXC1["LXC Container: maruchan"]
                 Cockpit1["Cockpit Web UI"]
                 Maru["<b>Maruchan Bot</b><br/>Podman container"]
             end
             subgraph LXC2["LXC Container: ai"]
                 Cockpit2["Cockpit Web UI"]
                 AI["<b>AI Service</b><br/>ramalama serve<br/>port 8080"]
             end
         end
      
         Discord["<b>Discord Bot</b><br/>External"]
         LAN["<b>Local LAN</b>"]
      
         Discord <--> Maru
         LAN <--> DNS
         LAN <--> AI
         AI --> Maru
         DNS -->|"DNS resolution"| LAN
         DNS -->|"DNS resolution"| LXC1
         DNS -->|"DNS resolution"| LXC2
        

      Homelab first steps - 2024-11-28.

      With this foundation, the architecture was simple, but I already had a clear idea of how to organize things to ensure scalability. As a starting point, I decided to maintain two repositories: one for roles and playbooks, and another for the inventory. The main playbook organizes three tasks:

      • Provision basic services on the server:
      • Proxmox
      • Cockpit
      • Certificates
      • Shared storage
      • Spin up containers:
        • LXC containers with Fedora images
        • Configure IPs and base applications (SSH, Cockpit, firewall, etc.)
      • Provision the containers:
        • Setup roles

      Proof of concept #

      Since this was still a personal project at this stage, I didn’t want to be too ambitious about what I added to the server. Three months later, the applications I ended up adding were a Forgejo instance and some games to run locally.

      ¶ Note: Proof of concept
          flowchart LR
          subgraph Proxmox["Proxmox VE Host"]
              subgraph LXC0["LXC Container: dns"]
                 DNS["<b>DNS</b><br/>BIND9<br/>port 53"]
              end
              subgraph LXC1["LXC Container: traefik"]
                 Traefik["<b>Traefik</b><br/>Reverse Proxy<br/>ports 80, 443<br/>Let's Encrypt / Cloudflare DNS-Challenge"]
              end
              subgraph LXC2["LXC Container: forgejo"]
                 Forgejo["<b>Forgejo</b><br/>Git Server<br/>port 3000 / 22"]
              end
              subgraph LXC3["LXC Container: semaphore"]
                 Semaphore["<b>Semaphore</b><br/>Ansible CI/CD"]
              end
              subgraph LXC4["LXC Container: ai"]
                 AI["<b>AI Service</b><br/>ramalama serve<br/>port 8080<br/>llama3.2:3b"]
              end
              subgraph LXC5["LXC Container: maruchan"]
                 Maru["<b>Maruchan Bot</b><br/>Discord Bot<br/>Podman container"]
              end
              subgraph LXC6["LXC Container: luanti"]
                 Luanti["<b>Luanti</b><br/>Minetest Server<br/>port 30000"]
              end
              subgraph LXC7["LXC Container: veloren"]
                 Veloren["<b>Veloren</b><br/>Game Server<br/>ports 14004, 14005, 14006/udp"]
              end
              subgraph LXC8["LXC Container: starbound"]
                 Starbound["<b>Starbound</b><br/>Game Server<br/>port 21025<br/>RCON port 21026<br/>SteamCMD"]
              end
          end
      
          Discord["<b>Discord Bot</b><br/>External"]
          LAN["<b>Local LAN</b>"]
      
          Discord <--> Maru
          LAN <--> Traefik
          LAN <--> Luanti
          LAN <--> Veloren
          LAN <--> Starbound
          LAN --> DNS
          DNS -->|"DNS resolution"| LXC1
          DNS -->|"DNS resolution"| LXC2
          DNS -->|"DNS resolution"| LXC3
          DNS -->|"DNS resolution"| LXC4
          Traefik -->|"HTTPS routing"| Forgejo
          Traefik -->|"HTTPS routing"| Semaphore
          AI -->|"http://localhost:8080"| Maru
          Maru -->|"RCON port 21026"| Starbound
        

      Final state of the POC - 2025-01-27.

      One improvement I made was structuring the LXC container generation process so that the system creates them directly from the inventory. For each container, I created variable files in inventory/hosts_vars/, where I defined the base configuration, DNS records, IPs, external storage space, and resource limits according to their intended roles. Then, in inventory/main.yml, I defined which hosts corresponded to containers and which roles would be assigned to each one. I wanted to replicate the experience of using a docker-compose.yml file, but adapted to the type of infrastructure I was building.

      ◇ Example: Container definition - Voxelibre

      inventory/hosts_vars/voxelibre.yml

      yml
      ansible_host: <IP>
      hostname: voxelibre
      
      # Container
      proxmox_container:
        vmid: 1013
        disk: 'local-lvm:8'
        netif:
          - "ip=<IP 2>/24,bridge=vmbr2"
        cores: 2
        memory: 4096
        unprivileged: True
      
      # External storage
      storage_mnt:
        - path: /voxelibre
          target: /var/lib/minetest/voxelibre
          uid: 996
          gid: 996
          size: 20G
      
      # Luanti Mode
      luanti_config:
        game:
          name: mineclone2
          url: https://content.luanti.org/uploads/bf06e78d80.zip
          user_password: p0t4t0p0t4t0
          mods:
          - name: mapserver
            url: https://content.luanti.org/uploads/8593934e95.zip
          - name: whitelist
            url: https://content.luanti.org/uploads/3856ecc059.zip
          - name: xban2
            url: https://content.luanti.org/uploads/14be84e5ee.zip
          - name: illumination
            url: https://content.luanti.org/uploads/65d28de215.zip
            # whitelist deps
          - name: lib_chatcmdbuilder
            url: https://content.luanti.org/uploads/e34ab089d8.zip
      
        world:
          id: "{{ hostname }}"
          name: Grillo's Server - VoxeLibre
          description: Personal server :)
          host: "{{ hostname }}.{{ domain_name }}"
          url: https://{{ hostname }}.{{ domain_name }}
          admin_name: grillo
          announce: false
          port: 30000
          settings:
          - enable_minimap = true
          - mapserver.enable_crafting = true
          - mapserver.send_interval = 10
          - secure.http_mods = mapserver
          - mapserver.url = http://127.0.0.1:8080
          - enable_rollback_recording = true
      
        mapserver:
          port: 8080
      
      # DNS settings
      dns_list:
        - "{{ hostname }}.luanti           IN      A       <IP>"
      
      # Traefik Config
      traefik_config:
        http:
          routers:
            to-voxelibre:
              rule: Host(`{{ hostname }}.{{ domain_name }}`)
              service: voxelibre
          services:
            voxelibre:
              loadBalancer:
                servers:
                - url: http://<IP 2>:8080

      inventory/main.yml

      Code
      containers:
        hosts:
          voxelibre:
      
      role_luanti:
        hosts:
          voxelibre:

      On the infrastructure side, I added two more tools: Traefik and SemaphoreUI.

      SemaphoreUI is an application for orchestrating automated processes with a comfortable web interface. For my use case, it worked well as a frontend to automate and execute the server playbooks. To enable it, I just needed to provide an SSH key for the host and access to the repositories already hosted on the Forgejo instance.

      Traefik, on the other hand, is an HTTP proxy; I mainly used it to expose web services through a single entry point, and that way, avoiding the need to generate certificates and DNS records for each container separately.

      As I mentioned before, many of these applications are distributed as pre-generated images and often don’t provide instructions on how to use them directly outside of a container. However, it’s possible to deduce the process by looking at the container files and the CI artifacts. By studying these, I decided to generate my own RPM packages. I started with SemaphoreUI and Traefik, but if you explore the organization where I maintain the packages, you’ll notice I didn’t stop there.

      The test result #

      A few months later, due to a computer failure in the house, we had to free up the hardware I was using for the homelab. By that point, I already considered the proof of concept a success and was planning to buy a permanent rig.

      Defining clear expectations about what I wanted to achieve was something I didn’t want to underestimate, as at this point I saw the potential for it to become something bigger than a personal project. I still wanted to avoid it turning into critical infrastructure, so I would leave out things like password managers or Home Assistant. I also didn’t want to expose public services, so mail servers, websites, or Mastodon instances were off the table (unless they were local experiments). With clear objectives, I looked for a small, energy-efficient machine, but with enough resources to run what I wanted.

      A major change I made was migrating the host from Proxmox to Fedora Server. My main reason for leaving Proxmox was its dependency on Debian as a base. This might sound counterintuitive, as it’s generally easier to manage a system on distros with long update cycles like CentOS or Debian, precisely because they avoid incorporating software versions that change how one interacts with the system. From that perspective, Fedora’s update cycle might sound like a disadvantage, but in my case, I like to explore the latest application versions and contributing when possible, so using Fedora helps me get involved in projects without sacrificing too much stability. Another factor that enabled the migration was that the Incus project was already gaining traction and looked like a viable alternative for managing system containers on Fedora.

      ¶ Note: Home grown Home lab
          flowchart LR
          subgraph Fedora["Fedora Host (Incus)"]
              subgraph LXC_DNS["LXD Container: dns"]
                 DNS["<b>DNS</b><br/>BIND9<br/>port 53"]
              end
              subgraph LXC_TRAEFIK["LXD Container: traefik"]
                 Traefik["<b>Traefik</b><br/>Reverse Proxy<br/>ports 80, 443<br/>Let's Encrypt / CF DNS-Challenge"]
              end
              subgraph LXC_AUTHELIA["LXD Container: authelia"]
                 Authelia["<b>Authelia</b><br/>Auth Server<br/>port 9091<br/>OIDC Provider<br/>Access Control"]
              end
              subgraph LXC_WGPORTAL["LXD Container: wgportal"]
                 WGPortal["<b>WireGuard Portal</b><br/>VPN Management<br/>web: 8080<br/>VPN: 51820<br/>SQLite"]
              end
              subgraph LXC_FORGEJO["LXD Container: forgejo"]
                 Forgejo["<b>Forgejo</b><br/>Git Server<br/>port 3000 / 22<br/>SQLite"]
              end
              subgraph LXC_SEMAPHORE["LXD Container: semaphore"]
                 Semaphore["<b>Semaphore</b><br/>Ansible CI/CD"]
              end
              subgraph LXC_JUPYTER["LXD Container: jupyter"]
                 Jupyter["<b>JupyterLab</b><br/>port 8888"]
              end
              subgraph LXC_TRILIUM["LXD Container: trilium"]
                 Trilium["<b>Trilium Notes</b><br/>Knowledge Base<br/>multi-instance"]
              end
              subgraph LXC_COMFYUI["LXD Container: comfyui"]
                 ComfyUI["<b>ComfyUI</b><br/>AI Image Gen<br/>ROCM (PyTorch)"]
              end
              subgraph LXC_OPENWEBUI["LXD Container: openwebui"]
                 OpenWebUI["<b>Open WebUI</b><br/>Chat Interface<br/>port 8080"]
              end
              subgraph LXC_RAMALAMA["LXD Container: ai"]
                 Ramalama["<b>Ramalama</b><br/>AI Model Serving<br/>port 8080<br/>llama3.2:3b"]
              end
              subgraph LXC_MARUCHAN["LXD Container: maruchan"]
                 Maru["<b>Maruchan Bot</b><br/>Discord Bot<br/>Podman"]
              end
              subgraph LXC_LUANTI["LXD Container: luanti"]
                 Luanti["<b>Luanti</b><br/>Minetest Server<br/>port 30000"]
              end
              subgraph LXC_VELOREN["LXD Container: veloren"]
                 Veloren["<b>Veloren</b><br/>Game Server<br/>14004, 14005, 14006/udp"]
              end
              subgraph LXC_STARBOUND["LXD Container: starbound"]
                 Starbound["<b>Starbound</b><br/>Game Server<br/>21025 / 21026<br/>SteamCMD"]
              end
              subgraph LXC_MANGBAND["LXD Container: mangband"]
                 Mangband["<b>Mangband</b><br/>MUD Game<br/>port 18346"]
              end
          end
      
          Discord["<b>Discord Bot</b><br/>External"]
          LAN["<b>Local LAN</b>"]
          VPN["<b>WireGuard VPN</b>"]
      
          Discord <--> Maru
          LAN <--> Traefik
          LAN <--> DNS
          LAN <--> Forgejo
          VPN <--> WGPortal
      
          Traefik -->|"HTTPS + Authelia"| Authelia
          Traefik -->|"routes / api"| Forgejo
          Traefik -->|"routes / web"| Semaphore
          Traefik -->|"routes"| Jupyter
          Traefik -->|"routes"| Trilium
      
          DNS -->|"DNS resolution"| LXC_TRAEFIK
          DNS -->|"DNS resolution"| LXC_AUTHELIA
          DNS -->|"DNS resolution"| LXC_FORGEJO
          DNS -->|"DNS resolution"| LXC_SEMAPHORE
          DNS -->|"DNS resolution"| LXC_RAMALAMA
          DNS -->|"DNS resolution"| LXC_OPENWEBUI
          DNS -->|"DNS resolution"| LXC_MARUCHAN
          DNS -->|"DNS resolution"| LXC_LUANTI
          DNS -->|"DNS resolution"| LXC_VELOREN
          DNS -->|"DNS resolution"| LXC_STARBOUND
          DNS -->|"DNS resolution"| LXC_MANGBAND
      
          OpenWebUI -->|"API calls"| Ramalama
          Maru -->|"AI inference"| Ramalama
          LAN <--> OpenWebUI
          LAN <--> ComfyUI
          LAN <--> Luanti
          LAN <--> Veloren
          LAN <--> Starbound
          LAN <--> Mangband
        

      A couple of months later - 2025-11-05

      The decision to use Ansible made the migration much easier. I updated the playbooks to use Incus instead of LXC, and everything worked without issues. Regarding roles and containers, apart from a couple of minor issues with permissions and how resource limits were defined, the transition was fairly clean. Yes, it was a big change and there are still things to migrate, but it was enough to get the services back up.

      For applications, this time I involved my partner to look for use cases. Among the services she relied on, Notion looked like a good target to find a local alternative. After trying AppFlowy, Anytype, Obsidian, and others, we ended up on Trilium. It’s not a panacea, but it can be hosted locally and synced with its multiplatform desktop app. It helps a lot that they are open to accept improvements.

      On the infrastructure side, I added a VPN with WGPortal and authentication for services using Authelia. Since I still planned to add more users to the system in the future, I added a mechanism to set firewall rules per container, ensuring they wouldn’t expose more than necessary or see network segments they shouldn’t have access to.

      Drawing the rest of the owl #

      We are approaching the second anniversary of the server soon, and I feel it has grown quite a bit. Despite that, there haven’t been any major structural or infrastructure changes since then. Many of the applications are used daily, while others remain proof of concept.

      If I have focused my efforts, it has been on improving security and simplifying account provisioning. Since I added access for some friends and family, I decided to move the user registry to an LDAP instance (lldap). The rest has been just testing different applications to see what sticks.

      ¶ Note: Current state
          flowchart LR
          subgraph Fedora["Fedora Host (Incus)"]
              subgraph LXC_DNS["LXD Container: dns"]
                 DNS["<b>DNS</b><br/>BIND9<br/>port 53"]
              end
              subgraph LXC_TRAEFIK["LXD Container: traefik"]
                 Traefik["<b>Traefik</b><br/>Reverse Proxy<br/>ports 80, 443<br/>Let's Encrypt / CF DNS-Challenge"]
              end
              subgraph LXC_AUTHELIA["LXD Container: authelia"]
                 Authelia["<b>Authelia</b><br/>Auth / OIDC<br/>port 9091"]
              end
              subgraph LXC_LLDAP["LXD Container: lldap"]
                 LLDAP["<b>LLDAP</b><br/>LDAP Server<br/>PostgreSQL :5432"]
              end
              subgraph LXC_WGPORTAL["LXD Container: wgportal"]
                 WGPortal["<b>WireGuard Portal</b><br/>VPN Mgmt<br/>web: 8080, VPN: 51820"]
              end
              subgraph LXC_SEMAPHORE["LXD Container: semaphore"]
                 Semaphore["<b>Semaphore</b><br/>Ansible CI/CD"]
              end
              subgraph LXC_MAILPIT["LXD Container: mailpit"]
                 Mailpit["<b>Mailpit</b><br/>Mail Testing"]
              end
              subgraph LXC_FORGEJO["LXD Container: forgejo"]
                 Forgejo["<b>Forgejo</b><br/>Git Server<br/>port 3000 / 22<br/>SQLite"]
              end
              subgraph LXC_FORGEJO_RUNNER["LXD Container: forgejo_runner"]
                 ForgejoRunner["<b>Forgejo Runner</b><br/>CI/CD Runner<br/>Podman backend"]
              end
              subgraph LXC_GIT_PAGES["LXD Container: git_pages"]
                 GitPages["<b>Git Pages</b><br/>Static Hosting"]
              end
              subgraph LXC_TRILIUM["LXD Container: trilium"]
                 Trilium["<b>Trilium Notes</b><br/>Knowledge Base<br/>multi-instance"]
              end
              subgraph LXC_JELLYFIN["LXD Container: jellyfin"]
                 Jellyfin["<b>Jellyfin</b><br/>Media Server"]
              end
              subgraph LXC_ACTUAL["LXD Container: actualbudget"]
                 ActualBudget["<b>Actual Budget</b><br/>Budgeting App"]
              end
              subgraph LXC_FILEBROWSER["LXD Container: filebrowser"]
                 FileBrowser["<b>File Browser</b><br/>Web File Mgmt<br/>media: /opt/media"]
              end
              subgraph LXC_ROMM["LXD Container: romm"]
                 ROMM["<b>ROMM</b><br/>ROM Manager<br/>PostgreSQL :5432<br/>Valkey, Coturn"]
              end
              subgraph LXC_RAMALAMA["LXD Container: ai"]
                 Ramalama["<b>Ramalama</b><br/>AI Model Serving<br/>port 8080<br/>llama3.2:3b"]
              end
              subgraph LXC_OPENWEBUI["LXD Container: openwebui"]
                 OpenWebUI["<b>Open WebUI</b><br/>Chat Interface<br/>port 8080"]
              end
              subgraph LXC_PIWEB["LXD Container: piweb"]
                 PiWeb["<b>Pi-Web</b><br/>Agent / Sessiond"]
              end
              subgraph LXC_MARUCHAN["LXD Container: maruchan"]
                 Maru["<b>Maruchan Bot</b><br/>Discord Bot<br/>Podman"]
              end
              subgraph LXC_TUWUNEL["LXD Container: tuwunel"]
                 Tuwunel["<b>Tuwunel</b><br/>Local Matrix Server<br/>port 8008<br/>Nginx"]
              end
              subgraph LXC_LIVEKIT["LXD Container: livekit"]
                 LiveKit["<b>LiveKit</b><br/>WebRTC Video<br/>Valkey, Nginx"]
              end
              subgraph LXC_CINNY["LXD Container: cinny"]
                 Cinny["<b>Cinny</b><br/>Matrix Client<br/>Nginx"]
              end
              subgraph LXC_OWNCast["LXD Container: owncast"]
                 Owncast["<b>Owncast</b><br/>Live Streaming<br/>FFmpeg"]
              end
              subgraph LXC_BFCOMPANION["LXD Container: bitfocus_companion"]
                 BFCompanion["<b>Bitfocus Companion</b><br/>Broadcasting"]
              end
              subgraph LXC_LUANTI["LXD Container: luanti"]
                 Luanti["<b>Luanti</b><br/>Minetest<br/>port 30000"]
              end
              subgraph LXC_MANGBAND["LXD Container: mangband"]
                 Mangband["<b>Mangband</b><br/>MUD RPG<br/>port 18346"]
              end
          end
      
          Discord["<b>Discord</b><br/>External"]
          LAN["<b>Local LAN</b>"]
          VPN["<b>WireGuard</b><br/>VPN"]
      
          Discord <--> Maru
          VPN <--> WGPortal
      
          LAN <-->|osc| BFCompanion
          LAN <-->|ssh:repo| Forgejo
          LAN <-->|matrix| Tuwunel
          LAN <-->|matrix:videocalls| LiveKit
          LAN <-->|ldap| LLDAP
          LAN <--> Luanti
          LAN <--> Mangband
          LAN <--> Traefik
          LAN <--> DNS
      
          DNS -->|"DNS resolution"| LXC_BFCOMPANION
          DNS -->|"DNS resolution"| LXC_FORGEJO
          DNS -->|"DNS resolution"| LXC_TUWUNEL
          DNS -->|"DNS resolution"| LXC_LIVEKIT
          DNS -->|"DNS resolution"| LXC_LLDAP
          DNS -->|"DNS resolution"| LXC_LUANTI
          DNS -->|"DNS resolution"| LXC_MANGBAND
          DNS -->|"DNS resolution"| LXC_TRAEFIK
          DNS -->|"DNS resolution"| LXC_WGPORTAL
      
          Traefik -->|"HTTPS + Authelia"| Authelia
          Traefik -->|"routes"| PiWeb
          Traefik -->|"routes"| Ramalama
          Traefik -->|"routes"| ActualBudget
          Traefik -->|"routes"| Cinny
          Traefik -->|"routes"| BFCompanion
          Traefik -->|"routes"| Forgejo
          Traefik -->|"routes"| Jellyfin
          Traefik -->|"routes"| LLDAP
          Traefik -->|"routes"| Mailpit
          Traefik -->|"routes"| FileBrowser
          Traefik -->|"routes"| Trilium
          Traefik -->|"routes"| Owncast
          Traefik -->|"routes"| GitPages
          Traefik -->|"routes"| Ramalama
          Traefik -->|"routes"| ROMM
          Traefik -->|"routes"| Semaphore
          Traefik -->|"routes"| WGPortal
      
          LLDAP -->|"auth"| Authelia
          ForgejoRunner -->|"API"| Forgejo
          GitPages -->|"API"| Forgejo
          Forgejo -->|"Infra Repo"| Semaphore
          OpenWebUI -->|"AI API"| Ramalama
          PiWeb -->|"AI API"| Ramalama
          Maru -->|"AI inference"| Ramalama
          FileBrowser -->|"/opt/media"| Jellyfin
        

      Current homelab state - 2026-10-15

      To infinity and beyond! #

      The next steps will involve moving some of the services still in the experimental phase to a secondary machine. I also plan to continue looking for mechanisms to handle backups and snapshots; I haven’t found anything that fully convinces me yet, especially because I hope to find something that offers a better experience than rsync and Btrfs’ manual snapshot system. Evaluating other applications like immich or freshrss is also on the list.

      Additionally, I’ll continue maintaining the packages for the applications I use. I believe many of them could be incorporated into Fedora, but I haven’t done the exhaustive study required to determine if it’s viable. For now, the builds are hosted on my COPR account, but if anyone is up for fixing them, I’d be happy to help with the review process.

      I plan to write more entries in this blog in the future to discuss the other applications I’ve tested in more detail, how to install them on Fedora, and take the opportunity to improve the documentation of the roles in the repository, which is currently falling short.

      On this page
      • The beginning and the tipping point
      • My first setup
      • Proof of concept
      • The test result
      • Drawing the rest of the owl
      • To infinity and beyond!

      ↑Return to Top↑

      Comments

      Join the conversation

      Built with Hugo. - circuit-loam

      • RSS feed

      No translation available

      Back to the home page
      Diagram