Frigate on Proxmox: the config problems nobody warns you about

Frigate itself is good software. Almost every problem I hit running it came from the layers around it: Proxmox, LXC, Docker, kernel modules, and my own YAML. None of them announced themselves clearly. Most looked like something else entirely.

This is the list I wish I’d had before starting.

The setup

For context, here’s the stack these lessons come from:

  • Host: a secondhand Dell R630 running Proxmox, dual socket, plenty of RAM.
  • Container: Frigate in Docker, inside a Proxmox LXC. Docker-in-LXC is common in homelabs and adds a layer of things to get wrong.
  • Detector: a Hailo-8 AI accelerator, pulled from a Raspberry Pi AI Kit, on PCIe.
  • Decode: an NVIDIA Tesla P4 handling video decode (NVDEC).
  • Cameras: five Annke/Hikvision turrets and a Reolink doorbell, on their own VLAN with no internet access.
  • Storage: recordings on a separate ZFS pool, bind-mounted into the container.

If your setup is a Pi or a bare-metal mini PC, some of this won’t apply. If it’s anything with “LXC” in it, most of it will.

1. The Hailo device that keeps changing its number

The standard advice for passing a device into an LXC is two lines in the container’s config: an lxc.cgroup2.devices.allow rule for the device’s major number, and an lxc.mount.entry for the device node.

That works until the major number changes. On my host, /dev/hailo0 moved between 239, 511, 239 and 238 across kernel updates and module reloads, even with DKMS rebuilding the driver correctly each time. Every change meant Frigate restart-looping on a Hailo permission error after a routine reboot.

The fix is to stop caring about the major number. Proxmox has native device passthrough:

pct set 101 -dev5 /dev/hailo0,mode=0666Code language: JavaScript (javascript)

Then delete the old lxc.mount.entry and devices.allow lines. Proxmox handles the rest, whatever number the kernel assigns.

Two gotchas:

  • Check which devN slots are taken first. I overwrote dev0, which held /dev/nvidia0, and broke all GPU decode in one command. The error was CUDA_ERROR_NO_DEVICE, which doesn’t point at the cause.
  • Stop the container before changing device entries. Hotplugging fails if the node already exists.

2. NVIDIA decode in Docker Compose

There are three ways to give a Compose service a GPU. Only one worked for me.

The --gpus flag and the newer deploy: resources: reservations: devices: syntax both failed with Cannot load libcuda.so.1 or CUDA device errors. Neither reliably requests the video capability that NVDEC needs.

What works is the older form:

runtime: nvidia
environment:
  - NVIDIA_VISIBLE_DEVICES=all
  - NVIDIA_DRIVER_CAPABILITIES=all

The Hailo also needs devices: - /dev/hailo0:/dev/hailo0 and cap_add: SYS_RAWIO alongside CAP_PERFMON.

3. The compose file you weren’t editing

My Frigate directory had both a compose.yml and a docker-compose.yml. Docker Compose prefers compose.yml when both exist, and says nothing about the other one. I spent a while editing the dead file and wondering why nothing changed.

Delete the duplicate. Then check the live file matches what’s actually running, because mine didn’t. The Hailo device mapping and several ports had been added to the running container at some point but never made it into the file. They vanished silently on the next docker compose up -d.

The ports worth checking explicitly:

  • 5000 and 8971: the web UI, unauthenticated and authenticated
  • 1984: the go2rtc API
  • 8555 TCP and UDP: WebRTC
  • 8554: the RTSP restream. Easy to miss, and Home Assistant’s stream integration connects to it directly.

4. The crash that looked like a network fault

For about a week, every camera dropped at once, repeatedly. All six ffmpeg processes logged Failed reading RTSP data: End of file within the same second, across two VLANs. That looks like a network problem. It wasn’t.

The container was out of memory. The LXC had been created with a 2 GiB limit, which was fine for three cameras on the previous Frigate version. Going to six cameras, plus 0.18’s new embeddings models, pushed it over. The host had over 100 GiB free; the container just wasn’t allowed any of it.

Why it looked like networking: under memory-cgroup pressure, the kernel throttles socket buffers. Every RTSP stream starves together, so every camera fails in the same second.

The signature to 3. The compose file you weren’t editingrecognise:

  • All cameras’ ffmpeg dying within the same second
  • The embeddings process, then Frigate itself, killed with signal 9
  • On the host, journalctl -k showing oom-kill:constraint=CONSTRAINT_MEMCG naming your container

The fix applies live, no restart needed:

pct set 101 -memory 8192 -swap 2048
pct set 101 -cores 8Code language: JavaScript (javascript)

Afterwards, memory settled around 2.6 GiB of 8, pressure stalls went flat, and skipped frames dropped to zero on every camera.

One more trap: you can’t see the limit from inside the container. cat /sys/fs/cgroup/memory.max returns max, because the limit is enforced on a parent cgroup the container can’t see. Read it on the host with cat /sys/fs/cgroup/lxc/101/memory.max. Also, the Proxmox Notes panel written by the community helper script still shows the original 2 GiB. It’s static text and doesn’t track the real config.

5. Streams: the audio loop and the cheapest CPU win

The audio role loop. My Annke cameras only carry audio on the main stream; the substream has none. I’d put the audio role on the substream input. Frigate then spawned an ffmpeg process every ten seconds or so that immediately failed with Output file does not contain any stream. Across three cameras, that churn destabilised the whole NVR.

The fix is to put audio on the main-stream input alongside record. One input can serve both roles.

Substream tuning. Frigate was detecting at 5–6 fps, but the camera substreams were running at 20 fps. Every extra frame still gets decoded, so ffmpeg was doing a lot of work that detection threw away. I set every substream in the camera’s own UI to:

SettingValue
Resolution1280×720, matching detect width and height
Frame rate6 fps
Bitrate1024 Kbps, variable
CodecH.265
I-frame interval6, which keeps a 1-second keyframe gap for fast stream startup

Then set global detect.fps: 6 to match. This was the biggest CPU lever available, bigger than adding cores. Keep an eye out for fast-moving objects being missed, because that won’t show up in any metric.

One thing that confused me afterwards: the live dashboard still looked smooth at 20 fps. That’s expected. Live view and Home Assistant cards use the main stream via go2rtc; only detection uses the substream. The System ? Cameras page shows the detect path’s real frame rate.

The Reolink doorbell was its own saga and gets its own post: two-way talk works, but not with the documented config.

6. Pasted YAML fragments and duplicate keys

Forum answers and docs hand you snippets like this:

detect:
  stationary:
    threshold: 180

If your config already has a top-level detect: block and you paste this below it, you now have two. I did exactly that, with cameras:, notifications: and detect: fragments. Frigate refused to start, the container went into a restart loop, and I blamed the settings themselves for a while. I’d reverted perfectly good changes before spotting the real cause.

Two habits that would have saved me hours:

  • Merge, don’t append. Every snippet goes inside the block that already exists.
  • Know how to recover. A broken config means editing config/config.yml from the host or LXC shell, because the web UI won’t be up. Keep a copy of the last good config before every change.

A related lesson: change one thing at a time. I once added a person filter and extra tracked labels together, Frigate became unstable, and I reverted both. I still don’t know which one caused it.

7. Upgrades: disk space and the stable tag

Frigate images are 7–8 GB. A pull lands alongside the image you’re already running, and old layers stick around after. On a 20 GB LXC root filesystem, that fills up roughly every second version bump. My 0.18.2 pull ran out of space mid-extract.

This matters more than it sounds. Frigate’s config directory, including its SQLite database, sits on that root filesystem. A full disk risks corrupting the database, even though recordings on separate storage are fine.

My upgrade routine now:

  1. Back up config.yml, and with the stack stopped, frigate.db.
  2. Check df -h / before pulling. You need the image size free.
  3. Edit only the version part of the image: line, keeping the existing suffix.
  4. docker compose pull && docker compose up -d
  5. Once it’s running properly, docker image prune -a. That reclaimed 7.5 GB for me once.

And one trap: don’t switch to the stable tag as a shortcut while running a newer version. When I checked, stable still pointed at 0.17.x, and the 0.18 database can’t roll back. Betas also ship as GitHub pre-releases, so they don’t appear on the default releases page.

8. Logs in UTC, everything else in local time

Frigate and Docker container logs are in UTC. Proxmox graphs, pct, the task list and host journalctl -k are in host local time. In the UK summer, that’s an hour apart.

So a container log line at 10:51 lines up with 11:51 on the Proxmox graphs. I drew two wrong conclusions in one session about what caused what before I noticed. Normalise the times before you claim anything happened before anything else.

Adding TZ=Europe/London (or your zone) to the Compose environment helps with Frigate’s own maintenance scheduling, but check which clock each log is actually using.

The short version

If you’re running Frigate in Docker inside a Proxmox LXC, check these before you go hunting for anything clever:

  • Accelerators passed through with Proxmox devN entries, not major-number rules
  • GPU via runtime: nvidia and the two environment variables
  • Only one compose file, and it matches the running container
  • At least 8 GiB of RAM for the container if you run embeddings or more than a few cameras
  • audio role on the stream that actually carries audio
  • Substream frame rate matched to detect.fps
  • YAML snippets merged into existing blocks, one change at a time
  • Free disk space checked before every pull, old images pruned after
  • Log timestamps normalised before drawing conclusions

Most of these cost me an evening each. None of them were Frigate’s fault.

Strategic Horizon Mapping: A Workshop Framework for Product Teams Who Need to See Beyond the Next Quarter

How to build defensible roadmaps that stop executive whiplash and give your team strategic breathing room


If you’re a Product Owner, Product Manager, or Customer Journey lead, you’ve probably lived this nightmare:

You’ve got a solid roadmap for the next 9 months. Your backlog is prioritized. Your team knows what they’re building and why. Then an executive returns from a conference, reads an analyst report, or has a conversation with a customer, and suddenly you’ve got a new “top priority” that blows up everything you’d planned.

Your team groans. You scramble to justify why this new thing should wait (or shouldn’t happen at all). The executive pushes back: “But we need to do this.” You don’t have a compelling counter-argument because you haven’t looked that far ahead. So you rebuild the roadmap, again, and watch team morale take another hit.

The problem isn’t bad executives. The problem is strategic blindness beyond your current planning horizon.

Product teams who can only see 9-12 months ahead are vulnerable to every shiny object, competitive panic, and strategic pivot that comes along. They’re playing defense because they haven’t done the work to play offense.

This is the workshop framework I developed to fix that. It’s designed to be run every 6 months with product teams, takes about half a day, and produces something more valuable than another roadmap: a defensible strategic position.

The Problem This Solves

Before we get to the framework, let’s be clear about what we’re solving for:

Symptom 1: Roadmap Whiplash Your team builds for Q1-Q3, then in Q2 someone throws in a Q4 priority that invalidates half your assumptions.

Symptom 2: Reactive Strategy Every new requirement feels equally urgent because you haven’t mapped out what’s coming or why it matters.

Symptom 3: Lost Team Autonomy Your team wants to own their roadmap but can’t defend it against executive-level course corrections because they lack strategic framing.

Symptom 4: Guesswork Masquerading as Planning You know you need to think further ahead, but “horizon scanning” sounds like expensive consultancy theatre rather than practical product work.

More

The Abundance Paradox: Why Having Enough Is Never Enough

I spent decades struggling financially. The kind of struggle where every decision comes with a calculation, where “enough” felt like a distant fantasy rather than an achievable state. Then something shifted. Through partnership, shared resources, and finally earning a stable income, I found myself in a place I’d never been before: financially secure.

You’d think that would be the happy ending. In many ways, it is. But reaching this vantage point has revealed something deeply unsettling about human nature and our collective future. I should be upfront about something: I’m writing this from the position of someone who made it across. That’s both my qualification and my limitation. I’ve lived both sides of the scarcity divide, but I’m now firmly on the side that benefits from current systems. The contradiction isn’t lost on me, and I think it’s important to name it before going further.

The Problem With “Enough”

When Elon Musk talks about “sustainable abundance” as humanity’s goal, I understand the appeal. Who wouldn’t want a world where everyone has what they need? But having lived on both sides of the scarcity divide, I’ve come to see a fundamental problem: humans don’t seem wired to accept “enough.”

The research backs this up. Studies on the “hedonic treadmill” show that we quickly adapt to improved circumstances, returning to baseline happiness levels regardless of material gains. Daniel Kahneman’s work suggested that daily emotional well-being plateaus around a certain income threshold, beyond which more money doesn’t make you meaningfully happier. Yet people who reach that threshold rarely stop accumulating. There’s always a next goal, a next purchase, a next milestone.

This isn’t a moral failing. It’s evolutionary legacy. For hundreds of thousands of years, the humans who survived were the ones who gathered more, stored more, protected more. Loss aversion became hardwired into our psychology because resources genuinely were scarce and unpredictable. The pain of losing something feels much sharper than the pleasure of gaining it, driving us to accumulate buffers far beyond immediate need.

But there’s more to it than just survival instinct. Possessions signal status, competence, and social position. They become part of our identity. Even when our basic needs are met, we continue competing for relative position rather than absolute well-being. My own experience taught me that money isn’t happiness, but it does provide security. And that security, especially when you have a young family depending on you, drives decisions in ways that pure logic never could.

But Are We Really This Way?

Here’s where I want to push back on my own thinking. The “selfish, acquisitive human” might be less universal than we assume. Anthropologists studying pre-agricultural societies have documented vastly different relationships with material goods. Marshall Sahlins called hunter-gatherers “the original affluent society”, not because they had much, but because their wants were limited and easily satisfied. They worked surprisingly little, shared abundantly, and accumulated almost nothing.

The shift to agriculture, paradoxically, may have introduced our scarcity mindset by creating storable surplus, inheritable property, and the possibility of inequality at scale. We’ve spent so long in this system that we’ve forgotten it wasn’t always the human condition.

Even today, the acquisitive, individualist human is largely a product of what researchers call WEIRD cultures = Western, Educated, Industrialized, Rich, and Democratic. These represent maybe 12% of the global population but dominate behavioral research and shape our assumptions about human nature. Other cultures organize themselves around very different values: collective well-being, harmony with nature, intergenerational responsibility.

This matters because it means we’re not necessarily stuck with our current programming. We’ve changed before. We could change again. The challenge is that the cultural shifts required tend to operate on geological timescales compared to the urgency of our current problems.

Victims of Our Own Progress

That said, we’ve built systems that reward short-term self-interest so thoroughly that asking people to act for long-term collective benefit feels almost naive. The “what’s in it for me” mindset isn’t irrational when everyone else operates that way. It’s adaptive.

Profiteering deepens this trap. Entire industries exist to maintain problems rather than solve them. Planned obsolescence, treating symptoms rather than causes, creating artificial scarcity in the midst of plenty. The incentive structure actually punishes genuine solutions if they threaten established revenue streams.

There’s another wrinkle worth understanding: the Jevons Paradox. Named after the 19th-century economist who observed that more efficient steam engines led to more coal consumption, not less, this principle keeps appearing throughout history. LED lighting was supposed to reduce energy use; instead we lit up more things. Cars became more fuel-efficient; we drove them further. The internet was supposed to reduce travel; it created new reasons to travel. Make something cheaper or more accessible, and we tend to consume more of it, often wiping out the gains.

This is the dark mirror of sustainable abundance. The very efficiency that might enable it could also accelerate consumption beyond any environmental limit. Technology alone won’t save us; the mindset using the technology has to change too. Otherwise we just become more efficient at destroying the conditions for our own flourishing.

The Status Problem

Even if we somehow achieved material abundance, we’d run into a problem that abundance alone can’t solve: status is inherently zero-sum. You can’t have everyone be above average. You can’t have everyone live in the “best” neighborhood or have the most prestigious job. As long as we measure ourselves against each other, scarcity will be manufactured even where material plenty exists.

This is why purely material solutions to inequality often fail. Give everyone the same income and people will compete for the right addresses, the right schools, the right experiences. Give everyone the same house and we’ll compete for who can renovate it most impressively. The competition simply migrates to whatever dimension still allows for differentiation.

This isn’t a counsel of despair – it’s a reminder that the real work isn’t just material. It’s about what we value and how we measure our lives. Star Trek’s vision works not because of replicators but because the culture has somehow shifted toward valuing exploration, mastery, and contribution over hierarchy and accumulation. The technology is incidental; the value system is everything.

The Environmental Reckoning

Nature has spent millions of years developing complex systems built on balance and constraint. Remove those constraints, and you might get runaway consumption that devastates ecosystems in ways we haven’t even considered. The “just get another” mentality could be more dangerous in a world of abundance than scarcity ever was.

My own understanding of scarcity taught me about hard work and resourcefulness. If abundance came without that struggle, would we value things differently? Would we develop the carelessness that comes with assumed plenty?

What’s striking is that the environmental crisis isn’t really a technology problem anymore. We largely know what to do. Renewable energy is cheaper than fossil fuels in many contexts. Sustainable agriculture techniques exist. Circular economy models work where they’re tried. The bottleneck is human, not technical. We have the tools; we lack the collective will and the system that would deploy them at scale.

What History Actually Shows Us

The few historical examples of large value shifts required both crisis and generational change. The gradual abolition of slavery, the expansion of civil rights, the recognition of women as full citizens – these transformations took generations and were met with enormous resistance.

But here’s something worth holding onto: some value shifts have happened faster than anyone expected. Same-sex marriage moved from unthinkable to widely accepted in less than a generation in many countries. Smoking went from glamorous to socially marginalised in decades. The Overton window (what counts as acceptable public opinion) can shift more quickly than we assume when conditions align.

There are also genuine bright spots worth acknowledging. Extreme poverty globally has fallen dramatically over the past 30 years. The B Corp movement is creating businesses with explicit social purposes alongside profit motives. Cities like Amsterdam are experimenting with “doughnut economics” – staying within ecological ceilings while ensuring social foundations. Costa Rica achieves quality of life comparable to wealthy nations on a fraction of the resource consumption. Bhutan measures Gross National Happiness alongside GDP. The cooperative movement employs hundreds of millions of people globally in democratically-owned enterprises.

None of these are solutions to everything. But they suggest the future isn’t predetermined. People are experimenting with different ways to organize human life, and some of those experiments are working. The dominant system isn’t the only possible system – it just feels that way because it’s so all-encompassing.

The AI Question

We’re also at an inflection point that adds a new dimension to all of this. AI could go either way – it could turbocharge the existing acquisitive system, concentrating wealth and power in unprecedented ways, or it could genuinely create conditions for abundance that previous generations couldn’t imagine.

The honest answer is that nobody knows which way it will go, and the outcome depends heavily on the values of the people deploying it. If AI development continues to be driven primarily by competitive logic and short-term profit, we’ll likely get more efficient versions of our current problems. If it’s deployed with genuine concern for human flourishing and ecological balance, the possibilities are different.

This is happening now, while we’re having this conversation. Whatever values we bring to bear in the next decade will shape the technology that shapes the next century. That’s both terrifying and clarifying – it means these abstract conversations about values have very concrete stakes, very soon.

The Trap We Can’t Escape

I can see this paradox clearly, but I’m unsure how to escape it. There would need to be a seismic shift in attitudes toward value itself. A motion away from financial reward and toward intrinsic worth. A fundamental reorientation of what we consider success.

But here’s the cruel irony: how do you change value systems when the current system actively selects against the very changes you need? A person who tries to live by intrinsic values often gets economically punished or socially marginalized within current structures. The system keeps generating people who are shaped by extrinsic rewards, creating a self-perpetuating cycle.

There’s a tension in being stuck in the middle of this. I can see the trap. I try to change things in my own sphere of influence, showing my kids that there are better ways to look at the world. But I often feel like I’m shouting into the void, knowing it’ll have only an infinitesimally small impact.

And there’s a deeper honesty I have to acknowledge: I’m writing this from inside the system, benefiting from it. My children’s security comes from my engagement with the very structures I’m critiquing. This isn’t hypocrisy exactly, but it is the human condition right now. None of us reading or writing this is outside the system we’re trying to change. That’s both humbling and clarifying – change has to come from people who are part of what needs changing, not from some imaginary position of purity outside it.

A Call for Species-Level Thinking

What strikes me most about our current moment is how urgently we need action, yet how divided we remain by class, race, politics, and agendas. These divisions are real and deserve attention, but they’re also distractions from a more fundamental truth: we’re all the same species facing the same existential challenges.

We need to bring ourselves together to solve this massive, complex problem. Not in some distant future when conditions are perfect, but now. The coordination required seems almost impossible given our evolutionary programming, yet somehow it’s necessary.

I don’t have solutions. I’m not an expert in economics, psychology, or environmental science. But I’ve lived through the transition from scarcity to security, and that journey has given me perspective on how difficult changing our relationship with resources really is. Even for individuals who can make the shift, it takes time. Trust in sustained abundance requires generational change.

Perhaps what we need isn’t just sustainable abundance, but sustainable purpose. Ways of finding meaning and direction that don’t depend on accumulating scarce resources or dominating others. Education that helps future generations understand both the historical struggle that shaped us and the new capabilities that could reshape us. Economic systems that channel competitive drives toward genuinely beneficial ends rather than wasteful consumption.

The question isn’t whether these ideas are important enough to discuss. Given what’s at stake for our species, they’re too important not to. Even if only a handful of people engage with these thoughts and shift their thinking slightly, that’s a start. The cultural changes we need aren’t going to happen through one viral essay or one charismatic leader – they happen through millions of small conversations and decisions that slowly shift what feels normal, possible, and worth pursuing.

Change is possible, just not in any timeframe that feels relevant to the urgency we face. But perhaps that’s exactly why we need to start the conversation now, with whatever voice we have, wherever we are, with whoever will listen.