dump
This commit is contained in:
parent
6ba25b90a9
commit
0f49c6c37c
35 changed files with 747 additions and 120 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
> Auto-generated documentation for the homelab deployment
|
> Auto-generated documentation for the homelab deployment
|
||||||
>
|
>
|
||||||
> Generated on: Wed, 30 Jul 2025 02:13:08 +0200
|
> Generated on: Wed, 30 Jul 2025 02:30:55 +0200
|
||||||
> Source: /home/plasmagoat/homelab
|
> Source: /home/plasmagoat/homelab
|
||||||
|
|
||||||
## 📚 Documentation Files
|
## 📚 Documentation Files
|
||||||
|
|
@ -44,7 +44,7 @@ homelab-generate-docs /path/to/output
|
||||||
|
|
||||||
- **Total Nodes**: 2
|
- **Total Nodes**: 2
|
||||||
- **Homelab-Enabled Nodes**: 2
|
- **Homelab-Enabled Nodes**: 2
|
||||||
- **Generated**: Wed, 30 Jul 2025 02:13:11 +0200
|
- **Generated**: Wed, 30 Jul 2025 02:30:59 +0200
|
||||||
|
|
||||||
## 🛠️ Management Tools
|
## 🛠️ Management Tools
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
> Current homelab deployment configuration
|
> Current homelab deployment configuration
|
||||||
>
|
>
|
||||||
> Generated on: Wed, 30 Jul 2025 02:13:01 +0200
|
> Generated on: Wed, 30 Jul 2025 02:30:45 +0200
|
||||||
> Working directory: /home/plasmagoat/homelab
|
> Working directory: /home/plasmagoat/homelab
|
||||||
|
|
||||||
## Deployment Summary
|
## Deployment Summary
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
> Auto-generated fleet overview
|
> Auto-generated fleet overview
|
||||||
>
|
>
|
||||||
> Generated on: Wed, 30 Jul 2025 02:12:41 +0200
|
> Generated on: Wed, 30 Jul 2025 02:30:24 +0200
|
||||||
> Source: /home/plasmagoat/homelab
|
> Source: /home/plasmagoat/homelab
|
||||||
|
|
||||||
## Fleet Statistics
|
## Fleet Statistics
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
> Detailed per-node configuration
|
> Detailed per-node configuration
|
||||||
>
|
>
|
||||||
> Generated on: Wed, 30 Jul 2025 02:12:50 +0200
|
> Generated on: Wed, 30 Jul 2025 02:30:33 +0200
|
||||||
|
|
||||||
## Node: photos
|
## Node: photos
|
||||||
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
| Service | Enabled | Port | Description | Tags |
|
| Service | Enabled | Port | Description | Tags |
|
||||||
|---------|---------|------|-------------|------|
|
|---------|---------|------|-------------|------|
|
||||||
|
| `example` | ❌ | 1234 | Example Homelab Service | |
|
||||||
| `gatus` | ❌ | 8080 | Gatus Status Page | |
|
| `gatus` | ❌ | 8080 | Gatus Status Page | |
|
||||||
| `grafana` | ❌ | 3000 | Grafana Metrics Dashboard | |
|
| `grafana` | ❌ | 3000 | Grafana Metrics Dashboard | |
|
||||||
| `minio` | ✅ | 9000 | minio | |
|
| `minio` | ✅ | 9000 | minio | |
|
||||||
|
|
@ -61,6 +62,7 @@
|
||||||
|
|
||||||
| Service | Enabled | Port | Description | Tags |
|
| Service | Enabled | Port | Description | Tags |
|
||||||
|---------|---------|------|-------------|------|
|
|---------|---------|------|-------------|------|
|
||||||
|
| `example` | ❌ | 1234 | Example Homelab Service | |
|
||||||
| `gatus` | ✅ | 8080 | Gatus Status Page | |
|
| `gatus` | ✅ | 8080 | Gatus Status Page | |
|
||||||
| `grafana` | ✅ | 3000 | Grafana Metrics Dashboard | |
|
| `grafana` | ✅ | 3000 | Grafana Metrics Dashboard | |
|
||||||
| `minio` | ❌ | 9000 | minio | |
|
| `minio` | ❌ | 9000 | minio | |
|
||||||
|
|
|
||||||
111
docs/services.md
111
docs/services.md
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
> Complete service documentation with core options, feature integrations, and smart defaults
|
> Complete service documentation with core options, feature integrations, and smart defaults
|
||||||
>
|
>
|
||||||
> Generated on: Wed, 30 Jul 2025 02:12:53 +0200
|
> Generated on: Wed, 30 Jul 2025 02:30:36 +0200
|
||||||
|
|
||||||
This document provides comprehensive documentation for homelab services, organized by:
|
This document provides comprehensive documentation for homelab services, organized by:
|
||||||
- **Core Service Options**: The main service configuration
|
- **Core Service Options**: The main service configuration
|
||||||
|
|
@ -11,12 +11,13 @@ This document provides comprehensive documentation for homelab services, organiz
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
**Total Available Services:** 4
|
**Total Available Services:** 5
|
||||||
|
|
||||||
## Service Integration Matrix
|
## Service Integration Matrix
|
||||||
|
|
||||||
| Service | Core Options | Monitoring | Logging | Proxy | Deployments |
|
| Service | Core Options | Monitoring | Logging | Proxy | Deployments |
|
||||||
|---------|--------------|------------|---------|-------|-------------|
|
|---------|--------------|------------|---------|-------|-------------|
|
||||||
|
| `example` | 5 | 📊 | 📝 | 🔀 | 0 |
|
||||||
| `gatus` | 11 | 📊 | 📝 | 🔀 | 1 |
|
| `gatus` | 11 | 📊 | 📝 | 🔀 | 1 |
|
||||||
| `grafana` | 3 | 📊 | 📝 | 🔀 | 1 |
|
| `grafana` | 3 | 📊 | 📝 | 🔀 | 1 |
|
||||||
| `minio` | 4 | ❌ | ❌ | ❌ | 1 |
|
| `minio` | 4 | ❌ | ❌ | ❌ | 1 |
|
||||||
|
|
@ -26,6 +27,112 @@ This document provides comprehensive documentation for homelab services, organiz
|
||||||
|
|
||||||
## Service Documentation
|
## Service Documentation
|
||||||
|
|
||||||
|
### example
|
||||||
|
|
||||||
|
**Deployment Status:** 0/2 nodes have this service enabled
|
||||||
|
|
||||||
|
#### Core Service Options
|
||||||
|
|
||||||
|
The main configuration options for example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
homelab.services.example = {
|
||||||
|
description = Example Homelab Service; # No description
|
||||||
|
enable = false; # Whether to enable Example Homelab Service.
|
||||||
|
openFirewall = true; # Whether to open the ports specified in `port` and `webPort` in the firewall.
|
||||||
|
port = 1234; # No description
|
||||||
|
systemdServices = [
|
||||||
|
"example.service",
|
||||||
|
"example"
|
||||||
|
]; # Systemd services to monitor
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Feature Integrations
|
||||||
|
|
||||||
|
##### 📊 Monitoring Integration
|
||||||
|
|
||||||
|
Available monitoring options:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
homelab.services.example = {
|
||||||
|
# ... core options above ...
|
||||||
|
|
||||||
|
monitoring.enable = true; # Enable monitoring for example
|
||||||
|
monitoring.extraLabels = {}; # No description
|
||||||
|
monitoring.healthCheck.conditions = [
|
||||||
|
"[STATUS] == 200"
|
||||||
|
]; # Health check conditions. Setting conditions enables health checks.
|
||||||
|
monitoring.healthCheck.enable = true; # No description
|
||||||
|
monitoring.healthCheck.extraChecks = []; # Additional health checks. Adding checks enables health monitoring.
|
||||||
|
# monitoring.healthCheck.path = <null or string>; # Health check endpoint path. Setting this enables health checks.
|
||||||
|
monitoring.metrics.enable = false; # No description
|
||||||
|
monitoring.metrics.extraEndpoints = []; # Additional metrics endpoints. Adding endpoints enables metrics collection.
|
||||||
|
# monitoring.metrics.path = <null or string>; # Metrics endpoint path. Setting this enables metrics collection.
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**example sets these monitoring defaults:**
|
||||||
|
```nix
|
||||||
|
enable = true;
|
||||||
|
extraLabels = {};
|
||||||
|
healthCheck = {"conditions":["[STATUS] == 200"],"enable":true,"extraChecks":[],"path":null};
|
||||||
|
metrics = {"enable":false,"extraEndpoints":[],"path":null};
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 📝 Logging Integration
|
||||||
|
|
||||||
|
Available logging options:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
homelab.services.example = {
|
||||||
|
# ... core options above ...
|
||||||
|
|
||||||
|
logging.enable = false; # Enable logging for example
|
||||||
|
logging.extraLabels = {}; # No description
|
||||||
|
logging.extraSources = []; # No description
|
||||||
|
logging.files = []; # No description
|
||||||
|
# logging.multiline = <null or (submodule)>; # No description
|
||||||
|
logging.parsing.extractFields = []; # No description
|
||||||
|
# logging.parsing.regex = <null or string>; # No description
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**example sets these logging defaults:**
|
||||||
|
```nix
|
||||||
|
enable = false;
|
||||||
|
extraLabels = {};
|
||||||
|
extraSources = [];
|
||||||
|
files = [];
|
||||||
|
multiline = null;
|
||||||
|
parsing = {"extractFields":[],"regex":null};
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 🔀 Proxy Integration
|
||||||
|
|
||||||
|
Available proxy options:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
homelab.services.example = {
|
||||||
|
# ... core options above ...
|
||||||
|
|
||||||
|
proxy.additionalSubdomains = []; # No description
|
||||||
|
proxy.enable = true; # Enable reverse proxy for example
|
||||||
|
proxy.enableAuth = false; # No description
|
||||||
|
proxy.subdomain = example; # No description
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**example sets these proxy defaults:**
|
||||||
|
```nix
|
||||||
|
additionalSubdomains = [];
|
||||||
|
enable = true;
|
||||||
|
enableAuth = false;
|
||||||
|
subdomain = example;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### gatus
|
### gatus
|
||||||
|
|
||||||
**Deployment Status:** 1/2 nodes have this service enabled
|
**Deployment Status:** 1/2 nodes have this service enabled
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,11 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
# services.loki.enable = true;
|
# services.loki.enable = true;
|
||||||
services.prometheus.enable = true;
|
# services.prometheus.enable = true;
|
||||||
services.grafana.enable = true;
|
# services.grafana.enable = true;
|
||||||
services.gatus.enable = true;
|
# services.gatus.enable = true;
|
||||||
|
services.vaultwarden.enable = true;
|
||||||
|
services.caddy.enable = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
system.stateVersion = "25.05";
|
system.stateVersion = "25.05";
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,5 @@ module "sandbox_vm" {
|
||||||
# You can override any default variable here:
|
# You can override any default variable here:
|
||||||
# cpu_cores = 4
|
# cpu_cores = 4
|
||||||
# memory = 2048
|
# memory = 2048
|
||||||
# disk_size = "10G"
|
disk_size = "10G"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":4,"terraform_version":"1.9.1","serial":16,"lineage":"c76b2921-285f-1904-f2ab-e6a410d16442","outputs":{},"resources":[{"module":"module.sandbox_vm","mode":"managed","type":"proxmox_vm_qemu","name":"nixos-vm","provider":"provider[\"registry.opentofu.org/telmate/proxmox\"]","instances":[{"schema_version":0,"attributes":{"additional_wait":5,"agent":1,"agent_timeout":90,"args":"","automatic_reboot":true,"balloon":0,"bios":"seabios","boot":" ","bootdisk":"","ci_wait":null,"cicustom":null,"cipassword":"$6$rounds=4096$h9zcOYHvB.sy0Ff/$M4cbXjzqmJZ7xRTl3ILWXrg9PePqNzpv.L7MnvMrhcGieK3hrPniU5YEY2Z5/NC1n4QM7VLRSwyP9g9zdjp67/","ciupgrade":true,"ciuser":"root","clone":null,"clone_id":9000,"clone_wait":10,"cores":0,"cpu":[{"affinity":"","cores":2,"flags":[],"limit":0,"numa":false,"sockets":1,"type":"host","units":0,"vcores":0}],"cpu_type":"","current_node":"proxmox-01","default_ipv4_address":"192.168.1.228","default_ipv6_address":"","define_connection_info":true,"desc":"Managed by Terraform.","disk":[],"disks":[{"ide":[{"ide0":[],"ide1":[{"cdrom":[],"cloudinit":[{"storage":"local-lvm"}],"disk":[],"ignore":false,"passthrough":[]}],"ide2":[],"ide3":[]}],"sata":[],"scsi":[],"virtio":[{"virtio0":[{"cdrom":[],"disk":[{"asyncio":"","backup":true,"cache":"","discard":false,"format":"raw","id":0,"iops_r_burst":0,"iops_r_burst_length":0,"iops_r_concurrent":0,"iops_wr_burst":0,"iops_wr_burst_length":0,"iops_wr_concurrent":0,"iothread":false,"linked_disk_id":-1,"mbps_r_burst":0,"mbps_r_concurrent":0,"mbps_wr_burst":0,"mbps_wr_concurrent":0,"readonly":false,"replicate":false,"serial":"","size":"5G","storage":"pv1","wwn":""}],"ignore":false,"passthrough":[]}],"virtio1":[],"virtio10":[],"virtio11":[],"virtio12":[],"virtio13":[],"virtio14":[],"virtio15":[],"virtio2":[],"virtio3":[],"virtio4":[],"virtio5":[],"virtio6":[],"virtio7":[],"virtio8":[],"virtio9":[]}]}],"efidisk":[],"force_create":false,"force_recreate_on_change_of":null,"full_clone":true,"hagroup":"","hastate":"","hostpci":[],"hotplug":"network,disk,usb","id":"proxmox-01/qemu/123","ipconfig0":"ip=dhcp","ipconfig1":null,"ipconfig10":null,"ipconfig11":null,"ipconfig12":null,"ipconfig13":null,"ipconfig14":null,"ipconfig15":null,"ipconfig2":null,"ipconfig3":null,"ipconfig4":null,"ipconfig5":null,"ipconfig6":null,"ipconfig7":null,"ipconfig8":null,"ipconfig9":null,"kvm":true,"linked_vmid":0,"machine":"","memory":1024,"name":"sandbox","nameserver":null,"network":[{"bridge":"vmbr0","firewall":false,"id":0,"link_down":false,"macaddr":"bc:24:11:46:6c:00","model":"virtio","mtu":0,"queues":0,"rate":0,"tag":0}],"numa":false,"onboot":false,"os_network_config":null,"os_type":null,"pci":[],"pcis":[],"pool":"","protection":false,"pxe":null,"qemu_os":"l26","reboot_required":false,"scsihw":"virtio-scsi-single","searchdomain":null,"serial":[{"id":0,"type":"socket"}],"skip_ipv4":false,"skip_ipv6":true,"smbios":[{"family":"","manufacturer":"","product":"","serial":"","sku":"","uuid":"5ae92cdd-a036-4602-af8c-358197f958d9","version":""}],"sockets":0,"ssh_forward_ip":null,"ssh_host":"192.168.1.228","ssh_port":"22","ssh_private_key":null,"ssh_user":null,"sshkeys":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICUP7m8jZJiclZGfSje8CeBYFhX10SrdtjYziuChmj1X plasmagoat@macbook-air\n","startup":"","tablet":true,"tags":"","target_node":"proxmox-01","target_nodes":null,"timeouts":null,"tpm_state":[],"unused_disk":[],"usb":[],"usbs":[],"vcpus":0,"vga":[],"vm_state":"running","vmid":123},"sensitive_attributes":[[{"type":"get_attr","value":"ssh_private_key"}],[{"type":"get_attr","value":"cipassword"}]],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWZhdWx0IjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19"}]}],"check_results":null}
|
{"version":4,"terraform_version":"1.9.1","serial":17,"lineage":"c76b2921-285f-1904-f2ab-e6a410d16442","outputs":{},"resources":[{"module":"module.sandbox_vm","mode":"managed","type":"proxmox_vm_qemu","name":"nixos-vm","provider":"provider[\"registry.opentofu.org/telmate/proxmox\"]","instances":[{"schema_version":0,"attributes":{"additional_wait":5,"agent":1,"agent_timeout":90,"args":"","automatic_reboot":true,"balloon":0,"bios":"seabios","boot":" ","bootdisk":"","ci_wait":null,"cicustom":null,"cipassword":"$6$rounds=4096$h9zcOYHvB.sy0Ff/$M4cbXjzqmJZ7xRTl3ILWXrg9PePqNzpv.L7MnvMrhcGieK3hrPniU5YEY2Z5/NC1n4QM7VLRSwyP9g9zdjp67/","ciupgrade":true,"ciuser":"root","clone":null,"clone_id":9000,"clone_wait":10,"cores":0,"cpu":[{"affinity":"","cores":2,"flags":[],"limit":0,"numa":false,"sockets":1,"type":"host","units":0,"vcores":0}],"cpu_type":"","current_node":"proxmox-01","default_ipv4_address":"192.168.1.228","default_ipv6_address":"2a05:f6c7:2030:0:be24:11ff:fe46:6c00","define_connection_info":true,"desc":"Managed by Terraform.","disk":[],"disks":[{"ide":[{"ide0":[],"ide1":[{"cdrom":[],"cloudinit":[{"storage":"local-lvm"}],"disk":[],"ignore":false,"passthrough":[]}],"ide2":[],"ide3":[]}],"sata":[],"scsi":[],"virtio":[{"virtio0":[{"cdrom":[],"disk":[{"asyncio":"","backup":true,"cache":"","discard":false,"format":"raw","id":0,"iops_r_burst":0,"iops_r_burst_length":0,"iops_r_concurrent":0,"iops_wr_burst":0,"iops_wr_burst_length":0,"iops_wr_concurrent":0,"iothread":false,"linked_disk_id":-1,"mbps_r_burst":0,"mbps_r_concurrent":0,"mbps_wr_burst":0,"mbps_wr_concurrent":0,"readonly":false,"replicate":false,"serial":"","size":"10G","storage":"pv1","wwn":""}],"ignore":false,"passthrough":[]}],"virtio1":[],"virtio10":[],"virtio11":[],"virtio12":[],"virtio13":[],"virtio14":[],"virtio15":[],"virtio2":[],"virtio3":[],"virtio4":[],"virtio5":[],"virtio6":[],"virtio7":[],"virtio8":[],"virtio9":[]}]}],"efidisk":[],"force_create":false,"force_recreate_on_change_of":null,"full_clone":true,"hagroup":"","hastate":"","hostpci":[],"hotplug":"network,disk,usb","id":"proxmox-01/qemu/123","ipconfig0":"ip=dhcp","ipconfig1":null,"ipconfig10":null,"ipconfig11":null,"ipconfig12":null,"ipconfig13":null,"ipconfig14":null,"ipconfig15":null,"ipconfig2":null,"ipconfig3":null,"ipconfig4":null,"ipconfig5":null,"ipconfig6":null,"ipconfig7":null,"ipconfig8":null,"ipconfig9":null,"kvm":true,"linked_vmid":0,"machine":"","memory":1024,"name":"sandbox","nameserver":null,"network":[{"bridge":"vmbr0","firewall":false,"id":0,"link_down":false,"macaddr":"bc:24:11:46:6c:00","model":"virtio","mtu":0,"queues":0,"rate":0,"tag":0}],"numa":false,"onboot":false,"os_network_config":null,"os_type":null,"pci":[],"pcis":[],"pool":"","protection":false,"pxe":null,"qemu_os":"l26","reboot_required":false,"scsihw":"virtio-scsi-single","searchdomain":null,"serial":[{"id":0,"type":"socket"}],"skip_ipv4":false,"skip_ipv6":true,"smbios":[{"family":"","manufacturer":"","product":"","serial":"","sku":"","uuid":"5ae92cdd-a036-4602-af8c-358197f958d9","version":""}],"sockets":0,"ssh_forward_ip":null,"ssh_host":"192.168.1.228","ssh_port":"22","ssh_private_key":null,"ssh_user":null,"sshkeys":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICUP7m8jZJiclZGfSje8CeBYFhX10SrdtjYziuChmj1X plasmagoat@macbook-air\n","startup":"","tablet":true,"tags":"","target_node":"proxmox-01","target_nodes":null,"timeouts":null,"tpm_state":[],"unused_disk":[],"usb":[],"usbs":[],"vcpus":0,"vga":[],"vm_state":"running","vmid":123},"sensitive_attributes":[[{"type":"get_attr","value":"cipassword"}],[{"type":"get_attr","value":"ssh_private_key"}]],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWZhdWx0IjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19"}]}],"check_results":null}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":4,"terraform_version":"1.9.1","serial":15,"lineage":"c76b2921-285f-1904-f2ab-e6a410d16442","outputs":{},"resources":[{"module":"module.sandbox_vm","mode":"managed","type":"proxmox_vm_qemu","name":"nixos-vm","provider":"provider[\"registry.opentofu.org/telmate/proxmox\"]","instances":[{"schema_version":0,"attributes":{"additional_wait":5,"agent":1,"agent_timeout":90,"args":"","automatic_reboot":true,"balloon":0,"bios":"seabios","boot":" ","bootdisk":"","ci_wait":null,"cicustom":null,"cipassword":"","ciupgrade":true,"ciuser":"root","clone":null,"clone_id":9000,"clone_wait":10,"cores":0,"cpu":[{"affinity":"","cores":2,"flags":[],"limit":0,"numa":false,"sockets":1,"type":"host","units":0,"vcores":0}],"cpu_type":"","current_node":"proxmox-01","default_ipv4_address":"192.168.1.228","default_ipv6_address":"2a05:f6c7:2030:0:be24:11ff:fe46:6c00","define_connection_info":true,"desc":"Managed by Terraform.","disk":[],"disks":[{"ide":[{"ide0":[],"ide1":[{"cdrom":[],"cloudinit":[{"storage":"local-lvm"}],"disk":[],"ignore":false,"passthrough":[]}],"ide2":[],"ide3":[]}],"sata":[],"scsi":[],"virtio":[{"virtio0":[{"cdrom":[],"disk":[{"asyncio":"","backup":true,"cache":"","discard":false,"format":"raw","id":0,"iops_r_burst":0,"iops_r_burst_length":0,"iops_r_concurrent":0,"iops_wr_burst":0,"iops_wr_burst_length":0,"iops_wr_concurrent":0,"iothread":false,"linked_disk_id":-1,"mbps_r_burst":0,"mbps_r_concurrent":0,"mbps_wr_burst":0,"mbps_wr_concurrent":0,"readonly":false,"replicate":false,"serial":"","size":"5G","storage":"pv1","wwn":""}],"ignore":false,"passthrough":[]}],"virtio1":[],"virtio10":[],"virtio11":[],"virtio12":[],"virtio13":[],"virtio14":[],"virtio15":[],"virtio2":[],"virtio3":[],"virtio4":[],"virtio5":[],"virtio6":[],"virtio7":[],"virtio8":[],"virtio9":[]}]}],"efidisk":[],"force_create":false,"force_recreate_on_change_of":null,"full_clone":true,"hagroup":"","hastate":"","hostpci":[],"hotplug":"network,disk,usb","id":"proxmox-01/qemu/123","ipconfig0":"ip=dhcp","ipconfig1":null,"ipconfig10":null,"ipconfig11":null,"ipconfig12":null,"ipconfig13":null,"ipconfig14":null,"ipconfig15":null,"ipconfig2":null,"ipconfig3":null,"ipconfig4":null,"ipconfig5":null,"ipconfig6":null,"ipconfig7":null,"ipconfig8":null,"ipconfig9":null,"kvm":true,"linked_vmid":0,"machine":"","memory":1024,"name":"sandbox","nameserver":null,"network":[{"bridge":"vmbr0","firewall":false,"id":0,"link_down":false,"macaddr":"bc:24:11:46:6c:00","model":"virtio","mtu":0,"queues":0,"rate":0,"tag":0}],"numa":false,"onboot":false,"os_network_config":null,"os_type":null,"pci":[],"pcis":[],"pool":"","protection":false,"pxe":null,"qemu_os":"l26","reboot_required":false,"scsihw":"virtio-scsi-single","searchdomain":null,"serial":[{"id":0,"type":"socket"}],"skip_ipv4":false,"skip_ipv6":true,"smbios":[{"family":"","manufacturer":"","product":"","serial":"","sku":"","uuid":"5ae92cdd-a036-4602-af8c-358197f958d9","version":""}],"sockets":0,"ssh_forward_ip":null,"ssh_host":"192.168.1.228","ssh_port":"22","ssh_private_key":null,"ssh_user":null,"sshkeys":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICUP7m8jZJiclZGfSje8CeBYFhX10SrdtjYziuChmj1X plasmagoat@macbook-air\n","startup":"","tablet":true,"tags":"","target_node":"proxmox-01","target_nodes":null,"timeouts":null,"tpm_state":[],"unused_disk":[],"usb":[],"usbs":[],"vcpus":0,"vga":[],"vm_state":"running","vmid":123},"sensitive_attributes":[[{"type":"get_attr","value":"ssh_private_key"}],[{"type":"get_attr","value":"cipassword"}]],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWZhdWx0IjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19"}]}],"check_results":null}
|
{"version":4,"terraform_version":"1.9.1","serial":16,"lineage":"c76b2921-285f-1904-f2ab-e6a410d16442","outputs":{},"resources":[{"module":"module.sandbox_vm","mode":"managed","type":"proxmox_vm_qemu","name":"nixos-vm","provider":"provider[\"registry.opentofu.org/telmate/proxmox\"]","instances":[{"schema_version":0,"attributes":{"additional_wait":5,"agent":1,"agent_timeout":90,"args":"","automatic_reboot":true,"balloon":0,"bios":"seabios","boot":" ","bootdisk":"","ci_wait":null,"cicustom":null,"cipassword":"$6$rounds=4096$h9zcOYHvB.sy0Ff/$M4cbXjzqmJZ7xRTl3ILWXrg9PePqNzpv.L7MnvMrhcGieK3hrPniU5YEY2Z5/NC1n4QM7VLRSwyP9g9zdjp67/","ciupgrade":true,"ciuser":"root","clone":null,"clone_id":9000,"clone_wait":10,"cores":0,"cpu":[{"affinity":"","cores":2,"flags":[],"limit":0,"numa":false,"sockets":1,"type":"host","units":0,"vcores":0}],"cpu_type":"","current_node":"proxmox-01","default_ipv4_address":"192.168.1.228","default_ipv6_address":"","define_connection_info":true,"desc":"Managed by Terraform.","disk":[],"disks":[{"ide":[{"ide0":[],"ide1":[{"cdrom":[],"cloudinit":[{"storage":"local-lvm"}],"disk":[],"ignore":false,"passthrough":[]}],"ide2":[],"ide3":[]}],"sata":[],"scsi":[],"virtio":[{"virtio0":[{"cdrom":[],"disk":[{"asyncio":"","backup":true,"cache":"","discard":false,"format":"raw","id":0,"iops_r_burst":0,"iops_r_burst_length":0,"iops_r_concurrent":0,"iops_wr_burst":0,"iops_wr_burst_length":0,"iops_wr_concurrent":0,"iothread":false,"linked_disk_id":-1,"mbps_r_burst":0,"mbps_r_concurrent":0,"mbps_wr_burst":0,"mbps_wr_concurrent":0,"readonly":false,"replicate":false,"serial":"","size":"5G","storage":"pv1","wwn":""}],"ignore":false,"passthrough":[]}],"virtio1":[],"virtio10":[],"virtio11":[],"virtio12":[],"virtio13":[],"virtio14":[],"virtio15":[],"virtio2":[],"virtio3":[],"virtio4":[],"virtio5":[],"virtio6":[],"virtio7":[],"virtio8":[],"virtio9":[]}]}],"efidisk":[],"force_create":false,"force_recreate_on_change_of":null,"full_clone":true,"hagroup":"","hastate":"","hostpci":[],"hotplug":"network,disk,usb","id":"proxmox-01/qemu/123","ipconfig0":"ip=dhcp","ipconfig1":null,"ipconfig10":null,"ipconfig11":null,"ipconfig12":null,"ipconfig13":null,"ipconfig14":null,"ipconfig15":null,"ipconfig2":null,"ipconfig3":null,"ipconfig4":null,"ipconfig5":null,"ipconfig6":null,"ipconfig7":null,"ipconfig8":null,"ipconfig9":null,"kvm":true,"linked_vmid":0,"machine":"","memory":1024,"name":"sandbox","nameserver":null,"network":[{"bridge":"vmbr0","firewall":false,"id":0,"link_down":false,"macaddr":"bc:24:11:46:6c:00","model":"virtio","mtu":0,"queues":0,"rate":0,"tag":0}],"numa":false,"onboot":false,"os_network_config":null,"os_type":null,"pci":[],"pcis":[],"pool":"","protection":false,"pxe":null,"qemu_os":"l26","reboot_required":false,"scsihw":"virtio-scsi-single","searchdomain":null,"serial":[{"id":0,"type":"socket"}],"skip_ipv4":false,"skip_ipv6":true,"smbios":[{"family":"","manufacturer":"","product":"","serial":"","sku":"","uuid":"5ae92cdd-a036-4602-af8c-358197f958d9","version":""}],"sockets":0,"ssh_forward_ip":null,"ssh_host":"192.168.1.228","ssh_port":"22","ssh_private_key":null,"ssh_user":null,"sshkeys":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICUP7m8jZJiclZGfSje8CeBYFhX10SrdtjYziuChmj1X plasmagoat@macbook-air\n","startup":"","tablet":true,"tags":"","target_node":"proxmox-01","target_nodes":null,"timeouts":null,"tpm_state":[],"unused_disk":[],"usb":[],"usbs":[],"vcpus":0,"vga":[],"vm_state":"running","vmid":123},"sensitive_attributes":[[{"type":"get_attr","value":"ssh_private_key"}],[{"type":"get_attr","value":"cipassword"}]],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWZhdWx0IjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19"}]}],"check_results":null}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ with lib; let
|
||||||
enhancer = entry:
|
enhancer = entry:
|
||||||
entry
|
entry
|
||||||
// {
|
// {
|
||||||
_upstream = "http://${entry.host}:${toString entry.port}${entry.path or ""}";
|
_upstream = "http://${entry.host}:${toString entry.port}";
|
||||||
_fqdn = "${entry.subdomain}.${entry._nodeConfig.config.homelab.externalDomain or homelabCfg.externalDomain}";
|
_fqdn = "${entry.subdomain}.${entry._nodeConfig.config.homelab.externalDomain or homelabCfg.externalDomain}";
|
||||||
_internal = "${entry.host}:${toString entry.port}";
|
_internal = "${entry.host}:${toString entry.port}";
|
||||||
};
|
};
|
||||||
|
|
|
||||||
162
modules/homelab/services/alertmanager.nix
Normal file
162
modules/homelab/services/alertmanager.nix
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
serviceName = "alertmanager";
|
||||||
|
cfg = config.homelab.services.${serviceName};
|
||||||
|
homelabCfg = config.homelab;
|
||||||
|
in {
|
||||||
|
imports = [
|
||||||
|
(import ../lib/features/monitoring.nix serviceName)
|
||||||
|
(import ../lib/features/logging.nix serviceName)
|
||||||
|
(import ../lib/features/proxy.nix serviceName)
|
||||||
|
];
|
||||||
|
|
||||||
|
# Core service options
|
||||||
|
options.homelab.services.${serviceName} = {
|
||||||
|
enable = mkEnableOption "Vault Warden";
|
||||||
|
|
||||||
|
description = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "Vault Warden";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 9093;
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to open the ports specified in `port` and `webPort` in the firewall.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
environmentFile = lib.mkOption {
|
||||||
|
type = with lib.types; nullOr path;
|
||||||
|
default = null;
|
||||||
|
example = "/var/lib/vaultwarden.env";
|
||||||
|
description = ''
|
||||||
|
Additional environment file as defined in {manpage}`systemd.exec(5)`.
|
||||||
|
|
||||||
|
Secrets like {env}`ADMIN_TOKEN` and {env}`SMTP_PASSWORD`
|
||||||
|
should be passed to the service without adding them to the world-readable Nix store.
|
||||||
|
|
||||||
|
Note that this file needs to be available on the host on which `vaultwarden` is running.
|
||||||
|
|
||||||
|
As a concrete example, to make the Admin UI available (from which new users can be invited initially),
|
||||||
|
the secret {env}`ADMIN_TOKEN` needs to be defined as described
|
||||||
|
[here](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page):
|
||||||
|
|
||||||
|
```
|
||||||
|
# Admin secret token, see
|
||||||
|
# https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page
|
||||||
|
ADMIN_TOKEN=...copy-paste a unique generated secret token here...
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
systemdServices = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [
|
||||||
|
"vaultwarden.service"
|
||||||
|
"vaultwarden"
|
||||||
|
];
|
||||||
|
description = "Systemd services to monitor";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Service configuration with smart defaults
|
||||||
|
config = mkIf cfg.enable (mkMerge [
|
||||||
|
{
|
||||||
|
services.prometheus.alertmanager = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = cfg.openFirewall;
|
||||||
|
|
||||||
|
environmentFile = alertmanagerEnv;
|
||||||
|
|
||||||
|
webExternalUrl = "http://monitor.lab:9093"; # optional but helpful
|
||||||
|
configuration = {
|
||||||
|
route = {
|
||||||
|
receiver = "null";
|
||||||
|
group_by = ["alertname"];
|
||||||
|
group_wait = "10s";
|
||||||
|
group_interval = "5m";
|
||||||
|
repeat_interval = "4h";
|
||||||
|
|
||||||
|
routes = [
|
||||||
|
{
|
||||||
|
receiver = "telegram";
|
||||||
|
matchers = [
|
||||||
|
"severity =~ \"warning|critical\""
|
||||||
|
];
|
||||||
|
group_wait = "10s";
|
||||||
|
continue = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
receivers = [
|
||||||
|
{name = "null";}
|
||||||
|
{
|
||||||
|
name = "telegram";
|
||||||
|
telegram_configs = [
|
||||||
|
{
|
||||||
|
api_url = "https://api.telegram.org";
|
||||||
|
bot_token = "$TELEGRAM_BOT_TOKEN";
|
||||||
|
chat_id = -1002642560007;
|
||||||
|
message_thread_id = 4;
|
||||||
|
parse_mode = "HTML";
|
||||||
|
send_resolved = true;
|
||||||
|
message = "{{ template \"telegram.message\". }}";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
templates = [
|
||||||
|
(pkgs.writeText "telegram.tmpl" (builtins.readFile ./provisioning/templates/telegram.tmpl))
|
||||||
|
# (pkgs.writeText "telegram.markdown.v2.tmpl" (builtins.readFile ./provisioning/templates/telegram.markdown.v2.tmpl))
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [cfg.port];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
homelab.services.${serviceName}.monitoring = {
|
||||||
|
metrics.path = "/metrics";
|
||||||
|
|
||||||
|
healthCheck.path = "/healthz";
|
||||||
|
healthCheck.conditions = ["[STATUS] == 200" "[RESPONSE_TIME] < 1000"];
|
||||||
|
|
||||||
|
extraLabels = {
|
||||||
|
component = "example";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
# homelab.services.${serviceName}.logging = {
|
||||||
|
# files = ["/var/log/example/log.log"];
|
||||||
|
# # parsing = {
|
||||||
|
# # regex = "^ts=(?P<timestamp>[^ ]+) caller=(?P<caller>[^ ]+) level=(?P<level>\\w+) msg=\"(?P<message>[^\"]*)\"";
|
||||||
|
# # extractFields = ["level" "caller"];
|
||||||
|
# # };
|
||||||
|
# extraLabels = {
|
||||||
|
# component = "example";
|
||||||
|
# application = "example";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
}
|
||||||
|
{
|
||||||
|
homelab.services.${serviceName}.proxy = {
|
||||||
|
enableAuth = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
96
modules/homelab/services/caddy.nix
Normal file
96
modules/homelab/services/caddy.nix
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
serviceName = "caddy";
|
||||||
|
cfg = config.homelab.services.${serviceName};
|
||||||
|
homelabCfg = config.homelab;
|
||||||
|
|
||||||
|
allProxyEntries = homelabCfg.reverseProxy.global.allEntries;
|
||||||
|
generateVirtualHosts = entries:
|
||||||
|
listToAttrs (map (entry: {
|
||||||
|
name = entry._fqdn;
|
||||||
|
value = {
|
||||||
|
extraConfig = ''
|
||||||
|
reverse_proxy ${entry._upstream}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
})
|
||||||
|
entries);
|
||||||
|
in {
|
||||||
|
imports = [
|
||||||
|
(import ../lib/features/monitoring.nix serviceName)
|
||||||
|
(import ../lib/features/logging.nix serviceName)
|
||||||
|
];
|
||||||
|
|
||||||
|
# Core service options
|
||||||
|
options.homelab.services.${serviceName} = {
|
||||||
|
enable = mkEnableOption "Caddy web server";
|
||||||
|
|
||||||
|
description = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "Caddy web server";
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to open the ports specified in `port` and `webPort` in the firewall.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
systemdServices = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [
|
||||||
|
"caddy.service"
|
||||||
|
"caddy"
|
||||||
|
];
|
||||||
|
description = "Systemd services to monitor";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Service configuration with smart defaults
|
||||||
|
config = mkIf cfg.enable (mkMerge [
|
||||||
|
{
|
||||||
|
services.caddy = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
virtualHosts = generateVirtualHosts allProxyEntries;
|
||||||
|
};
|
||||||
|
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [80 443];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
# homelab.services.${serviceName}.monitoring = {
|
||||||
|
# metrics.path = "/metrics";
|
||||||
|
|
||||||
|
# healthCheck.path = "/healthz";
|
||||||
|
# healthCheck.conditions = ["[STATUS] == 200" "[RESPONSE_TIME] < 1000"];
|
||||||
|
|
||||||
|
# extraLabels = {
|
||||||
|
# component = "example";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
}
|
||||||
|
{
|
||||||
|
# homelab.services.${serviceName}.logging = {
|
||||||
|
# files = ["/var/log/example/log.log"];
|
||||||
|
# # parsing = {
|
||||||
|
# # regex = "^ts=(?P<timestamp>[^ ]+) caller=(?P<caller>[^ ]+) level=(?P<level>\\w+) msg=\"(?P<message>[^\"]*)\"";
|
||||||
|
# # extractFields = ["level" "caller"];
|
||||||
|
# # };
|
||||||
|
# extraLabels = {
|
||||||
|
# component = "example";
|
||||||
|
# application = "example";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
}
|
||||||
|
{
|
||||||
|
# homelab.services.${serviceName}.proxy = {
|
||||||
|
# enableAuth = true;
|
||||||
|
# };
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,26 @@
|
||||||
./gatus.nix
|
./gatus.nix
|
||||||
./prometheus.nix
|
./prometheus.nix
|
||||||
./grafana.nix
|
./grafana.nix
|
||||||
|
./example.nix
|
||||||
|
./vaultwarden.nix
|
||||||
# ./monitoring/loki.nix
|
# ./monitoring/loki.nix
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# TODO
|
||||||
|
#
|
||||||
|
# ./alertmanager.nix
|
||||||
|
# ./dnsmasq.nix
|
||||||
|
# ./authelia.nix
|
||||||
|
# ./lldap.nix
|
||||||
|
# ./roundcube.nix
|
||||||
|
# ./mailserver.nix
|
||||||
|
./caddy.nix
|
||||||
|
# ./traefik.nix
|
||||||
|
# ./ente-photos.nix
|
||||||
|
# ./forgejo.nix
|
||||||
|
# ./forgejo-runner.nix
|
||||||
|
# ./jellyfin.nix
|
||||||
|
# ./arr.nix
|
||||||
|
#
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
86
modules/homelab/services/example.nix
Normal file
86
modules/homelab/services/example.nix
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
serviceName = "example";
|
||||||
|
cfg = config.homelab.services.${serviceName};
|
||||||
|
homelabCfg = config.homelab;
|
||||||
|
in {
|
||||||
|
imports = [
|
||||||
|
(import ../lib/features/monitoring.nix serviceName)
|
||||||
|
(import ../lib/features/logging.nix serviceName)
|
||||||
|
(import ../lib/features/proxy.nix serviceName)
|
||||||
|
];
|
||||||
|
|
||||||
|
# Core service options
|
||||||
|
options.homelab.services.${serviceName} = {
|
||||||
|
enable = mkEnableOption "Example Homelab Service";
|
||||||
|
|
||||||
|
description = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "Example Homelab Service";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 1234;
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to open the ports specified in `port` and `webPort` in the firewall.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
systemdServices = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [
|
||||||
|
"example.service"
|
||||||
|
"example"
|
||||||
|
];
|
||||||
|
description = "Systemd services to monitor";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Service configuration with smart defaults
|
||||||
|
config = mkIf cfg.enable (mkMerge [
|
||||||
|
{
|
||||||
|
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [cfg.port];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
homelab.services.${serviceName}.monitoring = {
|
||||||
|
metrics.path = "/metrics";
|
||||||
|
|
||||||
|
healthCheck.path = "/healthz";
|
||||||
|
healthCheck.conditions = ["[STATUS] == 200" "[RESPONSE_TIME] < 1000"];
|
||||||
|
|
||||||
|
extraLabels = {
|
||||||
|
component = "example";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
homelab.services.${serviceName}.logging = {
|
||||||
|
files = ["/var/log/example/log.log"];
|
||||||
|
# parsing = {
|
||||||
|
# regex = "^ts=(?P<timestamp>[^ ]+) caller=(?P<caller>[^ ]+) level=(?P<level>\\w+) msg=\"(?P<message>[^\"]*)\"";
|
||||||
|
# extractFields = ["level" "caller"];
|
||||||
|
# };
|
||||||
|
extraLabels = {
|
||||||
|
component = "example";
|
||||||
|
application = "example";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
homelab.services.${serviceName}.proxy = {
|
||||||
|
enableAuth = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
with lib; let
|
|
||||||
cfg = config.homelab.services.monitoring-stack;
|
|
||||||
in {
|
|
||||||
imports = [
|
|
||||||
./prometheus.nix
|
|
||||||
./alertmanager.nix
|
|
||||||
./grafana.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
options.homelab.services.monitoring-stack = {
|
|
||||||
enable = mkEnableOption "Complete monitoring stack (Prometheus + Alertmanager + Grafana)";
|
|
||||||
|
|
||||||
prometheus = {
|
|
||||||
enable = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = "Enable Prometheus";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
alertmanager = {
|
|
||||||
enable = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = "Enable Alertmanager";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
grafana = {
|
|
||||||
enable = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = "Enable Grafana";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
# Enable services based on configuration
|
|
||||||
homelab.services.prometheus.enable = mkDefault cfg.prometheus.enable;
|
|
||||||
homelab.services.alertmanager.enable = mkDefault cfg.alertmanager.enable;
|
|
||||||
homelab.services.grafana.enable = mkDefault cfg.grafana.enable;
|
|
||||||
|
|
||||||
# Configure Prometheus to use Alertmanager if both are enabled
|
|
||||||
homelab.services.prometheus.alertmanager = mkIf (cfg.prometheus.enable && cfg.alertmanager.enable) {
|
|
||||||
enable = true;
|
|
||||||
url = "http://localhost:${toString config.homelab.services.alertmanager.port}";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Configure Grafana to use Prometheus if both are enabled
|
|
||||||
homelab.services.grafana.datasources.prometheus = mkIf (cfg.prometheus.enable && cfg.grafana.enable) {
|
|
||||||
url = "http://localhost:${toString config.homelab.services.prometheus.port}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -11,7 +11,6 @@ with lib; let
|
||||||
|
|
||||||
# Generate Prometheus scrape configs from global monitoring data
|
# Generate Prometheus scrape configs from global monitoring data
|
||||||
prometheusScrapeConfigs = let
|
prometheusScrapeConfigs = let
|
||||||
# Get all metrics - try global first, fallback to local
|
|
||||||
allMetrics = homelabCfg.monitoring.global.allMetrics;
|
allMetrics = homelabCfg.monitoring.global.allMetrics;
|
||||||
|
|
||||||
jobGroups = groupBy (m: m.jobName) allMetrics;
|
jobGroups = groupBy (m: m.jobName) allMetrics;
|
||||||
|
|
|
||||||
137
modules/homelab/services/vaultwarden.nix
Normal file
137
modules/homelab/services/vaultwarden.nix
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
serviceName = "vaultwarden";
|
||||||
|
cfg = config.homelab.services.${serviceName};
|
||||||
|
homelabCfg = config.homelab;
|
||||||
|
in {
|
||||||
|
imports = [
|
||||||
|
(import ../lib/features/monitoring.nix serviceName)
|
||||||
|
(import ../lib/features/logging.nix serviceName)
|
||||||
|
(import ../lib/features/proxy.nix serviceName)
|
||||||
|
];
|
||||||
|
|
||||||
|
# Core service options
|
||||||
|
options.homelab.services.${serviceName} = {
|
||||||
|
enable = mkEnableOption "Vault Warden";
|
||||||
|
|
||||||
|
description = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "Vault Warden";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 8222;
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to open the ports specified in `port` and `webPort` in the firewall.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
environmentFile = lib.mkOption {
|
||||||
|
type = with lib.types; nullOr path;
|
||||||
|
default = null;
|
||||||
|
example = "/var/lib/vaultwarden.env";
|
||||||
|
description = ''
|
||||||
|
Additional environment file as defined in {manpage}`systemd.exec(5)`.
|
||||||
|
|
||||||
|
Secrets like {env}`ADMIN_TOKEN` and {env}`SMTP_PASSWORD`
|
||||||
|
should be passed to the service without adding them to the world-readable Nix store.
|
||||||
|
|
||||||
|
Note that this file needs to be available on the host on which `vaultwarden` is running.
|
||||||
|
|
||||||
|
As a concrete example, to make the Admin UI available (from which new users can be invited initially),
|
||||||
|
the secret {env}`ADMIN_TOKEN` needs to be defined as described
|
||||||
|
[here](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page):
|
||||||
|
|
||||||
|
```
|
||||||
|
# Admin secret token, see
|
||||||
|
# https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page
|
||||||
|
ADMIN_TOKEN=...copy-paste a unique generated secret token here...
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
systemdServices = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [
|
||||||
|
"vaultwarden.service"
|
||||||
|
"vaultwarden"
|
||||||
|
];
|
||||||
|
description = "Systemd services to monitor";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Service configuration with smart defaults
|
||||||
|
config = mkIf cfg.enable (mkMerge [
|
||||||
|
{
|
||||||
|
services.vaultwarden = {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
DOMAIN = "https://bitwarden.example.com";
|
||||||
|
SIGNUPS_ALLOWED = false;
|
||||||
|
|
||||||
|
ROCKET_ADDRESS = "0.0.0.0";
|
||||||
|
ROCKET_PORT = cfg.port;
|
||||||
|
|
||||||
|
ROCKET_LOG = "critical";
|
||||||
|
|
||||||
|
# This example assumes a mailserver running on localhost,
|
||||||
|
# thus without transport encryption.
|
||||||
|
# If you use an external mail server, follow:
|
||||||
|
# https://github.com/dani-garcia/vaultwarden/wiki/SMTP-configuration
|
||||||
|
# SMTP_HOST = "127.0.0.1";
|
||||||
|
# SMTP_PORT = 25;
|
||||||
|
# SMTP_SSL = false;
|
||||||
|
|
||||||
|
# SMTP_FROM = "admin@bitwarden.example.com";
|
||||||
|
# SMTP_FROM_NAME = "example.com Bitwarden server";
|
||||||
|
|
||||||
|
ADMIN_TOKEN = "1234";
|
||||||
|
};
|
||||||
|
environmentFile = cfg.environmentFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [cfg.port];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
# homelab.services.${serviceName}.monitoring = {
|
||||||
|
# metrics.path = "/metrics";
|
||||||
|
|
||||||
|
# healthCheck.path = "/healthz";
|
||||||
|
# healthCheck.conditions = ["[STATUS] == 200" "[RESPONSE_TIME] < 1000"];
|
||||||
|
|
||||||
|
# extraLabels = {
|
||||||
|
# component = "example";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
}
|
||||||
|
{
|
||||||
|
# homelab.services.${serviceName}.logging = {
|
||||||
|
# files = ["/var/log/example/log.log"];
|
||||||
|
# # parsing = {
|
||||||
|
# # regex = "^ts=(?P<timestamp>[^ ]+) caller=(?P<caller>[^ ]+) level=(?P<level>\\w+) msg=\"(?P<message>[^\"]*)\"";
|
||||||
|
# # extractFields = ["level" "caller"];
|
||||||
|
# # };
|
||||||
|
# extraLabels = {
|
||||||
|
# component = "example";
|
||||||
|
# application = "example";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
}
|
||||||
|
{
|
||||||
|
homelab.services.${serviceName}.proxy = {
|
||||||
|
enableAuth = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
{ config, pkgs, ... }: {
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
system.stateVersion = "25.05";
|
system.stateVersion = "25.05";
|
||||||
|
|
||||||
services.openssh.enable = true;
|
services.openssh.enable = true;
|
||||||
|
|
|
||||||
|
|
@ -114,9 +114,6 @@
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
overlays = [];
|
overlays = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
defaults = {pkgs, ...}: {
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
host-b = {
|
host-b = {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
{ config, pkgs, modulesPath, lib, ... }:
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
modulesPath,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
imports = [
|
imports = [
|
||||||
../../templates/base.nix
|
../../templates/base.nix
|
||||||
./networking.nix
|
./networking.nix
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@
|
||||||
networking.hostName = "dns";
|
networking.hostName = "dns";
|
||||||
# networking.useHostResolvConf = false;
|
# networking.useHostResolvConf = false;
|
||||||
# networking.interfaces.eth0.useDHCP = true;
|
# networking.interfaces.eth0.useDHCP = true;
|
||||||
networking.interfaces.eth0.ipv4.addresses = [{
|
networking.interfaces.eth0.ipv4.addresses = [
|
||||||
|
{
|
||||||
address = "192.168.1.53";
|
address = "192.168.1.53";
|
||||||
prefixLength = 24;
|
prefixLength = 24;
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
networking.defaultGateway = "192.168.1.1"; # your router
|
networking.defaultGateway = "192.168.1.1"; # your router
|
||||||
networking.nameservers = ["8.8.8.8"]; # fallback resolvers
|
networking.nameservers = ["8.8.8.8"]; # fallback resolvers
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
{ config, lib, pkgs, runnerId, ... }:
|
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
runnerId,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
networking.hostName = "forgejo-runner-${runnerId}";
|
networking.hostName = "forgejo-runner-${runnerId}";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
{ config, lib, ... }:
|
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
sops.secrets."forgejo-runner-registration-token" = {
|
sops.secrets."forgejo-runner-registration-token" = {
|
||||||
sopsFile = ../../secrets/forgejo/runner-secrets.yml;
|
sopsFile = ../../secrets/forgejo/runner-secrets.yml;
|
||||||
mode = "0440";
|
mode = "0440";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
{ config, pkgs, modulesPath, lib, ... }:
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
modulesPath,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
imports = [
|
imports = [
|
||||||
../../templates/base.nix
|
../../templates/base.nix
|
||||||
../../secrets/shared-sops.nix
|
../../secrets/shared-sops.nix
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
networking.hostName = "forgejo";
|
networking.hostName = "forgejo";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
networking.hostName = "monitor";
|
networking.hostName = "monitor";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,4 +41,11 @@
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
caddy = {
|
||||||
|
rule = "PathPrefix(`/`)";
|
||||||
|
service = "caddy";
|
||||||
|
entryPoints = ["web"];
|
||||||
|
priority = 15;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,4 +9,6 @@
|
||||||
proxmox.loadBalancer.serversTransport = "insecureTransport";
|
proxmox.loadBalancer.serversTransport = "insecureTransport";
|
||||||
nas.loadBalancer.servers = [{url = "https://192.168.1.226:5001";}];
|
nas.loadBalancer.servers = [{url = "https://192.168.1.226:5001";}];
|
||||||
nas.loadBalancer.serversTransport = "insecureTransport";
|
nas.loadBalancer.serversTransport = "insecureTransport";
|
||||||
|
|
||||||
|
caddy.loadBalancer.servers = [{url = "http://sandbox.lab:80";}];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
{ config, lib, pkgs, ... }: {
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
networking.hostName = "traefik";
|
networking.hostName = "traefik";
|
||||||
networking.interfaces.eth0.ipv4.addresses = [{
|
networking.interfaces.eth0.ipv4.addresses = [
|
||||||
|
{
|
||||||
address = "192.168.1.80";
|
address = "192.168.1.80";
|
||||||
prefixLength = 24;
|
prefixLength = 24;
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [80 443 8080 8082];
|
networking.firewall.allowedTCPPorts = [80 443 8080 8082];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,16 +50,43 @@ in {
|
||||||
|
|
||||||
staticConfigOptions = staticConfig;
|
staticConfigOptions = staticConfig;
|
||||||
|
|
||||||
dynamicConfigOptions.http = {
|
dynamicConfigOptions = {
|
||||||
|
# HTTP configuration (your existing setup)
|
||||||
|
http = {
|
||||||
routers = allRouters;
|
routers = allRouters;
|
||||||
services = allServices;
|
services = allServices;
|
||||||
middlewares = middlewares;
|
middlewares = middlewares;
|
||||||
|
|
||||||
serversTransports = {
|
serversTransports = {
|
||||||
insecureTransport = {
|
insecureTransport = {
|
||||||
insecureSkipVerify = true;
|
insecureSkipVerify = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
tcp = {
|
||||||
|
routers = {
|
||||||
|
caddy-fallback = {
|
||||||
|
rule = "HostSNI(`*`)"; # Matches any SNI
|
||||||
|
service = "caddy-tls";
|
||||||
|
entryPoints = ["websecure"];
|
||||||
|
priority = 1; # Lowest priority - only if no HTTP router matches
|
||||||
|
tls = {
|
||||||
|
passthrough = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services = {
|
||||||
|
caddy-tls = {
|
||||||
|
loadBalancer = {
|
||||||
|
servers = [
|
||||||
|
{
|
||||||
|
address = "sandbox.lab:443";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
{ config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
prometheus_exporter_port = 9100;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
prometheus_exporter_port = 9100;
|
||||||
|
in {
|
||||||
networking.firewall.allowedTCPPorts = [prometheus_exporter_port];
|
networking.firewall.allowedTCPPorts = [prometheus_exporter_port];
|
||||||
|
|
||||||
services.prometheus = {
|
services.prometheus = {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
{ config, lib, pkgs, ... }: {
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
users.users.plasmagoat = {
|
users.users.plasmagoat = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
description = "plasmagoat";
|
description = "plasmagoat";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue