Ansible Role: gitea-docker
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, backups, fail2ban integration, and extensive configuration options.
Features
- Docker-based deployment - Runs Gitea in a rootless container for enhanced security
- Complete security configuration - Password policies, 2FA, fail2ban integration, etc.
- Built-in backup and restore - Includes tasks for creating backups and restoring from backups
- Gitea Actions support - Supports creating multiple runners running in rootless containers using DinD (Docker-in-Docker)
- Extensible - Extra config variables for any Gitea setting not explicitly defined
Requirements
- 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.
# Installs Docker and Compose if not available
- name: Install Gitea using Docker Compose
hosts: git.example.com
become: yes
roles:
- role: gitea_docker
vars:
# The default vars assume you are running a reverse proxy that handles HTTPS
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
The backup system currently backs up all the data mounts and creates a compressed archive. The archive is stored on the remote machine at the directory given by gitea_root_backup_dir. The Ansible controller then downloads the archive and stores it at gitea_local_backup_dir.
Note
The backup task stops the Compose stack to avoid data corruption. There will be a short downtime.
Creating a Backup
To trigger a backup:
---
- name: Create Gitea backup
hosts: git.example.com
become: yes
tasks:
- name: Include gitea backup tasks
include_role:
name: gitea_docker
tasks_from: backup
vars:
gitea_root_backup_dir: '/opt/gitea/backups'
gitea_local_backup_dir: '~/backups/gitea'
Note
Currently backups only work with Gitea using
sqlite3.PostgresSQLandMySQL/MariaDBare planned for a future release.
Restoring from Backup
To restore from a backup, set the gitea_restore_backup variable to true. The tasks will use the latest backup in your backups directory on the Ansible controller. You may also specify a backup file to use with gitea_backup_file.
Warning
Restore operations will completely replace all existing Gitea data.
---
- name: Restore Gitea from backup
hosts: git.example.com
become: yes
roles:
- role: gitea_docker
vars:
# Your defined variables
# ...
gitea_restore_backup: true
gitea_backup_file: '~/gitea-backups/gitea-backup-20240115-020000.tar.gz' # Optional
Variables
Container Configuration
| Variable Name | Default Value | Description |
|---|---|---|
gitea_home_path |
/opt/gitea |
Base directory on the host where Gitea configuration, data, and logs are stored |
gitea_container_tag |
latest-rootless |
Docker image tag for the Gitea container (e.g., latest-rootless, 1.21.5-rootless) |
gitea_data_mount |
./data |
Relative path for mounting Gitea data directory (relative to gitea_home_path) |
gitea_config_mount |
./config |
Relative path for mounting Gitea configuration directory (relative to gitea_home_path) |
gitea_log_mount |
./log |
Relative path for mounting Gitea log directory (relative to gitea_home_path) |
gitea_web_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_mounted_log_path |
/opt/gitea/log/gitea.log |
Full path to the Gitea log file on the host (used for fail2ban integration) |
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
| Variable Name | Default Value | Description |
|---|---|---|
gitea_root_backup_dir |
/opt/gitea/backups |
Directory on the remote host where Gitea backups are stored |
gitea_local_backup_dir |
~/backups/gitea |
Directory on the Ansible controller where backups are downloaded for safekeeping |
gitea_restore_backup |
false |
If true, restores Gitea from a backup (WARNING: clears any existing data) |
gitea_backup_file |
Path to specific backup archive file to restore from; if empty, uses the most recent backup in gitea_local_backup_dir |
Runners Configuration
| Variable Name | Option | Description |
|---|---|---|
gitea_runner_global_registration_token |
Global registration token that applies to all runners (can be found in Gitea admin settings) | |
gitea_runners |
{} |
Dictionary of Gitea Actions runner configurations |
name |
Unique name identifier for the runner | |
data_mount |
Path on host for persistent runner data storage | |
config_file_mount |
Path on host 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 for available options |
Example: Using gitea_extra_config
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
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:
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.
Important Notes
-
Values: All values in
*_extra_configdictionaries should be strings, numbers, or booleans. -
Priority: Variables defined in
*_extra_configcan override the explicitly defined role variables if they conflict. -
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