initial commit

This commit is contained in:
hiperman
2026-01-30 15:07:31 -05:00
commit 7844cc4416
83 changed files with 3802 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
# ---> Ansible
*.retry
+18
View File
@@ -0,0 +1,18 @@
MIT License
Copyright (c) 2025 ansible
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
+512
View File
@@ -0,0 +1,512 @@
# Ansible Role: gitea
This Ansible role automates the deployment of Gitea - a self-hosted Git service, using Docker Compose. It provides a comprehensive setup with support for runners, fail2ban integration, and extensive configuration options. This role uses the centralized `docker_compose_app` role for standardized deployment, backup/restore, and health checks.
## Features
- **Standardized deployment** - Uses `docker_compose_app` for consistent deployment patterns
- **Docker-based deployment** - Runs Gitea in a rootless container for enhanced security
- **Complete security configuration** - Password policies, 2FA, fail2ban integration, etc.
- **Enterprise backup/restore** - Dual storage system with configurable retention policies
- **Health monitoring** - Automated health checks and deployment verification
- **Gitea Actions support** - Supports creating multiple runners running in rootless containers using DinD (Docker-in-Docker)
- **User management** - Automated user creation and removal
- **Extensible** - Extra config variables for any Gitea setting not explicitly defined
## Requirements
- Docker and Docker Compose installed (handled by `geerlingguy.docker` dependency)
- jmespath Python library (install with: `pip install jmespath`)
## Sample Usage in a Playbook
The following playbook was tested on the latest Debian 12, it should work on Ubuntu as well.
```yaml
# Installs Docker and Compose if not available
- name: Install Gitea using Docker Compose
hosts: git.example.com
become: yes
roles:
- role: gitea
vars:
# The default vars assume you are running a reverse proxy that handles HTTPS
app_name: gitea-prod
gitea_fqdn: 'git.example.com'
gitea_root_url: 'https://git.example.com'
gitea_protocol: http
gitea_http_listen: '0.0.0.0'
```
## Backup and Restore
This role uses the standardized backup/restore system from `docker_compose_app`, providing dual storage (controller + remote host) with configurable retention policies.
### Creating a Backup
```yaml
- name: Create Gitea backup
hosts: git.example.com
become: yes
roles:
- role: gitea
vars:
app_name: gitea-prod
app_backup: true
app_backup_retention_days_controller: 90
app_backup_retention_days_remote: 7
```
### Restoring from Backup
Restore from latest backup:
```yaml
- name: Restore Gitea from latest backup
hosts: git.example.com
become: yes
roles:
- role: gitea
vars:
app_name: gitea-prod
app_restore: true
app_restore_source: controller # or 'remote'
```
Restore from specific archive:
```yaml
- name: Restore Gitea from specific backup
hosts: git.example.com
become: yes
roles:
- role: gitea
vars:
app_name: gitea-prod
app_restore: true
app_restore_source: controller
app_restore_archive: /path/to/gitea-20240315-120000.tar.gz
```
> [!WARNING]
> Restore operations will **completely replace** all existing Gitea data.
# Variables
## Standardized Variables
This role uses the standardized `docker_compose_app` pattern. Core variables include:
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `app_name` | Required | Unique application instance name |
| `app_dir` | `{{ host_root_path }}/{{ app_name }}` | Application directory |
| `app_uid` | `{{ ansible_facts.user_uid }}` | File ownership UID |
| `app_gid` | `{{ ansible_facts.user_gid }}` | File ownership GID |
| `app_permission_mode` | `"0640"` | File permission mode |
| `app_restart_policy` | `"unless-stopped"` | Docker restart policy |
| `app_subdirectories` | `['data', 'config', 'log']` | Directories created in app_dir |
## Container Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_container_name` | `{{ app_name \| default('gitea') }}` | Docker container name for the Gitea service |
| `gitea_container_version` | `latest-rootless` | Docker image tag for the Gitea container (e.g., `latest-rootless`, `1.21.5-rootless`) |
| `gitea_restart_policy` | `{{ app_restart_policy }}` | Container restart policy (unless-stopped, always, on-failure, no) |
| `gitea_http_port` | `3000` | Host port that maps to Gitea's web interface |
| `gitea_ssh_port` | `2222` | Host port that maps to Gitea's SSH server |
| `gitea_data_path` | `{{ app_dir }}/data` | Full path to Gitea data directory on the host |
| `gitea_config_path` | `{{ app_dir }}/config` | Full path to Gitea configuration directory on the host |
| `gitea_log_path` | `{{ app_dir }}/log` | Full path to Gitea log directory on the host |
## Initial User Setup
| Variable Name | Option | Description |
|---------------|---------------|-------------|
| `gitea_users` | `[]` | List of user objects to create or remove in Gitea |
| | `username` | Login username for the Gitea user |
| | `email` | Email address for the Gitea user |
| | `password` | Password for the user (should be encrypted with Ansible Vault) |
| | `must_change_password` | If `true`, user must change password on first login |
| | `admin` | If `true`, user is created with administrator privileges |
| | `state` | Set to `present` to create user or `absent` to delete user |
## Backup and Restore
Backup and restore functionality is provided by the `docker_compose_app` role. Use the standard backup/restore variables:
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `app_backup` | `false` | Enable backup functionality |
| `app_backup_subdirectories` | `['data', 'config']` | Directories to backup (relative to app_dir) |
| `app_restore` | `false` | Enable restore functionality |
| `app_restore_source` | `controller` | Restore source (`controller` or `remote`) |
| `app_restore_archive` | - | Specific archive file to restore (overrides latest) |
| `app_backup_retention_days_controller` | `90` | Controller backup retention in days |
| `app_backup_retention_days_remote` | `7` | Remote backup retention in days |
## Runners Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_runner_global_registration_token` | `""` | Global registration token that applies to all runners (can be found in Gitea admin settings) |
| `gitea_runner_image` | `gitea/act_runner` | Docker image for Gitea Actions runners |
| `gitea_runner_container_version` | `latest-dind-rootless` | Docker image tag for runner containers |
| `gitea_runner_restart_policy` | `{{ gitea_restart_policy }}` | Container restart policy for runners |
| `gitea_runners` | `{}` | Dictionary of Gitea Actions runner configurations |
### Runner Configuration Options
Each runner in the `gitea_runners` dictionary supports these options:
| Option | Description |
|--------|-------------|
| `name` | Unique name identifier for the runner |
| `data_mount` | Path relative to app_dir for persistent runner data storage |
| `config_file_mount` | Path relative to app_dir for runner configuration files |
| `cache_enabled` | If `true`, enables action cache functionality (for `actions/cache` support) |
| `cache_port` | Port number on the host for accessing the runner's cache service (must be unique per runner) |
| `registration_token` | Runner-specific registration token (optional if `gitea_runner_global_registration_token` is set) |
## Fail2Ban Security
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_fail2ban_enabled` | `false` | Enable fail2ban protection to automatically ban IPs after failed login attempts |
| `gitea_fail2ban_jail_maxretry` | `10` | Number of failed login attempts before an IP is banned |
| `gitea_fail2ban_jail_findtime` | `3600` | Time window in seconds during which failed attempts are counted |
| `gitea_fail2ban_jail_bantime` | `900` | Duration in seconds that an IP remains banned |
| `gitea_fail2ban_jail_action` | `iptables-allports[chain="FORWARD"]` | Fail2ban action/rule to execute when banning an IP |
## Overall Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_app_name` | `Gitea` | Application name displayed throughout the Gitea interface |
| `gitea_user` | `gitea` | System username that runs the Gitea process inside the container |
| `gitea_run_mode` | `prod` | Application run mode: `prod` (production), `dev` (development), or `test` |
| `gitea_fqdn` | `localhost` | Fully qualified domain name for accessing the Gitea instance |
## Server Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_protocol` | `http` | Protocol for the root URL: `http` or `https` |
| `gitea_http_domain` | `{{ gitea_fqdn }}` | Domain name used in HTTP headers and clone URLs |
| `gitea_root_url` | `{{ gitea_protocol }}://{{ gitea_fqdn }}` | Full public URL where Gitea is accessible |
| `gitea_http_listen` | `127.0.0.1` | IP address the HTTP server binds to; use `0.0.0.0` to allow external access |
| `gitea_internal_http_port` | `3000` | Port number Gitea listens on inside the container |
| `gitea_internal_ssh_port` | `2222` | Port number SSH server listens on inside the container |
| `gitea_ssh_listen` | `0.0.0.0` | IP address the SSH server binds to |
| `gitea_ssh_domain` | `{{ gitea_http_domain }}` | Domain name shown in SSH clone URLs |
| `gitea_start_ssh` | `true` | Enable or disable the built-in SSH server |
| `gitea_landing_page` | `home` | Default page for non-authenticated users: `home`, `explore`, `organizations`, or `login` |
| `gitea_server_extra_config` | `{}` | Dictionary of additional server configuration options not covered above |
## Security Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_secret_key` | | Secret key used for encrypting cookies and tokens (generate with `gitea generate secret SECRET_KEY`) |
| `gitea_internal_token` | | Token used for internal API authentication (generate with `gitea generate secret INTERNAL_TOKEN`) |
| `gitea_install_lock` | `false` | If `true`, prevents the installation wizard from running |
| `gitea_disable_git_hooks` | `true` | If `true`, disables custom Git hooks for security |
| `gitea_disable_webhooks` | `false` | If `true`, disables all webhook functionality |
| `gitea_reverse_proxy_limit` | `1` | Number of reverse proxy hops to trust for obtaining the real client IP |
| `gitea_reverse_proxy_trusted_proxies` | `127.0.0.0/8,::1/128` | Comma-separated list of trusted proxy IP addresses or CIDR ranges |
| `gitea_password_complexity` | `off` | Password requirements: `off`, or comma-separated list of `lower`, `upper`, `digit`, `spec` |
| `gitea_password_min_length` | `8` | Minimum number of characters required for passwords |
| `gitea_password_check_pwn` | `false` | If `true`, checks passwords against the HaveIBeenPwned breach database |
| `gitea_2fa` | | Two-factor authentication setting; set to `enforced` to require 2FA for all users |
| `gitea_login_remember_days` | `31` | Number of days to keep users logged in when they select "Remember Me" |
| `gitea_cookie_remember_name` | `gitea_incredible` | Name of the cookie used for "Remember Me" functionality |
| `gitea_security_extra_config` | `{}` | Dictionary of additional security configuration options |
## Service Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_disable_registration` | `false` | If `true`, disables new user registration entirely |
| `gitea_register_email_confirm` | `false` | If `true`, requires email verification to complete registration |
| `gitea_register_manual_confirm` | `false` | If `true`, requires admin approval for new registrations |
| `gitea_require_signin_view` | `false` | If `true`, requires users to sign in to view any content |
| `gitea_enable_notify_mail` | `false` | If `true`, enables email notifications for events |
| `gitea_enable_captcha` | `false` | If `true`, shows CAPTCHA on registration form |
| `gitea_captcha_type` | `image` | Type of CAPTCHA to use: `image`, `recaptcha`, `hcaptcha`, or `mcaptcha` |
| `gitea_show_registration_button` | `true` | If `true`, displays registration button on login page |
| `gitea_default_keep_email_private` | `false` | If `true`, new users have email privacy enabled by default |
| `gitea_default_allow_create_organization` | `true` | If `true`, new users can create organizations |
| `gitea_default_user_is_restricted` | `false` | If `true`, new users are created with restricted permissions |
| `gitea_default_user_visibility` | `public` | Default visibility for new user profiles: `public`, `limited`, or `private` |
| `gitea_default_org_visibility` | `public` | Default visibility for new organizations: `public`, `limited`, or `private` |
| `gitea_default_org_member_visible` | `false` | If `true`, organization members are visible by default |
| `gitea_allow_only_internal_registration` | `false` | If `true`, only allows registration via internal authentication |
| `gitea_allow_only_external_registration` | `false` | If `true`, only allows registration via external authentication sources |
| `gitea_email_domain_allowlist` | | Comma-separated list of allowed email domains for registration |
| `gitea_email_domain_blocklist` | | Comma-separated list of blocked email domains for registration |
| `gitea_no_reply_address` | | No-reply email address used for system-generated emails |
| `gitea_enable_user_heatmap` | `true` | If `true`, displays user activity heatmap on profiles |
| `gitea_enable_timetracking` | `true` | If `true`, enables time tracking features for issues |
| `gitea_auto_watch_new_repos` | `true` | If `true`, users automatically watch repositories they create |
| `gitea_auto_watch_on_changes` | `false` | If `true`, users automatically watch repositories they contribute to |
| `gitea_show_milestones_dashboard_page` | `true` | If `true`, shows milestones on the dashboard page |
| `gitea_service_extra_config` | `{}` | Dictionary of additional service configuration options |
## Repository Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_repo_force_private` | `false` | If `true`, forces all new repositories to be private |
| `gitea_repo_default_private` | `last` | Default visibility for new repositories: `public`, `private`, or `last` (uses last selection) |
| `gitea_repo_default_push_create_private` | `true` | If `true`, repositories created via push are private by default |
| `gitea_repo_preferred_licenses` | `Apache License 2.0,MIT License` | Comma-separated list of license names to show at the top when creating repositories |
| `gitea_repo_disable_http_git` | `false` | If `true`, disables HTTP(S) Git operations (clone, push, pull) |
| `gitea_repo_disable_migrations` | `false` | If `true`, disables repository migration feature |
| `gitea_repo_disable_stars` | `false` | If `true`, disables the ability to star repositories |
| `gitea_repo_default_branch` | `main` | Default branch name for new repositories |
| `gitea_repository_extra_config` | `{}` | Dictionary of additional repository configuration options |
## CORS Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_cors_enabled` | `false` | Enable Cross-Origin Resource Sharing (CORS) headers |
| `gitea_cors_allowed_domains` | `*` | Domains allowed to make cross-origin requests; `*` allows all |
| `gitea_cors_allowed_methods` | `GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS` | HTTP methods allowed for cross-origin requests |
| `gitea_cors_max_age` | `10m` | Duration to cache preflight CORS request results |
| `gitea_cors_allowed_credentials` | `false` | If `true`, allows credentials (cookies, auth headers) in cross-origin requests |
| `gitea_cors_headers` | `Content-Type,User-Agent` | Custom headers allowed in cross-origin requests |
| `gitea_cors_x_frame_options` | `SAMEORIGIN` | X-Frame-Options header value: `SAMEORIGIN`, `DENY`, or `ALLOW-FROM uri` |
## UI Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_ui_default_theme` | `gitea-auto` | Default theme for the UI; `gitea-auto` switches based on system preference |
| `gitea_ui_themes` | | Comma-separated list of themes to make available; if empty, all themes are available |
| `gitea_ui_show_user_email` | `true` | If `true`, displays user email addresses in the UI (respects privacy settings) |
| `gitea_ui_show_full_name` | `false` | If `true`, displays full names instead of usernames where applicable |
| `gitea_ui_extra_config` | `{}` | Dictionary of additional UI configuration options |
## UI Meta Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_ui_meta_author` | `Gitea - Git with a cup of tea` | Content for the HTML meta author tag |
| `gitea_ui_meta_description` | `Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go` | Content for the HTML meta description tag (used by search engines) |
| `gitea_ui_meta_keywords` | `go,git,self-hosted,gitea` | Comma-separated keywords for the HTML meta keywords tag |
## Indexer Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_issue_indexer_type` | `bleve` | Issue search indexer engine: `bleve` (built-in), `db` (database), `elasticsearch`, or `meilisearch` |
| `gitea_issue_indexer_connection_string` | | Connection string for external indexer (required for `elasticsearch` or `meilisearch`) |
| `gitea_issue_indexer_name` | `gitea_issues` | Index name used in external indexer services |
| `gitea_issue_indexer_path` | `indexers/issues.bleve` | File path for bleve index storage (relative to Gitea data directory) |
| `gitea_repo_indexer_enabled` | `false` | Enable code search functionality (WARNING: requires significant disk space, ~6x repository size) |
| `gitea_repo_indexer_repo_types` | `sources,forks,mirrors,templates` | Types of repositories to include in code search index |
| `gitea_repo_indexer_type` | `bleve` | Code search indexer engine: `bleve` (built-in) or `elasticsearch` |
| `gitea_repo_indexer_path` | `indexers/repos.bleve` | File path for bleve code index storage (relative to Gitea data directory) |
| `gitea_repo_indexer_connection_string` | | Connection string for elasticsearch code indexer |
| `gitea_repo_indexer_name` | `gitea_codes` | Index name for code search in elasticsearch |
| `gitea_repo_indexer_include` | | Glob patterns for files to include in code search (e.g., `**.txt,**.md`); empty includes all |
| `gitea_repo_indexer_exclude` | | Glob patterns for files to exclude from code search (takes precedence over includes) |
| `gitea_repo_indexer_exclude_vendored` | `true` | If `true`, excludes vendored/third-party code from indexing |
| `gitea_repo_indexer_max_file_size` | `1048576` | Maximum file size in bytes to index (default 1 MiB); larger files are skipped |
| `gitea_indexer_startup_timeout` | `30s` | Maximum time to wait for indexer initialization; `-1` disables timeout |
| `gitea_indexer_extra_config` | `{}` | Dictionary of additional indexer configuration options |
## Packages Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_packages_enabled` | `true` | Enable package registry functionality (for npm, Maven, Docker, etc.) |
| `gitea_packages_extra_config` | `{}` | Dictionary of additional package registry configuration options |
## Actions Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_actions_enabled` | `false` | Enable Gitea Actions (CI/CD pipeline functionality) |
| `gitea_actions_default_actions_url` | `github` | Default URL for Actions marketplace; `github`, `self`, or custom URL |
| `gitea_actions_extra_config` | `{}` | Dictionary of additional Actions configuration options |
## Logging Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_log_root_path` | | Root directory for log files; required if `gitea_log_mode` is `file` or for fail2ban integration |
| `gitea_log_mode` | `console` | Log output destination: `console`, `file`, `conn` (network), or `smtp` (email) |
| `gitea_log_level` | `Info` | Logging verbosity level: `Trace`, `Debug`, `Info`, `Warn`, `Error`, or `Critical` |
| `gitea_enable_ssh_log` | `false` | If `true`, enables detailed logging for SSH operations |
| `gitea_log_extra_config` | `{}` | Dictionary of additional logging configuration options |
## Mailer Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_mailer_enabled` | `false` | Enable email functionality for notifications and registration |
| `gitea_mailer_protocol` | | Mail protocol: `smtp`, `smtps`, `smtp+starttls`, `smtp+unix`, `sendmail`, or `dummy` (logs only) |
| `gitea_mailer_smtp_addr` | | Hostname or IP address of the SMTP server |
| `gitea_mailer_smtp_port` | | Port number for the SMTP server (typically 25, 465, or 587) |
| `gitea_mailer_user` | | Username for SMTP authentication |
| `gitea_mailer_password` | | Password for SMTP authentication (should be encrypted with Ansible Vault) |
| `gitea_mailer_from` | `noreply@{{ gitea_http_domain }}` | Email address used as the sender for all outgoing emails |
| `gitea_mailer_subject_prefix` | | Text prepended to all email subject lines |
| `gitea_mailer_send_as_plain_text` | `false` | If `true`, sends emails as plain text instead of HTML |
| `gitea_mailer_extra_config` | `{}` | Dictionary of additional mailer configuration options |
## Mirror Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_mirror_enabled` | `true` | Enable repository mirroring functionality |
| `gitea_mirror_disable_new_pull` | `false` | If `true`, prevents creation of new pull mirrors (mirroring from external repos) |
| `gitea_mirror_disable_new_push` | `false` | If `true`, prevents creation of new push mirrors (mirroring to external repos) |
| `gitea_mirror_default_interval` | `8h` | Default synchronization interval for new mirrors |
| `gitea_mirror_min_interval` | `10m` | Minimum allowed interval between mirror synchronizations |
| `gitea_mirror_extra_config` | `{}` | Dictionary of additional mirror configuration options |
## Metrics Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_metrics_enabled` | `false` | Enable Prometheus metrics endpoint at `/metrics` |
| `gitea_metrics_token` | | Authentication token required to access the metrics endpoint |
| `gitea_metrics_extra_config` | `{}` | Dictionary of additional metrics configuration options |
## API Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_api_enable_swagger` | `true` | Enable Swagger UI for API documentation at `/api/swagger` |
| `gitea_api_max_response_items` | `50` | Maximum number of items returned in a single API response page |
| `gitea_api_default_paging_num` | `30` | Default number of items per page for API responses |
| `gitea_api_extra_config` | `{}` | Dictionary of additional API configuration options |
## OAuth2 Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_oauth2_enabled` | `true` | Enable OAuth2 provider functionality (allows other apps to use Gitea for authentication) |
| `gitea_oauth2_access_token_expiration_time` | `3600` | OAuth2 access token lifetime in seconds (default 1 hour) |
| `gitea_oauth2_refresh_token_expiration_time` | `730` | OAuth2 refresh token lifetime in hours (default ~30 days) |
| `gitea_oauth2_jwt_signing_algorithm` | `RS256` | Algorithm used to sign JWT tokens: `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, or `ES512` |
| `gitea_oauth2_jwt_secret` | | Secret key for signing JWT tokens (auto-generated if not provided) |
| `gitea_oauth2_extra_config` | `{}` | Dictionary of additional OAuth2 configuration options |
## Other Configuration
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_show_footer_version` | `true` | If `true`, displays Gitea version number in the page footer |
| `gitea_show_footer_template_load_time` | `true` | If `true`, displays page generation time in the footer |
| `gitea_enable_sitemap` | `true` | If `true`, generates XML sitemap at `/sitemap.xml` for search engines |
| `gitea_enable_feed` | `true` | If `true`, enables RSS and Atom feeds for repositories and users |
| `gitea_other_extra_config` | `{}` | Dictionary of additional miscellaneous configuration options |
## Additional Configuration
> [!NOTE]
> Not all variables that Gitea supports have been implemented yet. Read the following secion to add additional configuration options.
| Variable Name | Default Value | Description |
|---------------|---------------|-------------|
| `gitea_extra_config` | `{}` | Dictionary of any additional environment variables to pass to Gitea; consult the [Gitea configuration cheat sheet](https://docs.gitea.com/administration/config-cheat-sheet) for available options |
### Example: Using `gitea_extra_config`
```yaml
gitea_extra_config:
GITEA__webhook__ALLOWED_HOST_LIST: "external"
GITEA__webhook__SKIP_TLS_VERIFY: "false"
GITEA__cron__ENABLED: "true"
```
## Understanding Extra Configuration Variables
Many configuration sections include an `*_extra_config` variable (e.g., `gitea_server_extra_config`, `gitea_security_extra_config`, etc.). These variables allow you to add additional Gitea configuration options that aren't explicitly defined as separate variables in this role.
### How Extra Config Variables Work
Each `*_extra_config` variable is a dictionary that gets merged into the corresponding section of the Gitea configuration. The role converts these dictionaries into the appropriate environment variable format that Gitea expects.
### Naming Convention
Gitea uses environment variables with a specific naming pattern:
```
GITEA__<section>__<key>
```
When you use an `*_extra_config` variable, the role automatically handles the section name for you. You only need to provide the key-value pairs.
### Available Extra Config Variables
| Variable | Maps to Gitea Section |
|----------|----------------------|
| `gitea_server_extra_config` | `[server]` |
| `gitea_security_extra_config` | `[security]` |
| `gitea_service_extra_config` | `[service]` |
| `gitea_repository_extra_config` | `[repository]` |
| `gitea_ui_extra_config` | `[ui]` |
| `gitea_indexer_extra_config` | `[indexer]` |
| `gitea_packages_extra_config` | `[packages]` |
| `gitea_actions_extra_config` | `[actions]` |
| `gitea_log_extra_config` | `[log]` |
| `gitea_mailer_extra_config` | `[mailer]` |
| `gitea_mirror_extra_config` | `[mirror]` |
| `gitea_metrics_extra_config` | `[metrics]` |
| `gitea_api_extra_config` | `[api]` |
| `gitea_oauth2_extra_config` | `[oauth2]` |
| `gitea_other_extra_config` | `[other]` |
### Examples
#### Adding Server Configuration
```yaml
gitea_server_extra_config:
OFFLINE_MODE: true
DISABLE_ROUTER_LOG: false
ENABLE_GZIP: true
```
This translates to these environment variables:
```
GITEA__server__OFFLINE_MODE=true
GITEA__server__DISABLE_ROUTER_LOG=false
GITEA__server__ENABLE_GZIP=true
```
#### Using gitea_extra_config for Any Section
If you need to configure a section that doesn't have a dedicated `*_extra_config` variable, or want to set options across multiple sections, use `gitea_extra_config`:
```yaml
gitea_extra_config:
# Webhook configuration
GITEA__webhook__ALLOWED_HOST_LIST: "external"
GITEA__webhook__SKIP_TLS_VERIFY: "false"
# Cron configuration
GITEA__cron__ENABLED: "true"
GITEA__cron_DOT_update_checker__ENABLED: "false"
# Git configuration
GITEA__git__DISABLE_DIFF_HIGHLIGHT: "false"
GITEA__git__timeout__DEFAULT: "360"
```
### Finding Available Options
For a complete list of available configuration options, refer to the official [Gitea Configuration Cheat Sheet](https://docs.gitea.com/administration/config-cheat-sheet).
### Important Notes
1. **Values**: All values in `*_extra_config` dictionaries should be strings, numbers, or booleans.
2. **Priority**: Variables defined in `*_extra_config` can override the explicitly defined role variables if they conflict.
3. **Validation**: The role does not validate extra configuration options. Ensure you're using valid Gitea configuration keys by consulting the official documentation.
# License
MIT License
+253
View File
@@ -0,0 +1,253 @@
---
app_name: gitea
# User configuration. Note that if using rootless, the uid and gid must be 1000
gitea_uid: 1000
gitea_gid: 1000
# Container configuration
gitea_container_name: "{{ app_name | default('gitea') }}"
gitea_container_version: latest-rootless
gitea_restart_policy: "{{ app_restart_policy }}"
# Network configuration
gitea_http_port: 3000
gitea_ssh_port: 2222
# Volume paths
gitea_data_path: "{{ app_dir }}/data"
gitea_config_path: "{{ app_dir }}/config"
gitea_log_path: "{{ app_dir }}/log"
gitea_users: []
# gitea_users:
# - username: someuser
# email: user@example.com
# password: somepass # Should be a vault secret
# admin: true
# must_change_password: true
# state: present # `absent` if you want to delete this user
gitea_runners: []
# - name: <runner-name>
# data_mount: ./runners/main_runner
# registration_token: <token>
# cache_enabled: true
# cache_port: <port> # Use a unique port
gitea_runner_global_registration_token: ""
gitea_runner_image: gitea/act_runner
gitea_runner_container_version: latest-dind-rootless
gitea_runner_restart_policy: "{{ gitea_restart_policy }}"
# Fail2Ban vars
gitea_fail2ban_enabled: false
gitea_fail2ban_jail_maxretry: 10
gitea_fail2ban_jail_findtime: 3600
gitea_fail2ban_jail_bantime: 900
gitea_fail2ban_jail_action: 'iptables-allports[chain="FORWARD"]'
# App-specific configuration
# Overall (DEFAULT)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#overall-default
gitea_app_name: "Gitea"
gitea_user: "gitea"
gitea_run_mode: "prod"
gitea_fqdn: "localhost"
# Repository Configuration
# ->
gitea_repo_force_private: false
gitea_repo_default_private: 'last'
gitea_repo_default_push_create_private: true
gitea_repo_preferred_licenses: 'Apache License 2.0,MIT License'
gitea_repo_disable_http_git: false
gitea_repo_disable_migrations: false
gitea_repo_disable_stars: false
gitea_repo_default_branch: 'main'
gitea_repository_extra_config: {}
# CORS Configuration
# ->
gitea_cors_enabled: false
gitea_cors_allowed_domains: '*'
gitea_cors_allowed_methods: 'GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS'
gitea_cors_max_age: '10m'
gitea_cors_allowed_credentials: false
gitea_cors_headers: 'Content-Type,User-Agent'
gitea_cors_x_frame_options: 'SAMEORIGIN'
# UI Configuration
# ->
gitea_ui_default_theme: "gitea-auto"
gitea_ui_themes: ""
gitea_ui_show_user_email: true
gitea_ui_show_full_name: false
gitea_ui_extra_config: {}
# UI Meta Configuration
# ->
gitea_ui_meta_author: 'Gitea - Git with a cup of tea'
gitea_ui_meta_description: 'Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go'
gitea_ui_meta_keywords: 'go,git,self-hosted,gitea'
# Server (server)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#server-server
gitea_protocol: "http"
gitea_http_domain: "{{ gitea_fqdn }}"
gitea_root_url: "{{ gitea_protocol }}://{{ gitea_fqdn }}"
gitea_http_listen: "127.0.0.1"
gitea_internal_http_port: 3000
gitea_internal_ssh_port: 2222
gitea_ssh_listen: "0.0.0.0"
gitea_start_ssh: true
gitea_ssh_domain: "{{ gitea_http_domain }}"
gitea_landing_page: 'home'
gitea_server_extra_config: {}
# Security (security)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#security-security
gitea_secret_key: ""
gitea_internal_token: ""
gitea_install_lock: false
gitea_disable_git_hooks: true
gitea_disable_webhooks: false
gitea_reverse_proxy_limit: 1
gitea_reverse_proxy_trusted_proxies: "127.0.0.0/8,::1/128"
gitea_password_complexity: "off"
gitea_password_min_length: 8
gitea_password_check_pwn: false
gitea_2fa: ""
gitea_login_remember_days: 31
gitea_cookie_remember_name: "gitea_incredible"
gitea_security_extra_config: {}
# Service (service)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#service-service
gitea_disable_registration: false
gitea_register_email_confirm: false
gitea_register_manual_confirm: false
gitea_require_signin_view: false
gitea_enable_notify_mail: false
gitea_enable_captcha: false
gitea_require_captcha_for_login: false
gitea_captcha_type: image
gitea_show_registration_button: true
gitea_default_keep_email_private: false
gitea_default_allow_create_organization: true
gitea_default_user_is_restricted: false
gitea_default_user_visibility: public
gitea_default_org_visibility: public
gitea_default_org_member_visible: false
gitea_allow_only_internal_registration: false
gitea_allow_only_external_registration: false
gitea_email_domain_allowlist: ""
gitea_email_domain_blocklist: ""
gitea_no_reply_address: ""
gitea_enable_user_heatmap: true
gitea_enable_timetracking: true
gitea_auto_watch_new_repos: true
gitea_auto_watch_on_changes: false
gitea_show_milestones_dashboard_page: true
gitea_service_extra_config: {}
# Indexer (indexer)
# -> https://docs.gitea.com/administration/config-cheat-sheet#indexer-indexer
gitea_issue_indexer_type: 'bleve'
gitea_issue_indexer_connection_string: ''
gitea_issue_indexer_name: 'gitea_issues'
gitea_issue_indexer_path: 'indexers/issues.bleve'
gitea_repo_indexer_enabled: false
gitea_repo_indexer_repo_types: 'sources,forks,mirrors,templates'
gitea_repo_indexer_type: 'bleve'
gitea_repo_indexer_path: 'indexers/repos.bleve'
gitea_repo_indexer_connection_string: ''
gitea_repo_indexer_name: 'gitea_codes'
gitea_repo_indexer_include: ''
gitea_repo_indexer_exclude: ''
gitea_repo_indexer_exclude_vendored: true
gitea_repo_indexer_max_file_size: 1048576
gitea_indexer_startup_timeout: '30s'
gitea_indexer_extra_config: {}
# Packages (packages)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#packages-packages
gitea_packages_enabled: true
gitea_packages_extra_config: {}
# Actions (actions)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#actions-actions
gitea_actions_enabled: false
gitea_actions_default_actions_url: github
gitea_actions_extra_config: {}
# Log (log)
# -> https://docs.gitea.com/next/administration/config-cheat-sheet#log-log
gitea_log_root_path: ""
gitea_log_mode: console
gitea_log_level: Info
gitea_enable_ssh_log: false
gitea_log_extra_config: {}
# Mailer (mailer)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#mailer-mailer
gitea_mailer_enabled: false
gitea_mailer_protocol: "" # smtp, smtps, smtp+starttls, smtp+unix, sendmail, dummy
gitea_mailer_smtp_addr: ""
gitea_mailer_smtp_port: ""
gitea_mailer_user: ""
gitea_mailer_password: ""
gitea_mailer_from: "noreply@{{ gitea_http_domain }}"
gitea_mailer_subject_prefix: ""
gitea_mailer_send_as_plain_text: false
gitea_mailer_extra_config: {}
# Mirror (mirror)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#mirror-mirror
gitea_mirror_enabled: true
gitea_mirror_disable_new_pull: false
gitea_mirror_disable_new_push: false
gitea_mirror_default_interval: 8h
gitea_mirror_min_interval: 10m
gitea_mirror_extra_config: {}
# Other (other)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#other-other
gitea_show_footer_version: true
gitea_show_footer_template_load_time: true
gitea_enable_sitemap: true
gitea_enable_feed: true
gitea_other_extra_config: {}
# Metrics (metrics)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#metrics-metrics
gitea_metrics_enabled: false
gitea_metrics_token: ""
gitea_metrics_extra_config: {}
# API (api)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#api-api
gitea_api_enable_swagger: true
gitea_api_max_response_items: 50
gitea_api_default_paging_num: 30
gitea_api_extra_config: {}
# OAuth2 (oauth2)
# -> https://docs.gitea.io/en-us/config-cheat-sheet/#oauth2-oauth2
gitea_oauth2_enabled: true
gitea_oauth2_access_token_expiration_time: 3600
gitea_oauth2_refresh_token_expiration_time: 730
gitea_oauth2_jwt_signing_algorithm: RS256
gitea_oauth2_jwt_secret: ""
gitea_oauth2_extra_config: {}
# A dictionary of additional environment variables
# Read the cheat sheet before adding configurations https://docs.gitea.com/administration/config-cheat-sheet
gitea_extra_config: {}
# ENV_VAR_KEY: value
+6
View File
@@ -0,0 +1,6 @@
---
- name: "Restart fail2ban"
become: true
ansible.builtin.service:
name: fail2ban
state: restarted
+2
View File
@@ -0,0 +1,2 @@
install_date: Tue Dec 2 19:10:42 2025
version: ''
+40
View File
@@ -0,0 +1,40 @@
---
galaxy_info:
app_role_name: gitea
author: Patrick Jaroszewski
description: Ansible role to configure and deploy Gitea in Docker, with optional support for runners.
license: MIT License
min_ansible_version: 2.11
platforms:
- name: Debian
versions: all
- name: Ubuntu
version: all
galaxy_tags:
- gitea
- act_runner
- git
- gitserver
- selfhosted
dependencies:
- role: patrickj.docker_apps.docker_compose_app
vars:
app_role_name: gitea
app_compose_validate: false
app_compose_start: false
app_uid: "{{ gitea_uid }}"
app_gid: "{{ gitea_gid }}"
app_extra_templates:
- src: env.j2
dest: "{{ app_dir }}/.env"
# Directory structure
app_subdirectories:
- "{{ gitea_data_path }}"
- "{{ gitea_config_path }}"
- "{{ gitea_log_path }}"
# Backup configuration
app_backup_subdirectories:
- "{{ gitea_data_path }}"
- "{{ gitea_config_path }}"
+24
View File
@@ -0,0 +1,24 @@
---
- name: Get host IP
ansible.builtin.set_fact:
gitea_host_ip: "{{ ansible_default_ipv4.address }}"
- name: Create data directories for runners
ansible.builtin.file:
path: "{{ app_dir }}/{{ item.data_mount }}"
state: directory
mode: "{{ app_permission_mode }}"
owner: "{{ app_uid }}"
group: "{{ app_gid }}"
loop: "{{ gitea_runners }}"
- name: Create configuration files for each runner
ansible.builtin.template:
src: actions/config.yaml.j2
dest: "{{ app_dir }}/{{ item.config_file_mount }}"
mode: "{{ app_permission_mode }}"
owner: "{{ app_uid }}"
group: "{{ app_gid }}"
loop: "{{ gitea_runners }}"
+17
View File
@@ -0,0 +1,17 @@
---
- name: Deploy optional fail2ban rules
ansible.builtin.include_tasks: setup-fail2ban.yaml
when: gitea_fail2ban_enabled | bool
- name: Generate Gitea configuration files
ansible.builtin.include_tasks: generate-config.yaml
- name: Create or remove Gitea users
ansible.builtin.include_tasks: manage_users.yaml
when: gitea_users | length > 0
- name: Start Docker Compose stack after configuration
ansible.builtin.include_tasks: "{{ app_roles_path }}/docker_compose_app/tasks/manage_compose.yaml"
vars:
app_compose_start: true
+58
View File
@@ -0,0 +1,58 @@
---
- name: Get list of users
community.docker.docker_container_exec:
container: "{{ gitea_container_name }}"
command: /bin/bash -c "gitea admin user list"
register: user_list
failed_when: false
changed_when: false
when: gitea_users | length > 0
- name: Extract existing usernames
ansible.builtin.set_fact:
gitea_existing_users: "{{ user_list.stdout_lines[1:] | map('regex_replace', '^\\d+\\s+(\\S+)\\s+.*$', '\\1') | list | default([]) }}"
when:
- gitea_users | length > 0
- user_list.stdout_lines | default([]) | length > 1
- name: Create Gitea users
community.docker.docker_container_exec:
container: "{{ gitea_container_name }}"
command: >
/bin/bash -c "gitea admin user create
--username {{ user.username }}
--email {{ user.email }}
--password {{ user.password }}
--must-change-password={{ user.must_change_password | default(false) }}
--admin={{ user.admin | default(false) }}"
register: _gitea_user_result
failed_when:
- '"successfully created" not in _gitea_user_result.stdout'
changed_when:
- '"successfully created!" in _gitea_user_result.stdout'
when:
- user.username not in gitea_existing_users | default([]) and user.state | default('present') == 'present'
loop: "{{ gitea_users }}"
loop_control:
label: "user={{ user.username }}"
loop_var: user
# no_log: true # Avoid logging passwords
- name: Remove gitea users
community.docker.docker_container_exec:
container: "{{ gitea_container_name }}"
command: >
/bin/bash -c "gitea admin user delete
--username {{ user.username }}
--email {{ user.email }}"
register: _gitea_user_del_result
failed_when:
- '"error" in _gitea_user_del_result.stdout'
changed_when: "user.username in gitea_existing_users"
when: "user.username in gitea_existing_users | default([]) and user.state | default('present') == 'absent'"
loop: "{{ gitea_users }}"
loop_control:
label: "user={{ user.username }}"
loop_var: user
+39
View File
@@ -0,0 +1,39 @@
---
- name: Gather installed packages for checks later on
ansible.builtin.package_facts:
manager: "auto"
- name: Warn if fail2ban is not installed
ansible.builtin.fail:
msg: "the package fail2ban is not installed. no fail2ban filters deployed."
when: "'fail2ban' not in ansible_facts.packages"
failed_when: false
- name: Install fail2ban filter
become: true
ansible.builtin.template:
src: fail2ban/filter.conf.j2
dest: /etc/fail2ban/filter.d/gitea.local
owner: root
group: root
mode: "0444"
notify: "Restart fail2ban"
when: "'fail2ban' in ansible_facts.packages"
- name: Install fail2ban jail for logins over HTTP(S)
become: true
vars:
gitea_fail2ban_filter: gitea
gitea_fail2ban_port: "http,https,{{ gitea_ssh_port }}"
gitea_fail2ban_jail_name: gitea-docker
ansible.builtin.template:
src: fail2ban/jail.conf.j2
dest: /etc/fail2ban/jail.d/gitea.local
owner: root
group: root
mode: "0444"
notify: "Restart fail2ban"
when: "'fail2ban' in ansible_facts.packages"
@@ -0,0 +1,111 @@
# Example configuration file, it's safe to copy this as the default config file without any modification.
# https://gitea.com/gitea/act_runner/src/branch/main/internal/pkg/config/config.example.yaml
# You don't have to copy this file to your instance,
# just run `./act_runner generate-config > config.yaml` to generate a config file.
log:
# The level of logging, can be trace, debug, info, warn, error, fatal
level: info
runner:
# Where to store the registration result.
file: .runner
# Execute how many tasks concurrently at the same time.
capacity: 1
# Extra environment variables to run jobs.
envs:
# A_TEST_ENV_NAME_1: a_test_env_value_1
# A_TEST_ENV_NAME_2: a_test_env_value_2
# Extra environment variables to run jobs from a file.
# It will be ignored if it's empty or the file doesn't exist.
env_file: .env
# The timeout for a job to be finished.
# Please note that the Gitea instance also has a timeout (3h by default) for the job.
# So the job could be stopped by the Gitea instance if its timeout is shorter than this.
timeout: 3h
# The timeout for the runner to wait for running jobs to finish when shutting down.
# Any running jobs that haven't finished after this timeout will be cancelled.
shutdown_timeout: 0s
# Whether skip verifying the TLS certificate of the Gitea instance.
insecure: false
# The timeout for fetching the job from the Gitea instance.
fetch_timeout: 5s
# The interval for fetching the job from the Gitea instance.
fetch_interval: 2s
# The github_mirror of a runner is used to specify the mirror address of the github that pulls the action repository.
# It works when something like `uses: actions/checkout@v4` is used and DEFAULT_ACTIONS_URL is set to github,
# and github_mirror is not empty. In this case,
# it replaces https://github.com with the value here, which is useful for some special network environments.
github_mirror: ''
# The labels of a runner are used to determine which jobs the runner can run, and how to run them.
# Like: "macos-arm64:host" or "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
# Find more images provided by Gitea at https://gitea.com/gitea/runner-images .
# If it's empty when registering, it will ask for inputting labels.
# If it's empty when execute `daemon`, will use labels in `.runner` file.
labels:
- "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"
cache:
# Enable cache server to use actions/cache.
enabled: {{ item.cache_enabled | bool | lower }}
# The directory to store the cache data.
# If it's empty, the cache data will be stored in $HOME/.cache/actcache.
dir: ""
# The host of the cache server.
# It's not for the address to listen, but the address to connect from job containers.
# So 0.0.0.0 is a bad choice, leave it empty to detect automatically.
host: {{ gitea_host_ip }}
# The port of the cache server.
# 0 means to use a random available port.
port: {{ item.cache_port }}
# The external cache server URL. Valid only when enable is true.
# If it's specified, act_runner will use this URL as the ACTIONS_CACHE_URL rather than start a server by itself.
# The URL should generally end with "/".
external_server: ""
container:
# Specifies the network to which the container will connect.
# Could be host, bridge or the name of a custom network.
# If it's empty, act_runner will create a network automatically.
network: ""
# Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker).
privileged: false
# Any other options to be used when the container is started (e.g., --add-host=my.gitea.url:host-gateway).
options:
# The parent directory of a job's working directory.
# NOTE: There is no need to add the first '/' of the path as act_runner will add it automatically.
# If the path starts with '/', the '/' will be trimmed.
# For example, if the parent directory is /path/to/my/dir, workdir_parent should be path/to/my/dir
# If it's empty, /workspace will be used.
workdir_parent:
# Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob
# You can specify multiple volumes. If the sequence is empty, no volumes can be mounted.
# For example, if you only allow containers to mount the `data` volume and all the json files in `/src`, you should change the config to:
# valid_volumes:
# - data
# - /src/*.json
# If you want to allow any volume, please use the following configuration:
# valid_volumes:
# - '**'
valid_volumes: []
# Overrides the docker client host with the specified one.
# If it's empty, act_runner will find an available docker host automatically.
# If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers.
# If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work.
docker_host: ""
# Pull docker image(s) even if already present
force_pull: true
# Rebuild docker image(s) even if already present
force_rebuild: false
# Always require a reachable docker daemon, even if not required by act_runner
require_docker: false
# Timeout to wait for the docker daemon to be reachable, if docker is required by require_docker or act_runner
docker_timeout: 0s
host:
# The parent directory of a job's working directory.
# If it's empty, $HOME/.cache/act/ will be used.
workdir_parent:
+42
View File
@@ -0,0 +1,42 @@
---
services:
gitea:
image: docker.gitea.com/gitea:{{ gitea_container_version }}
container_name: "{{ gitea_container_name }}"
restart: "{{ gitea_restart_policy }}"
environment:
- USER_UID={{ app_uid }}
- USER_GID={{ app_gid }}
env_file:
- .env
volumes:
- "{{ gitea_data_path }}:/var/lib/gitea"
- "{{ gitea_config_path }}:/etc/gitea"
- "{{ gitea_log_path }}:/var/log/gitea"
- "/etc/timezone:/etc/timezone:ro"
- "/etc/localtime:/etc/localtime:ro"
ports:
- "127.0.0.1:{{ gitea_http_port }}:3000"
- "0.0.0.0:{{ gitea_ssh_port }}:2222"
{% for runner in gitea_runners %}
{{ runner.name }}:
image: "{{ gitea_runner_image }}:{{ gitea_runner_container_version }}"
container_name: "{{ app_name }}-{{ runner.name }}"
restart: "{{ gitea_runner_restart_policy }}"
privileged: true
depends_on:
- "{{ gitea_container_name }}"
volumes:
- {{ runner.config_file_mount }}:/config.yaml
- {{ runner.data_mount }}:/data
{% if runner.cache_enabled %}
ports:
- 127.0.0.1:{{ runner.cache_port }}:{{ runner.cache_port }}
{% endif %}
environment:
CONFIG_FILE: /config.yaml
GITEA_RUNNER_NAME: {{ runner.name }}
GITEA_INSTANCE_URL: {{ gitea_root_url }}
DOCKER_HOST: "unix:///var/run/user/{{ app_uid }}/docker.sock"
GITEA_RUNNER_REGISTRATION_TOKEN: {{ gitea_runner_global_registration_token | default(runner.registration_token) | default('') }}
{% endfor %}
+429
View File
@@ -0,0 +1,429 @@
# ============================================
# Default Configuration
# ============================================
GITEA__DEFAULT__APP_NAME={{ gitea_app_name }}
GITEA__DEFAULT__RUN_MODE={{ gitea_run_mode }}
GITEA__DEFAULT__RUN_USER={{ gitea_user }}
# ============================================
# Server Configuration
# ============================================
GITEA__server__PROTOCOL={{ gitea_protocol }}
GITEA__server__DOMAIN={{ gitea_http_domain }}
GITEA__server__ROOT_URL={{ gitea_root_url }}
GITEA__server__HTTP_ADDR={{ gitea_http_listen }}
GITEA__server__HTTP_PORT={{ gitea_internal_http_port }}
GITEA__server__SSH_PORT={{ gitea_internal_ssh_port }}
GITEA__server__SSH_LISTEN_HOST={{ gitea_ssh_listen }}
GITEA__server__START_SSH_SERVER={{ gitea_start_ssh | bool | lower }}
GITEA__server__SSH_DOMAIN={{ gitea_ssh_domain }}
GITEA__server__LANDING_PAGE={{ gitea_landing_page }}
{% if gitea_server_extra_config %}
# Additional Server Configuration
{% for item in gitea_server_extra_config | dict2items %}
GITEA__server__{{ item.key }}={{ item.value }}
{% endfor %}
{% endif %}
# ============================================
# Service Configuration
# ============================================
GITEA__service__DISABLE_REGISTRATION={{ gitea_disable_registration | bool | lower }}
GITEA__service__REGISTER_EMAIL_CONFIRM={{ gitea_register_email_confirm | bool | lower }}
GITEA__service__REGISTER_MANUAL_CONFIRM={{ gitea_register_manual_confirm | bool | lower }}
GITEA__service__REQUIRE_SIGNIN_VIEW={{ gitea_require_signin_view | bool | lower }}
GITEA__service__ENABLE_NOTIFY_MAIL={{ gitea_enable_notify_mail | bool | lower }}
GITEA__service__ENABLE_CAPTCHA={{ gitea_enable_captcha | bool | lower }}
{% if gitea_enable_captcha %}
GITEA__service__REQUIRE_CAPTCHA_FOR_LOGIN={{ gitea_require_captcha_for_login }}
GITEA__service__CAPTCHA_TYPE={{ gitea_captcha_type }}
{% endif %}
GITEA__service__SHOW_REGISTRATION_BUTTON={{ gitea_show_registration_button | bool | lower }}
GITEA__service__DEFAULT_KEEP_EMAIL_PRIVATE={{ gitea_default_keep_email_private | bool | lower }}
GITEA__service__DEFAULT_ALLOW_CREATE_ORGANIZATION={{ gitea_default_allow_create_organization | bool | lower }}
GITEA__service__DEFAULT_USER_IS_RESTRICTED={{ gitea_default_user_is_restricted | bool | lower }}
GITEA__service__DEFAULT_USER_VISIBILITY={{ gitea_default_user_visibility }}
GITEA__service__DEFAULT_ORG_VISIBILITY={{ gitea_default_org_visibility }}
GITEA__service__DEFAULT_ORG_MEMBER_VISIBLE={{ gitea_default_org_member_visible | bool | lower }}
GITEA__service__ALLOW_ONLY_INTERNAL_REGISTRATION={{ gitea_allow_only_internal_registration | bool | lower }}
GITEA__service__ALLOW_ONLY_EXTERNAL_REGISTRATION={{ gitea_allow_only_external_registration | bool | lower }}
{% if gitea_email_domain_allowlist %}
GITEA__service__EMAIL_DOMAIN_ALLOWLIST={{ gitea_email_domain_allowlist }}
{% endif %}
{% if gitea_email_domain_blocklist %}
GITEA__service__EMAIL_DOMAIN_BLOCKLIST={{ gitea_email_domain_blocklist }}
{% endif %}
{% if gitea_no_reply_address %}
GITEA__service__NO_REPLY_ADDRESS={{ gitea_no_reply_address }}
{% endif %}
GITEA__service__ENABLE_USER_HEATMAP={{ gitea_enable_user_heatmap | bool | lower }}
GITEA__service__ENABLE_TIMETRACKING={{ gitea_enable_timetracking | bool | lower }}
GITEA__service__AUTO_WATCH_NEW_REPOS={{ gitea_auto_watch_new_repos | bool | lower }}
GITEA__service__AUTO_WATCH_ON_CHANGES={{ gitea_auto_watch_on_changes | bool | lower }}
GITEA__service__SHOW_MILESTONES_DASHBOARD_PAGE={{ gitea_show_milestones_dashboard_page | bool | lower }}
{% if gitea_service_extra_config %}
# Additional Service Configuration
{% for item in gitea_service_extra_config | dict2items %}
{% if item.value is boolean %}
GITEA__service__{{ item.key }}={{ item.value | bool | lower }}
{% else %}
GITEA__service__{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
{% endif %}
# ============================================
# Security Configuration
# ============================================
{% if gitea_secret_key %}
GITEA__security__SECRET_KEY={{ gitea_secret_key }}
{% endif %}
{% if gitea_internal_token %}
GITEA__security__INTERNAL_TOKEN={{ gitea_internal_token }}
{% endif %}
GITEA__security__INSTALL_LOCK={{ gitea_install_lock | bool | lower }}
GITEA__security__DISABLE_GIT_HOOKS={{ gitea_disable_git_hooks | bool | lower }}
GITEA__security__DISABLE_WEBHOOKS={{ gitea_disable_webhooks | bool | lower }}
GITEA__security__PASSWORD_COMPLEXITY={{ gitea_password_complexity }}
GITEA__security__PASSWORD_MIN_LENGTH={{ gitea_password_min_length }}
GITEA__security__PASSWORD_CHECK_PWN={{ gitea_password_check_pwn | bool | lower }}
{% if gitea_2fa %}
GITEA__security__TWO_FACTOR_AUTH={{ gitea_2fa }}
{% endif %}
GITEA__security__LOGIN_REMEMBER_DAYS={{ gitea_login_remember_days }}
GITEA__security__COOKIE_REMEMBER_NAME={{ gitea_cookie_remember_name }}
{% if gitea_security_extra_config %}
# Additional Security Configuration
{% for item in gitea_security_extra_config | dict2items %}
GITEA__security__{{ item.key }}={{ item.value if item.value is not boolean else (item.value | bool | lower) }}
{% endfor %}
{% endif %}
# ============================================
# Repository Configuration
# ============================================
GITEA__repository__FORCE_PRIVATE={{ gitea_repo_force_private }}
GITEA__repository__DEFAULT_PRIVATE={{ gitea_repo_default_private }}
GITEA__repository__DEFAULT_PUSH_CREATE_PRIVATE={{ gitea_repo_default_push_create_private }}
GITEA__repository__PREFERRED_LICENSES={{ gitea_repo_preferred_licenses }}
GITEA__repository__DISABLE_HTTP_GIT={{ gitea_repo_disable_http_git }}
GITEA__repository__DEFAULT_BRANCH={{ gitea_repo_default_branch }}
GITEA__repository__DISABLE_STARS={{ gitea_repo_disable_stars }}
GITEA__repository__DISABLE_MIGRATIONS={{ gitea_repo_disable_migrations }}
{% if gitea_repository_extra_config %}
# Additional Repository Configuration
{% for item in gitea_repository_extra_config | dict2items %}
{% if item.value is boolean %}
GITEA__repository__{{ item.key }}={{ item.value | bool | lower }}
{% else %}
GITEA__repository__{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
{% endif %}
# ============================================
# CORS Configuration
# ============================================
GITEA__cors__ENABLED={{ gitea_cors_enabled }}
GITEA__cors__ALLOW_DOMAIN={{ gitea_cors_allowed_domains }}
GITEA__cors__METHODS={{ gitea_cors_allowed_methods }}
GITEA__cors__MAX_AGE={{ gitea_cors_max_age }}
GITEA__cors__ALLOW_CREDENTIALS={{ gitea_cors_allowed_credentials | bool | lower }}
GITEA__cors__HEADERS={{ gitea_cors_headers }}
GITEA__cors__X_FRAME_OPTIONS={{ gitea_cors_x_frame_options }}
# ============================================
# UI Configuration
# ============================================
GITEA__ui__DEFAULT_THEME={{ gitea_ui_default_theme }}
GITEA__ui__THEMES={{ gitea_ui_themes }}
GITEA__ui__SHOW_USER_EMAIL={{ gitea_ui_show_user_email }}
GITEA__ui__DEFAULT_SHOW_FULL_NAME={{ gitea_ui_show_full_name }}
{% if gitea_ui_extra_config %}
# Additional UI Configuration
{% for item in gitea_ui_extra_config | dict2items %}
{% if item.value is boolean %}
GITEA__ui__{{ item.key }}={{ item.value | bool | lower }}
{% else %}
GITEA__ui__{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
{% endif %}
# ============================================
# UI.meta Configuration
# ============================================
GITEA__ui.meta__AUTHOR={{ gitea_ui_meta_author }}
GITEA__ui.meta__DESCRIPTION={{ gitea_ui_meta_description }}
GITEA__ui.meta__KEYWORDS={{ gitea_ui_meta_keywords }}
# ============================================
# Indexer Configuration
# ============================================
# Issue Indexer
GITEA__indexer__ISSUE_INDEXER_TYPE={{ gitea_issue_indexer_type }}
{% if gitea_issue_indexer_type in ['elasticsearch', 'meilisearch'] and gitea_issue_indexer_connection_string %}
GITEA__indexer__ISSUE_INDEXER_CONN_STR={{ gitea_issue_indexer_connection_string }}
{% endif %}
{% if gitea_issue_indexer_type in ['elasticsearch', 'meilisearch'] and gitea_issue_indexer_name %}
GITEA__indexer__ISSUE_INDEXER_NAME={{ gitea_issue_indexer_name }}
{% endif %}
{% if gitea_issue_indexer_type == 'bleve' and gitea_issue_indexer_path %}
GITEA__indexer__ISSUE_INDEXER_PATH={{ gitea_issue_indexer_path }}
{% endif %}
# Repository Indexer
GITEA__indexer__REPO_INDEXER_ENABLED={{ gitea_repo_indexer_enabled | bool | lower }}
{% if gitea_repo_indexer_enabled %}
{% if gitea_repo_indexer_repo_types %}
GITEA__indexer__REPO_INDEXER_REPO_TYPES={{ gitea_repo_indexer_repo_types }}
{% endif %}
GITEA__indexer__REPO_INDEXER_TYPE={{ gitea_repo_indexer_type }}
{% if gitea_repo_indexer_type == 'bleve' and gitea_repo_indexer_path %}
GITEA__indexer__REPO_INDEXER_PATH={{ gitea_repo_indexer_path }}
{% endif %}
{% if gitea_repo_indexer_type == 'elasticsearch' and gitea_repo_indexer_connection_string %}
GITEA__indexer__REPO_INDEXER_CONN_STR={{ gitea_repo_indexer_connection_string }}
{% endif %}
{% if gitea_repo_indexer_type == 'elasticsearch' and gitea_repo_indexer_name %}
GITEA__indexer__REPO_INDEXER_NAME={{ gitea_repo_indexer_name }}
{% endif %}
{% if gitea_repo_indexer_include %}
GITEA__indexer__REPO_INDEXER_INCLUDE={{ gitea_repo_indexer_include }}
{% endif %}
{% if gitea_repo_indexer_exclude %}
GITEA__indexer__REPO_INDEXER_EXCLUDE={{ gitea_repo_indexer_exclude }}
{% endif %}
GITEA__indexer__REPO_INDEXER_EXCLUDE_VENDORED={{ gitea_repo_indexer_exclude_vendored | bool | lower }}
GITEA__indexer__MAX_FILE_SIZE={{ gitea_repo_indexer_max_file_size }}
{% endif %}
{% if gitea_indexer_startup_timeout %}
GITEA__indexer__STARTUP_TIMEOUT={{ gitea_indexer_startup_timeout }}
{% endif %}
{% if gitea_indexer_extra_config %}
# Additional Indexer Configuration
{% for item in gitea_indexer_extra_config | dict2items %}
{% if item.value is boolean %}
GITEA__indexer__{{ item.key }}={{ item.value | bool | lower }}
{% else %}
GITEA__indexer__{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
{% endif %}
# ============================================
# Packages Configuration
# ============================================
GITEA__packages__ENABLED={{ gitea_packages_enabled | bool | lower }}
{% if gitea_packages_extra_config %}
# Additional Packages Configuration
{% for item in gitea_packages_extra_config | dict2items %}
GITEA__packages__{{ item.key }}={{ item.value if item.value is not boolean else (item.value | bool | lower) }}
{% endfor %}
{% endif %}
# ============================================
# Actions Configuration
# ============================================
GITEA__actions__ENABLED={{ gitea_actions_enabled | bool | lower }}
{% if gitea_actions_enabled %}
GITEA__actions__DEFAULT_ACTIONS_URL={{ gitea_actions_default_actions_url }}
{% endif %}
{% if gitea_runner_global_registration_token %}
GITEA_RUNNER_REGISTRATION_TOKEN={{ gitea_runner_global_registration_token }}
{% endif %}
{% if gitea_actions_extra_config %}
# Additional Actions Configuration
{% for item in gitea_actions_extra_config | dict2items %}
GITEA__actions__{{ item.key }}={{ item.value if item.value is not boolean else (item.value | bool | lower) }}
{% endfor %}
{% endif %}
# ============================================
# Log Configuration
# ============================================
{% if gitea_log_root_path %}
GITEA__log__ROOT_PATH={{ gitea_log_root_path }}
{% endif %}
GITEA__log__MODE={{ gitea_log_mode }}
GITEA__log__LEVEL={{ gitea_log_level }}
{% if gitea_log_extra_config %}
# Additional Log Configuration
{% for item in gitea_log_extra_config | dict2items %}
{% if item.value is boolean %}
GITEA__log__{{ item.key }}={{ item.value | bool | lower }}
{% else %}
GITEA__log__{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
{% endif %}
# ============================================
# Mailer Configuration
# ============================================
GITEA__mailer__ENABLED={{ gitea_mailer_enabled | bool | lower }}
{% if gitea_mailer_enabled %}
{% if gitea_mailer_protocol %}
GITEA__mailer__PROTOCOL={{ gitea_mailer_protocol }}
{% endif %}
{% if gitea_mailer_smtp_addr %}
GITEA__mailer__SMTP_ADDR={{ gitea_mailer_smtp_addr }}
{% endif %}
{% if gitea_mailer_smtp_port %}
GITEA__mailer__SMTP_PORT={{ gitea_mailer_smtp_port }}
{% endif %}
{% if gitea_mailer_user %}
GITEA__mailer__USER={{ gitea_mailer_user }}
{% endif %}
{% if gitea_mailer_password %}
GITEA__mailer__PASSWD={{ gitea_mailer_password }}
{% endif %}
{% if gitea_mailer_from %}
GITEA__mailer__FROM={{ gitea_mailer_from }}
{% endif %}
{% if gitea_mailer_subject_prefix %}
GITEA__mailer__SUBJECT_PREFIX={{ gitea_mailer_subject_prefix }}
{% endif %}
GITEA__mailer__SEND_AS_PLAIN_TEXT={{ gitea_mailer_send_as_plain_text | bool | lower }}
{% endif %}
{% if gitea_mailer_extra_config %}
# Additional Mailer Configuration
{% for item in gitea_mailer_extra_config | dict2items %}
{% if item.value is boolean %}
GITEA__mailer__{{ item.key }}={{ item.value | bool | lower }}
{% else %}
GITEA__mailer__{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
{% endif %}
# ============================================
# Mirror Configuration
# ============================================
GITEA__mirror__ENABLED={{ gitea_mirror_enabled | bool | lower }}
GITEA__mirror__DISABLE_NEW_PULL={{ gitea_mirror_disable_new_pull | bool | lower }}
GITEA__mirror__DISABLE_NEW_PUSH={{ gitea_mirror_disable_new_push | bool | lower }}
GITEA__mirror__DEFAULT_INTERVAL={{ gitea_mirror_default_interval }}
GITEA__mirror__MIN_INTERVAL={{ gitea_mirror_min_interval }}
{% if gitea_mirror_extra_config %}
# Additional Mirror Configuration
{% for item in gitea_mirror_extra_config | dict2items %}
{% if item.value is boolean %}
GITEA__mirror__{{ item.key }}={{ item.value | bool | lower }}
{% else %}
GITEA__mirror__{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
{% endif %}
# ============================================
# Metrics Configuration
# ============================================
GITEA__metrics__ENABLED={{ gitea_metrics_enabled | bool | lower }}
{% if gitea_metrics_enabled and gitea_metrics_token %}
GITEA__metrics__TOKEN={{ gitea_metrics_token }}
{% endif %}
{% if gitea_metrics_extra_config %}
# Additional Metrics Configuration
{% for item in gitea_metrics_extra_config | dict2items %}
{% if item.value is boolean %}
GITEA__metrics__{{ item.key }}={{ item.value | bool | lower }}
{% else %}
GITEA__metrics__{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
{% endif %}
# ============================================
# API Configuration
# ============================================
GITEA__api__ENABLE_SWAGGER={{ gitea_api_enable_swagger | bool | lower }}
GITEA__api__MAX_RESPONSE_ITEMS={{ gitea_api_max_response_items }}
GITEA__api__DEFAULT_PAGING_NUM={{ gitea_api_default_paging_num }}
{% if gitea_api_extra_config %}
# Additional API Configuration
{% for item in gitea_api_extra_config | dict2items %}
{% if item.value is boolean %}
GITEA__api__{{ item.key }}={{ item.value | bool | lower }}
{% else %}
GITEA__api__{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
{% endif %}
# ============================================
# OAuth2 Configuration
# ============================================
GITEA__oauth2__ENABLED={{ gitea_oauth2_enabled | bool | lower }}
{% if gitea_oauth2_enabled %}
GITEA__oauth2__ACCESS_TOKEN_EXPIRATION_TIME={{ gitea_oauth2_access_token_expiration_time }}
GITEA__oauth2__REFRESH_TOKEN_EXPIRATION_TIME={{ gitea_oauth2_refresh_token_expiration_time }}
GITEA__oauth2__JWT_SIGNING_ALGORITHM={{ gitea_oauth2_jwt_signing_algorithm }}
{% if gitea_oauth2_jwt_secret %}
GITEA__oauth2__JWT_SECRET={{ gitea_oauth2_jwt_secret }}
{% endif %}
{% endif %}
{% if gitea_oauth2_extra_config %}
# Additional OAuth2 Configuration
{% for item in gitea_oauth2_extra_config | dict2items %}
{% if item.value is boolean %}
GITEA__oauth2__{{ item.key }}={{ item.value | bool | lower }}
{% else %}
GITEA__oauth2__{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
{% endif %}
# ============================================
# Other Configuration
# ============================================
GITEA__other__SHOW_FOOTER_VERSION={{ gitea_show_footer_version | bool | lower }}
GITEA__other__SHOW_FOOTER_TEMPLATE_LOAD_TIME={{ gitea_show_footer_template_load_time | bool | lower }}
GITEA__other__ENABLE_SITEMAP={{ gitea_enable_sitemap | bool | lower }}
GITEA__other__ENABLE_FEED={{ gitea_enable_feed | bool | lower }}
{% if gitea_other_extra_config %}
# Additional Other Configuration
{% for item in gitea_other_extra_config | dict2items %}
{% if item.value is boolean %}
GITEA__other__{{ item.key }}={{ item.value | bool | lower }}
{% else %}
GITEA__other__{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
{% endif %}
# ============================================
# Additonal environment variables
# ============================================
{% for item in gitea_extra_config | dict2items %}
{% if item.value is boolean %}
{{ item.key }}={{ item.value | bool | lower }}
{% else %}
{{ item.key }}={{ item.value }}
{% endif %}
{% endfor %}
@@ -0,0 +1,4 @@
# gitea.local
[Definition]
failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>
ignoreregex =
@@ -0,0 +1,11 @@
{# https://docs.gitea.com/administration/fail2ban-setup #}
[{{ gitea_fail2ban_jail_name }}]
enabled = true
filter = {{ gitea_fail2ban_filter }}
port = {{ gitea_fail2ban_port }}
logpath = {{ gitea_mounted_log_path }}
maxretry = {{ gitea_fail2ban_jail_maxretry }}
findtime = {{ gitea_fail2ban_jail_findtime }}
bantime = {{ gitea_fail2ban_jail_bantime }}
action = {{ gitea_fail2ban_jail_action }}