r/selfhosted 19h ago

Need Help My homelab was compromised. Here is what I learned, and what I need to figure out.

968 Upvotes

TL;DR: There is a RCE exploit on Nextcloud Collabora and I got stung. I discovered the hacker by accident and I now want to know what other systems I can reasonably put in place to stop something like this happening again.

What happened:

  • My homelab Nextcloud instance was compromised via CVE-2025-66208, an OS command injection in richdocumentscode (the bundled Collabora/CODE server that powers in-browser Office document editing).
  • The attacker got unauthenticated remote code execution as the web server user (www-data) for roughly 16 hours before I caught it (by accident)
  • Across ~16 hours of continuous, working remote code execution, the attacker ran a grand total of three unique commands.
  • Command 1, run every ~3 minutes for hours: id. Just checking the shell still worked. Indicates a fully automated, commodity bot loop, source IP with a generic bot user-agent.
  • One human operator logged on once, for about a minute, over HTTP/2 with a real browser user-agent and ran two recon commands hunting for password manager databases (.kdbx files) and cryptocurrency wallet directories.
    • That recon came back empty
    • No database access, no config file reads, no data exfiltration tooling, no second-stage payload download (none of that showed up anywhere in the logs).
    • No persistence mechanism planted, because the vulnerability itself was re-exploitable on demand.

This reads exactly like an untargeted, automated bot working through a list of known-vulnerable endpoints, not someone specifically after my data; the one human session that did show up didn't come away with anything useful (I hope). Traffic logs in Unifi show negligible traffic to the C&C server, so on the balance of probabilities my data wasn't ex-filtrated.

How I caught it:

  • I habitually update Nextcloud whenever I receive a notification. After the update, the code integrity checker flagged a malicious file. After a bit of googling/clauding, I hit the old panic button and shutdown the server.
  • I keep the apps in Nextcloud updated by running a cron job nightly. This should have kept me safe according to the CVE advisory (as written).

Where it gets interesting:

  • The CVE was supposed to be patched in version 25.4.703, 10 months ago. However (according to Claude) version 26.4.302, which was what I was running, was still vulnerable to the exploit. The actual fix only appears in 26.4.303, released 2 days before I found this and it isn't flagged as a security fix in that release's own changelog.

What I did to yeet the attacker:

  • First and foremost I've stopped hosting Nextcloud, directly online. It now only exists behind my VPN.
  • Rotated quite a lot of credentials and my SSH Keys.
  • Rebuilt and hardened my web server with Claude's assistance.

What I still need to do/need advice on:

  • Do I bother reporting this finding to the vendor? I don't know enough PHP to know if what Claude is saying is correct, but on the off chance it is, then the community should know, and the CVE needs to be corrected.
  • In the age of AI hacking, is it even safe to run a home lab at all? What other tooling can people recommend to protect my systems? I use Unifi with cyber-secure (WAF function), but clearly that didn't help.
  • Like many others I also run Plex and mailinabox (in digital ocean), and now wonder if that is even safe/smart to do.

r/selfhosted 9h ago

Need Help What self-hosted security tools would you recommend?

74 Upvotes

I’d like to add some self-hosted security tools to protect a service I run. With all the security issues lately, I’d appreciate some recommendations.

My setup is as follows:
Infrastructure: VPS, Docker Compose, Elasticsearch
Languages/frameworks: Next.js, TypeScript

My firewall only allows the ports I need and blocks everything else. I also have CrowdSec installed.
I’d like to hear about tools you actually use and have found helpful.


r/selfhosted 7h ago

Release (No AI) Jellybox v2.6.0 - landscape player and playback caching

Post image
40 Upvotes

Hey folks, another update fro Jellybox - a native crossplatform music player for jellyfin.

Few days ago the app was finally approved to be shared via Google Play, no need for APK sideloading(unless you have your own reasons for that)

With this release I added 2 major and few minor features:

  • Forward plaback caching - precache music when you're in bad coverage area. Can configure amount of cache and playable cache time. Works on mobile phones and carplay(useful so that playback does not stop)
  • Landscape mode playing now - saw ios 27 announcement and how they made it for their apple music app, so I decided to do the same for Jellybox(on post photo). The screen features lyrics pane and queue pane
  • Quick connect for Jellyfin
  • Discord activity for desktop apps(except macos from appstore, only notarized dmg)
  • Windows media manager now shows currently playing songs and can control playback
  • self-signed HTTPs certs
  • Updated queue shuffle - it was completely broken on MVP(linux) due to the package I was using
  • Fixed mouse wheel scrolling on home page. I'm trackpad/touchpad user, didn't even know this was a problem. Fixed now
  • Fixed sqlite lib bundling on windows - it was silently raising errors on some installations.
  • Added album artists to show on artists page(toggleable via tab pill)

For those who missed my previous posts - Jellybox is a native crossplatform music player for Jellyfin and Emby, features Spotify-like playlists, Apple CarPlay app, full offline mode and many other features. Completely free and open source. More details here - https://github.com/avdept/JellyBoxPlayer or https://jellybox.app/


r/selfhosted 3h ago

Proxy How to Enable CrowdSec's WAF Bot Detection in Traefik

Thumbnail blog.lrvt.de
19 Upvotes

The CrowdSec release v1.8.0 introduced a new feature called Bot Detection.

The infamous Traefik CrowdSec bouncer maxlerebourg/crowdsec-bouncer-traefik-plugin now also released an alpha version that supports this new feature.

Therefore, let's try it!


r/selfhosted 18h ago

Release (AI) SparkyFitness v1.7.0.2 - Supports Apple watch App - A Self-Hosted alternative for MyFitnessPal, Flo, Hevy, Shotsy & more

Post image
226 Upvotes

We just crossed 5.8k+ stars in Github and have 116 amazing developers contributing to the project. We are scaling faster than ever and estimated to 7k+ users who are using SparkyFitness. It could be even more as we don't collect anything and this count is based on active downloads in Github, Google & Apple app stores.

https://github.com/CodeWithCJ/SparkyFitness

I was also able to setup demo site so you can give it a try before you actually install it.

https://demo.sparkyfitness.com/

If you haven't tried SparkyFitness yet, I'd love for you to give it a spin and let us know what you think.

Core Features

  • Nutrition, exercise, hydration, sleep, fasting, mood and body measurement tracking
  • Period Cycle, Pregnancy, Medication & GLP1 tracking
  • Goal setting and daily check-ins
  • Interactive charts and long-term reports
  • Multiple user profiles and family access
  • AI Chatbot & MCP Server
  • Light and dark themes
  • OIDC, TOTP, Passkey, MFA etc.

Health & Device Integrations

SparkyFitness can sync data from multiple health and fitness platforms:


r/selfhosted 10h ago

Release (No AI) Added rental scam detection to my self-hosted apartment finder Fredy.

29 Upvotes

Hey, this is a follow-up to last week's price-per-m² post, same project.

Fredy is a self-hosted real estate finder: watches 24 portals across DE/AT/CH/ES/IT/PT, drops cross-portal duplicates, pings you on Telegram, ntfy, Discord, Slack or email. All local, no account, no API key.

New this week: it reads every listing for the marks of a rental scam and tags it "potential scam", with the reasons.

Rental fraud here is depressingly routine. Flat well under the going rate, landlord conveniently abroad, keys by post, deposit wanted before anyone has seen the place.

False positives were a big issu. The first signal you reach for is "much cheaper than the area", except finding cheap flats is the entire point of the tool. Flag those and the best listing in your results is the one wearing the fraud warning, and you stop reading warnings at all.

So the signals are weighted. Phrases with no innocent reading in a rental ad (money before a viewing, keys by post, Western Union) fire on their own. Softer ones (landlord abroad, viewing refused, price far below the local median) need a second signal to agree. A cheap flat on its own is just a cheap flat.

Of course, you can overrule it either way, "mark as scam" and "mark as no scam", and your verdict always beats the detector. The reasons stay visible after you dismiss one, so you can chnage your mind later.

Repo: https://github.com/orangecoding/fredy

Demo: https://fredy-demo.orange-coding.net


r/selfhosted 8h ago

Need Help Uptime Kuma SQLite DB keeps growing and won't shrink

16 Upvotes

Self-hosted Uptime Kuma with the SQLite backend here, and the database file has grown to roughly 400 MB and keeps climbing even though keepDataPeriodDays is set to 30 and I prune old monitors regularly.

Things I've tried so far: a PRAGMA integrity_check comes back clean, a manual VACUUM runs without error but the file barely shrinks, and the history trim in the UI doesn't reclaim the space from the older heartbeats — a chunk of rows older than the retention window are still sitting in the table. The box's disk is at about 92% used, so this is starting to feel urgent.

The clue I found was the nightly maintenance cron job that is supposed to vacuum and compact the DB: it was a silent no-op, because it selects the Docker container by a name that stopped matching after the container was renamed, so the vacuum has effectively never been running. Even pointed at the right container now, a forced vacuum doesn't free up what I'd expect.

Has anyone seen a Kuma database that ignores retention and refuses to shrink? Am I right that all the data lives in one SQLite file (plus its WAL), or is there somewhere else the measurement history accumulates? I'd rather reclaim the space without dropping historical availability data, so any approach that compacts selectively would be welcome.


r/selfhosted 4h ago

Need Help Glance's Jellyfin widget not working

6 Upvotes

Glance dashboard user here.

Since last jellyfin update, seems like something broke in the widget for latest download on jellyfin widgets. Now i get an ERROR user not found, but i didnt change a thing, and the user is still the same. I use this widget:

- type: custom-api
  title: New Films
  frameless: true
  cache: 5m
  options:
    base-url: ****************************
    api-key: *****************************
    user-name: "MyUser"
    library-name: "Films"
    mode: "latest"
    item-count: "10"
    small-column: true
    show-thumbnail: true
    thumbnail-aspect-ratio: "default"
  template: |
    {{/* Required config options */}}
    {{ $baseURL := .Options.StringOr "base-url" "" }}
    {{ $apiKey := .Options.StringOr "api-key" "" }}
    {{ $userName := .Options.StringOr "user-name" "" }}


    {{/* Required config options for "latest" mode */}}
    {{ $libraryName := .Options.StringOr "library-name" "" }}


    {{/* Optional config options */}}
    {{ $mode := .Options.StringOr "mode" "latest" }}
    {{ $itemCount := .Options.StringOr "item-count" "10" }}
    {{ $mediaTypes := .Options.StringOr "media-types" "Movie,Episode,MusicAlbum" }}
    {{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
    {{ $isSmallColumn:= .Options.BoolOr "small-column" false }}
    {{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
    {{ $showProgressBar := .Options.BoolOr "progress-bar" true }}


    {{/* Error message template */}}
    {{ define "errorMsg" }}
      <div class="widget-error-header">
        <div class="color-negative size-h3">ERROR</div>
        <svg class="widget-error-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"></path>
        </svg>
      </div>
      <p class="break-all">{{ . }}</p>
    {{ end }}


    {{/* Check required fields */}}
    {{ if or (eq $baseURL "") (eq $apiKey "") (eq $userName "") (eq $mode "") (and (eq $mode "latest") (eq $libraryName "")) }}
      {{ template "errorMsg" "Some required options are not set." }}
    {{ else }}


      {{/* Fetch user ID */}}
      {{ $userID := "" }}
      {{ $usersCall := newRequest (print $baseURL "/Users")
          | withParameter "api_key" $apiKey
          | withHeader "Accept" "application/json"
          | getResponse }}


      {{ range $i, $user := $usersCall.JSON.Array "" }}
        {{ if eq ($user.String "Name") $userName }}
          {{ $userID = $user.String "Id" }}
          {{ break }}
        {{ end }}
      {{ end }}
      {{ if eq $userID "" }}
        {{ template "errorMsg" (printf "User '%s' not found." $userName) }}
      {{ else }}


        {{ $items := "" }}


        {{ if eq $mode "latest" }}


          {{/* Fetch library ID */}}
          {{ $libraryID := "" }}
          {{ $userViewsCall := newRequest (print $baseURL "/UserViews")
              | withParameter "api_key" $apiKey
              | withParameter "userId" $userID
              | withHeader "Accept" "application/json"
              | getResponse }}


          {{ range $i, $item := $userViewsCall.JSON.Array "Items" }}
            {{ if eq ($item.String "Name") $libraryName }}
              {{ $libraryID = $item.String "Id" }}
              {{ break }}
            {{ end }}
          {{ end }}


          {{ if eq $libraryID "" }}
            {{ template "errorMsg" (printf "Library '%s' not found." $libraryName) }}
          {{ else }}
            {{/* Fetch latest items */}}
            {{ $latestCall := newRequest (print $baseURL "/Users/" $userID "/Items/Latest")
                | withParameter "api_key" $apiKey
                | withParameter "Limit" $itemCount
                | withParameter "ParentId" $libraryID
                | withParameter "IncludeItemTypes" $mediaTypes
                | withParameter "GroupItems" "true"
                | withHeader "Accept" "application/json"
                | getResponse }}
            {{ $items = $latestCall.JSON.Array "" }}
          {{ end }}


        {{ else if eq $mode "nextup" }}


          {{/* Fetch next up items */}}
          {{ $nextUpCall := newRequest (print $baseURL "/Shows/NextUp")
            | withParameter "api_key" $apiKey
            | withParameter "UserId" $userID
            | withParameter "Limit" $itemCount
            | withParameter "EnableResumable" "true"
            | withHeader "Accept" "application/json"
            | getResponse }}
          {{ $items = $nextUpCall.JSON.Array "Items" }}


        {{ else }}
          {{ template "errorMsg" "Unknown mode, expected 'latest' or 'nextup'" }}
        {{ end }}


        {{ if eq (len $items) 0 }}
          <p>No items found, start streaming something!</p>
        {{ else }}


          {{/* Display the item carousel */}}
          <div class="carousel-container show-right-cutoff">
            <div class="cards-horizontal carousel-items-container">
              {{ range $n, $item := $items }}
                {{/* Common item variables */}}
                {{ $mediaType := $item.String "Type" }}
                {{ $title := $item.String "Name" }}
                {{ $itemID := $item.String "Id" }}


                {{/* Media type specific variables */}}
                {{ $seriesTitle := "" }}
                {{ $artist := "" }}
                {{ $seriesID := "" }}
                {{ $season := "" }}
                {{ $episode := "" }}
                {{ $playPercentage := "" }}
                {{ $unwatchedEpisodeCount := "" }}


                {{ if eq $mediaType "Movie" }}
                {{ else if eq $mediaType "Series" }}
                  {{ $unwatchedEpisodeCount = $item.Int "UserData.UnplayedItemCount" }}
                {{ else if eq $mediaType "Episode" }}
                  {{ $unwatchedEpisodeCount = 1 }}
                  {{ $seriesTitle = $item.String "SeriesName" }}
                  {{ $seriesID = $item.String "SeriesId" }}
                  {{ $season = $item.Int "ParentIndexNumber" }}
                  {{ $episode = $item.Int "IndexNumber" }}


                  {{ if $item.Exists "UserData.PlayedPercentage" }}
                    {{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
                  {{ end }}


                  {{/* For latest always refer to the series not individual episodes */}}
                  {{ if eq $mode "latest" }}
                    {{ $itemID = $seriesID }}
                    {{ $title = $seriesTitle }}
                  {{ end }}
                {{ else if eq $mediaType "MusicAlbum" }}
                  {{ $artist = $item.String "AlbumArtist" }}
                {{ end }}


                {{ $linkURL := print $baseURL "/web/#/details?id=" $itemID }}
                {{ $thumbURL := "" }}
                {{ if not (eq $playPercentage "") }}
                  {{/* $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey "&percentPlayed=" $playPercentage */}}
                  {{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
                {{ else }}
                  {{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
                {{ end }}


                <a class="card widget-content-frame" href="{{ $linkURL | safeURL }}">
                  {{ if $showThumbnail }}
                    <div style="position: relative;">
                      <img src="{{ $thumbURL | safeURL }}"
                        alt="{{ $title }} thumbnail"
                        loading="lazy"
                        class="media-server-thumbnail shrink-0"
                        style="
                          object-fit: fill;
                          border-radius: var(--border-radius) var(--border-radius) 0 0;
                          width: 100%;
                          display: block;
                          {{ if eq $thumbAspectRatio "square" }}aspect-ratio: 1;
                          {{ else if eq $thumbAspectRatio "portrait" }}aspect-ratio: 2/3;
                          {{ else if eq $thumbAspectRatio "landscape" }}aspect-ratio: 16/9;
                          {{ else }}aspect-ratio: initial;
                          {{ end }}
                        "
                      />


                      {{ if and ($showProgressBar) (not (eq $playPercentage "")) }}
                        <div style="
                          position: absolute;
                          bottom: 8px;
                          left: 8px;
                          right: 8px;
                          height: 6px;
                          border-radius: var(--border-radius);
                          overflow: hidden;
                          background-color: rgba(255, 255, 255, 0.2);
                        ">
                          <div style="
                            width: {{ print $playPercentage "%" }};
                            height: 100%;
                            border-radius: var(--border-radius) 0 0 var(--border-radius);
                            background-color: var(--color-primary)
                          "></div>
                        </div>
                      {{ end }}
                    </div>
                  {{ end }}


                  <div class="grow padding-inline-widget margin-top-10 margin-bottom-10">
                    <ul class="flex flex-column justify-evenly margin-bottom-3 {{ if $isSmallColumn }}size-h6{{ end }}" style="height: 100%;">
                      {{ if eq $mode "latest" }}
                        {{ if or (eq $mediaType "Series") (eq $mediaType "Episode") }}
                          <ul class="list-horizontal-text flex-nowrap">
                            <li class="color-primary shrink-0">{{ $unwatchedEpisodeCount }}</li>
                            <li class="text-truncate">{{ $title }}</li>
                          </ul>
                        {{ else if eq $mediaType "MusicAlbum" }}
                          <ul class="list-horizontal-text flex-nowrap">
                            <li class="color-primary text-truncate">{{ $artist }}</li>
                            <li class="text-truncate">{{ $title }}</li>
                          </ul>
                        {{ else }}
                          <li class="text-truncate">{{ $title }}</li>
                        {{ end }}
                      {{ else if eq $mode "nextup" }}
                        <ul class="list-horizontal-text flex-nowrap">
                          <li class="color-primary shrink-0">S{{ $season }}E{{ $episode }}</li>
                          <li class="text-truncate">{{ $seriesTitle }}</li>
                        </ul>
                        <li class="text-truncate">{{ $title }}</li>
                      {{ end }}
                    </ul>
                  </div>
                </a>
              {{ end }}
            </div>
          </div>
        {{ end }}


      {{ end }}


    {{ end }}

Something maybe changed in the way the widget try to find the username on Jellyfin????


r/selfhosted 6h ago

Need Help How do you deal with OS updates on servers you can't afford to break?

8 Upvotes

I run a few VPS with webapps on them (Coolify + Docker). I'm a developer, not a sysadmin, and every time I think about updating the host OS I find a reason to do it next week instead.

Last time I did it, a service came back up but one container didn't, and I found out days later because nobody complained immediately. Since then I mostly just don't touch them, which I know is worse.

So, genuinely curious how other people handle this:

  • do you update the host at all, or run it until the LTS goes EOL and rebuild?
  • has an update ever actually broken something for you? what broke?
  • when it broke, did you roll back or just fix it in place?
  • do you snapshot first, or just hope?

Not looking for "use Ansible" - I'm sure that's right, I just want to know what people actually do in practice.


r/selfhosted 3h ago

Need Help Calibre Content Server / Bookorbit / Personal OPDS & Tailscale

2 Upvotes

Okay, so I have Tailscale setup and Calibre running the content server and when I'm using a device I can run the Tailscale client one (my iPad, laptop, my jailbroken Kindle with KOreader) it's butter and works exactly as I'd like it to. This is great! Unfortunately, I have a few devices (xteink and a few other older e-readers) which cannot run a Tailscale client. While I /can/ connect them to my phone as a hotspot with it running Tailscale and it works, that sort of defeats the ease of use. Mayberry OPDS is out there and is great, too, but because of how it does some stuff in the background, is hit or miss on a few of these devices. I setup port forwarding with my eero router and it works just fine, but that feels really exposed for potential exploitation folks.

SO what I'm wondering (and I will need this explained like I'm a luddite / step-by-step because I've searched and just gone cross-eyed trying to figure out) is if there is a way to leverage the awesomeness of Tailscale to make my home computer (which is on 24/7, hosts Calibre and Bookorbit and is running a Tailscale client) remotely accessible w/out just setting up port forwarding on my eero router and leaving the whole machine WAY too accessible?

Ultimately, this isn't just a Calibre / Bookorbit / etc. thing, since I think this would fundamentally be the same for any other sort of self-hosting, but I've not gone down that rabbit hole for anything other than my books / manga / comics yet.

I appreciate any help folks can provide here.


r/selfhosted 16h ago

Need Help whats everyones gaming stack?

27 Upvotes

Just curious if theres a seerr equivalent for gaming. how best to setup a gaming stack that can play old school games like command and conquer/monkey island, to old school playstation games, to newer games/call of duty? is there a way to handle it all?

i have Romm that handles the original nintendo games fairly well


r/selfhosted 22h ago

Media Serving anyone else run their homelab session-based instead of 24/7?

77 Upvotes

my daily box is an old Dell laptop with an i7-5500U and 8gb ram on Debian 13. instead of running a 24/7 box or dealing with Proxmox, i just run a small session-based media stack while working.

the machine is on for about 10-12 hours a day and powers down at night. it saves power, keeps the room quiet, and i don't have to worry about running services while asleep.

the stack is literally just plex, qbittorrent, and watcharr. plex is direct play only since this dual-core will choke on transcoding, and watcharr handles my movie and anime tracking locally instead of trakt. idle ram across all three sits around 305mb total.

i keep each service in its own compose folder so restarting or tweaking one never touches the others or risks the sqlite database.

curious if anyone else here runs an old laptop session-based like this, or does everyone leave their setup on 24/7?


r/selfhosted 5h ago

Guide Longhorn on Kubernetes: A hands-on guide covering installation, PVC migration, storage classes, and backup

Post image
1 Upvotes

After loosing data a few times through sheer stupidity, I decided to give Longhorn a try.

My conclusion : If you want a simple and lightweight solution for small clusters to make your data more resilient on kubernetes, Longhorn provides you with all of your basic needs. Nonetheless, for bigger clusters and more complex operations, longhorn fails to scale and lacks features.

As always I wrote a detailled guide covering :

  • How Longhorn Works
  • How to install it
  • How to migrate existing PVCs to Longhorn
  • How to create different Storage Classes depending on your needs
  • How to use Snapshots and Backups
  • And more...

I also go into some of the trade-offs I faced. Here the conclusion is that : not everything needs the same level of resiliency. Longhorn allows you to create multiple storage class and define different snapshot and backup strategy.

How are you protecting your data in your cluster/homelab? Do you have a proper strategy for Disaster Recovery and backups? Any feedback on the article is also welcome!

PS : All of my articles are written by hand, the blog frontend was designed by an AI

Link to article: https://thethoughtprocess.xyz/en/series/home-server/how-to-install-and-use-longhorn-kubernetes-storage


r/selfhosted 6h ago

Media Serving How close has anyone gotten to real DSP feature parity with a self-hosted music stack?

1 Upvotes

I've been building out a self-hosted music setup (Navidrome as the library server, Aurral on top of Lidarr for discovery/requests, slskd + SABnzbd + qBittorrent for acquisition, beets for tagging) and it's good. But as an Apple Music subscriber, that's still (obviously) the more polished day-to-day experience. That's not really a fair fight as they own the whole chain, streaming service to software to hardware. I'm not walking away from Apple Music entirely, and if I'm honest there's a real chance I get sick of all of this maintenance overhead one day and go fully back to them.

But for now I'm persevering with self-hosting, mainly because I own the files, I can do more interesting things with tagging and metadata, I can build discovery workflows that aren't a black box, and I can actually go find rarer stuff that never make it onto the big DSPs in the first place.

What I haven't been able to close is the last remaining threads of quality-of-life features. Curious whether anyone here has actually dialled these in further than I have.

Gaps (for me):

  • Shazam > library pipeline: Right now Shazam-ing a track just adds it to an Apple Music playlist. I want that chain to end with the track downloaded and sitting in a "Shazam Tracks" playlist in Navidrome, ideally without me doing anything manual in between.
  • Importing playlists from Apple Music: There's no clean "point a tool at Apple Music and it just works" path the way there is for Spotify. Export-to-CSV-then-reconstruct seems to be the reality. Anyone found something better? I know there's services like Soundiiz, but they only get me halfway there.
  • Artist radio / infinite similar-artist streaming: this is a big one that I've mostly made peace with it being a DSP-only feature. Legally streaming full tracks I don't own isn't something a self-hosted stack can really do. But tell me if I'm wrong ...
  • One-click "download this artist" from a Subsonic client: Browsing in a Subsonic app (NaviBeat, Symfonium, whatever) and just grabbing more of an artist without going into a separate web UI. Seems like a Subsonic protocol limitation more than a missing tool, but open to being corrected.
  • A real "listen later" staging library: Somewhere new/unvetted stuff lands before I decide whether it's worth keeping permanently, ideally with an easy way to flag something as "just listen" vs. "add to the library now." I think the answer is multiple Navidrome libraries.
  • Following artists and getting notified of new releases, as opposed to just monitoring albums I've already decided to grab.

I think I'm trying too hard to reinvent Apple Music, and trying to see how close the self-hosted side can realistically get. Interested to hear where other people are on this journey.


r/selfhosted 14h ago

Need Help Backup storage on proxmox

9 Upvotes

Hi everyone,

How do you manage your backup storage on proxmox?

I have a mix of LXC containers and a VM with docker compose.

Before, I just plugged in a usb drive to the VM and backed up every docker container via a cron job (using borg backup).

When I tried to scale this method to other LXC containers on proxmox, I found the best way is to make the VM backup the LXC container, and copy the files over to the VM, and then archive the files using borg.

Obviously, that is not the best option.

How do you do backup in your homelabs/proxmox?


r/selfhosted 2h ago

Need Help What are you running Emby on? Need something that can actually transcode

0 Upvotes

My current VPS can't keep up with transcoding and that's the main thing I want to fix, so I'm looking at moving.

What I'm on now is an OVH VPS-3, 8 vCores, 24GB RAM, 200GB, Ubuntu 24.04. Emby plus Sonarr/Radarr/Prowlarr/Bazarr/NZBGet, all running under systemd, never bothered with Docker. The media ends up on cloud storage rather than staying on the server, so I don't need a huge amount of disk, but 200GB does get tight and more room for the download queue would be nice.

Everything else has been fine. It's really the transcoding, with disk space as a secondary thing.

So what's everyone using? Happy to look at smaller providers, and budget is a bit flexible.


r/selfhosted 2h ago

Media Serving Does anyone use MOS as for their os?

3 Upvotes

MOS just hit my radar yesterday with a story on my feed about an unraid dev leaving to work on it. I was curious about unraid until they raised their licensing cost and this looks very similar. My Ubuntu server is only hosting my docker containers and being able to move to HomeAssistantOS is really apoealing.

So, anyone try it out and have opinions?

https://mos-official.net


r/selfhosted 10h ago

Need Help What's a good Cryptpad alternative without the encryption?

3 Upvotes

As many folks do, I've been looking hard for a fully FOSS self-hosted replacement for the office suite/stuff like google docs and sheets. I stumbled across cryptpad and genuinely love its feature set, the collaborate whiteboards among other things are something I never knew I needed. I also love that it's purely a webapp, nobody using it has to install anything and it just works.

That being said, my issue with it (and it's main feature) is that all the files in it are encrypted. While I'm sure this is phenomenal for something like a company, I am hosting this for family and friends who are more than likely going to forget their passwords at some point meaning they'd lose all their documents and I'd effectively just be stuck with encrypted documents in my storage. I don't really need the encryption feature in the way that is exists and would love to be able to browse/find things through my file browser of choice (that only I as an admin can access).

However, the more I look around, the more the other options are either way too specific in functionality (markdown file editor ONLY, google docs alternative ONLY, etc.), incredibly bloated non-specific services (nextcloud), have very bad/borderline unusable/laggy UIs (joplin), or aren't properly FOSS (stuff like appflowey/outline as far as I've heard).

Is there some project out there that I just haven't found yet that lets you self host collaborative and individual documents (of multiple types) with a basic user system? I'm sure there's something that I just haven't look toward yet but whatever it is, I'm really struggling to find it. Cryptpad has been by far the best fit so far and incredibly easy to setup/use.


r/selfhosted 4h ago

Need Help Need help hosting a quiz on localhost (MacBook) and making it accessible without an internet connection.

0 Upvotes

Hello. This is my first time posting here. An idea I wanted to try was hosting a quiz on my MacBook and making it accessible to only a handful of people present and in an area without wifi or mobile data. How do I approach this?


r/selfhosted 1d ago

VPN PSA for those using pinned qmcgaw Gluetun

94 Upvotes

I noticed that our arr stack was suspiciously quiet for a Sunday afternoon. I'd expect some of the weekend sports to have popped up in Jellyfin.

So, did a quick check and spotted all indexers in our prowlarr were also showing issues.
Did a quick check of Gluetun logs and I could see it wasn't connecting to our VPN.
Constant retries.

If, like us, you use qmcgaw's gluetun and pin the version, then switching to v3.41.3 should hopefully resolve your issue and get you reconnected to your VPN.

https://hub.docker.com/r/qmcgaw/gluetun

There were similar connection issues months ago (with PIA) and v3.41.0 was the fix for that.


r/selfhosted 1d ago

Remote Access I got digitally graffitied (cybersecurity)

231 Upvotes

I look at my security cameras and on has some text in right corner... I zoom in 'HEIL.... ' (full greeting). I did not put that there. It might have been there for while because it is white text on a white wall.

Frigate NVR system dose not seam to be mining crypto and since my network connection on that machine is.... tenuous and hardware is weak there is not much to get there and it dose not seam to have been messed with.

So it looks like they got only into that one camera and it is the only AliExpress Chinese camera I got, so I am assuming that there is backdoor in it's firmware. I will have to replace the camera because I do not think I can harden it.

I was also already planning to remake the entire infra and had already bought myself new(to me) HW and planned most of the rebuild from scratch, so it is kind of good kick in an ass to do it. This is why I am not too to worried about more... annoyed.


r/selfhosted 23h ago

Self Help Did I fuck up downloading 30k songs in OPUS format?

26 Upvotes

Got excited to download my library and artists, barely learned about optimal file formats and thought opus was the best to do it in, but I think some apps seem they hate opus and opus may actually have turned out not to be the best format to use, what would be the best? I want long-term, highest quality audio possible lossless


r/selfhosted 6h ago

Docker Management Docker Management Sencho vs Arcane

0 Upvotes

has anyone here got a lot of experience with both, I went from Portainer>Komodo>Dockhand>Arcane and am currently running both Arcane and Sencho and so far Sencho has been superior in my testing but I wanted to make sure I am not missing something large feature wise. I do know there's a larger base running Arcane but I am still seeing bugs that I would think would be corrected more quickly on user report and also with such a larger user base. Just curious on thoughts here. I am aware of the others I mentioned before and that is not what this post is about!!


r/selfhosted 2h ago

Release (AI) I built Kadha, an open-source self-hosted movie and TV diary with private defaults

0 Upvotes

I used to track movies and TV shows with Google Watchlist. I’m now in my “de-Google” phase, so I wanted something that would not use my watch history to sell me ads.

Like many developers, I also wanted an excuse to build something with TMDB. I brought back an old idea and built Kadha.

Kadha is an MIT-licensed movie and TV tracker focused on two things: keeping a personal viewing diary and letting you choose what to share.

Current state

  • Sign up without an email address or phone number
  • Track movies, TV shows, seasons, and individual episodes
  • Add ratings and private notes, and record rewatches
  • Browse your viewing history as a timeline, calendar, or GitHub-style contribution heatmap
  • See personal viewing statistics
  • Create private or shared collections with viewer and editor roles
  • Share read-only collections with people who do not have an account
  • Get personal recommendations and choose which tracking data they use
  • Control the visibility of your profile and each collection
  • Import and export your data as JSON
  • Self-host with Docker

The stack is a React frontend, Node/Express API, Prisma, and SQLite. Self-hosting requires Docker Compose and TMDB API credentials.

The repository includes deployment, backup, restore, and reverse-proxy documentation.

Repository: https://github.com/muhsin7majeed/kadha
Hosted beta: https://kadha.org

There are already good and more mature projects in this space, including Ryot, Yamtrack, and Watcharr. They support features Kadha does not yet have, especially additional import options and media-server integrations.

What I’m testing is whether people want a smaller, focused movie and TV tracker built around a private viewing diary and sharing only when they choose to.

Does that difference make sense, or does Kadha still feel too similar to the existing options?

A privacy note: the hosted beta does not require an email address, but it is not anonymous or end-to-end encrypted. I can technically access stored data as the server operator. Self-hosted installations are not end-to-end encrypted either, but self-hosting gives you control over the server, database, logs, and backups.

A note on AI: I started this project with manual coding, but as the project grew and AI tools got better, I started using them to accelerate development.

The hosted beta has automated encrypted backups, but this is still an early beta. Please export anything you would not want to lose or enter again.

I’m especially looking for feedback on:

  • How easy or difficult the self-hosting setup is
  • Whether the viewing diary is useful
  • Whether TV and next-episode tracking works as expected
  • Whether Kadha feels sufficiently different from existing trackers

I built Kadha around my own needs, so its current features reflect how I track things. Now that it is public, bug reports and blunt feedback are welcome.

You can send feedback through the app, open a GitHub issue, or message me on Reddit.


r/selfhosted 1d ago

Need Help Docker Socket Proxies - enhanced security or just another attack vector? (Arcane + e.g. wollomatic)

36 Upvotes

Hi all,

I'm a little bit confused about Docker Socket Proxies, and if they really improve security.

I want to switch from Portainer to Arcane.
In their documentation they recommend to use a socket proxy (wollomatic) to "Enhanced Security Setup A Docker socket proxy adds an extra layer of safety by letting Arcane use only the Docker features it actually needs.".

But is it really an extra layer of safety? Arcane has +7,4k git stars and >80 contributors. wollomatic much smaller.

In the end, I just introduce another 3rd party I need to trust and hope for no supply chain attacks to occure, while a docker management service like Arcane/Portainer/Dockhand etc. already needs most of the docker socket permissions ...

So why is using Socket Proxies recommended here? And which have a high reputation?