Tag: homelab

  • The Home Dashboard That Refuses to Become Another Chore

    A simple wall-mounted smart-home dashboard in a colorful interior

    Home dashboards have a habit of becoming museums of available data. CPU graphs, weather tiles, battery percentages and twelve tiny icons compete for attention, while the one useful answer—whether the back door is locked—requires scrolling. A good dashboard is not a control panel for everything. It is a shortcut to the next sensible action.

    Design around moments

    Think about when the screen is used. The morning view might show weather, travel time and the state of important doors. An evening view can prioritize lights, heating and media. A maintenance view may expose server health and low batteries. One permanent wall of widgets rarely serves all three moments well.

    Show exceptions first

    Normal systems do not need attention. Replace a sea of green indicators with a quiet status summary and reveal detail only when something is wrong. A single “everything is okay” message is calmer and more informative than twenty green circles.

    Keep controls forgiving

    Large targets, clear labels and immediate feedback matter more than visual cleverness. Avoid controls whose effect is ambiguous. If a button starts a scene, show what changed. If an action is risky, separate it from everyday controls and require confirmation.

    Respect the household

    A dashboard should make sense to someone who did not build it. Use ordinary language rather than entity IDs and technical abbreviations. Ask other people which tasks they actually want on the screen. Their answer may be “none,” which is also useful design feedback.

    Delete relentlessly

    If a card has not influenced a decision in a month, remove it. The underlying metric can remain available in a diagnostic tool. The shared dashboard should stay focused on information that changes what someone does next.

    The best home dashboard feels less like mission control and more like a good light switch: obvious, dependable and almost invisible.

  • Backups Are Boring Until Restore Day

    Multiple independent data vaults restoring a protected file

    Backup dashboards are excellent at producing green check marks. Unfortunately, a green check mark usually proves only that a job ran. It does not prove that the right files were captured, the archive can be opened or the recovery instructions make sense when the original system is gone.

    Start with consequences

    Classify data by what its loss would mean. Family photos and original work may be irreplaceable. Application containers can often be recreated, but their databases and configuration cannot. Downloaded media may be large yet replaceable. This distinction determines how many copies you need and how quickly each one must return.

    Use independent copies

    A useful baseline is multiple copies on different storage, with at least one outside the home. Independence matters. A second folder on the same machine is not protection from disk failure, malware or accidental deletion. An attached backup drive may disappear in the same electrical event as the server it protects.

    Protect the instructions

    Recovery documentation belongs outside the system being recovered. Record where backups live, how they are encrypted, which credentials are required and the order in which services should return. Include enough detail for a tired future version of yourself who no longer remembers the clever shortcut used two years ago.

    Restore small things often

    Choose a file every month and recover it to a temporary location. Periodically restore an application into an isolated environment and verify that it starts. These tests expose missing volumes, incomplete database dumps and forgotten encryption keys while the original system still exists.

    Measure recovery, not storage

    A tiny configuration file may matter more than a terabyte of replaceable media. Track the time needed to restore important services, not merely the capacity consumed by backups. Recovery time is the number that matters during an incident.

    Backups should be boring. Restore day should be boring too. That only happens when recovery is practiced before it becomes urgent.

  • Self-Hosting After the Honeymoon: What Is Actually Worth Running

    A home server keeping a few essential self-hosted services

    Self-hosting begins with possibility. One service becomes five, a dashboard becomes a second dashboard, and suddenly a quiet Sunday involves reading release notes for software that was supposed to simplify life. The honeymoon phase is fun. The useful phase begins when each service has to justify its maintenance.

    The test: would you miss it?

    A service earns its place when its disappearance causes a real inconvenience. Local DNS, password management, document storage, backups and home automation usually pass this test. A novelty dashboard displaying information already available elsewhere often does not. Stop judging the lab by container count; judge it by problems removed.

    Keep identity boring

    Central authentication is valuable, but it also creates a critical dependency. Use a setup you understand, maintain recovery credentials and document how to regain access when the identity provider is unavailable. Clever login flows are less impressive at midnight when every service redirects to an error page.

    Own the data that matters

    Photos, documents, notes and configuration deserve local control and multiple backups. That does not mean the internet must be banished. Off-site encrypted storage can complement local copies. The point is to avoid having a single company, disk or password become the only route to irreplaceable data.

    Prefer boring software

    Mature projects with clear documentation, predictable upgrades and portable data tend to survive enthusiasm cycles. A beautiful interface is welcome, but an export button is more important. Choose tools that let you leave without reconstructing years of information by hand.

    Delete with confidence

    Retiring a service is not failure. Export its data, archive its configuration and remove it. Fewer moving pieces mean clearer alerts, faster upgrades and more time for the systems that genuinely help.

    A sustainable homelab is not the one with the most logos on its start page. It is the one that still feels worth maintaining after the novelty disappears.

  • The Quiet Homelab: Performance Without the Jet-Engine Soundtrack

    A quiet home server with large cooling fans in a stylish living room

    A homelab can be technically brilliant and still be a terrible housemate. The familiar recipe—retired enterprise hardware, too many tiny fans and a rack placed wherever it fits—often creates a machine room in a place that was supposed to feel like home. The better goal is not silence at any cost. It is useful performance without a permanent jet-engine soundtrack.

    Begin with the work, not the rack

    Before buying quieter fans, list what the lab actually does. A few containers, Home Assistant, DNS, backups and a media server rarely need a dual-socket enterprise machine idling all day. Measure CPU use, memory pressure, storage activity and peak demand for a week. Downsizing an underused host can remove more heat and noise than any acoustic treatment.

    Large fans win

    Small fans have to spin quickly to move air. Larger fans can move the same volume more slowly and with a less irritating sound profile. Use unobstructed airflow, clean filters and sensible fan curves. Avoid forcing air through an unnecessary maze of drive cages and cables. A simple front-to-back path usually works better than a collection of heroic high-speed fans.

    Storage changes the character

    Hard drives produce more than airborne noise. Their vibration travels through shelves, floors and furniture. Rubber isolation helps, but placement matters more. Keep spinning disks away from hollow cabinets and shared walls. SSDs are ideal for active services; larger disks can remain for backups and bulk media where their activity is less constant.

    Temperature is a budget

    Chasing the lowest possible temperature creates noise without necessarily improving reliability. Modern hardware is designed to operate safely across a broad range. Set realistic temperature targets, monitor them and let fans respond gradually. Sudden fan ramps are often more distracting than a steady low hum.

    Design for maintenance

    A quiet system becomes loud again when filters clog or a fan starts failing. Leave enough space to clean it, label airflow direction and log temperatures. Keep one known-good replacement fan on hand. Quietness is not a one-time modification; it is part of operating the lab.

    The nicest homelab is the one you can forget is running. It should make the house smarter, safer and more useful—without constantly announcing its presence.

  • Cloudflare, DDNS and a Changing Home IP: My Actual Setup

    Cloudflare, DDNS and a Changing Home IP: My Actual Setup

    CloudOnFire runs from a residential internet connection with an address that can change. The trick is not pretending that a home connection behaves like a data centre. It is designing the public edge, DNS updates and origin server so that a routine address change becomes boring—and so that publishing the architecture does not publish an attack map.

    Abstract illustration of a home server protected by a cloud edge while network addresses change
    The pattern, deliberately abstracted: home origin, protected edge and an address that can move.

    The architecture in one paragraph

    A small web server lives inside an isolated virtualised environment on the home network. The domain’s authoritative DNS is managed at the cloud edge and public requests are proxied before reaching the origin. A tiny Dynamic DNS updater checks the residential public address and changes one designated DNS record only when necessary.

    That is the complete public description. Internal addresses, container identifiers, usernames, management paths and exact firewall configuration remain private because none of them would make this article more useful.

    Dynamic DNS should have one small job

    The updater needs permission to modify the relevant DNS record—not the entire account. The credential should be scoped to one zone and the minimum required DNS-edit capability. It belongs in protected configuration, never in a script pasted into a post, a screenshot, a shell-history tutorial or a public repository.

    The update interval does not need to be frantic. The client can compare the current public address with the existing DNS value, update only after a genuine change and log success without printing secrets.

    The safest automation is boring, narrowly authorised and almost invisible.

    The proxy is helpful, not magical

    Proxying through Cloudflare keeps normal visitors away from a direct origin connection and provides TLS termination, caching and traffic filtering. It does not automatically secure the machine behind it. If the origin still accepts arbitrary traffic from the entire internet, discovering the residential address can allow someone to bypass many edge protections.

    A stronger design limits web traffic at the origin to trusted proxy networks where practical, keeps the firewall explicit and exposes only what the public site actually needs. The hypervisor, database, SSH and container-management interfaces never belong on the public web.

    TLS all the way to the origin

    The browser-to-edge connection is only half of the journey. The edge-to-origin connection should also use valid TLS with strict certificate validation. “Flexible” encryption may look convenient, but it leaves the final leg unencrypted and can create confusing redirects. Full strict validation is the goal.

    WordPress is part of the security boundary

    The network can be beautifully designed and still be undermined by an abandoned plugin or weak administrator account. Themes and plugins stay updated, unused components are removed or disabled, administrator accounts are kept to a minimum and authentication is protected with MFA or a strong identity provider.

    The database is reachable only from the application environment. Backups are stored separately and restoration is tested rather than assumed. A backup that has never been restored is merely a theory.

    What I deliberately do not publish

    • The current or historical public IP address
    • Internal subnets, hostnames or container IDs
    • Router, hypervisor or operating-system fingerprints
    • Exact port-forwarding and management rules
    • API tokens, client secrets or screenshots containing them
    • The location of administration interfaces
    • Backup destinations and recovery credentials

    The lessons worth sharing

    Use narrowly scoped credentials. Separate public services from management. Encrypt both sides of the proxy. Assume addresses change. Keep the origin patched. Test recovery. Document the principles publicly and the implementation details privately.

    A changing home IP is not the interesting problem. The interesting problem is building a system in which change does not tempt you to weaken everything else.

    This article intentionally describes a general security pattern, not a reproducible map of the live CloudOnFire network. Configuration should be adapted to your own threat model and verified against current vendor documentation.

  • How I use Authelia

    How I use Authelia

    How I use Authelia

    I use Authelia as an Identity Provide in my network. That means that everyone who wants to use resources (such as Jellyfin or Gitea or Nextcloud) or who wants to “traverse” VLANs (e.g. to manage an OpenWrt router or switch or my Proxmox VE) has to login first. Authelia was my product of choice because

    • It is free and Open Source Software (FOSS)
    • It can act as an OpenID Connect (OIC) Identity provider
    • It can be integratet into an NGINX reverse proxy
    • It supports Two Factor Authentication (2FA) with Time based One Time Passwords (TOTP) or Fido2 compatible Keys such as the Yubikey.

    Installing Authelia on Proxmox

    I set up a small LXC container running Debian Bullseye (Debian 11) on Proxmox. It needs to be privileged because it needs to have access to /dev/urandom or /dev/random for the generation of random numbers.
    Then we need to install some software, add the authelia repos and finally install authelia:

    # run as rootapt update
apt install -y curl gnupg apt-transport-https sudo
curl -s https://apt.authelia.com/organization/signing.asc | sudo apt-key add -
echo "deb https://apt.authelia.com/stable/debian/debian/ all main" >>/etc/apt/sources.list.d/authelia.list
apt-key export C8E4D80D | sudo gpg --dearmour -o /usr/share/keyrings/authelia.gpg
apt update
apt install -y authelia

    Configuration of Authelia

    I mostly followed this guide here by Florian Mueller

    for the configuration. Basically we create sub-directories for all secrets and auto-generate them, create keys and add the secrets to the environment of authelia (the below is a shortened version of Florian’s scripts)

    important note The scripts below use a single SQLITE file rather than mysql! Also, no OIDC provider is configured – just a dummy entry. Please see the implications of this here

     

    for i in .secrets .users .assets .db ; do mkdir /etc/authelia/$i ; donefor i in jwtsecret session storage smtp oidcsecret redis ; do tr -cd '[:alnum:]' < /dev/urandom | fold -w "64" | head -n 1 | tr -d '\n' > /etc/authelia/.secrets/$i ; done
openssl genrsa -out /etc/authelia/.secrets/oicd.pem 4096
openssl rsa -in /etc/authelia/.secrets/oicd.pem -outform PEM -pubout -out /etc/authelia/.secrets/oicd.pub.pem
(cat >/etc/authelia/secrets) <<EOFAUTHELIA_JWT_SECRET_FILE=/etc/authelia/.secrets/jwtsecretAUTHELIA_SESSION_SECRET_FILE=/etc/authelia/.secrets/sessionAUTHELIA_STORAGE_ENCRYPTION_KEY_FILE=/etc/authelia/.secrets/storageAUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE=/etc/authelia/.secrets/smtpAUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE=/etc/authelia/.secrets/oidcsecretAUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE=/etc/authelia/.secrets/oicd.pemEOFchmod 600 -R /etc/authelia/.secrets/
chmod 600 /etc/authelia/secrets
(cat >/etc/systemd/system/authelia.service) <<EOF[Unit]Description=Authelia authentication and authorization serverAfter=multi-user.target

[Service]Environment=AUTHELIA_SERVER_DISABLE_HEALTHCHECK=trueEnvironmentFile=/etc/authelia/secretsExecStart=/usr/bin/authelia --config /etc/authelia/configuration.ymlSyslogIdentifier=authelia

[Install]WantedBy=multi-user.targetEOFsystemctl daemon-reload

    create the user file

    Next, we create a rudimentary User database yaml file with randomly generated passwords (the users can reset them with the “forgot password” link):

    echo "users:" > /etc/authelia/.users/users_database.yml
for user in bob alice dave frank ; do  randompassword=$(tr -cd '[:alnum:]' < /dev/urandom | fold -w "64" | head -n 1 | tr -d '\n')encryptedpwd=$(authelia hash-password --no-confirm   -- $randompassword  | cut -d " " -f 2)(echo "  ${user}:"echo '    displayname: "First Last"'echo "    password: $encryptedpwd"echo "    email: ${user}@yourdomain.com") >> /etc/authelia/.users/users_database.ymldonechmod 600 -R /etc/authelia/.users/

    create the configuration.yml

    Now we need to create a configuration file for authelia in /etc/authelia/configuration.yml

    cd /etc/authelia# save the old version of the fileif [ -e configuration.yml ] ; then  mv configuration.yml configuration.yml.oldfi# Now let's use Marc's version of Florian's Template File for the new config:wget https://raw.githubusercontent.com/onemarcfifty/cheat-sheets/main/templates/authelia/configuration.yml
chmod 600 configuration.yml

    Starting Authelia for the first time

    There we go – authelia should be able to run already – if you do

    systemctl start authelia
systemctl status authelia

    you should see all green and be able to browse to http://localhost:9091 and see the authelia login prompt. Even though this is an important checkpoint (in the sense that we can see if authelia will run at all), we can’t really use it yet. We need to take care of the following things:

    1. All domain names still point to example.com
    2. The start up checks are disabled (especially checking for an e-mail Server)

    You will need a real e-Mail account / Server for Authelia to work correctly (Users need this to reset their password and to register 2FA devices)

    1. We have no TLS enabled
    2. The policies need to be adapted
    3. We need to increase the security and hide Authelia behind an NGINX Server
    4. We need to harden the server
    5. The user accounts are not real

    Adapting and securing authelia

    to get a first idea of how much you need to change do grep example.com /etc/authelia/configuration.yml – that shows you all the lines where we specified the example.com domain.

    Enabling the startup checks and change the domain names

    The first one is the mail server. We need to edit the configuration.yml and give it the login data of a real mail server. This is done in the notifier section of the config:

    notifier:disable_startup_check: truesmtp:host: smtp.domain.comport: 465timeout: 5susername: noreply@auth.example.comsender: "Authentication Service <noreply@auth.example.com>"subject: "{title}"startup_check_address: noreply@auth.example.com

    Change all the settings to reflect a real mailbox that you control. Once you have done that, change the disable_startup_check: true to disable_startup_check: false and restart authelia:

    systemctl restart authelia
systemctl status authelia


    If you see errors, i.e. Authelia idn’t start then that’s because now it checks if it can log into the mailbox at startup. Reminder: The password it uses for the mailbox Server is in /etc/authelia/.secrets/smtp

    Onc Authelia starts, move on to the next step.

    TLS

    Before we can really use Authelia, we need to provide it with realSSL certificates. Use your own or get them from letsencrypt.

    Once you have copied the certificate and key to the server, adapt the configuration.yml file:

    server:host: 0.0.0.0port: 9091asset_path: /etc/authelia/.assets/tls:key: /etc/authelia/certs/server.keycertificate: /etc/authelia/certs/server.crt

    Basically I’ve just added the tls section and point it to the certificates. Again – restart Authelia, check the status. If it starts and if you can browse to https://...:9091 rather than http...then you can move to the next step.

    bind port

    For the moment Authelia listens on any interface, i.e. we can browse to port 9091 from the outside. We will however hide it behind an NGINX server. For this, Authelia should only listen to the localhost interface. Change the configuration.yml from

    server:host: 0.0.0.0port: 9091

    to

    server:host: 127.0.0.1port: 9091

    Restart and check – you should not be able to browse to it from the outside.

    Hiding Authelia behind NGINX

    In this step we install NGINX, let it listen to the outside world on port 443 and forward all requests to Authelia on the local host. You can use the templates from My cheat sheet repo on Github

    # install nginxapt install -y nginx# stop NGINXsystemctl stop nginx# remove the default siterm /etc/nginx/sites-enabled/*# download the templates from Marc's cheat sheetswget https://raw.githubusercontent.com/onemarcfifty/cheat-sheets/main/templates/nginx/authelia/siteconf -O /etc/nginx/sites-available/authelia.conf
wget https://raw.githubusercontent.com/onemarcfifty/cheat-sheets/main/templates/nginx/authelia/proxy-snippet -O /etc/nginx/snippets/proxy.conf
wget https://raw.githubusercontent.com/onemarcfifty/cheat-sheets/main/templates/nginx/authelia/ssl-snippet -O /etc/nginx/snippets/ssl.conf# link back the authelia site as enabled to NGINX ln -s /etc/nginx/sites-available/authelia.conf /etc/nginx/sites-enabled/authelia.conf# restart NGINXsystemctl start nginx


    adapting the policies

    The template file contains three sample policies for bypass, one factor and two factor. You will want to adapt these to your needs. My Server only has one policy:

    access_control:default_policy: denyrules:- domain: '*.mydomain.com'policy: two_factor

    Last but not least

    The last steps are

    • harden the server
    • make the user accounts real

    Server hardening is not in the scope of this article. Basically at least you should do the following:

    1. Lock down the firewall to only let pass port 443 tcp incoming (optionally port 67 UDP if you use dhcp and port 22 tcp if you want to access the server via ssh)
    2. disable / expire the password of the root account
    3. Create a non-root user for login who has sudo capabilities with a loooong password
    4. switch off password authentication and root login for sshd

    Now just review the settings in the /etc/authelia/.users/users_database.yml and make sure that the user accounts are real accounts with real mail addresses.

    That’s it – you’re all set and can now use Authelia in front of your servers with NGINX/Traefik/Caddy or the like and/or add OIDC providers for Proxmox, Gitea, Portainer, Nextcloud and so on…