diff --git a/.github/workflows/openclaw-docker.yml b/.github/workflows/openclaw-docker.yml deleted file mode 100644 index 5be2f9d..0000000 --- a/.github/workflows/openclaw-docker.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: Build and Push openclaw Docker Image - -on: - push: - branches: - - main - - master - paths: - - 'docker/openclaw/**' - - '.github/workflows/openclaw-docker.yml' - workflow_dispatch: - inputs: - force_rebuild: - description: 'Force rebuild' - required: false - default: 'false' - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }}/openclaw - -jobs: - build-and-push: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata (tags, labels) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=sha,prefix={{branch}}- - type=ref,event=branch - type=raw,value=latest,enable={{is_default_branch}} - - - name: Build and push Docker image - id: build - uses: docker/build-push-action@v5 - with: - context: ./docker/openclaw - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - platforms: linux/amd64 - - - name: Image digest - run: echo "Image pushed with digest ${{ steps.build.outputs.digest }}" diff --git a/ai/README.md b/ai/README.md new file mode 100644 index 0000000..42b8891 --- /dev/null +++ b/ai/README.md @@ -0,0 +1,108 @@ +# AI Namespace - ArgoCD Managed + +This directory contains Kubernetes manifests for the `ai` namespace. + +## 🔄 ArgoCD Integration + +All YAML files in this directory are automatically deployed to the K3s cluster by ArgoCD. + +## 📝 Adding New Applications + +1. Create your Kubernetes manifest files (deployment, service, ingress, etc.) +2. Place them in this directory +3. Commit and push to Git +4. ArgoCD will automatically detect and deploy the changes + +## 🏷️ Namespace + +All resources in this directory will be deployed to the **`ai` namespace**. + +## 📋 Examples + +### Deployment Example +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-ai-app + namespace: ai +spec: + replicas: 1 + selector: + matchLabels: + app: my-ai-app + template: + metadata: + labels: + app: my-ai-app + spec: + containers: + - name: my-ai-app + image: my-image:latest + ports: + - containerPort: 8080 +``` + +### Service Example +```yaml +apiVersion: v1 +kind: Service +metadata: + name: my-ai-app + namespace: ai +spec: + selector: + app: my-ai-app + ports: + - port: 80 + targetPort: 8080 +``` + +### Ingress Example +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: my-ai-app + namespace: ai + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod +spec: + ingressClassName: nginx + tls: + - hosts: + - myapp.junv.cc + secretName: myapp-tls + rules: + - host: myapp.junv.cc + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: my-ai-app + port: + number: 80 +``` + +## 🔐 Service Account + +The `ai-bot` service account (on 192.168.1.10) has full access to this namespace for management and automation tasks. + +## 📚 Related Documentation + +- ArgoCD Dashboard: https://argo.junv.cc +- Service Account Setup: See `/k8s/` directory for ai-bot configuration +- Domain: `*.junv.cc` with automatic TLS via cert-manager + +## ⚠️ Important Notes + +- Always specify `namespace: ai` in your manifests +- Use cert-manager annotations for automatic TLS certificates +- Follow the existing naming conventions for consistency +- Test manifests locally before committing when possible + +--- + +**Last Updated**: February 13, 2026 diff --git a/k8s/AI-BOT-USAGE.md b/k8s/AI-BOT-USAGE.md new file mode 100644 index 0000000..a649f49 --- /dev/null +++ b/k8s/AI-BOT-USAGE.md @@ -0,0 +1,125 @@ +# AI Bot Kubernetes Access Guide + +## Overview +This service account provides **full access to the `ai` namespace only** on the K3s cluster at 192.168.1.2. + +## Quick Start + +### 1. Set Environment Variable +```bash +export KUBECONFIG=~/ai-bot-kubeconfig.yaml +``` + +Or add to your `~/.bashrc` or `~/.zshrc`: +```bash +echo 'export KUBECONFIG=~/ai-bot-kubeconfig.yaml' >> ~/.bashrc +source ~/.bashrc +``` + +### 2. Verify Access +```bash +# Check current context +kubectl config current-context + +# List pods in ai namespace +kubectl get pods + +# View all resources in ai namespace +kubectl get all +``` + +## What You Can Do + +✅ **Full access in `ai` namespace:** +- Create, read, update, delete any resources (pods, deployments, services, etc.) +- View logs: `kubectl logs ` +- Execute commands: `kubectl exec -it -- /bin/bash` +- Port forward: `kubectl port-forward 8080:80` + +✅ **Read-only access to ALL other namespaces:** +- List and view resources: `kubectl get pods -n kube-system` +- Describe resources: `kubectl describe deployment -n media` +- View logs: `kubectl logs -n default` +- Watch resources: `kubectl get pods -n home-apps --watch` + +❌ **Cannot modify other namespaces:** +- Cannot create, update, or delete resources outside `ai` namespace +- Cannot apply manifests to other namespaces +- Cannot execute commands in pods outside `ai` namespace + +## Common Commands + +```bash +# List all pods in ai namespace (default) +kubectl get pods + +# List pods in other namespaces (read-only) +kubectl get pods -n kube-system +kubectl get pods -n media +kubectl get pods --all-namespaces + +# Switch namespace context +kubens default # View resources in default +kubens ai # Back to ai namespace + +# List available contexts +kubectx + +# Create resources (only works in ai namespace) +kubectl create deployment myapp --image=nginx +kubectl apply -f myapp.yaml + +# View logs (works in all namespaces) +kubectl logs -f +kubectl logs -n kube-system + +# Describe resources (works in all namespaces) +kubectl describe pod +kubectl describe deployment -n media + +# Delete resources (only works in ai namespace) +kubectl delete pod +kubectl delete deployment + +# Use k9s (interactive UI) +k9s +``` + +## Using k9s + +K9s is an interactive terminal UI for Kubernetes: +```bash +k9s +``` + +Key shortcuts: +- `:pods` - View pods +- `:deploy` - View deployments +- `:svc` - View services +- `Ctrl+A` - Show all namespaces (but you'll only see `ai`) +- `?` - Help menu +- `Ctrl+C` - Exit + +## Troubleshooting + +### "Forbidden" or "Access Denied" errors +You're trying to access resources outside the `ai` namespace. Check your namespace: +```bash +kubectl config get-contexts +``` + +### Connection issues +Ensure you can reach the cluster: +```bash +curl -k https://192.168.1.2:6443 +``` + +## Files Location +- **Kubeconfig**: `~/ai-bot-kubeconfig.yaml` +- **This guide**: `~/AI-BOT-USAGE.md` + +## Service Account Details +- **Name**: `ai-bot` +- **Namespace**: `ai` +- **Cluster**: `https://192.168.1.2:6443` +- **Token**: Embedded in kubeconfig (long-lived secret) diff --git a/k8s/README.md b/k8s/README.md new file mode 100644 index 0000000..26a8065 --- /dev/null +++ b/k8s/README.md @@ -0,0 +1,89 @@ +# Kubernetes Configuration Files + +This directory contains Kubernetes configuration files and documentation that are **not** deployed by ArgoCD. These are infrastructure-level configurations, service account setups, and reference materials. + +## 📁 Contents + +### Service Account Configuration + +- **`ai-bot-serviceaccount.yaml`** - ServiceAccount, Secret, Role, and RoleBinding for ai-bot + - Creates `ai-bot` service account in `ai` namespace + - Grants full access to `ai` namespace only + +- **`ai-bot-clusterrole.yaml`** - ClusterRole and ClusterRoleBinding for read-only access + - Grants read-only access (get, list, watch) to all namespaces + - Combined with the Role above, ai-bot has: + - Full access in `ai` namespace + - Read-only access in all other namespaces + +- **`ai-bot-kubeconfig.yaml`** - Kubeconfig file for ai-bot service account + - Pre-configured for 192.168.1.10 + - Contains embedded token and CA certificate + - ⚠️ **Do not commit to Git** (contains credentials) + +### Documentation + +- **`AI-BOT-USAGE.md`** - User guide for ai-bot service account + - How to use kubectl, k9s, kubectx, kubens + - Permission examples and limitations + - Common commands and troubleshooting + +### Backups + +- **`home-cluster-admin-backup.yaml`** - Backup of removed ClusterRoleBinding + - Original binding that granted cluster-admin to all service accounts + - Removed for security reasons (Feb 13, 2026) + - Keep for reference in case restoration is needed + +## 🚀 Usage + +### Apply Service Account Configuration + +```bash +kubectl apply -f ai-bot-serviceaccount.yaml +kubectl apply -f ai-bot-clusterrole.yaml +``` + +### Deploy Kubeconfig to 192.168.1.10 + +```bash +scp ai-bot-kubeconfig.yaml 192.168.1.10:~/ +scp AI-BOT-USAGE.md 192.168.1.10:~/ +``` + +## 🔐 Security Notes + +1. **ai-bot-kubeconfig.yaml** contains sensitive credentials + - Should be in `.gitignore` + - Only deploy to trusted machines + - Rotate token if compromised + +2. **Service Account Permissions** + - ai-bot has full access only in `ai` namespace + - Read-only access in all other namespaces + - Cannot escalate privileges + +3. **ClusterRoleBinding Removal** + - Removed `home-cluster-admin` binding that granted cluster-admin to all service accounts + - Individual service accounts now need explicit permissions + - Improves security posture significantly + +## 📋 Related + +- **AI Namespace Manifests**: `/ai/` directory (monitored by ArgoCD) +- **Terraform Configuration**: `/terraform/` directory +- **ArgoCD Values**: `/argocd-values.yaml` + +## 🔄 Setup History + +### 2026-02-13 +- Created ai-bot service account with restricted permissions +- Removed blanket cluster-admin access from all service accounts +- Set up ai-bot user on 192.168.1.10 with kubectl, k9s, kubectx, kubens +- Configured zsh with KUBECONFIG environment variable and aliases + +--- + +**Maintainer**: junv (wahyd4) +**Cluster**: K3s on 192.168.1.2 +**Management Host**: 192.168.1.10 (ai-bot user) diff --git a/k8s/ai-bot-clusterrole.yaml b/k8s/ai-bot-clusterrole.yaml new file mode 100644 index 0000000..b08774d --- /dev/null +++ b/k8s/ai-bot-clusterrole.yaml @@ -0,0 +1,27 @@ +--- +# ClusterRole for read-only access across all namespaces +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ai-bot-readonly-all-namespaces +rules: +- apiGroups: ["*"] + resources: ["*"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["pods/log", "pods/status"] + verbs: ["get", "list"] +--- +# ClusterRoleBinding to grant ai-bot read access everywhere +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ai-bot-readonly-all-namespaces-binding +subjects: +- kind: ServiceAccount + name: ai-bot + namespace: ai +roleRef: + kind: ClusterRole + name: ai-bot-readonly-all-namespaces + apiGroup: rbac.authorization.k8s.io diff --git a/k8s/ai-bot-kubeconfig.yaml b/k8s/ai-bot-kubeconfig.yaml new file mode 100644 index 0000000..c353cd0 --- /dev/null +++ b/k8s/ai-bot-kubeconfig.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Config +clusters: +- cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTkRRek56SXlOelF3SGhjTk1qVXdOREV4TVRFMU1URTBXaGNOTXpVd05EQTVNVEUxTVRFMApXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTkRRek56SXlOelF3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFRNm1KOVZRY0NXR0JIRTR5cjFZTXBFd1lOZ0piUWZ5YWVoRWt2NjZvWGEKYUJFNmNPN3cvWTJyVy9MYUdRa0dUaUErWlV6SUNrcEhPU1k4RERGakFUTjNvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVVByRTh5VmRJYUhWbzhGYXRRY3BvCjdRMVJFSDR3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnTFFRYno1REFCT0JJNlRXZFlnbXdocHVuYi9YWmdzaEwKRWlnWFZYMVRORUlDSVFDc0paM3k0ajE4dCsxRWpGTTZ4MXBxU3RJc0d0cHZMSzV5RkFQV1p5c1g5QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://192.168.1.2:6443 + name: k3s-cluster +contexts: +- context: + cluster: k3s-cluster + namespace: ai + user: ai-bot + name: ai-bot-context +current-context: ai-bot-context +users: +- name: ai-bot + user: + token: eyJhbGciOiJSUzI1NiIsImtpZCI6ImpYNDNkaXczVlQ2V240X00xb0luYlo3WGl6TEhWQ0ZrbE5YUE1wZVFXbGMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJhaSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhaS1ib3QtdG9rZW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYWktYm90Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYzM0ZTVkNmItYWVjZi00YjZkLWJlZGItNWM1OWM0MzM3YmIwIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmFpOmFpLWJvdCJ9.P0PPyU75MMwHAG2xVxn5VeqKR3Vh4XrJqhZEsKb08634ubvawDaZqMdu5BI2y32-szuRgZl-fqT_JsZxFZMhrCYbcDl2RCMtKa3sdDWViP8xJsq4dZ-sLNd_jP_hjIzTUr3Lq_bA1k3ivOlchd-6-C5rvVP4EtGQs0bl30audwk-bbEPYNFEu39e28diBkVrk5LCXr7-RLObIeJEs1Xro7kgNFCAuX3qGu8D6Z0fLa1HSBfVBz9OPItXZ_RUOo2Px8BA9KGChQqra2wI19roYVk4-SvrU9FRzLtWzbbYNq6B1-cXOaSJqaUKgspgs9XHE62TR2Q2hMrSJZtkkZ8F5Q diff --git a/k8s/ai-bot-serviceaccount.yaml b/k8s/ai-bot-serviceaccount.yaml new file mode 100644 index 0000000..875b893 --- /dev/null +++ b/k8s/ai-bot-serviceaccount.yaml @@ -0,0 +1,39 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ai-bot + namespace: ai +--- +apiVersion: v1 +kind: Secret +metadata: + name: ai-bot-token + namespace: ai + annotations: + kubernetes.io/service-account.name: ai-bot +type: kubernetes.io/service-account-token +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: ai-bot-full-access + namespace: ai +rules: +- apiGroups: ["*"] + resources: ["*"] + verbs: ["*"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ai-bot-full-access-binding + namespace: ai +subjects: +- kind: ServiceAccount + name: ai-bot + namespace: ai +roleRef: + kind: Role + name: ai-bot-full-access + apiGroup: rbac.authorization.k8s.io diff --git a/k8s/home-cluster-admin-backup.yaml b/k8s/home-cluster-admin-backup.yaml new file mode 100644 index 0000000..927e92d --- /dev/null +++ b/k8s/home-cluster-admin-backup.yaml @@ -0,0 +1,18 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"creationTimestamp":"2023-01-11T10:29:06Z","name":"home-cluster-admin","resourceVersion":"59908630","uid":"cf1764ad-c5cd-4b06-844b-deebda2c1388"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"cluster-admin"},"subjects":[{"apiGroup":"rbac.authorization.k8s.io","kind":"Group","name":"system:serviceaccounts"}]} + creationTimestamp: "2025-04-11T15:06:23Z" + name: home-cluster-admin + resourceVersion: "12797" + uid: c62c72fc-79ba-4a60-ba07-36437563f71e +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:serviceaccounts