Self-Hosting Everything on a Gaming Laptop

Self-Hosting Everything on a Gaming Laptop

How I run 40+ services on a Lenovo laptop with Proxmox — from media automation and document management to a full smart home. A tour of my self-hosted infrastructure.

I pay for nothing. No Google Drive, no LastPass, no Todoist, no streaming service middleman. Every piece of software that manages my life runs on a laptop sitting on a shelf in my apartment. A gaming laptop, specifically — one that was too loud for gaming and too powerful to just sit there.

This is the story of how a $900 Lenovo LOQ became the backbone of my digital life, running 2 virtual machines, 6 LXC containers, and 36 Docker services. From media automation and document management to smart home control and AI-powered morning briefings.

Why Self-Host?

The pitch for self-hosting usually comes in three flavors: privacy, learning, and cost. For me, it was all three, but they hit in that order.

Privacy came first. I’m a developer — I know what happens to data once you hand it to a company. Terms of service change. Acquisitions happen. “We value your privacy” is a sentence that precedes every single privacy violation. I wanted my passwords, my documents, my bookmarks, and my budget to live on hardware I control.

Learning came next. I’d been working with containers and infrastructure professionally, but there’s a difference between deploying someone else’s architecture and building your own from scratch. Self-hosting forces you to understand networking, DNS, reverse proxies, authentication flows, storage, and monitoring — not in theory, but in practice, at 2 AM when your SSL cert expired and nothing loads.

Cost sealed it. I tallied up my subscriptions one day: cloud storage, password manager, media services, note-taking apps, budgeting tools. It wasn’t catastrophic, but it was $50-70/month for services I could run myself. The laptop paid for itself in under a year.

Where It Started

My first “server” was a Raspberry Pi 3 — the $35 credit card-sized computer that launched a thousand homelabs. I installed Plex, Jackett, and Transmission on it, set up Samba for network shares, and convinced myself I had a media server. I also used it to play retro games through RetroArch — SNES, GBA, PS1 — and to watch movies on my TV. Or at least, I tried.

The Pi 3 has a quad-core ARM CPU clocked at 1.2 GHz and 1 GB of RAM. Plex transcoding was a slideshow. Jackett searches took forever. Transmission would choke if more than two torrents ran simultaneously. RetroArch was actually the thing it handled best — emulating a 1994 console on 2016 hardware was well within its means, but anything beyond PS1 was pushing it.

Still, that tiny board taught me more about Linux, networking, and self-hosting than any tutorial ever could. I learned to SSH into a headless machine, configure Samba shares, set up port forwarding, troubleshoot file permissions, and accept that 1 GB of RAM is not enough for anything. When I eventually outgrew it, I didn’t stop self-hosting — I just needed more power.

The Machine

Most homelabbers run a Dell OptiPlex, an old enterprise server, or a purpose-built NAS. I run a Lenovo LOQ 15IRH8 — a gaming laptop. Here’s why that’s not as crazy as it sounds.

SpecDetails
CPUIntel i7-13620H — 10 cores, 16 threads, up to 4.9 GHz
RAM16 GB DDR5
Storage1 TB NVMe SSD (LVM thin provisioning)
NetworkBuilt-in Gigabit Ethernet + Wi-Fi 7 (unused)
Power~35W idle with screen off

A laptop as a server has a few underrated advantages:

  • Built-in UPS. The battery keeps everything running during power outages. No external UPS needed. When the power goes out at 3 AM, my Home Assistant automations don’t miss a beat.
  • Built-in display. When something goes wrong at the hypervisor level, I don’t need to hunt for a monitor and cable. I open the lid.
  • Silent when idle. With the screen off and no GPU load, the fans rarely spin up. It’s quieter than a NAS.
  • Compact. It sits on a shelf. No rack, no dedicated space needed.

The tradeoffs are real — limited RAM expandability, single NVMe slot, laptop thermals under sustained load. But for my workload, 16 GB and 1 TB have been enough for two years.

Architecture Overview

The entire stack runs on Proxmox VE, a Debian-based hypervisor that manages virtual machines and LXC containers. Proxmox uses LVM thin provisioning on the 1 TB NVMe, which means I can over-provision storage and only consume actual disk space as data is written.

The Virtualization Strategy

I use three tiers of isolation, each chosen for a reason:

Virtual Machines — for workloads that need their own kernel or OS. Unraid needs to manage its own storage stack. Home Assistant OS ships as a complete appliance image with its own supervisor, add-on system, and update mechanism — it’s designed to run as a VM.

LXC Containers — for services that benefit from near-native performance without full VM overhead. Jellyfin gets its own LXC because media transcoding is CPU-intensive and I don’t want it competing for resources with 30 other containers. AdGuard Home runs in an LXC because DNS needs to be rock-solid and isolated. n8n gets its own container because workflow automation can occasionally eat surprising amounts of memory.

Docker Containers — for everything else. The bulk of my services run as Docker containers inside a single LXC (ID 101), managed through Portainer. Docker is perfect for stateless or semi-stateless services where the overhead of a full LXC isn’t justified.

Storage Layout

The 1 TB NVMe is partitioned with LVM:

PartitionSizePurpose
EFI1 GBBoot partition
pve-root96 GBProxmox OS
pve-swap8 GBSwap space
pve-data816 GBThin pool for VMs, LXCs, and containers

Each VM and LXC gets a thin-provisioned disk from the pool. Unraid’s VM has no pre-allocated disk because it manages its own virtual drives. The Docker LXC (101) gets 52 GB for all container data and volumes.

!RAM is the Real Constraint

With 16 GB of RAM shared across 2 VMs, 6 LXCs, and 36 Docker containers, memory management matters. Home Assistant OS gets 4 GB, Unraid gets 2 GB, and the rest share what’s left. Swap usage hovers around 7 GB during peak load — not ideal, but stable. The next upgrade will be more RAM, not more storage.

Network & Access

The Router

Everything connects through a TP-Link Archer BE800 — a Wi-Fi 7 tri-band router. It’s overkill for a homelab, but it’s what I use for daily life too. The Proxmox server connects via Ethernet, and IoT devices (smart home sensors, cameras) connect to a dedicated IoT Wi-Fi network.

DNS & Ad Blocking

AdGuard Home (LXC 200) serves as the network-wide DNS server. Every device on the network resolves DNS through it, which means:

  • Ads and trackers are blocked at the DNS level — no browser extensions needed
  • I get visibility into what every device on the network is querying
  • Local DNS entries point service.local hostnames to internal IPs

Reverse Proxy & Domains

Nginx Proxy Manager handles all reverse proxying. I own a domain through Cloudflare, and each service gets its own subdomain. NPM terminates SSL with Let’s Encrypt certificates and routes traffic to the correct container.

The flow looks like this:

User → volc.men → Cloudflare DNS → My IP (DDNS) → Router → NPM → Service

Cloudflare DDNS runs as a Docker container that monitors my public IP and updates the DNS records whenever it changes. No static IP needed.

Some services are public-facing (accessible from anywhere via domain), while others are local-only (accessible only on the home network or via Twingate).

Remote Access

Twingate provides zero-trust remote access to services I don’t want exposed to the public internet. Instead of opening ports or running a VPN server, Twingate creates encrypted tunnels from my devices to specific services. I can access my Proxmox dashboard, Portainer, or DBGate from anywhere without exposing them.

The Services

Storage: Unraid (VM 100)

Unraid runs as a VM and acts as the central NAS. It serves SMB and NFS shares to other VMs and containers — media libraries for Jellyfin, document storage for Paperless, general file storage for everything else. With only a virtual disk inside Proxmox for now, the plan is to eventually pass through physical drives when I expand storage.

Media Stack

The media stack is the most interconnected part of the setup. Here’s how the pieces fit together:

ServiceRole
Jellyfin (LXC 102)Media server — streams movies, shows, music to any device
SonarrTV show automation — monitors, downloads, organizes series
RadarrMovie automation — same as Sonarr but for films
ProwlarrIndexer manager — centralizes search across sources
JackettIndexer proxy — additional source support
SeerrRequest system — lets household members request media
DelugeTorrent client — handles downloads
RecyclarrQuality profiles — syncs TRaSH Guides quality settings to Sonarr/Radarr
AudiobookshelfAudiobook and podcast server with progress tracking
LavaMusic + LavalinkDiscord music bot for playing music in voice channels

The flow: someone requests a movie through Seerr → Radarr picks it up → Prowlarr/Jackett search for it → Deluge downloads it → Radarr renames and organizes it → Jellyfin detects and serves it. Fully automated.

Recyclarr deserves special mention — it automatically applies community-maintained quality profiles from TRaSH Guides, ensuring optimal file quality and naming conventions without manual configuration.

Document Management: Paperless-NGX

Paperless-NGX is one of the most life-changing services in the stack. Every document — bills, receipts, contracts, medical records — gets scanned or uploaded, OCR’d, tagged, and made searchable.

The document pipeline:

ServiceRole
Paperless-NGXCore document management — ingest, OCR, tag, archive
Paperless-AIAI-powered automatic tagging and categorization
Apache TikaContent extraction from complex file formats
GotenbergPDF generation and conversion
MeiliSearchFast full-text search across all documents

I drop a PDF into the consumption folder (or email it to a dedicated address), and minutes later it’s OCR’d, auto-tagged by the AI, and searchable. Two years of paperwork, fully digitized and instantly findable.

Productivity

ServiceWhat It Does
LinkwardenBookmark manager with full-page archiving — never lose a link to link rot
VikunjaTask and project management — Todoist replacement
n8n (LXC 106)Workflow automation — connects services, triggers actions, processes data
Changedetection.ioMonitors websites for changes — price drops, content updates, availability
HomepageDashboard that shows all services at a glance with live status and stats

Changedetection runs with Selenium and SockPuppetBrowser as headless browser backends, so it can monitor JavaScript-rendered pages that simple HTTP requests would miss.

Finance & Home

ServiceWhat It Does
Actual BudgetEnvelope-style budgeting — tracks spending, sets goals, imports transactions
WallosSubscription tracker — monitors recurring costs and alerts before renewals
GrocyHousehold management — grocery lists, pantry inventory, chore tracking

Security & Authentication

Authentik is the SSO (Single Sign-On) identity provider. Instead of managing separate accounts for every service, I sign in once through Authentik, and it handles authentication for Paperless, Linkwarden, Vikunja, Beszel, and others via OAuth2/OIDC.

Vaultwarden is a self-hosted Bitwarden-compatible password manager. Every password, TOTP code, and secure note lives here. It syncs across all my devices through the standard Bitwarden clients.

Monitoring & Maintenance

ServiceRole
BeszelLightweight server monitoring — CPU, RAM, disk, network graphs
WatchtowerAutomatic container updates — pulls new images and recreates containers
Portainer CEDocker management UI — deploy, monitor, and manage all containers
DBGateDatabase management GUI — inspect and query PostgreSQL directly

Supporting Services

Behind the scenes, several services keep everything running:

  • PostgreSQL — primary database for Authentik, Linkwarden, Paperless, and others
  • Redis — caching and session storage for Authentik and other services
  • MeiliSearch — full-text search engine (currently used by Paperless)
  • Gotenberg — document-to-PDF conversion for Paperless
  • Apache Tika — content extraction from Word docs, emails, and other formats
  • Selenium + SockPuppetBrowser — headless browsers for Changedetection

Smart Home: Home Assistant

Home Assistant OS runs as a dedicated VM (103) with 4 GB of RAM. It’s the brain of the apartment — controlling lights, climate, curtains, cameras, and appliances through a mix of Zigbee devices (via Zigbee2MQTT), Wi-Fi smart home products, and IR blasters.

It runs 42+ automations covering motion-activated adaptive lighting, AI-powered morning briefings via Telegram, automated climate control, smart curtain scheduling, vacuum coordination, and security camera alerts. The whole thing is tied together with a custom dashboard using the Frosted Glass theme, Mushroom chips, and Bubble Card.

I wrote a dedicated deep-dive on the Home Assistant setup — the Zigbee network, every automation, the dashboard, and the troubleshooting I did along the way. Read the full Home Assistant article here.

Troubleshooting & Fixes

Self-hosting isn’t all smooth sailing. Here are some real issues I hit and how I fixed them.

Authentik + Linkwarden: The Missing Email

After setting up Authentik as the SSO provider for Linkwarden, I discovered that Linkwarden requires an email address on the user record — but OAuth login through Authentik created users without one. Linkwarden silently broke on certain operations.

The fix was surgical: connect directly to the database and update the user record.

psql -U postgres

# Connect to the Linkwarden database
\c linkwarden

# Check the current state
SELECT * FROM "User";

# Set the missing email
UPDATE "User"
SET email = 'your@email.com'
WHERE id = '1';
-- Or by username:
UPDATE "User"
SET email = 'your@email.com'
WHERE username = 'yourusername';

Not elegant, but effective. This is a one-time fix — subsequent logins preserve the email.

Beszel + Authentik: Email Verification Scope

Beszel requires the email scope to either return email_verified: true or omit the field entirely. As of Authentik 2025.10, the default behavior returns email_verified: false, which causes Beszel to reject the authentication.

The fix: create a custom scope mapping in Authentik.

  1. Open Authentik Admin → CustomizationProperty MappingsCreate
  2. Select type: Scope Mapping
  3. Set scope name to email
  4. Set the expression to:
return {
    "email": user.email,
    "email_verified": True,
}
  1. Assign this custom mapping to the Beszel OAuth provider, replacing the default email scope.

This tells Beszel that the email is verified (it is — Authentik manages our users), and authentication works.

iGeneral Pattern

When integrating services with Authentik, always check what the service expects from OIDC scopes. Many apps have opinionated requirements about email verification, username format, or group membership. Authentik’s custom property mappings are the escape hatch — you can make the token return whatever the consuming service needs.

What I’ve Learned

Two years of self-hosting on a laptop has taught me a few things:

Start with the problem, not the solution. It’s tempting to deploy every shiny self-hosted app you see on r/selfhosted. But the services that actually stick are the ones that solve a real problem you have today. Paperless-NGX solved my drowning-in-documents problem. Actual Budget solved my where-did-my-money-go problem. Half the services I tried and removed were solutions looking for a problem.

LXC containers are underrated. Most homelab guides default to either full VMs or Docker for everything. LXCs hit a sweet spot — near-native performance with proper isolation, and they’re lighter than VMs. For services like Jellyfin (CPU-intensive transcoding) or AdGuard Home (needs to be bulletproof), the overhead of a full VM isn’t justified but the isolation from other containers is.

Monitoring matters more than you think. Beszel and the energy monitoring in Home Assistant have caught issues I would have missed — a container silently eating RAM, the water heater running for 3+ hours, a DNS query spike from a misbehaving device. You can’t fix what you can’t see.

Document everything as you go. Future you will not remember why you set that custom scope mapping in Authentik or which port Paperless uses. I learned this the hard way after rebuilding a container and spending hours re-discovering my own configuration.

16 GB of RAM is enough. Barely. With 7 GB of swap in use during peak load, I’m clearly pushing the limits. Everything works, but there’s no headroom for experimentation. The laptop supports 32 GB — that’s the most impactful upgrade I could make.


This setup has been running 24/7 for over two years on a laptop that cost less than most people’s annual subscription bills. It handles my media, my documents, my passwords, my budget, my smart home, and my morning news. Every byte of data lives on my shelf, in my apartment, under my control.

Is it more work than paying for cloud services? Absolutely. Is it worth it? Every single time I don’t see an ad, don’t get a “we’ve updated our privacy policy” email, or don’t wonder where my data ended up — yes.