├── .ansible-lint ├── .codespellignore ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── ansible-linting-check.yml │ ├── galaxy.yml │ ├── j2lint-check.yml │ └── yamllint-check.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .secrets.baseline ├── .yamllint ├── LICENSE ├── README.md ├── defaults ├── forgejo.yml ├── gitea.yml └── main.yml ├── files ├── EB114F5E6C0DC2BCDD183550A4B61A2DC5923710.asc └── extra_links_footer.tmpl ├── handlers └── main.yml ├── meta └── main.yml ├── requirements.yml ├── tasks ├── backup-scheduled.yml ├── backup.yml ├── configure.yml ├── create_user.yml ├── customize_footer.yml ├── customize_logo.yml ├── customize_public_files.yml ├── directory.yml ├── fail2ban.yml ├── gitea_secrets.yml ├── install_forgejo.yml ├── install_gitea.yml ├── install_source.yml ├── install_systemd.yml ├── jwt_secrets.yml ├── local_git_users.yml ├── main.yml ├── set_forgejo_version.yml ├── set_gitea_version.yml └── versioncheck.yml ├── templates ├── fail2ban │ ├── filter.conf.j2 │ └── jail.conf.j2 ├── gitea.ini.j2 ├── gitea.service.j2 ├── systemd-gitea-backup.service.conf.j2 └── systemd-gitea-backup.timer.conf.j2 └── vars ├── debian.yml ├── fork_forgejo.yml ├── fork_gitea.yml ├── main.yml ├── os_fallback_defaults.yml ├── redhat.yml └── suse.yml /.ansible-lint: -------------------------------------------------------------------------------- 1 | --- 2 | warn_list: 3 | - experimental 4 | exclude_paths: 5 | - .github/workflows/ 6 | -------------------------------------------------------------------------------- /.codespellignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roles-ansible/ansible_role_gitea/2fe1c04f06aaf1cd7090141aa66ba4ca0be7e0e5/.codespellignore -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # These are supported funding model platforms 3 | 4 | github: [do1jlr] 5 | liberapay: L3D 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # See https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates 3 | version: 2 4 | updates: 5 | - package-ecosystem: "github-actions" 6 | directory: "/" 7 | schedule: 8 | interval: "daily" 9 | -------------------------------------------------------------------------------- /.github/workflows/ansible-linting-check.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Ansible Lint check 3 | 4 | # yamllint disable-line rule:truthy 5 | on: [push, pull_request] 6 | 7 | jobs: 8 | build: 9 | name: Ansible Lint 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: "checkout git repo" 14 | uses: actions/checkout@v4.1.1 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Run ansible-lint 19 | uses: ansible-actions/ansible-lint-action@v1.0.3 20 | with: 21 | target: "./" 22 | collections_yml: "requirements.yml" 23 | python_dependency: "jmespath" 24 | -------------------------------------------------------------------------------- /.github/workflows/galaxy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Galaxy-NG Roles Import 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | release: 7 | types: ["created"] 8 | 9 | jobs: 10 | build: 11 | name: Galaxy Role Importer 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: "Checkout git repo" 16 | uses: actions/checkout@v4 17 | with: 18 | submodules: true 19 | fetch-depth: 0 20 | 21 | - name: "Release on galaxy" 22 | uses: ansible-actions/ansible-galaxy-action@v1.2.0 23 | with: 24 | galaxy_api_key: ${{ secrets.galaxy_api_key }} 25 | galaxy_version: "main" 26 | -------------------------------------------------------------------------------- /.github/workflows/j2lint-check.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Jinja2 Linting check 3 | 4 | # yamllint disable-line rule:truthy 5 | on: [push, pull_request] 6 | 7 | jobs: 8 | build: 9 | name: Jinja2 Linting 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: "checkout git repo" 14 | uses: actions/checkout@v4 15 | with: 16 | submodules: true 17 | fetch-depth: 0 18 | 19 | - name: Run j2lint 20 | uses: ansible-actions/j2lint-action@v0.0.1 21 | with: 22 | target: "./" 23 | -------------------------------------------------------------------------------- /.github/workflows/yamllint-check.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Yamllint check 3 | 4 | # yamllint disable-line rule:truthy 5 | on: [push, pull_request] 6 | 7 | jobs: 8 | build: 9 | name: Yamllint 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: "checkout git repo" 14 | uses: actions/checkout@v4 15 | with: 16 | submodules: true 17 | fetch-depth: 0 18 | 19 | - name: Run yamllint 20 | uses: ansible-actions/yamllint-action@v0.0.2 21 | with: 22 | target: "./" 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/ansible 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=ansible 3 | 4 | ### Ansible ### 5 | *.retry 6 | 7 | # End of https://www.toptal.com/developers/gitignore/api/ansible 8 | 9 | *.py 10 | 11 | .cache 12 | 13 | # Environments 14 | .env 15 | .venv 16 | env/ 17 | venv/ 18 | ENV/ 19 | env.bak/ 20 | venv.bak/ 21 | .ansible 22 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | repos: 3 | - repo: https://github.com/pre-commit/pre-commit-hooks 4 | rev: v5.0.0 5 | hooks: 6 | - id: check-yaml 7 | - id: end-of-file-fixer 8 | - id: trailing-whitespace 9 | - id: check-added-large-files 10 | - id: check-json 11 | - id: detect-private-key 12 | - id: check-case-conflict 13 | - id: requirements-txt-fixer 14 | - id: check-ast 15 | - id: check-shebang-scripts-are-executable 16 | - id: check-merge-conflict 17 | - id: check-symlinks 18 | - id: check-toml 19 | - id: check-xml 20 | # - id: detect-aws-credentials 21 | - id: check-docstring-first 22 | - repo: https://github.com/codespell-project/codespell 23 | rev: v2.4.1 24 | hooks: 25 | - id: codespell 26 | args: [-I, .codespellignore] 27 | - repo: https://github.com/Yelp/detect-secrets 28 | rev: v1.5.0 29 | hooks: 30 | - id: detect-secrets 31 | args: ["--baseline", ".secrets.baseline"] 32 | # exclude: .*/tests/.* 33 | - repo: https://github.com/aristanetworks/j2lint.git 34 | rev: v1.1.0 35 | hooks: 36 | - id: j2lint 37 | - repo: https://github.com/ansible-community/ansible-lint.git 38 | rev: v25.1.3 39 | hooks: 40 | - id: ansible-lint 41 | files: \.(yaml|yml)$ 42 | additional_dependencies: 43 | - jmespath 44 | 45 | - repo: https://github.com/adrienverge/yamllint 46 | rev: v1.36.0 47 | hooks: 48 | - id: yamllint 49 | 50 | - repo: https://github.com/aristanetworks/j2lint.git 51 | rev: v1.1.0 52 | hooks: 53 | - id: j2lint 54 | -------------------------------------------------------------------------------- /.secrets.baseline: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.5.0", 3 | "plugins_used": [ 4 | { 5 | "name": "ArtifactoryDetector" 6 | }, 7 | { 8 | "name": "AWSKeyDetector" 9 | }, 10 | { 11 | "name": "AzureStorageKeyDetector" 12 | }, 13 | { 14 | "name": "Base64HighEntropyString", 15 | "limit": 4.5 16 | }, 17 | { 18 | "name": "BasicAuthDetector" 19 | }, 20 | { 21 | "name": "CloudantDetector" 22 | }, 23 | { 24 | "name": "DiscordBotTokenDetector" 25 | }, 26 | { 27 | "name": "GitHubTokenDetector" 28 | }, 29 | { 30 | "name": "GitLabTokenDetector" 31 | }, 32 | { 33 | "name": "HexHighEntropyString", 34 | "limit": 3.0 35 | }, 36 | { 37 | "name": "IbmCloudIamDetector" 38 | }, 39 | { 40 | "name": "IbmCosHmacDetector" 41 | }, 42 | { 43 | "name": "IPPublicDetector" 44 | }, 45 | { 46 | "name": "JwtTokenDetector" 47 | }, 48 | { 49 | "name": "KeywordDetector", 50 | "keyword_exclude": "" 51 | }, 52 | { 53 | "name": "MailchimpDetector" 54 | }, 55 | { 56 | "name": "NpmDetector" 57 | }, 58 | { 59 | "name": "OpenAIDetector" 60 | }, 61 | { 62 | "name": "PrivateKeyDetector" 63 | }, 64 | { 65 | "name": "PypiTokenDetector" 66 | }, 67 | { 68 | "name": "SendGridDetector" 69 | }, 70 | { 71 | "name": "SlackDetector" 72 | }, 73 | { 74 | "name": "SoftlayerDetector" 75 | }, 76 | { 77 | "name": "SquareOAuthDetector" 78 | }, 79 | { 80 | "name": "StripeDetector" 81 | }, 82 | { 83 | "name": "TelegramBotTokenDetector" 84 | }, 85 | { 86 | "name": "TwilioKeyDetector" 87 | } 88 | ], 89 | "filters_used": [ 90 | { 91 | "path": "detect_secrets.filters.allowlist.is_line_allowlisted" 92 | }, 93 | { 94 | "path": "detect_secrets.filters.common.is_baseline_file", 95 | "filename": ".secrets.baseline" 96 | }, 97 | { 98 | "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", 99 | "min_level": 2 100 | }, 101 | { 102 | "path": "detect_secrets.filters.heuristic.is_indirect_reference" 103 | }, 104 | { 105 | "path": "detect_secrets.filters.heuristic.is_likely_id_string" 106 | }, 107 | { 108 | "path": "detect_secrets.filters.heuristic.is_lock_file" 109 | }, 110 | { 111 | "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" 112 | }, 113 | { 114 | "path": "detect_secrets.filters.heuristic.is_potential_uuid" 115 | }, 116 | { 117 | "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign" 118 | }, 119 | { 120 | "path": "detect_secrets.filters.heuristic.is_sequential_string" 121 | }, 122 | { 123 | "path": "detect_secrets.filters.heuristic.is_swagger_file" 124 | }, 125 | { 126 | "path": "detect_secrets.filters.heuristic.is_templated_secret" 127 | } 128 | ], 129 | "results": { 130 | "defaults/main.yml": [ 131 | { 132 | "type": "Hex High Entropy String", 133 | "filename": "defaults/main.yml", 134 | "hashed_secret": "6ffda8dbbef8536f790b2cf5a1dece3b6555d1ce", 135 | "is_verified": false, 136 | "line_number": 10 137 | }, 138 | { 139 | "type": "Hex High Entropy String", 140 | "filename": "defaults/main.yml", 141 | "hashed_secret": "a60b9a4c47a1fcc036df3710885f4f03c4ee9d39", 142 | "is_verified": false, 143 | "line_number": 11 144 | }, 145 | { 146 | "type": "Secret Keyword", 147 | "filename": "defaults/main.yml", 148 | "hashed_secret": "73de13cf365ff2b5ddfbc96078305cef8fdc2990", 149 | "is_verified": false, 150 | "line_number": 143 151 | } 152 | ], 153 | "tasks/set_forgejo_version.yml": [ 154 | { 155 | "type": "Hex High Entropy String", 156 | "filename": "tasks/set_forgejo_version.yml", 157 | "hashed_secret": "085e34c422eef6cf478a8fd627bf67f8f0e94cd8", 158 | "is_verified": false, 159 | "line_number": 97 160 | } 161 | ] 162 | }, 163 | "generated_at": "2025-03-16T21:11:53Z" 164 | } 165 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | 4 | rules: 5 | # 190 chars should be enough, but don't fail if a line is longer 6 | line-length: 7 | max: 190 8 | level: warning 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019 - today L3D 4 | Copyright (c) 2019 - 2021 Thomas Maurice 5 | 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, this 12 | list of conditions and the following disclaimer. 13 | 14 | 2. Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | 3. Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Ansible Galaxy](https://ansible.l3d.space/svg/roles-ansible.gitea.svg)](https://galaxy.ansible.com/ui/standalone/roles/roles-ansible/gitea/) 2 | [![BSD-3 Clause](https://ansible.l3d.space/svg/roles-ansible.gitea_license.svg)](LICENSE) 3 | [![Maintenance](https://ansible.l3d.space/svg/roles-ansible.gitea_maintainance.svg)](https://ansible.l3d.space/#roles-ansible.gitea) 4 | 5 | # ansible role gitea/forgejo 6 | 7 | This role installs and manages [gitea](https://gitea.io) or [forgejo](https://forgejo.org). A painless self-hosted Git service. Gitea is a community managed lightweight code hosting solution written in Go. Forgejo is a fork of it. 8 | [Source code & screenshots gitea](https://github.com/go-gitea/gitea). 9 | [Source code forgejo](https://code.forgejo.org/forgejo/forgejo). 10 | This role is also Part of the Ansible-Collection [l3d.git](https://galaxy.ansible.com/l3d/git). [![l3d.git](https://ansible.l3d.space/svg/l3d.git_ansible-collection_collection.svg)](https://github.com/roles-ansible/ansible_collection_git.git). 11 | 12 | ## Mirrors 13 | 14 | The role is mirrored to: 15 | 16 | - Github: [github.com/roles-ansible/ansible_role_gitea](https://github.com/roles-ansible/ansible_role_gitea.git) 17 | - Gitea: [git.l3d.ch/ansible/ansible_role_gitea](https://git.l3d.ch/ansible/ansible_role_gitea.git) 18 | More about it at [ansible.l3d.space](https://ansible.l3d.space/#roles-ansible.gitea) 19 | 20 | ## Sample Usage in a playbook 21 | 22 | The following code has been tested with the latest Debian Stable, it should work on Ubuntu and RedHat as well. 23 | 24 | ```yaml 25 | # ansible-galaxy role install roles-ansible.gitea 26 | 27 | - name: "Install gitea" 28 | hosts: git.example.com 29 | roles: 30 | - { role: roles-ansible.gitea, tags: gitea } 31 | vars: 32 | # Here we assume we are behind a reverse proxy that will 33 | # handle https for us, so we bind on localhost:3000 using HTTP 34 | # see https://docs.gitea.io/en-us/reverse-proxies/#nginx 35 | gitea_fqdn: "git.example.com" 36 | gitea_root_url: "https://git.example.com" 37 | gitea_protocol: http 38 | gitea_start_ssh: true 39 | ``` 40 | 41 | ## Choosing between Gitea's built-in SSH and host SSH Server 42 | 43 | Gitea has a built-in SSH server which is running on port 2222 (to not conflict with the host SSH server which usually running on port 22). 44 | This one is used by default in this role and results in a SSH clone URL of `gitea@:2222:/.git` because `gitea` is the default `RUN_AS` user. 45 | 46 | Often enough, one wants to have a "clean" SSH URL like `git@:/.git`. 47 | This is possible by using the host SSH server with the following variable configuration: 48 | 49 | ```yaml 50 | gitea_ssh_port: 22 # assuming the host SSH server is running on port 22 51 | gitea_user: git # otherwise there will be permission issues 52 | gitea_start_ssh: false # to not start the built-in SSH server 53 | ``` 54 | 55 | The above configuration works out of the box for new installations. 56 | When migrating from a running instance with existing SSH keys from the built-in SSH server to the host SSH server, you need to make sure that the host SSH server is running and that the `gitea_user` has the necessary permissions to access the repository data and the keys (stored in `/.ssh/`) 57 | 58 | NB: To use `git@` as described above, `gitea_user` must be `git` and it does not suffice to set `gitea_ssh_user: git`. 59 | See [this issue](https://github.com/go-gitea/gitea/issues/28563) for more information.. 60 | 61 | ## Variables 62 | 63 | Here is a deeper insight into the variables of this gitea role. For the exact function of some variables and the possibility to add more options we recommend a look at this [config cheat sheet](https://docs.gitea.com/administration/config-cheat-sheet). 64 | 65 | ### Chose between gitea and forgejo 66 | 67 | There is a fork of gitea called forgejo. Why? Read the [forgejo FAQ](https://forgejo.org/faq/). 68 | You have the option to choose between [gitea](https://gitea.io) and [forgejo](https://forgejo.org) by modifying the `gitea_fork` variable. 69 | | variable name | default value | description | 70 | | ------------- | ------------- | ----------- | 71 | | `gitea_fork` | `gitea` | optional choose to install forgejo instead of gitea by setting this value to `forgejo`. | 72 | 73 | ### gitea update mechanism 74 | 75 | To determine which gitea version to install, you can choose between two variants. 76 | Either you define exactly which release you install. Or you use the option `latest` to always install the latest release from the [gitea releases](https://github.com/go-gitea/gitea/releases/latest). 77 | 78 | ### Forgejo update mechanism 79 | 80 | It is advisable to define exactly which Forgejo release you want to install. See [Forgejo releases](https://forgejo.org/releases/) for the correct value to use in `gitea_version` eg `v1.21.5`. 81 | 82 | This is because the Forgejo project maintains both `stable` and `old stable` releases and the `latest` tag will refer to the _most recent release_ regardless of whether it is `stable` or `old stable`. This can lead to a situation where `latest` refers to an _older release_ than the version you have installed. 83 | 84 | ### Installing from source 85 | 86 | Source installations should only be done if custom files changes should be incorporated during the binary build process or a (unreleased) bug fix is urgently needed. 87 | For repeated source installation builds, it is recommended to set `gitea_install_source_cleanup_build_dir: false` to persist a static clone. 88 | The installation logic dynamically installs the pinned versions of nodejs and go for the current develop branch, which are usually never than the versions provided by the system package managers. 89 | 90 | > [!WARNING] 91 | > Note that when installing from HEAD/non-tagged version, the database schema version will likely be bumped, preventing an easy downgrade to a tagged version afterwards. 92 | 93 | ### gitea update 94 | 95 | | variable name | default value | description | 96 | | ------------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | 97 | | `gitea_version` | `latest` | Define either the exact release to install _(eg. `1.16.0`)_ or use `latest` _(default)_ to install the latest release. | 98 | | `gitea_version_check` | `true` | Check if installed version != `gitea_version` before initiating binary download | 99 | | `gitea_gpg_key` | `7C9E68152594688862D62AF62D9AE806EC1592E2` | the gpg key the gitea binary is signed with | 100 | | `gitea_forgejo_gpg_key` | `EB114F5E6C0DC2BCDD183550A4B61A2DC5923710` | the gpg key the forgejo binary is signed with | 101 | | `gitea_gpg_server` | `hkps://keys.openpgp.org` | A gpg key server where this role can download the gpg key | 102 | | `gitea_backup_on_upgrade` | `false` | Optionally a backup can be created with every update of gitea. | 103 | | `gitea_backup_location` | `{{ gitea_home }}/backups/` | Where to store the gitea backup if one is created with this role. | 104 | | `gitea_backup_scheduled` | `false` | Set systemd service and timer units to do gitea backup. | 105 | | `submodules_versioncheck` | `false` | a simple version check that can prevent you from accidentally running an older version of this role. _(recommended)_ | 106 | 107 | ### gitea installation 108 | 109 | | variable name | default value | description | 110 | | ------------------------------------------ | -------------------------------------------- | ---------------------------------------------- | 111 | | `gitea_install_source_source_url` | `https://github.com/go-gitea/gitea.git` | Clone URL for Forge source | 112 | | `gitea_install_source_binary_name` | `{{ gitea_fork }}` | Output binary name | 113 | | `gitea_install_source_binary_install_path` | `/usr/local/bin/` | Binary installation path | 114 | | `gitea_install_source_build_dir` | `/tmp/{{ gitea_fork }}` | Build directory | 115 | | `gitea_install_source_cleanup_build_dir` | `true` | Whether to remove the build dir after building | 116 | | `gitea_install_source_apt_build_deps` | `["sed", "make", "nodejs", "golang", "git"]` | APT Build dependencies | 117 | | `gitea_install_source_dnf_build_deps` | `["sed", "make", "nodejs", "go", "git"]` | DNF Build dependencies | 118 | 119 | ### gitea in the linux world 120 | 121 | | variable name | default value | description | 122 | | ------------------------------------ | ------------------------ | ----------------------------------------------------------------------------------------------- | 123 | | `gitea_group` | `gitea` | Primary UNIX group used by Gitea | 124 | | `gitea_groups` | null | Optionally a list of secondary UNIX groups used by Gitea | 125 | | `gitea_home` | `/var/lib/gitea` | Base directory to work | 126 | | `gitea_user_home` | `{{ gitea_home }}` | home of gitea user | 127 | | `gitea_executable_path` | `/usr/local/bin/gitea` | Path for gitea executable | 128 | | `gitea_forgejo_executable_path` | `/usr/local/bin/forgejo` | Path for forgejo executable | 129 | | `gitea_configuration_path` | `/etc/gitea` | Where to put the gitea.ini config | 130 | | `gitea_shell` | `/bin/false` | UNIX shell used by gitea. Set it to `/bin/bash` if you don't use the gitea built-in ssh server. | 131 | | `gitea_systemd_cap_net_bind_service` | `false` | Adds `AmbientCapabilities=CAP_NET_BIND_SERVICE` to systemd service file | 132 | 133 | ### Overall ([DEFAULT](https://docs.gitea.com/administration/config-cheat-sheet#overall-default)) 134 | 135 | | variable name | default value | description | 136 | | ---------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------- | 137 | | `gitea_app_name` | `Gitea` | Displayed application name | 138 | | `gitea_user` | `gitea ` | UNIX user used by Gitea | 139 | | `gitea_run_mode` | `prod` | Application run mode, affects performance and debugging. Either “dev”, “prod” or “test”. | 140 | | `gitea_fqdn` | `localhost` | Base FQDN for the installation, used as default for other variables. Set it to the FQDN where you can reach your gitea server | 141 | 142 | ### Repository ([repository](https://docs.gitea.com/administration/config-cheat-sheet#repository-repository)) 143 | 144 | | variable name | default value | description | 145 | | ------------------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------- | 146 | | `gitea_default_branch` | `main` | Default branch name of all repositories. | 147 | | `gitea_default_private` | `last` | Default private when creating a new repository. [`last`, `private`, `public`] | 148 | | `gitea_default_repo_units` | _(see defaults)_ | Comma separated list of default repo units. See official docs for more | 149 | | `gitea_disabled_repo_units` | | Comma separated list of globally disabled repo units. | 150 | | `gitea_disable_http_git` | `false` | Disable the ability to interact with repositories over the HTTP protocol. (true/false) | 151 | | `gitea_disable_stars` | `false` | Disable stars feature. | 152 | | `gitea_enable_push_create_org` | `false` | Allow users to push local repositories to Gitea and have them automatically created for an org. | 153 | | `gitea_enable_push_create_user` | `false` | Allow users to push local repositories to Gitea and have them automatically created for an user. | 154 | | `gitea_force_private` | `false` | Force every new repository to be private. | 155 | | `gitea_user_repo_limit` | `-1` | Limit how many repos a user can have _(`-1` for unlimited)_ | 156 | | `gitea_repository_root` | `{{ gitea_home }}/repos` | Root path for storing all repository data. It must be an absolute path. | 157 | | `gitea_repository_extra_config` | | you can use this variable to pass additional config parameters in the `[repository]` section of the config. | 158 | 159 | ### Repository - Upload ([repository.upload](https://docs.gitea.io/en-us/administration/config-cheat-sheet#repository---upload-repositoryupload)) 160 | 161 | | variable name | default value | description | 162 | | -------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------ | 163 | | `gitea_repository_upload_enabled` | `true` | Whether repository file uploads are enabled | 164 | | `gitea_repository_upload_max_size` | `4` | Max size of each file in megabytes. | 165 | | `gitea_repository_upload_extra_config` | | you can use this variable to pass additional config parameters in the `[repository.upload]` section of the config. | 166 | 167 | ### Repository - Signing ([repository.signing](https://docs.gitea.com/administration/config-cheat-sheet#repository---signing-repositorysigning)) 168 | 169 | | variable name | default value | description | 170 | | ---------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------- | 171 | | `gitea_enable_repo_signing_options` | `false` | Allow to configure repo signing options | 172 | | `gitea_repo_signing_key` | `default` | Key to sign with. | 173 | | `gitea_repo_signing_name` | | if a KEYID is provided as the `gitea_repo_signing_key`, use these as the Name and Email address of the signer. | 174 | | `gitea_repo_signing_email` | | if a KEYID is provided as the `gitea_repo_signing_key`, use these as the Name and Email address of the signer. | 175 | | `gitea_repo_initial_commit` | `always` | Sign initial commit. | 176 | | `gitea_repo_default_trust_model` | `collaborator` | The default trust model used for verifying commits. | 177 | | `gitea_repo_wiki` | `never` | Sign commits to wiki. | 178 | | `gitea_repo_crud_actions` | _(see defaults)_ | Sign CRUD actions. | 179 | | `gitea_repo_merges` | _(see defaults)_ | Sign merges. | 180 | | `gitea_enable_repo_signing_extra_config` | | you can use this variable to pass additional config parameters in the `[repository.signing]` section of the config. | 181 | 182 | ### CORS ([cors](https://docs.gitea.com/administration/config-cheat-sheet#cors-cors)) 183 | 184 | | variable name | default value | description | 185 | | ------------------------------ | ------------------------- | ----------------------------------------------------------------------------------------------------- | 186 | | `gitea_enable_cors` | `false` | enable cors headers (disabled by default) | 187 | | `gitea_cors_scheme` | `http` | scheme of allowed requests | 188 | | `gitea_cors_allow_domain` | `*` | list of requesting domains that are allowed | 189 | | `gitea_cors_allow_subdomain` | `false` | allow subdomains of headers listed above to request | 190 | | `gitea_cors_methods` | _(see defaults)_ | list of methods allowed to request | 191 | | `gitea_cors_max_age` | `10m` | max time to cache response | 192 | | `gitea_cors_allow_credentials` | `false` | allow request with credentials | 193 | | `gitea_cors_headers` | `Content-Type,User-Agent` | additional headers that are permitted in requests | 194 | | `gitea_cors_x_frame_options` | `SAMEORIGIN` | Set the `X-Frame-Options` header value. | 195 | | `gitea_cors_extra_config` | | you can use this variable to pass additional config parameters in the `[cors]` section of the config. | 196 | 197 | ### UI ([ui](https://docs.gitea.com/administration/config-cheat-sheet#ui-ui)) 198 | 199 | | variable name | default value | description | 200 | | ----------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------- | 201 | | `gitea_show_user_email` | `false` | Do you want to display email addresses ? (true/false) | 202 | | `gitea_theme_default` | `gitea-auto` or `forgejo-auto` | Default theme | 203 | | `gitea_themes` | (See `defaults/gitea.yml` or `defaults/forgejo.yml`) | List of enabled themes | 204 | | `gitea_ui_extra_config` | | you can use this variable to pass additional config parameters in the `[ui]` section of the config. | 205 | 206 | ### UI - Meta ([ui.meta](https://docs.gitea.com/administration/config-cheat-sheet#ui---metadata-uimeta)) 207 | 208 | | variable name | default value | description | 209 | | ---------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------- | 210 | | `gitea_ui_author` | _(see defaults)_ | Author meta tag of the homepage. | 211 | | `gitea_ui_description` | _(see defaults)_ | Description meta tag of the homepage. | 212 | | `gitea_ui_keywords` | _(see defaults)_ | Keywords meta tag of the homepage | 213 | | `gitea_ui_meta_extra_config` | | you can use this variable to pass additional config parameters in the `[ui.meta]` section of the config. | 214 | 215 | ### Server ([server](https://docs.gitea.com/administration/config-cheat-sheet#server-server)) 216 | 217 | | variable name | default value | description | 218 | | --------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | 219 | | `gitea_protocol` | `http` | Listening protocol [http, https, fcgi, unix, fcgi+unix] | 220 | | `gitea_http_domain` | `{{ gitea_fqdn }}` which is `localhost` | Domain name of this server. | 221 | | `gitea_root_url` | `http://{{ gitea_fqdn }}:3000` | Root URL used to access your web app (full URL) | 222 | | `gitea_http_listen` | `127.0.0.1` | HTTP listen address | 223 | | `gitea_http_port` | `3000` | Bind port _(redirect from `80` will be activated if value is `443`)_ | 224 | | `gitea_start_ssh` | `true` | When enabled, use the built-in SSH server. | 225 | | `gitea_ssh_domain` | `{{ gitea_fqdn }} ` | Domain name of this server, used for displayed clone URL | 226 | | `gitea_ssh_port` | `2222` | SSH port displayed in clone URL. | 227 | | `gitea_ssh_listen` | `0.0.0.0` | Listen address for the built-in SSH server. | 228 | | `gitea_offline_mode` | `true` | Disables use of CDN for static files and Gravatar for profile pictures. (true/false) | 229 | | `gitea_landing_page` | `home` | Landing page for unauthenticated users | 230 | | `gitea_lfs_server_enabled` | `false` | Enable GIT-LFS Support _(git large file storage: [git-lfs](https://git-lfs.github.com/))_. | 231 | | `gitea_lfs_jwt_secret` | | LFS authentication secret. Can be generated with `gitea generate secret JWT_SECRET`. Will be autogenerated if not defined | 232 | | `gitea_redirect_other_port` | `false` | If true and `gitea_protocol` is https, allows redirecting http requests on `gitea_port_to_redirect` to the https port Gitea listens on. | 233 | | `gitea_port_to_redirect` | `80` | Port for the http redirection service to listen on, if enabled | 234 | | `gitea_enable_tls_certs` | `false` | Write TLS Cert and Key Path to config file | 235 | | `gitea_tls_cert_file` | `https/cert.pem` | Cert file path used for HTTPS. | 236 | | `gitea_tls_key_file` | `https/key.pem` | Key file path used for HTTPS. | 237 | | `gitea_enable_acme` | `false` | Flag to enable automatic certificate management via an ACME capable CA Server. _(default is letsencrypt)_ | 238 | | `gitea_acme_url` | | The CA’s ACME directory URL | 239 | | `gitea_acme_accepttos` | `false` | This is an explicit check that you accept the terms of service of the ACME provider. | 240 | | `gitea_acme_directory` | `https` | Directory that the certificate manager will use to cache information such as certs and private keys. | 241 | | `gitea_acme_email` | | Email used for the ACME registration | 242 | | `gitea_acme_ca_root` | | The CA’s root certificate. If left empty, it defaults to using the system’s trust chain. | 243 | | `gitea_server_extra_config` | | you can use this variable to pass additional config parameters in the `[server]` section of the config. | 244 | 245 | ### Database ([database](https://docs.gitea.com/administration/config-cheat-sheet#database-database)) 246 | 247 | | variable name | default value | description | 248 | | ----------------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 249 | | `gitea_db_type` | `sqlite3` | The database type in use `[mysql, postgres, mssql, sqlite3]`. | 250 | | `gitea_db_host` | `127.0.0.0:3306` | Database host address and port or absolute path for unix socket [mysql, postgres] (ex: `/var/run/mysqld/mysqld.sock`). | 251 | | `gitea_db_name` | `root` | Database name | 252 | | `gitea_db_user` | `gitea` | Database username | 253 | | `gitea_db_password` | `lel` | Database password. **PLEASE CHANGE** | 254 | | `gitea_db_ssl` | `disable` | Configure SSL only if your database type supports it. Have a look into the [config-cheat-sheet](https://docs.gitea.com/administration/config-cheat-sheet#database-database) for more detailed information | 255 | | `gitea_db_path` | `{{ gitea_home }}/data/gitea.db` | DB path, if you use `sqlite3`. | 256 | | `gitea_db_log_sql` | `false` | Log the executed SQL. | 257 | | `gitea_database_extra_config` | | you can use this variable to pass additional config parameters in the `[database]` section of the config. | 258 | 259 | ### Indexer ([indexer](https://docs.gitea.com/administration/config-cheat-sheet#indexer-indexer)) 260 | 261 | | variable name | default value | description | 262 | | ---------------------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------- | 263 | | `gitea_repo_indexer_enabled` | `false` | Enables code search _(uses a lot of disk space, about 6 times more than the repository size)._ | 264 | | `gitea_repo_indexer_include` | | Glob patterns to include in the index _(comma-separated list)_. An empty list means include all files. | 265 | | `gitea_repo_indexer_exclude` | | Glob patterns to exclude from the index (comma-separated list). | 266 | | `gitea_repo_exclude_vendored` | `true` | Exclude vendored files from index. | 267 | | `gitea_repo_indexer_max_file_size` | `1048576` | Maximum size in bytes of files to be indexed. | 268 | | `gitea_indexer_extra_config` | | you can use this variable to pass additional config parameters in the `[indexer]` section of the config. | 269 | | `gitea_issue_indexer_type` | `bleve` | Code search engine type, could be bleve or elasticsearch | 270 | | `gitea_issue_indexer_conn_str` | | Issue indexer connection string, available when gitea_issue_indexer_type is elasticsearch | 271 | | `gitea_queue_issue_indexer_extra_config` | | you can use this variable to pass additional config parameters in the `[queue.issue_indexer]` section of the config. | 272 | 273 | ### Security ([security](https://docs.gitea.com/administration/config-cheat-sheet#security-security)) 274 | 275 | | variable name | default value | description | 276 | | ----------------------------- | ------------- | --------------------------------------------------------------------------------------------------------- | 277 | | `gitea_secret_key` | | Global secret key. Will be autogenerated if not defined. Should be unique. | 278 | | `gitea_disable_git_hooks` | `true` | Set to false to enable users with git hook privilege to create custom git hooks. Can be dangerous. | 279 | | `gitea_disable_webhooks` | `false` | Set to true to disable webhooks feature. | 280 | | `gitea_internal_token` | | Internal API token. Will be autogenerated if not defined. Should be unique. | 281 | | `gitea_password_check_pwn` | `false` | Check [HaveIBeenPwned](https://haveibeenpwned.com/Passwords) to see if a password has been exposed. | 282 | | `gitea_security_extra_config` | | you can use this variable to pass additional config parameters in the `[security]` section of the config. | 283 | 284 | ### Service ([service](https://docs.gitea.com/administration/config-cheat-sheet#service-service)) 285 | 286 | | variable name | default value | description | 287 | | ----------------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------- | 288 | | `gitea_disable_registration` | `false` | Do you want to disable user registration? (true/false) | 289 | | `gitea_register_email_confirm` | `false` | Enable this to ask for mail confirmation of registration. Requires `gitea_mailer_enabled` to be enabled. | 290 | | `gitea_require_signin` | `true` | Do you require a signin to see repo's (even public ones)? (true/false) | 291 | | `gitea_default_keep_mail_private` | `true` | By default set users to keep their email address privat | 292 | | `gitea_enable_captcha` | `true` | Do you want to enable captcha's ? (true/false) | 293 | | `gitea_show_registration_button` | `true` | Here you can hide the registration button. This will not disable registration! (true/false) | 294 | | `gitea_only_allow_external_registration` | `false` | Set to true to force registration only using third-party services (true/false) | 295 | | `gitea_enable_notify_mail` | `false` | Enable this to send e-mail to watchers of a repository when something happens, like creating issues (true/false) | 296 | | `gitea_auto_watch_new_repos` | `true` | Enable this to let all organisation users watch new repos when they are created (true/false) | 297 | | `gitea_auto_watch_on_changes` | `true` | Enable this to make users watch a repository after their first commit to it (true/false) | 298 | | `gitea_register_manual_confirm` | `false` | Enable this to manually confirm new registrations. Requires REGISTER_EMAIL_CONFIRM to be disabled. | 299 | | `gitea_default_allow_create_organization` | `false` | Allow new users to create organizations by default (true/false) | 300 | | `gitea_email_domain_allowlist` | | If non-empty, comma separated list of domain names that can only be used to register on this instance, wildcard is supported. | 301 | | `gitea_default_user_visibility` | `public` | Set default visibility mode for users, either "public", "limited" or "private". | 302 | | `gitea_default_org_visibility` | `public` | Set default visibility mode for organisations, either "public", "limited" or "private". | 303 | | `gitea_allow_only_internal_registration` | `false` | Set to true to force registration only via Gitea. | 304 | | `gitea_allow_only_external_registration` | `false` | Set to true to force registration only using third-party services. | 305 | | `gitea_show_milestones_dashboard_page` | `true` | Enable this to show the milestones dashboard page - a view of all the user's milestones | 306 | | `gitea_default_user_is_restricted` | `false` | Give new users restricted permissions by default (true/false) | 307 | | `gitea_service_extra_config` | | you can use this variable to pass additional config parameters in the `[service]` section of the config. | 308 | 309 | ### Mailer ([mailer](https://docs.gitea.com/administration/config-cheat-sheet#mailer-mailer)) 310 | 311 | | variable name | default value | description | 312 | | -------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | 313 | | `gitea_mailer_enabled` | `false` | Whether to enable the mailer. | 314 | | `gitea_mailer_protocol` | `dummy` | Mail server protocol. One of “smtp”, “smtps”, “smtp+starttls”, “smtp+unix”, “sendmail”, “dummy”. | 315 | | `gitea_mailer_smtp_addr` | | Mail server address. e.g. smtp.gmail.com. For smtp+unix, this should be a path to a unix socket instead. | 316 | | `gitea_mailer_smtp_port` | | Mail server port | 317 | | `gitea_mailer_use_client_cert` | `false` | Use client certificate for TLS/SSL. | 318 | | `gitea_mailer_client_cert_file` | | Client certificate file. | 319 | | `gitea_mailer_client_key_file` | | Client key file. | 320 | | `gitea_mailer_force_trust_server_cert` | `false` | completely ignores server certificate validation errors. This option is unsafe. Consider adding the certificate to the system trust store instead. | 321 | | `gitea_mailer_user` | | Username of mailing user (usually the sender’s e-mail address). | 322 | | `gitea_mailer_password ` | | Password of mailing user. Use `your password` for quoting if you use special characters in the password. | 323 | | `gitea_mailer_enable_helo` | `true` | Enable HELO operation. | 324 | | `gitea_mailer_from` | `noreply@{{ gitea_http_domain }}` | Mail from address, RFC 5322. | 325 | | `gitea_subject_prefix` | | Prefix to be placed before e-mail subject lines. | 326 | | `gitea_mailer_send_as_plaintext` | `false` | Send mails only in plain text, without HTML alternative. | 327 | | `gitea_mailer_extra_config` | | you can use this variable to pass additional config parameters in the `[mailer]` section of the config. | 328 | 329 | ### Session ([session](https://docs.gitea.com/administration/config-cheat-sheet#session-session)) 330 | 331 | | variable name | default value | description | 332 | | ---------------------------- | ------------- | -------------------------------------------------------------------------------------------------------- | 333 | | `gitea_session_provider` | `file` | Session engine provider | 334 | | `gitea_session_extra_config` | | you can use this variable to pass additional config parameters in the `[session]` section of the config. | 335 | 336 | ### Picture ([picture](https://docs.gitea.com/administration/config-cheat-sheet#picture-picture)) 337 | 338 | | variable name | default value | description | 339 | | ---------------------------- | ------------- | -------------------------------------------------------------------------------------------------------- | 340 | | `gitea_picture_extra_config` | | you can use this variable to pass additional config parameters in the `[picture]` section of the config. | 341 | 342 | ### Issue and pull request attachments ([attachment](https://docs.gitea.com/administration/config-cheat-sheet#issue-and-pull-request-attachments-attachment)) 343 | 344 | | variable name | default value | description | 345 | | ------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 346 | | `attachment_enabled` | `true` | Whether issue and pull request attachments are enabled. | 347 | | `gitea_attachment_types` | see Docs | Comma-separated list of allowed file extensions (`.zip,.txt`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types. | 348 | | `gitea_attachment_max_size` | `4` | Maximum size (MB). | 349 | | `gitea_attachment_extra_config` | | you can use this variable to pass additional config parameters in the `[attachment]` section of the config. | 350 | 351 | ### Log ([log](https://docs.gitea.com/administration/config-cheat-sheet#log-log)) 352 | 353 | | variable name | default value | description | 354 | | ------------------------ | ------------- | ---------------------------------------------------------------------------------------------------- | 355 | | `gitea_log_systemd` | `false` | Disable logging into `file`, use systemd-journald | 356 | | `gitea_log_level` | `Warn` | General log level. `[Trace, Debug, Info, Warn, Error, Critical, Fatal, None]` | 357 | | `gitea_log_extra_config` | | you can use this variable to pass additional config parameters in the `[log]` section of the config. | 358 | 359 | ### Metrics ([metrics](https://docs.gitea.com/administration/config-cheat-sheet#metrics-metrics)) 360 | 361 | | variable name | default value | description | 362 | | ---------------------------- | ------------- | -------------------------------------------------------------------------------------------------------- | 363 | | `gitea_metrics_enabled` | `false` | Enable the metrics endpoint | 364 | | `gitea_metrics_token` | | Bearer token for the Prometheus scrape job | 365 | | `gitea_metrics_extra_config` | | you can use this variable to pass additional config parameters in the `[metrics]` section of the config. | 366 | 367 | ### OAuth2 ([oauth2](https://docs.gitea.com/administration/config-cheat-sheet#oauth2-oauth2)) 368 | 369 | | variable name | default value | description | 370 | | --------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------ | 371 | | `gitea_oauth2_enabled` | `true` | Enable the Oauth2 provider (true/false) | 372 | | `gitea_oauth2_jwt_secret` | | Oauth2 JWT secret. Can be generated with `gitea generate secret JWT_SECRET`. Will be autogenerated if not defined. | 373 | | `gitea_oauth2_extra_config` | | you can use this variable to pass additional config parameters in the `[oauth2]` section of the config. | 374 | 375 | ### Federation ([federation](https://docs.gitea.com/administration/config-cheat-sheet#federation-federation)) 376 | 377 | | variable name | default value | description | 378 | | ----------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------- | 379 | | `gitea_federation_enabled` | `false` | Enable/Disable federation capabilities | 380 | | `gitea_federation_share_user_stats` | `false` | Enable/Disable user statistics for nodeinfo if federation is enabled | 381 | | `gitea_federation_extra_config` | | you can use this variable to pass additional config parameters in the `[federation]` section of the config. | 382 | 383 | ### Packages ([packages](https://docs.gitea.com/administration/config-cheat-sheet#packages-packages)) 384 | 385 | | variable name | default value | description | 386 | | ----------------------------- | ------------- | --------------------------------------------------------------------------------------------------------- | 387 | | `gitea_packages_enabled` | `true` | Enable/Disable package registry capabilities | 388 | | `gitea_packages_extra_config` | | you can use this variable to pass additional config parameters in the `[packages]` section of the config. | 389 | 390 | ### LFS ([lfs](https://docs.gitea.com/administration/config-cheat-sheet#lfs-lfs)) 391 | 392 | | variable name | default value | description | 393 | | ------------------------ | --------------------------- | ------------------------------------------------------------------------------------------------------ | 394 | | `gitea_lfs_storage_type` | `local` | Storage type for lfs | 395 | | `gitea_lfs_serve_direct` | `false` | Allows the storage driver to redirect to authenticated URLs to serve files directly. _(only Minio/S3)_ | 396 | | `gitea_lfs_content_path` | `{{ gitea_home }}/data/lfs` | Where to store LFS files | 397 | | `gitea_lfs_extra_config` | | you can use this variable to pass additional config parameters in the `[lfs]` section of the config. | 398 | 399 | ### Actions ([actions](https://docs.gitea.com/administration/config-cheat-sheet#actions-actions)) 400 | 401 | | variable name | default value | description | 402 | | ----------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | 403 | | `gitea_actions_enabled` | `false` | Enable/Disable actions capabilities globally. You may want to add `repo.actions` to `gitea_default_repo_units` to enable actions on all new repositories | 404 | | `gitea_actions_default_actions_url` | `github` | Default address to get action plugins, e.g. the default value means downloading from `https://github.com/actions/checkout` for `uses: actions/checkout@v3` | 405 | | `gitea_actions_extra_config` | | you can use this variable to pass additional config parameters in the `[actions]` section of the config. | 406 | 407 | ### Other ([other](https://docs.gitea.com/administration/config-cheat-sheet#other-other)) 408 | 409 | | variable name | default value | description | 410 | | -------------------------------------------- | ------------- | ---------------------------------------------------- | 411 | | `gitea_other_show_footer_version` | `true` | Show Gitea and Go version information in the footer. | 412 | | `gitea_other_show_footer_template_load_time` | `true` | Show time of template execution in the footer. | 413 | | `gitea_other_enable_sitemap` | `true` | Generate sitemap. | 414 | | `gitea_other_enable_feed` | `true` | Enable/Disable RSS/Atom feed. | 415 | 416 | ### additional gitea config 417 | 418 | | variable name | default value | description | 419 | | -------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | 420 | | `gitea_extra_config` | | Additional gitea configuration. Have a look at the [config-cheat-sheet](https://docs.gitea.com/administration/config-cheat-sheet) before using it! | 421 | 422 | ### Fail2Ban configuration 423 | 424 | If enabled, this will deploy a fail2ban filter and jail config for Gitea as described in the [Gitea Documentation](https://docs.gitea.io/en-us/fail2ban-setup/). 425 | 426 | As this will only deploy config files, fail2ban already has to be installed or otherwise the role will fail. 427 | 428 | | variable name | default value | description | 429 | | ------------------------------ | ------------------- | -------------------------------------------- | 430 | | `gitea_fail2ban_enabled` | `false` | Whether to deploy the fail2ban config or not | 431 | | `gitea_fail2ban_jail_maxretry` | `10` | fail2ban jail `maxretry` setting. | 432 | | `gitea_fail2ban_jail_findtime` | `3600` | fail2ban jail `findtime` setting. | 433 | | `gitea_fail2ban_jail_bantime` | `900` | fail2ban jail `bantime` setting. | 434 | | `gitea_fail2ban_jail_action` | `iptables-allports` | fail2ban jail `action` setting. | 435 | 436 | ### local gitea Users 437 | 438 | | variable | option | description | 439 | | ------------- | ---------------------- | --------------------------------------------- | 440 | | `gitea_users` | | dict to create local gitea or forgejo users | 441 | | | `name` | name for local gitea/forgejo user | 442 | | | `password` | user for local git user | 443 | | | `email` | email for local git user | 444 | | | `admin` | give user admin permissions | 445 | | | `must_change_password` | user should change password after first login | 446 | | | `state` | set to `absent` to delete user | 447 | 448 | ### optional customisation 449 | 450 | You can optionally customize your gitea using this ansible role. We got our information about customisation from [docs.gitea.io/en-us/customizing-gitea](https://docs.gitea.io/en-us/customizing-gitea/). 451 | To deploy multiple files we created the `gitea_custom_search` variable, that can point to the path where you put the custom gitea files _( default `"files/host_files/{{ inventory_hostname }}/gitea"`)_. 452 | 453 | - **LOGO**: 454 | - Set `gitea_customize_logo` to `true` 455 | - We search for: 456 | - `logo.svg` - Used for favicon, site icon, app icon 457 | - `logo.png` - Used for Open Graph 458 | - `favicon.png` - Used as fallback for browsers that don’t support SVG favicons 459 | - `favicon.svg` - Primary (SVG) favicon 460 | - `apple-touch-icon.png` - Used on iOS devices for bookmarks 461 | - We search in _(using [first_found](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/first_found_lookup.html))_: 462 | - `{{ gitea_custom_search }}/gitea_logo/` 463 | - `files/{{ inventory_hostname }}/gitea_logo/` 464 | - `files/{{ gitea_http_domain }}/gitea_logo/` 465 | - `files/gitea_logo/` 466 | - **FOOTER**: 467 | - Set `gitea_customize_footer` to `true` 468 | - We Search using first_found in: 469 | - "{{ gitea_custom_search }}/gitea_footer/extra_links_footer.tmpl" 470 | - "files/{{ inventory_hostname }}/gitea_footer/extra_links_footer.tmpl" 471 | - "files/{{ gitea_http_domain }}/gitea_footer/extra_links_footer.tmpl" 472 | - 'files/gitea_footer/extra_links_footer.tmpl' 473 | - 'files/extra_links_footer.tmpl' 474 | - **CUSTOM FILES**: 475 | - Set `gitea_customize_files` to `true` 476 | - Create a directory with the files you want to deploy. 477 | - Point `gitea_customize_files_path` to this directory. _(Default `{{ gitea_custom_search }}/gitea_files/`)_ 478 | - **CUSTOM THEMES**: 479 | - Set `gitea_custom_themes` to a list with URLs for custom theme CSS files. You usually want three individual files per theme. Example: 480 | ```yaml 481 | gitea_custom_themes: 482 | - https://example.com/theme-custom-auto.css 483 | - https://example.com/theme-custom-dark.css 484 | - https://example.com/theme-custom-light.css 485 | ``` 486 | - Set `gitea_themes` variable and include the names of the new themes. To keep the existing ones, you need to pass all themes names, e.g. `auto,gitea,arc-green,,,` 487 | 488 | ## Requirements 489 | 490 | This role uses the `ansible.builtin` and `community.general` ansible Collections. To download the latest forgejo/gitea release we use json_query. This requires `jmespath` to be available. 491 | 492 | ### Python packages 493 | 494 | - jmespath 495 | 496 | ### Galaxy Collections 497 | 498 | - community.general 499 | 500 | ### Example requirements Installation 501 | 502 | ``` 503 | ansible-galaxy collection install --update --role-file requirements.yml 504 | pip3 install --update jmespath 505 | ``` 506 | 507 | ## Contribute 508 | 509 | Don't hesitate to create a pull request, and if in doubt you can reach me at 510 | Mastodon [@l3d@chaos.social](https://chaos.social/@l3d). 511 | 512 | I'll be happy to fix any issues you raise, or even better, review your pull requests :) 513 | 514 | ## History of this role 515 | 516 | this ansible role was originally developed on [github.com/thomas-maurice/ansible-role-gitea](https://github.com/thomas-maurice/ansible-role-gitea.git). Since the role there has some problems like default values for the location of the gitea repositories and the merging of pull requests usually takes several months, a fork of the role was created that offers the same. Only tidier and with the claim to react faster to issues and pull requests. It is now Part of the [l3d.git](https://galaxy.ansible.com/l3d/git) Collection too. 517 | -------------------------------------------------------------------------------- /defaults/forgejo.yml: -------------------------------------------------------------------------------- 1 | --- 2 | gitea_theme_default: "forgejo-auto" 3 | # yamllint disable rule:line-length 4 | gitea_themes: "forgejo-auto,forgejo-light,forgejo-dark,gitea-auto,gitea-light,gitea-dark,forgejo-auto-deuteranopia-protanopia,forgejo-light-deuteranopia-protanopia,forgejo-dark-deuteranopia-protanopia,forgejo-auto-tritanopia,forgejo-light-tritanopia,forgejo-dark-tritanopia" 5 | # yamllint enable rule:line-length 6 | gitea_gpg_local_key: EB114F5E6C0DC2BCDD183550A4B61A2DC5923710.asc 7 | -------------------------------------------------------------------------------- /defaults/gitea.yml: -------------------------------------------------------------------------------- 1 | --- 2 | gitea_theme_default: "gitea-auto" 3 | gitea_themes: "gitea-auto,gitea-light,gitea-dark" 4 | gitea_gpg_local_key: '' 5 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Choose between https://forgejo.org/ and https://gitea.io/ 3 | # 'gitea' and 'forgejo' are valid options 4 | gitea_fork: "gitea" 5 | 6 | # gitea version 7 | # Use 'latest' to auto-update; upgrading past role version may lead to errors. 8 | gitea_version: "latest" 9 | gitea_version_check: true 10 | gitea_gpg_key: "7C9E68152594688862D62AF62D9AE806EC1592E2" 11 | gitea_forgejo_gpg_key: "EB114F5E6C0DC2BCDD183550A4B61A2DC5923710" 12 | gitea_gpg_server: "hkps://keys.openpgp.org" 13 | gitea_gpg_keyserver_option: "" 14 | gitea_backup_on_upgrade: false 15 | gitea_backup_location: "{{ gitea_home }}/backups/" 16 | # with systemd timer 17 | gitea_backup_scheduled: false 18 | gitea_backup_scheduled_calendar: daily 19 | # gitea_backup_scheduled_calendar: weekly 20 | submodules_versioncheck: false 21 | 22 | # gitea in the linux world 23 | gitea_group: "gitea" 24 | # gitea_groups: [] # Optional a list of groups user gitea will be added to 25 | gitea_home: "/var/lib/gitea" 26 | gitea_user_home: "{{ gitea_home }}" 27 | gitea_executable_path: "/usr/local/bin/gitea" 28 | gitea_forgejo_executable_path: "/usr/local/bin/forgejo" 29 | gitea_configuration_path: "/etc/gitea" 30 | gitea_shell: "/bin/false" 31 | gitea_systemd_cap_net_bind_service: false 32 | 33 | # optional users on gitea instance 34 | gitea_users: [] 35 | # example of entry 36 | # - name: johndoe 37 | # password: verysecret 38 | # email: "johndoe@example.com" 39 | # admin: false 40 | # must_change_password: true 41 | # state: present 42 | 43 | # Overall (DEFAULT) 44 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#overall-default 45 | gitea_app_name: "Gitea" 46 | gitea_user: "gitea" 47 | gitea_run_mode: "prod" 48 | gitea_fqdn: "localhost" 49 | 50 | # Repository (repository) 51 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#repository-repository 52 | gitea_default_branch: "main" 53 | gitea_default_private: "last" 54 | gitea_default_repo_units: "repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects" 55 | gitea_disabled_repo_units: "" 56 | gitea_disable_http_git: false 57 | gitea_disable_stars: false 58 | gitea_enable_push_create_org: false 59 | gitea_enable_push_create_user: false 60 | gitea_force_private: false 61 | gitea_user_repo_limit: "-1" 62 | gitea_repository_root: "{{ gitea_home }}/repos" 63 | gitea_repository_extra_config: "" 64 | 65 | # Repository - Upload (repository.upload) 66 | # -> https://docs.gitea.io/en-us/administration/config-cheat-sheet/#repository---upload-repositoryupload 67 | gitea_repository_upload_enabled: true 68 | gitea_repository_upload_max_size: 4 69 | gitea_repository_upload_extra_config: "" 70 | 71 | # Repository - Signing (repository.signing) 72 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#repository---signing-repositorysigning 73 | gitea_enable_repo_signing_options: false 74 | gitea_repo_signing_key: "default" 75 | gitea_repo_signing_name: "" 76 | gitea_repo_signing_email: "" 77 | gitea_repo_initial_commit: "always" 78 | gitea_repo_default_trust_model: "collaborator" 79 | gitea_repo_wiki: "never" 80 | gitea_repo_crud_actions: "pubkey, twofa, parentsigned" 81 | gitea_repo_merges: " pubkey, twofa, basesigned, commitssigned" 82 | gitea_enable_repo_signing_extra_config: "" 83 | 84 | # CORS (cors) 85 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#cors-cors 86 | gitea_enable_cors: false 87 | gitea_cors_scheme: "http" 88 | gitea_cors_allow_domain: "*" 89 | gitea_cors_allow_subdomain: false 90 | gitea_cors_methods: "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS" 91 | gitea_cors_max_age: "10m" 92 | gitea_cors_allow_credentials: false 93 | gitea_cors_headers: "Content-Type,User-Agent" 94 | gitea_cors_x_frame_options: "SAMEORIGIN" 95 | gitea_cors_extra_config: "" 96 | 97 | # UI (ui) 98 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#ui-ui 99 | gitea_show_user_email: false 100 | gitea_ui_extra_config: "" 101 | 102 | # UI - Metadata (ui.meta) 103 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#ui---metadata-uimeta 104 | gitea_ui_author: "Gitea - Git with a cup of tea" 105 | gitea_ui_description: "Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go:" 106 | gitea_ui_keywords: "go,git,self-hosted,gitea,forgejo" 107 | gitea_ui_meta_extra_config: "" 108 | 109 | # Server (server) 110 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#server-server 111 | gitea_protocol: "http" 112 | gitea_http_domain: "{{ gitea_fqdn }}" 113 | gitea_root_url: "http://{{ gitea_fqdn }}:3000" 114 | gitea_http_listen: "127.0.0.1" 115 | gitea_http_port: "3000" 116 | gitea_start_ssh: true 117 | gitea_ssh_domain: "{{ gitea_fqdn }}" 118 | gitea_ssh_port: "2222" 119 | gitea_ssh_listen: "0.0.0.0" 120 | gitea_offline_mode: true 121 | gitea_landing_page: "home" 122 | gitea_lfs_server_enabled: false 123 | gitea_lfs_jwt_secret: "" 124 | gitea_redirect_other_port: false 125 | gitea_port_to_redirect: "80" 126 | gitea_enable_tls_certs: false 127 | gitea_tls_cert_file: "https/cert.pem" 128 | gitea_tls_key_file: "https/key.pem" 129 | gitea_enable_acme: false 130 | gitea_acme_url: "" 131 | gitea_acme_accepttos: false 132 | gitea_acme_directory: "https" 133 | gitea_acme_email: "" 134 | gitea_acme_ca_root: "" 135 | gitea_server_extra_config: "" 136 | 137 | # Database (database) 138 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#database-database 139 | gitea_db_type: "sqlite3" 140 | gitea_db_host: "127.0.0.0:3306" 141 | gitea_db_name: "root" 142 | gitea_db_user: "gitea" 143 | gitea_db_password: "lel" 144 | gitea_db_ssl: "disable" 145 | gitea_db_path: "{{ gitea_home }}/data/gitea.db" 146 | gitea_db_log_sql: false 147 | gitea_database_extra_config: "" 148 | 149 | # Indexer (indexer) 150 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#indexer-indexer 151 | gitea_repo_indexer_enabled: false 152 | gitea_repo_indexer_include: "" 153 | gitea_repo_indexer_exclude: "" 154 | gitea_repo_exclude_vendored: true 155 | gitea_repo_indexer_max_file_size: "1048576" 156 | gitea_indexer_extra_config: "" 157 | gitea_issue_indexer_type: bleve 158 | gitea_issue_indexer_conn_str: "" 159 | gitea_queue_issue_indexer_extra_config: "" 160 | 161 | # Security (security) 162 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#security-security 163 | gitea_secret_key: "" 164 | gitea_disable_git_hooks: true 165 | gitea_disable_webhooks: false 166 | gitea_internal_token: "" 167 | gitea_password_check_pwn: false 168 | gitea_security_extra_config: "" 169 | 170 | # Service (service) 171 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#service-service 172 | gitea_disable_registration: false 173 | gitea_register_email_confirm: false 174 | gitea_register_manual_confirm: false 175 | gitea_require_signin: true 176 | gitea_default_keep_mail_private: true 177 | gitea_enable_captcha: true 178 | gitea_show_registration_button: true 179 | gitea_only_allow_external_registration: false 180 | gitea_enable_notify_mail: false 181 | gitea_auto_watch_new_repos: true 182 | gitea_auto_watch_on_changes: false 183 | gitea_default_allow_create_organization: false 184 | gitea_default_user_is_restricted: false 185 | gitea_email_domain_allowlist: "" 186 | gitea_default_user_visibility: public 187 | gitea_default_org_visibility: public 188 | gitea_allow_only_internal_registration: false 189 | gitea_allow_only_external_registration: false 190 | gitea_show_milestones_dashboard_page: true 191 | gitea_service_extra_config: "" 192 | 193 | # Mailer [mailer] 194 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#mailer-mailer 195 | gitea_mailer_enabled: false 196 | gitea_mailer_protocol: "dummy" 197 | gitea_mailer_smtp_addr: "" 198 | gitea_mailer_smtp_port: "" 199 | gitea_mailer_use_client_cert: false 200 | gitea_mailer_client_cert_file: "" 201 | gitea_mailer_client_key_file: "" 202 | gitea_mailer_force_trust_server_cert: false 203 | gitea_mailer_user: "" 204 | gitea_mailer_password: "" 205 | gitea_mailer_enable_helo: true 206 | gitea_mailer_from: "noreply@{{ gitea_http_domain }}" 207 | gitea_subject_prefix: "" 208 | gitea_mailer_send_as_plaintext: false 209 | gitea_mailer_extra_config: "" 210 | 211 | # Session (session) 212 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#session-session 213 | gitea_session_provider: "file" 214 | gitea_session_provider_config: "{{ gitea_home }}/data/sessions" 215 | gitea_session_extra_config: "" 216 | 217 | # Picture (picture) 218 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#picture-picture 219 | gitea_picture_extra_config: "" 220 | 221 | # Issue and pull request attachments (attachment) 222 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#issue-and-pull-request-attachments-attachment 223 | gitea_attachment_enabled: true 224 | gitea_attachment_types: ".csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip" 225 | gitea_attachment_max_size: 4 226 | gitea_attachment_extra_config: "" 227 | 228 | # Log (log) 229 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#log-log 230 | gitea_log_systemd: false 231 | gitea_log_level: "Warn" 232 | gitea_log_extra_config: "" 233 | 234 | # Metrics (metrics) 235 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#metrics-metrics 236 | gitea_metrics_enabled: false 237 | gitea_metrics_token: "" 238 | gitea_metrics_extra_config: "" 239 | 240 | # OAuth2 (oauth2) 241 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#oauth2-oauth2 242 | gitea_oauth2_enabled: true 243 | gitea_oauth2_jwt_secret: "" 244 | gitea_oauth2_extra_config: "" 245 | 246 | # Federation (federation) 247 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#federation-federation 248 | gitea_federation_enabled: false 249 | gitea_federation_share_user_stats: false 250 | gitea_federation_extra_config: "" 251 | 252 | # Packages (packages) 253 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#packages-packages 254 | gitea_packages_enabled: true 255 | gitea_packages_extra_config: "" 256 | 257 | # LFS (lfs) 258 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#lfs-lfs 259 | gitea_lfs_storage_type: "local" 260 | gitea_lfs_serve_direct: false 261 | gitea_lfs_content_path: "{{ gitea_home }}/data/lfs" 262 | gitea_lfs_extra_config: "" 263 | 264 | # Actions (actions) 265 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#actions-actions 266 | gitea_actions_enabled: false 267 | gitea_actions_default_actions_url: github 268 | gitea_actions_extra_config: "" 269 | 270 | # Other (other) 271 | # -> https://docs.gitea.io/en-us/config-cheat-sheet/#other-other 272 | gitea_other_show_footer_version: true 273 | gitea_other_show_footer_template_load_time: true 274 | gitea_other_enable_sitemap: true 275 | gitea_other_enable_feed: true 276 | 277 | # additional gitea config 278 | gitea_extra_config: "" 279 | 280 | # fail2ban 281 | gitea_fail2ban_enabled: false 282 | gitea_fail2ban_jail_maxretry: "10" 283 | gitea_fail2ban_jail_findtime: "3600" 284 | gitea_fail2ban_jail_bantime: "900" 285 | gitea_fail2ban_jail_action: "iptables-allports" 286 | 287 | # gitea customisation 288 | gitea_custom_search: "files/host_files/{{ inventory_hostname }}/gitea" 289 | gitea_customize_logo: false 290 | gitea_custom: "{{ gitea_home }}/custom" 291 | gitea_customize_footer: false 292 | gitea_customize_files: false 293 | gitea_customize_files_path: "{{ gitea_custom_search }}/gitea_files/" 294 | 295 | # systemd hardening 296 | gitea_systemd_hardening_enable: true 297 | gitea_cgroups_restriction_enable: true 298 | 299 | # source installation 300 | # https://github.com/go-gitea/gitea.git or https://codeberg.org/forgejo/forgejo.git 301 | gitea_install_source_source_url: https://github.com/go-gitea/gitea.git 302 | gitea_install_source_binary_name: "{{ gitea_fork }}" 303 | gitea_install_source_binary_install_path: /usr/local/bin/ 304 | gitea_install_source_build_dir: "/tmp/{{ gitea_fork }}" 305 | gitea_install_source_cleanup_build_dir: true 306 | gitea_install_source_apt_build_deps: 307 | - sed 308 | - make 309 | - nodejs 310 | - golang 311 | - git 312 | - jq 313 | gitea_install_source_dnf_build_deps: 314 | - sed 315 | - make 316 | - nodejs 317 | - go 318 | - git 319 | - jq 320 | -------------------------------------------------------------------------------- /files/EB114F5E6C0DC2BCDD183550A4B61A2DC5923710.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Comment: EB11 4F5E 6C0D C2BC DD18 3550 A4B6 1A2D C592 3710 3 | Comment: Forgejo 4 | Comment: Forgejo Releases 5 | 6 | xjMEY3T/yhYJKwYBBAHaRw8BAQdAVxqCQrSbpDNrx8CiTM8PUAVqdCyv2UmBDhpP 7 | HZIpoIDNHUZvcmdlam8gPGNvbnRhY3RAZm9yZ2Vqby5vcmc+wsB+BBMWCgDmAhsD 8 | BQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAhkBFiEE6xFPXmwNwrzdGDVQpLYaLcWS 9 | NxAFAmSc08VBFIAAAAAAEAAocHJvb2ZAYXJpYWRuZS5pZGh0dHBzOi8vY29kZWJl 10 | cmcub3JnL2Zvcmdlam8vZ2l0ZWFfcHJvb2Y2FIAAAAAAEAAdcHJvb2ZAYXJpYWRu 11 | ZS5pZGh0dHBzOi8vZmxvc3Muc29jaWFsL0Bmb3JnZWpvMRSAAAAAABAAGHByb29m 12 | QGFyaWFkbmUuaWRkbnM6Zm9yZ2Vqby5vcmc/dHlwZT1UWFQACgkQpLYaLcWSNxDM 13 | 2wEA6bOel3R25z3YUXL4hI2S8jRkJbOQawq0vgUnYNgS9hcBAK2zq4Zt4ctvSB+x 14 | TqhR6Zi6aqSD3QrRnUVvV1xZhdkEwsCABBMWCgDoAhsDBQsJCAcDBRUKCQgLBRYC 15 | AwEAAh4BAheAAhkBFiEE6xFPXmwNwrzdGDVQpLYaLcWSNxAFAmScz7JDFIAAAAAA 16 | EAAqcHJvb2ZAYXJpYWRuZS5pZGh0dHBzOi8vY29kZWJlcmcub3JnL2Zvcmdlam8v 17 | Zm9yZ2Vqb19wcm9vZjYUgAAAAAAQAB1wcm9vZkBhcmlhZG5lLmlkaHR0cHM6Ly9m 18 | bG9zcy5zb2NpYWwvQGZvcmdlam8xFIAAAAAAEAAYcHJvb2ZAYXJpYWRuZS5pZGRu 19 | czpmb3JnZWpvLm9yZz90eXBlPVRYVAAKCRCkthotxZI3EBJ1AP9UeN1HFGz90r34 20 | PGrOj1225HfJzdWgamEUkEKEwShcIQD+K/o7sLJM+C/mJXaCixAZgvRd9/rYq27T 21 | 9Y2rTQybSwnCwH4EExYKAOYCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4ACGQEW 22 | IQTrEU9ebA3CvN0YNVCkthotxZI3EAUCY3spkjYUgAAAAAAQAB1wcm9vZkBhcmlh 23 | ZG5lLmlkaHR0cHM6Ly9mbG9zcy5zb2NpYWwvQGZvcmdlam8xFIAAAAAAEAAYcHJv 24 | b2ZAYXJpYWRuZS5pZGRuczpmb3JnZWpvLm9yZz90eXBlPVRYVEEUgAAAAAAQAChw 25 | cm9vZkBhcmlhZG5lLmlkaHR0cHM6Ly9jb2RlYmVyZy5vcmcvZm9yZ2Vqby9naXRl 26 | YV9wcm9vZgAKCRCkthotxZI3EC+hAQCxsUupyqMChFMqk/74PqzSlmCd6RXtbezP 27 | W66YostSbgD9G+N+c9or1cBkcSejREOSy7TFrDrvek+ZhdZVhCp1UALCwEcEExYK 28 | AK8CGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4ACGQEWIQTrEU9ebA3CvN0YNVCk 29 | thotxZI3EAUCY3inA0EUgAAAAAAQAChwcm9vZkBhcmlhZG5lLmlkaHR0cHM6Ly9j 30 | b2RlYmVyZy5vcmcvZm9yZ2Vqby9naXRlYV9wcm9vZjEUgAAAAAAQABhwcm9vZkBh 31 | cmlhZG5lLmlkZG5zOmZvcmdlam8ub3JnP3R5cGU9VFhUAAoJEKS2Gi3FkjcQNV8B 32 | AJfcHBzskW78lJVJeQwCI70qorOhC/QUp80jjNzs5lO7AQCujYgrae3vZb/476sc 33 | wM33ufSpBguNwTLbCI6C5g8+B80mRm9yZ2VqbyBSZWxlYXNlcyA8cmVsZWFzZUBm 34 | b3JnZWpvLm9yZz7CkAQTFgoAOAIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgBYh 35 | BOsRT15sDcK83Rg1UKS2Gi3FkjcQBQJjeKH0AAoJEKS2Gi3FkjcQC5YBAKwCGFDD 36 | SpX0JwBrzIP8W8ElwHvdBz2XDg8LwyQgr722AP9r01rbFwY4axDxpNj+BUFxwD5F 37 | hza1cE3932eTsSOPDsKQBBMWCAA4FiEE6xFPXmwNwrzdGDVQpLYaLcWSNxAFAmN4 38 | k+kCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQpLYaLcWSNxBHrQD+PFo/ 39 | ii8p72HP0KsJbHPGnS/Sk9pFGd16fs1Hd88JHj0A/10XNyGQgwbe+X+K/a97vWW8 40 | vAzA1EtFIMfCGhIO8EoIzjMEY3UANBYJKwYBBAHaRw8BAQdAKvAs2Ij2RamYUzz4 41 | sBgsc2J+4fEwvSMcTp6rPZizRhfCwDUEGBYIACYWIQTrEU9ebA3CvN0YNVCkthot 42 | xZI3EAUCY3UANAIbAgUJAeEzgACBCRCkthotxZI3EHYgBBkWCAAdFiEE98vwIJTn 43 | Zl4X7WxE44G/PlDVNwcFAmN1ADQACgkQ44G/PlDVNwdIlgD+K15nuEec+VTFdP7Y 44 | Y3SxM8Rjg2EtXk007+LM7XQfN9sBAOLjBTzIdaaKOpoAkGQ9Th/IphSUOnPYZVO5 45 | a6cN+wAM458A/itf3urQehI5SbKtbRqIDhqQZQVAcEeG2eQFunuofjDWAQDt/gE5 46 | XgTiQgnkTcqAX7GQeE74O/Q5vDtX10NjbzV7D84zBGeOav0WCSsGAQQB2kcPAQEH 47 | QI2JXHjIx25g9WZHNyjkdUiRBPl5Y1JjjJCPvXM0/9RjwsA1BBgWCAAmFiEE6xFP 48 | XmwNwrzdGDVQpLYaLcWSNxAFAmeOav0CGwIFCQO1OAAAgQkQpLYaLcWSNxB2IAQZ 49 | FggAHRYhBA9SfPk6PQ0JJdPFXtCoIAUOFgnlBQJnjmr9AAoJENCoIAUOFgnljUwA 50 | +wSjU/mk4xGIlwzJdPnnNzIsiMeqtuYokbSrOIxXIhP1AP93qtVr+kOu3pDs9JC+ 51 | 8CYG0DK1QD1LmlGP59WRGevSCXChAQDy6SCfnfcr5P4fYaz04+Tl0CDUkFOGP+sV 52 | S/isPTssbAD9H2hKJKEmwuAd2MeFA3Bo3z5rUVWkfAcnv7Oy7u+OWQfOMwRlfHnh 53 | FgkrBgEEAdpHDwEBB0DGoKPPOOx7rnqT318eykUkMJbk83MhcBqrecOADO3i2sLA 54 | NQQYFggAJhYhBOsRT15sDcK83Rg1UKS2Gi3FkjcQBQJlfHnhAhsCBQkCx+oAAIEJ 55 | EKS2Gi3FkjcQdiAEGRYIAB0WIQTfMxnqNtWZwdSmg9SzsfYKxXfyogUCZXx54QAK 56 | CRCzsfYKxXfyoocRAP48OQpiBTkwC7kLLyuqVlP1t0hBQddr4i4rIV8Ug5tHzwEA 57 | pl8Q+S4k/ROQS5FOhy7GBC337SncJFJYDD0pTcSecw+J3AEAn4qax72Oyfb0vaPY 58 | m+WdqsfVBd2Hd2vJIwCjglp55B0BALIJE6nvACcKzTRUj7AQSLGvELGfJfM320xX 59 | E0ZVBZkKzjgEY3T/yhIKKwYBBAGXVQEFAQEHQJmdF8gfFNWE4XyR2Ft7hgmx4/JU 60 | WLxRJ+4NfLgeAgdGAwEIB8J4BBgWCAAgFiEE6xFPXmwNwrzdGDVQpLYaLcWSNxAF 61 | AmN0/8oCGwwACgkQpLYaLcWSNxB2ugD+McWq3vL+v/nN0rhNhin7mOU6Azlkjuk2 62 | FaG0gVuqbH0BAIpIl/ZiA8Es0lIv/zq+kT1voi9MT/wQ1H/vFhogDugC 63 | =zbGk 64 | -----END PGP PUBLIC KEY BLOCK----- 65 | -------------------------------------------------------------------------------- /files/extra_links_footer.tmpl: -------------------------------------------------------------------------------- 1 | Datenschutz 2 | Impressum 3 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Restart gitea" 3 | become: true 4 | listen: "systemctl restart gitea" 5 | ansible.builtin.systemd_service: 6 | name: gitea 7 | state: restarted 8 | when: ansible_service_mgr == "systemd" 9 | 10 | - name: "Reload systemd" 11 | become: true 12 | ansible.builtin.systemd_service: 13 | daemon_reload: true 14 | when: ansible_service_mgr == "systemd" 15 | 16 | - name: "Systemctl restart fail2ban" 17 | become: true 18 | ansible.builtin.systemd_service: 19 | name: fail2ban 20 | state: restarted 21 | when: ansible_service_mgr == "systemd" 22 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | role_name: gitea 4 | author: roles-ansible 5 | description: Ansible role to configure and deploy gitea and forgejo, a painless self-hosted Git service. 6 | license: "BSD-3-Clause" 7 | min_ansible_version: "2.11" 8 | platforms: 9 | - name: Debian 10 | versions: 11 | - all 12 | - name: Ubuntu 13 | versions: 14 | - all 15 | - name: Fedora 16 | versions: 17 | - all 18 | - name: EL 19 | versions: 20 | - all 21 | galaxy_tags: 22 | - gitea 23 | - forgejo 24 | - git 25 | - system 26 | - development 27 | - sourcecontrol 28 | - selfhosted 29 | - gitserver 30 | - gogs 31 | - linux 32 | dependencies: [] 33 | -------------------------------------------------------------------------------- /requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | collections: 3 | - name: "community.general" 4 | version: ">=10.0.0,<11.0.0" 5 | -------------------------------------------------------------------------------- /tasks/backup-scheduled.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: "Create backup directory" 4 | become: true 5 | ansible.builtin.file: 6 | path: "{{ gitea_backup_location }}" 7 | state: 'directory' 8 | owner: "{{ gitea_user }}" 9 | group: "{{ gitea_group }}" 10 | mode: 'u=rwx,g=rx,o=' 11 | 12 | - name: Ensure service gitea-backup.service exists 13 | ansible.builtin.template: 14 | src: systemd-gitea-backup.service.conf.j2 15 | dest: "/etc/systemd/system/{{ gitea_fork }}-backup.service" 16 | mode: '0644' 17 | notify: 18 | - Reload systemd 19 | 20 | - name: Ensure service gitea-backup.timer exists 21 | ansible.builtin.template: 22 | src: "systemd-gitea-backup.timer.conf.j2" 23 | dest: "/etc/systemd/system/{{ gitea_fork }}-backup.timer" 24 | mode: '0644' 25 | notify: 26 | - Reload systemd 27 | 28 | - name: Ensure service gitea-backup is enabled 29 | ansible.builtin.service: 30 | name: "{{ gitea_fork }}-backup.timer" 31 | enabled: true 32 | state: started 33 | -------------------------------------------------------------------------------- /tasks/backup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get service facts 3 | ansible.builtin.service_facts: 4 | 5 | - name: Backup block 6 | when: 7 | - ansible_facts.services["gitea.service"] is defined 8 | - ansible_facts.services["gitea.service"].state == "running" 9 | - gitea_active_version.stdout != gitea_version_target 10 | block: 11 | - name: Stopping gitea before upgrade 12 | become: true 13 | ansible.builtin.systemd_service: 14 | name: "gitea.service" 15 | state: "stopped" 16 | when: ansible_service_mgr == "systemd" 17 | 18 | - name: "Create backup directory" 19 | become: true 20 | ansible.builtin.file: 21 | path: "{{ gitea_backup_location }}" 22 | state: "directory" 23 | owner: "{{ gitea_user }}" 24 | group: "{{ gitea_group }}" 25 | mode: "u=rwx,g=rx,o=" 26 | 27 | - name: Backing up gitea before upgrade 28 | become: true 29 | ansible.builtin.command: 30 | cmd: "sudo -u {{ gitea_user }} {{ gitea_full_executable_path }} dump -c {{ gitea_configuration_path }}/gitea.ini" 31 | chdir: "{{ gitea_backup_location }}" 32 | changed_when: true 33 | rescue: 34 | - name: Starting gitea because backup failed 35 | become: true 36 | ansible.builtin.systemd_service: 37 | name: "gitea.service" 38 | state: "started" 39 | when: ansible_service_mgr == "systemd" 40 | 41 | - name: Print updating error and cancel 42 | ansible.builtin.fail: 43 | msg: "failed to backup gitea" 44 | -------------------------------------------------------------------------------- /tasks/configure.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Make sure gitea_register_email_confirm is false when gitea_register_manual_confirm is true 3 | ansible.builtin.fail: 4 | msg: | 5 | To manually confirm registrations, 6 | gitea_register_email_confirm needs to be false 7 | and gitea_register_manual_confirm should be true. 8 | when: gitea_register_manual_confirm | bool and gitea_register_email_confirm | bool 9 | 10 | - name: DEBUG 11 | ansible.builtin.debug: 12 | msg: "gitea_themes: {{ gitea_themes }}" 13 | 14 | - name: "Configure gitea" 15 | become: true 16 | ansible.builtin.template: 17 | src: "templates/gitea.ini.j2" 18 | dest: "{{ gitea_configuration_path }}/gitea.ini" 19 | owner: "{{ gitea_user }}" 20 | group: "{{ gitea_group }}" 21 | mode: "0640" 22 | notify: "systemctl restart gitea" 23 | 24 | - name: "Service gitea" 25 | become: true 26 | ansible.builtin.systemd_service: 27 | name: gitea 28 | state: started 29 | enabled: true 30 | when: ansible_service_mgr == "systemd" 31 | -------------------------------------------------------------------------------- /tasks/create_user.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Create Gitea Group" 3 | become: true 4 | ansible.builtin.group: 5 | name: "{{ gitea_group }}" 6 | system: true 7 | state: "present" 8 | 9 | - name: Switch shell when not using the builtin ssh server 10 | ansible.builtin.set_fact: 11 | gitea_shell: "/bin/bash" 12 | when: "not gitea_start_ssh and gitea_shell == '/bin/false'" 13 | 14 | - name: "Create Gitea user" 15 | become: true 16 | ansible.builtin.user: 17 | name: "{{ gitea_user }}" 18 | comment: "Gitea user" 19 | group: "{{ gitea_group }}" 20 | groups: "{{ gitea_groups | default(omit) }}" 21 | home: "{{ gitea_user_home }}" 22 | shell: "{{ gitea_shell }}" 23 | system: true 24 | -------------------------------------------------------------------------------- /tasks/customize_footer.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create directory for custom footer 3 | become: true 4 | ansible.builtin.file: 5 | path: "{{ item }}" 6 | state: directory 7 | owner: "{{ gitea_user }}" 8 | group: "{{ gitea_group }}" 9 | mode: "0755" 10 | loop: 11 | - "{{ gitea_custom }}/templates" 12 | - "{{ gitea_custom }}/templates/custom" 13 | 14 | - name: Transfer custom footer template 15 | become: true 16 | ansible.builtin.copy: 17 | src: "{{ lookup('first_found', transfer_custom_footer) }}" 18 | dest: "{{ gitea_custom }}/templates/custom/extra_links_footer.tmpl" 19 | owner: "{{ gitea_user }}" 20 | group: "{{ gitea_group }}" 21 | mode: "0755" 22 | failed_when: false 23 | tags: skip_ansible_lint 24 | notify: "systemctl restart gitea" 25 | -------------------------------------------------------------------------------- /tasks/customize_logo.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create directory for custom logos 3 | become: true 4 | ansible.builtin.file: 5 | path: "{{ item }}" 6 | state: directory 7 | owner: "{{ gitea_user }}" 8 | group: "{{ gitea_group }}" 9 | mode: "0755" 10 | loop: 11 | - "{{ gitea_custom }}/public" 12 | - "{{ gitea_custom }}/public/assets" 13 | - "{{ gitea_custom }}/public/assets/img" 14 | 15 | - name: Transfer custom logo.svg 16 | become: true 17 | ansible.builtin.copy: 18 | src: "{{ lookup('first_found', transfer_custom_logo_logosvg) }}" 19 | dest: "{{ gitea_custom }}/public/assets/img/logo.svg" 20 | owner: "{{ gitea_user }}" 21 | group: "{{ gitea_group }}" 22 | mode: "0640" 23 | tags: skip_ansible_lint 24 | failed_when: false 25 | 26 | - name: Transfer custom logo.png 27 | become: true 28 | ansible.builtin.copy: 29 | src: "{{ lookup('first_found', transfer_custom_logo_logopng) }}" 30 | dest: "{{ gitea_custom }}/public/assets/img/logo.png" 31 | owner: "{{ gitea_user }}" 32 | group: "{{ gitea_group }}" 33 | mode: "0640" 34 | tags: skip_ansible_lint 35 | failed_when: false 36 | 37 | - name: Transfer custom favicon.png 38 | become: true 39 | ansible.builtin.copy: 40 | src: "{{ lookup('first_found', transfer_custom_logo_faviconpng) }}" 41 | dest: "{{ gitea_custom }}/public/assets/img/favicon.png" 42 | owner: "{{ gitea_user }}" 43 | group: "{{ gitea_group }}" 44 | mode: "0640" 45 | tags: skip_ansible_lint 46 | failed_when: false 47 | 48 | - name: Transfer custom favicon.svg 49 | become: true 50 | ansible.builtin.copy: 51 | src: "{{ lookup('first_found', transfer_custom_logo_faviconsvg) }}" 52 | dest: "{{ gitea_custom }}/public/assets/img/favicon.svg" 53 | owner: "{{ gitea_user }}" 54 | group: "{{ gitea_group }}" 55 | mode: "0640" 56 | tags: skip_ansible_lint 57 | failed_when: false 58 | 59 | - name: Transfer custom apple-touch-icon.png 60 | become: true 61 | ansible.builtin.copy: 62 | src: "{{ lookup('first_found', transfer_custom_logo_appletouchiconpng) }}" 63 | dest: "{{ gitea_custom }}/public/assets/img/apple-touch-icon.png" 64 | owner: "{{ gitea_user }}" 65 | group: "{{ gitea_group }}" 66 | mode: "0640" 67 | tags: skip_ansible_lint 68 | failed_when: false 69 | -------------------------------------------------------------------------------- /tasks/customize_public_files.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create public directory for custom public web files 3 | become: true 4 | ansible.builtin.file: 5 | path: "{{ item }}" 6 | state: directory 7 | owner: "{{ gitea_user }}" 8 | group: "{{ gitea_group }}" 9 | mode: "0755" 10 | loop: 11 | - "{{ gitea_custom }}/public/assets/" 12 | 13 | - name: Transfer custom public web data 14 | become: true 15 | ansible.builtin.copy: 16 | src: "{{ gitea_customize_files_path }}" 17 | dest: "{{ gitea_custom }}/public/assets/" 18 | owner: "{{ gitea_user }}" 19 | group: "{{ gitea_group }}" 20 | directory_mode: true 21 | mode: "0755" 22 | failed_when: false 23 | tags: skip_ansible_lint 24 | notify: "systemctl restart gitea" 25 | 26 | - name: Create css directory for custom themes 27 | when: gitea_custom_themes is defined 28 | ansible.builtin.file: 29 | path: "{{ gitea_custom }}/public/css" 30 | state: directory 31 | owner: "{{ gitea_user }}" 32 | group: "{{ gitea_group }}" 33 | mode: "0755" 34 | 35 | - name: Get custom themes 36 | when: gitea_custom_themes is defined 37 | ansible.builtin.get_url: 38 | url: "{{ item.name }}" 39 | dest: "{{ gitea_custom }}/css/{{ item.name | basename }}" 40 | owner: "{{ gitea_user }}" 41 | group: "{{ gitea_group }}" 42 | mode: "0755" 43 | loop: "{{ gitea_custom_themes }}" 44 | notify: "systemctl restart gitea" 45 | -------------------------------------------------------------------------------- /tasks/directory.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Check {{ item }}" 3 | become: true 4 | ansible.builtin.file: 5 | path: "{{ item }}" 6 | state: directory 7 | owner: "{{ gitea_user }}" 8 | group: "{{ gitea_group }}" 9 | mode: "0755" 10 | check_mode: true 11 | diff: true 12 | register: _gitea_dir_check 13 | 14 | - name: "Create {{ item }}" # noqa no-handler execute immediately. 15 | when: _gitea_dir_check.changed 16 | become: true 17 | ansible.builtin.file: 18 | path: "{{ item }}" 19 | state: directory 20 | owner: "{{ gitea_user }}" 21 | group: "{{ gitea_group }}" 22 | mode: "0755" 23 | -------------------------------------------------------------------------------- /tasks/fail2ban.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install fail2ban filter 3 | become: true 4 | ansible.builtin.template: 5 | src: fail2ban/filter.conf.j2 6 | dest: /etc/fail2ban/filter.d/gitea.conf 7 | owner: root 8 | group: root 9 | mode: 0444 10 | notify: "Systemctl restart fail2ban" 11 | when: "'fail2ban' in ansible_facts.packages" 12 | 13 | - name: Install fail2ban jail 14 | become: true 15 | ansible.builtin.template: 16 | src: fail2ban/jail.conf.j2 17 | dest: /etc/fail2ban/jail.d/gitea.conf 18 | owner: root 19 | group: root 20 | mode: 0444 21 | notify: "Systemctl restart fail2ban" 22 | when: "'fail2ban' in ansible_facts.packages" 23 | 24 | - name: Warn if fail2ban is not installed 25 | ansible.builtin.fail: 26 | msg: "the package fail2ban is not installed. no fail2ban filters deployed." 27 | when: "'fail2ban' not in ansible_facts.packages" 28 | failed_when: false 29 | tags: skip_ansible_lint_ignore-errors 30 | -------------------------------------------------------------------------------- /tasks/gitea_secrets.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Generate gitea SECRET_KEY if not provided 3 | become: true 4 | ansible.builtin.shell: "umask 077; {{ gitea_full_executable_path }} generate secret SECRET_KEY > {{ gitea_configuration_path }}/gitea_secret_key" 5 | args: 6 | creates: "{{ gitea_configuration_path }}/gitea_secret_key" 7 | when: gitea_secret_key | string | length == 0 8 | 9 | - name: Read gitea SECRET_KEY from file 10 | become: true 11 | ansible.builtin.slurp: 12 | src: "{{ gitea_configuration_path }}/gitea_secret_key" 13 | register: remote_secret_key 14 | when: gitea_secret_key | string | length == 0 15 | 16 | - name: Set fact gitea_secret_key 17 | ansible.builtin.set_fact: 18 | gitea_secret_key: "{{ remote_secret_key['content'] | b64decode }}" 19 | when: gitea_secret_key | string | length == 0 20 | 21 | - name: Generate gitea INTERNAL_TOKEN if not provided 22 | become: true 23 | ansible.builtin.shell: "umask 077; {{ gitea_full_executable_path }} generate secret INTERNAL_TOKEN > {{ gitea_configuration_path }}/gitea_internal_token" 24 | args: 25 | creates: "{{ gitea_configuration_path }}/gitea_internal_token" 26 | when: gitea_internal_token | string | length == 0 27 | 28 | - name: Read gitea INTERNAL_TOKEN from file 29 | become: true 30 | ansible.builtin.slurp: 31 | src: "{{ gitea_configuration_path }}/gitea_internal_token" 32 | register: remote_internal_token 33 | when: gitea_internal_token | string | length == 0 34 | 35 | - name: Set fact gitea_internal_token 36 | ansible.builtin.set_fact: 37 | gitea_internal_token: "{{ remote_internal_token['content'] | b64decode }}" 38 | when: gitea_internal_token | string | length == 0 39 | -------------------------------------------------------------------------------- /tasks/install_forgejo.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Dependency block 3 | block: 4 | - name: Update apt cache 5 | become: true 6 | ansible.builtin.apt: 7 | cache_valid_time: 3600 8 | update_cache: true 9 | register: _pre_update_apt_cache 10 | until: _pre_update_apt_cache is succeeded 11 | when: 12 | - ansible_pkg_mgr == "apt" 13 | 14 | - name: Install dependencies 15 | become: true 16 | ansible.builtin.package: 17 | name: "{{ gitea_dependencies }}" 18 | state: present 19 | register: _install_dep_packages 20 | until: _install_dep_packages is succeeded 21 | retries: 5 22 | delay: 2 23 | 24 | - name: Install forgejo block 25 | when: not ansible_check_mode and (gitea_active_version.stdout != gitea_version_target) 26 | block: 27 | - name: Download forgejo archive 28 | ansible.builtin.get_url: 29 | url: "{{ gitea_forgejo_dl_url | first }}" 30 | dest: "/tmp/{{ gitea_filename }}" 31 | checksum: "sha256:{{ gitea_forgejo_checksum }}" 32 | mode: 0640 33 | register: _download_archive 34 | become: false 35 | until: _download_archive is succeeded 36 | retries: 5 37 | delay: 2 38 | 39 | - name: Download forgejo asc file 40 | ansible.builtin.get_url: 41 | url: "{{ gitea_forgejo_signed_url | first }}" 42 | dest: "/tmp/{{ gitea_filename }}.asc" 43 | mode: 0640 44 | register: _download_asc 45 | become: false 46 | until: _download_asc is succeeded 47 | retries: 5 48 | delay: 2 49 | 50 | - name: Check forgejo gpg key 51 | ansible.builtin.command: "gpg --list-keys 0x{{ gitea_forgejo_gpg_key }}" 52 | register: _gitea_gpg_key_status 53 | changed_when: false 54 | become: false 55 | failed_when: _gitea_gpg_key_status.rc not in (0, 2) 56 | 57 | - name: Print gpg key status on verbosity # noqa: H500 58 | ansible.builtin.debug: 59 | msg: "{{ _gitea_gpg_key_status.stdout }}" 60 | verbosity: 1 61 | 62 | - name: Gpg key 63 | block: 64 | - name: Import forgejo gpg key 65 | ansible.builtin.command: "gpg --keyserver {{ gitea_gpg_server }} --recv {{ gitea_forgejo_gpg_key }}" 66 | register: _gitea_import_key 67 | become: false 68 | changed_when: '"imported: 1" in _gitea_import_key.stderr' 69 | # when: '_gitea_gpg_key_status.rc != 0 or "expired" in _gitea_gpg_key_status.stdout' 70 | rescue: 71 | - name: Load local forgejo gpg key 72 | ansible.builtin.copy: 73 | src: "{{ gitea_gpg_local_key }}" 74 | dest: /tmp/ 75 | mode: "0644" 76 | become: false 77 | when: gitea_gpg_local_key | length > 0 78 | 79 | - name: Import local forgejo gpg key 80 | ansible.builtin.command: "gpg --import /tmp/{{ gitea_gpg_local_key | ansible.builtin.basename }}" 81 | register: import0 82 | changed_when: "'imported: [1-9]+' in import0.stdout" 83 | become: false 84 | when: gitea_gpg_local_key | length > 0 85 | 86 | - name: Check archive signature 87 | become: false 88 | ansible.builtin.command: "gpg --verify /tmp/{{ gitea_filename }}.asc /tmp/{{ gitea_filename }}" 89 | changed_when: false 90 | 91 | - name: Propagate gitea binary 92 | become: true 93 | ansible.builtin.copy: 94 | src: "/tmp/{{ gitea_filename }}" 95 | remote_src: true 96 | dest: "{{ gitea_full_executable_path }}" 97 | mode: 0755 98 | owner: root 99 | group: root 100 | notify: "systemctl restart gitea" 101 | -------------------------------------------------------------------------------- /tasks/install_gitea.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Dependency block 3 | block: 4 | - name: Update apt cache 5 | become: true 6 | ansible.builtin.apt: 7 | cache_valid_time: 3600 8 | update_cache: true 9 | register: _pre_update_apt_cache 10 | until: _pre_update_apt_cache is succeeded 11 | when: 12 | - ansible_pkg_mgr == "apt" 13 | 14 | - name: Install dependencies 15 | become: true 16 | ansible.builtin.package: 17 | name: "{{ gitea_dependencies }}" 18 | state: present 19 | register: _install_dep_packages 20 | until: _install_dep_packages is succeeded 21 | retries: 5 22 | delay: 2 23 | 24 | - name: Install gitea block 25 | when: (not gitea_version_check | bool) or (not ansible_check_mode and (gitea_active_version.stdout != gitea_version_target)) 26 | block: 27 | - name: Download gitea archive 28 | ansible.builtin.get_url: 29 | url: "{{ gitea_dl_url }}.xz" 30 | dest: "/tmp/{{ gitea_filename }}.xz" 31 | checksum: "sha256:{{ gitea_dl_url }}.xz.sha256" 32 | mode: 0640 33 | register: _download_archive 34 | become: false 35 | until: _download_archive is succeeded 36 | retries: 5 37 | delay: 2 38 | 39 | - name: Download gitea asc file 40 | ansible.builtin.get_url: 41 | url: "{{ gitea_dl_url }}.xz.asc" 42 | dest: "/tmp/{{ gitea_filename }}.xz.asc" 43 | mode: 0640 44 | register: _download_asc 45 | become: false 46 | until: _download_asc is succeeded 47 | retries: 5 48 | delay: 2 49 | 50 | - name: Check gitea gpg key 51 | ansible.builtin.command: "gpg --list-keys 0x{{ gitea_gpg_key }}" 52 | register: _gitea_gpg_key_status 53 | changed_when: false 54 | failed_when: _gitea_gpg_key_status.rc not in (0, 2) 55 | 56 | - name: Print gpg key status on verbosity # noqa: H500 57 | ansible.builtin.debug: 58 | msg: "{{ _gitea_gpg_key_status.stdout }}" 59 | verbosity: 1 60 | 61 | - name: Import gitea gpg key 62 | ansible.builtin.command: "gpg --keyserver {{ gitea_gpg_server }} --keyserver-option '{{ gitea_gpg_keyserver_option }}' --recv {{ gitea_gpg_key }}" 63 | register: _gitea_import_key 64 | become: false 65 | changed_when: '"imported: 1" in _gitea_import_key.stderr' 66 | when: '_gitea_gpg_key_status.rc != 0 or "expired" in _gitea_gpg_key_status.stdout' 67 | 68 | - name: Check archive signature 69 | ansible.builtin.command: "gpg --verify /tmp/{{ gitea_filename }}.xz.asc /tmp/{{ gitea_filename }}.xz" 70 | changed_when: false 71 | become: false 72 | 73 | - name: Unpack gitea binary 74 | ansible.builtin.command: 75 | cmd: "xz -k -d /tmp/{{ gitea_filename }}.xz" 76 | creates: "/tmp/{{ gitea_filename }}" 77 | 78 | - name: Propagate gitea binary 79 | become: true 80 | ansible.builtin.copy: 81 | src: "/tmp/{{ gitea_filename }}" 82 | remote_src: true 83 | dest: "{{ gitea_full_executable_path }}" 84 | mode: 0755 85 | owner: root 86 | group: root 87 | notify: "systemctl restart gitea" 88 | -------------------------------------------------------------------------------- /tasks/install_source.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Source build dependencies 3 | block: 4 | - name: Gather package facts 5 | ansible.builtin.package_facts: 6 | manager: auto 7 | 8 | - name: Ensure curl is installed 9 | ansible.builtin.package: 10 | name: "curl" 11 | state: present 12 | when: '"curl" not in ansible_facts.packages' 13 | 14 | - name: Source build dependencies - node 15 | block: 16 | - name: Query required node version from source 17 | ansible.builtin.get_url: 18 | url: >- 19 | {% if gitea_fork == 'forgejo' %} 20 | https://codeberg.org/forgejo/forgejo/raw/branch/forgejo/.forgejo/workflows/build-release.yml 21 | {% else %} 22 | https://raw.githubusercontent.com/go-gitea/gitea/main/.github/workflows/release-tag-rc.yml 23 | {% endif %} 24 | dest: "/tmp/{{ gitea_fork }}-build-release.yml" 25 | mode: "0644" 26 | register: build_file_download 27 | 28 | - name: Extract Node.js version from build file 29 | ansible.builtin.shell: | 30 | set -o pipefail 31 | grep -E "node-version:" "/tmp/{{ gitea_fork }}-build-release.yml" | head -n 1 | sed -E 's/.*node-version:\s*([0-9]+).*/\1/' 32 | register: node_version_result 33 | changed_when: false 34 | 35 | - name: Set node version fact 36 | ansible.builtin.set_fact: 37 | node_version: "{{ node_version_result.stdout | trim }}" 38 | 39 | - name: "Enable nodejs module stream - v{{ node_version }}" 40 | when: ansible_os_family == "RedHat" 41 | ansible.builtin.dnf: 42 | name: "@nodejs:{{ node_version }}" 43 | state: present 44 | become: true 45 | 46 | - name: Download NodeSource setup script 47 | ansible.builtin.get_url: 48 | url: "https://deb.nodesource.com/setup_{{ node_version }}.x" 49 | dest: "/tmp/nodesource_setup.sh" 50 | mode: "0755" 51 | when: ansible_os_family == 'Debian' 52 | 53 | - name: Execute NodeSource setup script 54 | ansible.builtin.command: bash /tmp/nodesource_setup.sh 55 | register: nodesource_result 56 | changed_when: nodesource_result.rc == 0 and "is already installed" not in nodesource_result.stdout 57 | when: ansible_os_family == 'Debian' 58 | 59 | - name: Install apt build dependencies 60 | become: true 61 | ansible.builtin.apt: 62 | name: "{{ item }}" 63 | state: present 64 | register: _install_build_deps 65 | until: _install_build_deps is succeeded 66 | retries: 5 67 | delay: 2 68 | loop: "{{ gitea_install_source_apt_build_deps }}" 69 | when: 'item not in ansible_facts.packages and ansible_os_family == "Debian"' 70 | 71 | - name: Install dnf build dependencies 72 | become: true 73 | ansible.builtin.dnf: 74 | name: "{{ item }}" 75 | state: present 76 | register: _install_build_deps 77 | until: _install_build_deps is succeeded 78 | retries: 5 79 | delay: 2 80 | loop: "{{ gitea_install_source_dnf_build_deps }}" 81 | when: 'item not in ansible_facts.packages and ansible_os_family == "RedHat"' 82 | 83 | - name: Source build dependencies - go 84 | block: 85 | - name: Extract required go version for source build 86 | ansible.builtin.get_url: 87 | url: >- 88 | {% if gitea_fork == 'forgejo' %} 89 | https://codeberg.org/forgejo/forgejo/raw/branch/forgejo/go.mod 90 | {% else %} 91 | https://raw.githubusercontent.com/go-gitea/gitea/main/go.mod 92 | {% endif %} 93 | dest: "/tmp/{{ gitea_fork }}-go.mod" 94 | mode: "0644" 95 | register: build_go_mod_file_download 96 | 97 | - name: Extract go version from go.mod file 98 | ansible.builtin.shell: | 99 | set -o pipefail 100 | grep -E "^go [0-9]+\.[0-9]+(\.[0-9]+)?" "/tmp/{{ gitea_fork }}-go.mod" | head -n 1 | sed -E 's/go ([0-9]+\.[0-9]+(\.[0-9]+)?).*/\1/' 101 | args: 102 | executable: /bin/bash 103 | register: go_version_result 104 | changed_when: false 105 | 106 | - name: Set go version fact 107 | ansible.builtin.set_fact: 108 | node_version: "{{ go_version_result.stdout | trim }}" 109 | register: go_minor 110 | 111 | # noqa: command-instead-of-module 112 | - name: Query latest patch version for minor 113 | ansible.builtin.shell: | 114 | set -o pipefail 115 | curl -s https://go.dev/dl/?mode=json | 116 | jq -r '.[] | select(.version | startswith("go{{ go_version_result.stdout }}")) | .version' | 117 | head -1 | sed 's/go//' 118 | args: 119 | executable: /bin/bash 120 | register: go_version_query 121 | changed_when: false 122 | 123 | - name: Set Go version fact 124 | ansible.builtin.set_fact: 125 | go_version_source_build: "{{ go_version_query.stdout | trim }}" 126 | 127 | - name: "Install required go version - v{{ go_version_source_build }}" 128 | ansible.builtin.shell: | 129 | # Check if Go version is already installed 130 | export GOBIN_PATH="${GOPATH:-$HOME/go}/bin" 131 | GO_ROOT="${HOME}/.go/go{{ go_version_source_build }}" 132 | 133 | if [ -x "$GO_ROOT/bin/go" ]; then 134 | echo "Go {{ go_version_source_build }} is already installed" 135 | else 136 | echo "Installing Go {{ go_version_source_build }}" 137 | go install golang.org/dl/go{{ go_version_source_build }}@latest 138 | $GOBIN_PATH/go{{ go_version_source_build }} download 139 | fi 140 | args: 141 | executable: /bin/bash 142 | creates: "{{ ansible_env.HOME }}/.go/go{{ go_version_source_build }}/bin/go" 143 | register: go_install_result 144 | changed_when: "'Installing Go' in go_install_result.stdout" 145 | 146 | - name: Build and install binary 147 | block: 148 | - name: Create build directory 149 | ansible.builtin.file: 150 | path: "{{ gitea_install_source_build_dir }}" 151 | state: directory 152 | mode: 0755 153 | register: _build_dir 154 | become: false 155 | 156 | # full clone is necessary to properly determine local version string 157 | - name: Clone git repository 158 | ansible.builtin.git: 159 | repo: "{{ gitea_install_source_source_url }}" 160 | dest: "{{ gitea_install_source_build_dir }}" 161 | version: "{{ gitea_install_source_source_ref }}" 162 | register: _git_clone 163 | become: false 164 | until: _git_clone is succeeded 165 | retries: 3 166 | delay: 5 167 | 168 | - name: Build the binary 169 | ansible.builtin.shell: | 170 | export GOBIN_PATH="${GOPATH:-$HOME/go}/bin" 171 | export GO="$GOBIN_PATH/go{{ go_version_source_build }}" 172 | export TAGS="bindata" 173 | $GO version 174 | make build 175 | args: 176 | chdir: "{{ gitea_install_source_build_dir }}" 177 | executable: /bin/bash 178 | register: _build_result 179 | become: false 180 | changed_when: _build_result.rc == 0 181 | failed_when: _build_result.rc != 0 182 | 183 | - name: Propagate built binary 184 | become: true 185 | ansible.builtin.copy: 186 | src: "{{ gitea_install_source_build_dir }}/gitea" 187 | remote_src: true 188 | dest: "{{ gitea_install_source_binary_install_path }}/{{ gitea_install_source_binary_name }}" 189 | mode: 0755 190 | owner: root 191 | group: root 192 | notify: systemctl restart gitea 193 | 194 | - name: Remove binary after move 195 | ansible.builtin.file: 196 | path: "{{ gitea_install_source_build_dir }}{{ gitea_install_source_binary_name }}" 197 | state: absent 198 | 199 | - name: Clean up build directory 200 | ansible.builtin.file: 201 | path: "{{ gitea_install_source_build_dir }}" 202 | state: absent 203 | become: false 204 | when: gitea_install_source_cleanup_build_dir | bool 205 | -------------------------------------------------------------------------------- /tasks/install_systemd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Setup systemd service" 3 | become: true 4 | ansible.builtin.template: 5 | src: "templates/gitea.service.j2" 6 | dest: "{{ gitea_systemd_path }}/gitea.service" 7 | owner: root 8 | group: root 9 | mode: 0644 10 | notify: 11 | - "Reload systemd" 12 | - "systemctl restart gitea" 13 | 14 | - name: "Reload systemd" 15 | become: true 16 | ansible.builtin.systemd_service: 17 | daemon_reload: true 18 | -------------------------------------------------------------------------------- /tasks/jwt_secrets.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Generate OAuth2 JWT_SECRET if not provided 3 | become: true 4 | ansible.builtin.shell: "umask 077; {{ gitea_full_executable_path }} generate secret JWT_SECRET > {{ gitea_configuration_path }}/gitea_oauth_jwt_secret" 5 | args: 6 | creates: "{{ gitea_configuration_path }}/gitea_oauth_jwt_secret" 7 | when: gitea_oauth2_jwt_secret | length == 0 8 | 9 | - name: Read OAuth2 JWT_SECRET from file 10 | become: true 11 | ansible.builtin.slurp: 12 | src: "{{ gitea_configuration_path }}/gitea_oauth_jwt_secret" 13 | register: oauth_jwt_secret 14 | when: gitea_oauth2_jwt_secret | length == 0 15 | 16 | - name: Set fact gitea_oauth2_jwt_secret 17 | ansible.builtin.set_fact: 18 | gitea_oauth2_jwt_secret: "{{ oauth_jwt_secret['content'] | b64decode }}" 19 | when: gitea_oauth2_jwt_secret | length == 0 20 | 21 | - name: Generate LFS JWT_SECRET if not provided 22 | become: true 23 | ansible.builtin.shell: "umask 077; {{ gitea_full_executable_path }} generate secret JWT_SECRET > {{ gitea_configuration_path }}/gitea_lfs_jwt_secret" 24 | args: 25 | creates: "{{ gitea_configuration_path }}/gitea_lfs_jwt_secret" 26 | when: gitea_lfs_jwt_secret | length == 0 27 | 28 | - name: Read LFS JWT_SECRET from file 29 | become: true 30 | ansible.builtin.slurp: 31 | src: "{{ gitea_configuration_path }}/gitea_lfs_jwt_secret" 32 | register: lfs_jwt_secret 33 | when: gitea_lfs_jwt_secret | length == 0 34 | 35 | - name: Set fact gitea_lfs_jwt_secret 36 | ansible.builtin.set_fact: 37 | gitea_lfs_jwt_secret: "{{ lfs_jwt_secret['content'] | b64decode }}" 38 | when: gitea_lfs_jwt_secret | length == 0 39 | -------------------------------------------------------------------------------- /tasks/local_git_users.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Identify gitea users 3 | ansible.builtin.command: 4 | cmd: "{{ gitea_full_executable_path }} -c {{ gitea_configuration_path }}/gitea.ini admin user list" 5 | become: true 6 | become_user: "{{ gitea_user }}" 7 | register: _giteausers 8 | changed_when: false 9 | 10 | - name: Use gitea cli to create user 11 | become: true 12 | become_user: "{{ gitea_user }}" 13 | ansible.builtin.command: 14 | cmd: > 15 | {{ gitea_full_executable_path }} -c {{ gitea_configuration_path }}/gitea.ini 16 | admin user create --username "{{ user.name }}" 17 | --password "{{ user.password }}" --email "{{ user.email }}" 18 | --must-change-password={{ user.must_change_password }} --admin={{ user.admin }} 19 | register: _gitearesult 20 | failed_when: 21 | - '"successfully created" not in _gitearesult.stdout' 22 | changed_when: 23 | - '"successfully created!" in _gitearesult.stdout' 24 | when: "_giteausers is defined and user.name not in _giteausers.stdout and user.state | default('present') == 'present'" 25 | loop: "{{ gitea_users }}" 26 | loop_control: 27 | label: "user={{ user.name }}" 28 | loop_var: user 29 | 30 | - name: Use gitea cli to delete user 31 | become: true 32 | become_user: "{{ gitea_user }}" 33 | ansible.builtin.command: 34 | cmd: > 35 | {{ gitea_full_executable_path }} -c {{ gitea_configuration_path }}/gitea.ini 36 | admin user delete --username "{{ user.name }}" 37 | register: _giteadelresult 38 | failed_when: 39 | - '"error" in _giteadelresult.stdout' 40 | changed_when: "_giteausers is defined and user.name in _giteausers.stdout" 41 | when: "_giteausers is defined and user.name in _giteausers.stdout and user.state | default('present') == 'absent'" 42 | loop: "{{ gitea_users }}" 43 | loop_control: 44 | label: "user={{ user.name }}" 45 | loop_var: user 46 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Perform optional versionscheck 3 | ansible.builtin.include_tasks: 4 | file: "versioncheck.yml" 5 | when: submodules_versioncheck | bool 6 | 7 | - name: Gather installed packages for checks later on 8 | ansible.builtin.package_facts: 9 | manager: "auto" 10 | 11 | - name: Prepare gitea/forgejo variable import 12 | block: 13 | - name: Gather vars for gitea or forgejo 14 | ansible.builtin.include_vars: 15 | file: "{{ lookup('ansible.builtin.first_found', 16 | gitea_fork_variables) }}" 17 | rescue: 18 | - name: Gitea/Forgejo import info 19 | ansible.builtin.fail: 20 | msg: "Only {{ gitea_supported_forks }} are supported." 21 | 22 | - name: Gather Gitea/Forgejo UI Theme variables 23 | ansible.builtin.include_vars: 24 | file: "{{ lookup('ansible.builtin.first_found', params) }}" 25 | name: _gitea_temp_theme_vars 26 | vars: 27 | params: 28 | files: 29 | - "{{ gitea_fork }}.yml" 30 | paths: 31 | - "defaults" 32 | 33 | - name: Set Gitea/Forgejo UI Theme variables as facts 34 | ansible.builtin.set_fact: 35 | "{{ item.key }}": "{{ item.value }}" 36 | when: item.key not in vars 37 | loop: "{{ _gitea_temp_theme_vars | dict2items }}" 38 | 39 | - name: Gather variables for each operating system 40 | ansible.builtin.include_vars: 41 | file: "{{ lookup('ansible.builtin.first_found', gitea_variables) }}" 42 | 43 | - name: Gather versioning information 44 | ansible.builtin.include_tasks: 45 | file: "set_{{ gitea_fork | lower }}_version.yml" 46 | when: gitea_version != "source" 47 | 48 | - name: Backup gitea before update 49 | ansible.builtin.include_tasks: 50 | file: "backup.yml" 51 | when: gitea_backup_on_upgrade|bool 52 | 53 | - name: Create gitea user and group 54 | ansible.builtin.include_tasks: 55 | file: "create_user.yml" 56 | 57 | - name: "Build and install from source [{{ gitea_fork }}]" 58 | ansible.builtin.include_tasks: 59 | file: "install_source.yml" 60 | when: gitea_version == "source" 61 | 62 | - name: "Install or update {{ gitea_fork }}" 63 | ansible.builtin.include_tasks: 64 | file: "install_{{ gitea_fork | lower }}.yml" 65 | when: gitea_version != "source" 66 | 67 | - name: Create directories 68 | ansible.builtin.include_tasks: 69 | file: "directory.yml" 70 | loop: 71 | - "{{ gitea_user_home }}" 72 | - "{{ gitea_home }}" 73 | - "{{ gitea_home }}/data" 74 | - "{{ gitea_custom }}" 75 | - "{{ gitea_custom }}/https" 76 | - "{{ gitea_custom }}/mailer" 77 | - "{{ gitea_home }}/indexers" 78 | - "{{ gitea_home }}/log" 79 | - "{{ gitea_repository_root }}" 80 | - "{{ gitea_configuration_path }}" 81 | 82 | - name: Setup gitea systemd service 83 | ansible.builtin.include_tasks: 84 | file: "install_systemd.yml" 85 | when: ansible_service_mgr == "systemd" 86 | 87 | - name: Generate JWT Secrets if undefined 88 | ansible.builtin.include_tasks: 89 | file: "jwt_secrets.yml" 90 | 91 | - name: Generate gitea secrets if undefined 92 | ansible.builtin.include_tasks: 93 | file: "gitea_secrets.yml" 94 | 95 | - name: Configure gitea 96 | ansible.builtin.include_tasks: 97 | file: "configure.yml" 98 | 99 | - name: Deploy optional fail2ban rules 100 | ansible.builtin.include_tasks: 101 | file: "fail2ban.yml" 102 | when: gitea_fail2ban_enabled | bool 103 | 104 | - name: Optionally customize gitea 105 | ansible.builtin.include_tasks: 106 | file: "customize_logo.yml" 107 | when: gitea_customize_logo | bool 108 | 109 | - name: Optionally customize footer 110 | ansible.builtin.include_tasks: 111 | file: "customize_footer.yml" 112 | when: gitea_customize_footer | bool 113 | 114 | - name: Optionally deploy public files 115 | ansible.builtin.include_tasks: 116 | file: "customize_public_files.yml" 117 | when: gitea_customize_files | bool or gitea_custom_themes is defined 118 | 119 | - name: Optionally create local Users on git instance 120 | ansible.builtin.include_tasks: 121 | file: "local_git_users.yml" 122 | when: gitea_users | length > 0 123 | 124 | - name: Optionally scheduled backup 125 | ansible.builtin.import_tasks: 126 | file: 'backup-scheduled.yml' 127 | when: gitea_backup_scheduled | bool 128 | -------------------------------------------------------------------------------- /tasks/set_forgejo_version.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Check forgejo installed version" 3 | ansible.builtin.shell: | 4 | set -eo pipefail 5 | {{ gitea_full_executable_path }} -v | cut -d' ' -f 3 6 | args: 7 | executable: "/bin/bash" 8 | register: gitea_active_version 9 | changed_when: false 10 | failed_when: false 11 | 12 | - name: "Determine 'latest' version release" 13 | when: gitea_version == "latest" 14 | block: 15 | - name: "Get latest forgejo release metadata" 16 | ansible.builtin.uri: 17 | url: "https://{{ gitea_forgejo_repo }}/api/v1/repos/forgejo/forgejo/releases?limit=1" 18 | return_content: true 19 | register: gitea_forgejo_remote_metadata 20 | become: false 21 | when: not ansible_check_mode 22 | 23 | - name: "Fail if running in check mode without versions set." 24 | ansible.builtin.fail: 25 | msg: | 26 | "You are running this playbook in check mode: 27 | Please set the Gitea version with the variable 'gitea_version', because the URI module cannot detect the latest version in this mode." 28 | when: ansible_check_mode and (gitea_version == 'latest' or gitea_version == 'present') 29 | 30 | - name: "Set fact latest forgejo release" 31 | ansible.builtin.set_fact: 32 | gitea_remote_version: "{{ gitea_forgejo_remote_metadata.json.0.tag_name[1:] }}" 33 | when: not ansible_check_mode 34 | 35 | - name: "Set forgejo version target (latest)" 36 | ansible.builtin.set_fact: 37 | gitea_version_target: "{{ gitea_remote_version }}" 38 | when: not ansible_check_mode 39 | 40 | - name: "Set forgejo version target {{ gitea_version }}" 41 | ansible.builtin.set_fact: 42 | gitea_version_target: "{{ gitea_version }}" 43 | when: gitea_version != "latest" 44 | 45 | - name: "Download forgejo version {{ gitea_version_target }}" 46 | when: not ansible_check_mode 47 | block: 48 | - name: "Get specific forgejo release metadata" 49 | ansible.builtin.uri: 50 | url: "https://{{ gitea_forgejo_repo }}/api/v1/repos/forgejo/forgejo/releases/tags/v{{ gitea_version_target }}" 51 | return_content: true 52 | register: gitea_forgejo_remote_tags_metadata 53 | become: false 54 | rescue: 55 | - name: "Error Downloading v{{ gitea_version_target }}" 56 | ansible.builtin.fail: 57 | msg: | 58 | We did not find the forgejo version you specified. 59 | Are you sure that '{{ gitea_version_target }}' is a valid forgejo version? 60 | Please verify 'https://{{ gitea_forgejo_repo }}/api/v1/repos/forgejo/forgejo/releases/tags/v{{ gitea_version_target }}' is a valid URL! 61 | 62 | - name: "Generate forgejo download url" 63 | ansible.builtin.set_fact: 64 | gitea_forgejo_dl_url: "{{ gitea_forgejo_remote_tags_metadata.json | community.general.json_query(gitea_forgejo_query_download) }}" 65 | when: not ansible_check_mode 66 | 67 | - name: "Generate forgejo download checksum url" 68 | ansible.builtin.set_fact: 69 | gitea_forgejo_checksum_url: "{{ gitea_forgejo_remote_tags_metadata.json | community.general.json_query(gitea_forgejo_query_checksum) }}" 70 | when: not ansible_check_mode 71 | 72 | - name: Get forgejo checksum 73 | ansible.builtin.uri: 74 | url: "{{ gitea_forgejo_checksum_url | first }}" 75 | return_content: true 76 | register: _gitea_forgejo_dl_checksum 77 | become: false 78 | when: not ansible_check_mode 79 | 80 | - name: Set forjeo checksum 81 | ansible.builtin.set_fact: 82 | gitea_forgejo_checksum: "{{ _gitea_forgejo_dl_checksum.content.split(' ')[0] }}" 83 | when: not ansible_check_mode 84 | 85 | - name: "Generate forgejo download signed url" 86 | ansible.builtin.set_fact: 87 | gitea_forgejo_signed_url: "{{ gitea_forgejo_remote_tags_metadata.json | community.general.json_query(gitea_forgejo_query_signed) }}" 88 | when: not ansible_check_mode 89 | 90 | - name: "Assert that remote version is higher" 91 | ansible.builtin.assert: 92 | that: 93 | - gitea_active_version is version(gitea_remote_version, 'lt') 94 | fail_msg: ERROR - Remote version is lower then current version! 95 | when: gitea_version == "latest" and gitea_active_version.stderr == "" | bool 96 | 97 | - name: Show Download URLs # noqa: H500 98 | when: not ansible_check_mode 99 | ansible.builtin.debug: 100 | msg: "{{ item }}" 101 | verbosity: 1 102 | loop: 103 | - "gitea_forgejo_dl_url: {{ gitea_forgejo_dl_url | first }}" 104 | - "gitea_forgejo_checksum: {{ gitea_forgejo_checksum }}" 105 | - "gitea_forgejo_signed_url: {{ gitea_forgejo_signed_url | first }}" 106 | -------------------------------------------------------------------------------- /tasks/set_gitea_version.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Check gitea installed version" 3 | ansible.builtin.shell: | 4 | set -eo pipefail 5 | {{ gitea_full_executable_path }} -v | cut -d' ' -f 3 6 | args: 7 | executable: /bin/bash 8 | register: gitea_active_version 9 | changed_when: false 10 | failed_when: false 11 | 12 | - name: "Determine 'latest' version release" 13 | when: gitea_version == "latest" 14 | block: 15 | - name: "Get latest gitea release metadata" 16 | ansible.builtin.uri: 17 | url: https://api.github.com/repos/go-gitea/gitea/releases/latest 18 | return_content: true 19 | register: gitea_remote_metadata 20 | become: false 21 | when: not ansible_check_mode 22 | 23 | - name: "Fail if running in check mode without versions set." 24 | ansible.builtin.fail: 25 | msg: | 26 | "You are running this playbook in check mode: 27 | Please set the Gitea version with the variable 'gitea_version', because the URI module cannot detect the latest version in this mode." 28 | when: ansible_check_mode and (gitea_version == 'latest' or gitea_version == 'present') 29 | 30 | - name: "Set fact latest gitea release" 31 | ansible.builtin.set_fact: 32 | gitea_remote_version: "{{ gitea_remote_metadata.json.tag_name[1:] }}" 33 | when: not ansible_check_mode 34 | 35 | - name: "Set gitea version target (latest)" 36 | ansible.builtin.set_fact: 37 | gitea_version_target: "{{ gitea_remote_version }}" 38 | when: not ansible_check_mode 39 | 40 | - name: "Set gitea version target {{ gitea_version }}" 41 | ansible.builtin.set_fact: 42 | gitea_version_target: "{{ gitea_version }}" 43 | when: gitea_version != "latest" 44 | 45 | - name: "Assert that remote version is higher" 46 | ansible.builtin.assert: 47 | that: 48 | - gitea_active_version is version(gitea_remote_version, 'lt') 49 | fail_msg: ERROR - Remote version is lower then current version! 50 | when: gitea_version == "latest" and gitea_active_version.stderr == "" | bool 51 | 52 | - name: "Generate gitea download URL" 53 | ansible.builtin.set_fact: 54 | gitea_dl_url: "https://github.com/go-gitea/gitea/releases/download/v{{ gitea_version_target }}/gitea-{{ gitea_version_target }}-linux-{{ gitea_arch }}" 55 | -------------------------------------------------------------------------------- /tasks/versioncheck.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (c) 2021 L3D 3 | # this file is released with the MIT license. 4 | # License: https://github.com/roles-ansible/ansible_role_template/blob/main/LICENSE 5 | - name: Create directory for versionscheck 6 | become: true 7 | ansible.builtin.file: 8 | path: "/etc/.ansible-version" 9 | state: directory 10 | mode: "0755" 11 | when: submodules_versioncheck | bool 12 | 13 | - name: Check playbook version 14 | become: true 15 | ansible.builtin.slurp: 16 | src: "/etc/.ansible-version/{{ playbook_version_path }}" 17 | register: playbook_version 18 | when: submodules_versioncheck | bool 19 | failed_when: false 20 | 21 | - name: Print remote role version # noqa: H500 22 | ansible.builtin.debug: 23 | msg: "Remote role version: {{ playbook_version.content | default('Y3VycmVudGx5IG5vdCBkZXBsb3llZAo=') | b64decode | string }}" 24 | when: submodules_versioncheck | bool 25 | 26 | - name: Print locale role version # noqa: H500 27 | ansible.builtin.debug: 28 | msg: "Local role version: '{{ playbook_version_number | string }}'." 29 | when: submodules_versioncheck | bool 30 | 31 | - name: Check if your version is outdated 32 | ansible.builtin.fail: 33 | msg: "Your ansible module has the version '{{ playbook_version_number }}' and is outdated. You need to update it!" 34 | when: 35 | - playbook_version.content|default("Mgo=")|b64decode|int - 1 >= playbook_version_number|int and submodules_versioncheck | bool 36 | 37 | - name: Write new version to remote disk 38 | become: true 39 | ansible.builtin.copy: 40 | content: "{{ playbook_version_number }}" 41 | dest: "/etc/.ansible-version/{{ playbook_version_path }}" 42 | mode: "0644" 43 | when: submodules_versioncheck | bool 44 | tags: skip_ansible_lint_template-instead-of-copy 45 | -------------------------------------------------------------------------------- /templates/fail2ban/filter.conf.j2: -------------------------------------------------------------------------------- 1 | # Managed by Ansible 2 | [Definition] 3 | failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from 4 | ignoreregex = 5 | -------------------------------------------------------------------------------- /templates/fail2ban/jail.conf.j2: -------------------------------------------------------------------------------- 1 | [gitea] 2 | enabled = true 3 | port = http,https 4 | filter = gitea 5 | logpath = {{ gitea_home }}/log/gitea.log 6 | maxretry = {{ gitea_fail2ban_jail_maxretry }} 7 | findtime = {{ gitea_fail2ban_jail_findtime }} 8 | bantime = {{ gitea_fail2ban_jail_bantime }} 9 | action = {{ gitea_fail2ban_jail_action }} 10 | -------------------------------------------------------------------------------- /templates/gitea.ini.j2: -------------------------------------------------------------------------------- 1 | ; this file is the configuration of your local Gitea instance 2 | ; {{ ansible_managed }} 3 | ; This file overwrites the default values from Gitea. 4 | ; undefined variables will use the default value from Gitea. 5 | ; Cheat Sheet: https://docs.gitea.com/next/administration/config-cheat-sheet/ 6 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet#overall-default 7 | APP_NAME = {{ gitea_app_name }} 8 | RUN_USER = {{ gitea_user }} 9 | RUN_MODE = {{ gitea_run_mode }} 10 | WORK_PATH = {{ gitea_home }} 11 | 12 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#repository-repository 13 | [repository] 14 | ROOT = {{ gitea_repository_root }} 15 | FORCE_PRIVATE = {{ gitea_force_private | ternary('true', 'false') }} 16 | DEFAULT_PRIVATE = {{ gitea_default_private }} 17 | MAX_CREATION_LIMIT = {{ gitea_user_repo_limit }} 18 | DISABLE_HTTP_GIT = {{ gitea_disable_http_git | ternary('true', 'false') }} 19 | ENABLE_PUSH_CREATE_USER = {{ gitea_enable_push_create_user | ternary('true', 'false') }} 20 | ENABLE_PUSH_CREATE_ORG = {{ gitea_enable_push_create_org | ternary('true', 'false') }} 21 | DISABLED_REPO_UNITS = {{ gitea_disabled_repo_units }} 22 | DEFAULT_REPO_UNITS = {{ gitea_default_repo_units }} 23 | DISABLE_STARS = {{ gitea_disable_stars | ternary('true', 'false') }} 24 | DEFAULT_BRANCH = {{ gitea_default_branch }} 25 | {{ gitea_repository_extra_config }} 26 | ; -> https://docs.gitea.com/next/administration/administration/config-cheat-sheet/#repository---upload-repositoryupload 27 | [repository.upload] 28 | ENABLED = {{ gitea_repository_upload_enabled | ternary('true', 'false') }} 29 | TEMP_PATH = {{ gitea_home }}/data/tmp/uploads 30 | FILE_MAX_SIZE = {{ gitea_repository_upload_max_size }} 31 | {{ gitea_repository_upload_extra_config }} 32 | {% if gitea_enable_repo_signing_options | bool %} 33 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#repository---signing-repositorysigning 34 | [repository.signing] 35 | SIGNING_KEY = {{ gitea_repo_signing_key }} 36 | SIGNING_NAME = {{ gitea_repo_signing_name }} 37 | SIGNING_EMAIL = {{ gitea_repo_signing_email }} 38 | INITIAL_COMMIT = {{ gitea_repo_initial_commit }} 39 | DEFAULT_TRUST_MODEL = {{ gitea_repo_default_trust_model }} 40 | WIKI = {{ gitea_repo_wiki }} 41 | CRUD_ACTIONS = {{ gitea_repo_crud_actions }} 42 | MERGES = {{ gitea_repo_merges }} 43 | {{ gitea_enable_repo_signing_extra_config }} 44 | {% endif %} 45 | {% if gitea_enable_cors | bool %} 46 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#cors-cors 47 | [cors] 48 | ENABLED = {{ gitea_enable_cors | ternary('true', 'false') }} 49 | SCHEME = {{ gitea_cors_scheme }} 50 | ALLOW_DOMAIN = {{ gitea_cors_allow_domain }} 51 | ALLOW_SUBDOMAIN = {{ gitea_cors_allow_subdomain | ternary('true', 'false') }} 52 | METHODS = {{ gitea_cors_methods }} 53 | MAX_AGE = {{ gitea_cors_max_age }} 54 | ALLOW_CREDENTIALS = {{ gitea_cors_allow_credentials | ternary('true', 'false') }} 55 | HEADERS = {{ gitea_cors_headers }} 56 | X_FRAME_OPTIONS = {{ gitea_cors_x_frame_options }} 57 | {{ gitea_cors_extra_config }} 58 | {% endif %} 59 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#ui-ui 60 | [ui] 61 | THEMES = {{ gitea_themes }} 62 | DEFAULT_THEME = {{ gitea_theme_default }} 63 | SHOW_USER_EMAIL = {{ gitea_show_user_email | ternary('true', 'false') }} 64 | {{ gitea_ui_extra_config }} 65 | [ui.meta] 66 | AUTHOR = {{ gitea_ui_author }} 67 | DESCRIPTION = {{ gitea_ui_description }} 68 | KEYWORDS = {{ gitea_ui_keywords }} 69 | {{ gitea_ui_meta_extra_config }} 70 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#server-server 71 | [server] 72 | APP_DATA_PATH = {{ gitea_home }}/data 73 | PROTOCOL = {{ gitea_protocol }} 74 | DOMAIN = {{ gitea_http_domain }} 75 | ROOT_URL = {{ gitea_root_url }} 76 | HTTP_ADDR = {{ gitea_http_listen }} 77 | HTTP_PORT = {{ gitea_http_port }} 78 | START_SSH_SERVER = {{ gitea_start_ssh | ternary('true', 'false') }} 79 | SSH_DOMAIN = {{ gitea_ssh_domain }} 80 | SSH_PORT = {{ gitea_ssh_port }} 81 | SSH_LISTEN_HOST = {{ gitea_ssh_listen }} 82 | OFFLINE_MODE = {{ gitea_offline_mode | ternary('true', 'false') }} 83 | {% if gitea_enable_tls_certs | bool %} 84 | CERT_FILE = {{ gitea_tls_cert_file }} 85 | KEY_FILE = {{ gitea_tls_key_file }} 86 | {% endif %} 87 | LANDING_PAGE = {{ gitea_landing_page }} 88 | {% if gitea_lfs_server_enabled | bool %} 89 | LFS_START_SERVER = true 90 | LFS_JWT_SECRET = {{ gitea_lfs_jwt_secret }} 91 | {% endif %} 92 | REDIRECT_OTHER_PORT = {{ gitea_redirect_other_port | ternary('true', 'false') }} 93 | PORT_TO_REDIRECT = {{ gitea_port_to_redirect }} 94 | ENABLE_ACME = {{ gitea_enable_acme | ternary('true', 'false') }} 95 | {% if gitea_enable_acme | bool %} 96 | {% if gitea_acme_url != '' %} 97 | ACME_URL = {{ gitea_acme_url }} 98 | {% endif %} 99 | ACME_ACCEPTTOS = {{ gitea_acme_accepttos | ternary('true', 'false') }} 100 | ACME_DIRECTORY = {{ gitea_acme_directory }} 101 | ACME_EMAIL = {{ gitea_acme_email }} 102 | ACME_CA_ROOT = {{ gitea_acme_ca_root }} 103 | {% endif %} 104 | {{ gitea_server_extra_config }} 105 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#database-database 106 | [database] 107 | DB_TYPE = {{ gitea_db_type }} 108 | HOST = {{ gitea_db_host }} 109 | NAME = {{ gitea_db_name }} 110 | USER = {{ gitea_db_user }} 111 | PASSWD = {{ gitea_db_password }} 112 | SSL_MODE = {{ gitea_db_ssl }} 113 | PATH = {{ gitea_db_path }} 114 | LOG_SQL = {{ gitea_db_log_sql | ternary('true', 'false') }} 115 | {{ gitea_database_extra_config }} 116 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#indexer-indexer 117 | [indexer] 118 | ISSUE_INDEXER_PATH = {{ gitea_home }}/indexers/issues.bleve 119 | ISSUE_INDEXER_TYPE = {{ gitea_issue_indexer_type }} 120 | {% if gitea_issue_indexer_type == 'elasticsearch' or gitea_issue_indexer_type == 'meilisearch' %} 121 | ISSUE_INDEXER_CONN_STR = {{ gitea_issue_indexer_conn_str }} 122 | {% endif %} 123 | REPO_INDEXER_ENABLED = {{ gitea_repo_indexer_enabled | ternary('true', 'false') }} 124 | REPO_INDEXER_PATH = {{ gitea_home }}/indexers/repos.bleve 125 | REPO_INDEXER_INCLUDE = {{ gitea_repo_indexer_include }} 126 | REPO_INDEXER_EXCLUDE = {{ gitea_repo_indexer_exclude }} 127 | REPO_INDEXER_EXCLUDE_VENDORED = {{ gitea_repo_exclude_vendored | ternary('true', 'false') }} 128 | MAX_FILE_SIZE = {{ gitea_repo_indexer_max_file_size }} 129 | {{ gitea_indexer_extra_config }} 130 | ; Queue (queue and queue.*) 131 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#queue-queue-and-queue 132 | [queue.issue_indexer] 133 | DATADIR = {{ gitea_home }}/indexers/issues.queue 134 | {{ gitea_queue_issue_indexer_extra_config }} 135 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#security-security 136 | [security] 137 | INSTALL_LOCK = true 138 | SECRET_KEY = {{ gitea_secret_key }} 139 | DISABLE_GIT_HOOKS = {{ gitea_disable_git_hooks | ternary('true', 'false') }} 140 | DISABLE_WEBHOOKS = {{ gitea_disable_webhooks | ternary('true', 'false') }} 141 | INTERNAL_TOKEN = {{ gitea_internal_token }} 142 | PASSWORD_CHECK_PWN = {{ gitea_password_check_pwn | ternary('true', 'false') }} 143 | {{ gitea_security_extra_config }} 144 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#service-service 145 | [service] 146 | REGISTER_EMAIL_CONFIRM = {{ gitea_register_email_confirm | ternary('true', 'false') }} 147 | DISABLE_REGISTRATION = {{ gitea_disable_registration | ternary('true', 'false') }} 148 | REQUIRE_SIGNIN_VIEW = {{ gitea_require_signin | ternary('true', 'false') }} 149 | ENABLE_NOTIFY_MAIL = {{ gitea_enable_notify_mail | ternary('true', 'false') }} 150 | ENABLE_CAPTCHA = {{ gitea_enable_captcha | ternary('true', 'false') }} 151 | DEFAULT_KEEP_EMAIL_PRIVATE = {{ gitea_default_keep_mail_private | ternary('true', 'false') }} 152 | SHOW_REGISTRATION_BUTTON = {{ gitea_show_registration_button | ternary('true', 'false') }} 153 | AUTO_WATCH_NEW_REPOS = {{ gitea_auto_watch_new_repos | ternary('true', 'false') }} 154 | AUTO_WATCH_ON_CHANGES = {{ gitea_auto_watch_on_changes | ternary('true', 'false') }} 155 | SHOW_MILESTONES_DASHBOARD_PAGE = {{ gitea_show_milestones_dashboard_page | ternary('true', 'false') }} 156 | REGISTER_MANUAL_CONFIRM = {{ gitea_register_manual_confirm | ternary('true', 'false') }} 157 | DEFAULT_ALLOW_CREATE_ORGANIZATION = {{ gitea_default_allow_create_organization | ternary('true', 'false') }} 158 | DEFAULT_USER_IS_RESTRICTED = {{ gitea_default_user_is_restricted | ternary('true', 'false') }} 159 | {% if gitea_email_domain_allowlist is defined and gitea_email_domain_allowlist | length %} 160 | EMAIL_DOMAIN_ALLOWLIST = {{ gitea_email_domain_allowlist }} 161 | {% endif %} 162 | DEFAULT_USER_VISIBILITY = {{ gitea_default_user_visibility }} 163 | DEFAULT_ORG_VISIBILITY = {{ gitea_default_org_visibility }} 164 | ALLOW_ONLY_INTERNAL_REGISTRATION = {{ gitea_allow_only_internal_registration | ternary('true', 'false') }} 165 | ALLOW_ONLY_EXTERNAL_REGISTRATION = {{ gitea_allow_only_external_registration | ternary('true', 'false') }} 166 | {{ gitea_service_extra_config }} 167 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#mailer-mailer 168 | [mailer] 169 | ENABLED = {{ gitea_mailer_enabled | ternary('true', 'false') }} 170 | {% if gitea_mailer_enabled | bool %} 171 | {% if gitea_mailer_use_client_cert | bool %} 172 | CLIENT_CERT_FILE = {{ gitea_mailer_client_cert_file }} 173 | CLIENT_KEY_FILE = {{ gitea_mailer_client_key_file }} 174 | {% endif %} 175 | PROTOCOL = {{ gitea_mailer_protocol }} 176 | SMTP_ADDR = {{ gitea_mailer_smtp_addr }} 177 | SMTP_PORT = {{ gitea_mailer_smtp_port }} 178 | USE_CLIENT_CERT = {{ gitea_mailer_use_client_cert | ternary('true', 'false') }} 179 | FORCE_TRUST_SERVER_CERT = {{ gitea_mailer_force_trust_server_cert | ternary('true', 'false') }} 180 | USER = {{ gitea_mailer_user }} 181 | PASSWD = {{ gitea_mailer_password }} 182 | ENABLE_HELO = {{ gitea_mailer_enable_helo | ternary('true', 'false') }} 183 | FROM = {{ gitea_mailer_from }} 184 | SUBJECT_PREFIX = {{ gitea_subject_prefix }} 185 | SEND_AS_PLAIN_TEXT = {{ gitea_mailer_send_as_plaintext | ternary('true', 'false') }} 186 | {{ gitea_mailer_extra_config }} 187 | {% endif %} 188 | 189 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#session-session 190 | [session] 191 | PROVIDER = {{ gitea_session_provider }} 192 | PROVIDER_CONFIG = {{ gitea_session_provider_config }} 193 | {{ gitea_session_extra_config }} 194 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#picture-picture 195 | [picture] 196 | AVATAR_UPLOAD_PATH = {{ gitea_home }}/data/avatars 197 | {{ gitea_picture_extra_config }} 198 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#issue-and-pull-request-attachments-attachment 199 | [attachment] 200 | ENABLED = {{ gitea_attachment_enabled | ternary('true', 'false') }} 201 | ALLOWED_TYPES = {{ gitea_attachment_types }} 202 | MAX_SIZE = {{ gitea_attachment_max_size }} 203 | PATH = {{ gitea_home }}/data/attachments 204 | {{ gitea_attachment_extra_config }} 205 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#log-log 206 | [log] 207 | ROOT_PATH = {{ gitea_home }}/log 208 | {% if gitea_log_systemd %} 209 | MODE = console 210 | {% else %} 211 | MODE = file 212 | {% endif %} 213 | LEVEL = {{ gitea_log_level }} 214 | {{ gitea_log_extra_config }} 215 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#metrics-metrics 216 | [metrics] 217 | ENABLED = {{ gitea_metrics_enabled | ternary('true', 'false') }} 218 | TOKEN = {{ gitea_metrics_token }} 219 | {{ gitea_metrics_extra_config }} 220 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#oauth2-oauth2 221 | [oauth2] 222 | ENABLED = {{ gitea_oauth2_enabled | ternary('true', 'false') }} 223 | JWT_SECRET = {{ gitea_oauth2_jwt_secret }} 224 | {{ gitea_oauth2_extra_config }} 225 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#federation-federation 226 | [federation] 227 | ENABLED = {{ gitea_federation_enabled | ternary('true', 'false') }} 228 | SHARE_USER_STATISTICS = {{ gitea_federation_share_user_stats | ternary('true', 'false') }} 229 | {{ gitea_federation_extra_config }} 230 | ; Packages (packages) 231 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#packages-packages 232 | [packages] 233 | ENABLED = {{ gitea_packages_enabled | ternary('true', 'false') }} 234 | {% if gitea_packages_enabled | bool %} 235 | CHUNKED_UPLOAD_PATH = {{ gitea_home }}/data/tmp/package-upload 236 | {{ gitea_packages_extra_config }} 237 | {% endif %} 238 | {% if gitea_lfs_server_enabled | bool %} 239 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#lfs-lfs 240 | [lfs] 241 | STORAGE_TYPE = {{ gitea_lfs_storage_type }} 242 | SERVE_DIRECT = {{ gitea_lfs_serve_direct | ternary('true', 'false') }} 243 | PATH = {{ gitea_lfs_content_path }} 244 | {{ gitea_lfs_extra_config }} 245 | {% endif %} 246 | {% if gitea_actions_enabled | bool %} 247 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#actions-actions 248 | [actions] 249 | ENABLED = {{ gitea_actions_enabled }} 250 | DEFAULT_ACTIONS_URL = {{ gitea_actions_default_actions_url }} 251 | {{ gitea_actions_extra_config }} 252 | {% endif %} 253 | ; Other (other) 254 | ; -> https://docs.gitea.com/next/administration/config-cheat-sheet/#other-other 255 | [other] 256 | SHOW_FOOTER_VERSION = {{ gitea_other_show_footer_version | ternary('true', 'false') }} 257 | SHOW_FOOTER_TEMPLATE_LOAD_TIME = {{ gitea_other_show_footer_template_load_time | ternary('true', 'false') }} 258 | ENABLE_SITEMAP = {{ gitea_other_enable_sitemap | ternary('true', 'false') }} 259 | ENABLE_FEED = {{ gitea_other_enable_feed | ternary('true', 'false') }} 260 | 261 | ; Optional additional config 262 | {{ gitea_extra_config }} 263 | -------------------------------------------------------------------------------- /templates/gitea.service.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | [Unit] 3 | Description={{ gitea_fork }} git server 4 | After=network.target 5 | 6 | [Service] 7 | User={{ gitea_user }} 8 | Group={{ gitea_group }} 9 | ExecStart={{ gitea_full_executable_path }} web --config {{ gitea_configuration_path }}/gitea.ini --custom-path {{ gitea_custom }}/ --work-path {{ gitea_home }} 10 | Restart=on-failure 11 | WorkingDirectory={{ gitea_home }} 12 | 13 | {% if gitea_systemd_hardening_enable | bool %} 14 | # Reduce Attack Surface 15 | # Exposure level 9.2 -> 2.0 16 | NoNewPrivileges=yes 17 | PrivateTmp=true 18 | ProtectHome=yes 19 | ProtectSystem=yes 20 | # ProtectSystem=strict 21 | {% if ansible_distribution == 'Ubuntu' and ansible_distribution_major_version | int >= 21 %} 22 | # ProtectProc=noaccess 23 | {% endif %} 24 | 25 | PrivateDevices=yes 26 | DeviceAllow= 27 | 28 | # PrivateUsers=yes 29 | 30 | UMask=077 31 | 32 | # ERROR: /proc not mounted - LibreOffice is unlikely to work well if at all 33 | # InaccessiblePaths=/proc 34 | 35 | ProtectKernelTunables=true 36 | ProtectKernelModules=yes 37 | {% if (ansible_distribution == 'Ubuntu' and ansible_distribution_major_version | int >= 20) or 38 | (ansible_os_family == 'RedHat' and ansible_distribution_major_version | int > 8 ) 39 | %} 40 | ProtectKernelLogs=yes 41 | ProtectHostname=yes 42 | ProtectClock=yes 43 | {% endif %} 44 | 45 | ProtectControlGroups=true 46 | LockPersonality=true 47 | RestrictRealtime=true 48 | RestrictNamespaces=yes 49 | # RestrictNamespaces=~CLONE_NEWCGROUP CLONE_NEWIPC CLONE_NEWNET CLONE_NEWPID 50 | RestrictSUIDSGID=yes 51 | MemoryDenyWriteExecute=yes 52 | RemoveIPC=Yes 53 | 54 | # PrivateNetwork=yes 55 | RestrictAddressFamilies=AF_INET AF_INET6 56 | RestrictAddressFamilies=~AF_UNIX 57 | 58 | IPAccounting=yes 59 | # IPAddressAllow=localhost link-local multicast 10.0.0.0/8 192.168.0.0/16 60 | # IPAddressDeny= 61 | 62 | {% if gitea_systemd_cap_net_bind_service %} 63 | AmbientCapabilities=CAP_NET_BIND_SERVICE 64 | {% endif %} 65 | CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_DAC_READ_SEARCH 66 | CapabilityBoundingSet=~CAP_SYS_RAWIO 67 | CapabilityBoundingSet=~CAP_SYS_PTRACE 68 | CapabilityBoundingSet=~CAP_DAC_* CAP_FOWNER CAP_IPC_OWNER 69 | CapabilityBoundingSet=~CAP_BPF 70 | CapabilityBoundingSet=~CAP_NET_ADMIN 71 | CapabilityBoundingSet=~CAP_KILL 72 | CapabilityBoundingSet=~CAP_NET_BROADCAST 73 | CapabilityBoundingSet=~CAP_SYS_NICE CAP_SYS_RESOURCE 74 | CapabilityBoundingSet=~CAP_SYS_BOOT 75 | CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE 76 | CapabilityBoundingSet=~CAP_SYS_CHROOT 77 | CapabilityBoundingSet=~CAP_BLOCK_SUSPEND 78 | CapabilityBoundingSet=~CAP_LEASE 79 | CapabilityBoundingSet=~CAP_SYS_PACCT 80 | CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG 81 | CapabilityBoundingSet=~CAP_SYS_ADMIN 82 | CapabilityBoundingSet=~CAP_SETUID CAP_SETGID 83 | CapabilityBoundingSet=~CAP_SETPCAP 84 | CapabilityBoundingSet=~CAP_CHOWN 85 | CapabilityBoundingSet=~CAP_FSETID CAP_SETFCAP 86 | CapabilityBoundingSet=~CAP_NET_RAW 87 | CapabilityBoundingSet=~CAP_IPC_LOCK 88 | 89 | {% if not (ansible_virtualization_type is defined and 90 | ansible_virtualization_type == "docker" 91 | ) 92 | %} 93 | {% if (ansible_os_family == 'RedHat' and ansible_distribution_major_version|int >= 8) or 94 | (ansible_distribution == "Ubuntu" and ansible_distribution_major_version|int > 18) 95 | %} 96 | SystemCallFilter=@system-service 97 | {% endif %} 98 | # SystemCallFilter=~@debug @mount @cpu-emulation @obsolete @privileged @resources @reboot @swap @raw-io @module 99 | SystemCallFilter=~@debug @mount @cpu-emulation @obsolete @resources @reboot @swap @raw-io @module 100 | # When system call is disallowed, return error code instead of killing process 101 | SystemCallErrorNumber=EPERM 102 | {% endif %} 103 | SystemCallArchitectures=native 104 | 105 | {% if gitea_cgroups_restriction_enable | bool %} 106 | CPUWeight={{ gitea_cgroups_cpushares | default('1024') }} 107 | CPUQuota={{ gitea_cgroups_cpuquota | default('80%') }} 108 | MemoryMax={{ gitea_cgroups_memorylimit | default('4G') }} 109 | IOWeight={{ gitea_cgroups_ioweight | default('80') }} 110 | {% endif %} 111 | 112 | {% endif %} 113 | [Install] 114 | WantedBy=multi-user.target 115 | -------------------------------------------------------------------------------- /templates/systemd-gitea-backup.service.conf.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | 3 | [Unit] 4 | Description={{ gitea_fork }} backup 5 | StartLimitIntervalSec=0 6 | Documentation=https://docs.gitea.com/administration/backup-and-restore 7 | Documentation=https://forgejo.org/docs/latest/admin/upgrade/#backup 8 | 9 | [Service] 10 | Type=oneshot 11 | User=gitea 12 | ExecStart=/usr/local/bin/{{ gitea_fork }} dump --config /etc/gitea/gitea.ini 13 | WorkingDirectory={{ gitea_backup_location }} 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /templates/systemd-gitea-backup.timer.conf.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | 3 | [Unit] 4 | Description={{ gitea_fork }} backup timer 5 | 6 | [Timer] 7 | Persistent=true 8 | OnCalendar={{ gitea_backup_scheduled_calendar }} 9 | 10 | ; Add jitter 11 | RandomizedDelaySec=5m 12 | 13 | [Install] 14 | WantedBy=timers.target 15 | -------------------------------------------------------------------------------- /vars/debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | gitea_dependencies: 3 | - git 4 | - gnupg2 5 | - xz-utils 6 | 7 | gitea_systemd_path: "/lib/systemd/system" 8 | -------------------------------------------------------------------------------- /vars/fork_forgejo.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # set filenames for forgejo 3 | gitea_full_executable_path: "{{ gitea_forgejo_executable_path }}" 4 | gitea_filename: "forgejo-{{ gitea_version_target }}-linux-{{ gitea_arch }}" 5 | gitea_forgejo_query_download: "assets[?name==`{{ gitea_filename }}`].browser_download_url" 6 | gitea_forgejo_query_checksum: "assets[?name==`{{ gitea_filename }}.sha256`].browser_download_url" 7 | gitea_forgejo_query_signed: "assets[?name==`{{ gitea_filename }}.asc`].browser_download_url" 8 | gitea_forgejo_repo: "code.forgejo.org" 9 | -------------------------------------------------------------------------------- /vars/fork_gitea.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # set filenames for gitea 3 | gitea_full_executable_path: "{{ gitea_executable_path }}" 4 | gitea_filename: "gitea-{{ gitea_version_target }}.linux-{{ gitea_arch }}" 5 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | gitea_go_arch_map: 3 | i386: "386" 4 | x86_64: "amd64" 5 | aarch64: "arm64" 6 | armv7l: "arm-6" 7 | armv6l: "arm-6" 8 | armv5l: "arm-5" 9 | 10 | gitea_arch: "{{ gitea_go_arch_map[ansible_architecture] | default(ansible_architecture) }}" 11 | gitea_supported_forks: "gitea and forgejo" 12 | 13 | gitea_fork_variables: 14 | files: 15 | - "fork_{{ gitea_fork | lower }}.yml" 16 | paths: 17 | - "vars" 18 | 19 | gitea_variables: 20 | files: 21 | - "{{ ansible_distribution | lower }}-{{ ansible_distribution_version | lower }}.yml" 22 | - "{{ ansible_distribution | lower }}-{{ ansible_distribution_major_version | lower }}.yml" 23 | - "{{ ansible_os_family | lower }}-{{ ansible_distribution_major_version | lower }}.yml" 24 | - "{{ ansible_distribution | lower }}.yml" 25 | - "{{ ansible_os_family | lower }}.yml" 26 | - "os_fallback_defaults.yml" 27 | paths: 28 | - "vars" 29 | 30 | transfer_custom_logo_logosvg: 31 | files: 32 | - "{{ gitea_custom_search }}/gitea_logo/logo.svg" 33 | - "files/{{ inventory_hostname }}/gitea_logo/logo.svg" 34 | - "files/{{ gitea_http_domain }}/gitea_logo/logo.svg" 35 | - "files/gitea_logo/logo.svg" 36 | 37 | transfer_custom_logo_logopng: 38 | files: 39 | - "{{ gitea_custom_search }}/gitea_logo/logo.png" 40 | - "files/{{ inventory_hostname }}/gitea_logo/logo.png" 41 | - "files/{{ gitea_http_domain }}/gitea_logo/logo.png" 42 | - "files/gitea_logo/logo.png" 43 | 44 | transfer_custom_logo_faviconpng: 45 | files: 46 | - "{{ gitea_custom_search }}/gitea_logo/favicon.png" 47 | - "files/{{ inventory_hostname }}/gitea_logo/favicon.png" 48 | - "files/{{ gitea_http_domain }}/gitea_logo/favicon.png" 49 | - "files/gitea_logo/favicon.png" 50 | 51 | transfer_custom_logo_faviconsvg: 52 | files: 53 | - "{{ gitea_custom_search }}/gitea_logo/favicon.svg" 54 | - "files/{{ inventory_hostname }}/gitea_logo/favicon.svg" 55 | - "files/{{ gitea_http_domain }}/gitea_logo/favicon.svg" 56 | - "files/gitea_logo/favicon.svg" 57 | 58 | transfer_custom_logo_appletouchiconpng: 59 | files: 60 | - "{{ gitea_custom_search }}/gitea_logo/apple-touch-icon.png" 61 | - "files/{{ inventory_hostname }}/gitea_logo/apple-touch-icon.png" 62 | - "files/{{ gitea_http_domain }}/gitea_logo/apple-touch-icon.png" 63 | - "files/gitea_logo/apple-touch-icon.png" 64 | 65 | transfer_custom_footer: 66 | files: 67 | - "{{ gitea_custom_search }}/gitea_footer/extra_links_footer.tmpl" 68 | - "files/{{ inventory_hostname }}/gitea_footer/extra_links_footer.tmpl" 69 | - "files/{{ gitea_http_domain }}/gitea_footer/extra_links_footer.tmpl" 70 | - "files/gitea_footer/extra_links_footer.tmpl" 71 | - "files/extra_links_footer.tmpl" 72 | 73 | playbook_version_number: 68 74 | playbook_version_path: "do1jlr.gitea.version" 75 | -------------------------------------------------------------------------------- /vars/os_fallback_defaults.yml: -------------------------------------------------------------------------------- 1 | --- 2 | gitea_dependencies: 3 | - git 4 | - gnupg2 5 | - xz-utils 6 | 7 | gitea_systemd_path: "/lib/systemd/system" 8 | -------------------------------------------------------------------------------- /vars/redhat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | gitea_dependencies: 3 | - git 4 | - gnupg2 5 | - xz 6 | 7 | gitea_systemd_path: "/lib/systemd/system" 8 | -------------------------------------------------------------------------------- /vars/suse.yml: -------------------------------------------------------------------------------- 1 | --- 2 | gitea_dependencies: 3 | - git 4 | - gpg2 5 | - xz 6 | 7 | gitea_systemd_path: "/etc/systemd/system" 8 | --------------------------------------------------------------------------------