Tier 1, start to finish
Build the box in an afternoon
A shopping list, three commands, and a kit for each room of the house. Nothing exposed to the internet. Copy, paste, done before dinner.
This is the fastest path from nothing to a working Tier 1 box. It doesn’t replace the guides — they explain the why and the trade-offs — but if you already know you want this, here it is in order. Every kit is a tiny, independent compose.yml; skip any you don’t want.
1. Buy (one evening of searching, a few days of shipping)
Pick one:
- A used mini PC — search for “mini PC N100 16GB” or any small-form-factor office PC with an 8th-generation-or-newer Intel chip, 16 GB of RAM and a 500 GB+ SSD. Typically $150–250 used. This is the better buy: x86 means every piece of software exists for it, and it idles at the power draw of a night light.
- A Raspberry Pi 5, 8 GB, with the official power supply and an NVMe HAT or a USB SSD (don’t run this off a microSD). About $120–160 all in. Everything below works; AI and camera detection will be slow.
Plus: an external USB drive (a 4 TB one is around $100) for photos and media, and, if you’ll do the smart home, a $30 Zigbee USB stick. Prices are rough and dated October 2026.
2. Base (20 minutes)
Install the current Ubuntu Server LTS (Raspberry Pi Imager on a Pi; a USB stick made with the official installer on a mini PC). Enable SSH during setup. Log in and run these three lines:
sudo apt update && sudo apt install -y docker.io docker-compose-v2 && sudo usermod -aG docker $USER && newgrp docker
curl -fsSL https://tailscale.com/install.sh | sh && sudo tailscale up
sudo apt install -y unattended-upgrades
The first installs Docker (which runs every kit). The second joins the box to your private network — install the Tailscale app on your phone and laptop too, sign in with the same account, and they can reach the box from anywhere with nothing opened on your router. The third keeps the OS patched on its own.
Make a folder for everything: mkdir -p ~/box /srv/media — the kits live in ~/box, your movies and music in /srv/media.
3. Pick your kits (10 minutes each)
Each one: run the single command, open the address, click through the setup screen. Addresses are http://box:PORT on your own network (replace box with the machine’s name or IP).
Backups — do this one first
Download compose.ymlEncrypted off-site backups with a web interface. Choose a storage bucket you rent (any S3-compatible one works), set a nightly schedule, point it at the folders the other kits create, and do a test restore of one file before you trust it.
mkdir -p ~/box/backups && cd ~/box/backups && curl -fsSLo compose.yml https://de-clouding.com/kits/backups.yml && docker compose up -dWhat's in it
# de-clouding.com kit: encrypted off-site backups with a web UI (Backrest, which runs restic)
# Point a plan at /userdata, set a schedule, choose a bucket you rent, and do the test restore.
services:
backrest:
image: garethgeorge/backrest:latest
container_name: backrest
hostname: backrest
restart: unless-stopped
volumes:
- ./backrest/data:/data
- ./backrest/config:/config
- ./backrest/cache:/cache
- ./backrest/tmp:/tmp
- /home:/userdata/home:ro # what to back up: add more lines like these
- /srv/media:/userdata/media:ro
environment:
- BACKREST_DATA=/data
- BACKREST_CONFIG=/config/config.json
- XDG_CACHE_HOME=/cache
- TMPDIR=/tmp
- TZ=America/New_York
ports:
- "9898:9898"
Check: open http://box:9898, add a repository and a plan, run it once, restore one file.
Network filtering and bedtime schedules
Download compose.ymlA DNS filter for the whole house: ads and trackers gone, and per-device schedules for the kids’ consoles. On Ubuntu, free up port 53 first: sudo mkdir -p /etc/systemd/resolved.conf.d && printf '[Resolve]\nDNS=1.1.1.1\nDNSStubListener=no\n' | sudo tee /etc/systemd/resolved.conf.d/adguard.conf && sudo systemctl restart systemd-resolved. Then point your router’s DNS at the box.
mkdir -p ~/box/dns && cd ~/box/dns && curl -fsSLo compose.yml https://de-clouding.com/kits/dns.yml && docker compose up -dWhat's in it
# de-clouding.com kit: DNS filtering and schedules (AdGuard Home)
# Before starting on Ubuntu: free port 53 from systemd-resolved (see the page).
services:
adguardhome:
image: adguard/adguardhome
container_name: adguardhome
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "3000:3000/tcp" # setup wizard, then the admin UI (choose port 3000 in the wizard)
volumes:
- ./adguard/work:/opt/adguardhome/work
- ./adguard/conf:/opt/adguardhome/conf
Check: open http://box:3000, finish the wizard, then nslookup example.com box answers.
Photos
Immich publishes its own compose file and asks you to use it rather than a hand-written one, so this kit is their official download:
mkdir -p ~/box/photos && cd ~/box/photos
curl -fsSLo compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
curl -fsSLo .env https://github.com/immich-app/immich/releases/latest/download/example.env
nano .env # set UPLOAD_LOCATION to a folder on your big drive, and DB_PASSWORD to something long
docker compose up -d
Check: open http://box:2283, create the admin account, install the Immich app on your phone and point it at http://box:2283 (or the Tailscale address below), turn on backup.
Passwords
Download compose.ymlVaultwarden speaks the Bitwarden protocol, so the official Bitwarden apps and browser extensions work against your own box. Those apps require HTTPS, which is what step 4 gives you — do step 4 for this one before creating your account, and set DOMAIN in the file to that address.
mkdir -p ~/box/passwords && cd ~/box/passwords && curl -fsSLo compose.yml https://de-clouding.com/kits/passwords.yml && docker compose up -dWhat's in it
# de-clouding.com kit: passwords (Vaultwarden, speaks the Bitwarden protocol)
# Browser extensions need HTTPS: reach this through `tailscale serve` (see the page)
# and set DOMAIN to that https:// address before you create your account.
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- DOMAIN=https://CHANGE-ME.your-tailnet.ts.net:8443
- SIGNUPS_ALLOWED=true # set to false after everyone in the house has an account
volumes:
- ./vaultwarden:/data
ports:
- "8080:80"
Check: open the HTTPS address from step 4, create your account, then set SIGNUPS_ALLOWED=false in the file and run docker compose up -d again.
Files in sync, no company in the middle
Download compose.ymlSyncthing keeps folders identical across your laptop, phone and the box, device to device. Install the Syncthing app on each device and pair them with the box by scanning the QR code.
mkdir -p ~/box/sync && cd ~/box/sync && curl -fsSLo compose.yml https://de-clouding.com/kits/sync.yml && docker compose up -dWhat's in it
# de-clouding.com kit: file sync between your own devices (Syncthing, no server account)
services:
syncthing:
image: syncthing/syncthing
container_name: syncthing
hostname: box
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
volumes:
- ./syncthing:/var/syncthing
ports:
- "8384:8384" # web UI
- "22000:22000/tcp" # sync
- "22000:22000/udp"
- "21027:21027/udp" # discovery on your own network
Check: open http://box:8384, set a password under Settings, add a folder, pair a device.
Music, movies and TV you own
Download compose.ymlJellyfin serves whatever you put in /srv/media to every screen in the house. Jellyfin apps exist for every TV, phone and tablet.
mkdir -p ~/box/media && cd ~/box/media && curl -fsSLo compose.yml https://de-clouding.com/kits/media.yml && docker compose up -dWhat's in it
# de-clouding.com kit: music, movies and TV you own (Jellyfin)
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
restart: unless-stopped
volumes:
- ./jellyfin/config:/config
- ./jellyfin/cache:/cache
- /srv/media:/media:ro # put your library here (or change the left side)
ports:
- "8096:8096"
# On an Intel mini PC, uncomment to let the GPU convert video for phones:
# devices:
# - /dev/dri:/dev/dri
Check: open http://box:8096, finish the wizard, add /media as a library.
Smart home brain
Download compose.ymlHome Assistant, container edition. Plug in the Zigbee stick before starting. Devices on your network are discovered automatically; cloud-only ones show up as integrations that ask for the vendor login — you decide.
mkdir -p ~/box/home && cd ~/box/home && curl -fsSLo compose.yml https://de-clouding.com/kits/home.yml && docker compose up -dWhat's in it
# de-clouding.com kit: smart home brain (Home Assistant, container flavor)
# For the long run, Home Assistant OS on its own device is the nicer experience; this gets you started.
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: homeassistant
restart: unless-stopped
privileged: true # lets it see a Zigbee/Z-Wave USB stick
network_mode: host # lets it discover devices on your network
environment:
- TZ=America/New_York # change to your time zone
volumes:
- ./homeassistant:/config
- /run/dbus:/run/dbus:ro
Check: open http://box:8123, create the account, let it discover.
The kids' Minecraft server, friends-only
Download compose.ymlEdit the WHITELIST line with your kids’ Minecraft usernames before starting. Nobody not on the list can join, ever. Friends joining from their houses: easiest is their parent installing Tailscale and you sharing the box with them; the kids guide has the other options. Consoles need the extra step described there.
mkdir -p ~/box/minecraft && cd ~/box/minecraft && curl -fsSLo compose.yml https://de-clouding.com/kits/minecraft.yml && docker compose up -dWhat's in it
# de-clouding.com kit: the family's own Minecraft (Java) server, friends-only from the first boot
# Add a friend later: docker compose exec minecraft rcon-cli whitelist add TheirName
services:
minecraft:
image: itzg/minecraft-server
container_name: minecraft
restart: unless-stopped
tty: true
stdin_open: true
environment:
- EULA=TRUE # you accept Minecraft's EULA by setting this
- TYPE=PAPER
- MEMORY=2G
- ONLINE_MODE=TRUE
- ENFORCE_WHITELIST=TRUE
- WHITELIST=KidOne,KidTwo # Minecraft usernames, comma-separated
- DIFFICULTY=normal
- MOTD=Our house. Friends only.
volumes:
- ./minecraft:/data
ports:
- "25565:25565"
Check: in Minecraft, Multiplayer → Add Server → address box. Add a friend with docker compose exec minecraft rcon-cli whitelist add TheirName.
Your own AI assistant
Download compose.ymlOllama runs the model, Open WebUI gives you the familiar chat page. On a mini PC without a graphics card expect a few words per second from a 3–4 billion-parameter model — slow, but the conversation never leaves the house. After starting, pull a model: docker compose exec ollama ollama pull qwen3:4b (model names change monthly; ask any assistant for a current small one).
mkdir -p ~/box/ai && cd ~/box/ai && curl -fsSLo compose.yml https://de-clouding.com/kits/ai.yml && docker compose up -dWhat's in it
# de-clouding.com kit: your own AI assistant (Ollama + Open WebUI), CPU only
# After it starts, pull a small model: docker compose exec ollama ollama pull qwen3:4b
# (ask any assistant for a current 3–4B model name; they change monthly). Expect a few words per second on a mini PC.
services:
ollama:
image: ollama/ollama
container_name: ollama
restart: unless-stopped
volumes:
- ./ollama:/root/.ollama
ports:
- "11434:11434"
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
restart: unless-stopped
environment:
- OLLAMA_BASE_URL=http://ollama:11434
volumes:
- ./open-webui:/app/backend/data
ports:
- "3001:8080"
depends_on:
- ollama
Check: open http://box:3001, create the first account (it becomes admin), pick the model, say hello.
4. Reach it from anywhere, with HTTPS, with nothing exposed
Tailscale can hand out real HTTPS addresses for things running on the box, visible only to your own devices. In the Tailscale admin console turn on MagicDNS and HTTPS certificates (DNS page), then on the box:
sudo tailscale serve --bg --https=8443 8080 # passwords
sudo tailscale serve --bg --https=2443 2283 # photos
sudo tailscale serve status # shows the https://box.<your-tailnet>.ts.net:PORT addresses
Use those https://…ts.net addresses in the phone apps. Nothing is reachable from the open internet; the router stays closed.
5. Hand the rest to Claude
Finish my Tier 1 box
Fill in the brackets, paste the whole thing into Claude (or any assistant you trust), and let it walk you through the rest one step at a time.
I'm building the "Tier 1 box" from de-clouding.com/box: a small always-on machine running Docker and Tailscale, with independent compose kits for each service and nothing exposed to the internet. My box: [mini PC or Raspberry Pi, RAM, OS version]. Kits I have running so far: [list, e.g. backups, dns, photos]. Kits I still want: [list]. Devices in the house: [phones, laptops, TVs, consoles]. Comfort with computers: [none / some / fluent]. Walk me through the remaining kits one at a time, waiting for me to paste the output of each step before giving the next. For each one: confirm the container is healthy (`docker compose ps`), help me through its first-run screen, set up the phone or TV app that goes with it, and add its data folder to the Backrest backup plan. Then help me publish the ones that need HTTPS through `tailscale serve`, and finish with a test restore of one file from the off-site backup. Keep the router closed: no port forwarding, no "DMZ". Check commands against each project's current documentation before giving them; tell me before anything hard to undo.
Everything here is one file per service on purpose: no installer, no magic, nothing that can break all at once. If a kit stops working because a project changed its compose format, open an issue and it gets fixed for everyone.