Huge role refactoring/cleanup. Other commits will propably follow. Because some bugs will exist. Still important for longrun and also for auto docs/help/slideshow generation

This commit is contained in:
2025-07-08 23:43:13 +02:00
parent 6b87a049d4
commit 563d5fd528
1242 changed files with 2301 additions and 1355 deletions

View File

@@ -0,0 +1,38 @@
# Administration
## update
```bash
cd {{docker_compose.directories.instance}}
docker-compose down
docker-compose pull
docker-compose up -d
```
Keep in mind to track and to don't interrupt the update process until the migration is done.
## set variables
```bash
COMPOSE_HTTP_TIMEOUT=600
DOCKER_CLIENT_TIMEOUT=600
```
## recreate
```bash
cd {{docker_compose.directories.instance}} && docker-compose -p gitea up -d --force-recreate
```
## database access
To access the database execute
```bash
docker-compose exec -it database /bin/mysql -u gitea -p
```
## bash in application
docker-compose exec -it application /bin/sh
## user management
### Change password
```bash
docker-compose exec --user git application gitea admin user change-password \
--username administrator \
--password "MyNewSecureP@ssw0rd"
```

View File

@@ -0,0 +1,33 @@
# Gitea
## Description
Boost your development journey with Gitea, a lightweight and energetic self-hosted Git service that offers efficient code collaboration, intuitive version control, and an agile environment for your projects. Ignite your coding spirit, innovate faster, and code with confidence!
## Overview
This role deploys Gitea using Docker. It automates the setup and update processes for your self-hosted Git service, integrating with a central MariaDB for the database. With functionalities for updating, recreating the container, variable management, database access, and shell access to the application container, this role streamlines the management of your Gitea instance.
For detailed administration procedures, please refer to the [Administration.md](./Administration.md) file.
## Features
- **Lightweight and Fast:** Enjoy a minimal yet efficient Git service tailored for development teams.
- **Efficient Code Collaboration:** Manage repositories and workflows with an intuitive interface.
- **Automated Updates & Re-creation:** Simplify maintenance with automated update and container recreation procedures.
- **Built-in Database Access:** Seamlessly interact with the underlying MariaDB for your Git service.
- **Integrated Configuration:** Easily manage settings via environment variables and Docker Compose templates.
## Further Resources
- [Gitea Official Website](https://gitea.io/)
- [Gitea LDAP integration](https://docs.gitea.com/usage/authentication)
- [Gitea Alternatives](https://chatgpt.com/share/67a5f599-c9b0-800f-87fe-49a3b61263e6)
## Credits
Developed and maintained by **Kevin Veen-Birkenbach**.
Learn more at [veen.world](https://www.veen.world).
Part of the [CyMaIS Project](https://github.com/kevinveenbirkenbach/cymais)
Licensed under [CyMaIS NonCommercial License (CNCL)](https://s.veen.world/cncl).

View File

@@ -0,0 +1,2 @@
# Todos
- Implement [OIDC](https://www.talkingquickly.co.uk/gitea-sso-with-keycloak-openldap-openid-connect), see [Chat GPT Conversation](https://chatgpt.com/share/67f61a49-a790-800f-81b3-439181dbf555)

View File

@@ -0,0 +1,26 @@
---
galaxy_info:
author: "Kevin Veen-Birkenbach"
description: "Boost your development journey with Gitea, a lightweight and energetic self-hosted Git service that offers efficient code collaboration, intuitive version control, and an agile environment for your projects. Ignite your coding spirit, innovate faster, and code with confidence!"
license: "CyMaIS NonCommercial License (CNCL)"
license_url: "https://s.veen.world/cncl"
company: |
Kevin Veen-Birkenbach
Consulting & Coaching Solutions
https://www.veen.world
galaxy_tags:
- gitea
- docker
- git
- self-hosted
- version control
repository: https://s.veen.world/cymais
issue_tracker_url: https://s.veen.world/cymaisissues
documentation: https://s.veen.world/cymais
logo:
class: "fa-solid fa-code"
run_after:
- web-app-matomo
- web-app-keycloak
- web-app-mailu
dependencies: []

View File

@@ -0,0 +1 @@
credentials:

View File

@@ -0,0 +1,7 @@
- name: Execute OIDC Cleanup Routine
include_tasks: cleanup/oidc.yml
when: not (applications | is_feature_enabled('oidc', application_id))
- name: Execute LDAP Cleanup Routine
include_tasks: cleanup/ldap.yml
when: not (applications | is_feature_enabled('ldap', application_id))

View File

@@ -0,0 +1,22 @@
- name: "Lookup existing LDAP auth source ID"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
gitea admin auth list \
| awk -v name="LDAP ({{ primary_domain }})" '$0 ~ name {print $1; exit}'
args:
chdir: "{{ docker_compose.directories.instance }}"
register: ldap_source_id_raw
failed_when: false
changed_when: false
- name: "Delete existing LDAP auth source if present"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
gitea admin auth delete --id {{ ldap_source_id_raw.stdout }}
args:
chdir: "{{ docker_compose.directories.instance }}"
when: ldap_source_id_raw.stdout != ""
register: ldap_delete
failed_when: ldap_delete.rc != 0

View File

@@ -0,0 +1,23 @@
- name: "Lookup existing OIDC auth source ID"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
gitea admin auth list \
| awk -v name="{{ oidc.button_text }}" '$0 ~ name {print $1; exit}'
args:
chdir: "{{ docker_compose.directories.instance }}"
register: oidc_source_id_raw
failed_when: false
changed_when: false
- name: "Delete existing OIDC auth source if present"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
gitea admin auth delete --id {{ oidc_source_id_raw.stdout }}
args:
chdir: "{{ docker_compose.directories.instance }}"
when: oidc_source_id_raw.stdout != ""
register: oidc_delete
failed_when: oidc_delete.rc != 0

View File

@@ -0,0 +1,73 @@
---
- name: "include service-rdbms-central"
include_role:
name: service-rdbms-central
- name: "include role webserver-proxy-domain for {{application_id}}"
include_role:
name: webserver-proxy-domain
vars:
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: Wait for Gitea HTTP endpoint
wait_for:
host: "127.0.0.1"
port: "{{ ports.localhost.http[application_id] }}"
delay: 5
timeout: 300
- name: "Run DB migrations inside Gitea container"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
/app/gitea/gitea migrate
args:
chdir: "{{ docker_compose.directories.instance }}"
register: migrate
changed_when: "'migrations completed' in migrate.stdout"
- name: "Create initial admin user"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
/app/gitea/gitea admin user create \
--admin \
--username "{{ users.administrator.username }}" \
--password "{{ users.administrator.password }}" \
--email "{{ users.administrator.email }}" \
-c /data/gitea/conf/app.ini
args:
chdir: "{{ docker_compose.directories.instance }}"
register: create_admin
changed_when: "'has been successfully created' in create_admin.stdout"
failed_when: create_admin.rc != 0 and 'user already exists' not in create_admin.stderr
- name: "Wait until Gitea setup and migrations are ready"
uri:
url: "http://127.0.0.1:{{ ports.localhost.http[application_id] }}/api/v1/version"
method: GET
status_code: 200
return_content: no
register: gitea_ready
until: gitea_ready.status == 200
retries: 20
delay: 5
when: applications | is_feature_enabled('oidc', application_id) or applications | is_feature_enabled('ldap', application_id)
- name: Execute Setup Routines
include_tasks: setup.yml
- name: Execute Cleanup Routines
include_tasks: cleanup.yml
when: mode_cleanup
- name: Include DNS role to register Gitea domain(s)
include_role:
name: network-dns-records
vars:
cloudflare_api_token: "{{ certbot_dns_api_token }}"
cloudflare_domains: "{{ [ domains | get_domain(application_id) ] }}"
cloudflare_target_ip: "{{ networks.internet.ip4 }}"
cloudflare_proxied: false
when: dns_provider == 'cloudflare'

View File

@@ -0,0 +1,7 @@
- name: Execute OIDC Setup Routine
include_tasks: setup/oidc.yml
when: applications | is_feature_enabled('oidc', application_id)
- name: Execute LDAP Setup Routine
include_tasks: setup/ldap.yml
when: applications | is_feature_enabled('ldap', application_id)

View File

@@ -0,0 +1,42 @@
- name: "Add LDAP Authentication Source"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
gitea admin auth add-ldap \
{{ gitea_ldap_auth_args | join(' ') }}
args:
chdir: "{{ docker_compose.directories.instance }}"
register: ldap_manage
failed_when: ldap_manage.rc != 0 and "login source already exists" not in ldap_manage.stderr
- name: "Lookup existing LDAP auth source ID"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
gitea admin auth list \
| tail -n +2 \
| grep -F "LDAP ({{ primary_domain }})" \
| awk '{print $1; exit}'
args:
chdir: "{{ docker_compose.directories.instance }}"
register: ldap_source_id_raw
failed_when:
- ldap_source_id_raw.rc != 0
- ldap_source_id_raw.stdout == ""
changed_when: false
- name: "Set LDAP source ID fact"
set_fact:
ldap_source_id: "{{ ldap_source_id_raw.stdout }}"
- name: "Update LDAP Authentication Source"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
gitea admin auth update-ldap \
--id {{ ldap_source_id }} \
{{ gitea_ldap_auth_args | join(' ') }}
args:
chdir: "{{ docker_compose.directories.instance }}"
register: ldap_manage
failed_when: ldap_manage.rc != 0

View File

@@ -0,0 +1,52 @@
- name: "Add Keycloak OIDC Provider"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
gitea admin auth add-oauth \
--provider openidConnect \
--name "{{ oidc.button_text }}" \
--key "{{ oidc.client.id }}" \
--secret "{{ oidc.client.secret }}" \
--auto-discover-url "{{ oidc.client.discovery_document }}" \
--scopes "openid profile email"
args:
chdir: "{{ docker_compose.directories.instance }}"
register: oidc_manage
failed_when: oidc_manage.rc != 0 and "login source already exists" not in oidc_manage.stderr
- name: "Lookup existing Keycloak auth source ID"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
/app/gitea/gitea admin auth list \
| tail -n +2 \
| grep -F "{{ oidc.button_text }}" \
| awk '{print $1; exit}'
args:
chdir: "{{ docker_compose.directories.instance }}"
register: oidc_source_id_raw
failed_when:
- oidc_source_id_raw.rc != 0
- oidc_source_id_raw.stdout == ""
changed_when: false
- name: "Set Keycloak source ID fact"
set_fact:
oidc_source_id: "{{ oidc_source_id_raw.stdout }}"
- name: "Update Keycloak OIDC Provider"
shell: |
docker-compose -f "{{ docker_compose.directories.instance }}/docker-compose.yml" \
exec -T --user git application \
gitea admin auth update-oauth \
--id {{ oidc_source_id }}\
--provider openidConnect \
--name "{{ oidc.button_text }}" \
--key "{{ oidc.client.id }}" \
--secret "{{ oidc.client.secret }}" \
--auto-discover-url "{{ oidc.client.discovery_document }}" \
--scopes "openid profile email"
args:
chdir: "{{ docker_compose.directories.instance }}"
register: oidc_manage
failed_when: oidc_manage.rc != 0

View File

@@ -0,0 +1,20 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %}
application:
{% include 'roles/docker-container/templates/base.yml.j2' %}
image: "{{ applications[application_id].images.gitea }}"
ports:
- "127.0.0.1:{{ports.localhost.http[application_id]}}:{{ container_port }}"
- "{{ports.public.ssh[application_id]}}:22"
volumes:
- data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
{% include 'roles/docker-container/templates/healthcheck/curl.yml.j2' %}
{% include 'roles/docker-container/templates/networks.yml.j2' %}
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
{% include 'roles/docker-compose/templates/volumes.yml.j2' %}
data:
{% include 'roles/docker-compose/templates/networks.yml.j2' %}

View File

@@ -0,0 +1,66 @@
# Configuration
# @see https://docs.gitea.com/next/administration/config-cheat-sheet#repository-repository
# General
DOMAIN={{domains | get_domain(application_id)}}
RUN_MODE="{{ 'dev' if (CYMAIS_ENVIRONMENT | lower) == 'development' else 'prod' }}"
ROOT_URL="{{ domains | get_url(application_id, web_protocol) }}/"
APP_NAME="{{ applications[application_id].title }}"
USER_UID=1000
USER_GID=1000
# Logging configuration
GITEA__log__MODE=console
GITEA__log__LEVEL={% if enable_debug | bool %}Debug{% else %}Info{% endif %}
# Database
DB_TYPE=mysql
DB_HOST={{database_host}}:{{database_port}}
DB_NAME={{database_name}}
DB_USER={{database_username}}
DB_PASSWD={{database_password}}
# SSH
SSH_PORT={{ports.public.ssh[application_id]}}
SSH_LISTEN_PORT=22
SSH_DOMAIN={{domains | get_domain(application_id)}}
# Mail Configuration
# @see https://docs.gitea.com/next/installation/install-with-docker#managing-deployments-with-environment-variables
# @todo test
GITEA__mailer__ENABLED=true
GITEA__mailer__FROM={{ users['no-reply'].email }}
GITEA__mailer__PROTOCOL=smtps
GITEA__mailer__SMTP_ADDR={{ system_email.host }}
GITEA__mailer__SMTP_PORT={{ system_email.port }}
GITEA__mailer__USER={{ users['no-reply'].email }}
GITEA__mailer__PASSWD={{ users['no-reply'].mailu_token }}
# Allow push creation
# @see https://github.com/go-gitea/gitea/issues/17619
GITEA__REPOSITORY__ENABLE_PUSH_CREATE_USER={{ applications[application_id].configuration.repository.enable_push_create_user | lower }}
GITEA__REPOSITORY__DEFAULT_PRIVATE={{ applications[application_id].configuration.repository.default_private | lower }}
GITEA__REPOSITORY__DEFAULT_PUSH_CREATE_PRIVATE={{ applications[application_id].configuration.repository.default_push_create_private | lower }}
GITEA__security__INSTALL_LOCK=true # Locks the installation page
# (De)activate OIDC
GITEA__openid__ENABLE_OPENID_SIGNUP={{ applications | is_feature_enabled('oidc',application_id) | lower }}
GITEA__openid__ENABLE_OPENID_SIGNIN={{ applications | is_feature_enabled('oidc',application_id) | lower }}
{% if applications | is_feature_enabled('oidc',application_id) or applications | is_feature_enabled('ldap',application_id) %}
EXTERNAL_USER_DISABLE_FEATURES=deletion,manage_credentials,change_username,change_full_name
{% if applications | is_feature_enabled('ldap',application_id) %}
GITEA__ldap__SYNC_USER_ON_LOGIN=true
{% endif %}
{% endif %}
# ------------------------------------------------
# Disable user self-registration
# ------------------------------------------------
# After this only admins can create accounts
GITEA__service__DISABLE_REGISTRATION=false

View File

@@ -0,0 +1,43 @@
title: "CyMaIS Code Hub"
images:
gitea: "gitea/gitea:latest"
configuration:
repository:
enable_push_create_user: True # Allow users to push local repositories to Gitea and have them automatically created for a user.
default_private: last # Default private when creating a new repository: last, private, public
default_push_create_private: True # Default private when creating a new repository with push-to-create.
features:
matomo: true
css: false
portfolio_iframe: true
central_database: true
ldap: true
oauth2: true
oidc: false # Deactivated because users aren't auto-created.
oauth2_proxy:
application: "application"
port: "3000"
acl:
blacklist:
- "/user/login"
csp:
flags:
script-src-elem:
unsafe-inline: true
style-src:
unsafe-inline: true
whitelist:
font-src:
- "data:"
- "blob:"
worker-src:
- "blob:"
manifest-src:
- "data:"
domains:
aliases:
- "git.{{ primary_domain }}"
docker:
services:
database:
enabled: true

View File

@@ -0,0 +1,18 @@
application_id: "gitea"
container_port: 3000
database_type: "mariadb"
gitea_ldap_auth_args:
- '--name "LDAP ({{ primary_domain }})"'
- '--host "{{ ldap.server.domain }}"'
- '--port {{ ldap.server.port }}'
- '--security-protocol "{{ ldap.server.security | trim or "unencrypted" }}"'
- '--bind-dn "{{ ldap.dn.administrator.data }}"'
- '--bind-password "{{ ldap.bind_credential }}"'
- '--user-search-base "{{ ldap.dn.ou.users }}"'
- '--user-filter "(&(objectClass=inetOrgPerson)(uid=%s))"'
- '--username-attribute "{{ ldap.user.attributes.id }}"'
- '--firstname-attribute "{{ ldap.user.attributes.firstname }}"'
- '--surname-attribute "{{ ldap.user.attributes.surname }}"'
- '--email-attribute "{{ ldap.user.attributes.mail }}"'
- '--public-ssh-key-attribute "{{ ldap.user.attributes.ssh_public_key }}"'
- '--synchronize-users'