Compare commits
363 Commits
renovate/o
...
09fbb76c8e
| Author | SHA1 | Date | |
|---|---|---|---|
| 09fbb76c8e | |||
| b1f3337c98 | |||
| e610e96d80 | |||
| c9997fb8a7 | |||
| b9cc44d7e8 | |||
| be884d07c6 | |||
| 2875d84f33 | |||
| 573601a7ec | |||
| fb60744c5a | |||
| 52ca68c4ce | |||
| 0934a1130a | |||
| 3d28650c1b | |||
| 15063c9885 | |||
| ba3cb2571c | |||
| 5edaeb123c | |||
| 0dc37f69cb | |||
| 777239ccb5 | |||
| 352af6f386 | |||
| 230197e3c6 | |||
| 0c5e22f538 | |||
| e79386b4a5 | |||
| 8f4932132a | |||
| bb6272b16e | |||
| 3a71410c19 | |||
| e5af5c3945 | |||
| 6de56bfd10 | |||
| d70a704f89 | |||
| 5df94c4656 | |||
| a6772893d0 | |||
| ba31945337 | |||
| fcaa28c95a | |||
| a40f9a046a | |||
| 80ed3358e8 | |||
| eae4ff426c | |||
| 0fadd95386 | |||
| 29e06c60eb | |||
| 27ae162886 | |||
| d96344b310 | |||
| e3483fcfe3 | |||
| 784b335f65 | |||
| 9300e327df | |||
| 90fb555dc2 | |||
| 78b3b6b400 | |||
| 90897daa27 | |||
| 0368252850 | |||
| 1503c57fbe | |||
| 0f12840b35 | |||
| 87a071925c | |||
| b6efe42dc2 | |||
| d2cfd7b73d | |||
| bf1cae3fc7 | |||
| 6712e94237 | |||
| 6f8e10f3fc | |||
| 3c04fd6b10 | |||
| ef353d635a | |||
| 0097d057d5 | |||
| b454fc606f | |||
| 7feb19b7fc | |||
| b21f8e402b | |||
| 68f51b26b0 | |||
| 1095d7ef4d | |||
| 8d83c6dc83 | |||
| 65e75a4d39 | |||
| 6c7457d095 | |||
| 9b556e98a9 | |||
| 202ebc7b86 | |||
| ec61023f74 | |||
| 05d3493bb7 | |||
| 2a9f8c3092 | |||
| 226ee59fa6 | |||
| c8f34c45ac | |||
| c0fa400159 | |||
| 6ccb00e86e | |||
| 7b8fb8d8bb | |||
| 0ae3181267 | |||
| c0d83249b9 | |||
| 974d70a39e | |||
| 4518fc674a | |||
| c3912af26b | |||
| 797b97496e | |||
| 29457af188 | |||
| 2a8e56824e | |||
| f71794de4d | |||
| f4a865ce7a | |||
| e7b3b220aa | |||
| 0642d29ed5 | |||
| 3f044670e0 | |||
| 122770b128 | |||
| d894d42129 | |||
| 3426b1215d | |||
| 73a189f4e8 | |||
| 4518cdda22 | |||
| 3682e4d5bf | |||
| 3135514f6d | |||
| 5e39cc9082 | |||
| 6eed078d30 | |||
| 0bb805eaaa | |||
| c0f9670837 | |||
| 69728501e1 | |||
| 0a516b3798 | |||
| c9bb63b373 | |||
| 5b5043755d | |||
| e0fcaeaad4 | |||
| 102efd1254 | |||
| 5400c69771 | |||
| b6c70c9931 | |||
| 2710996a19 | |||
| 32f8ccfeb8 | |||
| 12aab2bf0e | |||
| 957b6dab43 | |||
| d1b30c7e61 | |||
| d880c342a5 | |||
| ae38951164 | |||
| 1e363acfca | |||
| c78ca0933c | |||
| 9a31c6bf15 | |||
| 45aa92fe10 | |||
| 708ffe203c | |||
| e2c75d2f22 | |||
| 3ceec2f10c | |||
| 95cfbfbe66 | |||
| bf9aefb44a | |||
| 5ffb171821 | |||
| a35116aa31 | |||
| b32337a2ba | |||
| d27b43715c | |||
| 4b0ce7a2e3 | |||
| 7f2ef7270c | |||
| 73a9b275a7 | |||
| 8a61a936c6 | |||
| 1c2f77927f | |||
| 4f5b25d910 | |||
| 7c5fafd54e | |||
| de11ec0d1b | |||
| 07c32643e7 | |||
| 9c61d47fda | |||
| 0f24f1dd7b | |||
| 83e5cada3f | |||
| ccf6302924 | |||
| 5eb0362788 | |||
| 0985832c2d | |||
| db86abff25 | |||
| a1b40a6a21 | |||
| 444c4faf96 | |||
| 9f304af879 | |||
| c0524510b8 | |||
| a26a351396 | |||
| 9269f21692 | |||
| 9d6a9ff304 | |||
| 3cd094007e | |||
| 94a57daaf8 | |||
| 6fec8d29a6 | |||
| 3a94da6021 | |||
| 70511ff9bc | |||
| e8b37d90d8 | |||
| 30b7a78360 | |||
| 2561b354d1 | |||
| 949d8b11db | |||
| 6c46b20dba | |||
| f0f9cb4d34 | |||
| 8386e21722 | |||
| c871dae045 | |||
| 70e4967497 | |||
| 8e68c45573 | |||
| c4628523bc | |||
| 071e87ee44 | |||
| 9e17aadb56 | |||
| 3ca4ddc233 | |||
| 215a2ac1fb | |||
| 5b8a861daa | |||
| 319e3bafbe | |||
| ad1c60a049 | |||
| 41020f8c79 | |||
| 60c7dd4bdc | |||
| 0fde3108d6 | |||
| a299c2cc2b | |||
| a4ea45a39c | |||
| 30bae60308 | |||
| 2f3b7af0da | |||
| 30efd5ae6e | |||
| 0e1279473f | |||
| 718a0d7e33 | |||
| 9765f1cf86 | |||
| 5f3a00b382 | |||
| b379c181f2 | |||
| e1801347f2 | |||
| d53db88fd2 | |||
| 5fb2bcfc7e | |||
| f5da3b52a2 | |||
| c3dbb0a608 | |||
| a520c62277 | |||
| 6cf45eda17 | |||
| 753d43b643 | |||
| 263b60018d | |||
| 0816b6e434 | |||
| 18eb912f03 | |||
| a2c23c5f97 | |||
| 15ce411c3e | |||
| 04a8c98d63 | |||
| f46219f87e | |||
| 53154eeed7 | |||
| 2ad310c550 | |||
| d32d94eb00 | |||
| 5b62f7e386 | |||
| 52124193e2 | |||
| 0f8ee9e53d | |||
| 122c70d0a8 | |||
| 5463d76771 | |||
| 60f2056806 | |||
| 6119ac7271 | |||
| 1a01f82e30 | |||
| 74c9ddad62 | |||
| caf62609d3 | |||
| d5622416de | |||
| 4183831d2f | |||
| ae6ed770a9 | |||
| 59d936d467 | |||
| 9b56ce5e4f | |||
| 2424ad440b | |||
| dff138ba31 | |||
| d95eb6f4ab | |||
| 5252f209f5 | |||
| e7348b2718 | |||
| c7cd2c5355 | |||
| 71e75afadb | |||
| 23169aa2ca | |||
| d8aa0a6a32 | |||
| a6630c0376 | |||
| 9056839784 | |||
| 1f8afa2f8e | |||
| e7b22509cd | |||
| e39574b60e | |||
| 197ceb6688 | |||
| 3e95a5edd1 | |||
| 10fe51f52d | |||
| e197cf5e5e | |||
| c54109dbf3 | |||
| 5a97e4b1d8 | |||
| 12cdfd96e2 | |||
| 7d2056b3ee | |||
| 35e579fc01 | |||
| 302613b76a | |||
| 89542df777 | |||
| 233466e2cd | |||
| 461f0589b3 | |||
| 5c16cd3a4b | |||
| 5cd5263d19 | |||
| a886e7c79c | |||
| dd676716f9 | |||
| 110ffa9c22 | |||
| 6ed7d61e21 | |||
| 051083cd6e | |||
| 87f2446cd1 | |||
| faa55fa069 | |||
| af29de91d6 | |||
| 5f3a775201 | |||
| 81f750e5e5 | |||
| 641e50b5e9 | |||
| 3fe8626391 | |||
| 94f851c607 | |||
| d2134ad554 | |||
| 22910085b7 | |||
| 6a4dee0852 | |||
| 49d5803b4f | |||
| b5c51f6720 | |||
| 3a8dbc6e0c | |||
| ead8be8bcb | |||
| f027dad029 | |||
| e35b8ccac8 | |||
| f69128b245 | |||
| d14b62f384 | |||
| ab7b8a6f26 | |||
| 8acc480b05 | |||
| 65834037ee | |||
| 1bf63168f2 | |||
| b3db332075 | |||
| b84c792992 | |||
| 947f154a81 | |||
| 1a88b1c602 | |||
| 55fce1fc36 | |||
| bb4afc0c07 | |||
| eb92a85cac | |||
| 8f70ae5f2e | |||
| f89a2fd1cc | |||
| b493ee9d77 | |||
| 8de0663571 | |||
| 3fc534f44b | |||
| 1c8ccd0fc4 | |||
| 847fd3557b | |||
| d2c2f5038f | |||
| afb9dcec65 | |||
| ba51980cec | |||
| e0eb26b63d | |||
| eda5ba08a0 | |||
| 318aedf89d | |||
| 7b9090afc1 | |||
| a109290c18 | |||
| f4b9742ab1 | |||
| b103358816 | |||
| 46cacb339d | |||
| 1e7dd52721 | |||
| 044cc37392 | |||
| 68ba891abc | |||
| 81ed455ff8 | |||
| b7c2da4419 | |||
| 4bc01e2e78 | |||
| 94d51de471 | |||
| dc0104c55d | |||
| 83be6619e8 | |||
| 48ccacefdd | |||
| cfeef90515 | |||
| ce0bef4970 | |||
| bd5fd97ed0 | |||
| 52641779bc | |||
| e98e02705d | |||
| 3c849f52f7 | |||
| 36187fff41 | |||
| 1ac7504585 | |||
| 879c013e89 | |||
| aa7fe8d3cf | |||
| fd280f1fca | |||
| 2ad381e35c | |||
| e63a285dc3 | |||
| 5336df3134 | |||
| 966639e3c8 | |||
| 97924a8064 | |||
| 37b78f079e | |||
| 0d17825eab | |||
| ffeecf65f6 | |||
| fea49ae167 | |||
| 6b6e7937c1 | |||
| 487baa2813 | |||
| fe2f79d13c | |||
| c3a747c03c | |||
| f1f6ffb9a0 | |||
| e851f6ab8c | |||
| 2ecd20c9d7 | |||
| bdb3bd3234 | |||
| 47e957e444 | |||
| b2dfb2dc0b | |||
| 6ccc964c87 | |||
| 5c7b258ccf | |||
| 351426f055 | |||
| ca598f9750 | |||
| 0cb93ce8a1 | |||
| 6fde991ba9 | |||
| 5f3840cc02 | |||
| d9a22723ef | |||
| f97a655ad5 | |||
| c2aacd0ef4 | |||
| f36ce88026 | |||
| d19d332b59 | |||
| 5cf9de7997 | |||
| 3c84632a2d | |||
| 14bcc8546c | |||
| ca8a63fdbe | |||
| 3a46d17f02 | |||
| add851ee9e | |||
| edbfd26bde | |||
| dea0dfb7cc | |||
| 874fc826cd | |||
| 33cb5c72c7 | |||
| 31df54fcf0 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,4 +10,3 @@ devenv.local.yaml
|
||||
|
||||
# pre-commit
|
||||
.pre-commit-config.yaml
|
||||
.opencode
|
||||
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "openwrt/roles/ansible-openwrt"]
|
||||
path = openwrt/roles/ansible-openwrt
|
||||
url = https://github.com/gekmihesg/ansible-openwrt.git
|
||||
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@@ -2,7 +2,6 @@
|
||||
"recommendations": [
|
||||
"jnoortheen.nix-ide",
|
||||
"detachhead.basedpyright",
|
||||
"mkhl.direnv",
|
||||
"mermaidchart.vscode-mermaid-chart"
|
||||
"mkhl.direnv"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
when:
|
||||
- event: push
|
||||
branch: fresh-start
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: debian
|
||||
commands:
|
||||
- echo "This is the build step"
|
||||
- echo "echo hello world" > executable
|
||||
- name: a-test-step
|
||||
image: golang:1.16
|
||||
commands:
|
||||
- echo "Testing ..."
|
||||
- sh executable
|
||||
23
Makefile
23
Makefile
@@ -1,7 +1,3 @@
|
||||
SHELL := /usr/bin/env bash
|
||||
|
||||
.PHONY: install-router gen-talos-config apply-talos-config get-kubeconfig garm-image-build garm-image-push garm-image-build-push
|
||||
|
||||
install-router:
|
||||
ansible-playbook ansible/playbook.yml -i ansible/hosts
|
||||
|
||||
@@ -24,22 +20,3 @@ gen-talos-config:
|
||||
|
||||
apply-talos-config:
|
||||
talosctl -n anapistula-delrosalae apply-config -f talos/generated/anapistula-delrosalae.yaml
|
||||
|
||||
get-kubeconfig:
|
||||
talosctl -n anapistula-delrosalae kubeconfig talos/generated/kubeconfig
|
||||
|
||||
garm-image-build:
|
||||
set -euo pipefail; \
|
||||
source apps/garm/image-source.env; \
|
||||
docker build \
|
||||
-f docker/garm/Dockerfile \
|
||||
--build-arg GARM_COMMIT=$$GARM_COMMIT \
|
||||
-t $$GARM_IMAGE \
|
||||
.
|
||||
|
||||
garm-image-push:
|
||||
set -euo pipefail; \
|
||||
source apps/garm/image-source.env; \
|
||||
docker push $$GARM_IMAGE
|
||||
|
||||
garm-image-build-push: garm-image-build garm-image-push
|
||||
|
||||
353
README.md
353
README.md
@@ -1,283 +1,106 @@
|
||||
# Homelab
|
||||
|
||||
This repo contains configuration and documentation for my homelab setup, which is based on Talos OS for Kubernetes cluster and MikroTik router.
|
||||
## Goals
|
||||
|
||||
## Architecture
|
||||
Wanting to set up homelab kubernetes cluster.
|
||||
|
||||
Physical setup consists of MikroTik router which connects to the internet and serves as a gateway for the cluster and other devices in the home network as shown in the diagram below.
|
||||
### Software
|
||||
|
||||
```mermaid
|
||||
%%{init: {"flowchart": {"ranker": "tight-tree"}}}%%
|
||||
flowchart TD
|
||||
|
||||
subgraph internet[Internet]
|
||||
ipv4[IPv4 Internet]
|
||||
ipv6[IPv6 Internet]
|
||||
he_tunnel[Hurricane Electric IPv6 Tunnel Broker]
|
||||
isp[ISP]
|
||||
end
|
||||
|
||||
subgraph home[Home network]
|
||||
router[MikroTik Router]
|
||||
cluster[Talos cluster]
|
||||
lan[LAN]
|
||||
mgmt[Management network]
|
||||
cam[Camera system]
|
||||
router --> lan
|
||||
router --> cluster
|
||||
router --> mgmt
|
||||
router --> cam
|
||||
end
|
||||
|
||||
ipv4 -- "Public IPv4 address" --> isp
|
||||
ipv6 -- "Routed /48 IPv6 prefix" --> he_tunnel -- "6in4 Tunnel" --> isp
|
||||
isp --> router
|
||||
```
|
||||
|
||||
Devices are separated into VLANs and subnets for isolation and firewalling between devices and services. Whole internal network is configured to eliminate NAT where unnecessary. Pods on the Kubernetes cluster communicate with the router using native IP routing, there is no encapsulation, overlay network nor NAT on the nodes. Router knows where to direct packets destined for the pods because the cluster announces its IP prefixes to the router using BGP. Router also performs NAT for IPv4 traffic from the cluster to and from the internet, while IPv6 traffic is routed directly to the internet without NAT. High level logical routing diagram is shown below.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
isp[ISP] --- gpon
|
||||
|
||||
subgraph device[MikroTik CRS418-8P-8G-2s+]
|
||||
direction TB
|
||||
gpon[SFP GPON ONU]
|
||||
pppoe[PPPoE client]
|
||||
|
||||
he_tunnel[HE Tunnel]
|
||||
|
||||
router[Router]@{ shape: cyl }
|
||||
|
||||
dockers["""
|
||||
Dockers Containers (bridge)
|
||||
2001:470:61a3:500::/64
|
||||
172.17.0.0/16
|
||||
"""]@{ shape: cloud }
|
||||
tailscale["Tailscale Container"]
|
||||
|
||||
lan["""
|
||||
LAN (vlan2)
|
||||
2001:470:61a3::/64
|
||||
192.168.0.0/24
|
||||
"""]@{ shape: cloud }
|
||||
|
||||
mgmt["""
|
||||
Management network (vlan1)
|
||||
192.168.255.0/24
|
||||
"""]@{ shape: cloud }
|
||||
|
||||
cam["""
|
||||
Camera system (vlan3)
|
||||
192.168.3.0/24
|
||||
"""]@{ shape: cloud }
|
||||
|
||||
cluster["""
|
||||
Kubernetes cluster (vlan4)
|
||||
2001:470:61a3:100::/64
|
||||
192.168.1.0/24
|
||||
"""]@{ shape: cloud }
|
||||
|
||||
gpon --- pppoe -- """
|
||||
139.28.40.212
|
||||
Default IPv4 gateway
|
||||
""" --- router
|
||||
|
||||
pppoe --- he_tunnel -- """
|
||||
2001:470:61a3:: incoming
|
||||
Default IPv6 gateway
|
||||
""" --- router
|
||||
|
||||
router -- """
|
||||
2001:470:61a3:500:ffff:ffff:ffff:ffff
|
||||
172.17.0.1/16
|
||||
""" --- dockers --- tailscale
|
||||
|
||||
router -- """
|
||||
2001:470:61a3:0:ffff:ffff:ffff:ffff
|
||||
192.168.0.1
|
||||
"""--- lan
|
||||
|
||||
router -- """
|
||||
192.168.255.10
|
||||
"""--- mgmt
|
||||
|
||||
router -- "192.168.3.1" --- cam
|
||||
router -- """
|
||||
2001:470:61a3:100::1
|
||||
192.168.1.1
|
||||
""" --- cluster
|
||||
|
||||
end
|
||||
|
||||
subgraph k8s[K8s cluster]
|
||||
direction TB
|
||||
pod_network["""
|
||||
Pod networks
|
||||
2001:470:61a3:200::/104
|
||||
10.42.0.0/16
|
||||
(Dynamically allocated /120 IPv6 and /24 IPv4 prefixes per node)
|
||||
"""]@{ shape: cloud }
|
||||
|
||||
service_network["""
|
||||
Service network
|
||||
2001:470:61a3:300::/112
|
||||
10.43.0.0/16
|
||||
(Advertises vIP addresses via BGP from nodes hosting endpoints)
|
||||
"""]@{ shape: cloud }
|
||||
|
||||
load_balancer["""
|
||||
Load balancer network
|
||||
2001:470:61a3:400::/112
|
||||
10.44.0.0/16
|
||||
(Advertises vIP addresses via BGP from nodes hosting endpoints)
|
||||
"""]@{ shape: cloud }
|
||||
end
|
||||
|
||||
cluster -- "Routes exported via BGP" ----- k8s
|
||||
```
|
||||
|
||||
Currently the k8s cluster consists of single node (hostname anapistula-delrosalae), which is a PC with Ryzen 5 3600, 64GB RAM, RX 580 8GB (for accelerating LLMs), 1TB NVMe SSD, 2TB and 3TB HDDs and serves both as control plane and worker node.
|
||||
|
||||
## Software stack
|
||||
|
||||
The cluster itself is based on [Talos Linux](https://www.talos.dev/) (which is also a Kubernetes distribution) and uses [Cilium](https://cilium.io/) as CNI, IPAM, kube-proxy replacement, Load Balancer, and BGP control plane. Persistent volumes are managed by [OpenEBS LVM LocalPV](https://openebs.io/docs/user-guides/local-storage-user-guide/local-pv-lvm/lvm-overview). Applications are deployed using GitOps (this repo) and reconciled on cluster using [Flux](https://fluxcd.io/). Git repository is hosted on [Gitea](https://gitea.io/) running on a cluster itself. Secets are kept in [OpenBao](https://openbao.org/) (HashiCorp Vault fork) running on a cluster and synced to cluster objects using [Vault Secrets Operator](https://github.com/hashicorp/vault-secrets-operator). Deployments are kept up to date using self hosted [Renovate](https://www.mend.io/renovate/) bot updating manifests in the Git repository. Incoming HTTP traffic is routed to cluster using [Nginx Ingress Controller](https://kubernetes.github.io/ingress-nginx/) and certificates are issued by [cert-manager](https://cert-manager.io/) with [Let's Encrypt](https://letsencrypt.org/) ACME issuer with [cert-manager-webhook-ovh](https://github.com/aureq/cert-manager-webhook-ovh) resolving DNS-01 challanges. Cluster also runs [CloudNativePG](https://cloudnative-pg.io/) operator for managing PostgreSQL databases. Router is running [Mikrotik RouterOS](https://help.mikrotik.com/docs/spaces/ROS/pages/328059/RouterOS) and its configuration is managed via [Ansible](https://docs.ansible.com/) playbook in this repo. High level core cluster software architecture is shown on the diagram below.
|
||||
|
||||
> Talos Linux is an immutable Linux distribution purpose-built for running Kubernetes. The OS is distributed as an OCI (Docker) image and does not contain any package manager, shell, SSH, or any other tools for managing the system. Instead, all operations are performed using API, which can be accessed using `talosctl` CLI tool.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
router[MikroTik Router]
|
||||
router -- "Routes HTTP traffic" --> nginx
|
||||
cilium -- "Announces routes via BGP" --> router
|
||||
subgraph cluster[K8s cluster]
|
||||
direction TB
|
||||
flux[Flux CD] -- "Reconciles manifests" --> kubeapi[Kube API Server]
|
||||
flux -- "Fetches Git repo" --> gitea[Gitea]
|
||||
|
||||
|
||||
kubeapi -- "Configs, Services, Pods" --> cilium[Cilium]
|
||||
cilium -- "Routing" --> services[Services] -- "Endpoints" --> pods[Pods]
|
||||
cilium -- "Configures routing, interfaces, IPAM" --> pods[Pods]
|
||||
|
||||
|
||||
kubeapi -- "Ingress rules" --> nginx[NGINX Ingress Controller] -- "Routes HTTP traffic" ---> pods
|
||||
|
||||
kubeapi -- "Certificate requests" --> cert_manager[cert-manager] -- "Provides certificates" --> nginx
|
||||
cert_manager -- "ACME DNS-01 challanges" --> dns_webhook[cert-manager-webhook-ovh] -- "Resolves DNS challanges" --> ovh[OVH DNS]
|
||||
cert_manager -- "Requests DNS-01 challanges" --> acme[Let's Encrypt ACME server] -- "Verifies domain ownership" --> ovh
|
||||
|
||||
kubeapi -- "Assigns pods" --> kubelet[Kubelet] -- "Manages" --> pods
|
||||
|
||||
kubeapi -- "PVs, LvmVols" --> openebs[OpenEBS LVM LocalPV]
|
||||
openebs -- "Mounts volumes" --> pods
|
||||
openebs -- "Manages" --> lv[LVM LVs]
|
||||
|
||||
kubeapi -- "Gets Secret refs" --> vault_operator[Vault Secrets Operator] -- "Syncs secrets" --> kubeapi
|
||||
vault_operator -- "Retrieves secrets" --> vault[OpenBao] -- "Secret storage" --> lv
|
||||
vault -- "Auth method" --> kubeapi
|
||||
|
||||
gitea -- "Stores repositories" --> lv
|
||||
|
||||
gitea --> renovate[Renovate Bot] -- "Updates manifests" --> gitea
|
||||
|
||||
|
||||
end
|
||||
```
|
||||
|
||||
<!-- TODO: Backups, monitoring, logging, deployment with ansible etc -->
|
||||
|
||||
## Software
|
||||
1. Running applications
|
||||
1. NAS, backups, security recorder
|
||||
2. Online presence, website, email, communicators (ts3, matrix?)
|
||||
3. Git server, container registry
|
||||
4. Environment to deploy my own apps
|
||||
5. Some LLM server, apps for my own use
|
||||
6. Public services like Tor, mirrors of linux distros etc.
|
||||
7. [Some frontends](https://libredirect.github.io/)
|
||||
8. [Awesome-Selfhosted](https://github.com/awesome-selfhosted/awesome-selfhosted), [Awesome Sysadmin](https://github.com/awesome-foss/awesome-sysadmin)
|
||||
2. Managing them hopefully using GitOps
|
||||
1. FluxCD, Argo etc.
|
||||
2. State of cluster in git, all apps version pinned
|
||||
3. Some bot to inform about updates?
|
||||
3. It's a home**lab**
|
||||
1. Should be open to experimenting
|
||||
2. Avoiding vendor lock-in, changing my mind shouldn't block me for too long
|
||||
3. Backups of important data in easy to access format
|
||||
4. Expecting downtime, no critical workloads
|
||||
5. Trying to keep it reasonably up anyways
|
||||
|
||||
### Infrastructure
|
||||
|
||||
### Operating systems
|
||||
1. Using commodity hardware
|
||||
2. Reasonably scalable
|
||||
3. Preferably mobile workloads, software should be a bit more flexible than me moving disks and data
|
||||
4. Replication is overkill for most data
|
||||
5. Preferably dynamically configured network
|
||||
1. BGP with OpenWRT router
|
||||
2. Dynamically allocated host subnets
|
||||
3. Load-balancing (MetalLB?), ECMP on router
|
||||
4. Static IP configurations on nodes
|
||||
6. IPv6 native, IPv4 accessible
|
||||
1. IPv6 has whole block routed to us which gives us control over address routing and usage
|
||||
2. Which allows us to expose services directly to the internet without complex router config
|
||||
3. Which allows us to use eg. ExternalDNS to autoconfigure domain names for LB
|
||||
4. But majority of the world still runs IPv4, which should be supported for public services
|
||||
5. Exposing IPv4 service may require additional reconfiguration of router, port forwarding, manual domain setting or controller doing this some day in future
|
||||
6. One public IPv4 address means probably extensive use of rule-based ingress controllers
|
||||
7. IPv6 internet from pods should not be NATed
|
||||
8. IPv4 internet from pods should be NATed by router
|
||||
|
||||
| Logo | Name | Description |
|
||||
|------|------|-------------|
|
||||
| <img src="docs/assets/talos.svg" alt="Talos Linux" height="50" width="50"> | Talos Linux | Kubernetes distribution and operating system for cluster nodes |
|
||||
| <img src="docs/assets/mikrotik.svg" alt="MikroTik RouterOS" height="50" width="50"> | MikroTik RouterOS | Router operating system for MikroTik devices |
|
||||
### Current implementation idea
|
||||
|
||||
### Configuration management
|
||||
1. Cluster server nodes running Talos
|
||||
2. OpenWRT router
|
||||
1. VLAN / virtual interface, for cluster
|
||||
2. Configuring using Ansible
|
||||
3. Peering with cluster using BGP
|
||||
4. Load-balancing using ECMP
|
||||
3. Cluster networking
|
||||
1. Cilium CNI
|
||||
2. Native routing, no encapsulation or overlay
|
||||
3. Using Cilium's network policies for firewall needs
|
||||
4. IPv6 address pool
|
||||
1. Nodes: 2001:470:61a3:100::/64
|
||||
2. Pods: 2001:470:61a3:200::/64
|
||||
3. Services: 2001:470:61a3:300::/112
|
||||
4. Load balancer: 2001:470:61a3:400::/112
|
||||
5. IPv4 address pool
|
||||
1. Nodes: 192.168.1.32/27
|
||||
2. Pods: 10.42.0.0/16
|
||||
3. Services: 10.43.0.0/16
|
||||
4. Load balancer: 10.44.0.0/16
|
||||
4. Storage
|
||||
1. OS is installed on dedicated disk
|
||||
2. Mayastor managing all data disks
|
||||
1. DiskPool for each data disk in cluster, labelled by type SSD or HDD
|
||||
2. Creating StorageClass for each topology need (type, whether to replicate, on which node etc.)
|
||||
|
||||
| Logo | Name | Description |
|
||||
|------|------|-------------|
|
||||
| <img src="docs/assets/flux.svg" alt="Flux CD" height="50" width="50"> | Flux CD | GitOps operator for reconciling cluster state with Git repository |
|
||||
| <img src="docs/assets/ansible.svg" alt="Ansible" height="50" width="50"> | Ansible | Configuration management and automation tool |
|
||||
| | Vault Secrets Operator | Kubernetes operator for syncing secrets from OpenBao/Vault to Kubernetes |
|
||||
## Working with repo
|
||||
|
||||
### Networking
|
||||
Repo is preconfigured to use with nix and vscode
|
||||
|
||||
| Logo | Name | Description |
|
||||
|------|------|-------------|
|
||||
| <img src="docs/assets/cilium.svg" alt="Cilium" height="50" width="50"> | Cilium | CNI, BGP control plane, kube-proxy replacement and Load Balancer for cluster networking |
|
||||
| <img src="docs/assets/nginx.svg" alt="Nginx" height="50" width="50"> | Nginx Ingress Controller | Ingress controller for routing external traffic to services in the cluster |
|
||||
| <img src="docs/assets/cert-manager.svg" alt="cert-manager" height="50" width="50"> | cert-manager | Automatic TLS certificate management |
|
||||
Install nix, vscode should pick up settings and launch terminals in `nix develop` with all needed utils.
|
||||
|
||||
### Storage
|
||||
## Bootstrapping cluster
|
||||
|
||||
| Logo | Name | Description |
|
||||
|------|------|-------------|
|
||||
| <img src="docs/assets/openebs.svg" alt="OpenEBS" height="50" width="50"> | OpenEBS LVM LocalPV | Container Storage Interface for managing persistent volumes on local LVM pools |
|
||||
| <img src="docs/assets/openbao.svg" alt="OpenBao" height="50" width="50"> | OpenBao | Secret storage (HashiCorp Vault compatible) |
|
||||
| <img src="docs/assets/cloudnativepg.svg" alt="CloudNativePG" height="50" width="50"> | CloudNativePG | PostgreSQL operator for managing PostgreSQL instances |
|
||||
1. Configure OpenWRT, create dedicated interface for connecting server
|
||||
1. Set up node subnet, routing
|
||||
2. Create static host entry `kube-api.homelab.lumpiasty.xyz` pointing at ipv6 of first node
|
||||
2. Connect server
|
||||
3. Grab Talos ISO, dd it to usb stick
|
||||
4. Boot it and using keyboard set up static ip ipv6 subnet, should become reachable from pc
|
||||
5. `talosctl gen config homelab https://kube-api.homelab.lumpiasty.xyz:6443`
|
||||
6. Generate secrets `talosctl gen secrets`, **backup, keep `secrets.yml` safe**
|
||||
7. Generate config files `make gen-talos-config`
|
||||
8. Apply config to first node `talosctl apply-config --insecure -n 2001:470:61a3:100::2 -f controlplane.yml`
|
||||
9. Wait for reboot then `talosctl bootstrap --talosconfig=talosconfig -n 2001:470:61a3:100::2`
|
||||
10. Set up router and CNI
|
||||
|
||||
### Development tools
|
||||
## Updating Talos config
|
||||
|
||||
| Logo | Name | Description |
|
||||
|------|------|-------------|
|
||||
| <img src="docs/assets/devenv.svg" alt="devenv" height="50" width="50"> | devenv | Tool for declarative managment of development environment using Nix |
|
||||
| <img src="docs/assets/renovate.svg" alt="Renovate" height="50" width="50"> | Renovate | Bot for keeping dependencies up to date |
|
||||
Update patches and re-generate and apply configs.
|
||||
|
||||
### AI infrastructure
|
||||
|
||||
| Logo | Name | Address | Description |
|
||||
|------|------|---------|-------------|
|
||||
| <img src="docs/assets/llama-cpp.svg" alt="LLaMA.cpp" height="50" width="50"> | LLaMA.cpp | https://llama.lumpiasty.xyz/ | LLM inference server running local models with GPU acceleration |
|
||||
|
||||
### Applications/Services
|
||||
|
||||
| Logo | Name | Address | Description |
|
||||
|------|------|---------|-------------|
|
||||
| <img src="docs/assets/gitea.svg" alt="Gitea" height="50" width="50"> | Gitea | https://gitea.lumpiasty.xyz/ | Private Git repository hosting and artifact storage (Docker, Helm charts) |
|
||||
| <img src="docs/assets/open-webui.png" alt="Open WebUI" height="50" width="50"> | Open WebUI | https://openwebui.lumpiasty.xyz/ | Web UI for chatting with LLMs running on the cluster |
|
||||
| <img src="docs/assets/teamspeak.svg" alt="iSpeak3" height="50" width="50"> | iSpeak3.pl | [ts3server://ispeak3.pl](ts3server://ispeak3.pl) | Public TeamSpeak 3 voice communication server |
|
||||
| <img src="docs/assets/immich.svg" alt="Immich" height="50" width="50"> | Immich | https://immich.lumpiasty.xyz/ | Self-hosted photo and video backup and streaming service |
|
||||
| <img src="docs/assets/frigate.svg" alt="Frigate" height="50" width="50"> | Frigate | https://frigate.lumpiasty.xyz/ | NVR for camera system with AI object detection and classification |
|
||||
|
||||
|
||||
## Development
|
||||
|
||||
This repo leverages [devenv](https://devenv.sh/) for easy setup of a development environment. Install devenv, clone this repo and run `devenv shell` to make the tools and enviornment variables available in your shell. Alternatively, you can use direnv to automate enabling enviornment after entering directory in your shell. You can also install [direnv extension](https://marketplace.visualstudio.com/items?itemName=mkhl.direnv) in VSCode to automatically set up environment after opening workspace so all the fancy intellisense and extensions detect stuff correctly.
|
||||
|
||||
### App deployment
|
||||
|
||||
This repo is being watched by Flux running on cluster. To change config/add new app, simply commit to this repo and wait a while for cluster to reconcile changes. You can speed up this process by "notifying" Flux using `flux reconcile source git flux-system`.
|
||||
|
||||
Flux watches 3 kustomizations in this repo:
|
||||
|
||||
- flux-system - [cluster/flux-system](cluster/flux-system) directory, contains flux manifests
|
||||
- infra - [infra](infra) directory, contains cluster infrastructure manifests like storage classes, network policies, monitoring etc.
|
||||
- apps - [apps](apps) directory, contains manifests for applications deployed on cluster
|
||||
|
||||
### Talos config changes
|
||||
|
||||
Talos config in this repo is stored as yaml patches under [talos/patches](talos/patches) directory. Those patches can then be compiled into full Talos config files using `make gen-talos-config` command. Full config can then be applied to cluster using `make apply-talos-config` command, which applies config to all nodes in cluster.
|
||||
|
||||
To compile config, you need to have secrets file, which contains certificates and keys for cluster. Those secrets are then incorporated into final config files. That is also why we can not store full config in repo.
|
||||
|
||||
### Router config changes
|
||||
|
||||
Router config is stored as Ansible playbook under `ansible/` directory. To apply changes to router, run `ansible-playbook playbooks/routeros.yml` command in `ansible/` directory Before running playbook, you can check what changes will be applied to router using `--check` flag to `ansible-playbook` command, which will run playbook in "check mode" and show you the changes that would be applied without actually applying them. This is useful for verifying that your changes are correct before applying them to the router.
|
||||
|
||||
To run Ansible playbook, you need to have required Ansible collections installed. You can install them using `ansible-galaxy collection install -r ansible/requirements.yml` command. Configuring this in devenv is yet to be done, so you might need to install collections manually for now.
|
||||
|
||||
Secrets needed to access the router API are stored in OpenBao and loaded on demand when running playbook so you need to have access to appropriate secrets.
|
||||
|
||||
### Kube API access
|
||||
|
||||
To generate kubeconfig for accessing cluster API, run `make get-kubeconfig` command, which will generate kubeconfig under `talos/generated/kubeconfig` path. Devenv automatically sets `KUBECONFIG` enviornment variable to point to this file, so you can start using `kubectl` right away.
|
||||
|
||||
Like above, you need secrets file to generate kubeconfig.
|
||||
|
||||
<!-- TODO: Add instructions for setting up Router -->
|
||||
```
|
||||
make gen-talos-config
|
||||
make apply-talos-config
|
||||
```
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
## RouterOS Ansible
|
||||
|
||||
This directory contains the new Ansible automation for the MikroTik router.
|
||||
|
||||
- Transport: RouterOS API (`community.routeros` collection), not SSH CLI scraping.
|
||||
- Layout: one playbook (`playbooks/routeros.yml`) importing domain task files from `tasks/`.
|
||||
- Goal: idempotent convergence using `community.routeros.api_modify` for managed paths.
|
||||
|
||||
### Quick start
|
||||
|
||||
1. Install dependencies:
|
||||
- `ansible-galaxy collection install -r ansible/requirements.yml`
|
||||
- `python -m pip install librouteros hvac`
|
||||
2. Configure secret references in `ansible/vars/routeros-secrets.yml`.
|
||||
3. Store required fields in OpenBao under configured KV path.
|
||||
4. Export token (`OPENBAO_TOKEN` or `VAULT_TOKEN`).
|
||||
5. Run:
|
||||
- `ANSIBLE_CONFIG=ansible/ansible.cfg ansible-playbook ansible/playbooks/routeros.yml`
|
||||
|
||||
More details and design rationale: `docs/ansible/routeros-design.md`.
|
||||
@@ -1,5 +0,0 @@
|
||||
[defaults]
|
||||
inventory = inventory/hosts.yml
|
||||
host_key_checking = False
|
||||
retry_files_enabled = False
|
||||
result_format = yaml
|
||||
2
ansible/hosts
Normal file
2
ansible/hosts
Normal file
@@ -0,0 +1,2 @@
|
||||
[openwrt]
|
||||
2001:470:61a3:100:ffff:ffff:ffff:ffff ansible_scp_extra_args="-O"
|
||||
@@ -1,6 +0,0 @@
|
||||
all:
|
||||
children:
|
||||
mikrotik:
|
||||
hosts:
|
||||
crs418:
|
||||
ansible_host: 192.168.255.10
|
||||
6
ansible/playbook.yml
Normal file
6
ansible/playbook.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
- name: Configure router
|
||||
hosts: openwrt
|
||||
remote_user: root
|
||||
roles:
|
||||
- ansible-openwrt
|
||||
- router
|
||||
@@ -1,92 +0,0 @@
|
||||
---
|
||||
- name: Converge MikroTik RouterOS config
|
||||
hosts: mikrotik
|
||||
gather_facts: false
|
||||
connection: local
|
||||
|
||||
vars_files:
|
||||
- ../vars/routeros-secrets.yml
|
||||
|
||||
pre_tasks:
|
||||
- name: Load router secrets from OpenBao
|
||||
ansible.builtin.set_fact:
|
||||
routeros_api_username: >-
|
||||
{{
|
||||
lookup(
|
||||
'community.hashi_vault.vault_kv2_get',
|
||||
openbao_fields.routeros_api.path,
|
||||
engine_mount_point=openbao_kv_mount
|
||||
).secret[openbao_fields.routeros_api.username_key]
|
||||
}}
|
||||
routeros_api_password: >-
|
||||
{{
|
||||
lookup(
|
||||
'community.hashi_vault.vault_kv2_get',
|
||||
openbao_fields.routeros_api.path,
|
||||
engine_mount_point=openbao_kv_mount
|
||||
).secret[openbao_fields.routeros_api.password_key]
|
||||
}}
|
||||
routeros_pppoe_username: >-
|
||||
{{
|
||||
lookup(
|
||||
'community.hashi_vault.vault_kv2_get',
|
||||
openbao_fields.wan_pppoe.path,
|
||||
engine_mount_point=openbao_kv_mount
|
||||
).secret[openbao_fields.wan_pppoe.username_key]
|
||||
}}
|
||||
routeros_pppoe_password: >-
|
||||
{{
|
||||
lookup(
|
||||
'community.hashi_vault.vault_kv2_get',
|
||||
openbao_fields.wan_pppoe.path,
|
||||
engine_mount_point=openbao_kv_mount
|
||||
).secret[openbao_fields.wan_pppoe.password_key]
|
||||
}}
|
||||
routeros_tailscale_container_password: >-
|
||||
{{
|
||||
lookup(
|
||||
'community.hashi_vault.vault_kv2_get',
|
||||
openbao_fields.routeros_tailscale_container.path,
|
||||
engine_mount_point=openbao_kv_mount
|
||||
).secret[openbao_fields.routeros_tailscale_container.container_password_key]
|
||||
}}
|
||||
no_log: true
|
||||
|
||||
module_defaults:
|
||||
group/community.routeros.api:
|
||||
hostname: "{{ ansible_host }}"
|
||||
username: "{{ routeros_api_username }}"
|
||||
password: "{{ routeros_api_password }}"
|
||||
tls: true
|
||||
validate_certs: false
|
||||
validate_cert_hostname: false
|
||||
force_no_cert: true
|
||||
encoding: UTF-8
|
||||
|
||||
tasks:
|
||||
- name: Preflight checks
|
||||
ansible.builtin.import_tasks: ../tasks/preflight.yml
|
||||
|
||||
- name: Base network configuration
|
||||
ansible.builtin.import_tasks: ../tasks/base.yml
|
||||
|
||||
- name: WAN and tunnel interfaces
|
||||
ansible.builtin.import_tasks: ../tasks/wan.yml
|
||||
|
||||
- name: Hardware and platform tuning
|
||||
ansible.builtin.import_tasks: ../tasks/hardware.yml
|
||||
|
||||
- name: RouterOS container configuration
|
||||
ansible.builtin.import_tasks: ../tasks/containers.yml
|
||||
|
||||
- name: Addressing configuration
|
||||
ansible.builtin.import_tasks: ../tasks/addressing.yml
|
||||
|
||||
- name: Firewall configuration
|
||||
ansible.builtin.import_tasks: ../tasks/firewall.yml
|
||||
|
||||
- name: Routing configuration
|
||||
ansible.builtin.import_tasks: ../tasks/routing.yml
|
||||
|
||||
- name: System configuration
|
||||
ansible.builtin.import_tasks: ../tasks/system.yml
|
||||
@@ -1,5 +0,0 @@
|
||||
collections:
|
||||
- name: community.routeros
|
||||
version: ">=3.16.0"
|
||||
- name: community.hashi_vault
|
||||
version: ">=7.1.0"
|
||||
53
ansible/roles/router/files/bird.conf
Normal file
53
ansible/roles/router/files/bird.conf
Normal file
@@ -0,0 +1,53 @@
|
||||
# Would never work without this awesome blogpost
|
||||
# https://farcaller.net/2024/making-cilium-bgp-work-with-ipv6/
|
||||
|
||||
log "/tmp/bird.log" all;
|
||||
log syslog all;
|
||||
|
||||
#Router ID
|
||||
router id 192.168.1.1;
|
||||
|
||||
protocol kernel kernel4 {
|
||||
learn;
|
||||
scan time 10;
|
||||
merge paths yes;
|
||||
ipv4 {
|
||||
import none;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
|
||||
protocol kernel kernel6 {
|
||||
learn;
|
||||
scan time 10;
|
||||
merge paths yes;
|
||||
ipv6 {
|
||||
import none;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
|
||||
protocol device {
|
||||
scan time 10;
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
interface "*";
|
||||
}
|
||||
|
||||
protocol bgp homelab {
|
||||
debug { events };
|
||||
passive;
|
||||
direct;
|
||||
local 2001:470:61a3:100:ffff:ffff:ffff:ffff as 65000;
|
||||
neighbor range 2001:470:61a3:100::/64 as 65000;
|
||||
ipv4 {
|
||||
extended next hop yes;
|
||||
import all;
|
||||
export all;
|
||||
};
|
||||
ipv6 {
|
||||
import all;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
5
ansible/roles/router/handlers/main.yml
Normal file
5
ansible/roles/router/handlers/main.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
- name: Reload bird
|
||||
service:
|
||||
name: bird
|
||||
state: restarted
|
||||
enabled: true
|
||||
16
ansible/roles/router/tasks/main.yml
Normal file
16
ansible/roles/router/tasks/main.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
- name: Install bird2
|
||||
opkg:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
# Workaround for opkg module not handling multiple names at once well
|
||||
loop:
|
||||
- bird2
|
||||
- bird2c
|
||||
|
||||
- name: Set up bird.conf
|
||||
ansible.builtin.copy:
|
||||
src: bird.conf
|
||||
dest: /etc/bird.conf
|
||||
mode: "644"
|
||||
notify: Reload bird
|
||||
@@ -1,48 +0,0 @@
|
||||
---
|
||||
- name: Configure IPv4 addresses
|
||||
community.routeros.api_modify:
|
||||
path: ip address
|
||||
data:
|
||||
- address: 172.17.0.1/16
|
||||
interface: dockers
|
||||
network: 172.17.0.0
|
||||
- address: 192.168.4.1/24
|
||||
interface: lo
|
||||
network: 192.168.4.0
|
||||
- address: 192.168.100.20/24
|
||||
interface: sfp-sfpplus1
|
||||
network: 192.168.100.0
|
||||
- address: 192.168.255.10/24
|
||||
interface: bridge1
|
||||
network: 192.168.255.0
|
||||
- address: 192.168.0.1/24
|
||||
interface: vlan2
|
||||
network: 192.168.0.0
|
||||
- address: 192.168.1.1/24
|
||||
interface: vlan4
|
||||
network: 192.168.1.0
|
||||
- address: 192.168.3.1/24
|
||||
interface: vlan3
|
||||
network: 192.168.3.0
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure IPv6 addresses
|
||||
community.routeros.api_modify:
|
||||
path: ipv6 address
|
||||
data:
|
||||
- address: 2001:470:70:dd::2/64
|
||||
advertise: false
|
||||
interface: sit1
|
||||
- address: ::ffff:ffff:ffff:ffff/64
|
||||
from-pool: pool1
|
||||
interface: vlan2
|
||||
- address: 2001:470:61a3:500:ffff:ffff:ffff:ffff/64
|
||||
interface: dockers
|
||||
- address: 2001:470:61a3:100::1/64
|
||||
advertise: false
|
||||
interface: vlan4
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
@@ -1,226 +0,0 @@
|
||||
---
|
||||
- name: Configure bridges
|
||||
community.routeros.api_modify:
|
||||
path: interface bridge
|
||||
data:
|
||||
- name: bridge1
|
||||
vlan-filtering: true
|
||||
- name: dockers
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure VLAN interfaces
|
||||
community.routeros.api_modify:
|
||||
path: interface vlan
|
||||
data:
|
||||
- name: vlan2
|
||||
comment: LAN (PC, WIFI)
|
||||
interface: bridge1
|
||||
vlan-id: 2
|
||||
- name: vlan3
|
||||
comment: KAMERY
|
||||
interface: bridge1
|
||||
vlan-id: 3
|
||||
- name: vlan4
|
||||
comment: SERVER LAN
|
||||
interface: bridge1
|
||||
vlan-id: 4
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure interface lists
|
||||
community.routeros.api_modify:
|
||||
path: interface list
|
||||
data:
|
||||
- name: wan
|
||||
comment: contains interfaces facing internet
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure interface list members
|
||||
community.routeros.api_modify:
|
||||
path: interface list member
|
||||
data:
|
||||
- interface: pppoe-gpon
|
||||
list: wan
|
||||
- interface: lte1
|
||||
list: wan
|
||||
- interface: sit1
|
||||
list: wan
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure bridge ports
|
||||
community.routeros.api_modify:
|
||||
path: interface bridge port
|
||||
data:
|
||||
- bridge: dockers
|
||||
interface: veth1
|
||||
comment: Tailscale container interface
|
||||
- bridge: bridge1
|
||||
interface: ether1
|
||||
pvid: 2
|
||||
- bridge: bridge1
|
||||
interface: ether2
|
||||
pvid: 2
|
||||
- bridge: bridge1
|
||||
interface: ether8
|
||||
pvid: 4
|
||||
- bridge: bridge1
|
||||
interface: ether9
|
||||
pvid: 2
|
||||
- bridge: bridge1
|
||||
interface: ether10
|
||||
pvid: 3
|
||||
- bridge: bridge1
|
||||
interface: sfp-sfpplus2
|
||||
- bridge: bridge1
|
||||
interface: ether11
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure bridge VLAN membership
|
||||
community.routeros.api_modify:
|
||||
path: interface bridge vlan
|
||||
data:
|
||||
- bridge: bridge1
|
||||
tagged: sfp-sfpplus2
|
||||
untagged: ether1,ether2,ether9
|
||||
vlan-ids: 2
|
||||
- bridge: bridge1
|
||||
tagged: sfp-sfpplus2
|
||||
untagged: ether10
|
||||
vlan-ids: 3
|
||||
- bridge: bridge1
|
||||
untagged: ether8
|
||||
vlan-ids: 4
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure IPv4 pools
|
||||
community.routeros.api_modify:
|
||||
path: ip pool
|
||||
data:
|
||||
- name: dhcp_pool0
|
||||
ranges: 192.168.0.50-192.168.0.250
|
||||
comment: LAN DHCP pool
|
||||
- name: dhcp_pool1
|
||||
ranges: 192.168.255.1-192.168.255.9,192.168.255.11-192.168.255.254
|
||||
comment: MGMT DHCP pool
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure DHCP servers
|
||||
community.routeros.api_modify:
|
||||
path: ip dhcp-server
|
||||
data:
|
||||
- name: dhcp1
|
||||
address-pool: dhcp_pool0
|
||||
interface: vlan2
|
||||
lease-time: 30m
|
||||
comment: LAN
|
||||
- name: dhcp2
|
||||
address-pool: dhcp_pool1
|
||||
interface: bridge1
|
||||
lease-time: 30m
|
||||
comment: MGMT
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure DHCP networks
|
||||
community.routeros.api_modify:
|
||||
path: ip dhcp-server network
|
||||
data:
|
||||
- address: 192.168.0.0/24
|
||||
dns-server: 192.168.0.1
|
||||
gateway: 192.168.0.1
|
||||
- address: 192.168.255.0/24
|
||||
dns-none: true
|
||||
gateway: 192.168.255.10
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
# TODO: IPv6 pools are useful when we have dynamic prefix, but we don't
|
||||
# We can remove it now
|
||||
- name: Configure IPv6 pools
|
||||
community.routeros.api_modify:
|
||||
path: ipv6 pool
|
||||
data:
|
||||
- name: pool1
|
||||
prefix: 2001:470:61a3::/48
|
||||
prefix-length: 64
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure DNS
|
||||
community.routeros.api_find_and_modify:
|
||||
ignore_dynamic: false
|
||||
path: ip dns
|
||||
find: {}
|
||||
values:
|
||||
allow-remote-requests: true
|
||||
cache-size: 20480
|
||||
servers: 1.1.1.1,1.0.0.1,2606:4700:4700::1111,2606:4700:4700::1001
|
||||
|
||||
- name: Configure NAT-PMP global settings
|
||||
community.routeros.api_find_and_modify:
|
||||
ignore_dynamic: false
|
||||
path: ip nat-pmp
|
||||
find: {}
|
||||
values:
|
||||
enabled: true
|
||||
|
||||
- name: Configure NAT-PMP interfaces
|
||||
community.routeros.api_modify:
|
||||
path: ip nat-pmp interfaces
|
||||
data:
|
||||
- interface: dockers
|
||||
type: internal
|
||||
- interface: pppoe-gpon
|
||||
type: external
|
||||
- interface: vlan2
|
||||
type: internal
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure UPnP global settings
|
||||
community.routeros.api_find_and_modify:
|
||||
ignore_dynamic: false
|
||||
path: ip upnp
|
||||
find: {}
|
||||
values:
|
||||
enabled: true
|
||||
|
||||
- name: Configure UPnP interfaces
|
||||
community.routeros.api_modify:
|
||||
path: ip upnp interfaces
|
||||
data:
|
||||
- interface: dockers
|
||||
type: internal
|
||||
- interface: pppoe-gpon
|
||||
type: external
|
||||
- interface: vlan2
|
||||
type: internal
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure IPv6 ND defaults
|
||||
community.routeros.api_find_and_modify:
|
||||
ignore_dynamic: false
|
||||
path: ipv6 nd
|
||||
find:
|
||||
default: true
|
||||
values:
|
||||
advertise-dns: true
|
||||
@@ -1,66 +0,0 @@
|
||||
---
|
||||
- name: Configure container runtime defaults
|
||||
community.routeros.api_find_and_modify:
|
||||
ignore_dynamic: false
|
||||
path: container config
|
||||
find: {}
|
||||
values:
|
||||
registry-url: https://ghcr.io
|
||||
tmpdir: /tmp1/pull
|
||||
|
||||
- name: Configure container env lists
|
||||
community.routeros.api_modify:
|
||||
path: container envs
|
||||
data:
|
||||
- key: ADVERTISE_ROUTES
|
||||
list: tailscale
|
||||
value: 192.168.0.0/24,192.168.1.0/24,192.168.4.1/32,192.168.100.1/32,192.168.255.0/24,10.42.0.0/16,10.43.0.0/16,10.44.0.0/16,2001:470:61a3::/48
|
||||
- key: CONTAINER_GATEWAY
|
||||
list: tailscale
|
||||
value: 172.17.0.1
|
||||
- key: PASSWORD
|
||||
list: tailscale
|
||||
value: "{{ routeros_tailscale_container_password }}"
|
||||
- key: TAILSCALE_ARGS
|
||||
list: tailscale
|
||||
value: --accept-routes --advertise-exit-node --snat-subnet-routes=false
|
||||
- key: UPDATE_TAILSCALE
|
||||
list: tailscale
|
||||
value: y
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure container mounts
|
||||
community.routeros.api_modify:
|
||||
path: container mounts
|
||||
data:
|
||||
- dst: /var/lib/tailscale
|
||||
list: tailscale
|
||||
src: /usb1/tailscale
|
||||
- dst: /root
|
||||
list: tailscale-root
|
||||
src: /tmp1/tailscale-root
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure tailscale container
|
||||
community.routeros.api_modify:
|
||||
path: container
|
||||
data:
|
||||
- dns: 172.17.0.1
|
||||
envlists: tailscale
|
||||
hostname: mikrotik
|
||||
interface: veth1
|
||||
layer-dir: ""
|
||||
mountlists: tailscale
|
||||
name: tailscale-mikrotik:latest
|
||||
remote-image: fluent-networks/tailscale-mikrotik:latest
|
||||
root-dir: /usb1/containers/tailscale
|
||||
start-on-boot: true
|
||||
tmpfs: /tmp:67108864:01777
|
||||
workdir: /
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
@@ -1,480 +0,0 @@
|
||||
---
|
||||
- name: Configure IPv4 firewall filter rules
|
||||
community.routeros.api_modify:
|
||||
path: ip firewall filter
|
||||
data:
|
||||
- action: fasttrack-connection
|
||||
chain: forward
|
||||
connection-state: established,related
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow all already established connections
|
||||
connection-state: established,related
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow LTE modem management (next rule forbids it otherwise)
|
||||
dst-address: 192.168.8.1
|
||||
out-interface: lte1
|
||||
- action: reject
|
||||
chain: forward
|
||||
comment: Forbid forwarding 192.168.0.0/16 to WAN
|
||||
dst-address: 192.168.0.0/16
|
||||
out-interface-list: wan
|
||||
reject-with: icmp-network-unreachable
|
||||
- action: reject
|
||||
chain: forward
|
||||
comment: Forbid forwarding 10.0.0.0/8 to WAN
|
||||
dst-address: 10.0.0.0/8
|
||||
out-interface-list: wan
|
||||
reject-with: icmp-network-unreachable
|
||||
- action: reject
|
||||
chain: forward
|
||||
comment: Forbid forwarding 172.16.0.0/12 to WAN
|
||||
dst-address: 172.16.0.0/12
|
||||
out-interface-list: wan
|
||||
reject-with: icmp-network-unreachable
|
||||
- action: reject
|
||||
chain: forward
|
||||
comment: Forbid forwarding 100.64.0.0/10 to WAN
|
||||
dst-address: 100.64.0.0/10
|
||||
out-interface-list: wan
|
||||
reject-with: icmp-network-unreachable
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow from LAN to everywhere
|
||||
in-interface: vlan2
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow from SRV to internet
|
||||
in-interface: vlan4
|
||||
out-interface-list: wan
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow from SRV to CAM
|
||||
in-interface: vlan4
|
||||
out-interface: vlan3
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow from dockers to everywhere
|
||||
in-interface: dockers
|
||||
- action: jump
|
||||
chain: forward
|
||||
comment: Allow port forwards
|
||||
in-interface: pppoe-gpon
|
||||
jump-target: allow-ports
|
||||
- action: reject
|
||||
chain: forward
|
||||
comment: Reject all remaining (port unreachable from WAN)
|
||||
in-interface-list: wan
|
||||
log-prefix: FORWARD REJECT
|
||||
reject-with: icmp-port-unreachable
|
||||
- action: reject
|
||||
chain: forward
|
||||
comment: Reject all remaining (net prohibited from LAN)
|
||||
log-prefix: FORWARD REJECT
|
||||
reject-with: icmp-net-prohibited
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow all already established connections
|
||||
connection-state: established,related
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow HE tunnel
|
||||
in-interface: pppoe-gpon
|
||||
protocol: ipv6-encap
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow ICMP
|
||||
protocol: icmp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow Winbox
|
||||
dst-port: 8291
|
||||
log: true
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow SSH Mikrotik
|
||||
dst-port: 2137
|
||||
log: true
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow RouterOS API-SSL from MGMT
|
||||
dst-port: 8729
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow DNS from LAN
|
||||
dst-port: 53
|
||||
in-interface: vlan2
|
||||
protocol: udp
|
||||
- action: accept
|
||||
chain: input
|
||||
dst-port: 53
|
||||
in-interface: vlan2
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow DNS from SRV
|
||||
dst-port: 53
|
||||
in-interface: vlan4
|
||||
protocol: udp
|
||||
- action: accept
|
||||
chain: input
|
||||
dst-port: 53
|
||||
in-interface: vlan4
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow DNS from dockers
|
||||
dst-port: 53
|
||||
in-interface: dockers
|
||||
protocol: udp
|
||||
- action: accept
|
||||
chain: input
|
||||
dst-port: 53
|
||||
in-interface: dockers
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow BGP from SRV
|
||||
dst-port: 179
|
||||
in-interface: vlan4
|
||||
protocol: udp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: NAT-PMP from LAN
|
||||
dst-port: 5351
|
||||
in-interface: vlan2
|
||||
protocol: udp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: NAT-PMP from dockers (for tailscale)
|
||||
dst-port: 5351
|
||||
in-interface: dockers
|
||||
protocol: udp
|
||||
- action: reject
|
||||
chain: input
|
||||
comment: Reject all remaining
|
||||
log-prefix: INPUT REJECT
|
||||
reject-with: icmp-port-unreachable
|
||||
- action: accept
|
||||
chain: allow-ports
|
||||
comment: Allow TS3
|
||||
dst-port: 9987
|
||||
out-interface: vlan4
|
||||
protocol: udp
|
||||
- action: accept
|
||||
chain: allow-ports
|
||||
dst-port: 30033
|
||||
out-interface: vlan4
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: allow-ports
|
||||
comment: Allow HTTP
|
||||
dst-port: 80
|
||||
out-interface: vlan4
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: allow-ports
|
||||
comment: Allow HTTPS
|
||||
dst-port: 443
|
||||
out-interface: vlan4
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: allow-ports
|
||||
comment: Allow SSH Gitea
|
||||
dst-port: 22
|
||||
out-interface: vlan4
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: allow-ports
|
||||
comment: Allow anything udp to Tailscale
|
||||
dst-address: 172.17.0.2
|
||||
out-interface: dockers
|
||||
protocol: udp
|
||||
- action: accept
|
||||
chain: allow-ports
|
||||
comment: Allow anything from GPON to LAN (NAT-PMP)
|
||||
dst-address: 192.168.0.0/24
|
||||
in-interface: pppoe-gpon
|
||||
out-interface: vlan2
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure IPv4 NAT rules
|
||||
community.routeros.api_modify:
|
||||
path: ip firewall nat
|
||||
data:
|
||||
- action: masquerade
|
||||
chain: srcnat
|
||||
comment: Masquerade to internet
|
||||
out-interface-list: wan
|
||||
- action: masquerade
|
||||
chain: srcnat
|
||||
comment: GPON ONT management
|
||||
dst-address: 192.168.100.1
|
||||
- action: masquerade
|
||||
chain: srcnat
|
||||
comment: LTE Modem management
|
||||
dst-address: 192.168.8.1
|
||||
- action: dst-nat
|
||||
chain: dstnat
|
||||
comment: TS3
|
||||
dst-address: 139.28.40.212
|
||||
dst-port: 9987
|
||||
protocol: udp
|
||||
to-addresses: 10.44.0.0
|
||||
- action: dst-nat
|
||||
chain: dstnat
|
||||
dst-address: 139.28.40.212
|
||||
dst-port: 30033
|
||||
protocol: tcp
|
||||
to-addresses: 10.44.0.0
|
||||
- action: src-nat
|
||||
chain: srcnat
|
||||
comment: src-nat from LAN to TS3 to some Greenland address
|
||||
dst-address: 10.44.0.0
|
||||
dst-port: 9987
|
||||
in-interface: '!pppoe-gpon'
|
||||
protocol: udp
|
||||
to-addresses: 128.0.70.5
|
||||
- action: src-nat
|
||||
chain: srcnat
|
||||
dst-address: 10.44.0.0
|
||||
dst-port: 30033
|
||||
in-interface: '!pppoe-gpon'
|
||||
protocol: tcp
|
||||
to-addresses: 128.0.70.5
|
||||
- action: dst-nat
|
||||
chain: dstnat
|
||||
comment: HTTPS
|
||||
dst-address: 139.28.40.212
|
||||
dst-port: 443
|
||||
protocol: tcp
|
||||
to-addresses: 10.44.0.6
|
||||
- action: dst-nat
|
||||
chain: dstnat
|
||||
comment: HTTP
|
||||
dst-address: 139.28.40.212
|
||||
dst-port: 80
|
||||
protocol: tcp
|
||||
to-addresses: 10.44.0.6
|
||||
- action: dst-nat
|
||||
chain: dstnat
|
||||
comment: SSH Gitea
|
||||
dst-address: 139.28.40.212
|
||||
dst-port: 22
|
||||
protocol: tcp
|
||||
to-addresses: 10.44.0.6
|
||||
- action: dst-nat
|
||||
chain: dstnat
|
||||
comment: sunshine
|
||||
dst-address: 139.28.40.212
|
||||
dst-port: 47984
|
||||
in-interface: pppoe-gpon
|
||||
protocol: tcp
|
||||
to-addresses: 192.168.0.67
|
||||
- action: dst-nat
|
||||
chain: dstnat
|
||||
comment: sunshine
|
||||
dst-address: 139.28.40.212
|
||||
dst-port: 47989
|
||||
in-interface: pppoe-gpon
|
||||
protocol: tcp
|
||||
to-addresses: 192.168.0.67
|
||||
- action: dst-nat
|
||||
chain: dstnat
|
||||
comment: sunshine
|
||||
dst-address: 139.28.40.212
|
||||
dst-port: 48010
|
||||
in-interface: pppoe-gpon
|
||||
protocol: tcp
|
||||
to-addresses: 192.168.0.67
|
||||
- action: dst-nat
|
||||
chain: dstnat
|
||||
comment: sunshine
|
||||
dst-address: 139.28.40.212
|
||||
dst-port: 48010
|
||||
in-interface: pppoe-gpon
|
||||
protocol: udp
|
||||
to-addresses: 192.168.0.67
|
||||
- action: dst-nat
|
||||
chain: dstnat
|
||||
comment: sunshine
|
||||
dst-address: 139.28.40.212
|
||||
dst-port: 47998-48000
|
||||
in-interface: pppoe-gpon
|
||||
protocol: udp
|
||||
to-addresses: 192.168.0.67
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure IPv6 firewall filter rules
|
||||
community.routeros.api_modify:
|
||||
path: ipv6 firewall filter
|
||||
data:
|
||||
- action: fasttrack-connection
|
||||
chain: forward
|
||||
connection-state: established,related
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow all already established connections
|
||||
connection-state: established,related
|
||||
- action: reject
|
||||
chain: forward
|
||||
comment: Forbid forwarding routed /48 from tunnelbroker to WAN
|
||||
dst-address: 2001:470:61a3::/48
|
||||
out-interface-list: wan
|
||||
reject-with: icmp-no-route
|
||||
- action: reject
|
||||
chain: forward
|
||||
comment: Forbid forwarding routed /64 from tunnelbroker to WAN
|
||||
dst-address: 2001:470:71:dd::/64
|
||||
out-interface-list: wan
|
||||
reject-with: icmp-no-route
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow from LAN to everywhere
|
||||
in-interface: vlan2
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow ICMPv6 from internet to LAN
|
||||
in-interface-list: wan
|
||||
out-interface: vlan2
|
||||
protocol: icmpv6
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow from SRV to internet
|
||||
in-interface: vlan4
|
||||
out-interface-list: wan
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow from internet to SRV nodes
|
||||
dst-address: 2001:470:61a3:100::/64
|
||||
in-interface-list: wan
|
||||
out-interface: vlan4
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow from internet to homelab LB
|
||||
dst-address: 2001:470:61a3:400::/112
|
||||
in-interface-list: wan
|
||||
out-interface: vlan4
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow from SRV to CAM
|
||||
in-interface: vlan4
|
||||
out-interface: vlan3
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow from dockers to everywhere
|
||||
in-interface: dockers
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow from internet to dockers
|
||||
dst-address: 2001:470:61a3:500::/64
|
||||
in-interface-list: wan
|
||||
out-interface: dockers
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow tcp transmission port to LAN
|
||||
dst-port: 51413
|
||||
out-interface: vlan2
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: forward
|
||||
comment: Allow udp transmission port to LAN
|
||||
dst-port: 51413
|
||||
out-interface: vlan2
|
||||
protocol: udp
|
||||
- action: reject
|
||||
chain: forward
|
||||
comment: Reject all remaining
|
||||
reject-with: icmp-no-route
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow all already established connections
|
||||
connection-state: established,related
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow ICMPv6
|
||||
protocol: icmpv6
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow Winbox
|
||||
dst-port: 8291
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow SSH Mikrotik
|
||||
dst-port: 2137
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow DNS from LAN
|
||||
dst-port: 53
|
||||
in-interface: vlan2
|
||||
protocol: udp
|
||||
- action: accept
|
||||
chain: input
|
||||
dst-port: 53
|
||||
in-interface: vlan2
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow DNS from SRV
|
||||
dst-port: 53
|
||||
in-interface: vlan4
|
||||
protocol: udp
|
||||
- action: accept
|
||||
chain: input
|
||||
dst-port: 53
|
||||
in-interface: vlan4
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow DNS from dockers
|
||||
dst-port: 53
|
||||
in-interface: dockers
|
||||
protocol: udp
|
||||
- action: accept
|
||||
chain: input
|
||||
dst-port: 53
|
||||
in-interface: dockers
|
||||
protocol: tcp
|
||||
- action: accept
|
||||
chain: input
|
||||
comment: Allow BGP from SRV
|
||||
dst-port: 179
|
||||
in-interface: vlan4
|
||||
protocol: tcp
|
||||
src-address: 2001:470:61a3:100::/64
|
||||
- action: reject
|
||||
chain: input
|
||||
comment: Reject all remaining
|
||||
reject-with: icmp-admin-prohibited
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure IPv6 NAT rules
|
||||
community.routeros.api_modify:
|
||||
path: ipv6 firewall nat
|
||||
data:
|
||||
- action: src-nat
|
||||
chain: srcnat
|
||||
comment: src-nat tailnet to internet
|
||||
out-interface-list: wan
|
||||
src-address: fd7a:115c:a1e0::/48
|
||||
to-address: 2001:470:61a3:600::/64
|
||||
- action: masquerade
|
||||
chain: srcnat
|
||||
disabled: true
|
||||
in-interface: vlan2
|
||||
out-interface: vlan4
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
@@ -1,103 +0,0 @@
|
||||
---
|
||||
- name: Configure ethernet interface metadata and SFP options
|
||||
community.routeros.api_find_and_modify:
|
||||
ignore_dynamic: false
|
||||
path: interface ethernet
|
||||
find:
|
||||
default-name: "{{ item.default_name }}"
|
||||
values: "{{ item.config }}"
|
||||
loop:
|
||||
- default_name: ether1
|
||||
config:
|
||||
comment: Mój pc
|
||||
- default_name: ether2
|
||||
config:
|
||||
comment: Wifi środek
|
||||
- default_name: ether8
|
||||
config:
|
||||
comment: Serwer
|
||||
- default_name: ether9
|
||||
config:
|
||||
comment: Wifi góra
|
||||
- default_name: ether10
|
||||
config:
|
||||
comment: Kamera na domu
|
||||
- default_name: ether11
|
||||
config:
|
||||
comment: KVM serwer
|
||||
- default_name: sfp-sfpplus1
|
||||
config:
|
||||
auto-negotiation: false
|
||||
comment: GPON WAN
|
||||
speed: 2.5G-baseX
|
||||
- default_name: sfp-sfpplus2
|
||||
config:
|
||||
comment: GARAŻ
|
||||
loop_control:
|
||||
label: "{{ item.default_name }}"
|
||||
|
||||
- name: Configure LTE interface defaults
|
||||
community.routeros.api_find_and_modify:
|
||||
ignore_dynamic: false
|
||||
path: interface lte
|
||||
find:
|
||||
default-name: lte1
|
||||
values:
|
||||
apn-profiles: default-nodns
|
||||
comment: Backup LTE WAN
|
||||
|
||||
- name: Configure LTE APN profiles
|
||||
community.routeros.api_modify:
|
||||
path: interface lte apn
|
||||
data:
|
||||
- add-default-route: false
|
||||
apn: internet
|
||||
comment: default but without dns and default route
|
||||
ipv6-interface: lte1
|
||||
name: default-nodns
|
||||
use-network-apn: true
|
||||
use-peer-dns: false
|
||||
# Default APN we can't really remove yet I don't want to reconfigure it
|
||||
- add-default-route: true
|
||||
apn: internet
|
||||
authentication: none
|
||||
default-route-distance: 2
|
||||
ip-type: auto
|
||||
name: default
|
||||
use-network-apn: true
|
||||
use-peer-dns: true
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
|
||||
- name: Configure temporary disk for containers
|
||||
community.routeros.api_modify:
|
||||
path: disk
|
||||
data:
|
||||
- slot: tmp1
|
||||
type: tmpfs
|
||||
# This is not ideal, there's no unique identifier for usb disk,
|
||||
# after reinstall it might be assigned to another slot
|
||||
# Just adding disk with slot usb1 and not specifying anything else
|
||||
# so ansible doesn't touch it
|
||||
- slot: usb1
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
|
||||
- name: Configure switch settings
|
||||
community.routeros.api_find_and_modify:
|
||||
ignore_dynamic: false
|
||||
path: interface ethernet switch
|
||||
find:
|
||||
.id: "0"
|
||||
values:
|
||||
qos-hw-offloading: true
|
||||
# Enabling L3 offloading would cause all packets to skip firewall and NAT
|
||||
l3-hw-offloading: false
|
||||
|
||||
- name: Configure neighbor discovery settings
|
||||
community.routeros.api_find_and_modify:
|
||||
ignore_dynamic: false
|
||||
path: ip neighbor discovery-settings
|
||||
find: {}
|
||||
values:
|
||||
discover-interface-list: '!dynamic'
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
- name: Verify API connectivity and fetch basic facts
|
||||
community.routeros.api_facts:
|
||||
gather_subset:
|
||||
- default
|
||||
- hardware
|
||||
|
||||
- name: Show target identity
|
||||
ansible.builtin.debug:
|
||||
msg: "Managing {{ ansible_host }} ({{ ansible_facts['net_model'] | default('unknown model') }})"
|
||||
|
||||
- name: Assert expected router model
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ansible_facts['net_model'] is defined
|
||||
- ansible_facts['net_model'] == "CRS418-8P-8G-2S+"
|
||||
fail_msg: "Unexpected router model: {{ ansible_facts['net_model'] | default('unknown') }}"
|
||||
success_msg: "Router model matches expected CRS418-8P-8G-2S+"
|
||||
|
||||
- name: Read RouterOS device-mode flags
|
||||
community.routeros.api:
|
||||
path: system/device-mode
|
||||
register: routeros_device_mode
|
||||
check_mode: false
|
||||
changed_when: false
|
||||
|
||||
- name: Assert container feature is enabled in device mode
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- not (routeros_device_mode.skipped | default(false))
|
||||
- (routeros_device_mode | to_nice_json | lower) is search('container[^a-z0-9]+(yes|true)')
|
||||
fail_msg: "RouterOS device-mode does not report container as enabled. Payload: {{ routeros_device_mode | to_nice_json }}"
|
||||
success_msg: "RouterOS device-mode confirms container=yes"
|
||||
|
||||
- name: Read configured disks
|
||||
community.routeros.api_info:
|
||||
path: disk
|
||||
register: routeros_disks
|
||||
check_mode: false
|
||||
|
||||
- name: Assert usb1 disk is present
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- (routeros_disks.result | selectattr('slot', 'equalto', 'usb1') | list | length) > 0
|
||||
fail_msg: "Required disk slot usb1 is not present on router."
|
||||
success_msg: "Required disk usb1 is present"
|
||||
@@ -1,99 +0,0 @@
|
||||
---
|
||||
- name: Configure IPv4 routes
|
||||
community.routeros.api_modify:
|
||||
path: ip route
|
||||
data:
|
||||
- comment: Tailnet
|
||||
disabled: false
|
||||
distance: 1
|
||||
dst-address: 100.64.0.0/10
|
||||
gateway: 172.17.0.2
|
||||
routing-table: main
|
||||
scope: 30
|
||||
suppress-hw-offload: false
|
||||
target-scope: 10
|
||||
- disabled: false
|
||||
distance: 1
|
||||
dst-address: 0.0.0.0/0
|
||||
gateway: pppoe-gpon
|
||||
routing-table: main
|
||||
scope: 30
|
||||
suppress-hw-offload: false
|
||||
target-scope: 10
|
||||
vrf-interface: pppoe-gpon
|
||||
- disabled: false
|
||||
distance: 2
|
||||
dst-address: 0.0.0.0/0
|
||||
gateway: 192.168.8.1
|
||||
routing-table: main
|
||||
scope: 30
|
||||
suppress-hw-offload: false
|
||||
target-scope: 10
|
||||
vrf-interface: lte1
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
|
||||
- name: Configure IPv6 routes
|
||||
community.routeros.api_modify:
|
||||
path: ipv6 route
|
||||
data:
|
||||
- disabled: false
|
||||
distance: 1
|
||||
dst-address: 2000::/3
|
||||
gateway: 2001:470:70:dd::1
|
||||
scope: 30
|
||||
target-scope: 10
|
||||
- comment: Tailnet
|
||||
disabled: false
|
||||
dst-address: fd7a:115c:a1e0::/48
|
||||
gateway: 2001:470:61a3:500::1
|
||||
pref-src: ""
|
||||
routing-table: main
|
||||
suppress-hw-offload: false
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
|
||||
- name: Configure BGP instance
|
||||
community.routeros.api_modify:
|
||||
path: routing bgp instance
|
||||
data:
|
||||
- name: bgp-homelab
|
||||
as: 65000
|
||||
disabled: false
|
||||
router-id: 192.168.1.1
|
||||
routing-table: main
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure BGP templates
|
||||
community.routeros.api_modify:
|
||||
path: routing bgp template
|
||||
data:
|
||||
- name: klaster
|
||||
afi: ip,ipv6
|
||||
as: 6500
|
||||
disabled: false
|
||||
# Default template
|
||||
- name: default
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
|
||||
- name: Configure BGP connections
|
||||
community.routeros.api_modify:
|
||||
path: routing bgp connection
|
||||
data:
|
||||
- name: bgp1
|
||||
afi: ip,ipv6
|
||||
as: 65000
|
||||
connect: true
|
||||
disabled: false
|
||||
instance: bgp-homelab
|
||||
listen: true
|
||||
local.role: ibgp
|
||||
remote.address: 2001:470:61a3:100::3/128
|
||||
routing-table: main
|
||||
templates: klaster
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
@@ -1,43 +0,0 @@
|
||||
---
|
||||
- name: Configure system clock
|
||||
community.routeros.api_find_and_modify:
|
||||
ignore_dynamic: false
|
||||
path: system clock
|
||||
find: {}
|
||||
values:
|
||||
time-zone-name: Europe/Warsaw
|
||||
|
||||
- name: Configure dedicated Ansible management user
|
||||
community.routeros.api_modify:
|
||||
path: user
|
||||
data:
|
||||
- name: "{{ routeros_api_username }}"
|
||||
group: full
|
||||
password: "{{ routeros_api_password }}"
|
||||
disabled: false
|
||||
comment: "Ansible management user"
|
||||
handle_absent_entries: ignore
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
|
||||
- name: Configure service ports and service enablement
|
||||
community.routeros.api_find_and_modify:
|
||||
ignore_dynamic: false
|
||||
path: ip service
|
||||
find:
|
||||
name: "{{ item.name }}"
|
||||
values: "{{ item }}"
|
||||
loop:
|
||||
- name: ftp
|
||||
disabled: true
|
||||
- name: telnet
|
||||
disabled: true
|
||||
- name: www
|
||||
disabled: true
|
||||
- name: ssh
|
||||
port: 2137
|
||||
- name: api
|
||||
disabled: true
|
||||
- name: api-ssl
|
||||
disabled: false
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
@@ -1,44 +0,0 @@
|
||||
---
|
||||
- name: Configure PPPoE client
|
||||
community.routeros.api_modify:
|
||||
path: interface pppoe-client
|
||||
data:
|
||||
- disabled: false
|
||||
interface: sfp-sfpplus1
|
||||
keepalive-timeout: 2
|
||||
name: pppoe-gpon
|
||||
password: "{{ routeros_pppoe_password }}"
|
||||
use-peer-dns: true
|
||||
user: "{{ routeros_pppoe_username }}"
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure 6to4 tunnel interface
|
||||
community.routeros.api_modify:
|
||||
path: interface 6to4
|
||||
data:
|
||||
- comment: Hurricane Electric IPv6 Tunnel Broker
|
||||
local-address: 139.28.40.212
|
||||
mtu: 1472
|
||||
name: sit1
|
||||
remote-address: 216.66.80.162
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
|
||||
- name: Configure veth interface for containers
|
||||
community.routeros.api_modify:
|
||||
path: interface veth
|
||||
data:
|
||||
- address: 172.17.0.2/16,2001:470:61a3:500::1/64
|
||||
container-mac-address: 7E:7E:A1:B1:2A:7C
|
||||
dhcp: false
|
||||
gateway: 172.17.0.1
|
||||
gateway6: 2001:470:61a3:500:ffff:ffff:ffff:ffff
|
||||
mac-address: 7E:7E:A1:B1:2A:7B
|
||||
name: veth1
|
||||
comment: Tailscale container
|
||||
handle_absent_entries: remove
|
||||
handle_entries_content: remove_as_much_as_possible
|
||||
ensure_order: true
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
# Secret references only; actual values are loaded from OpenBao/Vault at runtime.
|
||||
|
||||
# KVv2 mount and secret path (full secret path is <mount>/data/<path>).
|
||||
openbao_kv_mount: secret
|
||||
|
||||
# Field names expected in the OpenBao secret.
|
||||
openbao_fields:
|
||||
routeros_api:
|
||||
path: routeros_api
|
||||
username_key: username
|
||||
password_key: password
|
||||
wan_pppoe:
|
||||
path: wan_pppoe
|
||||
username_key: username
|
||||
password_key: password
|
||||
routeros_tailscale_container:
|
||||
path: router_tailscale
|
||||
container_password_key: container_password
|
||||
@@ -1,8 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- postgres-volume.yaml
|
||||
- postgres-cluster.yaml
|
||||
- secret.yaml
|
||||
- release.yaml
|
||||
@@ -1,4 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: authentik
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
metadata:
|
||||
name: authentik-postgresql-cluster-lvmhdd
|
||||
namespace: authentik
|
||||
spec:
|
||||
instances: 1
|
||||
|
||||
imageName: ghcr.io/cloudnative-pg/postgresql:17.4
|
||||
|
||||
bootstrap:
|
||||
initdb:
|
||||
database: authentik
|
||||
owner: authentik
|
||||
|
||||
storage:
|
||||
pvcTemplate:
|
||||
storageClassName: hdd-lvmpv
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
volumeName: authentik-postgresql-cluster-lvmhdd-1
|
||||
@@ -1,33 +0,0 @@
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: authentik-postgresql-cluster-lvmhdd-1
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 10Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-hdd$
|
||||
volGroup: openebs-hdd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: authentik-postgresql-cluster-lvmhdd-1
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: authentik-postgresql-cluster-lvmhdd-1
|
||||
---
|
||||
# PVCs are dynamically created by the Postgres operator
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: authentik
|
||||
namespace: authentik
|
||||
spec:
|
||||
interval: 24h
|
||||
url: https://charts.goauthentik.io
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: authentik
|
||||
namespace: authentik
|
||||
spec:
|
||||
interval: 30m
|
||||
chart:
|
||||
spec:
|
||||
chart: authentik
|
||||
version: 2026.2.1
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: authentik
|
||||
namespace: authentik
|
||||
interval: 12h
|
||||
values:
|
||||
authentik:
|
||||
postgresql:
|
||||
host: authentik-postgresql-cluster-lvmhdd-rw
|
||||
name: authentik
|
||||
user: authentik
|
||||
|
||||
global:
|
||||
env:
|
||||
- name: AUTHENTIK_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: authentik-secret
|
||||
key: secret_key
|
||||
- name: AUTHENTIK_POSTGRESQL__PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: authentik-postgresql-cluster-lvmhdd-app
|
||||
key: password
|
||||
|
||||
postgresql:
|
||||
enabled: false
|
||||
|
||||
server:
|
||||
ingress:
|
||||
enabled: true
|
||||
ingressClassName: nginx-ingress
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt
|
||||
hosts:
|
||||
- authentik.lumpiasty.xyz
|
||||
tls:
|
||||
- secretName: authentik-ingress
|
||||
hosts:
|
||||
- authentik.lumpiasty.xyz
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: authentik-secret
|
||||
namespace: authentik
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultAuth
|
||||
metadata:
|
||||
name: authentik
|
||||
namespace: authentik
|
||||
spec:
|
||||
method: kubernetes
|
||||
mount: kubernetes
|
||||
kubernetes:
|
||||
role: authentik
|
||||
serviceAccount: authentik-secret
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: authentik-secret
|
||||
namespace: authentik
|
||||
spec:
|
||||
type: kv-v2
|
||||
|
||||
mount: secret
|
||||
path: authentik
|
||||
|
||||
destination:
|
||||
create: true
|
||||
name: authentik-secret
|
||||
type: Opaque
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
|
||||
vaultAuthRef: authentik
|
||||
@@ -1,48 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: crawl4ai-proxy
|
||||
namespace: crawl4ai
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: crawl4ai-proxy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: crawl4ai-proxy
|
||||
spec:
|
||||
containers:
|
||||
- name: crawl4ai-proxy
|
||||
image: gitea.lumpiasty.xyz/lumpiasty/crawl4ai-proxy-fit:latest
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: LISTEN_PORT
|
||||
value: "8000"
|
||||
- name: CRAWL4AI_ENDPOINT
|
||||
value: http://crawl4ai.crawl4ai.svc.cluster.local:11235/crawl
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8000
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 2
|
||||
failureThreshold: 6
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 15
|
||||
timeoutSeconds: 2
|
||||
failureThreshold: 6
|
||||
resources:
|
||||
requests:
|
||||
cpu: 25m
|
||||
memory: 32Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 128Mi
|
||||
@@ -1,5 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
@@ -1,14 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: crawl4ai-proxy
|
||||
namespace: crawl4ai
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: crawl4ai-proxy
|
||||
ports:
|
||||
- name: http
|
||||
port: 8000
|
||||
targetPort: 8000
|
||||
protocol: TCP
|
||||
@@ -1,62 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: crawl4ai
|
||||
namespace: crawl4ai
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: crawl4ai
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: crawl4ai
|
||||
spec:
|
||||
containers:
|
||||
- name: crawl4ai
|
||||
image: unclecode/crawl4ai:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: CRAWL4AI_API_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: crawl4ai-secret
|
||||
key: api_token
|
||||
optional: false
|
||||
- name: MAX_CONCURRENT_TASKS
|
||||
value: "5"
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 11235
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 6
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 15
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 6
|
||||
resources:
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 1Gi
|
||||
limits:
|
||||
cpu: "2"
|
||||
memory: 4Gi
|
||||
volumeMounts:
|
||||
- name: dshm
|
||||
mountPath: /dev/shm
|
||||
volumes:
|
||||
- name: dshm
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
sizeLimit: 1Gi
|
||||
@@ -1,4 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: crawl4ai
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: crawl4ai-secret
|
||||
namespace: crawl4ai
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultAuth
|
||||
metadata:
|
||||
name: crawl4ai
|
||||
namespace: crawl4ai
|
||||
spec:
|
||||
method: kubernetes
|
||||
mount: kubernetes
|
||||
kubernetes:
|
||||
role: crawl4ai
|
||||
serviceAccount: crawl4ai-secret
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: crawl4ai-secret
|
||||
namespace: crawl4ai
|
||||
spec:
|
||||
type: kv-v2
|
||||
|
||||
mount: secret
|
||||
path: crawl4ai
|
||||
|
||||
destination:
|
||||
create: true
|
||||
name: crawl4ai-secret
|
||||
type: Opaque
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
|
||||
vaultAuthRef: crawl4ai
|
||||
@@ -1,14 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: crawl4ai
|
||||
namespace: crawl4ai
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: crawl4ai
|
||||
ports:
|
||||
- name: http
|
||||
port: 11235
|
||||
targetPort: 11235
|
||||
protocol: TCP
|
||||
@@ -1,49 +0,0 @@
|
||||
# garm
|
||||
|
||||
This app deploys `garm` with external `garm-provider-k8s`.
|
||||
|
||||
- API/UI ingress: `https://garm.lumpiasty.xyz`
|
||||
- Internal service DNS: `http://garm.garm.svc.cluster.local:9997`
|
||||
|
||||
## Vault secret requirements
|
||||
|
||||
`VaultStaticSecret` reads `secret/data/garm` and expects at least:
|
||||
|
||||
- `jwt_auth_secret`
|
||||
- `database_passphrase` (must be 32 characters)
|
||||
|
||||
## Connect garm to Gitea
|
||||
|
||||
After Flux reconciles this app, initialize garm and add Gitea endpoint/credentials.
|
||||
|
||||
```bash
|
||||
# 1) Initialize garm (from your local devenv shell)
|
||||
garm-cli init \
|
||||
--name homelab \
|
||||
--url https://garm.lumpiasty.xyz \
|
||||
--username admin \
|
||||
--email admin@lumpiasty.xyz \
|
||||
--password '<STRONG_ADMIN_PASSWORD>' \
|
||||
--metadata-url http://garm.garm.svc.cluster.local:9997/api/v1/metadata \
|
||||
--callback-url http://garm.garm.svc.cluster.local:9997/api/v1/callbacks \
|
||||
--webhook-url http://garm.garm.svc.cluster.local:9997/webhooks
|
||||
|
||||
# 2) Add Gitea endpoint
|
||||
garm-cli gitea endpoint create \
|
||||
--name local-gitea \
|
||||
--description 'Cluster Gitea' \
|
||||
--base-url http://gitea-http.gitea.svc.cluster.local:80 \
|
||||
--api-base-url http://gitea-http.gitea.svc.cluster.local:80/api/v1
|
||||
|
||||
# 3) Add Gitea PAT credentials
|
||||
garm-cli gitea credentials add \
|
||||
--name gitea-pat \
|
||||
--description 'PAT for garm' \
|
||||
--endpoint local-gitea \
|
||||
--auth-type pat \
|
||||
--pat-oauth-token '<GITEA_PAT_WITH_write:repository,write:organization>'
|
||||
```
|
||||
|
||||
Then add repositories/orgs and create pools against provider `kubernetes_external`.
|
||||
|
||||
If Gitea refuses webhook installation to cluster-local URLs, set `gitea.config.webhook.ALLOWED_HOST_LIST` in `apps/gitea/release.yaml`.
|
||||
@@ -1,19 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: garm-provider-k8s-config
|
||||
namespace: garm
|
||||
data:
|
||||
provider-config.yaml: |
|
||||
kubeConfigPath: ""
|
||||
runnerNamespace: "garm-runners"
|
||||
podTemplate:
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
flavors:
|
||||
default:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
memory: 2Gi
|
||||
@@ -1,106 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: garm
|
||||
namespace: garm
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: garm
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: garm
|
||||
spec:
|
||||
serviceAccountName: garm
|
||||
initContainers:
|
||||
- name: render-garm-config
|
||||
image: alpine:3.23
|
||||
env:
|
||||
- name: JWT_AUTH_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: garm-config
|
||||
key: jwt_auth_secret
|
||||
- name: DATABASE_PASSPHRASE
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: garm-config
|
||||
key: database_passphrase
|
||||
command:
|
||||
- /bin/sh
|
||||
- -ec
|
||||
- |
|
||||
cat <<EOF > /etc/garm/config.toml
|
||||
[default]
|
||||
enable_webhook_management = true
|
||||
|
||||
[logging]
|
||||
enable_log_streamer = true
|
||||
log_format = "text"
|
||||
log_level = "info"
|
||||
log_source = false
|
||||
|
||||
[metrics]
|
||||
enable = true
|
||||
disable_auth = false
|
||||
|
||||
[jwt_auth]
|
||||
secret = "${JWT_AUTH_SECRET}"
|
||||
time_to_live = "8760h"
|
||||
|
||||
[apiserver]
|
||||
bind = "0.0.0.0"
|
||||
port = 9997
|
||||
use_tls = false
|
||||
[apiserver.webui]
|
||||
enable = true
|
||||
|
||||
[database]
|
||||
backend = "sqlite3"
|
||||
passphrase = "${DATABASE_PASSPHRASE}"
|
||||
[database.sqlite3]
|
||||
db_file = "/data/garm.db"
|
||||
busy_timeout_seconds = 5
|
||||
|
||||
[[provider]]
|
||||
name = "kubernetes_external"
|
||||
description = "Kubernetes provider"
|
||||
provider_type = "external"
|
||||
[provider.external]
|
||||
config_file = "/etc/garm/provider-config.yaml"
|
||||
provider_executable = "/opt/garm/providers.d/garm-provider-k8s"
|
||||
environment_variables = ["KUBERNETES_"]
|
||||
EOF
|
||||
volumeMounts:
|
||||
- name: config-dir
|
||||
mountPath: /etc/garm
|
||||
containers:
|
||||
- name: garm
|
||||
image: gitea.lumpiasty.xyz/lumpiasty/garm-k8s:r1380
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /bin/garm
|
||||
- --config
|
||||
- /etc/garm/config.toml
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 9997
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
- name: config-dir
|
||||
mountPath: /etc/garm
|
||||
- name: provider-config
|
||||
mountPath: /etc/garm/provider-config.yaml
|
||||
subPath: provider-config.yaml
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: garm-lvmhdd
|
||||
- name: config-dir
|
||||
emptyDir: {}
|
||||
- name: provider-config
|
||||
configMap:
|
||||
name: garm-provider-k8s-config
|
||||
@@ -1,5 +0,0 @@
|
||||
# renovate: datasource=github-refs depName=cloudbase/garm versioning=git
|
||||
GARM_COMMIT=818a9dddccba5f2843f185e6a846770988f31fc5
|
||||
GARM_COMMIT_NUMBER=1380
|
||||
GARM_IMAGE_REPO=gitea.lumpiasty.xyz/lumpiasty/garm-k8s
|
||||
GARM_IMAGE=gitea.lumpiasty.xyz/lumpiasty/garm-k8s:r1380
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- pvc.yaml
|
||||
- configmap.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
- rbac.yaml
|
||||
- secret.yaml
|
||||
- deployment.yaml
|
||||
@@ -1,9 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: garm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: garm-runners
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: garm-lvmhdd
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 5Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-hdd$
|
||||
volGroup: openebs-hdd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: garm-lvmhdd
|
||||
spec:
|
||||
capacity:
|
||||
storage: 5Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: garm-lvmhdd
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: garm-lvmhdd
|
||||
namespace: garm
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeName: garm-lvmhdd
|
||||
@@ -1,51 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: garm
|
||||
namespace: garm
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: garm-provider-k8s
|
||||
namespace: garm-runners
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods", "pods/log", "configmaps", "secrets", "events"]
|
||||
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: garm-provider-k8s
|
||||
namespace: garm-runners
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: garm
|
||||
namespace: garm
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: garm-provider-k8s
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: garm-namespace-manager
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces"]
|
||||
verbs: ["get"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: garm-namespace-manager
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: garm
|
||||
namespace: garm
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: garm-namespace-manager
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultAuth
|
||||
metadata:
|
||||
name: garm
|
||||
namespace: garm
|
||||
spec:
|
||||
method: kubernetes
|
||||
mount: kubernetes
|
||||
kubernetes:
|
||||
role: garm
|
||||
serviceAccount: garm
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: garm-config
|
||||
namespace: garm
|
||||
spec:
|
||||
type: kv-v2
|
||||
|
||||
mount: secret
|
||||
path: garm
|
||||
|
||||
destination:
|
||||
create: true
|
||||
name: garm-config
|
||||
type: Opaque
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
|
||||
vaultAuthRef: garm
|
||||
@@ -1,14 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: garm
|
||||
namespace: garm
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: garm
|
||||
ports:
|
||||
- name: http
|
||||
port: 9997
|
||||
targetPort: 9997
|
||||
protocol: TCP
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: gitea-shared-storage-lvmhdd
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 10Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-hdd$
|
||||
volGroup: openebs-hdd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: gitea-shared-storage-lvmhdd
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: gitea-shared-storage-lvmhdd
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: gitea-shared-storage-lvmhdd
|
||||
namespace: gitea
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeName: gitea-shared-storage-lvmhdd
|
||||
@@ -4,8 +4,6 @@ resources:
|
||||
- namespace.yaml
|
||||
- postgres-volume.yaml
|
||||
- postgres-cluster.yaml
|
||||
- gitea-shared-volume.yaml
|
||||
- valkey-volume.yaml
|
||||
- release.yaml
|
||||
- secret.yaml
|
||||
- backups.yaml
|
||||
|
||||
@@ -2,27 +2,15 @@
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
metadata:
|
||||
name: gitea-postgresql-cluster-lvmhdd
|
||||
name: gitea-postgresql-cluster
|
||||
namespace: gitea
|
||||
spec:
|
||||
instances: 1
|
||||
|
||||
imageName: ghcr.io/cloudnative-pg/postgresql:17.4
|
||||
|
||||
storage:
|
||||
pvcTemplate:
|
||||
storageClassName: hdd-lvmpv
|
||||
resources:
|
||||
requests:
|
||||
storage: 20Gi
|
||||
volumeName: gitea-postgresql-cluster-lvmhdd-1
|
||||
size: 10Gi
|
||||
storageClass: mayastor-single-hdd
|
||||
|
||||
# Just to avoid bootstrapping the instance agian
|
||||
# I migrated data manually using pv_migrate because this feature is broken
|
||||
# when source and target volumes are in different storage classes
|
||||
# CNPG just sets dataSource to the PVC and expects the underlying storage
|
||||
# to handle the migration, but it doesn't work here
|
||||
bootstrap:
|
||||
recovery:
|
||||
backup:
|
||||
name: backup-migration
|
||||
backup:
|
||||
volumeSnapshot:
|
||||
className: csi-mayastor-snapshotclass
|
||||
|
||||
@@ -23,11 +23,10 @@ spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: hdd-lvmpv
|
||||
storageClassName: openebs-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: gitea-postgresql-cluster-lvmhdd-1
|
||||
---
|
||||
# PVCs are dynamically created by the Postgres operator
|
||||
|
||||
@@ -45,35 +45,31 @@ spec:
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true
|
||||
existingClaim: gitea-valkey-primary-lvmhdd-0
|
||||
storageClass: mayastor-single-hdd
|
||||
resources:
|
||||
requests:
|
||||
cpu: 0
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
# We'll create PV and PVC manually
|
||||
create: false
|
||||
claimName: gitea-shared-storage-lvmhdd
|
||||
storageClass: mayastor-single-hdd
|
||||
|
||||
gitea:
|
||||
additionalConfigFromEnvs:
|
||||
- name: GITEA__DATABASE__PASSWD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: gitea-postgresql-cluster-lvmhdd-app
|
||||
name: gitea-postgresql-cluster-app
|
||||
key: password
|
||||
config:
|
||||
database:
|
||||
DB_TYPE: postgres
|
||||
HOST: gitea-postgresql-cluster-lvmhdd-rw:5432
|
||||
HOST: gitea-postgresql-cluster-rw:5432
|
||||
NAME: app
|
||||
USER: app
|
||||
indexer:
|
||||
ISSUE_INDEXER_TYPE: bleve
|
||||
REPO_INDEXER_ENABLED: true
|
||||
webhook:
|
||||
ALLOWED_HOST_LIST: garm.garm.svc.cluster.local,woodpecker.lumpiasty.xyz
|
||||
admin:
|
||||
username: GiteaAdmin
|
||||
email: gi@tea.com
|
||||
@@ -90,11 +86,6 @@ spec:
|
||||
# Requirement for sharing ip with other service
|
||||
externalTrafficPolicy: Cluster
|
||||
ipFamilyPolicy: RequireDualStack
|
||||
http:
|
||||
type: ClusterIP
|
||||
# We need the service to be at port 80 specifically
|
||||
# to work around bug of Actions Runner
|
||||
port: 80
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
@@ -102,7 +93,6 @@ spec:
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt
|
||||
acme.cert-manager.io/http01-edit-in-place: "true"
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "1g"
|
||||
hosts:
|
||||
- host: gitea.lumpiasty.xyz
|
||||
paths:
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: gitea-valkey-primary-lvmhdd-0
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 1Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-hdd$
|
||||
volGroup: openebs-hdd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: gitea-valkey-primary-lvmhdd-0
|
||||
spec:
|
||||
capacity:
|
||||
storage: 1Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: gitea-valkey-primary-lvmhdd-0
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: gitea-valkey-primary-lvmhdd-0
|
||||
namespace: gitea
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeName: gitea-valkey-primary-lvmhdd-0
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: immich-library-lvmhdd
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 150Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-hdd$
|
||||
volGroup: openebs-hdd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: immich-library-lvmhdd
|
||||
spec:
|
||||
capacity:
|
||||
storage: 150Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: immich-library-lvmhdd
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: library-lvmhdd
|
||||
namespace: immich
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 150Gi
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeName: immich-library-lvmhdd
|
||||
@@ -2,10 +2,8 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- valkey-volume.yaml
|
||||
- volume.yaml
|
||||
- redis.yaml
|
||||
- postgres-password.yaml
|
||||
- postgres-volume.yaml
|
||||
- postgres-cluster.yaml
|
||||
- immich-library.yaml
|
||||
- release.yaml
|
||||
|
||||
@@ -2,31 +2,21 @@
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
metadata:
|
||||
name: immich-db-lvmhdd
|
||||
name: immich-db
|
||||
namespace: immich
|
||||
spec:
|
||||
# TODO: Configure renovate to handle imageName
|
||||
imageName: ghcr.io/tensorchord/cloudnative-vectorchord:14-0.4.3
|
||||
|
||||
instances: 1
|
||||
|
||||
storage:
|
||||
pvcTemplate:
|
||||
storageClassName: hdd-lvmpv
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
volumeName: immich-db-lvmhdd-1
|
||||
|
||||
# Just to avoid bootstrapping the instance again
|
||||
# I migrated data manually using pv_migrate because this feature is broken
|
||||
# when source and target volumes are in different storage classes
|
||||
# CNPG just sets dataSource to the PVC and expects the underlying storage
|
||||
# to handle the migration, but it doesn't work here
|
||||
size: 10Gi
|
||||
storageClass: mayastor-single-hdd
|
||||
bootstrap:
|
||||
recovery:
|
||||
backup:
|
||||
name: backup-migration
|
||||
initdb:
|
||||
# Defaults of immich chart
|
||||
database: immich
|
||||
owner: immich
|
||||
|
||||
# We need to create custom role because default one does not allow to set up
|
||||
# vectorchord extension
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: immich-db-lvmhdd-1
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 10Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-hdd$
|
||||
volGroup: openebs-hdd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: immich-db-lvmhdd-1
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: immich-db-lvmhdd-1
|
||||
---
|
||||
# PVCs are dynamically created by the Postgres operator
|
||||
@@ -2,35 +2,28 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: valkey
|
||||
name: bitnami
|
||||
namespace: immich
|
||||
spec:
|
||||
interval: 24h
|
||||
url: https://valkey.io/valkey-helm/
|
||||
type: "oci"
|
||||
url: oci://registry-1.docker.io/bitnamicharts/
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: valkey
|
||||
name: redis
|
||||
namespace: immich
|
||||
spec:
|
||||
interval: 30m
|
||||
chart:
|
||||
spec:
|
||||
chart: valkey
|
||||
version: 0.9.3
|
||||
chart: redis
|
||||
version: 24.1.3
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: valkey
|
||||
name: bitnami
|
||||
values:
|
||||
dataStorage:
|
||||
enabled: true
|
||||
persistentVolumeClaimName: immich-valkey
|
||||
|
||||
auth:
|
||||
enabled: true
|
||||
usersExistingSecret: redis
|
||||
aclUsers:
|
||||
default:
|
||||
passwordKey: redis-password
|
||||
permissions: "~* &* +@all"
|
||||
global:
|
||||
defaultStorageClass: mayastor-single-hdd
|
||||
architecture: standalone
|
||||
|
||||
@@ -18,7 +18,7 @@ spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: immich
|
||||
version: 1.2.2
|
||||
version: 1.0.12
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: secustor
|
||||
@@ -27,14 +27,14 @@ spec:
|
||||
config:
|
||||
vecotrExtension: vectorchord
|
||||
postgres:
|
||||
host: immich-db-lvmhdd-rw
|
||||
host: immich-db-rw
|
||||
existingSecret:
|
||||
enabled: true
|
||||
secretName: immich-db-immich
|
||||
usernameKey: username
|
||||
passwordKey: password
|
||||
redis:
|
||||
host: valkey
|
||||
host: redis-master
|
||||
existingSecret:
|
||||
enabled: true
|
||||
secretName: redis
|
||||
@@ -47,7 +47,7 @@ spec:
|
||||
volumes:
|
||||
- name: uploads
|
||||
persistentVolumeClaim:
|
||||
claimName: library-lvmhdd
|
||||
claimName: library
|
||||
|
||||
machineLearning:
|
||||
enabled: true
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: immich-valkey
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 1Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-hdd$
|
||||
volGroup: openebs-hdd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: immich-valkey
|
||||
spec:
|
||||
capacity:
|
||||
storage: 1Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: immich-valkey
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: immich-valkey
|
||||
namespace: immich
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeName: immich-valkey
|
||||
13
apps/immich/volume.yaml
Normal file
13
apps/immich/volume.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: library
|
||||
namespace: immich
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 150Gi
|
||||
storageClassName: mayastor-single-hdd
|
||||
@@ -1,10 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- crawl4ai
|
||||
- crawl4ai-proxy
|
||||
- authentik
|
||||
- gitea
|
||||
- registry
|
||||
- renovate
|
||||
- librechat
|
||||
- frigate
|
||||
@@ -13,6 +11,3 @@ resources:
|
||||
- nas
|
||||
- searxng
|
||||
- ispeak3
|
||||
- openwebui
|
||||
- garm
|
||||
- woodpecker
|
||||
|
||||
@@ -16,7 +16,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: caddy
|
||||
image: caddy:2.11.2-alpine
|
||||
image: caddy:2.10.2-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
volumeMounts:
|
||||
- mountPath: /etc/caddy
|
||||
|
||||
@@ -1,260 +1,468 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/mostlygeek/llama-swap/refs/heads/main/config-schema.json
|
||||
healthCheckTimeout: 600
|
||||
logToStdout: "both" # proxy and upstream
|
||||
|
||||
macros:
|
||||
base_args: "--no-warmup --port ${PORT}"
|
||||
common_args: "--fit-target 1536 --no-warmup --port ${PORT}"
|
||||
gemma3_ctx_128k: "--ctx-size 131072"
|
||||
qwen35_ctx_128k: "--ctx-size 131072"
|
||||
qwen35_ctx_256k: "--ctx-size 262144"
|
||||
gemma_sampling: "--prio 2 --temp 1.0 --repeat-penalty 1.0 --min-p 0.00 --top-k 64 --top-p 0.95"
|
||||
qwen35_sampling: "--temp 0.6 --top-p 0.95 --top-k 20 --min-p 0.00 -ctk q8_0 -ctv q8_0"
|
||||
qwen35_35b_args: "--temp 1.0 --min-p 0.00 --top-p 0.95 --top-k 20 -ctk q8_0 -ctv q8_0"
|
||||
qwen35_35b_heretic_mmproj: "--mmproj-url https://huggingface.co/unsloth/Qwen3.5-35B-A3B-GGUF/resolve/main/mmproj-F16.gguf --mmproj /root/.cache/llama.cpp/unsloth_Qwen3.5-35B-A3B-GGUF_mmproj-F16.gguf"
|
||||
qwen35_4b_heretic_mmproj: "--mmproj-url https://huggingface.co/unsloth/Qwen3.5-4B-GGUF/resolve/main/mmproj-F16.gguf --mmproj /root/.cache/llama.cpp/unsloth_Qwen3.5-4B-GGUF_mmproj-F16.gguf"
|
||||
glm47_flash_args: "--temp 0.7 --top-p 1.0 --min-p 0.01 --repeat-penalty 1.0"
|
||||
thinking_on: "--chat-template-kwargs '{\"enable_thinking\": true}'"
|
||||
thinking_off: "--chat-template-kwargs '{\"enable_thinking\": false}'"
|
||||
|
||||
peers:
|
||||
openrouter:
|
||||
proxy: https://openrouter.ai/api
|
||||
apiKey: ${env.OPENROUTER_API_KEY}
|
||||
models:
|
||||
- z-ai/glm-5
|
||||
|
||||
hooks:
|
||||
on_startup:
|
||||
preload:
|
||||
- "Qwen3.5-0.8B-GGUF-nothink:Q4_K_XL"
|
||||
|
||||
groups:
|
||||
always:
|
||||
persistent: true
|
||||
exclusive: false
|
||||
swap: false
|
||||
members:
|
||||
- "Qwen3.5-0.8B-GGUF-nothink:Q4_K_XL"
|
||||
|
||||
models:
|
||||
"DeepSeek-R1-0528-Qwen3-8B-GGUF":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/DeepSeek-R1-0528-Qwen3-8B-GGUF:Q4_K_M
|
||||
--n-gpu-layers 37
|
||||
--ctx-size 16384
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3-8B-GGUF":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3-8B-GGUF:Q4_K_M
|
||||
--n-gpu-layers 37
|
||||
--ctx-size 16384
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3-8B-GGUF-no-thinking":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3-8B-GGUF:Q4_K_M
|
||||
--n-gpu-layers 37
|
||||
--ctx-size 16384
|
||||
--jinja
|
||||
--chat-template-file /config/qwen_nothink_chat_template.jinja
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"gemma3n-e4b":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/gemma-3n-E4B-it-GGUF:UD-Q4_K_XL
|
||||
--ctx-size 16384
|
||||
--n-gpu-layers 99
|
||||
--seed 3407
|
||||
--prio 2
|
||||
--temp 1.0
|
||||
--repeat-penalty 1.0
|
||||
--min-p 0.00
|
||||
--top-k 64
|
||||
--top-p 0.95
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"gemma3-12b":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/gemma-3-12b-it-GGUF:Q4_K_M
|
||||
${gemma3_ctx_128k}
|
||||
${gemma_sampling}
|
||||
${common_args}
|
||||
--ctx-size 16384
|
||||
--n-gpu-layers 99
|
||||
--prio 2
|
||||
--temp 1.0
|
||||
--repeat-penalty 1.0
|
||||
--min-p 0.00
|
||||
--top-k 64
|
||||
--top-p 0.95
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"gemma3-12b-novision":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/gemma-3-12b-it-GGUF:Q4_K_M
|
||||
${gemma3_ctx_128k}
|
||||
${gemma_sampling}
|
||||
--ctx-size 16384
|
||||
--n-gpu-layers 99
|
||||
--prio 2
|
||||
--temp 1.0
|
||||
--repeat-penalty 1.0
|
||||
--min-p 0.00
|
||||
--top-k 64
|
||||
--top-p 0.95
|
||||
--no-mmproj
|
||||
${common_args}
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"gemma3-12b-q2":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/gemma-3-12b-it-GGUF:Q2_K_L
|
||||
--ctx-size 16384
|
||||
--n-gpu-layers 99
|
||||
--prio 2
|
||||
--temp 1.0
|
||||
--repeat-penalty 1.0
|
||||
--min-p 0.00
|
||||
--top-k 64
|
||||
--top-p 0.95
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"gemma3-4b":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/gemma-3-4b-it-GGUF:Q4_K_M
|
||||
${gemma3_ctx_128k}
|
||||
${gemma_sampling}
|
||||
${common_args}
|
||||
--ctx-size 16384
|
||||
--n-gpu-layers 99
|
||||
--prio 2
|
||||
--temp 1.0
|
||||
--repeat-penalty 1.0
|
||||
--min-p 0.00
|
||||
--top-k 64
|
||||
--top-p 0.95
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"gemma3-4b-novision":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/gemma-3-4b-it-GGUF:Q4_K_M
|
||||
${gemma3_ctx_128k}
|
||||
${gemma_sampling}
|
||||
--no-mmproj
|
||||
${common_args}
|
||||
|
||||
"Qwen3-Coder-Next-GGUF:Q4_K_M":
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3-Coder-Next-GGUF:Q4_K_M
|
||||
--ctx-size 65536
|
||||
--predict 8192
|
||||
--ctx-size 16384
|
||||
--n-gpu-layers 99
|
||||
--prio 2
|
||||
--temp 1.0
|
||||
--min-p 0.01
|
||||
--top-p 0.95
|
||||
--top-k 40
|
||||
--repeat-penalty 1.0
|
||||
-ctk q8_0 -ctv q8_0
|
||||
${common_args}
|
||||
--min-p 0.00
|
||||
--top-k 64
|
||||
--top-p 0.95
|
||||
--no-mmproj
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-35B-A3B-GGUF:Q4_K_M":
|
||||
"Qwen3-4B-Thinking-2507":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-35B-A3B-GGUF:Q4_K_M
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_35b_args}
|
||||
${common_args}
|
||||
-hf unsloth/Qwen3-4B-Thinking-2507-GGUF:Q4_K_M
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 16384
|
||||
--predict 8192
|
||||
--temp 0.6
|
||||
--min-p 0.00
|
||||
--top-p 0.95
|
||||
--top-k 20
|
||||
--repeat-penalty 1.0
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-35B-A3B-GGUF-nothink:Q4_K_M":
|
||||
"Qwen3-4B-Thinking-2507-long-ctx":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-35B-A3B-GGUF:Q4_K_M
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_35b_args}
|
||||
${common_args}
|
||||
${thinking_off}
|
||||
-hf unsloth/Qwen3-4B-Thinking-2507-GGUF:Q4_K_M
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 262144
|
||||
--predict 81920
|
||||
--temp 0.6
|
||||
--min-p 0.00
|
||||
--top-p 0.95
|
||||
--top-k 20
|
||||
--repeat-penalty 1.0
|
||||
--no-warmup
|
||||
--flash-attn auto
|
||||
--cache-type-k q8_0
|
||||
--cache-type-v q8_0
|
||||
--port ${PORT}
|
||||
|
||||
# The "heretic" version does not provide the mmproj
|
||||
# so providing url to the one from the non-heretic version.
|
||||
"Qwen3.5-35B-A3B-heretic-GGUF:Q4_K_M":
|
||||
"Qwen3-4B-Instruct-2507":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf mradermacher/Qwen3.5-35B-A3B-heretic-GGUF:Q4_K_M
|
||||
${qwen35_35b_heretic_mmproj}
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_35b_args}
|
||||
${common_args}
|
||||
-hf unsloth/Qwen3-4B-Instruct-2507-GGUF:Q4_K_M
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 16384
|
||||
--predict 8192
|
||||
--temp 0.7
|
||||
--min-p 0.00
|
||||
--top-p 0.8
|
||||
--top-k 20
|
||||
--repeat-penalty 1.0
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-35B-A3B-heretic-GGUF-nothink:Q4_K_M":
|
||||
"Qwen3-4B-Instruct-2507-long-ctx":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf mradermacher/Qwen3.5-35B-A3B-heretic-GGUF:Q4_K_M
|
||||
${qwen35_35b_heretic_mmproj}
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_35b_args}
|
||||
${common_args}
|
||||
${thinking_off}
|
||||
-hf unsloth/Qwen3-4B-Instruct-2507-GGUF:Q4_K_M
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 262144
|
||||
--predict 81920
|
||||
--temp 0.7
|
||||
--min-p 0.00
|
||||
--top-p 0.8
|
||||
--top-k 20
|
||||
--repeat-penalty 1.0
|
||||
--no-warmup
|
||||
--flash-attn auto
|
||||
--cache-type-k q8_0
|
||||
--cache-type-v q8_0
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-0.8B-GGUF:Q4_K_XL":
|
||||
"Qwen2.5-VL-32B-Instruct-GGUF-IQ1_S":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-0.8B-GGUF:Q4_K_XL
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_sampling}
|
||||
${base_args}
|
||||
${thinking_on}
|
||||
-hf unsloth/Qwen2.5-VL-32B-Instruct-GGUF:IQ1_S
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 16384
|
||||
--predict 8192
|
||||
--temp 0.7
|
||||
--min-p 0.00
|
||||
--top-p 0.8
|
||||
--top-k 20
|
||||
--repeat-penalty 1.0
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-0.8B-GGUF-nothink:Q4_K_XL":
|
||||
"Qwen2.5-VL-32B-Instruct-GGUF-Q2_K_L":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-0.8B-GGUF:Q4_K_XL
|
||||
--ctx-size 4096
|
||||
${qwen35_sampling}
|
||||
${base_args}
|
||||
${thinking_off}
|
||||
-hf unsloth/Qwen2.5-VL-32B-Instruct-GGUF:Q2_K_L
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 16384
|
||||
--predict 8192
|
||||
--temp 0.7
|
||||
--min-p 0.00
|
||||
--top-p 0.8
|
||||
--top-k 20
|
||||
--repeat-penalty 1.0
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-2B-GGUF:Q4_K_M":
|
||||
"Qwen2.5-VL-7B-Instruct-GGUF":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-2B-GGUF:Q4_K_M
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_on}
|
||||
-hf unsloth/Qwen2.5-VL-7B-Instruct-GGUF:Q4_K_M
|
||||
--n-gpu-layers 37
|
||||
--ctx-size 16384
|
||||
--predict 8192
|
||||
--temp 0.7
|
||||
--min-p 0.00
|
||||
--top-p 0.8
|
||||
--top-k 20
|
||||
--repeat-penalty 1.0
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-2B-GGUF-nothink:Q4_K_M":
|
||||
"Qwen3-VL-2B-Instruct-GGUF":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-2B-GGUF:Q4_K_M
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_off}
|
||||
-hf Qwen/Qwen3-VL-2B-Instruct-GGUF:Q8_0
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 12288
|
||||
--predict 4096
|
||||
--flash-attn auto
|
||||
--jinja
|
||||
--temp 0.7
|
||||
--top-p 0.85
|
||||
--top-k 20
|
||||
--min-p 0.05
|
||||
--repeat-penalty 1.15
|
||||
--frequency-penalty 0.5
|
||||
--presence-penalty 0.4
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-4B-GGUF:Q4_K_M":
|
||||
"Qwen3-VL-4B-Instruct-GGUF":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-4B-GGUF:Q4_K_M
|
||||
${qwen35_ctx_128k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_on}
|
||||
-hf Qwen/Qwen3-VL-4B-Instruct-GGUF:Q8_0
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 12288
|
||||
--predict 4096
|
||||
--flash-attn auto
|
||||
--jinja
|
||||
--temp 0.7
|
||||
--top-p 0.85
|
||||
--top-k 20
|
||||
--min-p 0.05
|
||||
--repeat-penalty 1.15
|
||||
--frequency-penalty 0.5
|
||||
--presence-penalty 0.4
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-4B-GGUF-nothink:Q4_K_M":
|
||||
"Qwen3-VL-8B-Instruct-GGUF":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-4B-GGUF:Q4_K_M
|
||||
${qwen35_ctx_128k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_off}
|
||||
-hf Qwen/Qwen3-VL-8B-Instruct-GGUF:Q4_K_M
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 12288
|
||||
--predict 4096
|
||||
--flash-attn auto
|
||||
--jinja
|
||||
--temp 0.7
|
||||
--top-p 0.85
|
||||
--top-k 20
|
||||
--min-p 0.05
|
||||
--repeat-penalty 1.15
|
||||
--frequency-penalty 0.5
|
||||
--presence-penalty 0.4
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-4B-heretic-GGUF:Q4_K_M":
|
||||
"Qwen3-VL-2B-Instruct-GGUF-unslothish":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf mradermacher/Qwen3.5-4B-heretic-GGUF:Q4_K_M
|
||||
${qwen35_4b_heretic_mmproj}
|
||||
${qwen35_ctx_128k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_on}
|
||||
-hf Qwen/Qwen3-VL-2B-Instruct-GGUF:Q8_0
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 12288
|
||||
--predict 4096
|
||||
--flash-attn auto
|
||||
--jinja
|
||||
--temp 0.7
|
||||
--top-p 0.8
|
||||
--top-k 20
|
||||
--min-p 0.05
|
||||
--repeat-penalty 1.15
|
||||
--frequency-penalty 0.5
|
||||
--presence-penalty 0.6
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-4B-heretic-GGUF-nothink:Q4_K_M":
|
||||
"Qwen3-VL-4B-Instruct-GGUF-unslothish":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf mradermacher/Qwen3.5-4B-heretic-GGUF:Q4_K_M
|
||||
${qwen35_4b_heretic_mmproj}
|
||||
${qwen35_ctx_128k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_off}
|
||||
-hf Qwen/Qwen3-VL-4B-Instruct-GGUF:Q8_0
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 12288
|
||||
--predict 4096
|
||||
--flash-attn auto
|
||||
--jinja
|
||||
--temp 0.7
|
||||
--top-p 0.8
|
||||
--top-k 20
|
||||
--min-p 0.05
|
||||
--repeat-penalty 1.15
|
||||
--frequency-penalty 0.5
|
||||
--presence-penalty 0.6
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-9B-GGUF:Q4_K_M":
|
||||
"Qwen3-VL-8B-Instruct-GGUF-unslothish":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-9B-GGUF:Q4_K_M
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_on}
|
||||
-hf Qwen/Qwen3-VL-8B-Instruct-GGUF:Q4_K_M
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 12288
|
||||
--predict 4096
|
||||
--flash-attn auto
|
||||
--jinja
|
||||
--temp 0.7
|
||||
--top-p 0.8
|
||||
--top-k 20
|
||||
--min-p 0.05
|
||||
--repeat-penalty 1.15
|
||||
--frequency-penalty 0.5
|
||||
--presence-penalty 0.6
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-9B-GGUF-nothink:Q4_K_M":
|
||||
"Qwen3-VL-2B-Thinking-GGUF":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-9B-GGUF:Q4_K_M
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_off}
|
||||
-hf Qwen/Qwen3-VL-2B-Thinking-GGUF:Q8_0
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 12288
|
||||
--predict 4096
|
||||
--flash-attn auto
|
||||
--jinja
|
||||
--top-p 0.95
|
||||
--top-k 20
|
||||
--temp 1.0
|
||||
--min-p 0.0
|
||||
--repeat-penalty 1.0
|
||||
--presence-penalty 0.0
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-9B-GGUF:Q3_K_M":
|
||||
"Qwen3-VL-4B-Thinking-GGUF":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-9B-GGUF:Q3_K_M
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_on}
|
||||
-hf Qwen/Qwen3-VL-4B-Thinking-GGUF:Q4_K_M
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 12288
|
||||
--predict 4096
|
||||
--flash-attn auto
|
||||
--jinja
|
||||
--top-p 0.95
|
||||
--top-k 20
|
||||
--temp 1.0
|
||||
--min-p 0.0
|
||||
--repeat-penalty 1.0
|
||||
--presence-penalty 0.0
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-9B-GGUF-nothink:Q3_K_M":
|
||||
"Qwen3-VL-8B-Thinking-GGUF":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-9B-GGUF:Q3_K_M
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_off}
|
||||
-hf Qwen/Qwen3-VL-8B-Thinking-GGUF:Q4_K_M
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 12288
|
||||
--predict 4096
|
||||
--flash-attn auto
|
||||
--jinja
|
||||
--top-p 0.95
|
||||
--top-k 20
|
||||
--temp 1.0
|
||||
--min-p 0.0
|
||||
--repeat-penalty 1.0
|
||||
--presence-penalty 0.0
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-27B-GGUF:Q3_K_M":
|
||||
"Huihui-Qwen3-VL-8B-Instruct-abliterated-GGUF":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-27B-GGUF:Q3_K_M
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_on}
|
||||
-hf noctrex/Huihui-Qwen3-VL-8B-Instruct-abliterated-GGUF:Q6_K
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 12288
|
||||
--predict 4096
|
||||
--flash-attn auto
|
||||
--jinja
|
||||
--temp 0.7
|
||||
--top-p 0.85
|
||||
--top-k 20
|
||||
--min-p 0.05
|
||||
--repeat-penalty 1.15
|
||||
--frequency-penalty 0.5
|
||||
--presence-penalty 0.4
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
|
||||
"Qwen3.5-27B-GGUF-nothink:Q3_K_M":
|
||||
"Huihui-Qwen3-VL-8B-Thinking-abliterated-GGUF":
|
||||
ttl: 600
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/Qwen3.5-27B-GGUF:Q3_K_M
|
||||
${qwen35_ctx_256k}
|
||||
${qwen35_sampling}
|
||||
${common_args}
|
||||
${thinking_off}
|
||||
|
||||
"GLM-4.7-Flash-GGUF:Q4_K_M":
|
||||
cmd: |
|
||||
/app/llama-server
|
||||
-hf unsloth/GLM-4.7-Flash-GGUF:Q4_K_M
|
||||
${glm47_flash_args}
|
||||
${common_args}
|
||||
-hf noctrex/Huihui-Qwen3-VL-8B-Thinking-abliterated-GGUF:Q6_K
|
||||
--n-gpu-layers 99
|
||||
--ctx-size 12288
|
||||
--predict 4096
|
||||
--flash-attn auto
|
||||
--jinja
|
||||
--temp 0.7
|
||||
--top-p 0.85
|
||||
--top-k 20
|
||||
--min-p 0.05
|
||||
--repeat-penalty 1.15
|
||||
--frequency-penalty 0.5
|
||||
--presence-penalty 0.4
|
||||
--no-warmup
|
||||
--port ${PORT}
|
||||
@@ -6,8 +6,6 @@ metadata:
|
||||
namespace: llama
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: llama-swap
|
||||
@@ -18,7 +16,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: llama-swap
|
||||
image: ghcr.io/mostlygeek/llama-swap:v199-vulkan-b8589
|
||||
image: ghcr.io/mostlygeek/llama-swap:v172-vulkan-b7062
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /app/llama-swap
|
||||
@@ -29,15 +27,9 @@ spec:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: OPENROUTER_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: llama-openrouter
|
||||
key: OPENROUTER_API_KEY
|
||||
volumeMounts:
|
||||
- name: models
|
||||
mountPath: /root/.cache
|
||||
mountPath: /app/.cache
|
||||
- mountPath: /dev/kfd
|
||||
name: kfd
|
||||
- mountPath: /dev/dri
|
||||
@@ -49,7 +41,7 @@ spec:
|
||||
volumes:
|
||||
- name: models
|
||||
persistentVolumeClaim:
|
||||
claimName: llama-models-lvmssd
|
||||
claimName: llama-models
|
||||
- name: kfd
|
||||
hostPath:
|
||||
path: /dev/kfd
|
||||
|
||||
@@ -5,7 +5,7 @@ resources:
|
||||
- secret.yaml
|
||||
- auth-proxy.yaml
|
||||
- ingress.yaml
|
||||
- pvc-ssd.yaml
|
||||
- pvc.yaml
|
||||
- deployment.yaml
|
||||
configMapGenerator:
|
||||
- name: llama-swap
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: llama-models-lvmssd
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 200Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-ssd$
|
||||
volGroup: openebs-ssd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: llama-models-lvmssd
|
||||
spec:
|
||||
capacity:
|
||||
storage: 200Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: ssd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: llama-models-lvmssd
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: llama-models-lvmssd
|
||||
namespace: llama
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 200Gi
|
||||
storageClassName: ssd-lvmpv
|
||||
volumeName: llama-models-lvmssd
|
||||
13
apps/llama/pvc.yaml
Normal file
13
apps/llama/pvc.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
namespace: llama
|
||||
name: llama-models
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 200Gi
|
||||
storageClassName: mayastor-single-ssd
|
||||
@@ -36,26 +36,3 @@ spec:
|
||||
excludeRaw: true
|
||||
|
||||
vaultAuthRef: llama
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: llama-openrouter
|
||||
namespace: llama
|
||||
spec:
|
||||
type: kv-v2
|
||||
|
||||
mount: secret
|
||||
path: openrouter
|
||||
|
||||
destination:
|
||||
create: true
|
||||
name: llama-openrouter
|
||||
type: Opaque
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
templates:
|
||||
OPENROUTER_API_KEY:
|
||||
text: '{{ get .Secrets "API_KEY" }}'
|
||||
|
||||
vaultAuthRef: llama
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
namespace: openwebui
|
||||
name: openwebui-web
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app.kubernetes.io/component: open-webui
|
||||
app.kubernetes.io/instance: openwebui
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
namespace: openwebui
|
||||
name: openwebui
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
||||
nginx.ingress.kubernetes.io/proxy-buffering: "false"
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: 30m
|
||||
spec:
|
||||
ingressClassName: nginx-ingress
|
||||
rules:
|
||||
- host: openwebui.lumpiasty.xyz
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: openwebui-web
|
||||
port:
|
||||
number: 80
|
||||
path: /
|
||||
pathType: Prefix
|
||||
tls:
|
||||
- hosts:
|
||||
- openwebui.lumpiasty.xyz
|
||||
secretName: openwebui-ingress
|
||||
@@ -1,9 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- pvc.yaml
|
||||
- pvc-pipelines.yaml
|
||||
- secret.yaml
|
||||
- release.yaml
|
||||
- ingress.yaml
|
||||
@@ -1,4 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: openwebui
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: openwebui-pipelines-lvmhdd
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 1Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-hdd$
|
||||
volGroup: openebs-hdd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: openwebui-pipelines-lvmhdd
|
||||
spec:
|
||||
capacity:
|
||||
storage: 1Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: openwebui-pipelines-lvmhdd
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: openwebui-pipelines-lvmhdd
|
||||
namespace: openwebui
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeName: openwebui-pipelines-lvmhdd
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: openwebui-lvmhdd
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 10Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-hdd$
|
||||
volGroup: openebs-hdd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: openwebui-lvmhdd
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: openwebui-lvmhdd
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: openwebui-lvmhdd
|
||||
namespace: openwebui
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeName: openwebui-lvmhdd
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: open-webui
|
||||
namespace: openwebui
|
||||
spec:
|
||||
interval: 24h
|
||||
url: https://open-webui.github.io/helm-charts
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: openwebui
|
||||
namespace: openwebui
|
||||
spec:
|
||||
interval: 30m
|
||||
chart:
|
||||
spec:
|
||||
chart: open-webui
|
||||
version: 13.0.1
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: open-webui
|
||||
values:
|
||||
# Disable built in ingress, service is broken in chart
|
||||
# They have hard coded wrong target port
|
||||
# Reimplementing that in ingress.yaml
|
||||
ingress:
|
||||
enabled: false
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
existingClaim: openwebui-lvmhdd
|
||||
|
||||
enableOpenaiApi: true
|
||||
openaiBaseApiUrl: "http://llama.llama.svc.cluster.local:11434/v1"
|
||||
|
||||
ollama:
|
||||
enabled: false
|
||||
|
||||
pipelines:
|
||||
enabled: true
|
||||
persistence:
|
||||
enabled: true
|
||||
existingClaim: openwebui-pipelines-lvmhdd
|
||||
|
||||
# SSO with Authentik
|
||||
extraEnvVars:
|
||||
- name: WEBUI_URL
|
||||
value: "https://openwebui.lumpiasty.xyz"
|
||||
- name: OAUTH_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openwebui-authentik
|
||||
key: client_id
|
||||
- name: OAUTH_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openwebui-authentik
|
||||
key: client_secret
|
||||
- name: OAUTH_PROVIDER_NAME
|
||||
value: "authentik"
|
||||
- name: OPENID_PROVIDER_URL
|
||||
value: "https://authentik.lumpiasty.xyz/application/o/open-web-ui/.well-known/openid-configuration"
|
||||
- name: OPENID_REDIRECT_URI
|
||||
value: "https://openwebui.lumpiasty.xyz/oauth/oidc/callback"
|
||||
- name: ENABLE_OAUTH_SIGNUP
|
||||
value: "true"
|
||||
- name: ENABLE_LOGIN_FORM
|
||||
value: "false"
|
||||
- name: OAUTH_MERGE_ACCOUNTS_BY_EMAIL
|
||||
value: "true"
|
||||
@@ -1,43 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: openwebui-secret
|
||||
namespace: openwebui
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultAuth
|
||||
metadata:
|
||||
name: openwebui
|
||||
namespace: openwebui
|
||||
spec:
|
||||
method: kubernetes
|
||||
mount: kubernetes
|
||||
kubernetes:
|
||||
role: openwebui
|
||||
serviceAccount: openwebui-secret
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: openwebui-authentik
|
||||
namespace: openwebui
|
||||
spec:
|
||||
type: kv-v2
|
||||
|
||||
mount: secret
|
||||
path: authentik/openwebui
|
||||
|
||||
destination:
|
||||
create: true
|
||||
name: openwebui-authentik
|
||||
type: Opaque
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
templates:
|
||||
client_id:
|
||||
text: '{{ get .Secrets "client_id" }}'
|
||||
client_secret:
|
||||
text: '{{ get .Secrets "client_secret" }}'
|
||||
|
||||
vaultAuthRef: openwebui
|
||||
40
apps/registry/deployment.yaml
Normal file
40
apps/registry/deployment.yaml
Normal file
@@ -0,0 +1,40 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: registry
|
||||
namespace: registry
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: registry
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: registry
|
||||
spec:
|
||||
containers:
|
||||
- name: registry
|
||||
image: registry:3.0.0
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/registry
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: registry-data
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: registry-service
|
||||
namespace: registry
|
||||
spec:
|
||||
selector:
|
||||
app: registry
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 5000
|
||||
@@ -1,24 +1,26 @@
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
namespace: garm
|
||||
name: garm
|
||||
namespace: registry
|
||||
name: registry
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
||||
spec:
|
||||
ingressClassName: nginx-ingress
|
||||
rules:
|
||||
- host: garm.lumpiasty.xyz
|
||||
- host: registry.lumpiasty.xyz
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: garm
|
||||
name: registry-service
|
||||
port:
|
||||
number: 9997
|
||||
number: 80
|
||||
path: /
|
||||
pathType: Prefix
|
||||
tls:
|
||||
- hosts:
|
||||
- garm.lumpiasty.xyz
|
||||
secretName: garm-ingress
|
||||
- registry.lumpiasty.xyz
|
||||
secretName: researcher-ingress
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- secret.yaml
|
||||
- volume.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
@@ -2,4 +2,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: woodpecker
|
||||
name: registry
|
||||
13
apps/registry/volume.yaml
Normal file
13
apps/registry/volume.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: registry-data
|
||||
namespace: registry
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 50Gi
|
||||
storageClassName: mayastor-single-hdd
|
||||
@@ -9,4 +9,3 @@ data:
|
||||
RENOVATE_ENDPOINT: https://gitea.lumpiasty.xyz/api/v1
|
||||
RENOVATE_PLATFORM: gitea
|
||||
RENOVATE_GIT_AUTHOR: Renovate Bot <renovate@lumpiasty.xyz>
|
||||
RENOVATE_ALLOWED_COMMANDS: '["^node utils/update-garm-cli-hash\\.mjs$", "^node utils/update-garm-image-pin\\.mjs$"]'
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
- name: renovate
|
||||
# Update this to the latest available and then enable Renovate on
|
||||
# the manifest
|
||||
image: renovate/renovate:43.95.0-full
|
||||
image: renovate/renovate:43.4.3-full
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: renovate-gitea-token
|
||||
|
||||
@@ -39,4 +39,4 @@ spec:
|
||||
name: searxng-config
|
||||
- name: searxng-persistent-data
|
||||
persistentVolumeClaim:
|
||||
claimName: searxng-persistent-data-lvmhdd
|
||||
claimName: searxng-persistent-data
|
||||
|
||||
@@ -1,46 +1,13 @@
|
||||
---
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: searxng-persistent-data-lvmhdd
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 1Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-hdd$
|
||||
volGroup: openebs-hdd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: searxng-persistent-data-lvmhdd
|
||||
spec:
|
||||
capacity:
|
||||
storage: 1Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: searxng-persistent-data-lvmhdd
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: searxng-persistent-data-lvmhdd
|
||||
namespace: searxng
|
||||
name: searxng-persistent-data
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
storageClassName: hdd-lvmpv
|
||||
volumeName: searxng-persistent-data-lvmhdd
|
||||
storageClassName: mayastor-single-ssd
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- postgres-volume.yaml
|
||||
- postgres-cluster.yaml
|
||||
- release.yaml
|
||||
- secret.yaml
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
metadata:
|
||||
name: woodpecker-postgresql-cluster
|
||||
namespace: woodpecker
|
||||
spec:
|
||||
instances: 1
|
||||
|
||||
imageName: ghcr.io/cloudnative-pg/postgresql:17.4
|
||||
|
||||
bootstrap:
|
||||
initdb:
|
||||
database: woodpecker
|
||||
owner: woodpecker
|
||||
|
||||
storage:
|
||||
pvcTemplate:
|
||||
storageClassName: ssd-lvmpv
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
volumeName: woodpecker-postgresql-cluster-lvmssd
|
||||
@@ -1,33 +0,0 @@
|
||||
apiVersion: local.openebs.io/v1alpha1
|
||||
kind: LVMVolume
|
||||
metadata:
|
||||
labels:
|
||||
kubernetes.io/nodename: anapistula-delrosalae
|
||||
name: woodpecker-postgresql-cluster-lvmssd
|
||||
namespace: openebs
|
||||
spec:
|
||||
capacity: 10Gi
|
||||
ownerNodeID: anapistula-delrosalae
|
||||
shared: "yes"
|
||||
thinProvision: "no"
|
||||
vgPattern: ^openebs-ssd$
|
||||
volGroup: openebs-ssd
|
||||
---
|
||||
kind: PersistentVolume
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: woodpecker-postgresql-cluster-lvmssd
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: ssd-lvmpv
|
||||
volumeMode: Filesystem
|
||||
csi:
|
||||
driver: local.csi.openebs.io
|
||||
fsType: btrfs
|
||||
volumeHandle: woodpecker-postgresql-cluster-lvmssd
|
||||
---
|
||||
# PVC is dynamically created by the Postgres operator
|
||||
@@ -1,115 +0,0 @@
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: woodpecker
|
||||
namespace: woodpecker
|
||||
spec:
|
||||
interval: 24h
|
||||
url: https://woodpecker-ci.org/
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: woodpecker
|
||||
namespace: woodpecker
|
||||
spec:
|
||||
interval: 30m
|
||||
chart:
|
||||
spec:
|
||||
chart: woodpecker
|
||||
version: 3.5.1
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: woodpecker
|
||||
namespace: woodpecker
|
||||
interval: 12h
|
||||
values:
|
||||
server:
|
||||
enabled: true
|
||||
statefulSet:
|
||||
replicaCount: 1
|
||||
|
||||
persistentVolume:
|
||||
enabled: false # Using Postgresql database
|
||||
|
||||
env:
|
||||
WOODPECKER_HOST: "https://woodpecker.lumpiasty.xyz"
|
||||
# Gitea integration
|
||||
WOODPECKER_GITEA: "true"
|
||||
WOODPECKER_GITEA_URL: "https://gitea.lumpiasty.xyz"
|
||||
# PostgreSQL database configuration
|
||||
WOODPECKER_DATABASE_DRIVER: postgres
|
||||
# Password is loaded from woodpecker-postgresql-cluster-app secret (created by CNPG)
|
||||
WOODPECKER_DATABASE_DATASOURCE:
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: woodpecker-postgresql-cluster-app
|
||||
key: fqdn-uri
|
||||
# Allow logging in from all accounts on Gitea
|
||||
WOODPECKER_OPEN: "true"
|
||||
# Make lumpiasty admin
|
||||
WOODPECKER_ADMIN: GiteaAdmin
|
||||
|
||||
createAgentSecret: true
|
||||
|
||||
extraSecretNamesForEnvFrom:
|
||||
- woodpecker-secrets
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
ingressClassName: nginx-ingress
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt
|
||||
acme.cert-manager.io/http01-edit-in-place: "true"
|
||||
hosts:
|
||||
- host: woodpecker.lumpiasty.xyz
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: woodpecker-server
|
||||
servicePort: 80
|
||||
tls:
|
||||
- hosts:
|
||||
- woodpecker.lumpiasty.xyz
|
||||
secretName: woodpecker-ingress
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
|
||||
agent:
|
||||
enabled: true
|
||||
replicaCount: 2
|
||||
|
||||
env:
|
||||
WOODPECKER_SERVER: "woodpecker-server:9000"
|
||||
WOODPECKER_BACKEND: kubernetes
|
||||
WOODPECKER_BACKEND_K8S_NAMESPACE: woodpecker
|
||||
WOODPECKER_BACKEND_K8S_STORAGE_CLASS: ssd-lvmpv
|
||||
WOODPECKER_BACKEND_K8S_VOLUME_SIZE: 10G
|
||||
WOODPECKER_BACKEND_K8S_STORAGE_RWX: false
|
||||
WOODPECKER_CONNECT_RETRY_COUNT: "5"
|
||||
|
||||
mapAgentSecret: true
|
||||
|
||||
extraSecretNamesForEnvFrom:
|
||||
- woodpecker-secrets
|
||||
|
||||
persistence:
|
||||
enabled: false
|
||||
|
||||
serviceAccount:
|
||||
create: true
|
||||
rbac:
|
||||
create: true
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
@@ -1,62 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: woodpecker-secret
|
||||
namespace: woodpecker
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultAuth
|
||||
metadata:
|
||||
name: woodpecker
|
||||
namespace: woodpecker
|
||||
spec:
|
||||
method: kubernetes
|
||||
mount: kubernetes
|
||||
kubernetes:
|
||||
role: woodpecker
|
||||
serviceAccount: woodpecker-secret
|
||||
---
|
||||
# Main woodpecker secrets from Vault
|
||||
# Requires vault kv put secret/woodpecker \
|
||||
# WOODPECKER_AGENT_SECRET="$(openssl rand -hex 32)" \
|
||||
# WOODPECKER_GITEA_CLIENT="<gitea-oauth-client>" \
|
||||
# WOODPECKER_GITEA_SECRET="<gitea-oauth-secret>"
|
||||
# Note: Database password comes from CNPG secret (woodpecker-postgresql-cluster-app)
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: woodpecker-secrets
|
||||
namespace: woodpecker
|
||||
spec:
|
||||
type: kv-v2
|
||||
mount: secret
|
||||
path: woodpecker
|
||||
destination:
|
||||
create: true
|
||||
name: woodpecker-secrets
|
||||
type: Opaque
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
vaultAuthRef: woodpecker
|
||||
---
|
||||
# Container registry credentials for Kaniko
|
||||
# Requires vault kv put secret/container-registry \
|
||||
# REGISTRY_USERNAME="<username>" \
|
||||
# REGISTRY_PASSWORD="<token>"
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: container-registry
|
||||
namespace: woodpecker
|
||||
spec:
|
||||
type: kv-v2
|
||||
mount: secret
|
||||
path: container-registry
|
||||
destination:
|
||||
create: true
|
||||
name: container-registry
|
||||
type: Opaque
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
vaultAuthRef: woodpecker
|
||||
87
devenv.lock
87
devenv.lock
@@ -3,11 +3,10 @@
|
||||
"devenv": {
|
||||
"locked": {
|
||||
"dir": "src/modules",
|
||||
"lastModified": 1773504385,
|
||||
"narHash": "sha256-ANaeR+xVHxjGz36VI4qlZUbdhrlSE0xU7O7AUJKw3zU=",
|
||||
"lastModified": 1769881431,
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "4bce49e6f60c69e99eeb643efbbf74125cefd329",
|
||||
"rev": "72d5e66e2dd5112766ef4c9565872b51094b542d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -17,13 +16,27 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767039857,
|
||||
"owner": "NixOS",
|
||||
"repo": "flake-compat",
|
||||
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
@@ -35,6 +48,47 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"git-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769069492,
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "a1ef738813b15cf8ec759bdff5761b027e3e1d23",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"git-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1762808025,
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"krew2nix": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
@@ -45,11 +99,10 @@
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773451905,
|
||||
"narHash": "sha256-S/bukFEwbOYQbnR5UpciwYA42aEt1w5LK73GwARhsaA=",
|
||||
"lastModified": 1769904483,
|
||||
"owner": "a1994sc",
|
||||
"repo": "krew2nix",
|
||||
"rev": "bc779a8cf59ebf76ae60556bfe2d781a0a4cdbd9",
|
||||
"rev": "17d6ad3375899bd3f7d4d298481536155f3ec13c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -60,11 +113,10 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1773389992,
|
||||
"narHash": "sha256-wvfdLLWJ2I9oEpDd9PfMA8osfIZicoQ5MT1jIwNs9Tk=",
|
||||
"lastModified": 1769461804,
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c06b4ae3d6599a672a6210b7021d699c351eebda",
|
||||
"rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -77,14 +129,17 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"devenv": "devenv",
|
||||
"git-hooks": "git-hooks",
|
||||
"krew2nix": "krew2nix",
|
||||
"nixpkgs": "nixpkgs"
|
||||
"nixpkgs": "nixpkgs",
|
||||
"pre-commit-hooks": [
|
||||
"git-hooks"
|
||||
]
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
@@ -99,7 +154,6 @@
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
@@ -119,11 +173,10 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773297127,
|
||||
"narHash": "sha256-6E/yhXP7Oy/NbXtf1ktzmU8SdVqJQ09HC/48ebEGBpk=",
|
||||
"lastModified": 1769691507,
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "71b125cd05fbfd78cab3e070b73544abe24c5016",
|
||||
"rev": "28b19c5844cc6e2257801d43f2772a4b4c050a1b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -135,4 +188,4 @@
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
}
|
||||
|
||||
15
devenv.nix
15
devenv.nix
@@ -4,10 +4,7 @@ let
|
||||
# Python with hvac package
|
||||
python = pkgs.python313.withPackages (python-pkgs: with python-pkgs; [
|
||||
hvac
|
||||
librouteros
|
||||
]);
|
||||
|
||||
garm-cli = pkgs.callPackage ./nix/garm-cli.nix { };
|
||||
in
|
||||
{
|
||||
# Overlays - apply krew2nix to get kubectl with krew support
|
||||
@@ -24,7 +21,6 @@ in
|
||||
VAULT_ADDR = "https://openbao.lumpiasty.xyz:8200";
|
||||
PATH = "${config.devenv.root}/utils:${pkgs.coreutils}/bin";
|
||||
PYTHON_BIN = "${python}/bin/python";
|
||||
KUBECONFIG = "${config.devenv.root}/talos/generated/kubeconfig";
|
||||
};
|
||||
|
||||
# Packages
|
||||
@@ -36,16 +32,12 @@ in
|
||||
(kubectl.withKrewPlugins (plugins: with plugins; [
|
||||
mayastor
|
||||
openebs
|
||||
browse-pvc
|
||||
]))
|
||||
ansible
|
||||
fluxcd
|
||||
restic
|
||||
openbao
|
||||
pv-migrate
|
||||
mermaid-cli
|
||||
opencode
|
||||
garm-cli
|
||||
tea
|
||||
];
|
||||
|
||||
# Scripts
|
||||
@@ -64,9 +56,4 @@ in
|
||||
echo "Running tests"
|
||||
git --version | grep --color=auto "${pkgs.git.version}"
|
||||
'';
|
||||
|
||||
languages.ansible.enable = true;
|
||||
# TODO: automatically manage collections from ansible/requirements.yml
|
||||
# For now, we need to manually install them with `ansible-galaxy collection install -r ansible/requirements.yml`
|
||||
# This is not implemented in devenv
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
FROM golang:1.26-alpine AS build
|
||||
|
||||
ARG GARM_COMMIT
|
||||
ARG GARM_PROVIDER_K8S_VERSION=0.3.2
|
||||
|
||||
RUN apk add --no-cache ca-certificates git wget tar build-base util-linux-dev linux-headers
|
||||
|
||||
WORKDIR /src
|
||||
RUN git clone https://github.com/cloudbase/garm.git . && git checkout "${GARM_COMMIT}"
|
||||
|
||||
RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \
|
||||
go build -trimpath \
|
||||
-tags osusergo,netgo,sqlite_omit_load_extension \
|
||||
-ldflags="-linkmode external -extldflags '-static' -s -w" \
|
||||
-o /out/garm ./cmd/garm
|
||||
|
||||
RUN mkdir -p /out/providers.d \
|
||||
&& wget -qO /tmp/garm-provider-k8s.tar.gz "https://github.com/mercedes-benz/garm-provider-k8s/releases/download/v${GARM_PROVIDER_K8S_VERSION}/garm-provider-k8s_Linux_x86_64.tar.gz" \
|
||||
&& tar -xzf /tmp/garm-provider-k8s.tar.gz -C /out/providers.d \
|
||||
&& chmod 0755 /out/providers.d/garm-provider-k8s
|
||||
|
||||
FROM busybox
|
||||
|
||||
COPY --from=build /out/garm /bin/garm
|
||||
COPY --from=build /out/providers.d/garm-provider-k8s /opt/garm/providers.d/garm-provider-k8s
|
||||
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
|
||||
ENTRYPOINT ["/bin/garm"]
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><path fill="#1A1918" d="M126 64c0 34.2-27.8 62-62 62S2 98.2 2 64 29.8 2 64 2s62 27.8 62 62"/><path fill="#FFF" d="M65 39.9l16 39.6-24.1-19.1L65 39.9zm28.5 48.7L68.9 29.2c-.7-1.7-2.1-2.6-3.8-2.6-1.7 0-3.2.9-3.9 2.6L34 94.3h9.3L54 67.5l32 25.9c1.3 1 2.2 1.5 3.4 1.5 2.4 0 4.5-1.8 4.5-4.4.1-.5-.1-1.2-.4-1.9z"/></svg>
|
||||
|
Before Width: | Height: | Size: 377 B |
@@ -1,211 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
id="svg3881"
|
||||
width="735"
|
||||
height="735"
|
||||
version="1.1"
|
||||
sodipodi:docname="logo.svg"
|
||||
inkscape:version="1.1.2 (b8e25be8, 2022-02-05)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview119"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
width="735px"
|
||||
height="735.18701px"
|
||||
inkscape:zoom="0.83052846"
|
||||
inkscape:cx="86.089765"
|
||||
inkscape:cy="279.94224"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="815"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg3881" />
|
||||
<defs
|
||||
id="defs3834">
|
||||
<style
|
||||
id="style3812">.cls-7{fill:#fff}</style>
|
||||
<filter
|
||||
id="luminosity-noclip"
|
||||
x="598.71002"
|
||||
y="183.45"
|
||||
width="593.97998"
|
||||
height="570.21997"
|
||||
filterUnits="userSpaceOnUse"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feFlood
|
||||
flood-color="#fff"
|
||||
result="bg"
|
||||
id="feFlood3814" />
|
||||
<feBlend
|
||||
in="SourceGraphic"
|
||||
in2="bg"
|
||||
id="feBlend3816"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
<mask
|
||||
id="mask"
|
||||
x="598.71"
|
||||
y="183.45"
|
||||
width="593.98"
|
||||
height="570.22"
|
||||
maskUnits="userSpaceOnUse">
|
||||
<g
|
||||
id="g3823"
|
||||
filter="url(#luminosity-noclip)">
|
||||
<path
|
||||
d="m 895.7,183.45 c -157.46,0 -285.11,127.65 -285.11,285.11 0,157.46 127.65,285.11 285.11,285.11 157.46,0 285.11,-127.67 285.11,-285.11 0,-157.44 -127.65,-285.11 -285.11,-285.11 z m -0.07,545.42 C 751.82,728.87 635.42,612.41 635.39,468.6 635.36,324.79 752.1,208 896,208.26 c 143.9,0.26 260.14,116.74 260,260.5 -0.14,143.76 -116.58,260.15 -260.37,260.11 z"
|
||||
id="path3819" />
|
||||
<path
|
||||
d="m 875.36,590.92 c -8.93,-1.41 -13.67,-3.12 -23.71,-7.61 C 824,570.94 802.87,551.16 789,524.5 l -1.22,0.27 a 9.26,9.26 0 0 1 -2,0.22 9.37,9.37 0 0 1 -7.53,-3.83 9.26,9.26 0 0 1 -1.37,-8.35 l 2.27,-7.19 7.85,-25.13 a 9,9 0 0 1 15.27,-3.39 l 23.26,25.35 a 9.07,9.07 0 0 1 -1.47,13.55 61.2,61.2 0 0 0 14.52,14.56 88.71,88.71 0 0 0 16.26,5.65 181.32,181.32 0 0 0 24.73,4.4 V 440.2 h -21.52 a 18.49,18.49 0 0 1 -11,3.64 18.23,18.23 0 0 1 -13.57,-6.08 18.48,18.48 0 0 1 -0.11,-24.5 18.19,18.19 0 0 1 13.63,-6.26 18.53,18.53 0 0 1 11,3.6 h 21.58 v -3.33 C 866.23,401.5 857.8,390.93 855.14,376.59 851.3,356 864.4,335.5 885,329.92 a 41.23,41.23 0 0 1 10.74,-1.44 41.8,41.8 0 0 1 28.72,11.66 39.94,39.94 0 0 1 12.4,29 c 0,16.35 -7.65,29 -22.12,36.74 v 4.68 h 18.63 a 18.88,18.88 0 0 1 11,-3.6 18.09,18.09 0 0 1 13.56,6.13 18.49,18.49 0 0 1 -0.18,24.79 18,18 0 0 1 -13.36,5.88 18.81,18.81 0 0 1 -11,-3.54 h -0.6 c -5.05,0.3 -10.2,0.34 -15.19,0.39 h -2.94 v 100.98 a 147,147 0 0 0 18.3,-2.35 81.13,81.13 0 0 0 20,-6.37 59.65,59.65 0 0 0 14.84,-13.31 9,9 0 0 1 -0.82,-13.79 l 24.71,-23.65 a 9.1,9.1 0 0 1 6.34,-2.56 9.19,9.19 0 0 1 9,7 c 2.56,10.49 5.1,20.87 7.67,31.41 a 10.12,10.12 0 0 1 -9.81,12.53 10.2,10.2 0 0 1 -2.58,-0.33 c -12.36,22.51 -30.55,39.73 -52.75,49.88 l -4.09,1.95 c -11.35,5.24 -17.89,8.25 -29.89,9.57 l -19.9,19.52 z m 20,-233.29 c -6.26,0 -11.39,5.17 -11.69,11.76 a 11.56,11.56 0 0 0 3,8.41 11.77,11.77 0 0 0 8.26,3.81 h 1.08 c 6.23,0 11.21,-5 11.56,-11.6 0.35,-6.6 -4.55,-11.86 -11.41,-12.39 -0.16,0.02 -0.48,0.01 -0.76,0.01 z"
|
||||
id="path3821" />
|
||||
</g>
|
||||
</mask>
|
||||
<filter
|
||||
id="luminosity-noclip-2"
|
||||
x="583.53998"
|
||||
y="-8590.9902"
|
||||
width="624.32001"
|
||||
height="32766"
|
||||
filterUnits="userSpaceOnUse"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feFlood
|
||||
flood-color="#fff"
|
||||
result="bg"
|
||||
id="feFlood3826" />
|
||||
<feBlend
|
||||
in="SourceGraphic"
|
||||
in2="bg"
|
||||
id="feBlend3828"
|
||||
mode="normal" />
|
||||
</filter>
|
||||
</defs>
|
||||
<g
|
||||
id="g226"
|
||||
transform="translate(0,12.99976)">
|
||||
<g
|
||||
id="Background_wavy_outline"
|
||||
data-name="Background wavy outline"
|
||||
transform="translate(-528.23,-113.97)">
|
||||
<path
|
||||
d="m 1263.21,468.56 c 0,38.68 -23.69,73.14 -35,108 -11.74,36.17 -13.24,77.89 -35.15,108 -22.13,30.41 -61.49,44.63 -91.9,66.76 -30.11,21.91 -55.68,55.08 -91.84,66.83 -34.9,11.33 -74.93,-0.11 -113.6,-0.11 -38.67,0 -78.7,11.44 -113.59,0.11 -36.17,-11.75 -61.74,-44.92 -91.85,-66.83 -30.41,-22.13 -69.77,-36.35 -91.9,-66.76 -21.91,-30.1 -23.41,-71.82 -35.15,-108 -11.33,-34.9 -35,-69.36 -35,-108 0,-38.64 23.69,-73.14 35,-108 11.74,-36.17 13.24,-77.89 35.15,-108 22.13,-30.4 61.49,-44.63 91.9,-66.75 30.11,-21.91 55.68,-55.09 91.85,-66.83 34.89,-11.33 74.92,0.1 113.59,0.1 38.67,0 78.7,-11.43 113.59,-0.1 36.17,11.74 61.74,44.92 91.85,66.83 30.41,22.12 69.77,36.35 91.9,66.75 21.91,30.11 23.41,71.83 35.15,108 11.31,34.86 35,69.33 35,108 z"
|
||||
id="path3838"
|
||||
fill="#326ce5" />
|
||||
</g>
|
||||
<g
|
||||
id="Waves"
|
||||
transform="translate(-528.23,-113.97)">
|
||||
<g
|
||||
mask="url(#mask)"
|
||||
id="g3847"
|
||||
fill="none"
|
||||
stroke="#ffffff"
|
||||
stroke-miterlimit="10">
|
||||
<path
|
||||
d="m 598.71,427.68 c 42.43,0 42.43,20 84.85,20 42.42,0 42.43,-20 84.86,-20 42.43,0 42.42,20 84.85,20 42.43,0 42.42,-20 84.85,-20 42.43,0 42.43,20 84.85,20 42.42,0 42.43,-20 84.86,-20 42.43,0 42.43,20 84.86,20"
|
||||
id="path3841"
|
||||
stroke-width="3" />
|
||||
<path
|
||||
d="m 598.71,467.68 c 42.43,0 42.43,20 84.85,20 42.42,0 42.43,-20 84.86,-20 42.43,0 42.42,20 84.85,20 42.43,0 42.42,-20 84.85,-20 42.43,0 42.43,20 84.85,20 42.42,0 42.43,-20 84.86,-20 42.43,0 42.43,20 84.86,20"
|
||||
id="path3843"
|
||||
stroke-width="5" />
|
||||
<path
|
||||
d="m 598.71,515.68 c 42.43,0 42.43,20 84.85,20 42.42,0 42.43,-20 84.86,-20 42.43,0 42.42,20 84.85,20 42.43,0 42.42,-20 84.85,-20 42.43,0 42.43,20 84.85,20 42.42,0 42.43,-20 84.86,-20 42.43,0 42.43,20 84.86,20"
|
||||
id="path3845"
|
||||
stroke-width="7" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="Text"
|
||||
transform="translate(-528.23,-113.97)">
|
||||
<g
|
||||
id="g3878">
|
||||
<g
|
||||
id="Text_and_detail"
|
||||
data-name="Text and detail">
|
||||
<path
|
||||
id="Circle"
|
||||
class="cls-7"
|
||||
d="m 895.7,156.4 c -172.4,0 -312.16,139.76 -312.16,312.16 0,172.4 139.76,312.16 312.16,312.16 172.4,0 312.16,-139.72 312.16,-312.16 0,-172.44 -139.76,-312.16 -312.16,-312.16 z m -0.08,597.16 c -157.44,0 -284.89,-127.51 -284.92,-284.95 0,-157.61 127.78,-285.3 285.33,-285 157.55,0.3 284.81,127.8 284.67,285.22 -0.14,157.42 -127.64,284.78 -285.08,284.73 z"
|
||||
fill="#fff" />
|
||||
<g
|
||||
id="LETTERS">
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 751.7,610 c -1,-3.45 -5.75,-6.88 -9.44,-6.42 -5.24,0.67 -10.46,1.54 -16.76,2.48 2.32,-6.15 4.28,-11.4 6.28,-16.65 1.73,-4.56 -2,-6.77 -4.34,-9.21 -2.34,-2.44 -4.17,0.64 -5.76,1.9 -8.47,6.71 -16.68,13.75 -25.23,20.35 -4.06,3.13 -1,4.95 0.64,7.2 1.64,2.25 3.31,4.78 6.66,1.83 3.86,-3.39 7.94,-6.54 12,-9.83 0.15,0.38 0.29,0.56 0.25,0.68 -0.8,2.32 -1.67,4.62 -2.45,6.95 -1.63,4.92 1.52,8.51 6.69,7.7 2.15,-0.34 4.34,-1 6.9,0.1 -4.16,3.41 -7.77,6.61 -11.63,9.46 -3.17,2.34 -1.65,4.25 0.26,6 1.91,1.75 2.71,6.31 6.8,3 q 13.79,-11.12 27.49,-22.31 c 0.94,-0.77 2.15,-1.49 1.64,-3.23 z"
|
||||
id="path3851"
|
||||
fill="#fff" />
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 918.85,273.61 c 6.54,2.7 9.13,1.46 10.48,-5.3 0.3,-1.47 0.57,-2.93 0.93,-4.38 0.29,-1.18 0,-3.17 1.81,-2.92 1.81,0.25 4.13,-0.12 4.79,2.58 0.66,2.7 1.48,5.09 2.22,7.63 2.08,7 3.51,8.09 10.64,8.46 2.68,0.14 3.28,-0.77 2.57,-3.16 -1.12,-3.81 -2.09,-7.67 -3.28,-11.46 -0.55,-1.73 -1,-2.75 1.37,-3.74 5.78,-2.44 7.34,-7.68 7.75,-13.07 0,-6.66 -4,-11.53 -11.48,-13.53 -6.08,-1.62 -12.32,-2.63 -18.48,-4 -2.3,-0.5 -3.45,0.43 -3.88,2.63 -2.36,12 -4.76,24.08 -7.09,36.14 -0.31,1.63 -0.54,3.22 1.65,4.12 z m 17.54,-31 c 5.05,-0.51 9.92,2.41 9.87,5.4 -0.05,2.99 -1.8,4.44 -5.19,4.53 -2.09,-1.76 -6.94,1.1 -7.65,-3.37 -0.3,-1.89 -1,-6.11 2.97,-6.52 z"
|
||||
id="path3853"
|
||||
fill="#fff" />
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 853,664.82 c -2.84,-0.93 -5.74,-2.1 -6.74,2.62 -1.09,5.19 -2.75,10.25 -4.47,16.5 -2.63,-7.82 -5.07,-14.52 -7.1,-21.34 -1.33,-4.46 -5.15,-4.42 -8.37,-5 -3.55,-0.58 -2.91,3 -3.47,5 -3,10.36 -5.58,20.86 -8.8,31.16 -1.58,5.08 2.17,4.62 4.67,5.49 2.66,0.91 5.47,2 6.48,-2.4 1.21,-5.27 2.82,-10.45 4.45,-16.34 0.67,1.54 1.13,2.42 1.44,3.34 2,6 4.09,11.93 6,17.94 1.37,4.44 5.37,4.17 8.56,4.61 3.19,0.44 2.53,-3 3.06,-4.81 3,-10.38 5.53,-20.89 8.8,-31.17 1.49,-4.98 -1.96,-4.76 -4.51,-5.6 z"
|
||||
id="path3855"
|
||||
fill="#fff" />
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 1093.86,601.57 c -3.28,-0.47 -6.51,-1.44 -9.8,-1.75 -2.71,-0.25 -3.39,-1.19 -3.48,-4 -0.22,-7 -6.55,-12.74 -13.44,-12.82 -4.73,-0.13 -8.35,2.24 -11.25,5.56 -3.61,4.13 -6.71,8.7 -10.33,12.82 -2.46,2.81 -2.15,4.55 0.78,6.76 8.76,6.62 17.45,13.35 25.94,20.3 3,2.4 4.51,2.15 6.72,-0.86 4,-5.45 4.16,-5.32 -1.23,-9.5 -1.18,-0.92 -2.42,-1.78 -3.5,-2.81 -0.83,-0.79 -2.89,-1.11 -1.73,-2.91 0.94,-1.45 1.75,-3.35 4.16,-2.86 2.41,0.49 5,0.56 7.33,1.41 5.37,2 8.71,-0.09 11.63,-4.54 1.93,-2.89 2.03,-4.26 -1.8,-4.8 z m -30,5.43 c -0.75,0.06 -6.13,-4.56 -6.08,-5.23 0.13,-1.76 6.28,-7.65 8,-7.65 2.31,0.46 4,1.61 4.19,4.15 0.11,1.55 -4.97,8.63 -6.11,8.73 z"
|
||||
id="path3857"
|
||||
fill="#fff" />
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 845.26,274.6 c 0.35,2 1,3.6 3.49,3.21 9,-1.56 18.06,-2.91 27,-4.77 4.72,-1 1.47,-4.56 1.52,-7 0.05,-2.61 -1.37,-3.4 -3.93,-2.9 -4.89,0.95 -9.85,1.6 -14.74,2.57 -2.54,0.5 -3.21,-0.66 -3.45,-2.83 -0.21,-1.93 -0.49,-3.43 2.3,-3.74 4.13,-0.44 8.17,-1.61 12.3,-2.05 4.47,-0.48 3.65,-3.29 3.17,-6.13 -0.48,-2.84 -1.08,-5.17 -5,-4.09 -3.67,1 -7.56,1.16 -11.26,2.09 -2.6,0.66 -3.87,0.5 -4.41,-2.54 -0.59,-3.28 1.23,-3.55 3.55,-3.9 4.11,-0.61 8.2,-1.4 12.31,-2 2.63,-0.4 4.65,-1.13 3.59,-4.44 -0.85,-2.66 0.36,-6.86 -5.13,-5.72 -7.81,1.63 -15.68,3 -23.58,4 -3.78,0.48 -4.3,2.17 -3.74,5.31 2.03,11.67 4.02,23.33 6.01,34.93 z"
|
||||
id="path3859"
|
||||
fill="#fff" />
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 978.68,669.54 a 88.5,88.5 0 0 1 -8.92,3.07 c -2.51,0.8 -4.32,1.82 -2.82,5 1.19,2.46 0.87,6.55 5.62,4.65 0.87,-0.35 1.8,-1.17 2.65,-0.11 0.85,1.06 0.29,2.32 -0.13,3.32 -1.22,2.87 -3.78,4.1 -6.65,4.6 -2.87,0.5 -5.24,-0.87 -6.67,-3.37 a 32.79,32.79 0 0 1 -4,-11.2 c -0.93,-5.83 4.62,-10.93 9.91,-8.38 4.36,2.1 7.64,0.42 11.34,-0.66 2.53,-0.74 2.54,-2.25 1.08,-4.09 -3.38,-4.26 -8,-5.61 -13.24,-5.83 a 22.68,22.68 0 0 0 -15,5.6 c -5,4.48 -7,10.16 -5,16.65 2.53,8.49 4,18 14.56,20.8 8.1,2.13 15.24,-0.38 21,-6.12 6.23,-6.24 4.72,-13.51 2,-20.92 -1.19,-3.16 -2.35,-4.5 -5.73,-3.01 z"
|
||||
id="path3861"
|
||||
fill="#fff" />
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 1040.7,650.65 c -3.66,2.86 -7.64,5.31 -11.31,8.17 -2,1.56 -3,1.07 -4.29,-0.81 -1.29,-1.88 -1.69,-3 0.46,-4.41 3.33,-2.19 6.52,-4.59 9.76,-6.91 1.06,-0.76 2.34,-1.38 2.22,-3.22 a 13.54,13.54 0 0 0 -4.19,-5.8 c -1.86,-1.31 -3.3,0.69 -4.75,1.69 -3,2.08 -6.14,4 -8.94,6.34 -2.33,1.94 -3,0.17 -4.15,-1.21 -1.38,-1.61 -1.4,-2.61 0.53,-3.87 3.75,-2.45 7.22,-5.33 11,-7.71 3.1,-1.94 2.44,-3.82 0.62,-6.06 -1.61,-2 -2.59,-5 -6.15,-2.3 -6.52,4.86 -13.22,9.49 -19.89,14.17 -2.1,1.47 -2.19,2.93 -0.72,5 6.9,9.57 13.71,19.2 20.54,28.83 1.24,1.74 2.45,2.43 4.5,0.94 q 10.26,-7.5 20.69,-14.75 c 3.27,-2.27 1.29,-4.16 -0.11,-6.21 -1.4,-2.05 -2.73,-4.31 -5.82,-1.88 z"
|
||||
id="path3863"
|
||||
fill="#fff" />
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 782.4,634.42 c -1.4,-1 -2.88,-0.53 -4.14,0.45 q -15.18,11.8 -30.33,23.64 c -1.33,1 -2.32,2.47 -0.4,3.54 3.54,2 6.78,7 11.49,1.72 a 1.59,1.59 0 0 1 2.18,-0.47 c 3.76,2.46 7.55,4.87 11.3,7.33 1,0.68 0.67,1.74 0.55,2.72 -0.53,4.29 2.44,9.12 6.71,9.35 4.46,0.23 2.36,-4.48 3.76,-6.69 a 3,3 0 0 0 0.34,-0.94 c 2.6,-10.65 5.2,-21.31 8,-32.85 -1.12,-4.32 -6.07,-5.22 -9.46,-7.8 z m -6.4,26.72 c -7.81,-4.59 -7.81,-4.59 -1.47,-9.65 1.28,-1 2.6,-2 4.48,-3.44 A 56.33,56.33 0 0 1 776,661.14 Z"
|
||||
id="path3865"
|
||||
fill="#fff" />
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 769.49,297.35 c 5,6.94 12.68,9 20.82,6 8.46,-3.06 15,-11.32 14.66,-18.87 a 20.55,20.55 0 0 0 -1.24,-5.29 2.11,2.11 0 0 0 -2.13,-1.73 c -2.9,0 -8.23,5.19 -8.27,8.3 -0.05,4.19 -2.73,6.29 -6.08,7.63 -3.17,1.26 -6,0 -7.87,-2.63 a 73.14,73.14 0 0 1 -5.94,-9.75 c -1.4,-2.87 -1.14,-6 1.47,-8.23 2.61,-2.23 5.84,-3.74 9.55,-1.71 2.6,1.43 9.61,-1 11.1,-3.53 1,-1.62 -0.28,-2.53 -1.09,-3.43 a 13.88,13.88 0 0 0 -10.8,-4.68 c -13.38,0.05 -23.81,10.35 -22.4,21.61 0.8,6.34 4.73,11.34 8.22,16.31 z"
|
||||
id="path3867"
|
||||
fill="#fff" />
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 911.56,677.13 c -3.39,-8.82 -5.72,-10 -14.79,-8 a 3.88,3.88 0 0 0 -3.27,2.63 Q 887.8,690 882.14,708.3 c -0.33,1.07 -0.81,2.33 0.47,3.17 2.73,1.8 9.9,-0.72 11.13,-3.89 0.51,-1.32 0.52,-2.93 2.71,-2.89 4,0.08 8,0 12,-0.19 1.42,-0.06 2.3,0.48 2.55,1.76 0.77,4 3.17,5.18 6.48,4.32 6.77,-0.17 6.8,-0.19 4.58,-6 q -5.24,-13.76 -10.5,-27.45 z M 901,695.2 c -3,0 -3.44,-0.84 -2.54,-3.39 1.09,-3.12 2,-6.3 3.27,-10.36 1.33,3.4 2.31,5.85 3.24,8.31 2.08,5.57 2.03,5.38 -3.97,5.44 z"
|
||||
id="path3869"
|
||||
fill="#fff" />
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 999.44,302.68 c 2.34,1.28 4.57,4.69 7.27,0.18 3.57,-6 7.44,-11.79 11.16,-17.68 4.48,-7.08 4.6,-7.29 11.8,-2.76 3.83,2.42 4.84,-0.19 6.45,-2.52 1.72,-2.5 2.4,-4.41 -1,-6.41 q -12,-7.15 -23.55,-14.92 c -3.27,-2.18 -4.89,-1.6 -7,1.64 -2.34,3.57 -1.86,5.47 1.76,7.39 2.1,1.11 4.45,2.13 5.9,4.21 -0.74,1.19 -1.34,2.19 -2,3.17 -4.53,7.16 -8.93,14.4 -13.62,21.45 -2.52,3.88 0.39,4.91 2.83,6.25 z"
|
||||
id="path3871"
|
||||
fill="#fff" />
|
||||
</g>
|
||||
<g
|
||||
id="New_Anchor"
|
||||
data-name="New Anchor">
|
||||
<path
|
||||
class="cls-7"
|
||||
d="m 1008.89,520.42 c -2.57,-10.54 -5.11,-20.92 -7.68,-31.42 a 3.2,3.2 0 0 0 -5.33,-1.56 l -24.72,23.66 a 3.06,3.06 0 0 0 1.26,5.14 c 0.92,0.26 1.82,0.51 2.74,0.7 2,0.43 1.8,1.1 0.87,2.51 a 65.59,65.59 0 0 1 -20,19.58 l -0.2,0.12 a 86.78,86.78 0 0 1 -21.7,7 159.35,159.35 0 0 1 -23.53,2.72 1.84,1.84 0 0 1 -1.9,-1.87 V 436.62 a 1.08,1.08 0 0 1 1.08,-1.08 c 1,0 2.22,0.2 5.15,0.17 5.76,-0.06 11.76,-0.06 17.54,-0.4 1.88,-0.11 2.93,-0.05 4.13,0.85 a 12.35,12.35 0 0 0 16.71,-1.29 12.52,12.52 0 0 0 0.11,-16.76 12.3,12.3 0 0 0 -16.66,-1.58 4.07,4.07 0 0 1 -2.53,1.08 q -12.08,-0.06 -24.14,0 a 1.9,1.9 0 0 1 -1.39,-0.37 v -12.62 a 1.8,1.8 0 0 1 0.42,-1.18 6.42,6.42 0 0 1 2,-1.41 c 13,-6.6 19.74,-17.44 19.75,-31.87 0,-22.83 -22.27,-39.44 -44.29,-33.46 -17.46,4.74 -28.8,22.08 -25.51,39.77 2.42,13 10.07,22.1 22.51,26.92 a 6.59,6.59 0 0 1 1.33,0.66 1.8,1.8 0 0 1 0.71,1.47 v 10.32 a 1.78,1.78 0 0 1 -1.8,1.78 c -8.65,-0.1 -17.31,-0.06 -26,0 a 5.53,5.53 0 0 1 -3.31,-1.12 12.24,12.24 0 0 0 -16.62,1.7 12.37,12.37 0 0 0 16.73,18.07 5.08,5.08 0 0 1 3.3,-1.08 c 8.39,0 16.79,0.12 25.18,0 a 3.19,3.19 0 0 1 2.17,0.46 1,1 0 0 1 0.31,0.76 v 109.81 a 1.85,1.85 0 0 1 -2,1.84 192.44,192.44 0 0 1 -30.22,-5 92.79,92.79 0 0 1 -17.68,-6.21 1.56,1.56 0 0 1 -0.28,-0.16 66.87,66.87 0 0 1 -19.54,-21.38 1.38,1.38 0 0 1 1,-2.16 l 2.65,-0.54 a 3.08,3.08 0 0 0 1.6,-5.08 l -23.26,-25.35 a 3,3 0 0 0 -5.13,1.14 c -3.44,10.89 -6.79,21.53 -10.19,32.32 a 3.35,3.35 0 0 0 3.94,4.28 l 1.8,-0.41 a 5.12,5.12 0 0 1 5.69,2.64 c 13.38,26 33.5,44.81 60.12,56.7 10.4,4.65 14.52,6 23.5,7.37 a 1.78,1.78 0 0 1 1,0.51 l 13.67,13.55 a 4.91,4.91 0 0 0 6.85,0 l 13.28,-13 a 1.88,1.88 0 0 1 1.12,-0.52 c 13.3,-1.25 19.23,-4.54 33.54,-11.09 22.15,-10.13 39.74,-27.76 51.06,-49.32 1,-1.92 1.88,-2.15 3.58,-1.58 0.65,0.22 1.31,0.43 2,0.63 a 4.12,4.12 0 0 0 5.21,-4.98 z M 894.79,388.59 A 17.72,17.72 0 0 1 877.71,370.1 c 0.48,-10.46 9.18,-18.18 19,-17.43 10.34,0.8 17.46,9.11 16.94,18.69 -0.56,10.42 -9.1,17.96 -18.86,17.23 z"
|
||||
id="path3874"
|
||||
fill="#fff" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,16 +0,0 @@
|
||||
<svg width="35" height="35" viewBox="0 0 35 35" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M29.3361 18.8075H24.2368L21.6571 23.3262L24.2368 27.7838H29.3361L31.9157 23.3262L29.3361 18.8075Z" fill="#8061A9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M29.3361 6.83905H24.2368L21.6571 11.3577L24.2368 15.8153H29.3361L31.9157 11.3577L29.3361 6.83905Z" fill="#F17323"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.0774 1.13983H13.9781L11.3984 5.65852L13.9781 10.1161H19.0774L21.6571 5.65852L19.0774 1.13983Z" fill="#F8C517"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.81889 6.83905H3.71959L1.13989 11.3577L3.71959 15.8153H8.81889L11.3985 11.3577L8.81889 6.83905Z" fill="#CADD72"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.0774 12.8233H13.9781L11.3984 17.342L13.9781 21.7996H19.0774L21.6571 17.342L19.0774 12.8233Z" fill="#E82629"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.81889 18.8075H3.71959L1.13989 23.3262L3.71959 27.7838H8.81889L11.3985 23.3262L8.81889 18.8075Z" fill="#98C93E"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.0774 24.5067H13.9781L11.3984 29.0254L13.9781 33.483H19.0774L21.6571 29.0254L19.0774 24.5067Z" fill="#628AC6"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.8181 21.0633H14.2377L11.9205 17.1247L14.2377 13.1321H18.8181L21.1352 17.1247L18.8181 21.0633ZM19.6441 11.6834H13.3933L10.2587 17.116L13.3933 22.512H19.6441L22.797 17.116L19.6441 11.6834Z" fill="#363736"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.3932 23.3669L10.2587 28.7995L13.3932 34.1954H19.6441L22.797 28.7995L19.6441 23.3669H13.3932ZM11.9204 28.8082L14.2376 24.8156H18.818L21.1352 28.8082L18.818 32.7468H14.2376L11.9204 28.8082Z" fill="#363736"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.3932 0L10.2587 5.43263L13.3932 10.8285H19.6441L22.797 5.43263L19.6441 0H13.3932ZM11.9204 5.4412L14.2376 1.4487H18.818L21.1352 5.4412L18.818 9.37985H14.2376L11.9204 5.4412Z" fill="#363736"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M23.6518 17.6676L20.5172 23.1002L23.6518 28.4961H29.9026L33.0555 23.1002L29.9026 17.6676H23.6518ZM22.1791 23.1088L24.4962 19.1162H29.0766L31.3937 23.1088L29.0766 27.0475H24.4962L22.1791 23.1088Z" fill="#363736"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M23.6518 5.69922L20.5172 11.1319L23.6518 16.5278H29.9026L33.0555 11.1319L29.9026 5.69922H23.6518ZM22.1791 11.1405L24.4962 7.14791H29.0766L31.3937 11.1405L29.0766 15.0791H24.4962L22.1791 11.1405Z" fill="#363736"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.13453 17.6676L0 23.1002L3.13453 28.4961H9.38542L12.5383 23.1002L9.38542 17.6676H3.13453ZM1.66179 23.1088L3.97892 19.1162H8.55933L10.8765 23.1088L8.55933 27.0475H3.97892L1.66179 23.1088Z" fill="#363736"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.13453 5.69922L0 11.1319L3.13453 16.5278H9.38542L12.5383 11.1319L9.38542 5.69922H3.13453ZM1.66179 11.1405L3.97892 7.14791H8.55933L10.8765 11.1405L8.55933 15.0791H3.97892L1.66179 11.1405Z" fill="#363736"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.0 KiB |
@@ -1,22 +0,0 @@
|
||||
<svg width="415" height="435" viewBox="0 0 415 435" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M378.818 394.575C374.687 384.53 371.638 374.017 368.542 363.583C365.018 351.693 362.1 339.626 358.615 327.73C357.587 324.226 355.842 320.82 353.833 317.75C351.837 314.694 349.762 315.162 348.708 318.607C345.869 327.855 343.452 337.241 340.29 346.371C334.572 362.845 326.78 378.173 316.115 392.191C310.793 399.186 304.838 405.668 298.679 411.925C295.597 415.054 292.461 418.13 289.313 421.2C286.559 423.888 283.674 426.707 285.617 430.784C287.126 433.946 290.479 434.249 293.588 434.236C294.036 434.236 294.477 434.223 294.912 434.216C310.819 433.953 326.727 434.387 342.628 434.572C353.734 434.697 364.846 435.151 375.946 434.901C380.629 434.796 385.767 434.947 389.581 431.107C393.862 426.792 394.554 423.505 391.471 418.242C386.939 410.529 382.203 402.809 378.818 394.575Z" fill="url(#paint0_radial_248_90)"/>
|
||||
<path d="M409.948 262.887C407.879 262.38 405.857 261.826 403.894 261.188C383.527 254.68 369.45 241.453 353.964 226.559C351.599 224.274 350.829 221.672 350.994 218.405C351.87 203.189 350.038 188.157 347.357 173.231C343.583 152.409 337.345 132.279 328.848 112.867C326.938 108.513 324.388 104.659 323.058 100.042C322.926 99.5347 322.821 98.9551 323.163 98.5533C323.532 98.1054 324.276 98.2107 324.836 98.4215C329.777 100.437 337.635 122.774 343.985 117.063C345.342 115.844 345.842 113.98 346.192 112.202C351.58 85.5899 344.782 44.5856 321.016 28.1246C310.101 20.556 298.126 13.1983 285.031 10.2539C278.338 8.76522 271.06 8.84424 264.901 11.8743C261.844 13.363 259.084 15.563 255.765 16.3601C249.843 17.8224 243.947 14.5025 238.105 12.724C231.017 10.5964 223.284 10.7018 216.275 13.0665C210.643 14.9504 205.018 18.2967 199.175 17.2098C191.073 15.6948 185.23 6.34776 176.839 3.48239C166.774 0.0307768 155.595 0.0307897 145.287 2.34284C115.704 8.98259 87.9265 29.7516 67.2366 51.1265C44.531 74.5764 35.5002 105.595 55.5775 133.906C62.7508 144.024 73.2901 151.908 85.3181 155.017C87.6565 155.63 90.1266 156.104 92.0632 157.54C99.7108 163.225 83.5659 178.441 80.1143 183.381C72.6775 194.085 65.7479 205.184 60.5969 217.186C51.0391 239.417 46.8695 261.774 43.5232 285.573C37.7332 326.735 29.9802 369.044 10.7263 406.221C7.61722 412.196 3.74404 418.144 1.30024 424.415C0.713994 425.903 0.529556 427.655 1.30024 429.039C1.75475 429.836 2.49251 430.448 3.28954 430.87C7.59089 433.261 14.1252 432.727 18.8811 432.754C33.2211 432.806 47.5611 432.859 61.9274 432.885C69.2325 432.912 76.5309 432.938 83.836 432.938C89.0924 432.938 96.8256 434.269 101.601 431.739C104.684 430.119 106.383 426.667 107.233 423.268C108.478 418.275 109.275 413.151 110.606 408.158C114.696 392.889 120.513 378.358 127.976 364.393C139.819 342.215 152.196 317.151 130.209 296.909C124.419 291.6 117.753 287.378 111.541 282.595C110.349 281.667 109.176 279.783 110.428 278.933C110.909 278.59 111.567 278.67 112.18 278.801C136.163 283.821 158.335 309.583 156.847 334.251C156.05 347.129 150.872 358.682 146.94 370.631C142.955 382.771 138.285 394.773 137.165 407.677C136.71 412.775 136.183 417.926 136.131 423.051C136.052 429.691 138.548 433.116 146.09 433.142C173.683 433.195 201.276 433.623 228.87 433.887C235.878 433.966 250.278 436.278 253.09 427.221C254.124 423.874 252.8 420.291 251.075 417.261C249.349 414.231 247.142 411.392 246.213 408.019C244.514 401.992 247.168 395.642 249.988 390.043C253.255 383.562 257.319 377.482 260.56 371C264.361 364.15 268.82 357.773 272.245 350.686C275.855 343.275 278.78 335.549 281.197 327.69C284.464 317.144 286.829 306.335 288.687 295.473C289.082 293.121 289.339 290.75 289.622 288.379C289.767 287.187 289.912 285.994 290.083 284.809C290.274 283.478 290.57 281.897 292.296 282.022C302.592 282.747 287.139 341.675 285.788 345.271C282.626 353.716 278.832 361.923 274.366 369.782C268.761 379.636 258.459 388.581 260.981 401.037C261.884 405.444 262.944 411.767 266.93 414.554C272.397 418.407 279.438 412.005 283.318 408.527C289.424 403.026 294.338 396.472 299.489 390.096C313.671 372.568 324.586 352.622 332.523 331.564C341.152 308.568 345.006 285.698 348.029 261.477C348.214 260.094 348.51 258.526 349.676 257.789C351.007 256.939 352.732 257.578 354.162 258.217C371.69 265.97 390.628 272.241 409.691 270.403C412.029 270.166 414.947 269.184 415 266.846C415.046 264.534 412.207 263.414 409.948 262.887ZM316.708 250.912C316.523 251.577 316.016 252.157 315.43 252.532C314.317 253.224 312.828 253.408 311.55 253.54C303.053 254.416 294.687 251.814 287.04 248.363C285.821 247.829 284.596 247.276 283.377 246.663C271.718 240.873 260.883 232.613 251.931 223.161C244.336 215.137 238.335 205.632 234.218 195.383C233.342 193.203 232.308 190.871 231.801 188.559C231.373 186.596 231.643 184.284 233.158 182.927C234.113 182.077 235.417 181.761 236.662 181.491C240.832 180.667 245.265 180.213 249.487 180.588C251.213 180.694 253.018 181.148 254.243 182.341C255.33 183.375 255.863 184.837 256.344 186.273C258.413 192.485 260.145 198.887 263.089 204.783C266.067 210.757 269.993 216.363 274.083 221.619C275.572 223.529 277.113 225.387 278.707 227.225C286.592 236.282 296.953 244.384 309.06 246.689C309.541 246.795 310.015 246.874 310.523 246.953C312.196 247.19 313.948 247.355 315.384 248.283C316.076 248.738 316.688 249.449 316.767 250.273C316.761 250.484 316.761 250.694 316.708 250.912Z" fill="url(#paint1_radial_248_90)"/>
|
||||
<defs>
|
||||
<radialGradient id="paint0_radial_248_90" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(-404.314 -402.661) scale(1393.49)">
|
||||
<stop stop-color="#732DD9"/>
|
||||
<stop offset="0.1185" stop-color="#6A2BCB"/>
|
||||
<stop offset="0.3434" stop-color="#5125A5"/>
|
||||
<stop offset="0.6486" stop-color="#291C69"/>
|
||||
<stop offset="0.8139" stop-color="#121646"/>
|
||||
<stop offset="1" stop-color="#121646"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint1_radial_248_90" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(-404.315 -402.661) scale(1393.49)">
|
||||
<stop stop-color="#732DD9"/>
|
||||
<stop offset="0.1185" stop-color="#6A2BCB"/>
|
||||
<stop offset="0.3434" stop-color="#5125A5"/>
|
||||
<stop offset="0.6486" stop-color="#291C69"/>
|
||||
<stop offset="0.8139" stop-color="#121646"/>
|
||||
<stop offset="1" stop-color="#121646"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 6.0 KiB |
@@ -1,16 +0,0 @@
|
||||
<svg width="480" height="480" viewBox="0 0 480 480" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M245.308 31V110.692H325V31L245.308 31Z" fill="#425C82"/>
|
||||
<path d="M334.962 120.654V200.346H414.654V120.654H334.962Z" fill="#425C82"/>
|
||||
<path d="M245.308 120.654V200.346H325V120.654H245.308Z" fill="#425C82"/>
|
||||
<path d="M334.962 210.308V290H414.654V210.308H334.962Z" fill="#425C82"/>
|
||||
<path d="M245.308 210.308V290H325V210.308H245.308Z" fill="#101010"/>
|
||||
<path d="M155.654 210.308V290H235.346V210.308H155.654Z" fill="#101010"/>
|
||||
<path d="M66 210.308V290H145.692V210.308H66Z" fill="#101010"/>
|
||||
<path d="M155.654 120.654V200.346H235.346V120.654H155.654Z" fill="#101010"/>
|
||||
<path d="M104.25 416H100.125L93.5 406.812C91.875 408.271 90.1458 409.646 88.3125 410.938C86.5208 412.188 84.625 413.292 82.625 414.25C80.625 415.167 78.5625 415.896 76.4375 416.438C74.3542 416.979 72.2292 417.25 70.0625 417.25C65.3542 417.25 60.9167 416.375 56.75 414.625C52.625 412.833 49 410.375 45.875 407.25C42.7917 404.083 40.3542 400.354 38.5625 396.062C36.7708 391.729 35.875 387.021 35.875 381.938C35.875 376.896 36.7708 372.208 38.5625 367.875C40.3542 363.542 42.7917 359.792 45.875 356.625C49 353.458 52.625 350.979 56.75 349.188C60.9167 347.396 65.3542 346.5 70.0625 346.5C71.5625 346.5 73.1042 346.625 74.6875 346.875C76.3125 347.125 77.875 347.542 79.375 348.125C80.9167 348.667 82.3542 349.396 83.6875 350.312C85.0208 351.229 86.1458 352.354 87.0625 353.688V322.438H104.25V416ZM87.0625 381.938C87.0625 379.604 86.6042 377.354 85.6875 375.188C84.8125 372.979 83.6042 371.042 82.0625 369.375C80.5208 367.667 78.7083 366.312 76.625 365.312C74.5833 364.271 72.3958 363.75 70.0625 363.75C67.7292 363.75 65.5208 364.167 63.4375 365C61.3958 365.833 59.6042 367.042 58.0625 368.625C56.5625 370.167 55.375 372.062 54.5 374.312C53.625 376.562 53.1875 379.104 53.1875 381.938C53.1875 384.396 53.625 386.729 54.5 388.938C55.375 391.146 56.5625 393.083 58.0625 394.75C59.6042 396.417 61.3958 397.729 63.4375 398.688C65.5208 399.646 67.7292 400.125 70.0625 400.125C72.3958 400.125 74.5833 399.625 76.625 398.625C78.7083 397.583 80.5208 396.229 82.0625 394.562C83.6042 392.854 84.8125 390.917 85.6875 388.75C86.6042 386.542 87.0625 384.271 87.0625 381.938Z" fill="#101010"/>
|
||||
<path d="M143.938 399.625C144.604 399.833 145.271 399.979 145.938 400.062C146.604 400.104 147.271 400.125 147.938 400.125C149.604 400.125 151.208 399.896 152.75 399.438C154.292 398.979 155.729 398.333 157.062 397.5C158.438 396.625 159.646 395.583 160.688 394.375C161.771 393.125 162.646 391.75 163.312 390.25L175.812 402.812C174.229 405.062 172.396 407.083 170.312 408.875C168.271 410.667 166.042 412.188 163.625 413.438C161.25 414.688 158.729 415.625 156.062 416.25C153.438 416.917 150.729 417.25 147.938 417.25C143.229 417.25 138.792 416.375 134.625 414.625C130.5 412.875 126.875 410.438 123.75 407.312C120.667 404.188 118.229 400.479 116.438 396.188C114.646 391.854 113.75 387.104 113.75 381.938C113.75 376.646 114.646 371.812 116.438 367.438C118.229 363.062 120.667 359.333 123.75 356.25C126.875 353.167 130.5 350.771 134.625 349.062C138.792 347.354 143.229 346.5 147.938 346.5C150.729 346.5 153.458 346.833 156.125 347.5C158.792 348.167 161.312 349.125 163.688 350.375C166.104 351.625 168.354 353.167 170.438 355C172.521 356.792 174.354 358.812 175.938 361.062L143.938 399.625ZM152.688 364.438C151.896 364.146 151.104 363.958 150.312 363.875C149.562 363.792 148.771 363.75 147.938 363.75C145.604 363.75 143.396 364.188 141.312 365.062C139.271 365.896 137.479 367.104 135.938 368.688C134.438 370.271 133.25 372.188 132.375 374.438C131.5 376.646 131.062 379.146 131.062 381.938C131.062 382.562 131.083 383.271 131.125 384.062C131.208 384.854 131.312 385.667 131.438 386.5C131.604 387.292 131.792 388.062 132 388.812C132.208 389.562 132.479 390.229 132.812 390.812L152.688 364.438Z" fill="#101010"/>
|
||||
<path d="M202.688 416L177.188 349.062H196.625L211.25 390.812L225.812 349.062H245.312L219.812 416H202.688Z" fill="#101010"/>
|
||||
<path d="M276.438 399.625C277.104 399.833 277.771 399.979 278.438 400.062C279.104 400.104 279.771 400.125 280.438 400.125C282.104 400.125 283.708 399.896 285.25 399.438C286.792 398.979 288.229 398.333 289.562 397.5C290.938 396.625 292.146 395.583 293.188 394.375C294.271 393.125 295.146 391.75 295.812 390.25L308.312 402.812C306.729 405.062 304.896 407.083 302.812 408.875C300.771 410.667 298.542 412.188 296.125 413.438C293.75 414.688 291.229 415.625 288.562 416.25C285.938 416.917 283.229 417.25 280.438 417.25C275.729 417.25 271.292 416.375 267.125 414.625C263 412.875 259.375 410.438 256.25 407.312C253.167 404.188 250.729 400.479 248.938 396.188C247.146 391.854 246.25 387.104 246.25 381.938C246.25 376.646 247.146 371.812 248.938 367.438C250.729 363.062 253.167 359.333 256.25 356.25C259.375 353.167 263 350.771 267.125 349.062C271.292 347.354 275.729 346.5 280.438 346.5C283.229 346.5 285.958 346.833 288.625 347.5C291.292 348.167 293.812 349.125 296.188 350.375C298.604 351.625 300.854 353.167 302.938 355C305.021 356.792 306.854 358.812 308.438 361.062L276.438 399.625ZM285.188 364.438C284.396 364.146 283.604 363.958 282.812 363.875C282.062 363.792 281.271 363.75 280.438 363.75C278.104 363.75 275.896 364.188 273.812 365.062C271.771 365.896 269.979 367.104 268.438 368.688C266.938 370.271 265.75 372.188 264.875 374.438C264 376.646 263.562 379.146 263.562 381.938C263.562 382.562 263.583 383.271 263.625 384.062C263.708 384.854 263.812 385.667 263.938 386.5C264.104 387.292 264.292 388.062 264.5 388.812C264.708 389.562 264.979 390.229 265.312 390.812L285.188 364.438Z" fill="#101010"/>
|
||||
<path d="M334.125 416H317.062V349.062H321.188L326.812 355.562C329.562 353.062 332.667 351.146 336.125 349.812C339.625 348.438 343.271 347.75 347.062 347.75C351.146 347.75 355 348.542 358.625 350.125C362.25 351.667 365.417 353.812 368.125 356.562C370.833 359.271 372.958 362.458 374.5 366.125C376.083 369.75 376.875 373.625 376.875 377.75V416H359.812V377.75C359.812 376 359.479 374.354 358.812 372.812C358.146 371.229 357.229 369.854 356.062 368.688C354.896 367.521 353.542 366.604 352 365.938C350.458 365.271 348.812 364.938 347.062 364.938C345.271 364.938 343.583 365.271 342 365.938C340.417 366.604 339.042 367.521 337.875 368.688C336.708 369.854 335.792 371.229 335.125 372.812C334.458 374.354 334.125 376 334.125 377.75V416Z" fill="#101010"/>
|
||||
<path d="M405.312 416L379.812 349.062H399.25L413.875 390.812L428.438 349.062H447.938L422.438 416H405.312Z" fill="#101010"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 6.3 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user