homelab framework module init (everything is a mess)
This commit is contained in:
parent
0347f4d325
commit
bcbcc8b17b
94 changed files with 7289 additions and 436 deletions
|
|
@ -1,17 +0,0 @@
|
|||
🥇 Phase 1: Git + Secrets
|
||||
|
||||
✅ Set up Forgejo VM (NixOS declarative)
|
||||
|
||||
✅ Set up sops-nix + age keys (can live in the Git repo)
|
||||
|
||||
✅ Push flake + ansible + secrets to Forgejo
|
||||
|
||||
✅ Write a basic README with how to rebuild infra
|
||||
|
||||
🥈 Phase 2: GitOps
|
||||
|
||||
🔁 Add CI runner VM
|
||||
|
||||
🔁 Configure runner to deploy (nixos-rebuild or ansible-playbook) on commit
|
||||
|
||||
🔁 Optional: add webhooks to auto-trigger via Forgejo
|
||||
|
|
@ -18,7 +18,7 @@ in {
|
|||
stateDir = "/srv/forgejo";
|
||||
secrets = {
|
||||
mailer = {
|
||||
PASSWD = ;
|
||||
PASSWD = config.sops.secrets.forgejo-mailer-password.path;
|
||||
};
|
||||
};
|
||||
settings = {
|
||||
|
|
@ -76,12 +76,12 @@ in {
|
|||
ALLOW_DEACTIVATE_ALL = false;
|
||||
};
|
||||
|
||||
oauth2 = {
|
||||
};
|
||||
oauth2_client = {
|
||||
ENABLE_AUTO_REGISTRATION = true;
|
||||
UPDATE_AVATAR = true;
|
||||
};
|
||||
# oauth2 = {
|
||||
# };
|
||||
# oauth2_client = {
|
||||
# ENABLE_AUTO_REGISTRATION = true;
|
||||
# UPDATE_AVATAR = true;
|
||||
# };
|
||||
# log = {
|
||||
# ROOT_PATH = "/var/log/forgejo";
|
||||
# MODE = "file";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
let
|
||||
forgejoSops = ../../secrets/forgejo/secrets.yml;
|
||||
in
|
||||
{
|
||||
in {
|
||||
sops.secrets = {
|
||||
"forgejo-admin-password" = {
|
||||
sopsFile = forgejoSops;
|
||||
|
|
@ -15,5 +14,9 @@ in
|
|||
sopsFile = forgejoSops;
|
||||
owner = "forgejo";
|
||||
};
|
||||
"forgejo-mailer-password" = {
|
||||
sopsFile = forgejoSops;
|
||||
owner = "forgejo";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,13 @@
|
|||
middlewares = [];
|
||||
};
|
||||
|
||||
roundcube = {
|
||||
rule = "Host(`roundcube.procopius.dk`)";
|
||||
service = "roundcube";
|
||||
entryPoints = ["websecure"];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
|
||||
forgejo = {
|
||||
rule = "Host(`git.procopius.dk`)";
|
||||
service = "forgejo";
|
||||
|
|
@ -34,10 +41,4 @@
|
|||
entryPoints = ["websecure"];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
catchAll = {
|
||||
rule = "HostRegexp(`.+`)";
|
||||
service = "nginx";
|
||||
entryPoints = ["websecure"];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
traefik.loadBalancer.servers = [{url = "http://localhost:8080";}];
|
||||
|
||||
mail-acme.loadBalancer.servers = [{url = "http://mail.lab:80";}];
|
||||
roundcube.loadBalancer.servers = [{url = "http://mail.lab:80";}];
|
||||
|
||||
forgejo.loadBalancer.servers = [{url = "http://forgejo.lab:3000";}];
|
||||
proxmox.loadBalancer.servers = [{url = "https://192.168.1.205:8006";}];
|
||||
proxmox.loadBalancer.serversTransport = "insecureTransport";
|
||||
nas.loadBalancer.servers = [{url = "https://192.168.1.226:5001";}];
|
||||
nas.loadBalancer.serversTransport = "insecureTransport";
|
||||
nginx.loadBalancer.servers = [{url = "https://192.168.1.226:4433";}];
|
||||
nginx.loadBalancer.serversTransport = "insecureTransport";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,4 +32,52 @@
|
|||
entryPoints = ["websecure"];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
|
||||
ente-minio = {
|
||||
rule = "Host(`ente-minio.procopius.dk`)";
|
||||
service = "ente-minio";
|
||||
entryPoints = ["websecure"];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
ente-minio-api = {
|
||||
rule = "Host(`ente-minio-api.procopius.dk`)";
|
||||
service = "ente-minio-api";
|
||||
entryPoints = ["websecure"];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
|
||||
ente-museum = {
|
||||
rule = "Host(`ente-museum.procopius.dk`)";
|
||||
service = "ente-museum";
|
||||
entryPoints = ["websecure"];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
|
||||
ente-photos = {
|
||||
rule = "Host(`ente-photos.procopius.dk`) || Host(`ente-albums.procopius.dk`)";
|
||||
service = "ente-photos";
|
||||
entryPoints = ["websecure"];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
|
||||
ente-cast = {
|
||||
rule = "Host(`ente-cast.procopius.dk`) ";
|
||||
service = "ente-cast";
|
||||
entryPoints = ["websecure"];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
|
||||
ente-accounts = {
|
||||
rule = "Host(`ente-accounts.procopius.dk`) ";
|
||||
service = "ente-accounts";
|
||||
entryPoints = ["websecure"];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
|
||||
ente-auth = {
|
||||
rule = "Host(`ente-auth.procopius.dk`) ";
|
||||
service = "ente-auth";
|
||||
entryPoints = ["websecure"];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,4 +4,12 @@
|
|||
account.loadBalancer.servers = [{url = "http://192.168.1.226:3001";}];
|
||||
minio.loadBalancer.servers = [{url = "http://192.168.1.226:3201";}];
|
||||
minio-api.loadBalancer.servers = [{url = "http://192.168.1.226:3200";}];
|
||||
|
||||
ente-minio.loadBalancer.servers = [{url = "http://photos.lab:9001";}];
|
||||
ente-minio-api.loadBalancer.servers = [{url = "http://photos.lab:9000";}];
|
||||
ente-museum.loadBalancer.servers = [{url = "http://photos.lab:8080";}];
|
||||
ente-photos.loadBalancer.servers = [{url = "http://photos.lab:3000";}];
|
||||
ente-accounts.loadBalancer.servers = [{url = "http://photos.lab:3001";}];
|
||||
ente-cast.loadBalancer.servers = [{url = "http://photos.lab:3004";}];
|
||||
ente-auth.loadBalancer.servers = [{url = "http://photos.lab:3003";}];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,127 +0,0 @@
|
|||
Great question — and you're absolutely right to ask.
|
||||
|
||||
You **don’t need** Innernet or Headscale+patch *if* you're comfortable building a small self-hosted portal that handles:
|
||||
|
||||
* ✅ OIDC login
|
||||
* ✅ WireGuard peer key management
|
||||
* ✅ Config generation and download
|
||||
|
||||
So let’s break it down:
|
||||
|
||||
---
|
||||
|
||||
## 🧩 Why *Innernet* and *Headscale+patch* Exist
|
||||
|
||||
Those tools solve **user/device coordination**, dynamic routing, and access control *automatically*, **with batteries included**. They're great if you want a more managed, “plug-and-play” experience. Specifically:
|
||||
|
||||
| Tool | Purpose |
|
||||
| ------------------------ | ----------------------------------------------------------------- |
|
||||
| **Innernet** | Full WireGuard-based mesh + OIDC login + per-device management |
|
||||
| **Headscale** | Tailscale backend, enables user login + ACL + device coordination |
|
||||
| **Headscale+OIDC patch** | Add OIDC login to Headscale (by default, only pre-shared keys) |
|
||||
|
||||
These tools do things like:
|
||||
|
||||
* Assign IPs/DNS names to users
|
||||
* Regenerate keys
|
||||
* Handle coordination between peers
|
||||
* Gate access with identity
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Why You *Don’t* Need Them (Your Custom Portal Idea)
|
||||
|
||||
If you're fine with:
|
||||
|
||||
* Managing WireGuard server and IPs manually
|
||||
* Writing a small web service to issue `.conf` files after login
|
||||
* Using firewall rules for access control
|
||||
|
||||
Then you absolutely **can** build a custom system around **WireGuard + OIDC** like this:
|
||||
|
||||
---
|
||||
|
||||
### 🧱 Architecture: WireGuard + OIDC + Config Generator
|
||||
|
||||
```
|
||||
┌──────────────┐
|
||||
│ Your OIDC │
|
||||
│ provider │◄────── Google, Authentik, Keycloak
|
||||
└─────┬────────┘
|
||||
│
|
||||
(OIDC Login)
|
||||
│
|
||||
┌────────▼────────┐
|
||||
│ Web Portal │◄────── nginx + Go, Node.js, Flask, etc.
|
||||
│ (self-hosted) │
|
||||
└──┬────────────┬─┘
|
||||
Gen Keys │ │ Serve config
|
||||
& register │ └─────> `client.conf` / QR code
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ WireGuard server │ (NixOS)
|
||||
│ - Handles all peers │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔐 What Your Portal Needs to Do
|
||||
|
||||
* Authenticate via OIDC (OAuth2 flow)
|
||||
* Store a list of "authorized users"
|
||||
* When a user logs in:
|
||||
|
||||
* Check if they already have a WireGuard peer entry
|
||||
* If not: generate a keypair, assign IP (e.g. `10.100.0.5`)
|
||||
* Append to server config (`/etc/wireguard/wg0.conf`) or use `wg set`
|
||||
* Return config file or QR code for the mobile client
|
||||
|
||||
---
|
||||
|
||||
## ✅ Benefits of This DIY Approach
|
||||
|
||||
* 💡 Full control: you own every step
|
||||
* 🔐 OIDC is the gatekeeper (centrally managed access)
|
||||
* ⚡ No extra daemon/software overhead (just WireGuard + your app)
|
||||
* 🧩 Easily extensible (e.g., device limits, IP lease expiration)
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Tools You Can Use
|
||||
|
||||
| Purpose | Tools |
|
||||
| ---------------------- | -------------------------------------------------------------------------- |
|
||||
| OIDC Auth | [Dex](https://github.com/dexidp/dex), Keycloak, Authentik, or Firebase |
|
||||
| Web Portal Backend | Node.js (Express), Go, Flask, FastAPI |
|
||||
| Config Template Engine | Go templates, EJS, Jinja2 |
|
||||
| WireGuard Integration | `wg`, `wg-quick`, or directly edit `wg0.conf` |
|
||||
| NixOS Support | Use `networking.wireguard.interfaces.wg0.peers` to declaratively add peers |
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Bonus Features You Could Build
|
||||
|
||||
* 🔐 Per-user firewall rules
|
||||
* 🔁 One-time config URLs (`vpn.mydomain.com/invite/xyz`)
|
||||
* 🔐 Optional Authelia/Keycloak MFA
|
||||
* 📉 Dashboard with currently active peers (use `wg show`)
|
||||
|
||||
---
|
||||
|
||||
## ✨ Summary
|
||||
|
||||
| Option | You Need Innernet / Headscale? | Login via OIDC? | DNS Routing? | Complexity |
|
||||
| ----------------- | ------------------------------ | --------------- | ------------ | ---------- |
|
||||
| Your own portal | ❌ No | ✅ Yes | ❌ Manual | 🟡 Medium |
|
||||
| Innernet | ✅ Yes | ✅ Yes | ✅ Built-in | 🟠 Medium |
|
||||
| Headscale + patch | ✅ Yes | ✅ Yes | ✅ Built-in | 🔴 High |
|
||||
|
||||
You’re on a great path by choosing the custom VPN portal idea.
|
||||
Let me know if you'd like:
|
||||
|
||||
* A **sample architecture repo**
|
||||
* A **NixOS module to support peer configs**
|
||||
* Help building the **login + config generator backend**
|
||||
|
||||
I can generate a Nix flake and a working OIDC portal template to kickstart the project.
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
virtualisation.oci-containers.containers = {
|
||||
warpgate = {
|
||||
image = "ghcr.io/warp-tech/warpgate";
|
||||
ports = [
|
||||
"2222:2222"
|
||||
"8888:8888"
|
||||
];
|
||||
volumes = [
|
||||
"/srv/warpgate/data:/data"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue