The problem with relying on someone else's cloud
GitHub is great. Until you want to host something private that isn't a open-source project.
I have this note directory that contains everything - My journal, financial statements from my budget cli, and sensitive information that shouldn't be on github.
Not to mention I make Youtube videos. Nextcloud would allow me to transfer videos via my personal cloud to my server.
I happened to have a Raspberry Pi too, with an attached 1TB hard drive.
This would bypass file size limits on typical cloud platforms as well as keep my data in my own hands.
What you actually need
A cloud doesn't have to be complicated. Mine is three things:
- NixOS — declarative system configuration, reproducible builds, rollbacks
- Tailscale — mesh VPN so I can access my Pi from anywhere without opening ports to the internet
- Gitea — a lightweight, self-hosted Git service
That's it. No Kubernetes, no Docker Swarm, no load balancers. Just a single board computer running a system I define in code.
I guess you could say my cloud is an aggregation of software, but it works. It is awesome too!
The hardware
A Raspberry Pi 5 with an SD card. That's the hardware.
I know that sounds underwhelming. But for what I need — hosting Git repos, maybe running a few lightweight services — it's more than enough. And the power consumption is negligible compared to keeping a full desktop running 24/7.
The real advantage is that it's always on, always reachable, and costs almost nothing to run.
It's also a fantastic learning experience. One day, when finances are better, you bet I will have a much more substantial setup.
The configuration
This is where NixOS shines. The entire system is defined in a single file:
{ self, inputs, ... }:
let
username = "ben";
hostname = "lab";
addr = "${username}@${hostname}";
systemStateVersion = "25.05";
in {
flake.nixosConfigurations.${hostname} = inputs.nixos-raspberrypi.lib.nixosSystem {
specialArgs = { inherit hostname username; };
modules = [
self.modules.nixos.core
({ pkgs, lib, ... }: {
imports = with inputs.nixos-raspberrypi.nixosModules; [
raspberry-pi-5.base
raspberry-pi-5.bluetooth
sd-image
];
system.stateVersion = systemStateVersion;
networking.useNetworkd = true;
networking.networkmanager.enable = false;
services.tailscale.enable = true;
services.gitea = {
enable = true;
database.type = "sqlite3";
settings.service = {
DISABLE_REGISTRATION = true;
REQUIRE_SIGNIN_VIEW = true;
};
};
networking.firewall = {
allowedTCPPorts = [ 22 3000 80 443 ];
allowedUDPPorts = [ 41641 ];
};
})
];
};
}
There's a lot in there, so let me break it down.
Tailscale
I enable Tailscale and that's it. No port forwarding, no firewall rules for external access. Tailscale creates a private mesh between my devices — my desktop, my laptop, and this Pi are all on the same virtual network. I can SSH into the Pi from anywhere without exposing it to the public internet.
The only firewall ports I open are for Tailscale itself (UDP 41641) and the services running locally.
Gitea
Gitea is the self-hosted GitHub. It's lightweight, fast, and runs perfectly on a Pi. I configure it with:
- SQLite3 — no need for PostgreSQL or MySQL for a single-user instance
- Registration disabled — nobody else can create accounts
- Sign-in required — even viewing repos requires authentication
This means my private repos — like my notes — live on hardware I own, behind authentication I control.
This allows me to have git level control over my notes but store it somewhere (arguably) more secure than GitHub.
The shared modules
Notice self.modules.nixos.core at the top. That's the same core module my desktop and laptop use. It handles:
- user creation
- SSH configuration
- timezone and locale
- core packages (git, neovim, tmux, etc.)
This is the whole point of NixOS flakes. One configuration, shared across devices. My Pi gets the same base setup as my desktop without duplicating anything.
As this is my first server, I had to move some packages around. Certain 'graphical' packages (a server doesn't need programs with graphical interfaces) both at Home Manager and system level were moved to that graphical module. This allows the core collection of packages to be the standard on all my hosts (my hosts are like the server, my laptop, my desktop).
This enables my entire operating system to be under one folder on GitHub, iterative for all my devices. Pretty insane.
What this gives me
A few things I didn't have before:
- Private Git hosting — my financial data and personal projects stay on my hardware
- Remote access — SSH into my Pi from any device, anywhere, through Tailscale
- A platform — the Pi can run more than Gitea. A personal cloud storage, a note syncing service, a home automation hub. The NixOS config makes adding services as simple as enabling them in the configuration
- Reproducibility — if the SD card dies, I pull my config, flash a new card, rebuild, and everything comes back
That last one is what makes NixOS the right choice here. On any other system, rebuilding a server from scratch means remembering every package, every config file, every tweak. On NixOS, it's a nixos-rebuild command, which I even shortened to rebuild for the system level, rehome for home level packages.
What's next
The Pi is running, Gitea is serving repos, and I can reach it from anywhere. But there's more I want to do.
I mentioned in the budget app post that I want encrypted backups to Google Drive. The plan is monthly encrypted snapshots of the Gitea database and repo data, uploaded automatically. Sensitive financial data on my hardware, with a disaster recovery path that doesn't depend on any single provider.
I mentioned in a previous post about encrypting backups for my budget app sqlite database. this also applies to my note directory. Im looking at solutions to compress and encrypt my data on a weekly automated basis. The limits are aound 100gb on any given cloud service, and I want that limit to serve me for a long time.
I also want to explore running more services. Security options for SSH keys, encryption services like mentioned earlier. The beauty of NixOS is that adding a service is just a configuration change — which can be applied on any host for the other.
Is this really a "cloud"?
I've been calling this a personal cloud, and I think that's fair. It's not cloud in the AWS sense — there's no autoscaling, no load balancing, no container orchestration. It's a single board computer in my house.
But it gives me what the cloud promises: access to my data and services from anywhere, without depending on someone else's infrastructure. For a developer or a hobbyist, that might be all you need.
The Raspberry Pi costs about the same as a few months of a cloud hosting subscription. Except once you've bought it, it's yours. No monthly fees, no usage limits, no terms of service to worry about.
If you've been thinking about self-hosting, a Raspberry Pi with NixOS is a genuinely good place to start.
Arguably, the most powerful benefit is the skills you learn along the way. Not many people can say they setup their own cloud service.