Compare commits
25 Commits
90a44bd59f
...
gitops/upd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77ea1dc571 | ||
| 512b3cc2a6 | |||
| 3299373f3d | |||
| 80d0cc1168 | |||
| 5ca27a832b | |||
|
|
96ba77a606 | ||
|
|
dda6a9d032 | ||
|
|
1b6015f732 | ||
|
|
9877b093e8 | ||
|
|
0eab64c954 | ||
|
|
be362a5ab7 | ||
|
|
bb9f2ae3ce | ||
|
|
dc947165a4 | ||
|
|
1cd7625220 | ||
|
|
409f8247e6 | ||
|
|
8608696909 | ||
|
|
6454c893cb | ||
|
|
b2daa822a6 | ||
|
|
8ae7b086a5 | ||
|
|
4b7ed6085b | ||
|
|
0d97a796e9 | ||
|
|
b9f99c2950 | ||
|
|
a20ae55b8f | ||
|
|
36f447c39c | ||
|
|
76e3ff9d03 |
10
.claude/settings.json
Normal file
10
.claude/settings.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(for f:*)",
|
||||
"Bash(do echo:*)",
|
||||
"Read(//Users/jan.novak/srv/personal/home-kubernetes/**)",
|
||||
"Bash(done)"
|
||||
]
|
||||
}
|
||||
}
|
||||
16
.gitignore
vendored
16
.gitignore
vendored
@@ -1,4 +1,14 @@
|
||||
.terraform/
|
||||
.DS_Store
|
||||
|
||||
./kubernetes-kvm-terraform/join-command.txt
|
||||
./kubernetes-kvm-terraform/kubeconfig
|
||||
.terraform/
|
||||
.terraform.lock.hcl
|
||||
|
||||
kubernetes-kvm-terraform/join-command.txt
|
||||
kubernetes-kvm-terraform/kubeconfig
|
||||
|
||||
tmp/
|
||||
|
||||
vms/utility-101-shadow/docker/monitoring/smtp_password
|
||||
|
||||
docker-30/zot/sync-credentials.json
|
||||
kubernetes-kvm-terraform/gke_gcloud_auth_plugin_cache
|
||||
|
||||
7
blog/content/001-having-fun-with-gatewayApi.md
Normal file
7
blog/content/001-having-fun-with-gatewayApi.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# How i did have some fun with gatewayApi
|
||||
|
||||
As nginx-ingress will be no longer maintained it looks like the time to upgrade is coming even for the lazy old schoolers who were very happy with it (even though annotations and custom snippets might not be the cleanest way, people experienced with nginx might have liked it for a reason). Although I tried to pretend that there is no gatewayApi and ingress is the thing for quite some time recently everything aligned for me to give it a go.
|
||||
|
||||
## Which implementation to choose?
|
||||
|
||||
There is a number of options and I'm only vaguely aware of them as I was not interested in it for a long time. But i have a tendency of trying to do something with Envoy (personal feeling that it is the right next thing here?) and I'm using the Cilium network plugin in my homelab kubernetes cluster. All this considered answer is obvious: use envoy gateway which is part of cilium.
|
||||
10
docker-30/fuj-management/run.sh
Normal file
10
docker-30/fuj-management/run.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker rm -f fuj-management
|
||||
|
||||
# gitea registry login with kacerr / token
|
||||
docker run -d --name fuj-management \
|
||||
--restart=always \
|
||||
-p 8081:5001 \
|
||||
-v /srv/fuj-management/data:/app/data \
|
||||
gitea.home.hrajfrisbee.cz/kacerr/fuj-management:latest
|
||||
@@ -57,6 +57,15 @@ services:
|
||||
- GITEA__server__ROOT_URL=https://gitea.home.hrajfrisbee.cz
|
||||
- GITEA__security__SECRET_KEY=${GITEA_SECRET_KEY}
|
||||
- GITEA__security__INTERNAL_TOKEN=${INTERNAL_TOKEN}
|
||||
- GITEA__mailer__ENABLED=true
|
||||
- GITEA__mailer__PROTOCOL=smtps
|
||||
- GITEA__mailer__SMTP_ADDR=smtp.gmail.com
|
||||
- GITEA__mailer__SMTP_PORT=465
|
||||
- GITEA__mailer__USER=kacerr.cz@gmail.com
|
||||
- GITEA__mailer__PASSWD=${GMAIL_GITEA_APP_PASSWORD}
|
||||
- GITEA__mailer__FROM=kacerr.cz+gitea@gmail.com
|
||||
- GITEA__packages__ENABLED=true
|
||||
|
||||
#- GITEA__storage__STORAGE_TYPE=minio
|
||||
#- GITEA__storage__MINIO_ENDPOINT=minio:9000
|
||||
#- GITEA__storage__MINIO_ACCESS_KEY_ID=gitea
|
||||
@@ -83,10 +92,12 @@ services:
|
||||
depends_on:
|
||||
- gitea
|
||||
environment:
|
||||
GITEA_INSTANCE_URL: http://gitea:3000
|
||||
GITEA_INSTANCE_URL: https://gitea.home.hrajfrisbee.cz/
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: ${RUNNER_TOKEN}
|
||||
CONFIG_FILE: /config/config.yaml
|
||||
volumes:
|
||||
- ./runner-data:/data
|
||||
- ./runner-config.yaml:/config/config.yaml:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- gitea-network
|
||||
|
||||
84
docker-30/kanidm/gitea-action-kubernetes-access.md
Normal file
84
docker-30/kanidm/gitea-action-kubernetes-access.md
Normal file
@@ -0,0 +1,84 @@
|
||||
## 1. Create Kanidm service account + OAuth2 client
|
||||
|
||||
```bash
|
||||
# Create a service account for CI
|
||||
kanidm service-account create gitea_ci "Gitea CI Deploy" idm_admins --name idm_admin
|
||||
|
||||
# Create a group and add the service account
|
||||
kanidm group create k8s_deployers
|
||||
kanidm group add-members k8s_deployers gitea_ci
|
||||
|
||||
# Create the OAuth2 client (or reuse existing k8s one)
|
||||
# If you already have a k8s OIDC client, just add scope maps:
|
||||
kanidm system oauth2 update-scope-map k8s k8s_deployers openid groups
|
||||
|
||||
# Generate an API token for the service account
|
||||
kanidm service-account api-token generate --name idm_admin gitea_ci "gitea-ci-token"
|
||||
# ⚠️ Save the output token — this is the subject_token for exchange
|
||||
```
|
||||
|
||||
## 2. RBAC in Kubernetes
|
||||
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: gitea-ci-deploy
|
||||
subjects:
|
||||
- kind: User
|
||||
name: "gitea_ci@idm.home.hrajfrisbee.cz" # matches preferred_username claim
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: edit # scope down as needed
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
```
|
||||
|
||||
## 3. Token exchange + kubeconfig setup (test in bash)
|
||||
|
||||
```bash
|
||||
vault-login # prepared alias
|
||||
|
||||
#!/usr/bin/env bash
|
||||
# set -euo pipefail
|
||||
|
||||
KANIDM_URL="https://idm.home.hrajfrisbee.cz"
|
||||
OAUTH2_CLIENT_ID="k8s" # your k8s OIDC client name in Kanidm
|
||||
API_TOKEN=$(vault kv get -format=json -mount="secret" "k8s_home/gitea/gitea-ci-token" |jq -r .data.data.token)
|
||||
K8S_API="https://192.168.0.31:6443"
|
||||
|
||||
# Exchange the API token for an OIDC token via RFC 8693
|
||||
RESPONSE=$(curl -sf -X POST "${KANIDM_URL}/oauth2/token" \
|
||||
-d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
|
||||
-d "client_id=${OAUTH2_CLIENT_ID}" \
|
||||
-d "subject_token=${API_TOKEN}" \
|
||||
-d "subject_token_type=urn:ietf:params:oauth:token-type:access_token" \
|
||||
-d "audience=${OAUTH2_CLIENT_ID}" \
|
||||
-d "scope=openid groups")
|
||||
|
||||
ID_TOKEN=$(echo "$RESPONSE" | jq -r '.id_token')
|
||||
|
||||
# Inspect claims (sanity check)
|
||||
echo "$ID_TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq .
|
||||
|
||||
# Build kubeconfig
|
||||
export KUBECONFIG=$(mktemp)
|
||||
kubectl config set-cluster mycluster \
|
||||
--server="${K8S_API}" \
|
||||
--certificate-authority=/path/to/ca.crt
|
||||
|
||||
kubectl config set-credentials gitea-ci \
|
||||
--token="${ID_TOKEN}"
|
||||
|
||||
kubectl config set-context gitea-ci \
|
||||
--cluster=mycluster \
|
||||
--user=gitea-ci
|
||||
|
||||
kubectl config use-context gitea-ci
|
||||
|
||||
# Test
|
||||
kubectl auth whoami
|
||||
kubectl get ns
|
||||
|
||||
```
|
||||
@@ -1,3 +1,27 @@
|
||||
## Upgrade
|
||||
|
||||
```bash
|
||||
docker exec -it kanidmd kanidmd domain upgrade-check
|
||||
# make sure backup exists: /srv/docker/kanidm/data/kanidm/backups
|
||||
|
||||
# change container image in: /srv/docker/kanidm/run.sh
|
||||
|
||||
# kanidm data restore
|
||||
docker stop kanidmd
|
||||
docker run --rm -it \
|
||||
-v kanidmd:/data \
|
||||
-v kanidmd_backups:/backup \
|
||||
kanidm/server:latest \
|
||||
/sbin/kanidmd database restore -c /data/server.toml /backup/kanidm.backup.json
|
||||
docker start kanidmd
|
||||
```
|
||||
|
||||
## Recover passwords from kanidm instance
|
||||
|
||||
```bash
|
||||
docker exec -i -t kanidmd kanidmd recover-account idm_admin
|
||||
```
|
||||
|
||||
## add user to k8s group
|
||||
|
||||
based on: https://blog.kammel.dev/post/k8s_home_lab_2025_06/
|
||||
@@ -54,6 +78,50 @@ kanidm person get novakj | grep memberof
|
||||
kanidm group get idm_people_self_name_write
|
||||
```
|
||||
|
||||
## configure oauth proxy
|
||||
|
||||
```bash
|
||||
kanidm system oauth2 create oauth2-proxy "OAuth2 Proxy" https://oauth2-proxy.lab.home.hrajfrisbee.cz/oauth2/callback
|
||||
kanidm system oauth2 set-landing-url oauth2-proxy https://oauth2-proxy.lab.home.hrajfrisbee.cz
|
||||
kanidm system oauth2 enable-pkce oauth2-proxy
|
||||
kanidm system oauth2 warning-insecure-client-disable-pkce oauth2-proxy # if proxy doesn't support PKCE
|
||||
kanidm system oauth2 get oauth2-proxy # note the client secret
|
||||
|
||||
# update incorrect urls if needed
|
||||
remove-redirect-url
|
||||
kanidm system oauth2 add-redirect-url oauth2-proxy https://oauth2-proxy.lab.home.hrajfrisbee.cz/oauth2/callback
|
||||
kanidm system oauth2 set-landing-url oauth2-proxy https://oauth2-proxy.lab.home.hrajfrisbee.cz
|
||||
|
||||
# output
|
||||
✔ Multiple authentication tokens exist. Please select one · idm_admin@idm.home.hrajfrisbee.cz
|
||||
---
|
||||
class: account
|
||||
class: key_object
|
||||
class: key_object_internal
|
||||
class: key_object_jwe_a128gcm
|
||||
class: key_object_jwt_es256
|
||||
class: memberof
|
||||
class: oauth2_resource_server
|
||||
class: oauth2_resource_server_basic
|
||||
class: object
|
||||
displayname: OAuth2 Proxy
|
||||
key_internal_data: 69df0a387991455f7c9800f13b881803: valid jwe_a128gcm 0
|
||||
key_internal_data: c5f61c48a9c0eb61ba993a36748826cc: valid jws_es256 0
|
||||
name: oauth2-proxy
|
||||
oauth2_allow_insecure_client_disable_pkce: true
|
||||
oauth2_rs_basic_secret: hidden
|
||||
oauth2_rs_origin_landing: https://oauth2-proxylab.home.hrajfrisbee.cz/
|
||||
oauth2_strict_redirect_uri: true
|
||||
spn: oauth2-proxy@idm.home.hrajfrisbee.cz
|
||||
uuid: d0dcbad5-90e4-4e36-a51b-653624069009
|
||||
|
||||
secret: 7KJbUe5x35NVCT1VbzZfhYBU19cz9Xe9Z1fvw4WazrkHX2c8
|
||||
|
||||
|
||||
|
||||
kanidm system oauth2 update-scope-map oauth2-proxy k8s_users openid profile email
|
||||
```
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
@@ -71,4 +139,31 @@ docker run --rm -i -t -v --restart=always \
|
||||
docker.io/kanidm/server:latest \
|
||||
kanidmd cert-generate
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Service account for gitea runner
|
||||
|
||||
```bash
|
||||
# create service account
|
||||
#kanidm service-account create \
|
||||
# gitea_ci \ # account name
|
||||
# "Gitea CI Deploy" \ # display name
|
||||
# idm_admins \ # entry-managed-by (delegation group)
|
||||
# --name idm_admin # authenticate as this user
|
||||
|
||||
kanidm service-account create gitea_ci "Gitea CI Deploy" idm_admins --name idm_admin
|
||||
|
||||
# Create a group and add the service account
|
||||
kanidm group create k8s_deployers
|
||||
kanidm group add-members k8s_deployers gitea_ci
|
||||
|
||||
# Create the OAuth2 client (or reuse existing k8s one)
|
||||
# If you already have a k8s OIDC client, just add scope maps:
|
||||
kanidm system oauth2 update-scope-map k8s k8s_deployers openid groups
|
||||
|
||||
# Generate an API token for the service account
|
||||
kanidm service-account api-token generate --name idm_admin gitea_ci "gitea-ci-token"
|
||||
# ⚠️ Save the output token — this is the subject_token for exchange
|
||||
|
||||
```
|
||||
9
docker-30/kanidm/run.sh
Normal file
9
docker-30/kanidm/run.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
docker rm -f kanidmd
|
||||
|
||||
docker run -d --name=kanidmd --restart=always \
|
||||
-p '8443:8443' \
|
||||
-p '3636:3636' \
|
||||
--volume /srv/docker/kanidm/data:/data \
|
||||
docker.io/kanidm/server:1.9.1
|
||||
|
||||
# previous version: 1.8.5
|
||||
46
docker-30/lab-proxy/nginx.conf
Normal file
46
docker-30/lab-proxy/nginx.conf
Normal file
@@ -0,0 +1,46 @@
|
||||
# nginx.conf
|
||||
|
||||
error_log /dev/stderr;
|
||||
|
||||
http {
|
||||
|
||||
server {
|
||||
listen 9080;
|
||||
|
||||
location / {
|
||||
proxy_pass http://192.168.0.35:80;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
}
|
||||
|
||||
log_format detailed '$remote_addr - [$time_local] '
|
||||
'"$request_method $host$request_uri" '
|
||||
'$status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent"';
|
||||
|
||||
access_log /dev/stdout detailed;
|
||||
}
|
||||
|
||||
stream {
|
||||
# Stream doesn't log by default, enable explicitly:
|
||||
log_format stream_log '$remote_addr [$time_local] '
|
||||
'$protocol $ssl_preread_server_name '
|
||||
'$status $bytes_sent $bytes_received $session_time';
|
||||
|
||||
access_log /dev/stdout stream_log;
|
||||
|
||||
# Nginx ingress in kubernetes
|
||||
server {
|
||||
listen 9443;
|
||||
proxy_pass 192.168.0.35:443;
|
||||
}
|
||||
|
||||
# Gateway provided by cilium/envoy
|
||||
server {
|
||||
listen 9444;
|
||||
proxy_pass 192.168.0.36:443;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
events {}
|
||||
9
docker-30/lab-proxy/run.sh
Normal file
9
docker-30/lab-proxy/run.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
docker rm -f lab-proxy || /usr/bin/true
|
||||
|
||||
docker run -d --name lab-proxy \
|
||||
--restart unless-stopped \
|
||||
-v /srv/docker/lab-proxy/nginx.conf:/etc/nginx/nginx.conf:ro \
|
||||
-p 9443:9443 \
|
||||
-p 9444:9444 \
|
||||
-p 9080:9080 \
|
||||
nginx:alpine
|
||||
10
docker-30/maru-hleda-byt/run.sh
Normal file
10
docker-30/maru-hleda-byt/run.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker rm -f maru-hleda-byt
|
||||
|
||||
# gitea registry login with kacerr / token
|
||||
docker run -d --name maru-hleda-byt \
|
||||
--restart=always \
|
||||
-p 8080:8080 \
|
||||
-v /srv/maru-hleda-byt/data:/app/data \
|
||||
gitea.home.hrajfrisbee.cz/littlemeat/maru-hleda-byt:0.01
|
||||
22
docker-30/nginx/001-gitea.conf
Normal file
22
docker-30/nginx/001-gitea.conf
Normal file
@@ -0,0 +1,22 @@
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name gitea.home.hrajfrisbee.cz;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/gitea.home.hrajfrisbee.cz/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/gitea.home.hrajfrisbee.cz/privkey.pem;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
location / {
|
||||
proxy_pass http://192.168.0.30:3000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Gitea Git over HTTP
|
||||
client_max_body_size 512m;
|
||||
}
|
||||
35
docker-30/nginx/002-jellyfin.conf
Normal file
35
docker-30/nginx/002-jellyfin.conf
Normal file
@@ -0,0 +1,35 @@
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name jellyfin.home.hrajfrisbee.cz;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/gitea.home.hrajfrisbee.cz/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/gitea.home.hrajfrisbee.cz/privkey.pem;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
|
||||
# Security headers for media streaming
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Content-Type-Options "nosniff";
|
||||
|
||||
# Increase body size for high-res movie posters
|
||||
client_max_body_size 20M;
|
||||
|
||||
location / {
|
||||
# Proxy to your Synology or VM IP and Jellyfin port (default 8096)
|
||||
proxy_pass http://192.168.0.2:8096;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
|
||||
# Disable buffering for smoother streaming
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
||||
10
docker-30/vault/gitea-access-into-vault.md
Normal file
10
docker-30/vault/gitea-access-into-vault.md
Normal file
@@ -0,0 +1,10 @@
|
||||
## 1. Enable & configure JWT auth in Vault
|
||||
|
||||
```bash
|
||||
vault auth enable jwt
|
||||
|
||||
vault write auth/jwt/config \
|
||||
bound_issuer="https://gitea.home.hrajfrisbee.cz" \
|
||||
jwks_url="https://gitea.home.hrajfrisbee.cz/login/oauth/keys"
|
||||
|
||||
```
|
||||
@@ -4,6 +4,13 @@ resource "vault_mount" "kv" {
|
||||
description = "KV v2 secrets engine"
|
||||
}
|
||||
|
||||
resource "vault_jwt_auth_backend" "gitea" {
|
||||
path = "jwt"
|
||||
type = "jwt"
|
||||
bound_issuer = "https://gitea.home.hrajfrisbee.cz"
|
||||
jwks_url = "https://gitea.home.hrajfrisbee.cz/login/oauth/keys"
|
||||
}
|
||||
|
||||
resource "vault_policy" "eso_read" {
|
||||
name = "external-secrets-read"
|
||||
policy = <<-EOT
|
||||
@@ -16,6 +23,37 @@ resource "vault_policy" "eso_read" {
|
||||
EOT
|
||||
}
|
||||
|
||||
# for now i allow my gitea to read everything in /v1/secret/data/gitea
|
||||
resource "vault_policy" "gitea_ci_read" {
|
||||
name = "gitea-ci-read"
|
||||
policy = <<-EOT
|
||||
path "${vault_mount.kv.path}/data/gitea/*" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "${vault_mount.kv.path}/metadata/gitea/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_jwt_auth_backend_role" "gitea_ci" {
|
||||
backend = vault_jwt_auth_backend.gitea.path
|
||||
role_name = "gitea-ci"
|
||||
role_type = "jwt"
|
||||
token_policies = [vault_policy.gitea_ci_read.name]
|
||||
|
||||
user_claim = "sub"
|
||||
bound_audiences = ["https://gitea.home.hrajfrisbee.cz"]
|
||||
|
||||
# allow any valid jwt token when commented out
|
||||
# bound_claims = {
|
||||
# repository = "myorg/repo1,myorg/repo3"
|
||||
# }
|
||||
|
||||
token_ttl = 600
|
||||
token_max_ttl = 1200
|
||||
}
|
||||
|
||||
resource "vault_auth_backend" "approle" {
|
||||
type = "approle"
|
||||
}
|
||||
@@ -46,4 +84,32 @@ output "role_id" {
|
||||
output "secret_id" {
|
||||
value = vault_approle_auth_backend_role_secret_id.eso.secret_id
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
resource "vault_approle_auth_backend_role" "gitea_ci" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = "gitea-ci"
|
||||
token_policies = [vault_policy.gitea_ci_read.name]
|
||||
token_ttl = 600
|
||||
token_max_ttl = 1200
|
||||
}
|
||||
|
||||
data "vault_approle_auth_backend_role_id" "gitea_ci" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = vault_approle_auth_backend_role.gitea_ci.role_name
|
||||
}
|
||||
|
||||
resource "vault_approle_auth_backend_role_secret_id" "gitea_ci" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = vault_approle_auth_backend_role.gitea_ci.role_name
|
||||
}
|
||||
|
||||
output "gitea_ci_role_id" {
|
||||
value = data.vault_approle_auth_backend_role_id.gitea_ci.role_id
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "gitea_ci_secret_id" {
|
||||
value = vault_approle_auth_backend_role_secret_id.gitea_ci.secret_id
|
||||
sensitive = true
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -29,10 +29,10 @@ log "Backup size: ${BACKUP_SIZE} bytes"
|
||||
# --- Upload to MinIO ---
|
||||
log "Uploading to ${MC_ALIAS}/${S3_BUCKET}..."
|
||||
set -x
|
||||
mc cp --quiet "${BACKUP_FILE}" "${MC_ALIAS}/${S3_BUCKET}/vault-backup-${TIMESTAMP}.tar.gz"
|
||||
minio-cli cp --quiet "${BACKUP_FILE}" "${MC_ALIAS}/${S3_BUCKET}/vault-backup-${TIMESTAMP}.tar.gz"
|
||||
|
||||
# --- Prune old backups ---
|
||||
log "Pruning backups older than ${RETENTION_DAYS} days..."
|
||||
mc rm --quiet --recursive --force --older-than "${RETENTION_DAYS}d" "${MC_ALIAS}/${S3_BUCKET}/"
|
||||
minio-cli rm --quiet --recursive --force --older-than "${RETENTION_DAYS}d" "${MC_ALIAS}/${S3_BUCKET}/"
|
||||
|
||||
log "Backup complete: vault-backup-${TIMESTAMP}.tar.gz"
|
||||
52
docker-30/zot/config.yaml
Normal file
52
docker-30/zot/config.yaml
Normal file
@@ -0,0 +1,52 @@
|
||||
distSpecVersion: "1.1.0"
|
||||
storage:
|
||||
rootDirectory: /var/lib/zot
|
||||
gc: true
|
||||
gcDelay: "24h"
|
||||
dedupe: true
|
||||
http:
|
||||
address: 0.0.0.0
|
||||
port: 5000
|
||||
compat:
|
||||
- docker2s2
|
||||
log:
|
||||
# level: info
|
||||
level: debug
|
||||
extensions:
|
||||
ui:
|
||||
enable: true
|
||||
search:
|
||||
enable: true
|
||||
sync:
|
||||
enable: true
|
||||
credentialsFile: "/etc/zot/sync-credentials.json"
|
||||
registries:
|
||||
- urls: ["https://registry-1.docker.io"]
|
||||
onDemand: true
|
||||
tlsVerify: true
|
||||
content:
|
||||
- prefix: "library/**"
|
||||
destination: "/docker.io/library"
|
||||
- prefix: "democraticcsi/**"
|
||||
destination: "/democraticcsi"
|
||||
- prefix: "**"
|
||||
destination: "/docker.io"
|
||||
|
||||
- urls: ["https://registry.k8s.io"]
|
||||
onDemand: true
|
||||
tlsVerify: true
|
||||
content:
|
||||
- prefix: "**"
|
||||
destination: "/registry.k8s.io"
|
||||
- urls: ["https://ghcr.io"]
|
||||
onDemand: true
|
||||
tlsVerify: true
|
||||
content:
|
||||
- prefix: "**"
|
||||
destination: "/ghcr.io"
|
||||
- urls: ["https://quay.io"]
|
||||
onDemand: true
|
||||
tlsVerify: true
|
||||
content:
|
||||
- prefix: "**"
|
||||
destination: "/quay.io"
|
||||
12
docker-30/zot/docker-compose.yaml
Normal file
12
docker-30/zot/docker-compose.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
services:
|
||||
zot:
|
||||
image: ghcr.io/project-zot/zot-linux-amd64:latest
|
||||
container_name: zot
|
||||
restart: unless-stopped
|
||||
command: serve /etc/zot/config.yaml
|
||||
ports:
|
||||
- "5000:5000"
|
||||
volumes:
|
||||
- ./config.yaml:/etc/zot/config.yaml:ro
|
||||
- ./sync-credentials.json:/etc/zot/sync-credentials.json:ro
|
||||
- /srv/container-registry-data:/var/lib/zot
|
||||
391
experiments/e2b/dev-vm-deployment-plan.md
Normal file
391
experiments/e2b/dev-vm-deployment-plan.md
Normal file
@@ -0,0 +1,391 @@
|
||||
# E2B Dev VM Setup on KVM Homelab
|
||||
|
||||
## Context
|
||||
|
||||
The user wants to run the E2B infrastructure dev stack on a KVM virtual machine in their homelab. E2B uses Firecracker microVMs (which need `/dev/kvm`), so the guest VM needs **nested virtualization** (KVM-in-KVM). This guide covers VM creation, OS configuration, toolchain installation, and running the full dev stack.
|
||||
|
||||
> **Note from upstream**: [DEV-LOCAL.md](DEV-LOCAL.md) says "Linux is required. This is a work in progress. Not everything will function as expected."
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Create the KVM VM on the Hypervisor Host
|
||||
|
||||
### 1.1 Enable nested virtualization on the host
|
||||
|
||||
**Intel:**
|
||||
|
||||
```bash
|
||||
cat /sys/module/kvm_intel/parameters/nested # check
|
||||
sudo modprobe -r kvm_intel && sudo modprobe kvm_intel nested=1
|
||||
echo "options kvm_intel nested=1" | sudo tee /etc/modprobe.d/kvm-nested.conf
|
||||
```
|
||||
|
||||
**AMD:**
|
||||
|
||||
```bash
|
||||
cat /sys/module/kvm_amd/parameters/nested
|
||||
sudo modprobe -r kvm_amd && sudo modprobe kvm_amd nested=1
|
||||
echo "options kvm_amd nested=1" | sudo tee /etc/modprobe.d/kvm-nested.conf
|
||||
|
||||
# get details about loaded kernel module
|
||||
systool -v -m kvm_amd
|
||||
```
|
||||
|
||||
### 1.2 Create the VM
|
||||
|
||||
```bash
|
||||
virt-install \
|
||||
--name e2b-dev \
|
||||
--ram 16384 \
|
||||
--vcpus 8 \
|
||||
--cpu host-passthrough \
|
||||
--os-variant ubuntu24.04 \
|
||||
--disk path=/var/lib/libvirt/images/e2b-dev.qcow2,size=100,format=qcow2,bus=virtio \
|
||||
--network bridge=virbr0,model=virtio \
|
||||
--graphics none \
|
||||
--console pty,target_type=serial \
|
||||
--cdrom /path/to/ubuntu-24.04-live-server-amd64.iso \
|
||||
--extra-args 'console=ttyS0,115200n8'
|
||||
```
|
||||
|
||||
**Why these specs:**
|
||||
| Resource | Value | Rationale |
|
||||
|----------|-------|-----------|
|
||||
| RAM | 16 GB (24-32 better) | 4 GB for huge pages (2048 x 2MB), ~4 GB for 10 Docker containers, rest for Go services + Firecracker VMs |
|
||||
| vCPUs | 8 | Firecracker VMs consume vCPUs; Go services are concurrent |
|
||||
| Disk | 100 GB | Docker images, FC binaries, kernels, rootfs, Go cache, build artifacts |
|
||||
| CPU | `host-passthrough` | **Mandatory** -- exposes VMX/SVM to guest so `/dev/kvm` works inside the VM |
|
||||
|
||||
### 1.3 Alternative: libvirt XML
|
||||
|
||||
If you manage VMs declaratively, the critical part is:
|
||||
|
||||
```xml
|
||||
<cpu mode='host-passthrough' check='none' migratable='off'/>
|
||||
```
|
||||
|
||||
### 1.4 Verify nested KVM works (after OS install)
|
||||
|
||||
```bash
|
||||
ls -la /dev/kvm # must exist
|
||||
lsmod | grep kvm # kvm + kvm_intel/kvm_amd
|
||||
grep -cE '(vmx|svm)' /proc/cpuinfo # must be > 0
|
||||
```
|
||||
|
||||
If `/dev/kvm` is missing, go back to 1.1.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: OS Configuration (inside the guest VM)
|
||||
|
||||
**Recommended OS:** Ubuntu 24.04 LTS Server (matches CI, well-tested with Firecracker)
|
||||
|
||||
### 2.1 Base packages
|
||||
|
||||
```bash
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
sudo apt install -y \
|
||||
build-essential git curl wget unzip jq make gcc pkg-config \
|
||||
iptables iproute2 net-tools ca-certificates gnupg \
|
||||
lsb-release software-properties-common gettext-base
|
||||
```
|
||||
|
||||
### 2.2 Kernel modules
|
||||
|
||||
```bash
|
||||
# Load now
|
||||
sudo modprobe nbd nbds_max=64
|
||||
sudo modprobe kvm
|
||||
sudo modprobe kvm_intel # or kvm_amd
|
||||
sudo modprobe tun
|
||||
sudo modprobe veth
|
||||
sudo modprobe nf_tables
|
||||
sudo modprobe nft_nat
|
||||
|
||||
# Persist across reboots
|
||||
cat <<'EOF' | sudo tee /etc/modules-load.d/e2b.conf
|
||||
nbd
|
||||
kvm
|
||||
kvm_intel
|
||||
tun
|
||||
veth
|
||||
nf_tables
|
||||
nft_nat
|
||||
EOF
|
||||
|
||||
echo "options nbd nbds_max=64" | sudo tee /etc/modprobe.d/nbd.conf
|
||||
```
|
||||
|
||||
### 2.3 Sysctl
|
||||
|
||||
```bash
|
||||
cat <<'EOF' | sudo tee /etc/sysctl.d/99-e2b.conf
|
||||
vm.nr_hugepages=2048
|
||||
vm.max_map_count=1048576
|
||||
vm.swappiness=10
|
||||
vm.vfs_cache_pressure=50
|
||||
net.ipv4.ip_forward=1
|
||||
net.core.somaxconn=65535
|
||||
net.core.netdev_max_backlog=65535
|
||||
net.ipv4.tcp_max_syn_backlog=65535
|
||||
EOF
|
||||
|
||||
sudo sysctl --system
|
||||
```
|
||||
|
||||
### 2.4 Udev rules (suppress NBD inotify noise)
|
||||
|
||||
```bash
|
||||
cat <<'EOF' | sudo tee /etc/udev/rules.d/99-e2b-nbd.rules
|
||||
KERNEL=="nbd*", OPTIONS+="nowatch"
|
||||
EOF
|
||||
sudo udevadm control --reload-rules && sudo udevadm trigger
|
||||
```
|
||||
|
||||
### 2.5 File descriptor limits
|
||||
|
||||
```bash
|
||||
cat <<'EOF' | sudo tee /etc/security/limits.d/e2b.conf
|
||||
* soft nofile 1048576
|
||||
* hard nofile 1048576
|
||||
root soft nofile 1048576
|
||||
root hard nofile 1048576
|
||||
EOF
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Install Toolchain
|
||||
|
||||
### 3.1 Docker
|
||||
|
||||
```bash
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
sudo usermod -aG docker $USER
|
||||
# Log out and back in
|
||||
docker --version && docker compose version
|
||||
```
|
||||
|
||||
### 3.2 mise (manages all tools from `.tool-versions`)
|
||||
|
||||
```bash
|
||||
curl https://mise.run | sh
|
||||
echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
### 3.3 Install project tools
|
||||
|
||||
The repo's [.tool-versions](.tool-versions) pins:
|
||||
|
||||
| Tool | Version |
|
||||
| --- | --- |
|
||||
| golang | 1.25.4 |
|
||||
| buf | 1.28.1 |
|
||||
| bun | 1.3.2 |
|
||||
| protoc | 29.3 |
|
||||
| protoc-gen-go | 1.28.1 |
|
||||
| protoc-gen-go-grpc | 1.6.1 |
|
||||
| protoc-gen-connect-go | 1.18.1 |
|
||||
| golangci-lint | 2.8.0 |
|
||||
| terraform | 1.5.7 |
|
||||
| packer | 1.13.1 |
|
||||
| python | 3.13.11 |
|
||||
| gcloud | 534.0.0 |
|
||||
|
||||
```bash
|
||||
cd ~/e2b-infra # after cloning
|
||||
mise install # installs everything from .tool-versions
|
||||
```
|
||||
|
||||
> **Note:** `gcloud` is only needed for `gsutil` to download prebuilt artifacts. If you don't have GCP credentials, you can download them via HTTPS instead (see Phase 5).
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Clone Repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/e2b-dev/infra.git ~/e2b-infra
|
||||
cd ~/e2b-infra
|
||||
go work sync
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Download Prebuilt Artifacts
|
||||
|
||||
Firecracker binaries and Linux kernels must be downloaded from the public GCS bucket.
|
||||
|
||||
**With gsutil (if gcloud is configured):**
|
||||
|
||||
```bash
|
||||
make download-public-kernels
|
||||
make download-public-firecrackers
|
||||
```
|
||||
|
||||
**Without GCP credentials (HTTPS alternative):**
|
||||
|
||||
The bucket `e2b-prod-public-builds` is publicly accessible. You'll need to browse/list it to find available versions, then download manually:
|
||||
|
||||
```bash
|
||||
# Install gsutil standalone (no GCP project needed for public buckets)
|
||||
# OR use curl/wget against:
|
||||
# https://storage.googleapis.com/e2b-prod-public-builds/
|
||||
# to discover and download kernel and firecracker builds
|
||||
```
|
||||
|
||||
The simplest path is to install just the `gcloud` CLI (via mise) and run the make targets -- no GCP project or auth is needed for public bucket reads.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Prepare Local Environment
|
||||
|
||||
### 6.1 Start infrastructure containers
|
||||
|
||||
```bash
|
||||
make local-infra
|
||||
# Starts: PostgreSQL 17.4, Redis 7.4.2, ClickHouse 25.4.5.24,
|
||||
# Grafana 12.0.0, Loki 3.4.1, Tempo 2.8.2, Mimir 2.17.1,
|
||||
# OTEL Collector 0.146.0, Vector, Memcached 1.6.38
|
||||
```
|
||||
|
||||
Wait for all containers to be healthy:
|
||||
|
||||
```bash
|
||||
docker compose -f packages/local-dev/docker-compose.yaml ps
|
||||
```
|
||||
|
||||
### 6.2 Initialize databases
|
||||
|
||||
```bash
|
||||
make -C packages/db migrate-local # PostgreSQL
|
||||
make -C packages/clickhouse migrate-local # ClickHouse
|
||||
```
|
||||
|
||||
### 6.3 Build envd (in-VM daemon)
|
||||
|
||||
```bash
|
||||
make -C packages/envd build
|
||||
```
|
||||
|
||||
### 6.4 Seed database with dev credentials
|
||||
|
||||
```bash
|
||||
make -C packages/local-dev seed-database
|
||||
```
|
||||
|
||||
Creates test user, team, API key, and access token for local development.
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: Run the Dev Stack
|
||||
|
||||
Each service runs in the foreground. Use **tmux**, **screen**, or separate SSH sessions.
|
||||
|
||||
| Terminal | Command | Listens on |
|
||||
| --- | --- | --- |
|
||||
| 1 | `make local-infra` | (Docker containers) |
|
||||
| 2 | `make -C packages/api run-local` | `:3000` |
|
||||
| 3 | `make -C packages/orchestrator build-debug && sudo make -C packages/orchestrator run-local` | `:5008` |
|
||||
| 4 | `make -C packages/client-proxy run-local` | `:3002` |
|
||||
|
||||
> The orchestrator **requires sudo** -- Firecracker needs root for `/dev/kvm`, network namespaces, veth pairs, nftables rules, and NBD devices.
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: Verify
|
||||
|
||||
### 8.1 Health checks
|
||||
|
||||
```bash
|
||||
curl -s http://localhost:3000/health # API
|
||||
curl -s -o /dev/null -w "%{http_code}" http://localhost:53000 # Grafana (expect 302)
|
||||
curl -s 'http://localhost:8123/?query=SELECT%201' # ClickHouse
|
||||
redis-cli -h localhost -p 6379 ping # Redis
|
||||
```
|
||||
|
||||
### 8.2 Build the base template
|
||||
|
||||
```bash
|
||||
make -C packages/shared/scripts local-build-base-template
|
||||
```
|
||||
|
||||
### 8.3 Test with E2B client SDK
|
||||
|
||||
```bash
|
||||
export E2B_API_KEY=e2b_53ae1fed82754c17ad8077fbc8bcdd90
|
||||
export E2B_ACCESS_TOKEN=sk_e2b_89215020937a4c989cde33d7bc647715
|
||||
export E2B_API_URL=http://localhost:3000
|
||||
export E2B_SANDBOX_URL=http://localhost:3002
|
||||
# Use E2B SDK/CLI to create a sandbox
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 9: Access from Host (Optional)
|
||||
|
||||
### SSH port forwarding
|
||||
|
||||
```bash
|
||||
ssh -N \
|
||||
-L 3000:localhost:3000 \
|
||||
-L 3002:localhost:3002 \
|
||||
-L 53000:localhost:53000 \
|
||||
-L 5432:localhost:5432 \
|
||||
-L 8123:localhost:8123 \
|
||||
user@<vm-ip>
|
||||
```
|
||||
|
||||
### Or use bridged networking
|
||||
|
||||
If the VM has a routable IP on your LAN, services are directly accessible (Docker binds to `0.0.0.0`, Go services listen on all interfaces).
|
||||
|
||||
---
|
||||
|
||||
## Service Endpoints Reference
|
||||
|
||||
| Service | URL |
|
||||
| --- | --- |
|
||||
| E2B API | `http://localhost:3000` |
|
||||
| E2B Client Proxy | `http://localhost:3002` |
|
||||
| E2B Orchestrator | `http://localhost:5008` |
|
||||
| Grafana | `http://localhost:53000` |
|
||||
| PostgreSQL | `postgres://postgres:postgres@localhost:5432` |
|
||||
| ClickHouse (HTTP) | `http://localhost:8123` |
|
||||
| ClickHouse (native) | `localhost:9000` |
|
||||
| Redis | `localhost:6379` |
|
||||
| OTEL Collector (gRPC) | `localhost:4317` |
|
||||
| OTEL Collector (HTTP) | `localhost:4318` |
|
||||
| Loki | `http://localhost:3100` |
|
||||
| Vector | `localhost:30006` |
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Problem | Fix |
|
||||
| --- | --- |
|
||||
| `/dev/kvm` missing in guest | Enable nested virt on host (Phase 1.1), use `host-passthrough` CPU |
|
||||
| `modprobe nbd` fails | Check kernel has NBD support: `modinfo nbd` |
|
||||
| Orchestrator permission errors | Must run with `sudo` |
|
||||
| Huge pages < 2048 | Not enough contiguous memory; increase VM RAM or set earlier in boot |
|
||||
| Docker containers won't start | Check `systemctl status docker`, port conflicts with `ss -tlnp` |
|
||||
| `gsutil` not found | Install via `mise install gcloud` or download artifacts via HTTPS |
|
||||
|
||||
---
|
||||
|
||||
## After VM Reboot Checklist
|
||||
|
||||
```bash
|
||||
# 1. Verify kernel modules and sysctl (should be persistent)
|
||||
lsmod | grep nbd
|
||||
cat /proc/sys/vm/nr_hugepages # expect 2048
|
||||
|
||||
# 2. Start infra
|
||||
cd ~/e2b-infra && make local-infra
|
||||
|
||||
# 3. Start services (separate terminals)
|
||||
make -C packages/api run-local
|
||||
sudo make -C packages/orchestrator run-local
|
||||
make -C packages/client-proxy run-local
|
||||
```
|
||||
95
experiments/e2b/installation.md
Normal file
95
experiments/e2b/installation.md
Normal file
@@ -0,0 +1,95 @@
|
||||
## dev-vm on beelink
|
||||
|
||||
```bash
|
||||
virt-install \
|
||||
--name e2b-dev \
|
||||
--ram 16384 \
|
||||
--vcpus 8 \
|
||||
--cpu host-passthrough \
|
||||
--os-variant ubuntu24.04 \
|
||||
--disk path=/srv/vms/e2b-dev.qcow2,size=100,format=qcow2,bus=virtio \
|
||||
--network bridge=br0,model=virtio \
|
||||
--graphics none \
|
||||
--console pty,target_type=serial \
|
||||
--location /srv/vms/isos/ubuntu-24.04.3-live-server-amd64.iso,kernel=casper/vmlinuz,initrd=casper/initrd \
|
||||
--extra-args 'console=ttyS0,115200n8'
|
||||
|
||||
|
||||
# base packages
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
sudo apt install -y \
|
||||
build-essential git curl wget unzip jq make gcc pkg-config \
|
||||
iptables iproute2 net-tools ca-certificates gnupg \
|
||||
lsb-release software-properties-common gettext-base
|
||||
|
||||
|
||||
# kernel modules
|
||||
# Load now
|
||||
sudo modprobe nbd nbds_max=64
|
||||
sudo modprobe kvm
|
||||
sudo modprobe kvm_amd # or kvm_amd
|
||||
sudo modprobe tun
|
||||
sudo modprobe veth
|
||||
sudo modprobe nf_tables
|
||||
sudo modprobe nft_nat
|
||||
|
||||
# Persist across reboots
|
||||
cat <<'EOF' | sudo tee /etc/modules-load.d/e2b.conf
|
||||
nbd
|
||||
kvm
|
||||
kvm_amd
|
||||
tun
|
||||
veth
|
||||
nf_tables
|
||||
nft_nat
|
||||
EOF
|
||||
|
||||
echo "options nbd nbds_max=64" | sudo tee /etc/modprobe.d/nbd.conf
|
||||
|
||||
# sysctl
|
||||
cat <<'EOF' | sudo tee /etc/sysctl.d/99-e2b.conf
|
||||
vm.nr_hugepages=2048
|
||||
vm.max_map_count=1048576
|
||||
vm.swappiness=10
|
||||
vm.vfs_cache_pressure=50
|
||||
net.ipv4.ip_forward=1
|
||||
net.core.somaxconn=65535
|
||||
net.core.netdev_max_backlog=65535
|
||||
net.ipv4.tcp_max_syn_backlog=65535
|
||||
EOF
|
||||
|
||||
sudo sysctl --system
|
||||
|
||||
# udev rules
|
||||
cat <<'EOF' | sudo tee /etc/udev/rules.d/99-e2b-nbd.rules
|
||||
KERNEL=="nbd*", OPTIONS+="nowatch"
|
||||
EOF
|
||||
sudo udevadm control --reload-rules && sudo udevadm trigger
|
||||
|
||||
# file descriptor limits
|
||||
cat <<'EOF' | sudo tee /etc/security/limits.d/e2b.conf
|
||||
* soft nofile 1048576
|
||||
* hard nofile 1048576
|
||||
root soft nofile 1048576
|
||||
root hard nofile 1048576
|
||||
EOF
|
||||
```
|
||||
|
||||
## install toolchain
|
||||
|
||||
```bash
|
||||
# docker
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
sudo usermod -aG docker $USER
|
||||
# Log out and back in
|
||||
docker --version && docker compose version
|
||||
|
||||
# mise
|
||||
curl https://mise.run | sh
|
||||
echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
280
experiments/e2b/sanbox-usage-generated-from-infra-repo.md
Normal file
280
experiments/e2b/sanbox-usage-generated-from-infra-repo.md
Normal file
@@ -0,0 +1,280 @@
|
||||
# E2B Sandbox Usage Guide
|
||||
|
||||
A practical guide for creating, observing, and using E2B sandboxes via the API.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Local Dev Setup
|
||||
|
||||
Seed the database to create a test team and API key:
|
||||
|
||||
```bash
|
||||
make -C packages/local-dev seed-database
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
E2B_API_KEY=e2b_53ae1fed82754c17ad8077fbc8bcdd90
|
||||
E2B_ACCESS_TOKEN=sk_e2b_89215020937a4c989cde33d7bc647715
|
||||
E2B_API_URL=http://localhost:3000
|
||||
E2B_SANDBOX_URL=http://localhost:3002
|
||||
```
|
||||
|
||||
All examples below use `$E2B_API_URL` and `$E2B_API_KEY` — export them in your shell for convenience:
|
||||
|
||||
```bash
|
||||
export E2B_API_URL=http://localhost:3000
|
||||
export E2B_API_KEY=e2b_53ae1fed82754c17ad8077fbc8bcdd90
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. Create a Sandbox
|
||||
|
||||
```bash
|
||||
curl -X POST $E2B_API_URL/sandboxes \
|
||||
-H "X-API-Key: $E2B_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"templateID": "base",
|
||||
"timeout": 300
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"sandboxID": "i1234567890abcdef",
|
||||
"templateID": "base",
|
||||
"envdVersion": "0.5.8",
|
||||
"domain": "i1234567890abcdef.your-domain"
|
||||
}
|
||||
```
|
||||
|
||||
Save the `sandboxID` and `domain` from the response for subsequent commands.
|
||||
|
||||
### Optional Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `secure` | bool | Returns an `envdAccessToken` for authenticated envd access |
|
||||
| `envVars` | object | Inject environment variables into the VM |
|
||||
| `metadata` | object | Tag the sandbox for filtering (e.g. `{"purpose": "test"}`) |
|
||||
| `autoPause` | bool | Pause instead of kill on timeout |
|
||||
| `allow_internet_access` | bool | Allow internet egress from the VM |
|
||||
| `network.allowPublicTraffic` | bool | Allow inbound public traffic |
|
||||
| `network.allowOut` | array | Allowed egress destinations (IPs, CIDRs, domains) |
|
||||
| `network.denyOut` | array | Denied egress destinations (IPs/CIDRs only) |
|
||||
| `volumeMounts` | array | Mount persistent volumes (`{"name": "vol", "path": "/data"}`) |
|
||||
|
||||
**Example with options:**
|
||||
|
||||
```bash
|
||||
curl -X POST $E2B_API_URL/sandboxes \
|
||||
-H "X-API-Key: $E2B_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"templateID": "base",
|
||||
"timeout": 300,
|
||||
"secure": true,
|
||||
"envVars": {"MY_VAR": "hello"},
|
||||
"metadata": {"purpose": "demo"}
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Observe Sandbox State
|
||||
|
||||
### Get details of a specific sandbox
|
||||
|
||||
```bash
|
||||
curl $E2B_API_URL/sandboxes/{sandboxID} \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
```
|
||||
|
||||
Returns state (`running`/`paused`), CPU/memory/disk config, network settings, and TTL (`endAt`).
|
||||
|
||||
### List all sandboxes
|
||||
|
||||
```bash
|
||||
# Running only
|
||||
curl "$E2B_API_URL/v2/sandboxes?state=running" \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
|
||||
# Running and paused
|
||||
curl "$E2B_API_URL/v2/sandboxes?state=running&state=paused" \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
|
||||
# Filter by metadata
|
||||
curl "$E2B_API_URL/v2/sandboxes?metadata=purpose%3Ddemo" \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
```
|
||||
|
||||
### Get resource metrics (CPU, memory, disk)
|
||||
|
||||
```bash
|
||||
curl "$E2B_API_URL/sandboxes/{sandboxID}/metrics?start=$(date -v-5M +%s)&end=$(date +%s)" \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"timestampUnix": 1234567890,
|
||||
"cpuCount": 2,
|
||||
"cpuUsedPct": 25.5,
|
||||
"memUsed": 268435456,
|
||||
"memTotal": 536870912,
|
||||
"diskUsed": 1073741824,
|
||||
"diskTotal": 5368709120
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Get sandbox logs
|
||||
|
||||
```bash
|
||||
curl "$E2B_API_URL/v2/sandboxes/{sandboxID}/logs?limit=100&direction=backward" \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
```
|
||||
|
||||
Optional query parameters: `cursor` (ms timestamp), `level` (min log level), `search` (substring match).
|
||||
|
||||
---
|
||||
|
||||
## 3. Use the Sandbox
|
||||
|
||||
The in-VM daemon (**envd**) runs on port 49983 inside each sandbox, exposed via the sandbox's `domain`.
|
||||
|
||||
### Upload a file
|
||||
|
||||
```bash
|
||||
curl -X POST https://{domain}/files \
|
||||
-H "Content-Type: multipart/form-data" \
|
||||
-F "file=@script.py" \
|
||||
-F "path=/home/user/script.py"
|
||||
```
|
||||
|
||||
### Using the E2B Python SDK
|
||||
|
||||
Point the SDK at your local API:
|
||||
|
||||
```python
|
||||
from e2b import Sandbox
|
||||
|
||||
sbx = Sandbox("base", api_url="http://localhost:3000")
|
||||
|
||||
# Run a command
|
||||
result = sbx.commands.run("echo 'Hello from Firecracker VM!'")
|
||||
print(result.stdout)
|
||||
|
||||
# Write and execute a file
|
||||
sbx.files.write("/home/user/hello.py", "print('Hello world')")
|
||||
result = sbx.commands.run("python3 /home/user/hello.py")
|
||||
print(result.stdout)
|
||||
|
||||
# List files
|
||||
files = sbx.files.list("/home/user")
|
||||
for f in files:
|
||||
print(f.name)
|
||||
|
||||
sbx.kill()
|
||||
```
|
||||
|
||||
### Envd Connect RPC API
|
||||
|
||||
The envd daemon exposes Connect RPC services for programmatic access:
|
||||
|
||||
**Process Service:**
|
||||
- `Start(ProcessConfig)` — start a new process
|
||||
- `List()` — list running processes
|
||||
- `Connect(ProcessSelector)` — connect to process stdio
|
||||
- `Signal(ProcessSelector, Signal)` — send signal to process
|
||||
|
||||
**Filesystem Service:**
|
||||
- `ListDir(Path)` — list directory contents
|
||||
- `Stat(Path)` — get file metadata
|
||||
- `WatchDir(Path)` — watch for changes
|
||||
- `Move(Source, Dest)` — move/rename file
|
||||
- `RemoveDir(Path)` — remove directory
|
||||
|
||||
---
|
||||
|
||||
## 4. Lifecycle Management
|
||||
|
||||
### Extend timeout
|
||||
|
||||
```bash
|
||||
# Add 60 seconds to the TTL
|
||||
curl -X POST $E2B_API_URL/sandboxes/{sandboxID}/refreshes \
|
||||
-H "X-API-Key: $E2B_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"duration": 60}'
|
||||
|
||||
# Or set an absolute timeout (seconds from now)
|
||||
curl -X POST $E2B_API_URL/sandboxes/{sandboxID}/timeout \
|
||||
-H "X-API-Key: $E2B_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"timeout": 120}'
|
||||
```
|
||||
|
||||
### Pause (snapshot to disk)
|
||||
|
||||
```bash
|
||||
curl -X POST $E2B_API_URL/sandboxes/{sandboxID}/pause \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
```
|
||||
|
||||
### Resume / reconnect
|
||||
|
||||
```bash
|
||||
curl -X POST $E2B_API_URL/sandboxes/{sandboxID}/connect \
|
||||
-H "X-API-Key: $E2B_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"timeout": 300}'
|
||||
```
|
||||
|
||||
Returns `200` if already running, `201` if resumed from paused state.
|
||||
|
||||
### Kill
|
||||
|
||||
```bash
|
||||
curl -X DELETE $E2B_API_URL/sandboxes/{sandboxID} \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
```
|
||||
|
||||
### Create a snapshot (template from running sandbox)
|
||||
|
||||
```bash
|
||||
curl -X POST $E2B_API_URL/sandboxes/{sandboxID}/snapshots \
|
||||
-H "X-API-Key: $E2B_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name": "my-snapshot"}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Network Configuration
|
||||
|
||||
Update network rules on a running sandbox:
|
||||
|
||||
```bash
|
||||
curl -X PUT $E2B_API_URL/sandboxes/{sandboxID}/network \
|
||||
-H "X-API-Key: $E2B_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"allowOut": ["8.8.8.8", "example.com"],
|
||||
"denyOut": ["0.0.0.0/0"]
|
||||
}'
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- If `allowOut` contains domain names, `denyOut` must include `0.0.0.0/0`
|
||||
- Domain names are not supported in `denyOut` (IPs/CIDRs only)
|
||||
- `allowOut` entries take precedence over `denyOut`
|
||||
- Omitting both fields clears all rules
|
||||
46
experiments/e2b/using-e2b-infra.md
Normal file
46
experiments/e2b/using-e2b-infra.md
Normal file
@@ -0,0 +1,46 @@
|
||||
## VMs
|
||||
|
||||
```bash
|
||||
|
||||
E2B_API_URL=http://192.168.0.61:3000
|
||||
|
||||
# create vm
|
||||
curl -X POST $E2B_API_URL/sandboxes \
|
||||
-H "X-API-Key: $E2B_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"templateID": "base",
|
||||
"timeout": 300
|
||||
}'
|
||||
|
||||
# response
|
||||
{"alias":"base","clientID":"6532622b","domain":null,"envdVersion":"0.5.8","sandboxID":"in3h60s6h0ie3kigrcls4","templateID":"pz1l1owhmy0w84e12eqv","trafficAccessToken":null}
|
||||
|
||||
sandboxID=in3h60s6h0ie3kigrcls4
|
||||
|
||||
# create sandboxVM and capture id
|
||||
sandboxID=$(curl -s -X POST http://localhost:3000/sandboxes -H "X-API-Key: $E2B_API_KEY" -H "Content-Type: application/json" -d '{
|
||||
"templateID": "base",
|
||||
"timeout": 300
|
||||
}' | jq -r .sandboxID
|
||||
)
|
||||
|
||||
|
||||
# get state
|
||||
curl http://localhost:3000/sandboxes/${sandboxID} \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
|
||||
# list running sandboxes
|
||||
curl "http://localhost:3000/v2/sandboxes?state=running" \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
|
||||
# sandbox resource metrics
|
||||
curl "http://localhost:3000/sandboxes/{sandboxID}/metrics?start=$(date -v-5M +%s)&end=$(date +%s)" \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
|
||||
# sandbox logs
|
||||
curl "http://localhost:3000/v2/sandboxes/{sandboxID}/logs?limit=100&direction=backward" \
|
||||
-H "X-API-Key: $E2B_API_KEY"
|
||||
|
||||
|
||||
```
|
||||
@@ -0,0 +1,22 @@
|
||||
# Disable the default all-in-one installation
|
||||
shims:
|
||||
disableAll: true
|
||||
firecracker:
|
||||
enabled: true
|
||||
|
||||
# In this chart version, 'env' must be a map, not a list.
|
||||
# The template converts these keys into Environment Variables for you.
|
||||
env:
|
||||
kataArtifacts: "firecracker"
|
||||
multiInstallSuffix: "" # This fixes the specific error you saw
|
||||
installArtifactsOnly: false
|
||||
|
||||
# Automatically create the RuntimeClass
|
||||
runtimeClass:
|
||||
create: true
|
||||
name: kata-fc
|
||||
handler: kata-fc
|
||||
|
||||
# Set Firecracker as the default for amd64 nodes
|
||||
defaultShim:
|
||||
amd64: firecracker
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: node.k8s.io/v1
|
||||
kind: RuntimeClass
|
||||
metadata:
|
||||
name: kata-fc
|
||||
handler: kata-fc
|
||||
scheduling:
|
||||
nodeSelector:
|
||||
# Ensure these pods only land on your specialized node
|
||||
runtime: kata-fc
|
||||
tolerations:
|
||||
- key: "dedicated"
|
||||
operator: "Equal"
|
||||
value: "kata-fc"
|
||||
effect: "NoSchedule"
|
||||
198
experiments/kata_and_fc_on_kube/readme.md
Normal file
198
experiments/kata_and_fc_on_kube/readme.md
Normal file
@@ -0,0 +1,198 @@
|
||||
## Node: kube-node-34
|
||||
|
||||
```bash
|
||||
apt install cpu-checker
|
||||
|
||||
# check kvm availability
|
||||
kvm-ok
|
||||
cat /sys/module/kvm_amd/parameters/nested
|
||||
lsmod | grep kvm
|
||||
|
||||
# install kata containers
|
||||
# using kata-deploy ?
|
||||
|
||||
export VERSION=$(curl -sSL https://api.github.com/repos/kata-containers/kata-containers/releases/latest | jq .tag_name | tr -d '"')
|
||||
export CHART="oci://ghcr.io/kata-containers/kata-deploy-charts/kata-deploy"
|
||||
|
||||
helm upgrade --install kata-deploy "${CHART}" --version "${VERSION}" --values experiments/kata_and_fc_on_kube/manifests/kata-deploy-values.yaml
|
||||
|
||||
# label only specific nodes to be used with kata-fc
|
||||
kubectl label node kube-node-34 runtime=kata-fc
|
||||
# taint node with NoSchedule
|
||||
kubectl taint nodes kube-node-34 dedicated=kata-fc:NoSchedule
|
||||
|
||||
# configure runtime class
|
||||
k apply -f experiments/kata_and_fc_on_kube/manifests//runtime-class_kata-fc.yaml
|
||||
|
||||
# devmapper configuration for firecracker in containerd
|
||||
ctr plugins ls | grep devmapper
|
||||
|
||||
# create data and metadata files
|
||||
# might want to replace this with LVM !!!!
|
||||
# sudo mkdir -p /var/lib/containerd/devmapper
|
||||
# sudo truncate -s 10G /var/lib/containerd/devmapper/data
|
||||
# sudo truncate -s 1G /var/lib/containerd/devmapper/init_metadata
|
||||
|
||||
# # Associate the files with Loop Devices
|
||||
# sudo losetup /dev/loop10 /var/lib/containerd/devmapper/data
|
||||
# sudo losetup /dev/loop11 /var/lib/containerd/devmapper/init_metadata
|
||||
|
||||
# # Use dmsetup to create the pool:
|
||||
# # This command creates the mapping.
|
||||
# # The numbers '0 20971520' represent the size in 512-byte sectors (for a 10GB file).
|
||||
# sudo dmsetup create containerd-pool --table "0 20971520 thin-pool /dev/loop11 /dev/loop10 128 32768 1"
|
||||
|
||||
lvcreate -L 10G -T kata-vg/kata-pool
|
||||
|
||||
# Add the configuration to /etc/containerd/config.toml:
|
||||
# Find the [plugins."io.containerd.snapshotter.v1.devmapper"] section and update it:
|
||||
|
||||
[plugins."io.containerd.snapshotter.v1.devmapper"]
|
||||
# LVM uses a specific naming convention in /dev/mapper/
|
||||
# It is VolumeGroupName-LogicalVolumeName
|
||||
pool_name = "kata--vg-kata--pool"
|
||||
root_path = "/var/lib/containerd/devmapper"
|
||||
base_image_size = "10GB"
|
||||
discard_blocks = true
|
||||
|
||||
|
||||
# restart containerd
|
||||
systemctl restart containerd
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
### kube node preparation & deployment
|
||||
|
||||
```bash
|
||||
# ---------------------------------------------------------------------------
|
||||
# Packages
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
apt-get update
|
||||
apt-get install -y \
|
||||
qemu-guest-agent \
|
||||
openssh-server \
|
||||
apt-transport-https \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg \
|
||||
nvme-cli
|
||||
|
||||
systemctl enable --now qemu-guest-agent
|
||||
systemctl enable --now ssh
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# nvme-tcp
|
||||
# ---------------------------------------------------------------------------
|
||||
apt-get install -y linux-modules-extra-$(uname -r)
|
||||
modprobe nvme-tcp
|
||||
echo "nvme-tcp" >> /etc/modules-load.d/nvme-tcp.conf
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Kernel modules for Kubernetes
|
||||
# ---------------------------------------------------------------------------
|
||||
cat > /etc/modules-load.d/k8s.conf <<'EOF'
|
||||
overlay
|
||||
br_netfilter
|
||||
EOF
|
||||
|
||||
modprobe overlay
|
||||
modprobe br_netfilter
|
||||
|
||||
cat > /etc/sysctl.d/k8s.conf <<'EOF'
|
||||
net.bridge.bridge-nf-call-iptables = 1
|
||||
net.bridge.bridge-nf-call-ip6tables = 1
|
||||
net.ipv4.ip_forward = 1
|
||||
EOF
|
||||
|
||||
sysctl --system
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# containerd
|
||||
# ---------------------------------------------------------------------------
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
|
||||
> /etc/apt/sources.list.d/docker.list
|
||||
apt-get update && apt-get install -y containerd.io
|
||||
|
||||
cat > /etc/containerd/config.toml <<'EOF'
|
||||
version = 2
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
|
||||
runtime_type = "io.containerd.runc.v2"
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
|
||||
SystemdCgroup = true
|
||||
[plugins."io.containerd.grpc.v1.cri".registry]
|
||||
config_path = "/etc/containerd/certs.d"
|
||||
EOF
|
||||
|
||||
# Registry mirrors pointing to Zot at 192.168.0.30:5000
|
||||
mkdir -p \
|
||||
/etc/containerd/certs.d/docker.io \
|
||||
/etc/containerd/certs.d/registry.k8s.io \
|
||||
/etc/containerd/certs.d/ghcr.io \
|
||||
/etc/containerd/certs.d/quay.io
|
||||
|
||||
cat > /etc/containerd/certs.d/docker.io/hosts.toml <<'EOF'
|
||||
server = "https://registry-1.docker.io"
|
||||
[host."http://192.168.0.30:5000/v2/docker.io"]
|
||||
capabilities = ["pull", "resolve"]
|
||||
skip_verify = true
|
||||
override_path = true
|
||||
EOF
|
||||
|
||||
cat > /etc/containerd/certs.d/registry.k8s.io/hosts.toml <<'EOF'
|
||||
server = "https://registry.k8s.io"
|
||||
[host."http://192.168.0.30:5000/v2/registry.k8s.io"]
|
||||
capabilities = ["pull", "resolve"]
|
||||
skip_verify = true
|
||||
override_path = true
|
||||
EOF
|
||||
|
||||
cat > /etc/containerd/certs.d/ghcr.io/hosts.toml <<'EOF'
|
||||
server = "https://ghcr.io"
|
||||
[host."http://192.168.0.30:5000/v2/ghcr.io"]
|
||||
capabilities = ["pull", "resolve"]
|
||||
skip_verify = true
|
||||
override_path = true
|
||||
EOF
|
||||
|
||||
cat > /etc/containerd/certs.d/quay.io/hosts.toml <<'EOF'
|
||||
server = "https://quay.io"
|
||||
[host."http://192.168.0.30:5000/v2/quay.io"]
|
||||
capabilities = ["pull", "resolve"]
|
||||
skip_verify = true
|
||||
override_path = true
|
||||
EOF
|
||||
|
||||
systemctl restart containerd
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# kubelet systemd drop-in
|
||||
# ---------------------------------------------------------------------------
|
||||
mkdir -p /etc/systemd/system/kubelet.service.d
|
||||
cat > /etc/systemd/system/kubelet.service.d/10-containerd.conf <<'EOF'
|
||||
[Unit]
|
||||
After=containerd.service
|
||||
Requires=containerd.service
|
||||
|
||||
[Service]
|
||||
ExecStartPre=/bin/bash -c 'until [ -S /var/run/containerd/containerd.sock ]; do sleep 1; done'
|
||||
ExecStartPre=/usr/bin/crictl info
|
||||
EOF
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# kubeadm / kubelet / kubectl v1.32
|
||||
# ---------------------------------------------------------------------------
|
||||
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key \
|
||||
| gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
||||
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /" \
|
||||
> /etc/apt/sources.list.d/kubernetes.list
|
||||
apt-get update && apt-get install -y kubelet kubeadm kubectl
|
||||
apt-mark hold kubelet kubeadm kubectl
|
||||
|
||||
|
||||
# join kube cluster
|
||||
JOIN_COMMAND="kubeadm join 192.168.0.31:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>"
|
||||
14
experiments/microsandbox/install.md
Normal file
14
experiments/microsandbox/install.md
Normal file
@@ -0,0 +1,14 @@
|
||||
```bash
|
||||
virt-install \
|
||||
--name microsandbox \
|
||||
--ram 8192\
|
||||
--vcpus 4 \
|
||||
--cpu host-passthrough \
|
||||
--os-variant ubuntu24.04 \
|
||||
--disk path=/srv/vms/microsandbox.qcow2,size=100,format=qcow2,bus=virtio \
|
||||
--network bridge=br0,model=virtio \
|
||||
--graphics none \
|
||||
--console pty,target_type=serial \
|
||||
--location /srv/vms/isos/ubuntu-24.04.3-live-server-amd64.iso,kernel=casper/vmlinuz,initrd=casper/initrd \
|
||||
--extra-args 'console=ttyS0,115200n8'
|
||||
```
|
||||
@@ -0,0 +1,27 @@
|
||||
#cloud-config
|
||||
hostname: ${hostname}
|
||||
manage_etc_hosts: true
|
||||
|
||||
# Kernel modules for container networking
|
||||
write_files:
|
||||
- path: /etc/modules-load.d/k8s.conf
|
||||
content: |
|
||||
overlay
|
||||
br_netfilter
|
||||
- path: /etc/sysctl.d/k8s.conf
|
||||
content: |
|
||||
net.bridge.bridge-nf-call-iptables = 1
|
||||
net.bridge.bridge-nf-call-ip6tables = 1
|
||||
net.ipv4.ip_forward = 1
|
||||
|
||||
packages:
|
||||
- curl
|
||||
- gpg
|
||||
- apt-transport-https
|
||||
|
||||
runcmd:
|
||||
- modprobe overlay
|
||||
- modprobe br_netfilter
|
||||
- sysctl --system
|
||||
- swapoff -a
|
||||
- sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
|
||||
74
experiments/orb-stack/modules/base-template/main.tf
Normal file
74
experiments/orb-stack/modules/base-template/main.tf
Normal file
@@ -0,0 +1,74 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
orbstack = {
|
||||
source = "robertdebock/orbstack"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
cloudinit = {
|
||||
source = "hashicorp/cloudinit"
|
||||
version = "~> 2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "node_count" {
|
||||
description = "Number of nodes to deploy"
|
||||
type = number
|
||||
default = 3
|
||||
}
|
||||
|
||||
variable "name" {
|
||||
description = "Base name for the machines"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "distro" {
|
||||
description = "OS distribution"
|
||||
type = string
|
||||
default = "ubuntu"
|
||||
}
|
||||
|
||||
variable "distro_version" {
|
||||
description = "OS distribution version/codename"
|
||||
type = string
|
||||
default = "noble"
|
||||
}
|
||||
|
||||
variable "extra_cloud_init_parts" {
|
||||
description = "Additional cloud-init parts to layer on top of the base config"
|
||||
type = list(object({ content = string, content_type = string }))
|
||||
default = []
|
||||
}
|
||||
|
||||
data "cloudinit_config" "this" {
|
||||
count = var.node_count
|
||||
|
||||
part {
|
||||
content_type = "text/cloud-config"
|
||||
content = templatefile("${path.module}/cloud-init-base.yaml", {
|
||||
hostname = "${var.name}-${count.index + 1}"
|
||||
})
|
||||
}
|
||||
|
||||
dynamic "part" {
|
||||
for_each = var.extra_cloud_init_parts
|
||||
content {
|
||||
content_type = part.value.content_type
|
||||
content = part.value.content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "orbstack_machine" "this" {
|
||||
count = var.node_count
|
||||
|
||||
name = "${var.name}-${count.index + 1}"
|
||||
distro = var.distro
|
||||
region = var.distro_version
|
||||
|
||||
user_data = data.cloudinit_config.this[count.index].rendered
|
||||
}
|
||||
|
||||
output "machines" {
|
||||
value = { for m in orbstack_machine.this : m.name => m.ip_address }
|
||||
}
|
||||
11
experiments/orb-stack/stacks/k3s/cloud-init-cp.yaml
Normal file
11
experiments/orb-stack/stacks/k3s/cloud-init-cp.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
#cloud-config
|
||||
merge_how:
|
||||
- name: list
|
||||
settings: [append]
|
||||
- name: dict
|
||||
settings: [recurse_array]
|
||||
|
||||
runcmd:
|
||||
- curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server" K3S_TOKEN="${k3s_token}" sh -
|
||||
- until kubectl get nodes; do sleep 2; done
|
||||
- cp /etc/rancher/k3s/k3s.yaml /root/kubeconfig.yaml
|
||||
9
experiments/orb-stack/stacks/k3s/cloud-init-worker.yaml
Normal file
9
experiments/orb-stack/stacks/k3s/cloud-init-worker.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
#cloud-config
|
||||
merge_how:
|
||||
- name: list
|
||||
settings: [append]
|
||||
- name: dict
|
||||
settings: [recurse_array]
|
||||
|
||||
runcmd:
|
||||
- curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="agent" K3S_URL="https://${cp_ip}:6443" K3S_TOKEN="${join_token}" sh -
|
||||
39
experiments/orb-stack/stacks/k3s/main.tf
Normal file
39
experiments/orb-stack/stacks/k3s/main.tf
Normal file
@@ -0,0 +1,39 @@
|
||||
variable "k3s_token" {
|
||||
description = "Shared secret for k3s cluster join (set via TF_VAR or tfvars)"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
module "control_plane" {
|
||||
source = "../../modules/base-template"
|
||||
name = "k3s-cp"
|
||||
node_count = 1
|
||||
|
||||
extra_cloud_init_parts = [{
|
||||
content_type = "text/cloud-config"
|
||||
content = templatefile("${path.module}/cloud-init-cp.yaml", {
|
||||
k3s_token = var.k3s_token
|
||||
})
|
||||
}]
|
||||
}
|
||||
|
||||
module "workers" {
|
||||
source = "../../modules/base-template"
|
||||
name = "k3s-worker"
|
||||
node_count = 2
|
||||
|
||||
extra_cloud_init_parts = [{
|
||||
content_type = "text/cloud-config"
|
||||
content = templatefile("${path.module}/cloud-init-worker.yaml", {
|
||||
cp_ip = values(module.control_plane.machines)[0]
|
||||
join_token = var.k3s_token
|
||||
})
|
||||
}]
|
||||
}
|
||||
|
||||
output "cluster" {
|
||||
value = {
|
||||
control_plane = module.control_plane.machines
|
||||
workers = module.workers.machines
|
||||
}
|
||||
}
|
||||
219
experiments/rke2/rke2-basics.md
Normal file
219
experiments/rke2/rke2-basics.md
Normal file
@@ -0,0 +1,219 @@
|
||||
## install
|
||||
|
||||
```bash
|
||||
# master node
|
||||
curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION=v1.32.12+rke2r1 sh -
|
||||
systemctl enable rke2-server.service
|
||||
systemctl start rke2-server.service
|
||||
journalctl -u rke2-server -f
|
||||
|
||||
# open firewalld
|
||||
sudo firewall-cmd --permanent --add-port=9345/tcp
|
||||
sudo firewall-cmd --permanent --add-port=6443/tcp
|
||||
sudo firewall-cmd --permanent --add-port=10250/tcp # Kubelet
|
||||
sudo firewall-cmd --reload
|
||||
|
||||
# install nerdctl
|
||||
# Set the version
|
||||
VERSION="2.2.1" # Check GitHub for the latest version
|
||||
|
||||
# Download the tarball
|
||||
wget https://github.com/containerd/nerdctl/releases/download/v${VERSION}/nerdctl-${VERSION}-linux-arm64.tar.gz
|
||||
|
||||
# Extract to your path
|
||||
sudo tar -C /usr/local/bin -xzvf nerdctl-${VERSION}-linux-arm64.tar.gz nerdctl
|
||||
|
||||
# configure nerdctl
|
||||
sudo mkdir -p /etc/nerdctl
|
||||
sudo tee /etc/nerdctl/nerdctl.toml <<EOF
|
||||
address = "unix:///run/k3s/containerd/containerd.sock"
|
||||
namespace = "k8s.io"
|
||||
EOF
|
||||
|
||||
# install buildkit
|
||||
# Set current stable version
|
||||
BK_VER="0.28.0"
|
||||
|
||||
# Download arm64 binary
|
||||
wget https://github.com/moby/buildkit/releases/download/v${BK_VER}/buildkit-v${BK_VER}.linux-arm64.tar.gz
|
||||
|
||||
# Extract only the binaries to /usr/local/bin
|
||||
sudo tar -C /usr/local/bin -xzvf buildkit-v${BK_VER}.linux-arm64.tar.gz --strip-components=1 bin/
|
||||
|
||||
# Create the service file
|
||||
sudo tee /etc/systemd/system/buildkit.service <<EOF
|
||||
[Unit]
|
||||
Description=BuildKit
|
||||
Documentation=https://github.com/moby/buildkit
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/buildkitd --addr unix:///run/buildkit/buildkitd.sock
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Reload and Start
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now buildkit
|
||||
|
||||
# ---------------------------------------------
|
||||
|
||||
|
||||
# agent/worker node
|
||||
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="agent" INSTALL_RKE2_VERSION=v1.32.12+rke2r1 sh -
|
||||
systemctl enable rke2-agent.service
|
||||
mkdir -p /etc/rancher/rke2/
|
||||
# token from master node
|
||||
# cat /var/lib/rancher/rke2/server/node-token
|
||||
cat <<EOF | sudo tee /etc/rancher/rke2/config.yaml
|
||||
server: https://192.168.64.3:9345
|
||||
token: K107618960f87b9efb3a3255ce00a9743d29f1db9376820c9144cb85fa3c554dc69::server:06b2effdf0c9ce3952efc8a5d80bf084
|
||||
EOF
|
||||
systemctl start rke2-agent.service
|
||||
journalctl -u rke2-agent -f
|
||||
|
||||
|
||||
# Set up kubectl on the server node
|
||||
echo 'export KUBECONFIG=/etc/rancher/rke2/rke2.yaml' >> ~/.bashrc
|
||||
echo 'export PATH=$PATH:/var/lib/rancher/rke2/bin' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
|
||||
|
||||
## build and deploy application
|
||||
|
||||
```bash
|
||||
# build container with nerdctl
|
||||
nerdctl --namespace k8s.io build --tag hello-world:latest .
|
||||
|
||||
# export image as tar on master node
|
||||
nerdctl save hello-world:latest -o hello-world.tar
|
||||
# copy it over to worker node
|
||||
scp hello-world.tar novakj@192.168.64.4:~/
|
||||
# import image on the agent node
|
||||
sudo /var/lib/rancher/rke2/bin/ctr --address /run/k3s/containerd/containerd.sock -n k8s.io images import hello-world.tar
|
||||
|
||||
kubectl create namespace rke2-apps
|
||||
|
||||
cat <<EOF > deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: hello-world-deployment
|
||||
namespace: rke2-apps
|
||||
labels:
|
||||
type: staticwebapp
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
type: staticwebapp
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
type: staticwebapp
|
||||
spec:
|
||||
containers:
|
||||
- name: staticwebapp
|
||||
image: hello-world:latest
|
||||
imagePullPolicy: Never
|
||||
ports:
|
||||
- containerPort: 80
|
||||
resources:
|
||||
requests:
|
||||
memory: "32Mi"
|
||||
cpu: "200m"
|
||||
limits:
|
||||
memory: "64Mi"
|
||||
cpu: "300m"
|
||||
EOF
|
||||
|
||||
kubectl create -f deployment.yaml
|
||||
|
||||
# expose deployment
|
||||
kubectl expose deployment hello-world-deployment --name hello-world-service --port=8080 --target-port=80 -n rke2-apps
|
||||
|
||||
# install ingress-nginx (even though i thought that there is ingress controller already deployed)
|
||||
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml
|
||||
|
||||
# create ingress with "localhost" as host
|
||||
kubectl create ingress hello-world-ingress --class=nginx --rule="test-host/*=hello-world-service:8080" -n rke2-apps
|
||||
kubectl port-forward -n ingress-nginx service/ingress-nginx-controller 8081:80
|
||||
|
||||
|
||||
|
||||
# incomplete completion configuration ;-)
|
||||
dnf install bash-completion -y
|
||||
alias 'k=kubectl'
|
||||
|
||||
# ~/.bashrc
|
||||
|
||||
# 1. Load the main bash-completion package first
|
||||
# On Rocky/RHEL, it's usually at this path:
|
||||
[[ -r "/usr/share/bash-completion/bash_completion" ]] && . "/usr/share/bash-completion/bash_completion"
|
||||
|
||||
# Enable kubectl bash completion
|
||||
source <(kubectl completion bash)
|
||||
|
||||
# Set up the alias
|
||||
alias k=kubectl
|
||||
|
||||
# Link the kubectl completion logic to the 'k' alias
|
||||
complete -o default -F __start_kubectl k
|
||||
```
|
||||
|
||||
|
||||
|
||||
## upgrading RKE2
|
||||
|
||||
```bash
|
||||
# install upgrade controller
|
||||
kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/download/v0.9.1/system-upgrade-controller.yaml
|
||||
|
||||
# server upgrade
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: upgrade.cattle.io/v1
|
||||
kind: Plan
|
||||
metadata:
|
||||
name: rke2-server-upgrade
|
||||
namespace: system-upgrade
|
||||
spec:
|
||||
concurrency: 1
|
||||
cordon: true
|
||||
nodeSelector:
|
||||
matchExpressions:
|
||||
- key: node-role.kubernetes.io/control-plane
|
||||
operator: In
|
||||
values: ["true"]
|
||||
serviceAccountName: system-upgrade
|
||||
upgrade:
|
||||
image: rancher/rke2-upgrade
|
||||
version: v1.33.9+rke2r1
|
||||
EOF
|
||||
|
||||
# agent upgrade
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: upgrade.cattle.io/v1
|
||||
kind: Plan
|
||||
metadata:
|
||||
name: rke2-agent-upgrade
|
||||
namespace: system-upgrade
|
||||
spec:
|
||||
concurrency: 1
|
||||
cordon: true
|
||||
nodeSelector:
|
||||
matchExpressions:
|
||||
- key: node-role.kubernetes.io/control-plane
|
||||
operator: DoesNotExist
|
||||
prepare:
|
||||
# Logic: "Don't start workers until servers are done"
|
||||
args: ["wait-for-plan", "rke2-server-upgrade"]
|
||||
image: rancher/rke2-upgrade
|
||||
serviceAccountName: system-upgrade
|
||||
upgrade:
|
||||
image: rancher/rke2-upgrade
|
||||
version: v1.33.9+rke2r1
|
||||
EOF
|
||||
```
|
||||
215
experiments/rke2/step-by-step.md
Normal file
215
experiments/rke2/step-by-step.md
Normal file
@@ -0,0 +1,215 @@
|
||||
## VMS creation
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
# hypervisor: beelink (192.168.0.6)
|
||||
|
||||
vms_path=/srv/vms/images
|
||||
isos_path=/srv/vms/isos
|
||||
cd $isos_path
|
||||
# Grab Ubuntu 24.04 cloud image
|
||||
wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
|
||||
|
||||
# Create a base disk from the cloud image (repeat per node)
|
||||
for NODE in rke2-server rke2-agent1 rke2-agent2; do
|
||||
DISK_SIZE="30G"
|
||||
[[ "$NODE" == rke2-agent* ]] && DISK_SIZE="50G"
|
||||
|
||||
qemu-img create -f qcow2 -F qcow2 -b $isos_path/noble-server-cloudimg-amd64.img $vms_path/${NODE}.qcow2
|
||||
qemu-img resize $vms_path/${NODE}.qcow2 ${DISK_SIZE}
|
||||
done
|
||||
```
|
||||
|
||||
|
||||
```bash
|
||||
# prepare cloud-init/user-data
|
||||
apt install cloud-image-utils
|
||||
|
||||
# prepare cloud-init and launch VMs
|
||||
declare -A nodes=(
|
||||
[rke2-server]="192.168.0.51"
|
||||
[rke2-agent1]="192.168.0.52"
|
||||
[rke2-agent2]="192.168.0.53"
|
||||
)
|
||||
|
||||
for node in "${!nodes[@]}"; do
|
||||
ip="${nodes[$node]}"
|
||||
|
||||
# user-data
|
||||
cat <<EOF > user-data-${node}
|
||||
#cloud-config
|
||||
hostname: ${node}
|
||||
manage_etc_hosts: false
|
||||
users:
|
||||
- name: sre
|
||||
sudo: ALL=(ALL) NOPASSWD:ALL
|
||||
shell: /bin/bash
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINQxxkqmvtVI+8c5BkTaJ5c2HfBFRXJWMmEcevvfP9tV jan.novak@Jans-MacBook-Air.local
|
||||
write_files:
|
||||
- path: /etc/hosts
|
||||
append: true
|
||||
content: |
|
||||
192.168.0.51 rke2-server
|
||||
192.168.0.52 rke2-agent1
|
||||
192.168.0.53 rke2-agent2
|
||||
- path: /etc/modules-load.d/rke2.conf
|
||||
content: |
|
||||
br_netfilter
|
||||
overlay
|
||||
- path: /etc/sysctl.d/99-rke2.conf
|
||||
content: |
|
||||
net.bridge.bridge-nf-call-iptables = 1
|
||||
net.bridge.bridge-nf-call-ip6tables = 1
|
||||
net.ipv4.ip_forward = 1
|
||||
swap:
|
||||
filename: /swap.img
|
||||
size: 0
|
||||
maxsize: 0
|
||||
runcmd:
|
||||
- swapoff -a
|
||||
- sed -i '/swap/d' /etc/fstab
|
||||
- modprobe br_netfilter
|
||||
- modprobe overlay
|
||||
- sysctl --system
|
||||
package_update: true
|
||||
packages:
|
||||
- qemu-guest-agent
|
||||
- nfs-common
|
||||
- open-iscsi
|
||||
power_state:
|
||||
mode: reboot
|
||||
EOF
|
||||
|
||||
# network config
|
||||
cat <<EOF > network-config-${node}
|
||||
network:
|
||||
version: 2
|
||||
ethernets:
|
||||
eth0:
|
||||
match:
|
||||
driver: "virtio_net"
|
||||
addresses:
|
||||
- "${ip}/24"
|
||||
nameservers:
|
||||
addresses:
|
||||
- 8.8.8.8
|
||||
routes:
|
||||
- to: "default"
|
||||
via: "192.168.0.4"
|
||||
EOF
|
||||
|
||||
cloud-localds --network-config=./network-config-${node} \
|
||||
$vms_path/${node}-seed.iso ./user-data-${node}
|
||||
done
|
||||
|
||||
# Launch VMs
|
||||
for node in "${!nodes[@]}"; do
|
||||
virt-install \
|
||||
--name ${node} \
|
||||
--ram 4096 --vcpus 2 \
|
||||
--os-variant ubuntu24.04 \
|
||||
--disk $vms_path/${node}.qcow2,bus=virtio \
|
||||
--disk $vms_path/${node}-seed.iso,device=cdrom \
|
||||
--network bridge=br0,model=virtio \
|
||||
--graphics none \
|
||||
--console pty,target_type=serial \
|
||||
--noautoconsole \
|
||||
--import
|
||||
done
|
||||
|
||||
```
|
||||
|
||||
|
||||
## RKE2 installation
|
||||
|
||||
```bash
|
||||
# there are no .deb packages - only rpm or tarball
|
||||
# "magic" install script can handle that
|
||||
curl -sfL https://get.rke2.io | INSTALL_RKE2_CHANNEL=v1.32 sudo sh -
|
||||
|
||||
# Create config directory
|
||||
sudo mkdir -p /etc/rancher/rke2
|
||||
|
||||
# Server configuration
|
||||
cat <<EOF | sudo tee /etc/rancher/rke2/config.yaml
|
||||
# Bind the API to the node's IP (not 127.0.0.1)
|
||||
tls-san:
|
||||
- rke2-server
|
||||
- 192.168.0.51
|
||||
# Write kubeconfig readable by non-root
|
||||
write-kubeconfig-mode: "0644"
|
||||
# CNI - canal is default and fine for home lab
|
||||
# Alternatives: cilium, calico, multus
|
||||
cni:
|
||||
- canal
|
||||
# Disable servicelb if you plan to use metallb
|
||||
disable:
|
||||
- rke2-service-lb
|
||||
EOF
|
||||
|
||||
# Enable and start
|
||||
sudo systemctl enable rke2-server.service
|
||||
sudo systemctl start rke2-server.service
|
||||
|
||||
# Watch bootstrap (takes 2-3 min on first run)
|
||||
sudo journalctl -u rke2-server -f
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Grab the join token and kubeconfig
|
||||
|
||||
```bash
|
||||
|
||||
# Token for agents to join
|
||||
sudo cat /var/lib/rancher/rke2/server/node-token
|
||||
# Save this somewhere - you'll need it on every agent
|
||||
|
||||
# Set up kubectl on the server node
|
||||
echo 'export KUBECONFIG=/etc/rancher/rke2/rke2.yaml' >> ~/.bashrc
|
||||
echo 'export PATH=$PATH:/var/lib/rancher/rke2/bin' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
|
||||
# Verify
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
|
||||
## Install RKE2 Agents (Workers)
|
||||
|
||||
```bash
|
||||
# Install RKE2 agent - same channel as server
|
||||
curl -sfL https://get.rke2.io | INSTALL_RKE2_CHANNEL=v1.32 INSTALL_RKE2_TYPE=agent sudo sh -
|
||||
|
||||
# Create config
|
||||
sudo mkdir -p /etc/rancher/rke2
|
||||
|
||||
cat <<EOF | sudo tee /etc/rancher/rke2/config.yaml
|
||||
server: https://192.168.0.51:9345
|
||||
token: K10dba0bfff01d610ffed41c6b82a1b8861ee19e5af34a3bdd21970936823a846da::server:1f02fb36a288dcd06770cab28b015bd7
|
||||
EOF
|
||||
|
||||
# Enable and start
|
||||
sudo systemctl enable rke2-agent.service
|
||||
sudo systemctl start rke2-agent.service
|
||||
|
||||
# Watch join
|
||||
sudo journalctl -u rke2-agent -f
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Copy Kubeconfig to Your Workstation
|
||||
|
||||
```bash
|
||||
# On your workstation (not the VMs)
|
||||
scp sre@192.168.0.51:/etc/rancher/rke2/rke2.yaml ~/.kube/rke2-homelab.yaml
|
||||
|
||||
# Fix the server address (it'll say 127.0.0.1)
|
||||
gsed -i 's/127.0.0.1/192.168.0.51/' ~/.kube/rke2-homelab.yaml
|
||||
|
||||
export KUBECONFIG=~/.kube/rke2-homelab.yaml
|
||||
kubectl get nodes
|
||||
```
|
||||
10316
gitops/home-kubernetes/00-crds/gateway-api-crds.yaml
Normal file
10316
gitops/home-kubernetes/00-crds/gateway-api-crds.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: gitea-ci-deploy
|
||||
subjects:
|
||||
- kind: User
|
||||
name: "gitea_ci@idm.home.hrajfrisbee.cz" # matches preferred_username claim
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
roleRef:
|
||||
# kind: ClusterRole
|
||||
# name: edit # scope down as needed
|
||||
# apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
# this is obviously too much permissions
|
||||
# but we can live with it for homelab
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: oidc-cluster-admin
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
subjects:
|
||||
- apiGroup: rbac.authorization.k8s.io
|
||||
kind: User
|
||||
name: https://idm.home.hrajfrisbee.cz/oauth2/openid/k8s#35842461-a1c4-4ad6-8b29-697c5ddbfe84
|
||||
- apiGroup: rbac.authorization.k8s.io
|
||||
kind: User
|
||||
name: novakj@idm.home.hrajfrisbee.cz
|
||||
@@ -0,0 +1,22 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: letsencrypt-prod-dns
|
||||
spec:
|
||||
acme:
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
email: kacerr.cz@gmail.com
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-dns-account-key
|
||||
solvers:
|
||||
- dns01:
|
||||
rfc2136:
|
||||
nameserver: dns-update-proxy.cert-manager.svc.cluster.local:53
|
||||
tsigKeyName: acme-update-key
|
||||
tsigAlgorithm: HMACSHA512
|
||||
tsigSecretSecretRef:
|
||||
name: acme-update-key
|
||||
key: acme-update-key
|
||||
selector:
|
||||
dnsZones:
|
||||
- "lab.home.hrajfrisbee.cz"
|
||||
@@ -0,0 +1,33 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: dns-update-proxy
|
||||
namespace: cert-manager
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: dns-update-proxy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: dns-update-proxy
|
||||
spec:
|
||||
containers:
|
||||
- name: socat-tcp
|
||||
image: alpine/socat
|
||||
args:
|
||||
- TCP-LISTEN:53,fork,reuseaddr
|
||||
- TCP:87.236.195.209:5353
|
||||
ports:
|
||||
- containerPort: 53
|
||||
protocol: TCP
|
||||
- name: socat-udp
|
||||
image: alpine/socat
|
||||
args:
|
||||
- -T5
|
||||
- UDP-RECVFROM:53,fork,reuseaddr
|
||||
- UDP:87.236.195.209:5353
|
||||
ports:
|
||||
- containerPort: 53
|
||||
protocol: UDP
|
||||
@@ -0,0 +1,18 @@
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: acme-update-key
|
||||
namespace: cert-manager
|
||||
spec:
|
||||
refreshInterval: 1h
|
||||
secretStoreRef:
|
||||
name: vault-backend # or your store
|
||||
kind: ClusterSecretStore
|
||||
target:
|
||||
name: acme-update-key
|
||||
creationPolicy: Owner
|
||||
data:
|
||||
- secretKey: acme-update-key
|
||||
remoteRef:
|
||||
key: k8s_home/cert-manager
|
||||
property: acme-update-key
|
||||
@@ -19,8 +19,14 @@ spec:
|
||||
upgrade:
|
||||
crds: CreateReplace
|
||||
values:
|
||||
global:
|
||||
logLevel: 6
|
||||
crds:
|
||||
enabled: false
|
||||
config:
|
||||
apiVersion: controller.config.cert-manager.io/v1alpha1
|
||||
kind: ControllerConfiguration
|
||||
enableGatewayAPI: true
|
||||
prometheus:
|
||||
enabled: true
|
||||
extraObjects:
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: dns-update-proxy
|
||||
namespace: cert-manager
|
||||
spec:
|
||||
selector:
|
||||
app: dns-update-proxy
|
||||
ports:
|
||||
- name: dns-tcp
|
||||
port: 53
|
||||
targetPort: 53
|
||||
protocol: TCP
|
||||
- name: dns-udp
|
||||
port: 53
|
||||
targetPort: 53
|
||||
protocol: UDP
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: wildcard-lab-home-hrajfrisbee
|
||||
namespace: kube-system
|
||||
spec:
|
||||
secretName: wildcard-lab-home-hrajfrisbee-tls
|
||||
issuerRef:
|
||||
name: letsencrypt-prod-dns
|
||||
kind: ClusterIssuer
|
||||
dnsNames:
|
||||
- "*.lab.home.hrajfrisbee.cz"
|
||||
27
gitops/home-kubernetes/cilium/gateway.yaml
Normal file
27
gitops/home-kubernetes/cilium/gateway.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: cilium-gateway
|
||||
namespace: kube-system
|
||||
spec:
|
||||
gatewayClassName: cilium
|
||||
listeners:
|
||||
- name: http
|
||||
port: 80
|
||||
protocol: HTTP
|
||||
allowedRoutes:
|
||||
namespaces:
|
||||
from: All
|
||||
- name: lab-home-hrajfrisbee-https-wildcard
|
||||
hostname: "*.lab.home.hrajfrisbee.cz"
|
||||
port: 443
|
||||
protocol: HTTPS
|
||||
tls:
|
||||
mode: Terminate
|
||||
certificateRefs:
|
||||
- kind: Secret
|
||||
name: wildcard-lab-home-hrajfrisbee-tls
|
||||
allowedRoutes:
|
||||
namespaces:
|
||||
from: All
|
||||
@@ -13,16 +13,19 @@ spec:
|
||||
kind: HelmRepository
|
||||
name: cilium
|
||||
namespace: flux-system
|
||||
version: 1.18.5
|
||||
version: 1.19.1
|
||||
interval: 5m0s
|
||||
values:
|
||||
cluster:
|
||||
name: "home-kube"
|
||||
devices: "eth+ bond+ en+"
|
||||
hubble:
|
||||
relay:
|
||||
enabled: true
|
||||
ui:
|
||||
enabled: true
|
||||
ingressController:
|
||||
enabled: true
|
||||
ipam:
|
||||
mode: cluster-pool
|
||||
operator:
|
||||
@@ -30,6 +33,15 @@ spec:
|
||||
clusterPoolIPv4PodCIDRList: "10.96.0.0/16"
|
||||
l2announcements:
|
||||
enabled: true
|
||||
gatewayAPI:
|
||||
enabled: true
|
||||
gatewayClass:
|
||||
create: "true"
|
||||
kubeProxyReplacement: true
|
||||
k8sServiceHost: 192.168.0.31 # or LB IP
|
||||
k8sServicePort: 6443
|
||||
|
||||
# disable envoy daemonset - i guess that is stupid idea anyway
|
||||
# envoy:
|
||||
# enabled: false
|
||||
# l7Proxy: false
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: operator-test-lab-home-hrajfrisbee-2
|
||||
namespace: default
|
||||
annotations:
|
||||
gateway-cert-operator.io/gateway-name: "cilium-gateway"
|
||||
gateway-cert-operator.io/gateway-namespace: "kube-system"
|
||||
|
||||
spec:
|
||||
secretName: operator-test-lab-home-hrajfrisbee-2
|
||||
issuerRef:
|
||||
group: cert-manager.io
|
||||
kind: ClusterIssuer
|
||||
name: letsencrypt-prod
|
||||
dnsNames:
|
||||
- "operator-test-2.lab.home.hrajfrisbee.cz"
|
||||
@@ -0,0 +1,17 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: operator-test-lab-home-hrajfrisbee
|
||||
namespace: default
|
||||
annotations:
|
||||
gateway-cert-operator.io/gateway-name: "cilium-gateway"
|
||||
gateway-cert-operator.io/gateway-namespace: "kube-system"
|
||||
|
||||
spec:
|
||||
secretName: operator-test-lab-home-hrajfrisbee
|
||||
issuerRef:
|
||||
group: cert-manager.io
|
||||
kind: ClusterIssuer
|
||||
name: letsencrypt-prod
|
||||
dnsNames:
|
||||
- "operator-test.lab.home.hrajfrisbee.cz"
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: operator-test
|
||||
namespace: default
|
||||
labels:
|
||||
app: operator-test
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: operator-test
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: operator-test
|
||||
spec:
|
||||
containers:
|
||||
- name: whoami
|
||||
image: traefik/whoami
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 16Mi
|
||||
limits:
|
||||
memory: 32Mi
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: operator-test-redirect
|
||||
namespace: default
|
||||
labels:
|
||||
app: operator-test
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: cilium-gateway
|
||||
namespace: kube-system
|
||||
sectionName: http
|
||||
hostnames:
|
||||
- operator-test.lab.home.hrajfrisbee.cz
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
filters:
|
||||
- type: RequestRedirect
|
||||
requestRedirect:
|
||||
scheme: https
|
||||
statusCode: 301
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: operator-test
|
||||
namespace: default
|
||||
labels:
|
||||
app: operator-test
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: cilium-gateway
|
||||
namespace: kube-system
|
||||
sectionName: auto-operator-test-lab-home-hrajfrisbee-operator-test-lab-home-hrajfrisbee-cz
|
||||
hostnames:
|
||||
- operator-test.lab.home.hrajfrisbee.cz
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: operator-test
|
||||
namespace: default
|
||||
port: 80
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: gateway.networking.k8s.io/v1beta1
|
||||
kind: ReferenceGrant
|
||||
metadata:
|
||||
name: allow-kube-system-gateway
|
||||
namespace: default
|
||||
spec:
|
||||
from:
|
||||
- group: gateway.networking.k8s.io
|
||||
kind: Gateway
|
||||
namespace: kube-system
|
||||
to:
|
||||
- group: ""
|
||||
kind: Secret
|
||||
name: operator-test-lab-home-hrajfrisbee
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: operator-test
|
||||
namespace: default
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: operator-test
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: http
|
||||
@@ -6,13 +6,13 @@ metadata:
|
||||
spec:
|
||||
provider:
|
||||
vault:
|
||||
server: "https://vault.hrajfrisbee.cz:8200"
|
||||
server: "https://vault.hrajfrisbee.cz"
|
||||
path: "secret"
|
||||
version: "v2"
|
||||
auth:
|
||||
appRole:
|
||||
path: "approle"
|
||||
roleId: "8833d0f8-d35d-d7ea-658b-c27837d121ab" # or reference a secret
|
||||
roleId: "864e352d-2064-2bf9-2c73-dbd676a95368" # or reference a secret
|
||||
secretRef:
|
||||
name: vault-approle
|
||||
key: secret-id
|
||||
|
||||
@@ -6,5 +6,5 @@ metadata:
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/reconcile: disabled
|
||||
type: Opaque
|
||||
data:
|
||||
secret-id: # --- find me in keepass bro ---
|
||||
stringData:
|
||||
secret-id: --- fill in the secret_id ---
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: SecretStore
|
||||
metadata:
|
||||
name: vault-backend
|
||||
namespace: external-secrets
|
||||
spec:
|
||||
provider:
|
||||
vault:
|
||||
server: "https://vault.hrajfrisbee.cz:8200"
|
||||
path: "secret"
|
||||
version: "v2"
|
||||
auth:
|
||||
appRole:
|
||||
path: "approle"
|
||||
roleId: "864e352d-2064-2bf9-2c73-dbd676a95368" # or reference a secret
|
||||
secretRef:
|
||||
name: vault-approle
|
||||
key: secret-id
|
||||
@@ -14,6 +14,19 @@ spec:
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: 00-rbac
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m0s
|
||||
path: ./gitops/home-kubernetes/00-rbac
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: cilium
|
||||
namespace: flux-system
|
||||
@@ -117,6 +130,19 @@ spec:
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: experiments
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m0s
|
||||
path: ./gitops/home-kubernetes/experiments
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
# ---
|
||||
# apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
# kind: Kustomization
|
||||
|
||||
16
gitops/home-kubernetes/flux-system/helmrelease_flux-web.yaml
Normal file
16
gitops/home-kubernetes/flux-system/helmrelease_flux-web.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: flux-web
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 30m
|
||||
releaseName: flux-web
|
||||
chartRef:
|
||||
kind: OCIRepository
|
||||
name: flux-operator
|
||||
values:
|
||||
fullnameOverride: flux-web
|
||||
installCRDs: true
|
||||
web:
|
||||
serverOnly: true
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: OCIRepository
|
||||
metadata:
|
||||
name: flux-operator
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 30m
|
||||
url: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator
|
||||
layerSelector:
|
||||
mediaType: "application/vnd.cncf.helm.chart.content.v1.tar+gzip"
|
||||
operation: copy
|
||||
ref:
|
||||
semver: "0.x"
|
||||
63
gitops/home-kubernetes/fuj/deployment_fuj-management.yaml
Normal file
63
gitops/home-kubernetes/fuj/deployment_fuj-management.yaml
Normal file
@@ -0,0 +1,63 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: fuj-management
|
||||
namespace: fuj
|
||||
labels:
|
||||
app: fuj-management
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: fuj-management
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: fuj-management
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: gitea-registry
|
||||
containers:
|
||||
- name: fuj-management
|
||||
image: gitea.home.hrajfrisbee.cz/kacerr/fuj-management:0.39-go
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
env:
|
||||
- name: PORT
|
||||
value: "8080"
|
||||
- name: TZ
|
||||
value: Europe/Prague
|
||||
- name: CREDENTIALS_PATH
|
||||
value: /secrets/credentials.json
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 128Mi
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
volumeMounts:
|
||||
- name: bot-credentials
|
||||
mountPath: /secrets
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: bot-credentials
|
||||
secret:
|
||||
secretName: fuj-management-bot-credentials
|
||||
60
gitops/home-kubernetes/fuj/deployment_fujarna.yaml
Normal file
60
gitops/home-kubernetes/fuj/deployment_fujarna.yaml
Normal file
@@ -0,0 +1,60 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: fujarna
|
||||
namespace: fuj
|
||||
labels:
|
||||
app: fujarna
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: fujarna
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: fujarna
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: gitea-registry
|
||||
containers:
|
||||
- name: fujarna
|
||||
image: gitea.home.hrajfrisbee.cz/kacerr/fujarna:v0.0.2
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
env:
|
||||
- name: PORT
|
||||
value: "8080"
|
||||
- name: TZ
|
||||
value: Europe/Prague
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /app/data
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 128Mi
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/tournaments
|
||||
port: 8080
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/tournaments
|
||||
port: 8080
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: tournament-data
|
||||
@@ -0,0 +1,22 @@
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: gitea-registry
|
||||
namespace: fuj
|
||||
spec:
|
||||
refreshInterval: 1h
|
||||
secretStoreRef:
|
||||
name: vault-backend
|
||||
kind: ClusterSecretStore
|
||||
target:
|
||||
name: gitea-registry
|
||||
creationPolicy: Owner
|
||||
template:
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
data:
|
||||
.dockerconfigjson: "{{ .token }}"
|
||||
data:
|
||||
- secretKey: token
|
||||
remoteRef:
|
||||
key: k8s_home/gitea/container-registry
|
||||
property: token
|
||||
30
gitops/home-kubernetes/fuj/httproute-notls.yaml
Normal file
30
gitops/home-kubernetes/fuj/httproute-notls.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: fujarna-redirect
|
||||
namespace: fuj
|
||||
labels:
|
||||
app: fujarna
|
||||
app.kubernetes.io/name: fujarna-httproute
|
||||
app.kubernetes.io/instance: fujarna
|
||||
app.kubernetes.io/version: '6.0'
|
||||
app.kubernetes.io/component: httproute
|
||||
app.kubernetes.io/part-of: fujarna
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: cilium-gateway
|
||||
namespace: kube-system
|
||||
sectionName: http
|
||||
hostnames:
|
||||
- fujarna.lab.home.hrajfrisbee.cz
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
filters:
|
||||
- type: RequestRedirect
|
||||
requestRedirect:
|
||||
scheme: https
|
||||
statusCode: 301
|
||||
29
gitops/home-kubernetes/fuj/httproute_fujarna.yaml
Normal file
29
gitops/home-kubernetes/fuj/httproute_fujarna.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: fujarna
|
||||
namespace: fuj
|
||||
labels:
|
||||
app: fujarna
|
||||
app.kubernetes.io/name: fujarna-httproute
|
||||
app.kubernetes.io/instance: fujarna
|
||||
app.kubernetes.io/version: '6.0'
|
||||
app.kubernetes.io/component: httproute
|
||||
app.kubernetes.io/part-of: fujarna
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: cilium-gateway
|
||||
namespace: kube-system
|
||||
sectionName: lab-home-hrajfrisbee-https-wildcard
|
||||
hostnames:
|
||||
- fujarna.lab.home.hrajfrisbee.cz
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: fujarna
|
||||
namespace: fuj
|
||||
port: 80
|
||||
28
gitops/home-kubernetes/fuj/httproute_management.yaml
Normal file
28
gitops/home-kubernetes/fuj/httproute_management.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: fuj-management
|
||||
namespace: fuj
|
||||
labels:
|
||||
app: fuj-management
|
||||
app.kubernetes.io/name: fuj-management-httproute
|
||||
app.kubernetes.io/instance: fuj-management
|
||||
app.kubernetes.io/component: httproute
|
||||
app.kubernetes.io/part-of: fuj-management
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: cilium-gateway
|
||||
namespace: kube-system
|
||||
sectionName: lab-home-hrajfrisbee-https-wildcard
|
||||
hostnames:
|
||||
- fuj-management.lab.home.hrajfrisbee.cz
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: fuj-management
|
||||
namespace: fuj
|
||||
port: 80
|
||||
30
gitops/home-kubernetes/fuj/ingress.yaml
Normal file
30
gitops/home-kubernetes/fuj/ingress.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: fujarna
|
||||
namespace: fuj
|
||||
annotations:
|
||||
# WebSocket support - increase timeouts for live scoring connections
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
|
||||
# Uncomment for cert-manager TLS:
|
||||
# cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
spec:
|
||||
ingressClassName: nginx # change to "traefik" for k3s default
|
||||
rules:
|
||||
- host: hrajfrisbee.cz # change to your domain
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: fujarna
|
||||
port:
|
||||
number: 80
|
||||
# Uncomment for TLS:
|
||||
# tls:
|
||||
# - hosts:
|
||||
# - hrajfrisbee.cz
|
||||
# secretName: fujarna-tls
|
||||
4
gitops/home-kubernetes/fuj/namespace.yaml
Normal file
4
gitops/home-kubernetes/fuj/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: fuj
|
||||
12
gitops/home-kubernetes/fuj/pvc.yaml
Normal file
12
gitops/home-kubernetes/fuj/pvc.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: tournament-data
|
||||
namespace: fuj
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
# storageClassName: local-path # uncomment to override cluster default
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: v1
|
||||
data:
|
||||
credentials.json: ewogICAgInR5cGUiOiAic2VydmljZV9hY2NvdW50IiwKICAgICJwcm9qZWN0X2lkIjogInBsYXRlZC1tZXNoLTQ4OTAxMC1zMSIsCiAgICAicHJpdmF0ZV9rZXlfaWQiOiAiYzQxM2VhYWUzMzk0NGFmZDljZjkyZjgzNGYzYmM1NDM5OGI1ZGY5YyIsCiAgICAicHJpdmF0ZV9rZXkiOiAiLS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tXG5NSUlFdmdJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLZ3dnZ1NrQWdFQUFvSUJBUURuTzBJQ3p2NDNaMWFKXG5MYi9NSkFZbld2U2NWM2tlelBGSHpHNVd2WUE3SXBxM2ZkcUp6ZWYxSzcxeGJodGY5NFB6T2RNVGdrYXcxcmZYXG40QjhOMS9laWFZaWUyZkkwenA4emptejl0YnpDUjVwM0hiK3M0eHROR3hVUDJBWWQzVmRrbE5TRFlacGJ5Qm8rXG5qNWl1cy9BOXdYV1ZkQ2EvNnA1MmtYSU1Ld3o4b05rbmpMRTlzV21ZV1kvQmJZT1o0UExPSjNTWEdEMFJNQzlGXG4wbjBLUDJTRWxvaTFPc2wvV2s0Q21WazJFc0lNSjBiMHA1Wm1GZUZ6SlAzSFZUS0VtOExHam5vWjVwQmwzWGM0XG5GOThKSVFFQzZQallOcXQvSFlxdWRLb2hrelVSS2h5ekVJdHp3NXBrUnk3d1l1OGJHSGJOMzF0dWFpeDRMdFNjXG5zYU5oOHJhVEFnTUJBQUVDZ2dFQWFXZ2U4RTdSbmdueWJiZzRMV1BpbGtBbEw3dkVUK0VXd0NjVnlWNjdQTG5LXG5rNGpBZlg4cWxSMnFUekhsTXJzUElHb2txVWtDMW93YTVFS2JoV0VFMXJtSytQYmJMVzFmTDA1bXFzVVUxZTkwXG5INGFsSUxlcWMxeThIaXZZcGZhSFp5ZGROTUxpYmFKckxFZWpUMGhoWkpWeTkzMHFTT1EzOWs3WkVXanlrNW9WXG5WcUk2SE4yVGUrRTN0aklmNFcrN0lKN0c3RU9ZVG4zZHlrQnZCN1QwLzR2M0pUeGMzTk1IN0RZYzFyd1dicEdKXG5JcmNidndOa3VyVHhsdWg1VGtvSkZjd3ZXdEl4NE52MFFPNkk5TlpjMllPakZUMncwMUFrKzNDSTJLNmJOVE9qXG43WWFxYlRoNDk2cU1Md2NtRmFUZy9tbXEzMGZycEVsMWdQTWJWZFJqTVFLQmdRRDY3SDMvb0pGU1ZDWnFYQjFEXG5tdHZRblVMSWUvZkU5TXc4T2VrcUdMclQxbGlUTllhTks4YnRsOGFrbFlZY3FXU09zWk53ZkdyNmNhOGhUSEwyXG5pWXZNbkR4aVJPWkVkeElPUFJGY2l4SlNpdG5hb3kzSmtMMml0K2cxMUVGdUEyS3dGd29jc0RrRkQ1QTh0ZEFpXG5UOGhEeEc4dE5saFFrTUY0ekRMNTE2cHRLUUtCZ1FEcjZNZitLelBoNHM2Qm1GVzkrUzNtZEFZZkJETkJsZHJrXG56L1hrY2NteHNWeUpNNTErR2MzY3kzYmhIRDU4aGVLb3U1ZHdYanNqZkRCZlZKcjBpTHM0R3dGbjNlWlJYNmluXG5NVmlycmpyUWt5WnlSVDJkcHl5ODQ5MGN1WC9xQ01hbTVRYzY0UmpJN3JhRTM5ZDBRcnRRd0hWbnZCN1RHaEcvXG50WElXeThMQld3S0JnRGRtMi9NQyt0TVlyVnF5ZCt1alY0RmFGNUs0ZkY1S1JvWE5xNE9WN2pvemkxOEZaRzNyXG5Db01QRGRidEJLMXpZVFo0VXJ0MVhSRnE1R1lQd1JwYUNEbm5EUllOYkdJVmdERVFucksyS2hkN2ZOcGZTUTdHXG5ISGkrN2xCa1N3WUZUVmJmMzJXeUt3VEpDT20rb3ZQUWRjRXdyL05sbWw0L2Q5ZzZEYzlJSk9MeEFvR0JBTi9yXG5QaGwwN0hRV0VpbFViTjQ3TEdRMzhLOTBEeXJMa00vcXpOMGZYSEM3aHJmOE5CdERadkdTZHE1SlhzNVhUc01WXG4vREorWHVmWnN4aHBlQU52M1RUdC9UR1hvRXZRM29hRUFrUkN4alMvMTVoVFBKN3QxVHNkbGZ6ejNnUklmRFpoXG40YkR6ZzlFRk5GMS9Fa1NhS3E0Rlgrc3MxcDFOZTFkYVpJWmF0ZXROQW9HQkFLeStZTGRjQVh6dElaMTkvS0wwXG5sWTBPZi92azVJNUtKNlNiVUVheU9HTFJkWTJBdGk1R1QwQlpjVEV3QjYzWTNyWEVNQ3BsM25Ca1pVRklRczNEXG5wSE9DUDdDMXQ3STRSZlBGaGlSTzEvQnVsajZjUXNrUHFJWlpadGxOQjdROG1BVEttMnpXVThZTjRNbFhZSVBVXG5naGRrZHVQRWIyRC9ueDl3U3F2NzdUeWJcbi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS1cbiIsCiAgICAiY2xpZW50X2VtYWlsIjogImZ1ai1tYW5hZ2VtZW50LWJvdEBwbGF0ZWQtbWVzaC00ODkwMTAtczEuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLAogICAgImNsaWVudF9pZCI6ICIxMDM0ODY2MjM3NTQxOTMzODgxMzQiLAogICAgImF1dGhfdXJpIjogImh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi9hdXRoIiwKICAgICJ0b2tlbl91cmkiOiAiaHR0cHM6Ly9vYXV0aDIuZ29vZ2xlYXBpcy5jb20vdG9rZW4iLAogICAgImF1dGhfcHJvdmlkZXJfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9vYXV0aDIvdjEvY2VydHMiLAogICAgImNsaWVudF94NTA5X2NlcnRfdXJsIjogImh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3JvYm90L3YxL21ldGFkYXRhL3g1MDkvZnVqLW1hbmFnZW1lbnQtYm90JTQwcGxhdGVkLW1lc2gtNDg5MDEwLXMxLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwKICAgICJ1bml2ZXJzZV9kb21haW4iOiAiZ29vZ2xlYXBpcy5jb20iCn0=
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: fuj-management-bot-credentials
|
||||
namespace: fuj
|
||||
type: Opaque
|
||||
14
gitops/home-kubernetes/fuj/service_fuj-management.yaml
Normal file
14
gitops/home-kubernetes/fuj/service_fuj-management.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: fuj-management
|
||||
namespace: fuj
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: fuj-management
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
name: http
|
||||
14
gitops/home-kubernetes/fuj/service_fujarna.yaml
Normal file
14
gitops/home-kubernetes/fuj/service_fujarna.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: fujarna
|
||||
namespace: fuj
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: fujarna
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
name: http
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: ghost-on-kubernetes-redirect
|
||||
namespace: ghost-on-kubernetes
|
||||
labels:
|
||||
app: ghost-on-kubernetes
|
||||
app.kubernetes.io/name: ghost-on-kubernetes-httproute
|
||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
||||
app.kubernetes.io/version: '6.0'
|
||||
app.kubernetes.io/component: httproute
|
||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: cilium-gateway
|
||||
namespace: kube-system
|
||||
sectionName: http
|
||||
hostnames:
|
||||
- ghost.lab.home.hrajfrisbee.cz
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
filters:
|
||||
- type: RequestRedirect
|
||||
requestRedirect:
|
||||
scheme: https
|
||||
statusCode: 301
|
||||
29
gitops/home-kubernetes/ghost-on-kubernetes/07-httproute.yaml
Normal file
29
gitops/home-kubernetes/ghost-on-kubernetes/07-httproute.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: ghost-on-kubernetes
|
||||
namespace: ghost-on-kubernetes
|
||||
labels:
|
||||
app: ghost-on-kubernetes
|
||||
app.kubernetes.io/name: ghost-on-kubernetes-httproute
|
||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
||||
app.kubernetes.io/version: '6.0'
|
||||
app.kubernetes.io/component: httproute
|
||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: cilium-gateway
|
||||
namespace: kube-system
|
||||
sectionName: lab-home-hrajfrisbee-https-wildcard
|
||||
hostnames:
|
||||
- ghost.lab.home.hrajfrisbee.cz
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: ghost-on-kubernetes-service
|
||||
namespace: ghost-on-kubernetes
|
||||
port: 2368
|
||||
@@ -25,7 +25,7 @@ spec:
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: ghost-on-kubernetes-service
|
||||
|
||||
@@ -11,11 +11,13 @@ spec:
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: ingress-nginx
|
||||
version: 4.12.0
|
||||
version: 4.14.1
|
||||
values:
|
||||
controller:
|
||||
admissionWebhooks:
|
||||
enabled: false
|
||||
patch:
|
||||
enabled: false
|
||||
config:
|
||||
annotations-risk-level: "Critical"
|
||||
interval: 5m0s
|
||||
@@ -17,7 +17,7 @@ data:
|
||||
ttl 30
|
||||
}
|
||||
hosts {
|
||||
192.168.0.30 vault.hrajfrisbee.cz
|
||||
# 192.168.0.30 vault.hrajfrisbee.cz
|
||||
fallthrough
|
||||
}
|
||||
prometheus :9153
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: mariadb-operator-crds
|
||||
namespace: mariadb-operator
|
||||
spec:
|
||||
interval: 1h
|
||||
chart:
|
||||
spec:
|
||||
chart: mariadb-operator-crds
|
||||
version: "25.10.*"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: mariadb-operator
|
||||
namespace: flux-system
|
||||
install:
|
||||
crds: Create
|
||||
upgrade:
|
||||
crds: CreateReplace
|
||||
@@ -0,0 +1,31 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: mariadb-operator
|
||||
namespace: mariadb-operator
|
||||
spec:
|
||||
interval: 1h
|
||||
dependsOn:
|
||||
- name: mariadb-operator-crds
|
||||
chart:
|
||||
spec:
|
||||
chart: mariadb-operator
|
||||
version: "25.10.*"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: mariadb-operator
|
||||
namespace: flux-system
|
||||
values:
|
||||
# uses built-in cert-controller for webhook TLS (no cert-manager dep)
|
||||
webhook:
|
||||
cert:
|
||||
certManager:
|
||||
enabled: false
|
||||
# disable HA for operator itself (fine for testing)
|
||||
ha:
|
||||
enabled: false
|
||||
# optional: enable metrics
|
||||
metrics:
|
||||
enabled: false
|
||||
serviceMonitor:
|
||||
enabled: false
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: mariadb-operator
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 1h
|
||||
url: https://helm.mariadb.com/mariadb-operator
|
||||
4
gitops/home-kubernetes/mariadb-operator/namespace.yaml
Normal file
4
gitops/home-kubernetes/mariadb-operator/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: mariadb-operator
|
||||
34
gitops/home-kubernetes/next-cloud/externalsecret.yaml
Normal file
34
gitops/home-kubernetes/next-cloud/externalsecret.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: nextcloud-secrets
|
||||
namespace: nextcloud
|
||||
spec:
|
||||
refreshInterval: 1h
|
||||
secretStoreRef:
|
||||
name: vault-backend # or your store
|
||||
kind: ClusterSecretStore
|
||||
target:
|
||||
name: nextcloud-secrets
|
||||
creationPolicy: Owner
|
||||
data:
|
||||
- secretKey: nextcloud-password
|
||||
remoteRef:
|
||||
key: k8s_home/nextcloud/admin
|
||||
property: password
|
||||
- secretKey: nextcloud-username
|
||||
remoteRef:
|
||||
key: k8s_home/nextcloud/admin
|
||||
property: username
|
||||
- secretKey: db-username
|
||||
remoteRef:
|
||||
key: k8s_home/nextcloud/postgres
|
||||
property: db-username
|
||||
- secretKey: postgres-password
|
||||
remoteRef:
|
||||
key: k8s_home/nextcloud/postgres
|
||||
property: password
|
||||
- secretKey: redis-password
|
||||
remoteRef:
|
||||
key: k8s_home/nextcloud/redis
|
||||
property: password
|
||||
263
gitops/home-kubernetes/next-cloud/helmrelease.yaml
Normal file
263
gitops/home-kubernetes/next-cloud/helmrelease.yaml
Normal file
@@ -0,0 +1,263 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: nextcloud
|
||||
namespace: nextcloud
|
||||
spec:
|
||||
interval: 30m
|
||||
timeout: 15m # Nextcloud init can be slow
|
||||
chart:
|
||||
spec:
|
||||
chart: nextcloud
|
||||
version: "8.6.0" # Latest as of Jan 2025
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: nextcloud
|
||||
namespace: flux-system
|
||||
interval: 12h
|
||||
install:
|
||||
crds: CreateReplace
|
||||
remediation:
|
||||
retries: 3
|
||||
upgrade:
|
||||
crds: CreateReplace
|
||||
cleanupOnFail: true
|
||||
remediation:
|
||||
retries: 3
|
||||
remediateLastFailure: true
|
||||
# CRITICAL: Suspend during major version upgrades to prevent restart loops
|
||||
# suspend: true
|
||||
values:
|
||||
image:
|
||||
repository: nextcloud
|
||||
tag: 32.0.3-apache # Latest as of Jan 2025. For fresh installs only.
|
||||
# UPGRADE PATH: If upgrading from older version, go sequentially:
|
||||
# 29.x → 30.0.x → 31.0.x → 32.0.x (one major at a time)
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
replicaCount: 1 # >1 requires Redis, see below
|
||||
|
||||
nextcloud:
|
||||
host: nextcloud.lab.home.hrajfrisbee.cz # Substitute or hardcode
|
||||
# existingSecret: nextcloud-admin # Alternative to inline credentials
|
||||
existingSecret:
|
||||
enabled: true
|
||||
secretName: nextcloud-secrets
|
||||
# usernameKey: username
|
||||
passwordKey: nextcloud-password
|
||||
|
||||
username: admin
|
||||
# password set via valuesFrom secret
|
||||
|
||||
|
||||
# PHP tuning - critical for stability
|
||||
phpConfigs:
|
||||
uploadLimit.ini: |
|
||||
upload_max_filesize = 16G
|
||||
post_max_size = 16G
|
||||
max_input_time = 3600
|
||||
max_execution_time = 3600
|
||||
www-conf.ini: |
|
||||
[www]
|
||||
pm = dynamic
|
||||
pm.max_children = 20
|
||||
pm.start_servers = 4
|
||||
pm.min_spare_servers = 2
|
||||
pm.max_spare_servers = 6
|
||||
pm.max_requests = 500
|
||||
memory.ini: |
|
||||
memory_limit = 1G
|
||||
opcache.ini: |
|
||||
opcache.enable = 1
|
||||
opcache.interned_strings_buffer = 32
|
||||
opcache.max_accelerated_files = 10000
|
||||
opcache.memory_consumption = 256
|
||||
opcache.save_comments = 1
|
||||
opcache.revalidate_freq = 60
|
||||
; Set to 0 if using ConfigMap-mounted configs
|
||||
|
||||
configs:
|
||||
# Proxy and overwrite settings - CRITICAL for ingress
|
||||
proxy.config.php: |-
|
||||
<?php
|
||||
$CONFIG = array (
|
||||
'trusted_proxies' => array(
|
||||
0 => '127.0.0.1',
|
||||
1 => '10.0.0.0/8',
|
||||
2 => '172.16.0.0/12',
|
||||
3 => '192.168.0.0/16',
|
||||
),
|
||||
'forwarded_for_headers' => array('HTTP_X_FORWARDED_FOR'),
|
||||
'overwriteprotocol' => 'https',
|
||||
);
|
||||
|
||||
# Performance and maintenance
|
||||
custom.config.php: |-
|
||||
<?php
|
||||
$CONFIG = array (
|
||||
'default_phone_region' => 'US',
|
||||
'maintenance_window_start' => 1,
|
||||
'filelocking.enabled' => true,
|
||||
'memcache.local' => '\\OC\\Memcache\\APCu',
|
||||
'memcache.distributed' => '\\OC\\Memcache\\Redis',
|
||||
'memcache.locking' => '\\OC\\Memcache\\Redis',
|
||||
'redis' => array(
|
||||
'host' => 'nextcloud-redis-master',
|
||||
'port' => 6379,
|
||||
'password' => getenv('REDIS_PASSWORD'),
|
||||
),
|
||||
);
|
||||
|
||||
extraEnv:
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: nextcloud-secrets
|
||||
key: redis-password
|
||||
|
||||
# Ingress - adjust for your ingress controller
|
||||
ingress:
|
||||
enabled: true
|
||||
className: nginx # or traefik, etc.
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "16G"
|
||||
nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/server-snippet: |
|
||||
server_tokens off;
|
||||
proxy_hide_header X-Powered-By;
|
||||
rewrite ^/.well-known/webfinger /index.php/.well-known/webfinger last;
|
||||
rewrite ^/.well-known/nodeinfo /index.php/.well-known/nodeinfo last;
|
||||
rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
|
||||
rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json;
|
||||
location = /.well-known/carddav {
|
||||
return 301 $scheme://$host/remote.php/dav;
|
||||
}
|
||||
location = /.well-known/caldav {
|
||||
return 301 $scheme://$host/remote.php/dav;
|
||||
}
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
tls:
|
||||
- secretName: nextcloud-tls
|
||||
hosts:
|
||||
- nextcloud.lab.home.hrajfrisbee.cz
|
||||
|
||||
# PostgreSQL - strongly recommended over MariaDB for Nextcloud
|
||||
postgresql:
|
||||
enabled: true
|
||||
global:
|
||||
postgresql:
|
||||
auth:
|
||||
username: nextcloud
|
||||
database: nextcloud
|
||||
existingSecret: nextcloud-secrets
|
||||
secretKeys:
|
||||
userPasswordKey: postgres-password
|
||||
primary:
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 8Gi
|
||||
storageClass: "" # Use default or specify
|
||||
resources:
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: 100m
|
||||
limits:
|
||||
memory: 512Mi
|
||||
|
||||
# Redis - required for file locking and sessions
|
||||
redis:
|
||||
enabled: true
|
||||
auth:
|
||||
enabled: true
|
||||
existingSecret: nextcloud-secrets
|
||||
existingSecretPasswordKey: redis-password
|
||||
architecture: standalone
|
||||
master:
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 1Gi
|
||||
|
||||
# Disable built-in databases we're not using
|
||||
mariadb:
|
||||
enabled: false
|
||||
internalDatabase:
|
||||
enabled: false
|
||||
|
||||
externalDatabase:
|
||||
enabled: true
|
||||
type: postgresql
|
||||
host: nextcloud-postgresql # Service name created by subchart
|
||||
user: nextcloud
|
||||
database: nextcloud
|
||||
existingSecret:
|
||||
enabled: true
|
||||
secretName: nextcloud-secrets
|
||||
passwordKey: postgres-password
|
||||
|
||||
# Cron job - CRITICAL: never use AJAX cron
|
||||
cronjob:
|
||||
enabled: true
|
||||
schedule: "*/5 * * * *"
|
||||
resources:
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: 50m
|
||||
limits:
|
||||
memory: 512Mi
|
||||
|
||||
# Main persistence
|
||||
persistence:
|
||||
enabled: true
|
||||
storageClass: "" # Specify your storage class
|
||||
size: 100Gi
|
||||
accessMode: ReadWriteOnce
|
||||
# nextcloudData - separate PVC for user data (recommended)
|
||||
nextcloudData:
|
||||
enabled: true
|
||||
storageClass: ""
|
||||
size: 500Gi
|
||||
accessMode: ReadWriteOnce
|
||||
|
||||
# Resource limits - tune based on usage
|
||||
resources:
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
memory: 2Gi
|
||||
|
||||
# Liveness/Readiness - tuned to prevent upgrade restart loops
|
||||
livenessProbe:
|
||||
enabled: true
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 10
|
||||
failureThreshold: 6
|
||||
successThreshold: 1
|
||||
readinessProbe:
|
||||
enabled: true
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 10
|
||||
failureThreshold: 6
|
||||
successThreshold: 1
|
||||
startupProbe:
|
||||
enabled: true
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 10
|
||||
failureThreshold: 30 # 15 minutes for upgrades
|
||||
|
||||
# Security context - avoid fsGroup recursive chown
|
||||
securityContext:
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
podSecurityContext:
|
||||
fsGroup: 33 # www-data
|
||||
|
||||
# Metrics - optional but recommended
|
||||
metrics:
|
||||
enabled: false # Enable if you have Prometheus
|
||||
# serviceMonitor:
|
||||
# enabled: true
|
||||
8
gitops/home-kubernetes/next-cloud/helmrepository.yaml
Normal file
8
gitops/home-kubernetes/next-cloud/helmrepository.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: nextcloud
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 24h
|
||||
url: https://nextcloud.github.io/helm/
|
||||
7
gitops/home-kubernetes/next-cloud/namespace.yaml
Normal file
7
gitops/home-kubernetes/next-cloud/namespace.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: nextcloud
|
||||
labels:
|
||||
pod-security.kubernetes.io/enforce: baseline
|
||||
pod-security.kubernetes.io/warn: restricted
|
||||
@@ -39,6 +39,7 @@ spec:
|
||||
ingress:
|
||||
enabled: true
|
||||
className: nginx
|
||||
pathType: Prefix
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
hosts:
|
||||
|
||||
@@ -4,7 +4,7 @@ metadata:
|
||||
name: oauth2-proxy-secrets
|
||||
namespace: oauth2-proxy
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/reconcile: disabled
|
||||
kustomize.toolkit.fluxcd.io/reconcile: disabled
|
||||
stringData:
|
||||
client-id: oauth2-proxy
|
||||
client-secret: <REPLACE_WITH_KANIDM_SECRET>
|
||||
|
||||
@@ -33,7 +33,7 @@ spec:
|
||||
rabbitmqHost: "plane-mq.lab.home.hrajfrisbee.cz" # optional
|
||||
ingressClass: nginx
|
||||
ingress_annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-production
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/auth-url: "https://oauth2-proxy.lab.home.hrajfrisbee.cz/oauth2/auth"
|
||||
nginx.ingress.kubernetes.io/auth-signin: "https://oauth2-proxy.lab.home.hrajfrisbee.cz/oauth2/start?rd=$scheme://$host$escaped_request_uri"
|
||||
nginx.ingress.kubernetes.io/auth-response-headers: "X-Auth-Request-User,X-Auth-Request-Email,Authorization"
|
||||
|
||||
@@ -24,7 +24,7 @@ spec:
|
||||
- host: podinfo.lab.home.hrajfrisbee.cz
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
pathType: Prefix
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
|
||||
12
gitops/home-kubernetes/seafile/conf/seahub_settings.py
Normal file
12
gitops/home-kubernetes/seafile/conf/seahub_settings.py
Normal file
@@ -0,0 +1,12 @@
|
||||
EMAIL_USE_TLS = True
|
||||
EMAIL_HOST = 'smtp.gmail.com'
|
||||
EMAIL_HOST_USER = 'kacerr.cz@gmail.com'
|
||||
EMAIL_HOST_PASSWORD = 'zeyd ppmy gfqu gaws' # App Password, not your login password
|
||||
EMAIL_PORT = 587
|
||||
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
|
||||
SERVER_EMAIL = EMAIL_HOST_USER
|
||||
|
||||
|
||||
FILE_SERVER_ROOT = 'https://seafile.lab.home.hrajfrisbee.cz/seafhttp'
|
||||
|
||||
DEBUG = True
|
||||
30
gitops/home-kubernetes/seafile/externalsecret.yaml
Normal file
30
gitops/home-kubernetes/seafile/externalsecret.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: seafile-secret
|
||||
namespace: seafile
|
||||
spec:
|
||||
refreshInterval: 1h
|
||||
secretStoreRef:
|
||||
name: vault-backend # or your store
|
||||
kind: ClusterSecretStore
|
||||
target:
|
||||
name: seafile-secret
|
||||
creationPolicy: Owner
|
||||
data:
|
||||
- secretKey: JWT_PRIVATE_KEY
|
||||
remoteRef:
|
||||
key: k8s_home/seafile
|
||||
property: JWT_PRIVATE_KEY
|
||||
- secretKey: SEAFILE_MYSQL_DB_PASSWORD
|
||||
remoteRef:
|
||||
key: k8s_home/seafile
|
||||
property: SEAFILE_MYSQL_DB_PASSWORD
|
||||
- secretKey: INIT_SEAFILE_ADMIN_PASSWORD
|
||||
remoteRef:
|
||||
key: k8s_home/seafile
|
||||
property: INIT_SEAFILE_ADMIN_PASSWORD
|
||||
- secretKey: INIT_SEAFILE_MYSQL_ROOT_PASSWORD
|
||||
remoteRef:
|
||||
key: k8s_home/seafile
|
||||
property: INIT_SEAFILE_MYSQL_ROOT_PASSWORD
|
||||
114
gitops/home-kubernetes/seafile/helmrelease.yaml
Normal file
114
gitops/home-kubernetes/seafile/helmrelease.yaml
Normal file
@@ -0,0 +1,114 @@
|
||||
# apps/seafile/helmrelease.yaml
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: seafile
|
||||
namespace: seafile
|
||||
spec:
|
||||
interval: 30m
|
||||
chart:
|
||||
spec:
|
||||
chart: ce
|
||||
version: "13.0.2"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: seafile
|
||||
namespace: flux-system
|
||||
install:
|
||||
createNamespace: true
|
||||
remediation:
|
||||
retries: 3
|
||||
upgrade:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
# Post-render patches
|
||||
postRenderers:
|
||||
- kustomize:
|
||||
patches:
|
||||
# Remove imagePullSecrets from all Deployments
|
||||
- target:
|
||||
kind: Deployment
|
||||
patch: |
|
||||
- op: remove
|
||||
path: /spec/template/spec/imagePullSecrets
|
||||
# Remove from StatefulSets (MariaDB, etc.)
|
||||
- target:
|
||||
kind: StatefulSet
|
||||
patch: |
|
||||
- op: remove
|
||||
path: /spec/template/spec/imagePullSecrets
|
||||
# Remove from Pods if any
|
||||
- target:
|
||||
kind: Pod
|
||||
patch: |
|
||||
- op: remove
|
||||
path: /spec/imagePullSecrets
|
||||
values:
|
||||
seafile:
|
||||
initMode: true
|
||||
|
||||
# The following are the configurations of seafile container
|
||||
configs:
|
||||
image: seafileltd/seafile-mc:13.0-latest
|
||||
seafileDataVolume:
|
||||
storage: 10Gi
|
||||
|
||||
# The following are environments of seafile services
|
||||
env:
|
||||
# for Seafile server
|
||||
TIME_ZONE: "UTC"
|
||||
SEAFILE_LOG_TO_STDOUT: "true"
|
||||
SITE_ROOT: "/"
|
||||
SEAFILE_SERVER_HOSTNAME: "seafile.lab.home.hrajfrisbee.cz"
|
||||
SEAFILE_SERVER_PROTOCOL: "https"
|
||||
|
||||
# for database
|
||||
SEAFILE_MYSQL_DB_HOST: "seafile-mariadb"
|
||||
SEAFILE_MYSQL_DB_PORT: "3306"
|
||||
SEAFILE_MYSQL_DB_USER: "seafile"
|
||||
#SEAFILE_MYSQL_DB_CCNET_DB_NAME: "ccnet-db"
|
||||
#SEAFILE_MYSQL_DB_SEAFILE_DB_NAME: "seafile-db"
|
||||
#SEAFILE_MYSQL_DB_SEAHUB_DB_NAME: "seahub-db"
|
||||
|
||||
# for cache
|
||||
CACHE_PROVIDER: "redis"
|
||||
|
||||
## for redis
|
||||
REDIS_HOST: "redis"
|
||||
REDIS_PORT: "6379"
|
||||
|
||||
## for memcached
|
||||
#MEMCACHED_HOST: ""
|
||||
#MEMCACHED_PORT: "11211"
|
||||
|
||||
# for notification
|
||||
ENABLE_NOTIFICATION_SERVER: "false"
|
||||
NOTIFICATION_SERVER_URL: ""
|
||||
|
||||
# for seadoc
|
||||
ENABLE_SEADOC: "false"
|
||||
SEADOC_SERVER_URL: "" # only valid in ENABLE_SEADOC = true
|
||||
|
||||
# for Seafile AI
|
||||
ENABLE_SEAFILE_AI: "false"
|
||||
SEAFILE_AI_SERVER_URL: ""
|
||||
|
||||
# for Metadata server
|
||||
MD_FILE_COUNT_LIMIT: "100000"
|
||||
|
||||
# initialization (only valid in first-time deployment and initMode = true)
|
||||
|
||||
## for Seafile admin
|
||||
INIT_SEAFILE_ADMIN_EMAIL: "kacerr.cz@gmail.com"
|
||||
|
||||
# if you are using another secret name / key for seafile or mysql, please make correct the following fields:
|
||||
#secretsMap:
|
||||
# DB_ROOT_PASSWD: # Env's name
|
||||
# secret: seafile-secret # secret's name, `seafile-secret` if not specify
|
||||
# key: INIT_SEAFILE_MYSQL_ROOT_PASSWORD # secret's key, `Env's name` if not specify
|
||||
|
||||
# extra configurations
|
||||
extraResources: {}
|
||||
extraEnv: []
|
||||
extraVolumes: []
|
||||
8
gitops/home-kubernetes/seafile/helmrepository.yaml
Normal file
8
gitops/home-kubernetes/seafile/helmrepository.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: seafile
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 1h
|
||||
url: https://haiwen.github.io/seafile-helm-chart/repo
|
||||
35
gitops/home-kubernetes/seafile/ingress.yaml
Normal file
35
gitops/home-kubernetes/seafile/ingress.yaml
Normal file
@@ -0,0 +1,35 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
meta.helm.sh/release-name: seafile
|
||||
meta.helm.sh/release-namespace: seafile
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "100m" # 0 = unlimited, or "500m"
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
||||
nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
|
||||
labels:
|
||||
app.kubernetes.io/component: app
|
||||
app.kubernetes.io/instance: seafile
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: seafile
|
||||
name: seafile
|
||||
namespace: seafile
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
rules:
|
||||
- host: seafile.lab.home.hrajfrisbee.cz
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: seafile
|
||||
port:
|
||||
number: 80
|
||||
path: /
|
||||
pathType: Prefix
|
||||
tls:
|
||||
- hosts:
|
||||
- seafile.lab.home.hrajfrisbee.cz
|
||||
secretName: seafile-tls
|
||||
@@ -0,0 +1,10 @@
|
||||
apiVersion: k8s.mariadb.com/v1alpha1
|
||||
kind: Database
|
||||
metadata:
|
||||
name: ccnet-db
|
||||
namespace: seafile
|
||||
spec:
|
||||
mariaDbRef:
|
||||
name: seafile-mariadb
|
||||
characterSet: utf8mb4
|
||||
collate: utf8mb4_general_ci
|
||||
@@ -0,0 +1,10 @@
|
||||
apiVersion: k8s.mariadb.com/v1alpha1
|
||||
kind: Database
|
||||
metadata:
|
||||
name: seafile-db
|
||||
namespace: seafile
|
||||
spec:
|
||||
mariaDbRef:
|
||||
name: seafile-mariadb
|
||||
characterSet: utf8mb4
|
||||
collate: utf8mb4_general_ci
|
||||
@@ -0,0 +1,10 @@
|
||||
apiVersion: k8s.mariadb.com/v1alpha1
|
||||
kind: Database
|
||||
metadata:
|
||||
name: seahub-db
|
||||
namespace: seafile
|
||||
spec:
|
||||
mariaDbRef:
|
||||
name: seafile-mariadb
|
||||
characterSet: utf8mb4
|
||||
collate: utf8mb4_general_ci
|
||||
61
gitops/home-kubernetes/seafile/mariadb-grant-seafile.yaml
Normal file
61
gitops/home-kubernetes/seafile/mariadb-grant-seafile.yaml
Normal file
@@ -0,0 +1,61 @@
|
||||
apiVersion: k8s.mariadb.com/v1alpha1
|
||||
kind: Grant
|
||||
metadata:
|
||||
name: all-privileges
|
||||
spec:
|
||||
mariaDbRef:
|
||||
name: seafile-mariadb
|
||||
username: seafile
|
||||
database: "*"
|
||||
table: "*"
|
||||
privileges:
|
||||
- ALL PRIVILEGES
|
||||
grantOption: true
|
||||
# ---
|
||||
# apiVersion: k8s.mariadb.com/v1alpha1
|
||||
# kind: Grant
|
||||
# metadata:
|
||||
# name: seafile-grant
|
||||
# namespace: seafile
|
||||
# spec:
|
||||
# mariaDbRef:
|
||||
# name: seafile-mariadb
|
||||
# privileges:
|
||||
# - ALL PRIVILEGES
|
||||
# database: seafile-db
|
||||
# table: "*"
|
||||
# username: seafile
|
||||
# host: "%"
|
||||
# grantOption: false
|
||||
# ---
|
||||
# apiVersion: k8s.mariadb.com/v1alpha1
|
||||
# kind: Grant
|
||||
# metadata:
|
||||
# name: seahub-grant
|
||||
# namespace: seafile
|
||||
# spec:
|
||||
# mariaDbRef:
|
||||
# name: seafile-mariadb
|
||||
# privileges:
|
||||
# - ALL PRIVILEGES
|
||||
# database: seahub-db
|
||||
# table: "*"
|
||||
# username: seafile
|
||||
# host: "%"
|
||||
# grantOption: false
|
||||
# ---
|
||||
# apiVersion: k8s.mariadb.com/v1alpha1
|
||||
# kind: Grant
|
||||
# metadata:
|
||||
# name: ccnet-grant
|
||||
# namespace: seafile
|
||||
# spec:
|
||||
# mariaDbRef:
|
||||
# name: seafile-mariadb
|
||||
# privileges:
|
||||
# - ALL PRIVILEGES
|
||||
# database: ccnet-db
|
||||
# table: "*"
|
||||
# username: seafile
|
||||
# host: "%"
|
||||
# grantOption: false
|
||||
13
gitops/home-kubernetes/seafile/mariadb-user.yaml
Normal file
13
gitops/home-kubernetes/seafile/mariadb-user.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
apiVersion: k8s.mariadb.com/v1alpha1
|
||||
kind: User
|
||||
metadata:
|
||||
name: seafile
|
||||
namespace: seafile
|
||||
spec:
|
||||
mariaDbRef:
|
||||
name: seafile-mariadb
|
||||
passwordSecretKeyRef:
|
||||
name: seafile-secret
|
||||
key: SEAFILE_MYSQL_DB_PASSWORD
|
||||
maxUserConnections: 20
|
||||
host: "%"
|
||||
33
gitops/home-kubernetes/seafile/mariadb.yaml
Normal file
33
gitops/home-kubernetes/seafile/mariadb.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
apiVersion: k8s.mariadb.com/v1alpha1
|
||||
kind: MariaDB
|
||||
metadata:
|
||||
name: seafile-mariadb
|
||||
namespace: seafile
|
||||
spec:
|
||||
rootPasswordSecretKeyRef:
|
||||
name: seafile-secret
|
||||
key: INIT_SEAFILE_MYSQL_ROOT_PASSWORD
|
||||
|
||||
image: mariadb:11.4
|
||||
|
||||
port: 3306
|
||||
|
||||
storage:
|
||||
size: 10Gi
|
||||
# storageClassName: your-storage-class
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
memory: 1Gi
|
||||
|
||||
myCnf: |
|
||||
[mariadb]
|
||||
bind-address=*
|
||||
default_storage_engine=InnoDB
|
||||
binlog_format=row
|
||||
innodb_autoinc_lock_mode=2
|
||||
innodb_buffer_pool_size=256M
|
||||
max_allowed_packet=256M
|
||||
39
gitops/home-kubernetes/seafile/memcached.yaml
Normal file
39
gitops/home-kubernetes/seafile/memcached.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
# apiVersion: apps/v1
|
||||
# kind: Deployment
|
||||
# metadata:
|
||||
# name: seafile-memcached
|
||||
# namespace: seafile
|
||||
# spec:
|
||||
# replicas: 1
|
||||
# selector:
|
||||
# matchLabels:
|
||||
# app: seafile-memcached
|
||||
# template:
|
||||
# metadata:
|
||||
# labels:
|
||||
# app: seafile-memcached
|
||||
# spec:
|
||||
# containers:
|
||||
# - name: memcached
|
||||
# image: memcached:1.6-alpine
|
||||
# args: ["-m", "128"] # 128MB memory limit
|
||||
# ports:
|
||||
# - containerPort: 11211
|
||||
# resources:
|
||||
# requests:
|
||||
# memory: 64Mi
|
||||
# cpu: 25m
|
||||
# limits:
|
||||
# memory: 192Mi
|
||||
# ---
|
||||
# apiVersion: v1
|
||||
# kind: Service
|
||||
# metadata:
|
||||
# name: seafile-memcached
|
||||
# namespace: seafile
|
||||
# spec:
|
||||
# selector:
|
||||
# app: seafile-memcached
|
||||
# ports:
|
||||
# - port: 11211
|
||||
# targetPort: 11211
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user