# erebe/personal-server: a k3s personal server setup kept in git

> This repository documents one person's self-hosted server: k3s, nginx ingress, cert-manager, Postfix and Dovecot, Nextcloud, Wireguard and a Raspberry Pi node, with secrets encrypted by SOPS and a GPG key. It is a reference build, not a product, and the README is candid about what two years of running it taught the author.

**erebe/personal-server** — Personal server configuration with k3s

- Repository: https://github.com/erebe/personal-server
- Stars: 3,155 · Forks: 168
- Language: HTML
- License: not declared
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/erebe-personal-server

## What problem erebe/personal-server addresses

The README opens with a history rather than a feature list, and that history is the argument. The author moved from Gentoo on scrap hardware behind a parent's telephone line, to Debian with Ansible, to Docker, and describes the failure mode each time: cramming mail, web, gitlab, pop3, imap, torrent, owncloud and munin onto one Debian machine led to unstable repositories and conflicting package versions, until an apt-get upgrade became the nemesis. The stated goals are narrow: simple to deploy, manage and update; everything inside the git repository; automation on free-tier GitHub Actions that is still reproducible locally; and the same packaging path for system applications and the author's own projects.

That last goal is what separates this from a tutorial. A mail server, a Kubernetes control plane and a personal Nextcloud instance are all treated as deployable artifacts in one tree. The audience is a single operator who owns the machine, the domain and the keys, and who is willing to read a long document before typing anything. It is not aimed at a team that needs a supported product with a release cadence.

## The structure of the repository: k8s, services, secrets, nodes

The top level tells you how the author thinks. There is a k8s/ directory for cluster manifests, a services/ directory for the applications, a secrets/ directory for encrypted material, a secrets_decrypted/ directory, a nodes/ directory, plus dns/, config/ and a justfile. The README's table of contents mirrors that split: Part I is the setup (GPG key, SOPS, SSH key, a Makefile, the provider, the base machine, DNS, k3s, nginx ingress, cert-manager), Part II is build and deploy (Postfix with Dovecot, Fetchmail and SpamAssassin, GitHub Actions image builds, webhook deployment, Nextcloud), Part III is reliability (backups, with monitoring marked TODO), and Part IV scales out with Wireguard, WsTunnel, a Raspberry Pi as a k3s node and PiHole.

Two details are worth noting. The updates list records that the iptables configuration was replaced by nftables in July 2023, so the networking layer is not frozen at the 2020 state the title jokes about. And monitoring is still a TODO in the table of contents, which means the observability story in the original document is incomplete. The 2023 epilogue adds sections on security, maintainability, extensibility and observability, so the author revisited those gaps rather than hiding them.

## Installing: the justfile and a first deployment

There is no installer script and no published package. The repository is the distribution: you clone it, and the justfile is the entry point. The install recipe decrypts the SSH key pair and the kubeconfig out of the SOPS-encrypted files and writes them to disk, then appends an SSH client config block if the host is not already present.

```bash
just install
```

Running that recipe executes sops -d against secrets/ssh.yml twice, once for the public key and once for the private key, writing them to ~/.ssh/erebe_eu.pub and ~/.ssh/erebe_eu, then chmod 600 on both. It appends config/ssh_client_config to ~/.ssh/config when erebe.eu is not already there, and decrypts secrets/kubernetes-config.yml into ~/.kube/config. You need a working SOPS setup and the corresponding GPG key before any of this succeeds, because the README's first setup steps are creating the GPG key and encrypting secrets with SOPS.

The second recipe is the deployment path. It reads a secret out of the encrypted webhook file into the environment for the duration of the command, then posts to the author's webhook endpoint with an application name and the image tag latest. The recipe is named release and takes the application name as its argument, so the invocation is just release followed by that name.

```bash
just release
```

The justfile defines this as a shell recipe: sops exec-env services/secrets/webhook.yml 'echo ${DEPLOYER_SECRET}' captures the token, then curl -i -X POST sends a JSON body of { "application_name": "{{app}}", "image_tag": "latest" } with a Content-Type of application/json and an X-Webhook-Token header to https://hooks.erebe.eu/hooks/deploy. The hostname in that URL is the author's own, so the recipe as written only works against his infrastructure. You should expect to replace that endpoint, and to check what the receiving side does with image_tag, because the recipe always sends latest.

## Secrets handling and the s3 recipe

The most transferable part of the justfile is the s3 recipe, and its comments are unusually careful about scope. It drops you into a subshell holding the credentials for an S3 endpoint, for poking at restic buckets by hand. Unlike just install, nothing is written to disk: sops exec-env passes the decrypted values through the environment and they die with the shell. The comment warns that the whole of secrets/restic.yml comes along, so both restic repository passwords are in scope, not just the S3 keys, and tells you to treat the shell as holding the keys to both repositories and to exit when done. It gives two example commands, aws s3 ls s3://lisez-next/ and rclone ls s3:lisez-next/nvme.

The recipe also accepts a repository name so that restic runs with no flags, with the comment noting that proxmox does the same thing through /etc/restic/<name>.env. Passing nvme-backup selects one repository; with no argument both remain reachable but neither is selected, and the comment shows the explicit form using restic -r "$RESTIC_NEXTCLOUD_REPOSITORY" with a password-command of printf %s "$RESTIC_NEXTCLOUD_PASSWORD". A second variant points at a self-hosted gateway, versitygw, instead of the offsite provider. This is the pattern worth stealing: decrypted secrets live in one shell, never in a file, and the recipe documents which repositories a stray command can reach.

## Where this setup breaks down

The repository does not state a licence. For a tree that contains a full mail server configuration and deployment automation, that is a real gap: you cannot tell what you are permitted to reuse, and the README does not address it. Treat the code as something to read and reimplement rather than copy wholesale until that is resolved.

The webhook deployment is the second constraint. The release recipe posts to a single hardcoded hostname and always sends image_tag latest, so there is no built-in notion of promoting a specific build or rolling back to a previous tag. The README does not document rollback. If your deployments need staged promotion or an audit trail of which image is live, this mechanism is the wrong shape.

The third is the operational surface itself. The author's own 2023 epilogue exists because two years of running the setup produced feedback on security, maintainability, extensibility and observability, and monitoring is still listed as a TODO in the table of contents. A mail server with Postfix, Dovecot, Fetchmail and SpamAssassin is not a component you install once; deliverability, blocklists and TLS certificate renewal are ongoing. If nobody on the team wants to own that, do not put mail in this cluster. Finally, the Raspberry Pi node joins through the Wireguard VPN, so the cluster's reach depends on that tunnel staying up.

## How it compares with Ansible and with a managed platform

The README itself is the comparison. The author ran Ansible before this and describes the integration between systemd and Docker as weird, with time spent gluing trivial things. The difference here is not that k3s is better than Ansible; it is that the unit of deployment becomes a container image plus a manifest, so a system application and a personal project ship the same way. Ansible converges a machine's state from a description of packages and files. This repository converges a cluster's state from images and YAML, and keeps the encrypted inputs in the same tree.

The other alternative is a managed platform or a hosted mail and cloud provider. That removes the certificate, backup and deliverability work entirely, at the cost of the thing the README's opening argues for: keeping the data and the compute under your own control. The author frames the whole project against reliance on centralized providers, quoting a 2007 talk about the internet losing its decentralized nature. If that motivation is not yours, the maintenance burden of this setup buys you very little.

## Maintenance, upgrades and the licence question

The last push to the repository was on 2026-09-23, so the tree is current. The updates list shows a pattern of revisiting components rather than leaving them: nftables replaced iptables in July 2023, DNS over HTTPS was added for PiHole in September 2021, and healthchecks.io pings were added for backups in December 2020. A renovate.json file sits at the top level, which suggests dependency updates are automated through Renovate. The release list contains a single entry, a custom vsmtp build dated 2023-02-25, so the release mechanism is not the primary distribution channel; the git history is.

Upgrade cost is therefore the cost of tracking upstream projects yourself: k3s, nginx ingress, cert-manager, Postfix, Dovecot, Nextcloud, Wireguard and the rest each move on their own schedule. Nothing here describes a supported upgrade path between versions of this repository. On licensing, the repository does not declare one, and the README does not discuss licence implications for the components it installs. Several of those components carry their own licences, including the mail stack and Nextcloud, so check each upstream project separately before you build on this. That is a factual gap, not legal advice.

## Conclusion

Adopt this as a reading list and a source of file layouts if you already run Linux, own a domain and want the whole configuration under version control; the repository gives you a working shape for SOPS, k3s and a justfile-driven install rather than a template you clone and boot. Do not adopt it if you want a supported installer, a licence you can read, or a mail server you can hand to someone else to operate. Before copying anything, verify the licence, since the repository does not state one, and confirm that the SOPS and GPG keys you plan to use are ones you control, because the entire secrets workflow assumes the private key never leaves your machine.

## FAQ

### What does erebe/personal-server actually do?

It is a documented configuration for running a personal server on k3s, covering GPG and SOPS secret management, DNS automation, Debian and k3s installation, nginx ingress with cert-manager, a Postfix and Dovecot mail server, Nextcloud, backups, Wireguard and a Raspberry Pi node. The README describes it as one person's setup rather than a distributable product.

### How do I set up erebe/personal-server?

Clone the repository and run the install recipe from the justfile, which decrypts the SSH key pair and kubeconfig from SOPS-encrypted files into ~/.ssh and ~/.kube. That requires a working SOPS setup and the matching GPG key first, since the README's setup order is GPG key, then SOPS, then SSH.

### How much does running a personal server with this setup cost?

No figures appear in the README. It describes choosing a server provider, a registrar for DNS, and using free-tier GitHub Actions for image builds, but it states no prices for hosting, domains or hardware.

### How do I make a personal server like erebe/personal-server?

The README lays out the order: create a GPG key, encrypt secrets with SOPS, generate an SSH key, automate installation with a Makefile, choose a provider and a registrar, then install k3s and add nginx ingress with cert-manager. Application deployment comes after that, through the justfile release recipe.

### What is a personal server?

In this project it means a machine you own and operate yourself, hosting your own mail, cloud storage, DNS and backups, with the configuration kept in a git repository. The README frames it as an alternative to relying on centralized providers for data and compute.

## Sources

- [erebe/personal-server on GitHub](https://github.com/erebe/personal-server)
- [Issues](https://github.com/erebe/personal-server/issues)
- [README](https://github.com/erebe/personal-server/blob/master/README.md)
- [Releases](https://github.com/erebe/personal-server/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/erebe-personal-server
