Compare commits
1 Commits
gitops/upd
...
974c3e8b00
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
974c3e8b00 |
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"permissions": {
|
|
||||||
"allow": [
|
|
||||||
"Bash(for f:*)",
|
|
||||||
"Bash(do echo:*)",
|
|
||||||
"Read(//Users/jan.novak/srv/personal/home-kubernetes/**)",
|
|
||||||
"Bash(done)"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,14 +1 @@
|
|||||||
.DS_Store
|
|
||||||
|
|
||||||
.terraform/
|
.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
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/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,15 +57,6 @@ services:
|
|||||||
- GITEA__server__ROOT_URL=https://gitea.home.hrajfrisbee.cz
|
- GITEA__server__ROOT_URL=https://gitea.home.hrajfrisbee.cz
|
||||||
- GITEA__security__SECRET_KEY=${GITEA_SECRET_KEY}
|
- GITEA__security__SECRET_KEY=${GITEA_SECRET_KEY}
|
||||||
- GITEA__security__INTERNAL_TOKEN=${INTERNAL_TOKEN}
|
- 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__STORAGE_TYPE=minio
|
||||||
#- GITEA__storage__MINIO_ENDPOINT=minio:9000
|
#- GITEA__storage__MINIO_ENDPOINT=minio:9000
|
||||||
#- GITEA__storage__MINIO_ACCESS_KEY_ID=gitea
|
#- GITEA__storage__MINIO_ACCESS_KEY_ID=gitea
|
||||||
@@ -92,12 +83,10 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- gitea
|
- gitea
|
||||||
environment:
|
environment:
|
||||||
GITEA_INSTANCE_URL: https://gitea.home.hrajfrisbee.cz/
|
GITEA_INSTANCE_URL: http://gitea:3000
|
||||||
GITEA_RUNNER_REGISTRATION_TOKEN: ${RUNNER_TOKEN}
|
GITEA_RUNNER_REGISTRATION_TOKEN: ${RUNNER_TOKEN}
|
||||||
CONFIG_FILE: /config/config.yaml
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./runner-data:/data
|
- ./runner-data:/data
|
||||||
- ./runner-config.yaml:/config/config.yaml:ro
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
networks:
|
networks:
|
||||||
- gitea-network
|
- gitea-network
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
## 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,169 +0,0 @@
|
|||||||
## 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/
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export GROUP_NAME=k8s_users
|
|
||||||
kanidm group create ${GROUP_NAME}
|
|
||||||
kanidm group add-members ${GROUP_NAME} novakj
|
|
||||||
|
|
||||||
|
|
||||||
export OAUTH2_NAME=k8s
|
|
||||||
kanidm system oauth2 create-public ${OAUTH2_NAME} ${OAUTH2_NAME} http://localhost:8000
|
|
||||||
kanidm system oauth2 add-redirect-url ${OAUTH2_NAME} http://localhost:8000
|
|
||||||
kanidm system oauth2 update-scope-map ${OAUTH2_NAME} ${GROUP_NAME} email openid profile groups
|
|
||||||
kanidm system oauth2 enable-localhost-redirects ${OAUTH2_NAME}
|
|
||||||
|
|
||||||
|
|
||||||
kubectl oidc-login setup \
|
|
||||||
--oidc-issuer-url=https://idm.home.hrajfrisbee.cz/oauth2/openid/k8s \
|
|
||||||
--oidc-client-id=k8s
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
kubectl config set-credentials oidc \
|
|
||||||
--exec-api-version=client.authentication.k8s.io/v1 \
|
|
||||||
--exec-interactive-mode=Never \
|
|
||||||
--exec-command=kubectl \
|
|
||||||
--exec-arg=oidc-login \
|
|
||||||
--exec-arg=get-token \
|
|
||||||
--exec-arg="--oidc-issuer-url=https://idm.home.hrajfrisbee.cz/oauth2/openid/k8s" \
|
|
||||||
--exec-arg="--oidc-client-id=k8s"
|
|
||||||
|
|
||||||
kubectl create clusterrolebinding oidc-cluster-admin \
|
|
||||||
--clusterrole=cluster-admin \
|
|
||||||
--user='https://idm.home.hrajfrisbee.cz/oauth2/openid/k8s#35842461-a1c4-4ad6-8b29-697c5ddbfe84'
|
|
||||||
|
|
||||||
```
|
|
||||||
## commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# recover admin password
|
|
||||||
# on the docker host
|
|
||||||
docker exec -i -t kanidmd kanidmd recover-account admin
|
|
||||||
docker exec -i -t kanidmd kanidmd recover-account idm_admin
|
|
||||||
|
|
||||||
# kanidm mangement commands (could be run on any logged in client)
|
|
||||||
kanidm person credential create-reset-token novakj
|
|
||||||
kanidm person get novakj | grep memberof
|
|
||||||
kanidm group get kanidm group get
|
|
||||||
kanidm group get idm_all_accounts
|
|
||||||
kanidm group get idm_all_persons
|
|
||||||
kanidm group account-policy credential-type-minimum idm_all_accounts any
|
|
||||||
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
|
|
||||||
|
|
||||||
docker run -d --name=kanidmd --restart=always \
|
|
||||||
-p '8443:8443' \
|
|
||||||
-p '3636:3636' \
|
|
||||||
--volume /srv/docker/kanidm/data:/data \
|
|
||||||
docker.io/kanidm/server:latest
|
|
||||||
|
|
||||||
docker run --rm -i -t -v --restart=always \
|
|
||||||
-p '8443:8443' \
|
|
||||||
-p '3636:3636' \
|
|
||||||
--volume /srv/docker/kanidm/data:/data \
|
|
||||||
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
|
|
||||||
|
|
||||||
```
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
# The server configuration file version.
|
|
||||||
version = "2"
|
|
||||||
|
|
||||||
# The webserver bind address. Requires TLS certificates.
|
|
||||||
# If the port is set to 443 you may require the
|
|
||||||
# NET_BIND_SERVICE capability. This accepts a single address
|
|
||||||
# or an array of addresses to listen on.
|
|
||||||
# Defaults to "127.0.0.1:8443"
|
|
||||||
bindaddress = "0.0.0.0:8443"
|
|
||||||
#
|
|
||||||
# The read-only ldap server bind address. Requires
|
|
||||||
# TLS certificates. If set to 636 you may require the
|
|
||||||
# NET_BIND_SERVICE capability. This accepts a single address
|
|
||||||
# or an array of addresses to listen on.
|
|
||||||
# Defaults to "" (disabled)
|
|
||||||
# ldapbindaddress = "0.0.0.0:3636"
|
|
||||||
#
|
|
||||||
# The path to the kanidm database.
|
|
||||||
db_path = "/data/kanidm.db"
|
|
||||||
#
|
|
||||||
# If you have a known filesystem, kanidm can tune the
|
|
||||||
# database page size to match. Valid choices are:
|
|
||||||
# [zfs, other]
|
|
||||||
# If you are unsure about this leave it as the default
|
|
||||||
# (other). After changing this
|
|
||||||
# value you must run a vacuum task.
|
|
||||||
# - zfs:
|
|
||||||
# * sets database pagesize to 64k. You must set
|
|
||||||
# recordsize=64k on the zfs filesystem.
|
|
||||||
# - other:
|
|
||||||
# * sets database pagesize to 4k, matching most
|
|
||||||
# filesystems block sizes.
|
|
||||||
# db_fs_type = "zfs"
|
|
||||||
#
|
|
||||||
# The number of entries to store in the in-memory cache.
|
|
||||||
# Minimum value is 256. If unset
|
|
||||||
# an automatic heuristic is used to scale this.
|
|
||||||
# You should only adjust this value if you experience
|
|
||||||
# memory pressure on your system.
|
|
||||||
# db_arc_size = 2048
|
|
||||||
#
|
|
||||||
# TLS chain and key in pem format. Both must be present.
|
|
||||||
# If the server receives a SIGHUP, these files will be
|
|
||||||
# re-read and reloaded if their content is valid.
|
|
||||||
tls_chain = "/data/chain.pem"
|
|
||||||
tls_key = "/data/key.pem"
|
|
||||||
#
|
|
||||||
# The log level of the server. May be one of info, debug, trace
|
|
||||||
#
|
|
||||||
# NOTE: this can be overridden by the environment variable
|
|
||||||
# `KANIDM_LOG_LEVEL` at runtime
|
|
||||||
# Defaults to "info"
|
|
||||||
# log_level = "info"
|
|
||||||
#
|
|
||||||
# The DNS domain name of the server. This is used in a
|
|
||||||
# number of security-critical contexts
|
|
||||||
# such as webauthn, so it *must* match your DNS
|
|
||||||
# hostname. It is used to create
|
|
||||||
# security principal names such as `william@idm.example.com`
|
|
||||||
# so that in a (future) trust configuration it is possible
|
|
||||||
# to have unique Security Principal Names (spns) throughout
|
|
||||||
# the topology.
|
|
||||||
#
|
|
||||||
# ⚠️ WARNING ⚠️
|
|
||||||
#
|
|
||||||
# Changing this value WILL break many types of registered
|
|
||||||
# credentials for accounts including but not limited to
|
|
||||||
# webauthn, oauth tokens, and more.
|
|
||||||
# If you change this value you *must* run
|
|
||||||
# `kanidmd domain rename` immediately after.
|
|
||||||
domain = "idm.home.hrajfrisbee.cz"
|
|
||||||
#
|
|
||||||
# The origin for webauthn. This is the url to the server,
|
|
||||||
# with the port included if it is non-standard (any port
|
|
||||||
# except 443). This must match or be a descendent of the
|
|
||||||
# domain name you configure above. If these two items are
|
|
||||||
# not consistent, the server WILL refuse to start!
|
|
||||||
# origin = "https://idm.example.com"
|
|
||||||
# # OR
|
|
||||||
# origin = "https://idm.example.com:8443"
|
|
||||||
origin = "https://idm.home.hrajfrisbee.cz"
|
|
||||||
|
|
||||||
# HTTPS requests can be reverse proxied by a loadbalancer.
|
|
||||||
# To preserve the original IP of the caller, these systems
|
|
||||||
# will often add a header such as "Forwarded" or
|
|
||||||
# "X-Forwarded-For". Some other proxies can use the PROXY
|
|
||||||
# protocol v2 header. While we support the PROXY protocol
|
|
||||||
# v1 header, we STRONGLY discourage it's use as it has
|
|
||||||
# significantly greater overheads compared to v2 during
|
|
||||||
# processing.
|
|
||||||
# This setting allows configuration of the list of trusted
|
|
||||||
# IPs or IP ranges which can supply this header information,
|
|
||||||
# and which format the information is provided in.
|
|
||||||
# Defaults to "none" (no trusted sources)
|
|
||||||
# Only one option can be used at a time.
|
|
||||||
# [http_client_address_info]
|
|
||||||
# proxy-v2 = ["127.0.0.1", "127.0.0.0/8"]
|
|
||||||
# # OR
|
|
||||||
# [http_client_address_info]
|
|
||||||
# x-forward-for = ["127.0.0.1", "127.0.0.0/8"]
|
|
||||||
# # OR
|
|
||||||
# [http_client_address_info]
|
|
||||||
# # AVOID IF POSSIBLE!!!
|
|
||||||
# proxy-v1 = ["127.0.0.1", "127.0.0.0/8"]
|
|
||||||
|
|
||||||
# LDAPS requests can be reverse proxied by a loadbalancer.
|
|
||||||
# To preserve the original IP of the caller, these systems
|
|
||||||
# can add a header such as the PROXY protocol v2 header.
|
|
||||||
# While we support the PROXY protocol v1 header, we STRONGLY
|
|
||||||
# discourage it's use as it has significantly greater
|
|
||||||
# overheads compared to v2 during processing.
|
|
||||||
# This setting allows configuration of the list of trusted
|
|
||||||
# IPs or IP ranges which can supply this header information,
|
|
||||||
# and which format the information is provided in.
|
|
||||||
# Defaults to "none" (no trusted sources)
|
|
||||||
# [ldap_client_address_info]
|
|
||||||
# proxy-v2 = ["127.0.0.1", "127.0.0.0/8"]
|
|
||||||
# # OR
|
|
||||||
# [ldap_client_address_info]
|
|
||||||
# # AVOID IF POSSIBLE!!!
|
|
||||||
# proxy-v1 = ["127.0.0.1", "127.0.0.0/8"]
|
|
||||||
|
|
||||||
[online_backup]
|
|
||||||
# The path to the output folder for online backups
|
|
||||||
path = "/data/kanidm/backups/"
|
|
||||||
# The schedule to run online backups (see https://crontab.guru/)
|
|
||||||
# every day at 22:00 UTC (default)
|
|
||||||
schedule = "00 22 * * *"
|
|
||||||
# four times a day at 3 minutes past the hour, every 6th hours
|
|
||||||
# schedule = "03 */6 * * *"
|
|
||||||
# We also support non standard cron syntax, with the following format:
|
|
||||||
# sec min hour day of month month day of week year
|
|
||||||
# (it's very similar to the standard cron syntax, it just allows to specify the seconds
|
|
||||||
# at the beginning and the year at the end)
|
|
||||||
# Number of backups to keep (default 7)
|
|
||||||
# versions = 7
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
# 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 {}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/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
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# docker-30
|
|
||||||
|
|
||||||
## taiscale
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Add signing key
|
|
||||||
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/$(lsb_release -cs).noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
|
|
||||||
|
|
||||||
# Add repo
|
|
||||||
echo "deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/tailscale.list
|
|
||||||
|
|
||||||
# Install
|
|
||||||
sudo apt update && sudo apt install tailscale
|
|
||||||
|
|
||||||
# Start
|
|
||||||
sudo tailscale up
|
|
||||||
```
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
## vault-cli install
|
|
||||||
|
|
||||||
```bash
|
|
||||||
VAULT_VERSION="1.21.2"
|
|
||||||
wget https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip
|
|
||||||
unzip vault_${VAULT_VERSION}_linux_amd64.zip
|
|
||||||
sudo mv vault /usr/local/bin/
|
|
||||||
```
|
|
||||||
|
|
||||||
## minio-cli
|
|
||||||
|
|
||||||
```bash
|
|
||||||
wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /tmp/minio-cli
|
|
||||||
chmod +x /tmp/minio-cli
|
|
||||||
sudo mv /tmp/minio-cli /usr/local/bin/minio-cli
|
|
||||||
|
|
||||||
minio-cli alias set synology http://192.168.0.2:9000 k8s ----proper secret here----
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## backup token
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir -p /etc/vault.d/
|
|
||||||
vault policy write backup - <<EOF
|
|
||||||
path "sys/storage/raft/snapshot" {
|
|
||||||
capabilities = ["read"]
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
vault token create -policy=backup -period=8760h -orphan > /etc/vault.d/backup-token
|
|
||||||
chmod 600 /etc/vault.d/backup-token
|
|
||||||
|
|
||||||
```
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"ui": true,
|
|
||||||
"listener": {
|
|
||||||
"tcp": {
|
|
||||||
"address": "0.0.0.0:8200",
|
|
||||||
"tls_disable": "1",
|
|
||||||
"tls_cert_file": "/vault/certs/fullchain.pem",
|
|
||||||
"tls_key_file": "/vault/certs/privkey.pem"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"backend": {
|
|
||||||
"file": {
|
|
||||||
"path": "/vault/data/file"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"default_lease_ttl": "168h",
|
|
||||||
"max_lease_ttl": "0h",
|
|
||||||
"api_addr": "https://vault.hrajfrisbee.cz"
|
|
||||||
// "api_addr": "http://0.0.0.0:8200"
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
services:
|
|
||||||
vault:
|
|
||||||
image: hashicorp/vault:1.21.1
|
|
||||||
container_name: vault
|
|
||||||
restart: unless-stopped
|
|
||||||
cap_add:
|
|
||||||
- IPC_LOCK
|
|
||||||
ports:
|
|
||||||
- 8200:8200
|
|
||||||
environment:
|
|
||||||
- VAULT_ADDR=http://0.0.0.0:8200
|
|
||||||
- VAULT_API_ADDR=http://0.0.0.0:8200
|
|
||||||
- VAULT_ADDRESS=http://0.0.0.0:8200
|
|
||||||
volumes:
|
|
||||||
- ./data:/vault/data
|
|
||||||
- ./config:/vault/config
|
|
||||||
- ./logs:/vault/logs
|
|
||||||
- ./certs:/vault/certs
|
|
||||||
entrypoint: vault
|
|
||||||
command: server -config=/vault/config/vault.json -log-level=debug
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
## 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"
|
|
||||||
|
|
||||||
```
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
## deployment notes
|
|
||||||
|
|
||||||
There was a problem with "production" deployment of Vault through docker container, because default `docker-entrypoint.sh` adds argument saying where dev instance is supposed to listen and then vault crashes because it tries to listen on same port twice.
|
|
||||||
|
|
||||||
Solution: override default entrypoint
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# vault helpers
|
|
||||||
alias set-vault="export VAULT_ADDR=https://docker-30:8200"
|
|
||||||
alias set-vault-ignore-tls="export VAULT_ADDR=https://docker-30:8200; export VAULT_SKIP_VERIFY=true"
|
|
||||||
|
|
||||||
|
|
||||||
export VAULT_ADDR="https://vault.hrajfrisbee.cz"
|
|
||||||
export VAULT_SKIP_VERIFY=true
|
|
||||||
```
|
|
||||||
|
|
||||||
## backup
|
|
||||||
|
|
||||||
Simple file copy initiated by cron, backend storage is minio (s3) running on synology
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo '30 2 * * * root /root/bin/vault-backup.sh >> /var/log/vault-backup.log 2>&1' > /etc/cron.d/vault-backup
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# output role info
|
|
||||||
tofu output -raw role_id
|
|
||||||
tofu output -raw secret_id
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## vault initialization
|
|
||||||
|
|
||||||
```bash
|
|
||||||
|
|
||||||
vault operator init -key-shares=1 -key-threshold=1
|
|
||||||
|
|
||||||
```
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
resource "vault_mount" "kv" {
|
|
||||||
path = "secret"
|
|
||||||
type = "kv-v2"
|
|
||||||
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
|
|
||||||
path "${vault_mount.kv.path}/data/*" {
|
|
||||||
capabilities = ["read"]
|
|
||||||
}
|
|
||||||
path "${vault_mount.kv.path}/metadata/*" {
|
|
||||||
capabilities = ["read", "list"]
|
|
||||||
}
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "vault_approle_auth_backend_role" "eso" {
|
|
||||||
backend = vault_auth_backend.approle.path
|
|
||||||
role_name = "external-secrets"
|
|
||||||
token_policies = [vault_policy.eso_read.name]
|
|
||||||
token_ttl = 3600
|
|
||||||
token_max_ttl = 14400
|
|
||||||
}
|
|
||||||
|
|
||||||
data "vault_approle_auth_backend_role_id" "eso" {
|
|
||||||
backend = vault_auth_backend.approle.path
|
|
||||||
role_name = vault_approle_auth_backend_role.eso.role_name
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "vault_approle_auth_backend_role_secret_id" "eso" {
|
|
||||||
backend = vault_auth_backend.approle.path
|
|
||||||
role_name = vault_approle_auth_backend_role.eso.role_name
|
|
||||||
}
|
|
||||||
|
|
||||||
output "role_id" {
|
|
||||||
value = data.vault_approle_auth_backend_role_id.eso.role_id
|
|
||||||
sensitive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
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
@@ -1,12 +0,0 @@
|
|||||||
terraform {
|
|
||||||
required_providers {
|
|
||||||
vault = {
|
|
||||||
source = "hashicorp/vault"
|
|
||||||
version = "~> 4.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
provider "vault" {
|
|
||||||
# Uses VAULT_ADDR and VAULT_TOKEN from env
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# set -x # Enable debug output
|
|
||||||
|
|
||||||
# --- Configuration ---
|
|
||||||
VAULT_DATA_DIR="${VAULT_DATA_DIR:-/srv/docker/vault/data/}"
|
|
||||||
S3_BUCKET="${S3_BUCKET:-vault-backup}"
|
|
||||||
MC_ALIAS="${MC_ALIAS:-synology}" # Pre-configured mc alias
|
|
||||||
RETENTION_DAYS="${RETENTION_DAYS:-60}"
|
|
||||||
|
|
||||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
|
||||||
BACKUP_FILE="/tmp/vault-backup-${TIMESTAMP}.tar.gz"
|
|
||||||
|
|
||||||
log() { echo "[$(date -Iseconds)] $*"; }
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
rm -f "${BACKUP_FILE}"
|
|
||||||
}
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
# --- Create backup ---
|
|
||||||
log "Backing up ${VAULT_DATA_DIR}..."
|
|
||||||
tar -czf "${BACKUP_FILE}" -C "$(dirname "${VAULT_DATA_DIR}")" "$(basename "${VAULT_DATA_DIR}")"
|
|
||||||
|
|
||||||
BACKUP_SIZE=$(stat -c%s "${BACKUP_FILE}")
|
|
||||||
log "Backup size: ${BACKUP_SIZE} bytes"
|
|
||||||
|
|
||||||
# --- Upload to MinIO ---
|
|
||||||
log "Uploading to ${MC_ALIAS}/${S3_BUCKET}..."
|
|
||||||
set -x
|
|
||||||
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..."
|
|
||||||
minio-cli rm --quiet --recursive --force --older-than "${RETENTION_DAYS}d" "${MC_ALIAS}/${S3_BUCKET}/"
|
|
||||||
|
|
||||||
log "Backup complete: vault-backup-${TIMESTAMP}.tar.gz"
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
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"
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,391 +0,0 @@
|
|||||||
# 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
|
|
||||||
```
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
## 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
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
@@ -1,280 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
## 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"
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
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"
|
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
## 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>"
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
```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'
|
|
||||||
```
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#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
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
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 }
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#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
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#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 -
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,219 +0,0 @@
|
|||||||
## 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
|
|
||||||
```
|
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
## 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
|
|
||||||
```
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,28 +0,0 @@
|
|||||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
|
||||||
kind: HelmRelease
|
|
||||||
metadata:
|
|
||||||
name: external-secrets-crds
|
|
||||||
namespace: external-secrets
|
|
||||||
spec:
|
|
||||||
interval: 1h
|
|
||||||
chart:
|
|
||||||
spec:
|
|
||||||
chart: external-secrets
|
|
||||||
sourceRef:
|
|
||||||
kind: HelmRepository
|
|
||||||
name: external-secrets
|
|
||||||
namespace: flux-system
|
|
||||||
version: "1.2.1"
|
|
||||||
values:
|
|
||||||
installCRDs: true
|
|
||||||
webhook:
|
|
||||||
create: false
|
|
||||||
certController:
|
|
||||||
create: false
|
|
||||||
serviceAccount:
|
|
||||||
create: false
|
|
||||||
resources: {}
|
|
||||||
crds:
|
|
||||||
createClusterExternalSecret: true
|
|
||||||
createClusterSecretStore: true
|
|
||||||
createPushSecret: true
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
apiVersion: source.toolkit.fluxcd.io/v1
|
|
||||||
kind: HelmRepository
|
|
||||||
metadata:
|
|
||||||
name: external-secrets
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 1h
|
|
||||||
url: https://charts.external-secrets.io
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
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
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +0,0 @@
|
|||||||
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"
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
|
||||||
kind: HelmRelease
|
|
||||||
metadata:
|
|
||||||
name: cert-manager
|
|
||||||
namespace: cert-manager
|
|
||||||
spec:
|
|
||||||
interval: 1h
|
|
||||||
chart:
|
|
||||||
spec:
|
|
||||||
chart: cert-manager
|
|
||||||
version: "v1.17.2"
|
|
||||||
sourceRef:
|
|
||||||
kind: HelmRepository
|
|
||||||
name: cert-manager
|
|
||||||
namespace: flux-system
|
|
||||||
install:
|
|
||||||
createNamespace: true
|
|
||||||
crds: CreateReplace
|
|
||||||
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:
|
|
||||||
- |
|
|
||||||
apiVersion: cert-manager.io/v1
|
|
||||||
kind: ClusterIssuer
|
|
||||||
metadata:
|
|
||||||
name: letsencrypt-staging
|
|
||||||
spec:
|
|
||||||
acme:
|
|
||||||
server: https://acme-staging-v02.api.letsencrypt.org/directory
|
|
||||||
email: kacerr.cz+lets-encrypt@gmail.com
|
|
||||||
privateKeySecretRef:
|
|
||||||
name: letsencrypt-staging-account-key
|
|
||||||
solvers:
|
|
||||||
- http01:
|
|
||||||
ingress:
|
|
||||||
ingressClassName: nginx
|
|
||||||
- |
|
|
||||||
apiVersion: cert-manager.io/v1
|
|
||||||
kind: ClusterIssuer
|
|
||||||
metadata:
|
|
||||||
name: letsencrypt-prod
|
|
||||||
spec:
|
|
||||||
acme:
|
|
||||||
server: https://acme-v02.api.letsencrypt.org/directory
|
|
||||||
email: kacerr.cz+lets-encrypt@gmail.com
|
|
||||||
privateKeySecretRef:
|
|
||||||
name: letsencrypt-prod-account-key
|
|
||||||
solvers:
|
|
||||||
- http01:
|
|
||||||
ingress:
|
|
||||||
ingressClassName: nginx
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
apiVersion: source.toolkit.fluxcd.io/v1
|
|
||||||
kind: HelmRepository
|
|
||||||
metadata:
|
|
||||||
name: cert-manager
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 1h
|
|
||||||
url: https://charts.jetstack.io
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: cert-manager
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
apiVersion: cilium.io/v2alpha1
|
|
||||||
kind: CiliumL2AnnouncementPolicy
|
|
||||||
metadata:
|
|
||||||
name: default
|
|
||||||
spec:
|
|
||||||
interfaces:
|
|
||||||
- ^en.* # Match your interfaces
|
|
||||||
loadBalancerIPs: true
|
|
||||||
serviceSelector:
|
|
||||||
matchLabels: {}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
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"
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
---
|
|
||||||
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
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
|
||||||
kind: HelmRelease
|
|
||||||
metadata:
|
|
||||||
name: cilium
|
|
||||||
namespace: kube-system
|
|
||||||
spec:
|
|
||||||
chart:
|
|
||||||
spec:
|
|
||||||
chart: cilium
|
|
||||||
reconcileStrategy: ChartVersion
|
|
||||||
sourceRef:
|
|
||||||
kind: HelmRepository
|
|
||||||
name: cilium
|
|
||||||
namespace: flux-system
|
|
||||||
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:
|
|
||||||
clusterPoolIPv4MaskSize: 24
|
|
||||||
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
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
apiVersion: "cilium.io/v2alpha1"
|
|
||||||
kind: CiliumLoadBalancerIPPool
|
|
||||||
metadata:
|
|
||||||
name: cilium-lb-ipam
|
|
||||||
namespace: kube-system
|
|
||||||
spec:
|
|
||||||
blocks:
|
|
||||||
- start: "192.168.0.35"
|
|
||||||
stop: "192.168.0.39"
|
|
||||||
16
gitops/home-kubernetes/cilium/release.yaml
Normal file
16
gitops/home-kubernetes/cilium/release.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||||
|
kind: HelmRelease
|
||||||
|
metadata:
|
||||||
|
name: cilium
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
chart:
|
||||||
|
spec:
|
||||||
|
chart: cilium
|
||||||
|
reconcileStrategy: ChartVersion
|
||||||
|
sourceRef:
|
||||||
|
kind: HelmRepository
|
||||||
|
name: cilium
|
||||||
|
version: 1.16.5
|
||||||
|
interval: 5m0s
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
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"
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
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"
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
---
|
|
||||||
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
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
---
|
|
||||||
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
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
---
|
|
||||||
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
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
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
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
apiVersion: external-secrets.io/v1
|
|
||||||
kind: ClusterSecretStore
|
|
||||||
metadata:
|
|
||||||
name: vault-backend
|
|
||||||
namespace: external-secrets
|
|
||||||
spec:
|
|
||||||
provider:
|
|
||||||
vault:
|
|
||||||
server: "https://vault.hrajfrisbee.cz"
|
|
||||||
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
|
|
||||||
namespace: external-secrets
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
|
||||||
kind: HelmRelease
|
|
||||||
metadata:
|
|
||||||
name: external-secrets
|
|
||||||
namespace: external-secrets
|
|
||||||
spec:
|
|
||||||
interval: 30m
|
|
||||||
chart:
|
|
||||||
spec:
|
|
||||||
chart: external-secrets
|
|
||||||
version: "1.2.1" # latest stable 1.x
|
|
||||||
sourceRef:
|
|
||||||
kind: HelmRepository
|
|
||||||
name: external-secrets
|
|
||||||
namespace: flux-system
|
|
||||||
install:
|
|
||||||
createNamespace: true
|
|
||||||
remediation:
|
|
||||||
retries: 3
|
|
||||||
upgrade:
|
|
||||||
remediation:
|
|
||||||
retries: 3
|
|
||||||
values:
|
|
||||||
replicaCount: 1
|
|
||||||
leaderElect: true
|
|
||||||
|
|
||||||
# Resources (adjust to your cluster)
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 50m
|
|
||||||
memory: 128Mi
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
|
|
||||||
webhook:
|
|
||||||
replicaCount: 1
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 25m
|
|
||||||
memory: 64Mi
|
|
||||||
limits:
|
|
||||||
memory: 128Mi
|
|
||||||
podDisruptionBudget:
|
|
||||||
enabled: true
|
|
||||||
minAvailable: 1
|
|
||||||
|
|
||||||
certController:
|
|
||||||
replicaCount: 1
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 25m
|
|
||||||
memory: 64Mi
|
|
||||||
limits:
|
|
||||||
memory: 128Mi
|
|
||||||
|
|
||||||
# Metrics (enable if prometheus-operator is present)
|
|
||||||
serviceMonitor:
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
# Pod disruption budgets
|
|
||||||
podDisruptionBudget:
|
|
||||||
enabled: true
|
|
||||||
minAvailable: 1
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: external-secrets
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
name: vault-approle
|
|
||||||
namespace: external-secrets
|
|
||||||
annotations:
|
|
||||||
kustomize.toolkit.fluxcd.io/reconcile: disabled
|
|
||||||
type: Opaque
|
|
||||||
stringData:
|
|
||||||
secret-id: --- fill in the secret_id ---
|
|
||||||
@@ -1,32 +1,6 @@
|
|||||||
---
|
---
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
|
||||||
name: 00-crds
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 10m0s
|
|
||||||
path: ./gitops/home-kubernetes/00-crds
|
|
||||||
prune: true
|
|
||||||
sourceRef:
|
|
||||||
kind: GitRepository
|
|
||||||
name: flux-system
|
|
||||||
---
|
|
||||||
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:
|
metadata:
|
||||||
name: cilium
|
name: cilium
|
||||||
namespace: flux-system
|
namespace: flux-system
|
||||||
@@ -40,47 +14,6 @@ spec:
|
|||||||
---
|
---
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
|
||||||
name: cert-manager
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 10m0s
|
|
||||||
path: ./gitops/home-kubernetes/cert-manager
|
|
||||||
prune: true
|
|
||||||
sourceRef:
|
|
||||||
kind: GitRepository
|
|
||||||
name: flux-system
|
|
||||||
---
|
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
|
||||||
name: external-secrets
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 10m0s
|
|
||||||
path: ./gitops/home-kubernetes/external-secrets
|
|
||||||
prune: true
|
|
||||||
sourceRef:
|
|
||||||
kind: GitRepository
|
|
||||||
name: flux-system
|
|
||||||
dependsOn:
|
|
||||||
- name: 00-crds
|
|
||||||
---
|
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
|
||||||
name: kube-prometheus
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 10m0s
|
|
||||||
path: ./gitops/home-kubernetes/kube-prometheus
|
|
||||||
prune: true
|
|
||||||
sourceRef:
|
|
||||||
kind: GitRepository
|
|
||||||
name: flux-system
|
|
||||||
---
|
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
metadata:
|
||||||
name: ingress-nginx
|
name: ingress-nginx
|
||||||
namespace: flux-system
|
namespace: flux-system
|
||||||
@@ -95,50 +28,11 @@ spec:
|
|||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
name: oauth-proxy
|
name: kuard
|
||||||
namespace: flux-system
|
namespace: flux-system
|
||||||
spec:
|
spec:
|
||||||
interval: 10m0s
|
interval: 10m0s
|
||||||
path: ./gitops/home-kubernetes/oauth-proxy
|
path: ./gitops/home-kubernetes/kuard
|
||||||
prune: true
|
|
||||||
sourceRef:
|
|
||||||
kind: GitRepository
|
|
||||||
name: flux-system
|
|
||||||
---
|
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
|
||||||
name: podinfo
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 10m0s
|
|
||||||
path: ./gitops/home-kubernetes/podinfo
|
|
||||||
prune: true
|
|
||||||
sourceRef:
|
|
||||||
kind: GitRepository
|
|
||||||
name: flux-system
|
|
||||||
---
|
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
|
||||||
name: plane
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 10m0s
|
|
||||||
path: ./gitops/home-kubernetes/plane
|
|
||||||
prune: true
|
|
||||||
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
|
prune: true
|
||||||
sourceRef:
|
sourceRef:
|
||||||
kind: GitRepository
|
kind: GitRepository
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ spec:
|
|||||||
branch: main
|
branch: main
|
||||||
secretRef:
|
secretRef:
|
||||||
name: flux-system
|
name: flux-system
|
||||||
url: https://gitea.home.hrajfrisbee.cz/kacerr/home-kubernetes
|
url: https://gitlab.hrajfrisbee.cz/infrastructure/home-kubernetes.git
|
||||||
---
|
---
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
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"
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
---
|
|
||||||
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
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
---
|
|
||||||
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
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
---
|
|
||||||
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
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: fuj
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
data:
|
|
||||||
credentials.json: ewogICAgInR5cGUiOiAic2VydmljZV9hY2NvdW50IiwKICAgICJwcm9qZWN0X2lkIjogInBsYXRlZC1tZXNoLTQ4OTAxMC1zMSIsCiAgICAicHJpdmF0ZV9rZXlfaWQiOiAiYzQxM2VhYWUzMzk0NGFmZDljZjkyZjgzNGYzYmM1NDM5OGI1ZGY5YyIsCiAgICAicHJpdmF0ZV9rZXkiOiAiLS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tXG5NSUlFdmdJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLZ3dnZ1NrQWdFQUFvSUJBUURuTzBJQ3p2NDNaMWFKXG5MYi9NSkFZbld2U2NWM2tlelBGSHpHNVd2WUE3SXBxM2ZkcUp6ZWYxSzcxeGJodGY5NFB6T2RNVGdrYXcxcmZYXG40QjhOMS9laWFZaWUyZkkwenA4emptejl0YnpDUjVwM0hiK3M0eHROR3hVUDJBWWQzVmRrbE5TRFlacGJ5Qm8rXG5qNWl1cy9BOXdYV1ZkQ2EvNnA1MmtYSU1Ld3o4b05rbmpMRTlzV21ZV1kvQmJZT1o0UExPSjNTWEdEMFJNQzlGXG4wbjBLUDJTRWxvaTFPc2wvV2s0Q21WazJFc0lNSjBiMHA1Wm1GZUZ6SlAzSFZUS0VtOExHam5vWjVwQmwzWGM0XG5GOThKSVFFQzZQallOcXQvSFlxdWRLb2hrelVSS2h5ekVJdHp3NXBrUnk3d1l1OGJHSGJOMzF0dWFpeDRMdFNjXG5zYU5oOHJhVEFnTUJBQUVDZ2dFQWFXZ2U4RTdSbmdueWJiZzRMV1BpbGtBbEw3dkVUK0VXd0NjVnlWNjdQTG5LXG5rNGpBZlg4cWxSMnFUekhsTXJzUElHb2txVWtDMW93YTVFS2JoV0VFMXJtSytQYmJMVzFmTDA1bXFzVVUxZTkwXG5INGFsSUxlcWMxeThIaXZZcGZhSFp5ZGROTUxpYmFKckxFZWpUMGhoWkpWeTkzMHFTT1EzOWs3WkVXanlrNW9WXG5WcUk2SE4yVGUrRTN0aklmNFcrN0lKN0c3RU9ZVG4zZHlrQnZCN1QwLzR2M0pUeGMzTk1IN0RZYzFyd1dicEdKXG5JcmNidndOa3VyVHhsdWg1VGtvSkZjd3ZXdEl4NE52MFFPNkk5TlpjMllPakZUMncwMUFrKzNDSTJLNmJOVE9qXG43WWFxYlRoNDk2cU1Md2NtRmFUZy9tbXEzMGZycEVsMWdQTWJWZFJqTVFLQmdRRDY3SDMvb0pGU1ZDWnFYQjFEXG5tdHZRblVMSWUvZkU5TXc4T2VrcUdMclQxbGlUTllhTks4YnRsOGFrbFlZY3FXU09zWk53ZkdyNmNhOGhUSEwyXG5pWXZNbkR4aVJPWkVkeElPUFJGY2l4SlNpdG5hb3kzSmtMMml0K2cxMUVGdUEyS3dGd29jc0RrRkQ1QTh0ZEFpXG5UOGhEeEc4dE5saFFrTUY0ekRMNTE2cHRLUUtCZ1FEcjZNZitLelBoNHM2Qm1GVzkrUzNtZEFZZkJETkJsZHJrXG56L1hrY2NteHNWeUpNNTErR2MzY3kzYmhIRDU4aGVLb3U1ZHdYanNqZkRCZlZKcjBpTHM0R3dGbjNlWlJYNmluXG5NVmlycmpyUWt5WnlSVDJkcHl5ODQ5MGN1WC9xQ01hbTVRYzY0UmpJN3JhRTM5ZDBRcnRRd0hWbnZCN1RHaEcvXG50WElXeThMQld3S0JnRGRtMi9NQyt0TVlyVnF5ZCt1alY0RmFGNUs0ZkY1S1JvWE5xNE9WN2pvemkxOEZaRzNyXG5Db01QRGRidEJLMXpZVFo0VXJ0MVhSRnE1R1lQd1JwYUNEbm5EUllOYkdJVmdERVFucksyS2hkN2ZOcGZTUTdHXG5ISGkrN2xCa1N3WUZUVmJmMzJXeUt3VEpDT20rb3ZQUWRjRXdyL05sbWw0L2Q5ZzZEYzlJSk9MeEFvR0JBTi9yXG5QaGwwN0hRV0VpbFViTjQ3TEdRMzhLOTBEeXJMa00vcXpOMGZYSEM3aHJmOE5CdERadkdTZHE1SlhzNVhUc01WXG4vREorWHVmWnN4aHBlQU52M1RUdC9UR1hvRXZRM29hRUFrUkN4alMvMTVoVFBKN3QxVHNkbGZ6ejNnUklmRFpoXG40YkR6ZzlFRk5GMS9Fa1NhS3E0Rlgrc3MxcDFOZTFkYVpJWmF0ZXROQW9HQkFLeStZTGRjQVh6dElaMTkvS0wwXG5sWTBPZi92azVJNUtKNlNiVUVheU9HTFJkWTJBdGk1R1QwQlpjVEV3QjYzWTNyWEVNQ3BsM25Ca1pVRklRczNEXG5wSE9DUDdDMXQ3STRSZlBGaGlSTzEvQnVsajZjUXNrUHFJWlpadGxOQjdROG1BVEttMnpXVThZTjRNbFhZSVBVXG5naGRrZHVQRWIyRC9ueDl3U3F2NzdUeWJcbi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS1cbiIsCiAgICAiY2xpZW50X2VtYWlsIjogImZ1ai1tYW5hZ2VtZW50LWJvdEBwbGF0ZWQtbWVzaC00ODkwMTAtczEuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLAogICAgImNsaWVudF9pZCI6ICIxMDM0ODY2MjM3NTQxOTMzODgxMzQiLAogICAgImF1dGhfdXJpIjogImh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi9hdXRoIiwKICAgICJ0b2tlbl91cmkiOiAiaHR0cHM6Ly9vYXV0aDIuZ29vZ2xlYXBpcy5jb20vdG9rZW4iLAogICAgImF1dGhfcHJvdmlkZXJfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9vYXV0aDIvdjEvY2VydHMiLAogICAgImNsaWVudF94NTA5X2NlcnRfdXJsIjogImh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3JvYm90L3YxL21ldGFkYXRhL3g1MDkvZnVqLW1hbmFnZW1lbnQtYm90JTQwcGxhdGVkLW1lc2gtNDg5MDEwLXMxLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwKICAgICJ1bml2ZXJzZV9kb21haW4iOiAiZ29vZ2xlYXBpcy5jb20iCn0=
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
name: fuj-management-bot-credentials
|
|
||||||
namespace: fuj
|
|
||||||
type: Opaque
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: fujarna
|
|
||||||
namespace: fuj
|
|
||||||
spec:
|
|
||||||
type: ClusterIP
|
|
||||||
selector:
|
|
||||||
app: fujarna
|
|
||||||
ports:
|
|
||||||
- port: 80
|
|
||||||
targetPort: 8080
|
|
||||||
protocol: TCP
|
|
||||||
name: http
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: ghost-on-kubernetes
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/name: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/version: '6.0'
|
|
||||||
app.kubernetes.io/component: namespace
|
|
||||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
apiVersion: external-secrets.io/v1
|
|
||||||
kind: ExternalSecret
|
|
||||||
metadata:
|
|
||||||
name: ghost-config
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
spec:
|
|
||||||
refreshInterval: 1h
|
|
||||||
secretStoreRef:
|
|
||||||
name: vault-backend
|
|
||||||
kind: ClusterSecretStore
|
|
||||||
target:
|
|
||||||
name: ghost-config
|
|
||||||
data:
|
|
||||||
- secretKey: gmail-app-password
|
|
||||||
remoteRef:
|
|
||||||
key: k8s_home/ghost # Vault path (without 'data/' prefix)
|
|
||||||
property: gmail-app-password
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
apiVersion: external-secrets.io/v1
|
|
||||||
kind: ExternalSecret
|
|
||||||
metadata:
|
|
||||||
name: ghost-on-kubernetes-mysql-env
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
spec:
|
|
||||||
refreshInterval: 1h
|
|
||||||
secretStoreRef:
|
|
||||||
name: vault-backend
|
|
||||||
kind: ClusterSecretStore
|
|
||||||
target:
|
|
||||||
name: ghost-on-kubernetes-mysql-env # resulting K8s secret name
|
|
||||||
data:
|
|
||||||
- secretKey: MYSQL_DATABASE # key in K8s secret
|
|
||||||
remoteRef:
|
|
||||||
key: k8s_home/ghost # Vault path (without 'data/' prefix)
|
|
||||||
property: mysql-db-name # field within Vault secret
|
|
||||||
- secretKey: MYSQL_USER # key in K8s secret
|
|
||||||
remoteRef:
|
|
||||||
key: k8s_home/ghost
|
|
||||||
property: mysql-db-user
|
|
||||||
- secretKey: MYSQL_PASSWORD
|
|
||||||
remoteRef:
|
|
||||||
key: k8s_home/ghost
|
|
||||||
property: mysql-db-password
|
|
||||||
- secretKey: MYSQL_ROOT_PASSWORD
|
|
||||||
remoteRef:
|
|
||||||
key: k8s_home/ghost
|
|
||||||
property: mysql-db-root-password
|
|
||||||
- secretKey: MYSQL_HOST
|
|
||||||
remoteRef:
|
|
||||||
key: k8s_home/ghost
|
|
||||||
property: mysql-host
|
|
||||||
|
|
||||||
|
|
||||||
# type: Opaque
|
|
||||||
# stringData:
|
|
||||||
# MYSQL_DATABASE: mysql-db-name # Same as in config.production.json
|
|
||||||
# MYSQL_USER: mysql-db-user # Same as in config.production.json
|
|
||||||
# MYSQL_PASSWORD: mysql-db-password # Same as in config.production.json
|
|
||||||
# MYSQL_ROOT_PASSWORD: mysql-db-root-password # Same as in config.production.json
|
|
||||||
# MYSQL_HOST: '%' # Same as in config.production.json
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
name: ghost-on-kubernetes-mysql-env
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes-mysql
|
|
||||||
app.kubernetes.io/name: ghost-on-kubernetes-mysql-env
|
|
||||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/version: '6.0'
|
|
||||||
app.kubernetes.io/component: database-secret
|
|
||||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
|
||||||
|
|
||||||
type: Opaque
|
|
||||||
stringData:
|
|
||||||
MYSQL_DATABASE: mysql-db-name # Same as in config.production.json
|
|
||||||
MYSQL_USER: mysql-db-user # Same as in config.production.json
|
|
||||||
MYSQL_PASSWORD: mysql-db-password # Same as in config.production.json
|
|
||||||
MYSQL_ROOT_PASSWORD: mysql-db-root-password # Same as in config.production.json
|
|
||||||
MYSQL_HOST: '%' # Same as in config.production.json
|
|
||||||
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
name: tls-secret
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/name: tls-secret
|
|
||||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/version: '6.0'
|
|
||||||
app.kubernetes.io/component: tls-secret
|
|
||||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
|
||||||
|
|
||||||
|
|
||||||
type: kubernetes.io/tls
|
|
||||||
stringData:
|
|
||||||
tls.crt: content-tls-crt-base64 # Optional, if you want to use your own TLS certificate
|
|
||||||
tls.key: content-tls-key-base64 # Optional, if you want to use your own TLS certificate
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
metadata:
|
|
||||||
name: k8s-ghost-content
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/name: k8s-ghost-content
|
|
||||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/version: '6.0'
|
|
||||||
app.kubernetes.io/component: storage
|
|
||||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
|
||||||
|
|
||||||
spec:
|
|
||||||
# Change this to your storageClassName, we suggest using a storageClassName that supports ReadWriteMany for production.
|
|
||||||
storageClassName: freenas-iscsi
|
|
||||||
volumeMode: Filesystem
|
|
||||||
# Change this to your accessModes. We suggest ReadWriteMany for production, ReadWriteOnce for development.
|
|
||||||
# With ReadWriteMany, you can have multiple replicas of Ghost, so you can achieve high availability.
|
|
||||||
# Note that ReadWriteMany is not supported by all storage providers and may require additional configuration.
|
|
||||||
# Ghost officialy doesn't support HA, they suggest using a CDN or caching. Info: https://ghost.org/docs/faq/clustering-sharding-multi-server/
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce # Change this to your accessModes if needed, we suggest ReadWriteMany so we can scale the deployment later.
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 1Gi
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
metadata:
|
|
||||||
name: ghost-on-kubernetes-mysql-pvc
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes-mysql
|
|
||||||
app.kubernetes.io/name: ghost-on-kubernetes-mysql-pvc
|
|
||||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/version: '6.0'
|
|
||||||
app.kubernetes.io/component: database-storage
|
|
||||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
|
||||||
|
|
||||||
|
|
||||||
spec:
|
|
||||||
storageClassName: freenas-iscsi
|
|
||||||
volumeMode: Filesystem
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 1Gi
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: ghost-on-kubernetes-service
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/name: ghost-on-kubernetes-service
|
|
||||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/version: '6.0'
|
|
||||||
app.kubernetes.io/component: service-frontend
|
|
||||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
|
||||||
|
|
||||||
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 2368
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: ghk8s
|
|
||||||
name: ghk8s
|
|
||||||
type: ClusterIP
|
|
||||||
selector:
|
|
||||||
app: ghost-on-kubernetes
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: ghost-on-kubernetes-mysql-service
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes-mysql
|
|
||||||
app.kubernetes.io/name: ghost-on-kubernetes-mysql-service
|
|
||||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/version: '6.0'
|
|
||||||
app.kubernetes.io/component: service-database
|
|
||||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
|
||||||
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 3306
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: mysqlgh
|
|
||||||
name: mysqlgh
|
|
||||||
type: ClusterIP
|
|
||||||
clusterIP: None
|
|
||||||
selector:
|
|
||||||
app: ghost-on-kubernetes-mysql
|
|
||||||
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
name: ghost-config-prod
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/name: ghost-config-prod
|
|
||||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/version: '6.0'
|
|
||||||
app.kubernetes.io/component: ghost-config
|
|
||||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
|
||||||
type: Opaque
|
|
||||||
stringData:
|
|
||||||
config.production.json: |-
|
|
||||||
{
|
|
||||||
"url": "https://ghost.lab.home.hrajfrisbee.cz",
|
|
||||||
"admin": {
|
|
||||||
"url": "https://ghost.lab.home.hrajfrisbee.cz"
|
|
||||||
},
|
|
||||||
"server": {
|
|
||||||
"port": 2368,
|
|
||||||
"host": "0.0.0.0"
|
|
||||||
},
|
|
||||||
"mail": {
|
|
||||||
"transport": "SMTP",
|
|
||||||
"from": "user@server.com",
|
|
||||||
"options": {
|
|
||||||
"service": "Google",
|
|
||||||
"host": "smtp.gmail.com",
|
|
||||||
"port": 465,
|
|
||||||
"secure": true,
|
|
||||||
"auth": {
|
|
||||||
"user": "user@server.com",
|
|
||||||
"pass": "passsword"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"logging": {
|
|
||||||
"transports": [
|
|
||||||
"stdout"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"database": {
|
|
||||||
"client": "mysql",
|
|
||||||
"connection":
|
|
||||||
{
|
|
||||||
"host": "ghost-on-kubernetes-mysql-service",
|
|
||||||
"user": "mysql-db-user",
|
|
||||||
"password": "mysql-db-password",
|
|
||||||
"database": "mysql-db-name",
|
|
||||||
"port": "3306"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"process": "local",
|
|
||||||
"paths": {
|
|
||||||
"contentPath": "/home/nonroot/app/ghost/content"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: StatefulSet
|
|
||||||
metadata:
|
|
||||||
name: ghost-on-kubernetes-mysql
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes-mysql
|
|
||||||
app.kubernetes.io/name: ghost-on-kubernetes-mysql
|
|
||||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/version: '6.0'
|
|
||||||
app.kubernetes.io/component: database
|
|
||||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
|
||||||
|
|
||||||
spec:
|
|
||||||
serviceName: ghost-on-kubernetes-mysql-service
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: ghost-on-kubernetes-mysql
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes-mysql
|
|
||||||
spec:
|
|
||||||
initContainers:
|
|
||||||
- name: ghost-on-kubernetes-mysql-init
|
|
||||||
securityContext:
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
privileged: false
|
|
||||||
readOnlyRootFilesystem: true
|
|
||||||
image: docker.io/busybox:stable-musl
|
|
||||||
imagePullPolicy: Always # You can change this value according to your needs
|
|
||||||
command:
|
|
||||||
- /bin/sh
|
|
||||||
- -c
|
|
||||||
- |
|
|
||||||
set -e
|
|
||||||
echo 'Changing ownership of mysql mount directory to 65534:65534'
|
|
||||||
chown -Rfv 65534:65534 /mnt/mysql || echo 'Error changing ownership of mysql mount directory to 65534:65534'
|
|
||||||
echo 'Changing ownership of tmp mount directory to 65534:65534'
|
|
||||||
chown -Rfv 65534:65534 /mnt/tmp || echo 'Error changing ownership of tmp mount directory to 65534:65534'
|
|
||||||
echo 'Changing ownership of socket mount directory to 65534:65534'
|
|
||||||
chown -Rfv 65534:65534 /mnt/var/run/mysqld || echo 'Error changing ownership of socket mount directory to 65534:65534'
|
|
||||||
|
|
||||||
|
|
||||||
volumeMounts:
|
|
||||||
- name: ghost-on-kubernetes-mysql-volume
|
|
||||||
mountPath: /mnt/mysql
|
|
||||||
subPath: mysql-empty-subdir
|
|
||||||
readOnly: false
|
|
||||||
|
|
||||||
- name: ghost-on-kubernetes-mysql-tmp
|
|
||||||
mountPath: /mnt/tmp
|
|
||||||
readOnly: false
|
|
||||||
|
|
||||||
- name: ghost-on-kubernetes-mysql-socket
|
|
||||||
mountPath: /mnt/var/run/mysqld
|
|
||||||
readOnly: false
|
|
||||||
|
|
||||||
# YOu can ajust the resources according to your needs
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
memory: 0Mi
|
|
||||||
cpu: 0m
|
|
||||||
limits:
|
|
||||||
memory: 1Gi
|
|
||||||
cpu: 900m
|
|
||||||
|
|
||||||
containers:
|
|
||||||
- name: ghost-on-kubernetes-mysql
|
|
||||||
securityContext:
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
privileged: false
|
|
||||||
readOnlyRootFilesystem: true
|
|
||||||
runAsNonRoot: true
|
|
||||||
runAsUser: 65534
|
|
||||||
|
|
||||||
image: docker.io/mysql:8.4
|
|
||||||
imagePullPolicy: Always # You can change this value according to your needs
|
|
||||||
envFrom:
|
|
||||||
- secretRef:
|
|
||||||
name: ghost-on-kubernetes-mysql-env
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
memory: 500Mi # You can change this value according to your needs
|
|
||||||
cpu: 300m # You can change this value according to your needs
|
|
||||||
limits:
|
|
||||||
memory: 1Gi # You can change this value according to your needs
|
|
||||||
cpu: 900m # You can change this value according to your needs
|
|
||||||
ports:
|
|
||||||
- containerPort: 3306
|
|
||||||
protocol: TCP
|
|
||||||
name: mysqlgh
|
|
||||||
volumeMounts:
|
|
||||||
- name: ghost-on-kubernetes-mysql-volume
|
|
||||||
mountPath: /var/lib/mysql
|
|
||||||
subPath: mysql-empty-subdir
|
|
||||||
readOnly: false
|
|
||||||
|
|
||||||
- name: ghost-on-kubernetes-mysql-tmp
|
|
||||||
mountPath: /tmp
|
|
||||||
readOnly: false
|
|
||||||
|
|
||||||
- name: ghost-on-kubernetes-mysql-socket
|
|
||||||
mountPath: /var/run/mysqld
|
|
||||||
readOnly: false
|
|
||||||
|
|
||||||
automountServiceAccountToken: false
|
|
||||||
|
|
||||||
# Optional: Uncomment the following to specify node selectors
|
|
||||||
# affinity:
|
|
||||||
# nodeAffinity:
|
|
||||||
# requiredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
# nodeSelectorTerms:
|
|
||||||
# - matchExpressions:
|
|
||||||
# - key: node-role.kubernetes.io/worker
|
|
||||||
# operator: In
|
|
||||||
# values:
|
|
||||||
# - 'true'
|
|
||||||
|
|
||||||
securityContext:
|
|
||||||
seccompProfile:
|
|
||||||
type: RuntimeDefault
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
- name: ghost-on-kubernetes-mysql-volume
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: ghost-on-kubernetes-mysql-pvc
|
|
||||||
- name: ghost-on-kubernetes-mysql-tmp
|
|
||||||
emptyDir:
|
|
||||||
sizeLimit: 128Mi
|
|
||||||
- name: ghost-on-kubernetes-mysql-socket
|
|
||||||
emptyDir:
|
|
||||||
sizeLimit: 128Mi
|
|
||||||
@@ -1,214 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: ghost-on-kubernetes
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/name: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/instance: ghost-on-kubernetes
|
|
||||||
app.kubernetes.io/version: '6.0'
|
|
||||||
app.kubernetes.io/component: ghost
|
|
||||||
app.kubernetes.io/part-of: ghost-on-kubernetes
|
|
||||||
|
|
||||||
|
|
||||||
spec:
|
|
||||||
# If you want HA for your Ghost instance, you can increase the number of replicas AFTER creation and you need to adjust the storage class. See 02-pvc.yaml for more information.
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: ghost-on-kubernetes
|
|
||||||
minReadySeconds: 5
|
|
||||||
strategy:
|
|
||||||
type: RollingUpdate
|
|
||||||
rollingUpdate:
|
|
||||||
maxUnavailable: 0
|
|
||||||
maxSurge: 3
|
|
||||||
revisionHistoryLimit: 4
|
|
||||||
progressDeadlineSeconds: 600
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
namespace: ghost-on-kubernetes
|
|
||||||
labels:
|
|
||||||
app: ghost-on-kubernetes
|
|
||||||
spec:
|
|
||||||
automountServiceAccountToken: false # Disable automounting of service account token
|
|
||||||
volumes:
|
|
||||||
- name: k8s-ghost-content
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: k8s-ghost-content
|
|
||||||
|
|
||||||
- name: ghost-config-prod
|
|
||||||
secret:
|
|
||||||
secretName: ghost-config-prod
|
|
||||||
defaultMode: 420
|
|
||||||
|
|
||||||
- name: tmp
|
|
||||||
emptyDir:
|
|
||||||
sizeLimit: 64Mi
|
|
||||||
|
|
||||||
initContainers:
|
|
||||||
- name: permissions-fix
|
|
||||||
imagePullPolicy: Always
|
|
||||||
image: docker.io/busybox:stable-musl
|
|
||||||
env:
|
|
||||||
- name: GHOST_INSTALL
|
|
||||||
value: /home/nonroot/app/ghost
|
|
||||||
- name: GHOST_CONTENT
|
|
||||||
value: /home/nonroot/app/ghost/content
|
|
||||||
- name: NODE_ENV
|
|
||||||
value: production
|
|
||||||
securityContext:
|
|
||||||
readOnlyRootFilesystem: true
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpu: 900m
|
|
||||||
memory: 1000Mi
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 128Mi
|
|
||||||
command:
|
|
||||||
- /bin/sh
|
|
||||||
- '-c'
|
|
||||||
- |
|
|
||||||
set -e
|
|
||||||
|
|
||||||
export DIRS='files logs apps themes data public settings images media'
|
|
||||||
echo 'Check if base dirs exists, if not, create them'
|
|
||||||
echo "Directories to check: $DIRS"
|
|
||||||
for dir in $DIRS; do
|
|
||||||
if [ ! -d $GHOST_CONTENT/$dir ]; then
|
|
||||||
echo "Creating $GHOST_CONTENT/$dir directory"
|
|
||||||
mkdir -pv $GHOST_CONTENT/$dir || echo "Error creating $GHOST_CONTENT/$dir directory"
|
|
||||||
fi
|
|
||||||
chown -Rfv 65532:65532 $GHOST_CONTENT/$dir && echo "chown ok on $dir" || echo "Error changing ownership of $GHOST_CONTENT/$dir directory"
|
|
||||||
done
|
|
||||||
exit 0
|
|
||||||
|
|
||||||
|
|
||||||
volumeMounts:
|
|
||||||
- name: k8s-ghost-content
|
|
||||||
mountPath: /home/nonroot/app/ghost/content
|
|
||||||
readOnly: false
|
|
||||||
|
|
||||||
containers:
|
|
||||||
- name: ghost-on-kubernetes
|
|
||||||
# For development, you can use the following image:
|
|
||||||
# image: ghcr.io/sredevopsorg/ghost-on-kubernetes:latest-dev
|
|
||||||
# image: ghcr.io/sredevopsorg/ghost-on-kubernetes:main
|
|
||||||
image: ghost:bookworm
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- name: ghk8s
|
|
||||||
containerPort: 2368
|
|
||||||
protocol: TCP
|
|
||||||
|
|
||||||
# You should uncomment the following lines in production. Change the values according to your environment.
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /ghost/api/v4/admin/site/
|
|
||||||
port: ghk8s
|
|
||||||
httpHeaders:
|
|
||||||
- name: X-Forwarded-Proto
|
|
||||||
value: https
|
|
||||||
- name: Host
|
|
||||||
value: ghost.lab.home.hrajfrisbee.cz
|
|
||||||
periodSeconds: 10
|
|
||||||
timeoutSeconds: 3
|
|
||||||
successThreshold: 1
|
|
||||||
failureThreshold: 3
|
|
||||||
initialDelaySeconds: 10
|
|
||||||
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /ghost/api/v4/admin/site/
|
|
||||||
port: ghk8s
|
|
||||||
httpHeaders:
|
|
||||||
- name: X-Forwarded-Proto
|
|
||||||
value: https
|
|
||||||
- name: Host
|
|
||||||
value: ghost.lab.home.hrajfrisbee.cz
|
|
||||||
periodSeconds: 300
|
|
||||||
timeoutSeconds: 3
|
|
||||||
successThreshold: 1
|
|
||||||
failureThreshold: 1
|
|
||||||
initialDelaySeconds: 30
|
|
||||||
|
|
||||||
env:
|
|
||||||
- name: NODE_ENV
|
|
||||||
value: production
|
|
||||||
- name: url
|
|
||||||
value: "https://ghost.lab.home.hrajfrisbee.cz"
|
|
||||||
- name: database__client
|
|
||||||
value: "mysql"
|
|
||||||
- name: database__connection__host
|
|
||||||
value: "ghost-on-kubernetes-mysql-service"
|
|
||||||
- name: database__connection__port
|
|
||||||
value: "3306"
|
|
||||||
- name: database__connection__user
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: ghost-on-kubernetes-mysql-env
|
|
||||||
key: MYSQL_USER
|
|
||||||
- name: database__connection__password
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: ghost-on-kubernetes-mysql-env
|
|
||||||
key: MYSQL_PASSWORD
|
|
||||||
- name: database__connection__database
|
|
||||||
value: "ghost"
|
|
||||||
- name: mail__transport
|
|
||||||
value: "SMTP"
|
|
||||||
- name: mail__options__service
|
|
||||||
value: "Gmail"
|
|
||||||
- name: mail__options__auth__user
|
|
||||||
value: "kacerr.cz@gmail.com"
|
|
||||||
- name: mail__options__auth__pass
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: ghost-config
|
|
||||||
key: gmail-app-password
|
|
||||||
- name: mail__from
|
|
||||||
value: "'Kacerr's Blog' <kacerr.cz@gmail.com>"
|
|
||||||
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpu: 800m
|
|
||||||
memory: 800Mi
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 256Mi
|
|
||||||
|
|
||||||
volumeMounts:
|
|
||||||
- name: k8s-ghost-content
|
|
||||||
mountPath: /home/nonroot/app/ghost/content
|
|
||||||
readOnly: false
|
|
||||||
- name: ghost-config-prod
|
|
||||||
readOnly: true
|
|
||||||
mountPath: /home/nonroot/app/ghost/config.production.json
|
|
||||||
subPath: config.production.json
|
|
||||||
- name: tmp # This is the temporary volume mount to allow loading themes
|
|
||||||
mountPath: /tmp
|
|
||||||
readOnly: false
|
|
||||||
securityContext:
|
|
||||||
readOnlyRootFilesystem: true
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
runAsNonRoot: true
|
|
||||||
runAsUser: 65532
|
|
||||||
|
|
||||||
|
|
||||||
restartPolicy: Always
|
|
||||||
terminationGracePeriodSeconds: 15
|
|
||||||
dnsPolicy: ClusterFirst
|
|
||||||
# Optional: Uncomment the following to specify node selectors
|
|
||||||
# affinity:
|
|
||||||
# nodeAffinity:
|
|
||||||
# requiredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
# nodeSelectorTerms:
|
|
||||||
# - matchExpressions:
|
|
||||||
# - key: node-role.kubernetes.io/worker
|
|
||||||
# operator: In
|
|
||||||
# values:
|
|
||||||
# - 'true'
|
|
||||||
securityContext: {}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
---
|
|
||||||
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
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user