Compare commits

..
9 Commits
Author SHA1 Message Date
claudeandClaude Opus 5.5 284ecc4581 Remove unused gitea MCP deployment
Demo / hello (push) Successful in 13s
It was never included from main.yml, used an invalid apiVersion for the
Deployment and exposed mcp.gitea.eom.dev publicly. The MCP servers now
live in ansible-role-mcp-servers, cluster-internal only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 14:12:26 -05:00
ClaudeandClaude Opus 5.5 6144791cb9 Gitea: declare the Dex login source in Helm values
Demo / hello (push) Successful in 12s
Records the source that was configured live with gitea admin auth:
OIDC discovery from Dex, groups scope, and login restricted to members
of Gitea Users via the groups claim. Needs gitea_dex_client_secret in
Vault (the same secret as Dex's gitea client).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 19:12:03 -05:00
ericandClaude Opus 5.5 170c3a069e Gitea: keep off the node that hosts ingress-nginx
Demo / hello (push) Successful in 17s
Sharing the 1-CPU ingress node with Nextcloud starved it into a
restart loop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 18:22:16 -05:00
ericandClaude Opus 5.5 5702010a3d Gitea: sign in only through Dex, send sign-up to /members
Demo / hello (push) Successful in 13s
Disable the password sign-in form so /user/login redirects to Dex,
keep registration enabled for Dex auto-registration, and redirect
/user/sign_up to www.eom.dev/members at the ingress.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 17:56:00 -05:00
ClaudeandClaude Opus 5.5 f56eab28af Poll for gitea rollout instead of using rollout status
Demo / hello (push) Successful in 20s
`kubectl rollout status` fails immediately once a rollout has exceeded
its progress deadline, even if the new pod is about to become ready.
Poll the deployment until replicas, updated and available counts agree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 13:31:04 -05:00
ClaudeandClaude Opus 5.5 584779945d Give PostgreSQL enough CPU to pass its liveness probe
Demo / hello (push) Successful in 18s
With a 150m CPU limit, pg_isready routinely exceeds the 5s probe timeout
under load (e.g. Gitea's startup migration check), so the kubelet kills
postgres mid-query. This is the cause of the long-running restart loop on
gitea-postgresql-0. Raise the limit to one core (request 250m).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 13:28:29 -05:00
ClaudeandClaude Opus 5.5 b81a2d64d0 Pin valkey/postgresql resources; harden runner token step
The live valkey and postgresql StatefulSets had memory limits raised by
hand (8Gi and 2Gi). A helm upgrade reverts those to the bitnami 192Mi
preset, and valkey then OOMs loading its ~3.3GB dataset. Move the limits
into role defaults so upgrades keep them.

Generate the runner token with kubectl exec against the deployment after
waiting for its rollout, with retries, instead of kubernetes.core.k8s_exec
(the control plane's kubernetes python client is too old for it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 13:05:10 -05:00
ClaudeandClaude Opus 5.5 0f1ed99dfc Log real client IPs and enable Gitea Actions with a runner
Demo / hello (push) Successful in 18s
- Trust X-Forwarded-For from the pod network (10.244.0.0/16) via
  security.REVERSE_PROXY_TRUSTED_PROXIES / REVERSE_PROXY_LIMIT so Gitea
  logs the external client address instead of the ingress-nginx pod IP.
- Set actions.ENABLED explicitly and deploy an instance-wide runner via
  the gitea/actions chart (release "gitea-actions", pinned to 0.1.2).
  The registration token is generated in-cluster and stored in a Secret
  on first run, so no token lives in git or the vault.
- Fix the old actions.yaml, which reused the "gitea" release name and
  would have clobbered the main Gitea release.
- Add a demo workflow (.gitea/workflows/demo.yaml).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:56:58 -05:00
eric 9f46e92cd7 Catppuccin 2026-10-26 18:55:54 -04:00
6 changed files with 221 additions and 94 deletions
+42
View File
@@ -0,0 +1,42 @@
# Demo workflow showing Gitea Actions running on the in-cluster runner.
name: Demo
on:
push:
workflow_dispatch:
jobs:
hello:
runs-on: ubuntu-latest
steps:
- name: Say hello
run: |
echo "Hello from Gitea Actions on ${{ gitea.server_url }}"
echo "Repository: ${{ gitea.repository }}"
echo "Ref: ${{ gitea.ref }}"
echo "Commit: ${{ gitea.sha }}"
echo "Triggered by: ${{ gitea.actor }} (${{ gitea.event_name }})"
- name: Check out the role
uses: actions/checkout@v4
- name: Show the role layout
run: find . -path ./.git -prune -o -type f -print | sort
- name: Validate YAML
run: |
python3 -c 'import yaml' 2>/dev/null || (apt-get update -qq && apt-get install -y -qq python3-yaml >/dev/null)
python3 - <<'PY'
import pathlib, sys
import yaml
bad = 0
for p in sorted(pathlib.Path('.').rglob('*.y*ml')):
if '.git' in p.parts:
continue
try:
yaml.safe_load(p.read_text())
print(f"ok {p}")
except yaml.YAMLError as e:
bad += 1
print(f"FAIL {p}: {e}")
sys.exit(1 if bad else 0)
PY
+33
View File
@@ -1,3 +1,36 @@
#SPDX-License-Identifier: MIT-0
---
# defaults file for ansible-role-gitea
# CIDRs allowed to set X-Forwarded-For / X-Real-IP for Gitea.
# 10.244.0.0/16 is the cluster pod network, where ingress-nginx runs.
gitea_trusted_proxies: "127.0.0.0/8,::1/128,10.244.0.0/16"
# Resources for chart subcharts. These match the limits previously set by
# hand on the live StatefulSets; the bitnami default presets (192Mi) OOM.
gitea_valkey_resources:
requests:
cpu: 100m
memory: 1Gi
ephemeral-storage: 50Mi
limits:
cpu: 150m
memory: 8Gi
ephemeral-storage: 4Gi
# PostgreSQL needs real CPU: at 150m its liveness probe (pg_isready, 5s
# timeout) times out under load and the kubelet restarts it.
gitea_postgresql_resources:
requests:
cpu: 250m
memory: 128Mi
ephemeral-storage: 50Mi
limits:
cpu: "1"
memory: 2Gi
ephemeral-storage: 2Gi
# Gitea Actions runner (gitea/actions chart)
gitea_actions_enabled: true
gitea_actions_chart_version: 0.1.2
gitea_actions_runner_replicas: 1
gitea_actions_runner_token_secret: gitea-actions-runner-token
+65 -10
View File
@@ -1,23 +1,78 @@
- name: deploy actions
---
# Deploys an instance-wide Gitea Actions runner (act_runner + DinD).
- name: check for existing runner registration token secret
kubernetes.core.k8s_info:
kind: Secret
namespace: gitea
name: "{{ gitea_actions_runner_token_secret }}"
register: runner_token_secret
- name: generate and store a runner registration token
when: runner_token_secret.resources | length == 0
block:
# Poll instead of `kubectl rollout status`, which exits immediately once
# a slow rollout has passed the deployment's progressDeadlineSeconds.
- name: wait for the gitea deployment to finish rolling out
command: >-
kubectl -n gitea get deployment gitea
-o jsonpath={.spec.replicas},{.status.replicas},{.status.updatedReplicas},{.status.availableReplicas}
register: gitea_rollout
until: gitea_rollout.stdout.split(',') | unique | length == 1
retries: 90
delay: 10
changed_when: false
- name: generate instance-level runner registration token
command: kubectl -n gitea exec deployment/gitea -c gitea -- gitea actions generate-runner-token
register: runner_token
retries: 10
delay: 15
until: runner_token.rc == 0 and (runner_token.stdout | trim | length) > 0
changed_when: false
no_log: true
- name: store runner registration token
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Secret
metadata:
name: "{{ gitea_actions_runner_token_secret }}"
namespace: gitea
type: Opaque
stringData:
token: "{{ runner_token.stdout | trim }}"
no_log: true
- name: deploy gitea actions runner
kubernetes.core.helm:
name: gitea
name: gitea-actions
chart_ref: gitea/actions
chart_version: "{{ gitea_actions_chart_version }}"
release_namespace: gitea
create_namespace: true
values:
enabled: true
provisioning:
enabled: true
giteaRootURL: https://gitea.eom.dev
existingSecret: "{{ gitea_actions_runner_token_secret }}"
existingSecretKey: token
statefulset:
actRunner:
replicas: "{{ gitea_actions_runner_replicas }}"
persistence:
size: 1Gi
runner:
config: |
log:
level: debug
level: info
cache:
enabled: false
container:
require_docker: true
docker_timeout: 300s
runner:
capacity: 2
labels:
- "ubuntu-latest:docker://node:16-bullseye"
- "ubuntu-22.04:docker://node:16-bullseye"
- "ubuntu-20.04:docker://node:16-bullseye"
- "ubuntu-18.04:docker://node:16-buster"
- "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
- "ubuntu-24.04:docker://docker.gitea.com/runner-images:ubuntu-24.04"
- "ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"
+73
View File
@@ -17,6 +17,19 @@
release_namespace: gitea
create_namespace: true
values:
# Keep heavy apps off the 1-CPU node that hosts ingress-nginx; sharing it
# starved Nextcloud and risks the ingress / MetalLB announcement.
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
labelSelector:
matchLabels:
app.kubernetes.io/component: controller
app.kubernetes.io/name: ingress-nginx
image:
pullPolicy: Always
service:
@@ -61,17 +74,42 @@
bindPassword: "{{ openldap_readonly_password }}"
usernameAttribute: uid
publicSSHKeyAttribute: sshPublicKey
# Sign-in through Dex; only members of Gitea Users (sent in the groups
# claim) may log in. The name "Dex" fixes the callback URL
# /user/oauth2/Dex/callback registered in Dex.
oauth:
- name: Dex
provider: openidConnect
key: gitea
secret: "{{ gitea_dex_client_secret }}"
autoDiscoverUrl: https://dex.eom.dev/.well-known/openid-configuration
scopes: "openid profile email groups"
requiredClaimName: groups
requiredClaimValue: Gitea Users
groupClaimName: groups
config:
APP_NAME: "Gitea"
service:
# Keep false: true would also block Dex auto-registration of members.
# The sign-up button is redirected to www.eom.dev/members at ingress.
DISABLE_REGISTRATION: false
SHOW_REGISTRATION_BUTTON: true
# Sign-in goes through Dex only (admin fallback: gitea admin CLI).
ENABLE_PASSWORD_SIGNIN_FORM: false
ENABLE_PASSKEY_AUTHENTICATION: false
DEFAULT_ALLOW_CREATE_ORGANIZATION: false
ALLOW_ONLY_EXTERNAL_REGISTRATION: true
ENABLE_NOTIFY_MAIL: true
EMAIL_DOMAIN_BLOCKLIST: "spammer.com,mailinator.com,tempmail.com,10minutemail.com,guerrillamail.com,dispostable.com,fakemail.com,maildrop.cc,trashmail.com,yopmail.com,techstrategylab.com,timminsgoldminetour.com,claxyn.org,sise.claxyn.org,blyxen.com,seti.blyxen.com,tute.blyxen.com,tula.blyxen.com,sise.blyxen.org,ivolix.com,seti.lyvix.org,tute.lyvix.org,seti.ivolix.org,semo.ivolix.com,elyquin.org,simu.elyquin.org,semo.claxyn.com,sise.oxilv.com,simu.glinxy.org,simu.hivoltz.org,semo.elyquin.com,prisite.online,sise.dravix.org,dravix.org,semo.glinxy.com,glinxy.com,dark-webmarket.com,seti.juxal.org,juxal.org,9e5d.getir.space,getir.space,topcompanygroup.com,6d43.getir.space,9e2d.mikrowellen-tests.com,verifiedlinklist.com,xylzen.com,tapi.xylzen.com,ylixo.com,tapi.ylixo.com,tute.ylixo.com,estrella.glinxy.com,nestmailbox.com,theweifamily.icu,1mail.x24hr.com,8.dnsabr.com,23.8.dnsabr.com,2712.bubbles-swimming.co.uk,anonmails.de,spambog.ru,anonmails.de,virginvoyages.click,travellersrest.click,mailus.virginvoyages.com,tula.hivoltz.org,theblueholiday.click,mailius.virginvoyages.com,travellersrest.click,twitch.work,backlinks.monster,onlinecmail.com,gsasearchenginerankervps.com,seoautomationpro.online"
ENABLE_CAPTCHA: true
REGISTER_EMAIL_CONFIRM: true
security:
# Trust X-Forwarded-For from ingress-nginx (pod network) so Gitea
# logs the real client address instead of the ingress pod IP.
REVERSE_PROXY_LIMIT: 1
REVERSE_PROXY_TRUSTED_PROXIES: "{{ gitea_trusted_proxies }}"
actions:
ENABLED: true
oauth2_client:
ENABLE_AUTO_REGISTRATION: true
UPDATE_AVATAR: true
@@ -84,8 +122,14 @@
PASSWD: "{{ gitea_admin_password }}"
FROM: Gitea <gitea@eom.dev>
ENVELOPE_FROM: gitea@eom.dev
ui:
THEMES: catppuccin-rosewater-auto,catppuccin-flamingo-auto,catppuccin-pink-auto,catppuccin-mauve-auto,catppuccin-red-auto,catppuccin-maroon-auto,catppuccin-peach-auto,catppuccin-yellow-auto,catppuccin-green-auto,catppuccin-teal-auto,catppuccin-sky-auto,catppuccin-sapphire-auto,catppuccin-blue-auto,catppuccin-lavender-auto
DEFAULT_THEME: catppuccin-blue-auto
valkey:
enabled: true
primary:
# The chart's default preset (192Mi) cannot load the existing dataset.
resources: "{{ gitea_valkey_resources }}"
valkey-cluster:
enabled: false
replica:
@@ -110,8 +154,37 @@
password: "{{ gitea_admin_password }}"
database: gitea
primary:
resources: "{{ gitea_postgresql_resources }}"
persistence:
enabled: true
size: 2Ti
postgresql-ha:
enabled: false
- name: Send Gitea's sign-up button to the eom.dev membership site
kubernetes.core.k8s:
state: present
definition:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gitea-signup-redirect
namespace: gitea
annotations:
nginx.ingress.kubernetes.io/temporal-redirect: https://www.eom.dev/members
spec:
ingressClassName: nginx
tls:
- hosts: [gitea.eom.dev]
secretName: gitea-tls
rules:
- host: gitea.eom.dev
http:
paths:
- path: /user/sign_up
pathType: Exact
backend:
service:
name: gitea-http
port:
number: 3000
+5 -3
View File
@@ -2,6 +2,8 @@
---
# tasks file for ansible-role-gitea
- name: gitea
include_tasks: "{{ item }}"
loop:
- mcp.yaml
include_tasks: gitea.yaml
- name: gitea actions runner
include_tasks: actions.yaml
when: gitea_actions_enabled | bool
-78
View File
@@ -1,78 +0,0 @@
- name: deploy mcp
k8s:
definition:
apiVersion: v1
kind: Deployment
metadata:
name: mcp
namespace: gitea
spec:
replicas: 1
selector:
matchLabels:
app: mcp
template:
metadata:
labels:
app: mcp
spec:
containers:
- name: mcp
image: gitea/gitea-mcp-server
env:
- name: GITEA_HOST
value: https://gitea.eom.dev
- name: GITEA_INSECURE
value: "false"
- name: GITEA_ACCESS_TOKEN
value: "{{ localai_gitea_access_token }}"
- name: MCP_MODE
value: http
ports:
- containerPort: 8080
- name: service for mcp
k8s:
definition:
apiVersion: v1
kind: Service
metadata:
name: mcp
namespace: gitea
spec:
selector:
app: mcp
ports:
- port: 80
name: http
targetPort: 8080
type: ClusterIP
- name: ingress
k8s:
state: present
definition:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: ca-issuer
name: mcp
namespace: gitea
spec:
ingressClassName: nginx
rules:
- host: mcp.gitea.eom.dev
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: mcp
port:
number: 80
tls:
- hosts:
- mcp.gitea.eom.dev
secretName: mcp