What actually runs on it
Everything here runs on two always-on machines at home in Denmark. No cluster, no orchestrator, no rack — just Docker Compose and a file of YAML I actually understand.
One machine holds the services: git, a password vault, the dashboard, and the tunnel that lets any of it be reached at all. The second exists to run things I do not trust, inside virtual machines it destroys afterwards.
Some of it is reachable from the internet. Most of it deliberately is not, and the difference is a decision made per service rather than a default.
- Open ports
- 0
- Machines
- 2
- Certificates to renew
- 0
- Monthly bill
- electricity
Services
Private Git
PrivateSelf-hosted Forgejo. Repositories, issues and pull requests on hardware I own, rather than handed to someone else. Sign-ups are disabled and every page requires authentication — it exists for exactly one user, and it is not linked from here.
- Forgejo
- SQLite
- Docker
Password vault
PublicA Bitwarden-compatible vault, reachable only through the tunnel. It also holds the encrypted bundle of every other secret in here, which turns rebuilding the whole setup into a restore rather than an excavation.
- Vaultwarden
- Docker
Task worker
PublicHands a job to a throwaway virtual machine, lets it work, then destroys the machine. Link and mail analysis, dev chores, container builds. The sandbox gets filtered egress and no route back inward, because the whole point is running things I would not run on a real host.
- Incus
- FastAPI
- Cloudflare Access
Dashboard
Local onlyContainer health, host resources, backup history and tunnel state on one pane of glass. Kept off the internet on purpose: it reads the Docker API, and nothing that can enumerate containers belongs on a public hostname.
- Homepage
- docker-socket-proxy
- Dozzle
Cloudflare Tunnel
PublicHow anything gets in at all. The server dials out and holds the connection open, so there is no port forwarding, no static IP, and nothing on the router listening for strangers.
- cloudflared
- QUIC
Backups
PrivateBoth machines snapshot themselves nightly and push offsite, encrypted before anything leaves the house. Verified by actually restoring and cloning from the result — an untested backup is a rumour, not a backup.
- restic
- rclone
- systemd timers
Pep-talk
PrivateA Fantasy Premier League helper. Each week it works out what to do with the team — transfers, captain, bench — from the numbers rather than a hunch. Built for one manager, hosted here, not published.
- Fantasy Premier League
- Docker
This site
PublicThe page you are reading. Static files served by nginx on the server, rebuilt straight from the git repository a few minutes after anything lands on the default branch. It reaches you the same way everything else here does — down the tunnel. No third-party host, no build service.
- Astro
- nginx
- Docker
No open ports, anywhere
The usual way to self-host is to forward a port on the router and hope. This does the opposite: the server dials out to Cloudflare and keeps that connection open. Traffic arrives down a pipe the server itself opened, so there is nothing inbound to find, scan or brute-force.
- 01
Your browser
Asks for a hostname on notacloudserver.net.
- 02
Cloudflare edge
Terminates TLS. Certificates are its problem, not mine.
- 03
Encrypted tunnel
A QUIC connection the server opened, outbound.
- 04
cloudflared
A container on the server holding the other end.
- 05
The service
Answers on the Docker network. Never on the router.
The whole thing, listed
- Hosts
- Two x86 machines, always on
- Service OS
- Debian 13 (trixie)
- Worker OS
- Arch, Wayland, tiling
- Runtime
- Docker Engine + Compose
- Sandboxing
- Incus containers and VMs, thrown away after use
- Ingress
- Cloudflare Tunnel, outbound only
- Edge auth
- Cloudflare Access, one-time PIN
- Version control
- Self-hosted Forgejo
- Dashboard
- Homepage, with per-container logs
- Backups
- restic to object storage, nightly
- Secrets
- age-encrypted bundle, held in the vault
- This site
- Astro, rebuilt on a timer, served by nginx
- Open ports
- Zero